From: Matthew Vogt Date: Mon, 5 Mar 2012 01:39:24 +0000 (+1000) Subject: Merge master <-> api_changes X-Git-Tag: qt-v5.0.0-alpha1~249^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0284817d6cd7e17afa8da26ee6e9199100754446;p=profile%2Fivi%2Fqtdeclarative.git Merge master <-> api_changes Change-Id: Iad2f07b989b25349fd2d4fff010e24dcd5a1688f --- 0284817d6cd7e17afa8da26ee6e9199100754446 diff --cc bin/rename-qtdeclarative-symbols.sh index 8418502,0000000..0d521dd mode 100755,000000..100755 --- a/bin/rename-qtdeclarative-symbols.sh +++ b/bin/rename-qtdeclarative-symbols.sh @@@ -1,639 -1,0 +1,642 @@@ +#!/bin/sh +############################################################################# +## +## Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +## Contact: http://www.qt-project.org/ +## +## This file is part of the QtQml module of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:LGPL$ +## GNU Lesser General Public License Usage +## This file may be used under the terms of the GNU Lesser General Public +## License version 2.1 as published by the Free Software Foundation and +## appearing in the file LICENSE.LGPL included in the packaging of this +## file. Please review the following information to ensure the GNU Lesser +## General Public License version 2.1 requirements will be met: +## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +## +## In addition, as a special exception, Nokia gives you certain additional +## rights. These rights are described in the Nokia Qt LGPL Exception +## version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU General +## Public License version 3.0 as published by the Free Software Foundation +## and appearing in the file LICENSE.GPL included in the packaging of this +## file. Please review the following information to ensure the GNU General +## Public License version 3.0 requirements will be met: +## http://www.gnu.org/copyleft/gpl.html. +## +## Other Usage +## Alternatively, this file may be used in accordance with the terms and +## conditions contained in a signed written agreement between you and Nokia. +## +## +## +## +## +## +## $QT_END_LICENSE$ +## +############################################################################# + +# Replaces deprecated QDeclarative symbol names with their replacements +# +# Changes instances in all regular files under the specified directory; +# use on a clean source tree! + +if [ "$#" -lt "1" ] +then + echo " Usage: $0 " + exit 1; +fi + +MODIFY_DIR="$1" + +QML_SYMBOLS="\ + QDeclarativeAbstractBinding + QDeclarativeAbstractBoundSignal + QDeclarativeAbstractExpression + QDeclarativeAccessible + QDeclarativeAccessors + QDeclarativeAccessorProperties + QDeclarativeAnimationTimer + QDeclarativeAssociationList + QDeclarativeAttachedPropertiesFunc + QDeclarativeBinding + QDeclarativeBindingPrivate + QDeclarativeBindingProfiler + QDeclarativeBoundSignal + QDeclarativeBoundSignalParameters + QDeclarativeBoundSignalProxy + QDeclarativeBuiltinFunctions + QDeclarativeCleanup + QDeclarativeColorValueType + QDeclarativeCompiledData + QDeclarativeCompiler + QDeclarativeCompilerTypes ++ QDeclarativeCompilingProfiler + QDeclarativeComponent + QDeclarativeComponentAttached + QDeclarativeComponentExtension + QDeclarativeComponentPrivate + QDeclarativeComponent_setQmlParent + QDeclarativeCompositeTypeData + QDeclarativeConnectionsParser + QDeclarativeContext + QDeclarativeContextData + QDeclarativeContextPrivate + QDeclarativeCustomParser + QDeclarativeCustomParserNode + QDeclarativeCustomParserNodePrivate + QDeclarativeCustomParserProperty + QDeclarativeCustomParserPropertyPrivate + QDeclarativeData + QDeclarativeDataBlob + QDeclarativeDataExtended + QDeclarativeDataLoader + QDeclarativeDataLoaderNetworkReplyProxy + QDeclarativeDataLoaderThread + QDeclarativeDateExtension + QDeclarativeDataTest + QDeclarativeDebug + QDeclarativeDebugClient + QDeclarativeDebugClientPrivate + QDeclarativeDebugConnection + QDeclarativeDebugConnectionPrivate + QDeclarativeDebugContextReference + QDeclarativeDebugData + QDeclarativeDebugEngineReference + QDeclarativeDebugEnginesQuery + QDeclarativeDebugExpressionQuery + QDeclarativeDebugFileReference + QDeclarativeDebugger + QDeclarativeDebuggingEnabler + QDeclarativeDebugHelper + QDeclarativeDebugObjectExpressionWatch + QDeclarativeDebugObjectQuery + QDeclarativeDebugObjectReference + QDeclarativeDebugPropertyReference + QDeclarativeDebugPropertyWatch + QDeclarativeDebugQuery + QDeclarativeDebugRootContextQuery + QDeclarativeDebugServer + QDeclarativeDebugServerConnection + QDeclarativeDebugServerPrivate + QDeclarativeDebugServerThread + QDeclarativeDebugService + QDeclarativeDebugServicePrivate + QDeclarativeDebugStatesDelegate + QDeclarativeDebugTrace + QDeclarativeDebugWatch + QDeclarativeDelayedError + QDeclarativeDirComponents + QDeclarativeDirParser + QDeclarativeDirScripts + QDeclarativeDOMNodeResource + QDeclarativeEasingValueType + QDeclarativeElement + QDeclarativeEngine + QDeclarativeEngineDebug + QDeclarativeEngineDebugClient + QDeclarativeEngineDebugService + QDeclarativeEngineDebugPrivate + QDeclarativeEnginePrivate + QDeclarativeError + QDeclarativeErrorPrivate + QDeclarativeExpression + QDeclarativeExpressionPrivate + QDeclarativeExtensionInterface + QDeclarativeExtensionPlugin + QDeclarativeFontValueType + QDeclarativeGraphics_DerivedObject + QDeclarativeGuard + QDeclarativeGuardedContextData + QDeclarativeGuardImpl ++ QDeclarativeHandlingSignalProfiler + QDeclarativeImageProvider + QDeclarativeImageProviderPrivate + QDeclarativeImportDatabase + QDeclarativeImportedNamespace + QDeclarativeImports + QDeclarativeImportsPrivate + QDeclarativeIncubationController + QDeclarativeIncubator + QDeclarativeIncubatorController + QDeclarativeIncubatorPrivate + QDeclarativeIncubators + QDeclarativeInfo + QDeclarativeInfoPrivate + QDeclarativeInspector + QDeclarativeInspectorInterface + QDeclarativeInspectorService + QDeclarativeInstruction + QDeclarativeInstructionData + QDeclarativeInstructionMeta + QDeclarativeIntegerCache + QDeclarativeJavaScriptExpression + QDeclarativeJavaScriptExpressionGuard + QDeclarativeJS + QDeclarativeJSGrammar + QDeclarativeListProperty + QDeclarativeListReference + QDeclarativeListReferencePrivate + QDeclarativeLocale + QDeclarativeLocalStoragePlugin + QDeclarativeMatrix4x4ValueType + QDeclarativeMetaType + QDeclarativeMetaTypeData + QDeclarativeNetworkAccessManagerFactory + QDeclarativeNotifier + QDeclarativeNotifierEndpoint + QDeclarativeNullableValue + QDeclarativeNumberExtension ++ QDeclarativeObjectCreatingProfiler + QDeclarativeObjectData + QDeclarativeObjectProperty + QDeclarativeObserverMode + QDeclarativeOpenMetaObject + QDeclarativeOpenMetaObjectPrivate + QDeclarativeOpenMetaObjectType + QDeclarativeOpenMetaObjectTypePrivate + QDeclarativeParser + QDeclarativeParserStatus + QDeclarativePointFValueType + QDeclarativePointValueType + QDeclarativePool + QDeclarativePrivate + QDeclarativeProfilerData + QDeclarativeProfilerService + QDeclarativeProperties + QDeclarativeProperty + QDeclarativePropertyCache + QDeclarativePropertyCacheMethodArguments + QDeclarativePropertyData + QDeclarativePropertyMap + QDeclarativePropertyMapMetaObject + QDeclarativePropertyMapPrivate + QDeclarativePropertyPrivate + QDeclarativePropertyRawData + QDeclarativePropertyValueInterceptor + QDeclarativePropertyValueSource + QDeclarativeProxyMetaObject + QDeclarativeQmldirData + QDeclarativeQtQuick1Module + QDeclarativeQtQuick2Module + QDeclarativeQtQuick2DebugStatesDelegate + QDeclarativeQuaternionValueType + QDeclarativeRectFValueType + QDeclarativeRectValueType + QDeclarativeRefCount + QDeclarativeRefPointer + QDeclarativeRegisterType + QDeclarativeRewrite + QDeclarativeScript + QDeclarativeScriptBlob + QDeclarativeScriptData + QDeclarativeScriptPrivate + QDeclarativeScriptString + QDeclarativeScriptStringPrivate + QDeclarativeSizeFValueType + QDeclarativeSizeValueType + QDeclarativeSqlDatabaseData + QDeclarativeStringConverters + QDeclarativeThread + QDeclarativeThreadPrivate + QDeclarativeTrace + QDeclarativeType + QDeclarativeTypeData + QDeclarativeTypeInfo + QDeclarativeTypeLoader + QDeclarativeTypeModule + QDeclarativeTypeModulePrivate + QDeclarativeTypeModuleVersion + QDeclarativeTypeNameCache + QDeclarativeTypeNotAvailable + QDeclarativeTypePrivate + QDeclarativeTypesExtensionInterface + QDeclarativeV8Function + QDeclarativeV8Handle + QDeclarativeValueType + QDeclarativeValueTypeProxyBinding + QDeclarativeValueTypeFactory + QDeclarativeVector2DValueType + QDeclarativeVector3DValueType + QDeclarativeVector4DValueType + QDeclarativeVME + QDeclarativeVMEGuard + QDeclarativeVMEMetaData + QDeclarativeVMEMetaObject + QDeclarativeVMEMetaObjectEndpoint + QDeclarativeVMEVariant + QDeclarativeVMETypes + QDeclarativeWatcher + QDeclarativeWatchProxy + QDeclarativeXMLHttpRequest + QDeclarativeXMLHttpRequestData + QDeclarative_isFileCaseCorrect + QDeclarative_setParent_noEvent + QQuickProperties + QQuickPropertyCacheMethodArguments + QQuickPropertyData +" + +QUICK_SYMBOLS="\ + QDeclarativeAbstractAnimation + QDeclarativeAbstractAnimationAction + QDeclarativeAbstractAnimationPrivate + QDeclarativeAction + QDeclarativeActionEvent + QDeclarativeAnchors + QDeclarativeAnimationController + QDeclarativeAnimationControllerPrivate + QDeclarativeAnimationGroup + QDeclarativeAnimationGroupPrivate + QDeclarativeAnimationPropertyUpdater + QDeclarativeApplication + QDeclarativeApplicationPrivate + QDeclarativeBehavior + QDeclarativeBehaviorPrivate + QDeclarativeBind + QDeclarativeBindPrivate + QDeclarativeBulkValueAnimator + QDeclarativeBulkValueUpdater + QDeclarativeCachedBezier + QDeclarativeChangeSet + QDeclarativeColorAnimation + QDeclarativeConnections + QDeclarativeConnectionsPrivate + QDeclarativeCurve + QDeclarativeDefaultTextureFactory + QDeclarativeFlick + QDeclarativeFocusPanel + QDeclarativeFolderListModel + QDeclarativeFolderListModelPrivate + QDeclarativeFontLoader + QDeclarativeFontLoaderPrivate + QDeclarativeFontObject + QDeclarativeGestureArea + QDeclarativeGestureAreaParser + QDeclarativeGestureAreaPrivate + QDeclarativeGraphics + QDeclarativeItem + QDeclarativeItemAccessor + QDeclarativeItemChangeListener + QDeclarativeItemKeyFilter + QDeclarativeItemPrivate + QDeclarativeListAccessor + QDeclarativeListCompositor + QDeclarativeListElement + QDeclarativeListModel + QDeclarativeListModelParser + QDeclarativeListModelWorkerAgent + QDeclarativeListView + QDeclarativeNumberAnimation + QDeclarativePackage + QDeclarativePackageAttached + QDeclarativePackagePrivate + QDeclarativeParallelAnimation + QDeclarativeParticle + QDeclarativeParticleMotion + QDeclarativeParticleMotionGravity + QDeclarativeParticleMotionLinear + QDeclarativeParticleMotionWander + QDeclarativeParticles + QDeclarativeParticlesPainter + QDeclarativeParticlesPrivate + QDeclarativePath + QDeclarativePathArc + QDeclarativePathAttribute + QDeclarativePathCatmullRomCurve + QDeclarativePathCubic + QDeclarativePathCurve + QDeclarativePathData + QDeclarativePathElement + QDeclarativePathInterpolator + QDeclarativePathLine + QDeclarativePathPercent + QDeclarativePathPrivate + QDeclarativePathQuad + QDeclarativePathSvg + QDeclarativePauseAnimation + QDeclarativePauseAnimationPrivate + QDeclarativePixmap + QDeclarativePixmapData + QDeclarativePixmapKey + QDeclarativePixmapNull + QDeclarativePixmapReader + QDeclarativePixmapReaderThreadObject + QDeclarativePixmapReply + QDeclarativePixmapStore + QDeclarativePropertyAction + QDeclarativePropertyActionPrivate + QDeclarativePropertyAnimation + QDeclarativePropertyAnimationPrivate + QDeclarativePropertyChanges + QDeclarativePropertyChangesParser + QDeclarativePropertyChangesPrivate + QDeclarativeReplaceSignalHandler + QDeclarativeRevertAction + QDeclarativeRotationAnimation + QDeclarativeRotationAnimationPrivate + QDeclarativeSequentialAnimation + QDeclarativeScriptAction + QDeclarativeScriptActionPrivate + QDeclarativeSetPropertyAnimationAction + QDeclarativeSimpleAction + QDeclarativeSmoothedAnimation + QDeclarativeSmoothedAnimationPrivate + QDeclarativeSpringAnimation + QDeclarativeSpringAnimationPrivate + QDeclarativeState + QDeclarativeStateActions + QDeclarativeStateChange + QDeclarativeStateChangeScript + QDeclarativeStateChangeScriptPrivate + QDeclarativeStateGroup + QDeclarativeStateGroupPrivate + QDeclarativeStateOperation + QDeclarativeStateOperationPrivate + QDeclarativeStatePrivate + QDeclarativeStyledText + QDeclarativeStyledTextImgTag + QDeclarativeStyledTextPrivate + QDeclarativeSystemPalette + QDeclarativeSystemPalettePrivate + QDeclarativeTextureFactory + QDeclarativeTimeLine + QDeclarativeTimeLineCallback + QDeclarativeTimeLineObject + QDeclarativeTimeLinePrivate + QDeclarativeTimeLineValue + QDeclarativeTimeLineValueProxy + QDeclarativeTimeLineValues + QDeclarativeTimer + QDeclarativeTimerPrivate + QDeclarativeTransition + QDeclarativeTransitionInstance + QDeclarativeTransitionManager + QDeclarativeTransitionManagerPrivate + QDeclarativeTransitionPrivate + QDeclarativeUtilModule + QDeclarativeVector3dAnimation + QDeclarativeView + QDeclarativeViewInspector + QDeclarativeViewInspectorPrivate + QDeclarativeViewPrivate + QDeclarativeWebView + QDeclarativeXmlListModel + QDeclarativeXmlListModelPrivate + QDeclarativeXmlListModelRole + QDeclarativeXmlListRange + QDeclarativeXmlQueryEngine + QDeclarativeXmlQueryResult + QDeclarativeXmlQueryThreadObject + QDeclarativeXmlRoleList + QDeclarativeSvgParser + QDeclarativeWorkerScript + QDeclarativeWorkerScriptEngine + QDeclarativeWorkerScriptEnginePrivate +" + +QML_INCLUDE_FILES="\ + qdeclarativeaccessible.h + qdeclarativeaccessors_p.h + qdeclarativebinding_p.h + qdeclarativebinding_p_p.h + qdeclarativeboundsignal_p.h + qdeclarativebuiltinfunctions_p.h + qdeclarativecleanup_p.h + qdeclarativecompiler_p.h + qdeclarativecomponentattached_p.h + qdeclarativecomponent.h + qdeclarativecomponent_p.h + qdeclarativecontext.h + qdeclarativecontext_p.h + qdeclarativecustomparser_p.h + qdeclarativecustomparser_p_p.h + qdeclarativedata_p.h + qdeclarativedebugclient_p.h + qdeclarativedebug.h + qdeclarativedebughelper_p.h + qdeclarativedebugserverconnection_p.h + qdeclarativedebugserver_p.h + qdeclarativedebugservice_p.h + qdeclarativedebugservice_p_p.h + qdeclarativedebugstatesdelegate_p.h + qdeclarativedebugtrace_p.h + qdeclarativedirparser_p.h + qdeclarativeenginedebug_p.h + qdeclarativeenginedebugservice_p.h + qdeclarativeengine.h + qdeclarativeengine_p.h + qdeclarativeerror.h + qdeclarativeexpression.h + qdeclarativeexpression_p.h + qdeclarativeextensioninterface.h + qdeclarativeextensionplugin.h + qdeclarativeglobal_p.h + qdeclarativeguard_p.h + qdeclarative.h + qdeclarativeimageprovider.h + qdeclarativeimport_p.h + qdeclarativeincubator.h + qdeclarativeincubator_p.h + qdeclarativeinfo.h + qdeclarativeinspectorinterface_p.h + qdeclarativeinspectorprotocol.h + qdeclarativeinspectorservice_p.h + qdeclarativeinstruction_p.h + qdeclarativeintegercache_p.h + qdeclarativejsastfwd_p.h + qdeclarativejsast_p.h + qdeclarativejsastvisitor_p.h + qdeclarativejsengine_p.h + qdeclarativejsglobal_p.h + qdeclarativejsgrammar_p.h + qdeclarativejskeywords_p.h + qdeclarativejslexer_p.h + qdeclarativejsmemorypool_p.h + qdeclarativejsparser_p.h + qdeclarativelist.h + qdeclarativelist_p.h + qdeclarativelocale_p.h + qdeclarativemetatype_p.h + qdeclarativenetworkaccessmanagerfactory.h + qdeclarativenotifier_p.h + qdeclarativenullablevalue_p_p.h + qdeclarativeopenmetaobject_p.h + qdeclarativeparserstatus.h + qdeclarativepool_p.h + qdeclarativeprivate.h + qdeclarativeprofilerservice_p.h + qdeclarativepropertycache_p.h + qdeclarativeproperty.h + qdeclarativepropertymap.h + qdeclarativeproperty_p.h + qdeclarativepropertyvalueinterceptor_p.h + qdeclarativepropertyvaluesource.h + qdeclarativeproxymetaobject_p.h + qdeclarativerefcount_p.h + qdeclarativerewrite_p.h + qdeclarativescript_p.h + qdeclarativescriptstring.h + qdeclarativescriptstring_p.h + qdeclarativesqldatabase_p.h + qdeclarativestringconverters_p.h + qdeclarativethread_p.h + qdeclarativetrace_p.h + qdeclarativetypeloader_p.h + qdeclarativetypenamecache_p.h + qdeclarativetypenotavailable_p.h + qdeclarativevaluetype_p.h + qdeclarativevmemetaobject_p.h + qdeclarativevme_p.h + qdeclarativewatcher_p.h + qdeclarativexmlhttprequest_p.h + qdeclarativexmllistmodel_p.h +" + +QUICK_INCLUDE_FILES="\ + qdeclarativeanimation_p.h + qdeclarativeanimation_p_p.h + qdeclarativeanimationcontroller_p.h + qdeclarativeapplication_p.h + qdeclarativebehavior_p.h + qdeclarativebind_p.h + qdeclarativechangeset_p.h + qdeclarativeconnections_p.h + qdeclarativefolderlistmodel.h + qdeclarativefontloader_p.h + qdeclarativelistaccessor_p.h + qdeclarativelistcompositor_p.h + qdeclarativelistmodel_p.h + qdeclarativelistmodel_p_p.h + qdeclarativelistmodelworkeragent_p.h + qdeclarativepackage_p.h + qdeclarativepathinterpolator_p.h + qdeclarativepath_p.h + qdeclarativepath_p_p.h + qdeclarativepixmapcache_p.h + qdeclarativepropertychanges_p.h + qdeclarativesmoothedanimation_p.h + qdeclarativesmoothedanimation_p_p.h + qdeclarativespringanimation_p.h + qdeclarativestategroup_p.h + qdeclarativestateoperations_p.h + qdeclarativestate_p.h + qdeclarativestate_p_p.h + qdeclarativestyledtext_p.h + qdeclarativesvgparser_p.h + qdeclarativesystempalette_p.h + qdeclarativetimeline_p_p.h + qdeclarativetimer_p.h + qdeclarativetransitionmanager_p_p.h + qdeclarativetransition_p.h + qdeclarativeutilmodule_p.h + qdeclarativeworkerscript_p.h +" + +replaceMatch() +{ + SYMBOL="$1" + REPLACEMENT="$2" + echo "Replacing $SYMBOL with $REPLACEMENT:" + + CONTAINERS=$(find "$MODIFY_DIR" ! -path ".git" -type f | xargs grep -l -I "$SYMBOL") + for CONTAINER in $CONTAINERS + do + echo " $CONTAINER" + TMP_FILE="$CONTAINER.tmp" + + sed 's|'"$SYMBOL"'|'"$REPLACEMENT"'|g' <"$CONTAINER" >"$TMP_FILE" + mv "$TMP_FILE" "$CONTAINER" + done + echo +} + +for QML_SYMBOL in $QML_SYMBOLS +do + QML_REPLACEMENT="QQml${QML_SYMBOL#QDeclarative}" + replaceMatch "\" "QtQml/$QML_REPLACEMENT" + replaceMatch "\<$QML_SYMBOL\>" "$QML_REPLACEMENT" +done + +for QUICK_SYMBOL in $QUICK_SYMBOLS +do + QUICK_REPLACEMENT="QQuick${QUICK_SYMBOL#QDeclarative}" + replaceMatch "\" "QtQuick/$QUICK_REPLACEMENT" + replaceMatch "\<$QUICK_SYMBOL\>" "$QUICK_REPLACEMENT" +done + +for QML_INCLUDE_FILE in $QML_INCLUDE_FILES +do + QML_INCLUDE_REPLACEMENT="qqml${QML_INCLUDE_FILE#qdeclarative}" + replaceMatch "\<$QML_INCLUDE_FILE\>" "$QML_INCLUDE_REPLACEMENT" +done + +for QUICK_INCLUDE_FILE in $QUICK_INCLUDE_FILES +do + QUICK_INCLUDE_REPLACEMENT="qquick${QUICK_INCLUDE_FILE#qdeclarative}" + replaceMatch "\<$QUICK_INCLUDE_FILE\>" "$QUICK_INCLUDE_REPLACEMENT" +done + +# Various one-off replacements +replaceMatch "\" "QtQml" +replaceMatch "\") +for CONTAINER in $CONTAINERS +do + echo " $CONTAINER" + TMP_FILE="$CONTAINER.tmp" + + sed 's|\|qml|g' <"$CONTAINER" >"$TMP_FILE" + mv "$TMP_FILE" "$CONTAINER" +done +echo + +echo "Replacements complete" +exit 0 diff --cc examples/HACKING index 0000000,7eea497..9539d2d mode 000000,100644..100644 --- a/examples/HACKING +++ b/examples/HACKING @@@ -1,0 -1,23 +1,23 @@@ -Some guidelines for QtDeclarative examples ++Some guidelines for QtQml examples + + Snippets + --- + Snippets are snatches of QML code that won't even run on their own. They don't belong here, they belong in doc/src/snippets. They should be contained in files that will compile on their own, for automated syntax validation, but don't have to look like anything. + + Examples + --- + + Examples are large blocks of QML code that demonstrate a feature. You should be able to launch an example and visually see the feature take effect. Examples should be written in a small form, and should automatically activate any features. Ideally, when you run an example, you see the feature demonstrate itself over and over until you get bored and close the application using your platform's close window mechanism. Examples shouldn't contain their own close buttons or start screen, explanatory text should be kept to a minimum (show, not tell), and reserve interaction for demonstrating interactive elements. The code should be held to a high level of quality, and should be understandable by people new to QML. + + Unless the demonstrated feature uses it, assume no interface devices other than a screen that can show a 320x480 rectangle and a generic pointing device (with the shared subset of mouse/touch functionality). + + Groups of similar examples should be placed in one folder with a single launcher application, which uses the shared folder of common components. + + The example, or launcher application in case of groups, should contain a qdoc comment explaining the example. The example or launcher should be buildable as a full C++ application and runnable with the standard qml file launcher. Usually this will consist primarily of using the macro found in shared.h. + + Demos + --- + + Demos are examples of creating full applications using QML. They should fit both a desktop and a mobile form factor, they should have their own start screen and method of exiting the application. They should be at a level of quality that you'd be comfortable submitting them to an app store for a platform of the appropriate hardware (screen size, input methods, etc.). The code should be written to a level that is easily understood and modified by a QML expert. + + Demos should have a qdoc file in their directory explaining the demo at a high level. The demo should be buildable as a full C++ application and preferably runnable with the standard qml file launcher. diff --cc examples/demos/calculator/CalculatorCore/Button.qml index 0000000,872fc81..e7b3637 mode 000000,100644..100644 --- a/examples/demos/calculator/CalculatorCore/Button.qml +++ b/examples/demos/calculator/CalculatorCore/Button.qml @@@ -1,0 -1,84 +1,84 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + BorderImage { + id: button + + property alias operation: buttonText.text + property string color: "" + + Accessible.name: operation + Accessible.description: "This button does " + operation + Accessible.role: Accessible.Button + + signal clicked + + source: "images/button-" + color + ".png"; clip: true + border { left: 10; top: 10; right: 10; bottom: 10 } + + Rectangle { + id: shade + anchors.fill: button; radius: 10; color: "black"; opacity: 0 + } + + Text { + id: buttonText + anchors.centerIn: parent; anchors.verticalCenterOffset: -1 + font.pixelSize: parent.width > parent.height ? parent.height * .5 : parent.width * .5 + style: Text.Sunken; color: "white"; styleColor: "black"; smooth: true + } + + MouseArea { + id: mouseArea + anchors.fill: parent + onClicked: { + window.doOp(operation) + button.clicked() + } + } + + states: State { + name: "pressed"; when: mouseArea.pressed == true + PropertyChanges { target: shade; opacity: .4 } + } + } diff --cc examples/demos/calculator/CalculatorCore/Display.qml index 0000000,3333484..3dceeab mode 000000,100644..100644 --- a/examples/demos/calculator/CalculatorCore/Display.qml +++ b/examples/demos/calculator/CalculatorCore/Display.qml @@@ -1,0 -1,68 +1,68 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + BorderImage { + id: image + + property alias text : displayText.text + property alias currentOperation : operationText + + source: "images/display.png" + border { left: 10; top: 10; right: 10; bottom: 10 } + + Text { + id: displayText + anchors { + right: parent.right; verticalCenter: parent.verticalCenter; verticalCenterOffset: -1 + rightMargin: 6; left: operationText.right + } + font.pixelSize: parent.height * .6; text: "0"; horizontalAlignment: Text.AlignRight; elide: Text.ElideRight + color: "#343434"; smooth: true; font.bold: true + } + Text { + id: operationText + font.bold: true; font.pixelSize: parent.height * .7 + color: "#343434"; smooth: true + anchors { left: parent.left; leftMargin: 6; verticalCenterOffset: -3; verticalCenter: parent.verticalCenter } + } + } diff --cc examples/demos/calculator/calculator-desktop.qml index 0000000,7e72f50..be65c77 mode 000000,100644..100644 --- a/examples/demos/calculator/calculator-desktop.qml +++ b/examples/demos/calculator/calculator-desktop.qml @@@ -1,0 -1,136 +1,136 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + import QtQuick.Window 2.0 + import "CalculatorCore" + import "CalculatorCore/calculator.js" as CalcEngine + + Rectangle { + id: window + + width: 640; height: 480 + color: "#282828" + + property string rotateLeft: "\u2939" + property string rotateRight: "\u2935" + property string leftArrow: "\u2190" + property string division : "\u00f7" + property string multiplication : "\u00d7" + property string squareRoot : "\u221a" + property string plusminus : "\u00b1" + + function doOp(operation) { CalcEngine.doOperation(operation) } + focus: true + Keys.onPressed: doOp(event.text); + + Item { + id: main + width: 640 + height: 480 + anchors.centerIn: parent + + Column { + id: box; spacing: 8 + + anchors { fill: parent; topMargin: 6; bottomMargin: 6; leftMargin: 6; rightMargin: 6 } + + Display { + id: display + width: box.width-3 + height: 64 + } + + Column { + id: column; spacing: 6 + + property real h: ((box.height - 72) / 6) - ((spacing * (6 - 1)) / 6) + property real w: (box.width / 4) - ((spacing * (4 - 1)) / 4) + + Row { + spacing: 6 + Button { width: column.w; height: column.h; color: 'purple'; operation: "Off" } + Button { width: column.w; height: column.h; color: 'purple'; operation: leftArrow } + Button { width: column.w; height: column.h; color: 'purple'; operation: "C" } + Button { width: column.w; height: column.h; color: 'purple'; operation: "AC" } + } + + Row { + spacing: 6 + property real w: (box.width / 4) - ((spacing * (4 - 1)) / 4) + + Button { width: column.w; height: column.h; color: 'green'; operation: "mc" } + Button { width: column.w; height: column.h; color: 'green'; operation: "m+" } + Button { width: column.w; height: column.h; color: 'green'; operation: "m-" } + Button { width: column.w; height: column.h; color: 'green'; operation: "mr" } + } + + Grid { + id: grid; rows: 5; columns: 5; spacing: 6 + + property real w: (box.width / columns) - ((spacing * (columns - 1)) / columns) + + Button { width: grid.w; height: column.h; operation: "7"; color: 'blue' } + Button { width: grid.w; height: column.h; operation: "8"; color: 'blue' } + Button { width: grid.w; height: column.h; operation: "9"; color: 'blue' } + Button { width: grid.w; height: column.h; operation: division } + Button { width: grid.w; height: column.h; operation: squareRoot } + Button { width: grid.w; height: column.h; operation: "4"; color: 'blue' } + Button { width: grid.w; height: column.h; operation: "5"; color: 'blue' } + Button { width: grid.w; height: column.h; operation: "6"; color: 'blue' } + Button { width: grid.w; height: column.h; operation: multiplication } + Button { width: grid.w; height: column.h; operation: "x^2" } + Button { width: grid.w; height: column.h; operation: "1"; color: 'blue' } + Button { width: grid.w; height: column.h; operation: "2"; color: 'blue' } + Button { width: grid.w; height: column.h; operation: "3"; color: 'blue' } + Button { width: grid.w; height: column.h; operation: "-" } + Button { width: grid.w; height: column.h; operation: "1/x" } + Button { width: grid.w; height: column.h; operation: "0"; color: 'blue' } + Button { width: grid.w; height: column.h; operation: "." } + Button { width: grid.w; height: column.h; operation: plusminus } + Button { width: grid.w; height: column.h; operation: "+" } + Button { width: grid.w; height: column.h; operation: "="; color: 'red' } + } + } + } + + } + } diff --cc examples/demos/calculator/calculator-mobile.qml index 0000000,b4fc372..7ee622f mode 000000,100644..100644 --- a/examples/demos/calculator/calculator-mobile.qml +++ b/examples/demos/calculator/calculator-mobile.qml @@@ -1,0 -1,164 +1,164 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + import QtQuick.Window 2.0 + import "CalculatorCore" + import "CalculatorCore/calculator.js" as CalcEngine + + Rectangle { + id: window + + width: 320; height: 480 + color: "#282828" + + property string rotateLeft: "\u2939" + property string rotateRight: "\u2935" + property string leftArrow: "\u2190" + property string division : "\u00f7" + property string multiplication : "\u00d7" + property string squareRoot : "\u221a" + property string plusminus : "\u00b1" + + function doOp(operation) { CalcEngine.doOperation(operation) } + + Item { + id: main + state: "orientation " + Screen.orientation + + //Note: Assumes a primarily portrait device + property bool landscapeWindow: window.width > window.height + property real baseWidth: landscapeWindow ? window.height : window.width + property real baseHeight: landscapeWindow ? window.width : window.height + property real rotationDelta: landscapeWindow ? -90 : 0 + + rotation: rotationDelta + width: main.baseWidth + height: main.baseHeight + anchors.centerIn: parent + + Column { + id: box; spacing: 8 + + anchors { fill: parent; topMargin: 6; bottomMargin: 6; leftMargin: 6; rightMargin: 6 } + + Display { + id: display + width: box.width-3 + height: 64 + } + + Column { + id: column; spacing: 6 + + property real h: ((box.height - 72) / 6) - ((spacing * (6 - 1)) / 6) + property real w: (box.width / 4) - ((spacing * (4 - 1)) / 4) + + Row { + spacing: 6 + Button { width: column.w; height: column.h; color: 'purple'; operation: "Off" } + Button { width: column.w; height: column.h; color: 'purple'; operation: leftArrow } + Button { width: column.w; height: column.h; color: 'purple'; operation: "C" } + Button { width: column.w; height: column.h; color: 'purple'; operation: "AC" } + } + + Row { + spacing: 6 + property real w: (box.width / 4) - ((spacing * (4 - 1)) / 4) + + Button { width: column.w; height: column.h; color: 'green'; operation: "mc" } + Button { width: column.w; height: column.h; color: 'green'; operation: "m+" } + Button { width: column.w; height: column.h; color: 'green'; operation: "m-" } + Button { width: column.w; height: column.h; color: 'green'; operation: "mr" } + } + + Grid { + id: grid; rows: 5; columns: 5; spacing: 6 + + property real w: (box.width / columns) - ((spacing * (columns - 1)) / columns) + + Button { width: grid.w; height: column.h; operation: "7"; color: 'blue' } + Button { width: grid.w; height: column.h; operation: "8"; color: 'blue' } + Button { width: grid.w; height: column.h; operation: "9"; color: 'blue' } + Button { width: grid.w; height: column.h; operation: division } + Button { width: grid.w; height: column.h; operation: squareRoot } + Button { width: grid.w; height: column.h; operation: "4"; color: 'blue' } + Button { width: grid.w; height: column.h; operation: "5"; color: 'blue' } + Button { width: grid.w; height: column.h; operation: "6"; color: 'blue' } + Button { width: grid.w; height: column.h; operation: multiplication } + Button { width: grid.w; height: column.h; operation: "x^2" } + Button { width: grid.w; height: column.h; operation: "1"; color: 'blue' } + Button { width: grid.w; height: column.h; operation: "2"; color: 'blue' } + Button { width: grid.w; height: column.h; operation: "3"; color: 'blue' } + Button { width: grid.w; height: column.h; operation: "-" } + Button { width: grid.w; height: column.h; operation: "1/x" } + Button { width: grid.w; height: column.h; operation: "0"; color: 'blue' } + Button { width: grid.w; height: column.h; operation: "." } + Button { width: grid.w; height: column.h; operation: plusminus } + Button { width: grid.w; height: column.h; operation: "+" } + Button { width: grid.w; height: column.h; operation: "="; color: 'red' } + } + } + } + + states: [ + State { + name: "orientation " + Qt.LandscapeOrientation + PropertyChanges { target: main; rotation: 90 + rotationDelta; width: main.baseHeight; height: main.baseWidth } + }, + State { + name: "orientation " + Qt.InvertedPortraitOrientation + PropertyChanges { target: main; rotation: 180 + rotationDelta; } + }, + State { + name: "orientation " + Qt.InvertedLandscapeOrientation + PropertyChanges { target: main; rotation: 270 + rotationDelta; width: main.baseHeight; height: main.baseWidth } + } + ] + + transitions: Transition { + SequentialAnimation { + RotationAnimation { direction: RotationAnimation.Shortest; duration: 300; easing.type: Easing.InOutQuint } + NumberAnimation { properties: "x,y,width,height"; duration: 300; easing.type: Easing.InOutQuint } + } + } + } + } diff --cc examples/demos/calculator/calculator.pro index 0000000,3bf3b8c..297d5cf mode 000000,100644..100644 --- a/examples/demos/calculator/calculator.pro +++ b/examples/demos/calculator/calculator.pro @@@ -1,0 -1,9 +1,9 @@@ + TEMPLATE = app + -QT += quick declarative ++QT += quick qml + SOURCES += main.cpp + + target.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/demos/calculator + qml.files = calculator-desktop.qml calculator-mobile.qml CalculatorCore + qml.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/demos/calculator + INSTALLS += target qml diff --cc examples/demos/calculator/main.cpp index 0000000,c7f9b29..fafe14f mode 000000,100644..100644 --- a/examples/demos/calculator/main.cpp +++ b/examples/demos/calculator/main.cpp @@@ -1,0 -1,66 +1,66 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** + ** This file is part of the examples of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:BSD$ + ** You may use this file under the terms of the BSD license as follows: + ** + ** "Redistribution and use in source and binary forms, with or without + ** modification, are permitted provided that the following conditions are + ** met: + ** * Redistributions of source code must retain the above copyright + ** notice, this list of conditions and the following disclaimer. + ** * Redistributions in binary form must reproduce the above copyright + ** notice, this list of conditions and the following disclaimer in + ** the documentation and/or other materials provided with the + ** distribution. + ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor + ** the names of its contributors may be used to endorse or promote + ** products derived from this software without specific prior written + ** permission. + ** + ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + #include + #include + #include -#include ++#include + + void usage() + { + printf("Pass -desktop to use the Desktop UI"); + exit(0); + } + + int main(int argc, char* argv[]) + { + QGuiApplication app(argc,argv); + QQuickView view; + QUrl launchFile = QUrl::fromLocalFile(QLatin1String("calculator-mobile.qml")); + if (app.arguments().contains(QLatin1String("-help"))) + usage(); + if (app.arguments().contains(QLatin1String("-desktop"))) + launchFile = QUrl::fromLocalFile(QLatin1String("calculator-desktop.qml")); + view.connect(view.engine(), SIGNAL(quit()), &app, SLOT(quit())); + view.setSource(launchFile); + view.show(); + return app.exec(); + } + diff --cc examples/demos/flickr/content/Button.qml index 0000000,d6a8d3e..57f846a mode 000000,100644..100644 --- a/examples/demos/flickr/content/Button.qml +++ b/examples/demos/flickr/content/Button.qml @@@ -1,0 -1,79 +1,79 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Item { + id: container + + signal clicked + + property string text + + BorderImage { + id: buttonImage + source: "images/toolbutton.sci" + width: container.width; height: container.height + } + BorderImage { + id: pressed + opacity: 0 + source: "images/toolbutton.sci" + width: container.width; height: container.height + } + MouseArea { + id: mouseRegion + anchors.fill: buttonImage + onClicked: { container.clicked(); } + } + Text { + color: "white" + anchors.centerIn: buttonImage; font.bold: true; font.pixelSize: 15 + text: container.text; style: Text.Raised; styleColor: "black" + } + states: [ + State { + name: "Pressed" + when: mouseRegion.pressed == true + PropertyChanges { target: pressed; opacity: 1 } + } + ] + } diff --cc examples/demos/flickr/content/GridDelegate.qml index 0000000,794d768..f8838bd mode 000000,100644..100644 --- a/examples/demos/flickr/content/GridDelegate.qml +++ b/examples/demos/flickr/content/GridDelegate.qml @@@ -1,0 -1,111 +1,111 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Item { + id: wrapper; width: GridView.view.cellWidth; height: GridView.view.cellHeight + + function photoClicked() { + imageDetails.photoTitle = title; + imageDetails.photoTags = tags; + imageDetails.photoWidth = photoWidth; + imageDetails.photoHeight = photoHeight; + imageDetails.photoType = photoType; + imageDetails.photoAuthor = photoAuthor; + imageDetails.photoDate = photoDate; + imageDetails.photoUrl = url; + imageDetails.rating = 0; + scaleMe.state = "Details"; + } + + Item { + anchors.centerIn: parent + scale: 0.0 + Behavior on scale { NumberAnimation { easing.type: Easing.InOutQuad} } + id: scaleMe + + Item { + width: 77; height: 77; anchors.centerIn: parent + Rectangle { + id: whiteRect; width: 77; height: 77; color: "#dddddd"; smooth: true + Image { id: thumb; source: imagePath; x: 1; y: 1; smooth: true } + Image { source: "images/gloss.png" } + } + } + + Connections { + target: toolBar + onButton2Clicked: if (scaleMe.state == 'Details' ) scaleMe.state = 'Show' + } + + states: [ + State { + name: "Show"; when: thumb.status == Image.Ready + PropertyChanges { target: scaleMe; scale: 1 } + }, + State { + name: "Details" + PropertyChanges { target: scaleMe; scale: 1 } + ParentChange { target: whiteRect; x: 10; y: 20; parent: imageDetails.frontContainer } + PropertyChanges { target: background; state: "DetailedView" } + } + ] + transitions: [ + Transition { + from: "Show"; to: "Details" + ParentAnimation { + via: foreground + NumberAnimation { properties: "x,y"; duration: 500; easing.type: Easing.InOutQuad } + } + }, + Transition { + from: "Details"; to: "Show" + ParentAnimation { + via: foreground + NumberAnimation { properties: "x,y"; duration: 500; easing.type: Easing.InOutQuad } + } + } + ] + } + MouseArea { anchors.fill: wrapper; onClicked: photoClicked() } + } + diff --cc examples/demos/flickr/content/ImageDetails.qml index 0000000,83f2537..42b5e84 mode 000000,100644..100644 --- a/examples/demos/flickr/content/ImageDetails.qml +++ b/examples/demos/flickr/content/ImageDetails.qml @@@ -1,0 -1,323 +1,323 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + import QtQuick.Particles 2.0 + + Flipable { + id: container + + property alias frontContainer: containerFront + property string photoTitle: "" + property string photoTags: "" + property int photoWidth + property int photoHeight + property string photoType + property string photoAuthor + property string photoDate + property string photoUrl + property int rating: 2 + property variant prevScale: 1.0 + + property int flipDuration: 1600 + + signal closed + + transform: Rotation { + id: itemRotation + origin.x: container.width / 2; + axis.y: 1; axis.z: 0 + } + + front: Item { + id: containerFront; anchors.fill: container + + Rectangle { + anchors.fill: parent + color: "black"; opacity: 0.4 + } + + Column { + spacing: 10 + anchors { + left: parent.left; leftMargin: 10 + right: parent.right; rightMargin: 10 + top: parent.top; topMargin: 120 + } + Text { font.bold: true; color: "white"; elide: Text.ElideRight; text: container.photoTitle; width: parent.width } + Text { color: "white"; elide: Text.ElideRight; text: "Size: " + container.photoWidth + 'x' + container.photoHeight; width: parent.width } + Text { color: "white"; elide: Text.ElideRight; text: "Type: " + container.photoType; width: parent.width } + Text { color: "white"; elide: Text.ElideRight; text: "Author: " + container.photoAuthor; width: parent.width } + Text { color: "white"; elide: Text.ElideRight; text: "Published: " + container.photoDate; width: parent.width } + Text { color: "white"; elide: Text.ElideRight; text: container.photoTags == "" ? "" : "Tags: "; width: parent.width } + Text { color: "white"; elide: Text.ElideRight; text: container.photoTags; width: parent.width } + } + } + + back: Item { + anchors.fill: container + + Rectangle { anchors.fill: parent; color: "black"; opacity: 0.4 } + + Progress { + anchors.centerIn: parent; width: 200; height: 22 + progress: bigImage.progress; visible: bigImage.status != Image.Ready + } + + Flickable { + id: flickable; anchors.fill: parent; clip: true + contentWidth: imageContainer.width; contentHeight: imageContainer.height + + function updateMinimumScale() { + if (bigImage.status == Image.Ready && bigImage.width != 0) { + slider.minimum = Math.min(flickable.width / bigImage.width, flickable.height / bigImage.height); + if (bigImage.width * slider.value > flickable.width) { + var xoff = (flickable.width/2 + flickable.contentX) * slider.value / prevScale; + flickable.contentX = xoff - flickable.width/2; + } + if (bigImage.height * slider.value > flickable.height) { + var yoff = (flickable.height/2 + flickable.contentY) * slider.value / prevScale; + flickable.contentY = yoff - flickable.height/2; + } + prevScale = slider.value; + } + } + + onWidthChanged: updateMinimumScale() + onHeightChanged: updateMinimumScale() + + Item { + id: imageContainer + width: Math.max(bigImage.width * bigImage.scale, flickable.width); + height: Math.max(bigImage.height * bigImage.scale, flickable.height); + Image { + id: bigImage; source: container.photoUrl; scale: slider.value + anchors.centerIn: parent; smooth: !flickable.movingVertically + onStatusChanged : { + // Default scale shows the entire image. + if (bigImage.status == Image.Ready && bigImage.width != 0) { + slider.minimum = Math.min(flickable.width / bigImage.width, flickable.height / bigImage.height); + prevScale = Math.min(slider.minimum, 1); + slider.value = prevScale; + } + if (inBackState && bigImage.status == Image.Ready) + effectBox.imageInAnim(); + } + property bool inBackState: false + onInBackStateChanged:{ + if(inBackState && bigImage.status == Image.Ready) + effectBox.imageInAnim(); + else if (!inBackState && bigImage.status == Image.Ready) + effectBox.imageOutAnim(); + } + } + ShaderEffectSource{ + id: pictureSource + sourceItem: bigImage + smooth: true + //Workaround: Doesn't work below lines + width: bigImage.width + height: bigImage.width + visible: false + } + Turbulence{//only fill visible rect + id: turbulence + system: imageSystem + anchors.fill: parent + strength: 240 + enabled: false + } + + Item{ + id: effectBox + width: bigImage.width * bigImage.scale + height: bigImage.height * bigImage.scale + anchors.centerIn: parent + function imageInAnim(){ + bigImage.visible = false; + noiseIn.visible = true; + endEffectTimer.start(); + } + function imageOutAnim(){ + bigImage.visible = false; + noiseIn.visible = false; + turbulence.enabled = true; + endEffectTimer.start(); + pixelEmitter.burst(2048); + } + Timer{ + id: endEffectTimer + interval: flipDuration + repeat: false + running: false + onTriggered:{ + turbulence.enabled = false; + noiseIn.visible = false; + bigImage.visible = true; + } + } + ShaderEffect{ + id: noiseIn + anchors.fill: parent + property real t: 0 + visible: false + onVisibleChanged: tAnim.start() + NumberAnimation{ + id: tAnim + target: noiseIn + property: "t" + from: 0.0 + to: 1.0 + duration: flipDuration + } + property variant source: pictureSource + property variant noise: ShaderEffectSource{ + sourceItem:Image{ + source: "images/noise.png" + } + hideSource: true + smooth: false + } + fragmentShader:" + uniform sampler2D noise; + uniform sampler2D source; + uniform highp float t; + uniform lowp float qt_Opacity; + varying highp vec2 qt_TexCoord0; + void main(){ + //Want to use noise2, but it always returns (0,0)? + if(texture2D(noise, qt_TexCoord0).w <= t) + gl_FragColor = texture2D(source, qt_TexCoord0) * qt_Opacity; + else + gl_FragColor = vec4(0.,0.,0.,0.); + } + " + } + ParticleSystem{ + id: imageSystem + } + Emitter{ + id: pixelEmitter + system: imageSystem + //anchors.fill: parent + width: Math.min(bigImage.width * bigImage.scale, flickable.width); + height: Math.min(bigImage.height * bigImage.scale, flickable.height); + anchors.centerIn: parent + size: 4 + lifeSpan: flipDuration + emitRate: 2048 + enabled: false + } + CustomParticle{ + id: blowOut + system: imageSystem + property real maxWidth: effectBox.width + property real maxHeight: effectBox.height + vertexShader:" + uniform highp float maxWidth; + uniform highp float maxHeight; + + varying highp vec2 fTex2; + + void main() { + defaultMain(); + fTex2 = vec2(qt_ParticlePos.x / maxWidth, qt_ParticlePos.y / maxHeight); + } + " + property variant pictureTexture: pictureSource + fragmentShader: " + uniform lowp float qt_Opacity; + uniform sampler2D pictureTexture; + varying highp vec2 fTex2; + void main() { + gl_FragColor = texture2D(pictureTexture, fTex2) * qt_Opacity; + }" + } + + + + } + } + } + + Text { + text: "Image Unavailable" + visible: bigImage.status == Image.Error + anchors.centerIn: parent; color: "white"; font.bold: true + } + + Slider { + id: slider; visible: { bigImage.status == Image.Ready && maximum > minimum } + anchors { + bottom: parent.bottom; bottomMargin: 65 + left: parent.left; leftMargin: 25 + right: parent.right; rightMargin: 25 + } + onValueChanged: { + if (bigImage.width * value > flickable.width) { + var xoff = (flickable.width/2 + flickable.contentX) * value / prevScale; + flickable.contentX = xoff - flickable.width/2; + } + if (bigImage.height * value > flickable.height) { + var yoff = (flickable.height/2 + flickable.contentY) * value / prevScale; + flickable.contentY = yoff - flickable.height/2; + } + prevScale = value; + } + } + } + + states: State { + name: "Back" + PropertyChanges { target: itemRotation; angle: 180 } + PropertyChanges { target: toolBar; button2Visible: false } + PropertyChanges { target: toolBar; button1Label: "Back" } + PropertyChanges { target: bigImage; inBackState: true } + } + + transitions: Transition { + SequentialAnimation { + PropertyAction { target: bigImage; property: "smooth"; value: false } + NumberAnimation { easing.type: Easing.InOutQuad; properties: "angle"; duration: flipDuration } + PropertyAction { target: bigImage; property: "smooth"; value: !flickable.movingVertically } + } + } + } diff --cc examples/demos/flickr/content/ListDelegate.qml index 0000000,9c23915..00f837f mode 000000,100644..100644 --- a/examples/demos/flickr/content/ListDelegate.qml +++ b/examples/demos/flickr/content/ListDelegate.qml @@@ -1,0 -1,64 +1,64 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Component { + Item { + id: wrapper; width: wrapper.ListView.view.width; height: 86 + Item { + id: moveMe + Rectangle { color: "black"; opacity: index % 2 ? 0.2 : 0.4; height: 84; width: wrapper.width; y: 1 } + Rectangle { + x: 6; y: 4; width: 77; height: 77; color: "white"; smooth: true + + Image { source: imagePath; x: 1; y: 1 } + Image { source: "images/gloss.png" } + } + Column { + x: 92; width: wrapper.ListView.view.width - 95; y: 15; spacing: 2 + Text { text: title; color: "white"; width: parent.width; font.pixelSize: 14; font.bold: true; elide: Text.ElideRight; style: Text.Raised; styleColor: "black" } + Text { text: photoAuthor; width: parent.width; font.pixelSize: 14; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" } + Text { text: photoDate; width: parent.width; font.pixelSize: 14; elide: Text.ElideRight; color: "#cccccc"; style: Text.Raised; styleColor: "black" } + } + } + } + } diff --cc examples/demos/flickr/content/Progress.qml index 0000000,81f1e79..ed2629b mode 000000,100644..100644 --- a/examples/demos/flickr/content/Progress.qml +++ b/examples/demos/flickr/content/Progress.qml @@@ -1,0 -1,88 +1,88 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + import QtQuick.Particles 2.0 + + Item{ + id: container + property variant progress: 0 + + Rectangle { + anchors.fill: parent; smooth: true + border.color: "white"; border.width: 0; radius: height/2 - 2 + gradient: Gradient { + GradientStop { position: 0; color: "#66343434" } + GradientStop { position: 1.0; color: "#66000000" } + } + } + + ParticleSystem{ + running: container.visible + id: barSys + } + ImageParticle{ + color: "lightsteelblue" + alpha: 0.1 + colorVariation: 0.05 + source: "images/particle.png" + system: barSys + } + Emitter{ + y: 2; height: parent.height-4; + x: 2; width: Math.max(parent.width * progress - 4, 0); + speed: AngleDirection{ angleVariation: 180; magnitudeVariation: 12 } + system: barSys + emitRate: width; + lifeSpan: 1000 + size: 20 + sizeVariation: 4 + endSize: 12 + maximumEmitted: parent.width; + } + + Text { + text: Math.round(progress * 100) + "%" + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + color: Qt.rgba(1.0, 1.0 - progress, 1.0 - progress,0.9); font.bold: true; font.pixelSize: 15 + } + } diff --cc examples/demos/flickr/content/RssModel.qml index 0000000,f28a23d..51cea49 mode 000000,100644..100644 --- a/examples/demos/flickr/content/RssModel.qml +++ b/examples/demos/flickr/content/RssModel.qml @@@ -1,0 -1,64 +1,64 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + import QtQuick.XmlListModel 2.0 + + XmlListModel { + property string tags : "" + + function encodeTags(x) { return encodeURIComponent(x.replace(' ',',')); } + + source: "http://api.flickr.com/services/feeds/photos_public.gne?"+(tags ? "tags="+encodeTags(tags)+"&" : "")+"format=rss2" + query: "/rss/channel/item" + namespaceDeclarations: "declare namespace media=\"http://search.yahoo.com/mrss/\";" + + XmlRole { name: "title"; query: "title/string()" } + XmlRole { name: "imagePath"; query: "media:thumbnail/@url/string()" } + XmlRole { name: "url"; query: "media:content/@url/string()" } + XmlRole { name: "description"; query: "description/string()" } + XmlRole { name: "tags"; query: "media:category/string()" } + XmlRole { name: "photoWidth"; query: "media:content/@width/string()" } + XmlRole { name: "photoHeight"; query: "media:content/@height/string()" } + XmlRole { name: "photoType"; query: "media:content/@type/string()" } + XmlRole { name: "photoAuthor"; query: "author/string()" } + XmlRole { name: "photoDate"; query: "pubDate/string()" } + } diff --cc examples/demos/flickr/content/ScrollBar.qml index 0000000,388e43d..7c62ad0 mode 000000,100644..100644 --- a/examples/demos/flickr/content/ScrollBar.qml +++ b/examples/demos/flickr/content/ScrollBar.qml @@@ -1,0 -1,81 +1,81 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Item { + id: container + + property variant flickableArea + + Rectangle { + radius: 5 + color: "black" + opacity: 0.3 + border.color: "white" + border.width: 2 + x: 0 + y: flickableArea.visibleArea.yPosition * container.height + width: parent.width + height: flickableArea.visibleArea.heightRatio * container.height + } + states: [ + State { + name: "show" + when: flickableArea.movingVertically + PropertyChanges { + target: container + opacity: 1 + } + } + ] + transitions: [ + Transition { + from: "*" + to: "*" + NumberAnimation { + target: container + properties: "opacity" + duration: 400 + } + } + ] + } diff --cc examples/demos/flickr/content/Slider.qml index 0000000,0f9e8b2..c4e7436 mode 000000,100644..100644 --- a/examples/demos/flickr/content/Slider.qml +++ b/examples/demos/flickr/content/Slider.qml @@@ -1,0 -1,91 +1,91 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Item { + id: slider; width: 400; height: 16 + + // value is read/write. + property real value: 1 + onValueChanged: updatePos(); + property real maximum: 1 + property real minimum: 1 + property int xMax: width - handle.width - 4 + onXMaxChanged: updatePos(); + onMinimumChanged: updatePos(); + + function updatePos() { + if (maximum > minimum) { + var pos = 2 + (value - minimum) * slider.xMax / (maximum - minimum); + pos = Math.min(pos, width - handle.width - 2); + pos = Math.max(pos, 2); + handle.x = pos; + } else { + handle.x = 2; + } + } + + Rectangle { + anchors.fill: parent + border.color: "white"; border.width: 0; radius: 8 + gradient: Gradient { + GradientStop { position: 0.0; color: "#66343434" } + GradientStop { position: 1.0; color: "#66000000" } + } + } + + Rectangle { + id: handle; smooth: true + y: 2; width: 30; height: slider.height-4; radius: 6 + gradient: Gradient { + GradientStop { position: 0.0; color: "lightgray" } + GradientStop { position: 1.0; color: "gray" } + } + + MouseArea { + id: mouse + anchors.fill: parent; drag.target: parent + drag.axis: Drag.XAxis; drag.minimumX: 2; drag.maximumX: slider.xMax+2 + onPositionChanged: { value = (maximum - minimum) * (handle.x-2) / slider.xMax + minimum; } + } + } + } diff --cc examples/demos/flickr/content/TitleBar.qml index 0000000,3dab005..223939f mode 000000,100644..100644 --- a/examples/demos/flickr/content/TitleBar.qml +++ b/examples/demos/flickr/content/TitleBar.qml @@@ -1,0 -1,128 +1,128 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Item { + id: titleBar + property string untaggedString: "Uploads from everyone" + property string taggedString: "Recent uploads tagged " + + BorderImage { source: "images/titlebar.sci"; width: parent.width; height: parent.height + 14; y: -7 } + + Item { + id: container + width: (parent.width * 2) - 55 ; height: parent.height + + function accept() { + imageDetails.closed() + titleBar.state = "" + background.state = "" + rssModel.tags = editor.text + } + + Image { + id: quitButton + anchors.left: parent.left//; anchors.leftMargin: 0 + anchors.verticalCenter: parent.verticalCenter + source: "images/quit.png" + MouseArea { + anchors.fill: parent + onClicked: Qt.quit() + } + } + + Text { + id: categoryText + anchors { + left: quitButton.right; right: tagButton.left; leftMargin: 10; rightMargin: 10 + verticalCenter: parent.verticalCenter + } + elide: Text.ElideLeft + text: (rssModel.tags=="" ? untaggedString : taggedString + rssModel.tags) + font.bold: true; font.pixelSize: 15; color: "White"; style: Text.Raised; styleColor: "Black" + } + + Button { + id: tagButton; x: titleBar.width - 50; width: 45; height: 32; text: "..." + onClicked: if (titleBar.state == "Tags") container.accept(); else titleBar.state = "Tags" + anchors.verticalCenter: parent.verticalCenter + } + + Item { + id: lineEdit + y: 4; height: parent.height - 9 + anchors { left: tagButton.right; leftMargin: 5; right: parent.right; rightMargin: 5 } + + BorderImage { source: "images/lineedit.sci"; anchors.fill: parent } + + TextInput { + id: editor + anchors { + left: parent.left; right: parent.right; leftMargin: 10; rightMargin: 10 + verticalCenter: parent.verticalCenter + } + cursorVisible: true; font.bold: true + color: "#151515"; selectionColor: "Green" + } + + Keys.forwardTo: [ (returnKey), (editor)] + + Item { + id: returnKey + Keys.onReturnPressed: container.accept() + Keys.onEnterPressed: container.accept() + Keys.onEscapePressed: titleBar.state = "" + } + } + } + + states: State { + name: "Tags" + PropertyChanges { target: container; x: -tagButton.x + 5 } + PropertyChanges { target: tagButton; text: "OK" } + PropertyChanges { target: editor; focus: true } + } + + transitions: Transition { + NumberAnimation { properties: "x"; easing.type: Easing.InOutQuad } + } + } diff --cc examples/demos/flickr/content/ToolBar.qml index 0000000,e82be63..356993b mode 000000,100644..100644 --- a/examples/demos/flickr/content/ToolBar.qml +++ b/examples/demos/flickr/content/ToolBar.qml @@@ -1,0 -1,69 +1,69 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Item { + id: toolbar + + property alias button1Label: button1.text + property alias button2Label: button2.text + property alias button2Visible: button2.visible + + signal button1Clicked + signal button2Clicked + + BorderImage { source: "images/titlebar.sci"; width: parent.width; height: parent.height + 14; y: -7 } + + Row { + anchors.right: parent.right; anchors.rightMargin: 5; y: 3; height: 32; spacing: 30 + Button { + id: button1 + width: 140; height: 32 + onClicked: toolbar.button1Clicked() + } + + Button { + id: button2; width: 140; height: 32 + onClicked: toolbar.button2Clicked() + } + } + } diff --cc examples/demos/flickr/content/UnifiedDelegate.qml index 0000000,00a777b..0b068c0 mode 000000,100644..100644 --- a/examples/demos/flickr/content/UnifiedDelegate.qml +++ b/examples/demos/flickr/content/UnifiedDelegate.qml @@@ -1,0 -1,154 +1,154 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + import QtQuick.Particles 2.0 + + Package { + function photoClicked() { + imageDetails.photoTitle = title; + imageDetails.photoTags = tags; + imageDetails.photoWidth = photoWidth; + imageDetails.photoHeight = photoHeight; + imageDetails.photoType = photoType; + imageDetails.photoAuthor = photoAuthor; + imageDetails.photoDate = photoDate; + imageDetails.photoUrl = url; + imageDetails.rating = 0; + scaleMe.state = "Details"; + } + + Item { + id: gridwrapper; + width: GridView.view.cellWidth; height: GridView.view.cellHeight + Package.name: "grid" + } + Item { + id: streamwrapper; + width: 80; height: 80 + Package.name: "stream" + } + Item { + //anchors.centerIn: parent//Doesn't animate :( + width: 80; height: 80 + scale: 0.0 + Behavior on scale { NumberAnimation { easing.type: Easing.InOutQuad} } + id: scaleMe + + Item { + id: whiteRectContainer + width: 77; height: 77; anchors.centerIn: parent + Rectangle { + id: whiteRect; width: 77; height: 77; color: "#dddddd"; smooth: true + x:0; y:0 + Image { id: thumb; source: imagePath; x: 1; y: 1; smooth: true } + Image { source: "images/gloss.png" } + MouseArea { anchors.fill: parent; onClicked: photoClicked() } + } + } + + Connections { + target: toolBar + onButton2Clicked: if (scaleMe.state == 'Details' ) scaleMe.state = 'Show' + } + + state: 'inStream' + states: [ + State { + name: "Show"; when: thumb.status == Image.Ready + PropertyChanges { target: scaleMe; scale: 1; } + }, + State { + name: "Details" + PropertyChanges { target: scaleMe; scale: 1 } + ParentChange { target: whiteRect; x: 10; y: 20; parent: imageDetails.frontContainer } + PropertyChanges { target: background; state: "DetailedView" } + } + ] + transitions: [ + Transition { + from: "Show"; to: "Details" + ParentAnimation { + via: foreground + NumberAnimation { properties: "x,y"; duration: 500; easing.type: Easing.InOutQuad } + } + }, + Transition { + from: "Details"; to: "Show" + SequentialAnimation{ + ParentAnimation { + via: foreground + NumberAnimation { properties: "x,y"; duration: 500; easing.type: Easing.InOutQuad } + } + } + } + ] + Item{ + id: stateContainer + states: [ + State { + name: 'inStream' + when: screen.inGridView == false + ParentChange { + target: scaleMe; parent: streamwrapper + x: 0; y: 0; + } + }, + State { + name: 'inGrid' + when: screen.inGridView == true + ParentChange { + target: scaleMe; parent: gridwrapper + x: 0; y: 0; + } + } + ] + + transitions: [ + Transition { + ParentAnimation { + NumberAnimation { target: scaleMe; properties: 'x,y,width,height'; duration: 300 } + } + } + ] + } + } + } diff --cc examples/demos/flickr/flickr-90.qml index 0000000,ae06957..b95b1c9 mode 000000,100644..100644 --- a/examples/demos/flickr/flickr-90.qml +++ b/examples/demos/flickr/flickr-90.qml @@@ -1,0 -1,52 +1,52 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Item { + width: 480; height: 320 + + Loader { + y: 320; rotation: -90 + transformOrigin: Item.TopLeft + source: "flickr.qml" + } + } diff --cc examples/demos/flickr/flickr.qml index 0000000,74c41f1..98ca519 mode 000000,100644..100644 --- a/examples/demos/flickr/flickr.qml +++ b/examples/demos/flickr/flickr.qml @@@ -1,0 -1,158 +1,158 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + import QtQuick.Particles 2.0 + import "content" + + Item { + id: screen; width: 320; height: 480 + property bool inGridView : true + + Rectangle { + id: background + anchors.fill: parent; color: "#343434"; + + Image { source: "content/images/stripes.png"; fillMode: Image.Tile; anchors.fill: parent; opacity: 0.3 } + ParticleSystem { + id: bgParticles + anchors.fill: parent + ImageParticle { + groups: ["trail"] + source: "content/images/particle.png" + color: "#1A1A6F" + alpha: 0.1 + colorVariation: 0.01 + blueVariation: 0.8 + } + Emitter { + group: "drops" + width: parent.width + emitRate: 0.5 + lifeSpan: 20000 + startTime: 16000 + speed: PointDirection{ + y: {screen.height/18} + } + } + TrailEmitter { + follow: "drops" + group: "trail" + emitRatePerParticle: 18 + size: 32 + endSize: 0 + sizeVariation: 4 + lifeSpan: 1200 + anchors.fill: parent + emitWidth: 16 + emitHeight: 16 + emitShape: EllipseShape{} + } + } + + VisualDataModel{ + id: vdm + delegate: UnifiedDelegate{} + model: RssModel { id: rssModel } + } + + Item { + id: views + width: parent.width + anchors.top: titleBar.bottom; anchors.bottom: toolBar.top + + GridView { + id: photoGridView; model: vdm.parts.grid + cacheBuffer: 1000 + cellWidth: (parent.width-2)/4; cellHeight: cellWidth; width: parent.width; height: parent.height + } + + states: State { + name: "GridView"; when: state.inGridView == true + } + + transitions: Transition { + NumberAnimation { properties: "x"; duration: 500; easing.type: Easing.InOutQuad } + } + + ImageDetails { id: imageDetails; width: parent.width; anchors.left: views.right; height: parent.height } + + Item { id: foreground; anchors.fill: parent } + } + + TitleBar { id: titleBar; width: parent.width; height: 40; opacity: 0.9 } + + ToolBar { + id: toolBar + height: 40; anchors.bottom: parent.bottom; width: parent.width; opacity: 0.9 + button1Label: "Update"; button2Label: "View mode" + onButton1Clicked: rssModel.reload() + onButton2Clicked: if (screen.inGridView == true) screen.inGridView = false; else screen.inGridView = true + } + + Connections { + target: imageDetails + onClosed: { + if (background.state == "DetailedView") { + background.state = ''; + imageDetails.photoUrl = ""; + } + } + } + + states: State { + name: "DetailedView" + PropertyChanges { target: views; x: -parent.width } + PropertyChanges { target: toolBar; button1Label: "View..." } + PropertyChanges { + target: toolBar + onButton1Clicked: if (imageDetails.state=='') imageDetails.state='Back'; else imageDetails.state='' + } + PropertyChanges { target: toolBar; button2Label: "Back" } + PropertyChanges { target: toolBar; onButton2Clicked: imageDetails.closed() } + } + + transitions: Transition { + NumberAnimation { properties: "x"; duration: 500; easing.type: Easing.InOutQuad } + } + + } + } diff --cc examples/demos/minehunt/MinehuntCore/Explosion.qml index 0000000,0983b68..a1b4292 mode 000000,100644..100644 --- a/examples/demos/minehunt/MinehuntCore/Explosion.qml +++ b/examples/demos/minehunt/MinehuntCore/Explosion.qml @@@ -1,0 -1,69 +1,69 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + import QtQuick.Particles 2.0 + + Item { + property bool explode : false + ParticleSystem { + width: 40 + height: 40 + ImageParticle { + groups: ["star"] + source: "file:MinehuntCore/pics/star.png" // TODO: Use qrc path once QTBUG-21129 is fixed + } + Emitter { + id: particles + enabled: false + anchors.centerIn: parent + group: "star" + speed: AngleDirection { angleVariation: 360; magnitude: 150; magnitudeVariation: 50 } + emitRate: 200 + z: 100 + lifeSpan: 1000 + } + } + states: State { name: "exploding"; when: explode + StateChangeScript { script: particles.burst(200); } + } + + } diff --cc examples/demos/minehunt/MinehuntCore/Tile.qml index 0000000,14c1f51..1180b6f mode 000000,100644..100644 --- a/examples/demos/minehunt/MinehuntCore/Tile.qml +++ b/examples/demos/minehunt/MinehuntCore/Tile.qml @@@ -1,0 -1,128 +1,128 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Flipable { + id: flipable + property int angle: 0 + + width: 40; height: 40 + transform: Rotation { origin.x: 20; origin.y: 20; axis.x: 1; axis.z: 0; angle: flipable.angle } + + front: Image { + source: "pics/front.png"; width: 40; height: 40 + + Image { + anchors.centerIn: parent + source: "pics/flag.png"; opacity: modelData.hasFlag + + Behavior on opacity { NumberAnimation {} } + } + } + + back: Image { + source: "pics/back.png" + width: 40; height: 40 + + Text { + anchors.centerIn: parent + text: modelData.hint; color: "white"; font.bold: true + opacity: !modelData.hasMine && modelData.hint > 0 + } + + Image { + anchors.centerIn: parent + source: "pics/bomb.png"; opacity: modelData.hasMine + } + + Explosion { id: expl } + } + + states: State { + name: "back"; when: modelData.flipped + PropertyChanges { target: flipable; angle: 180 } + } + + property real pauseDur: 250 + transitions: Transition { + SequentialAnimation { + ScriptAction { + script: { + var ret = Math.abs(flipable.x - field.clickx) + + Math.abs(flipable.y - field.clicky); + if (modelData.hasMine && modelData.flipped) + pauseDur = ret * 3 + else + pauseDur = ret + } + } + PauseAnimation { + duration: pauseDur + } + RotationAnimation { easing.type: Easing.InOutQuad } + ScriptAction { script: if (modelData.hasMine && modelData.flipped) { expl.explode = true } } + } + } + + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.LeftButton | Qt.RightButton + onClicked: { + field.clickx = flipable.x + field.clicky = flipable.y + var row = Math.floor(index / 9) + var col = index - (Math.floor(index / 9) * 9) + if (mouse.button == undefined || mouse.button == Qt.RightButton) { + flag(row, col) + } else { + flip(row, col) + } + } + onPressAndHold: { + field.clickx = flipable.x + field.clicky = flipable.y + var row = Math.floor(index / 9) + var col = index - (Math.floor(index / 9) * 9) + flag(row, col) + } + } + } diff --cc examples/demos/minehunt/main.cpp index 0000000,47c0436..0aa11a1 mode 000000,100644..100644 --- a/examples/demos/minehunt/main.cpp +++ b/examples/demos/minehunt/main.cpp @@@ -1,0 -1,64 +1,64 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** + ** This file is part of the demonstration applications of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + #include + #include -#include -#include ++#include ++#include + + #include "minehunt.h" + + int main(int argc, char *argv[]) + { + QGuiApplication app(argc, argv); + QQuickView canvas; + + qmlRegisterType(); + MinehuntGame* game = new MinehuntGame(); + + canvas.setResizeMode(QQuickView::SizeRootObjectToView); + canvas.engine()->rootContext()->setContextObject(game); + canvas.setSource(QString("qrc:///minehunt.qml")); + QObject::connect(canvas.engine(), SIGNAL(quit()), &app, SLOT(quit())); + + canvas.show(); + return app.exec(); + } diff --cc examples/demos/minehunt/minehunt.cpp index 0000000,facbec3..cde3027 mode 000000,100644..100644 --- a/examples/demos/minehunt/minehunt.cpp +++ b/examples/demos/minehunt/minehunt.cpp @@@ -1,0 -1,221 +1,221 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** + ** This file is part of the demonstration applications of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + #include + #include + #include + + #include "minehunt.h" + -void tilesPropAppend(QDeclarativeListProperty* prop, TileData* value) ++void tilesPropAppend(QQmlListProperty* prop, TileData* value) + { + Q_UNUSED(prop); + Q_UNUSED(value); + return; //Append not supported + } + -int tilesPropCount(QDeclarativeListProperty* prop) ++int tilesPropCount(QQmlListProperty* prop) + { + return static_cast*>(prop->data)->count(); + } + -TileData* tilesPropAt(QDeclarativeListProperty* prop, int index) ++TileData* tilesPropAt(QQmlListProperty* prop, int index) + { + return static_cast*>(prop->data)->at(index); + } + -QDeclarativeListProperty MinehuntGame::tiles(){ - return QDeclarativeListProperty(this, &_tiles, &tilesPropAppend, ++QQmlListProperty MinehuntGame::tiles(){ ++ return QQmlListProperty(this, &_tiles, &tilesPropAppend, + &tilesPropCount, &tilesPropAt, 0); + } + + MinehuntGame::MinehuntGame() + : numCols(9), numRows(9), playing(true), won(false) + { + setObjectName("mainObject"); + srand(QTime(0,0,0).secsTo(QTime::currentTime())); + + //initialize array + for(int ii = 0; ii < numRows * numCols; ++ii) { + _tiles << new TileData; + } + reset(); + + } + + void MinehuntGame::setBoard() + { + foreach(TileData* t, _tiles){ + t->setHasMine(false); + t->setHint(-1); + } + //place mines + int mines = nMines; + remaining = numRows*numCols-mines; + while ( mines ) { + int col = int((double(rand()) / double(RAND_MAX)) * numCols); + int row = int((double(rand()) / double(RAND_MAX)) * numRows); + + TileData* t = tile( row, col ); + + if (t && !t->hasMine()) { + t->setHasMine( true ); + mines--; + } + } + + //set hints + for (int r = 0; r < numRows; r++) + for (int c = 0; c < numCols; c++) { + TileData* t = tile(r, c); + if (t && !t->hasMine()) { + int hint = getHint(r,c); + t->setHint(hint); + } + } + + setPlaying(true); + } + + void MinehuntGame::reset() + { + foreach(TileData* t, _tiles){ + t->unflip(); + t->setHasFlag(false); + } + nMines = 12; + nFlags = 0; + emit numMinesChanged(); + emit numFlagsChanged(); + setPlaying(false); + QTimer::singleShot(600,this, SLOT(setBoard())); + } + + int MinehuntGame::getHint(int row, int col) + { + int hint = 0; + for (int c = col-1; c <= col+1; c++) + for (int r = row-1; r <= row+1; r++) { + TileData* t = tile(r, c); + if (t && t->hasMine()) + hint++; + } + return hint; + } + + bool MinehuntGame::flip(int row, int col) + { + if(!playing) + return false; + + TileData *t = tile(row, col); + if (!t || t->hasFlag()) + return false; + + if(t->flipped()){ + int flags = 0; + for (int c = col-1; c <= col+1; c++) + for (int r = row-1; r <= row+1; r++) { + TileData *nearT = tile(r, c); + if(!nearT || nearT == t) + continue; + if(nearT->hasFlag()) + flags++; + } + if(!t->hint() || t->hint() != flags) + return false; + for (int c = col-1; c <= col+1; c++) + for (int r = row-1; r <= row+1; r++) { + TileData *nearT = tile(r, c); + if (nearT && !nearT->flipped() && !nearT->hasFlag()) { + flip( r, c ); + } + } + return true; + } + + t->flip(); + + if (t->hint() == 0) { + for (int c = col-1; c <= col+1; c++) + for (int r = row-1; r <= row+1; r++) { + TileData* t = tile(r, c); + if (t && !t->flipped()) { + flip( r, c ); + } + } + } + + if(t->hasMine()){ + for (int r = 0; r < numRows; r++)//Flip all other mines + for (int c = 0; c < numCols; c++) { + TileData* t = tile(r, c); + if (t && t->hasMine()) { + flip(r, c); + } + } + won = false; + hasWonChanged(); + setPlaying(false); + return true; + } + + remaining--; + if(!remaining){ + won = true; + hasWonChanged(); + setPlaying(false); + return true; + } + return true; + } + + bool MinehuntGame::flag(int row, int col) + { + TileData *t = tile(row, col); + if(!t || !playing || t->flipped()) + return false; + + t->setHasFlag(!t->hasFlag()); + nFlags += (t->hasFlag()?1:-1); + emit numFlagsChanged(); + return true; + } diff --cc examples/demos/minehunt/minehunt.h index 0000000,a0ae23f..34bab71 mode 000000,100644..100644 --- a/examples/demos/minehunt/minehunt.h +++ b/examples/demos/minehunt/minehunt.h @@@ -1,0 -1,129 +1,129 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** + ** This file is part of the demonstration applications of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + -#include ++#include + + class TileData : public QObject + { + Q_OBJECT + public: + TileData() : _hasFlag(false), _hasMine(false), _hint(-1), _flipped(false) {} + + Q_PROPERTY(bool hasFlag READ hasFlag WRITE setHasFlag NOTIFY hasFlagChanged) + bool hasFlag() const { return _hasFlag; } + + Q_PROPERTY(bool hasMine READ hasMine NOTIFY hasMineChanged) + bool hasMine() const { return _hasMine; } + + Q_PROPERTY(int hint READ hint NOTIFY hintChanged) + int hint() const { return _hint; } + + Q_PROPERTY(bool flipped READ flipped NOTIFY flippedChanged()) + bool flipped() const { return _flipped; } + + void setHasFlag(bool flag) {if(flag==_hasFlag) return; _hasFlag = flag; emit hasFlagChanged();} + void setHasMine(bool mine) {if(mine==_hasMine) return; _hasMine = mine; emit hasMineChanged();} + void setHint(int hint) { if(hint == _hint) return; _hint = hint; emit hintChanged(); } + void flip() { if (_flipped) return; _flipped = true; emit flippedChanged(); } + void unflip() { if(!_flipped) return; _flipped = false; emit flippedChanged(); } + + signals: + void flippedChanged(); + void hasFlagChanged(); + void hintChanged(); + void hasMineChanged(); + + private: + bool _hasFlag; + bool _hasMine; + int _hint; + bool _flipped; + }; + + class MinehuntGame : public QObject + { + Q_OBJECT + public: + MinehuntGame(); + - Q_PROPERTY(QDeclarativeListProperty tiles READ tiles CONSTANT) - QDeclarativeListProperty tiles(); ++ Q_PROPERTY(QQmlListProperty tiles READ tiles CONSTANT) ++ QQmlListProperty tiles(); + + Q_PROPERTY(bool isPlaying READ isPlaying NOTIFY isPlayingChanged) + bool isPlaying() {return playing;} + + Q_PROPERTY(bool hasWon READ hasWon NOTIFY hasWonChanged) + bool hasWon() {return won;} + + Q_PROPERTY(int numMines READ numMines NOTIFY numMinesChanged) + int numMines() const{return nMines;} + + Q_PROPERTY(int numFlags READ numFlags NOTIFY numFlagsChanged) + int numFlags() const{return nFlags;} + + public slots: + Q_INVOKABLE bool flip(int row, int col); + Q_INVOKABLE bool flag(int row, int col); + void setBoard(); + void reset(); + + signals: + void isPlayingChanged(); + void hasWonChanged(); + void numMinesChanged(); + void numFlagsChanged(); + + private: + bool onBoard( int r, int c ) const { return r >= 0 && r < numRows && c >= 0 && c < numCols; } + TileData *tile( int row, int col ) { return onBoard(row, col) ? _tiles[col+numRows*row] : 0; } + int getHint(int row, int col); + void setPlaying(bool b){if(b==playing) return; playing=b; emit isPlayingChanged();} + + QList _tiles; + int numCols; + int numRows; + bool playing; + bool won; + int remaining; + int nMines; + int nFlags; + }; diff --cc examples/demos/minehunt/minehunt.pro index 0000000,81b6b80..78e874d mode 000000,100644..100644 --- a/examples/demos/minehunt/minehunt.pro +++ b/examples/demos/minehunt/minehunt.pro @@@ -1,0 -1,5 +1,5 @@@ -QT += declarative quick ++QT += qml quick + + HEADERS += minehunt.h + SOURCES += main.cpp minehunt.cpp + RESOURCES = minehunt.qrc diff --cc examples/demos/minehunt/minehunt.qml index 0000000,7c4948a..42dc408 mode 000000,100644..100644 --- a/examples/demos/minehunt/minehunt.qml +++ b/examples/demos/minehunt/minehunt.qml @@@ -1,0 -1,112 +1,112 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + import "MinehuntCore" 2.0 + + Item { + id: field + property int clickx: 0 + property int clicky: 0 + + width: 450; height: 450 + + Image { source: "MinehuntCore/pics/background.png"; anchors.fill: parent; fillMode: Image.Tile } + + Grid { + anchors.horizontalCenter: parent.horizontalCenter + columns: 9; spacing: 1 + + Repeater { + id: repeater + model: tiles + delegate: Tile {} + } + } + + Row { + id: gamedata + x: 20; spacing: 20 + anchors.bottom: field.bottom; anchors.bottomMargin: 15 + + Image { + source: "MinehuntCore/pics/quit.png" + scale: quitMouse.pressed ? 0.8 : 1.0 + smooth: quitMouse.pressed + y: 10 + MouseArea { + id: quitMouse + anchors.fill: parent + anchors.margins: -20 + onClicked: Qt.quit() + } + } + Column { + spacing: 2 + Image { source: "MinehuntCore/pics/bomb-color.png" } + Text { anchors.horizontalCenter: parent.horizontalCenter; color: "white"; text: numMines } + } + + Column { + spacing: 2 + Image { source: "MinehuntCore/pics/flag-color.png" } + Text { anchors.horizontalCenter: parent.horizontalCenter; color: "white"; text: numFlags } + } + } + + Image { + anchors.bottom: field.bottom; anchors.bottomMargin: 15 + anchors.right: field.right; anchors.rightMargin: 20 + source: isPlaying ? 'MinehuntCore/pics/face-smile.png' : + hasWon ? 'MinehuntCore/pics/face-smile-big.png': 'MinehuntCore/pics/face-sad.png' + + MouseArea { anchors.fill: parent; onPressed: reset() } + } + Text { + anchors.centerIn: parent; width: parent.width - 20 + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.WordWrap + text: "Minehunt demo has to be compiled to run.\n\nPlease see README." + color: "white"; font.bold: true; font.pixelSize: 14 + visible: tiles == undefined + } + + } diff --cc examples/demos/photoviewer/PhotoViewerCore/AlbumDelegate.qml index 0000000,f183c4b..164f47f mode 000000,100644..100644 --- a/examples/demos/photoviewer/PhotoViewerCore/AlbumDelegate.qml +++ b/examples/demos/photoviewer/PhotoViewerCore/AlbumDelegate.qml @@@ -1,0 -1,147 +1,147 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + import QtQuick.XmlListModel 2.0 + + Component { + id: albumDelegate + Package { + + Item { + Package.name: 'browser' + GridView { + id: photosGridView; model: visualModel.parts.grid; width: mainWindow.width; height: mainWindow.height - 21 + x: 0; y: 21; cellWidth: 160; cellHeight: 153; interactive: false + onCurrentIndexChanged: photosListView.positionViewAtIndex(currentIndex, ListView.Contain) + } + } + + Item { + Package.name: 'fullscreen' + ListView { + id: photosListView; model: visualModel.parts.list; orientation: Qt.Horizontal + width: mainWindow.width; height: mainWindow.height; interactive: false + onCurrentIndexChanged: photosGridView.positionViewAtIndex(currentIndex, GridView.Contain) + highlightRangeMode: ListView.StrictlyEnforceRange; snapMode: ListView.SnapOneItem + } + } + + Item { + Package.name: 'album' + id: albumWrapper; width: 210; height: 220 + + VisualDataModel { + id: visualModel; delegate: PhotoDelegate { } + model: RssModel { id: rssModel; tags: tag } + } + + BusyIndicator { + id: busyIndicator + anchors { centerIn: parent; verticalCenterOffset: -20 } + on: rssModel.status != XmlListModel.Ready + } + + PathView { + id: photosPathView; model: visualModel.parts.stack; pathItemCount: 5 + visible: !busyIndicator.visible + anchors.centerIn: parent; anchors.verticalCenterOffset: -30 + path: Path { + PathAttribute { name: 'z'; value: 9999.0 } + PathLine { x: 1; y: 1 } + PathAttribute { name: 'z'; value: 0.0 } + } + } + + MouseArea { + anchors.fill: parent + onClicked: mainWindow.editMode ? photosModel.remove(index) : albumWrapper.state = 'inGrid' + } + + Tag { + anchors { horizontalCenter: parent.horizontalCenter; bottom: parent.bottom; bottomMargin: 10 } + frontLabel: tag; backLabel: qsTr("Remove"); flipped: mainWindow.editMode + onTagChanged: rssModel.tags = tag + onBackClicked: if (mainWindow.editMode) photosModel.remove(index); + } + + states: [ + State { + name: 'inGrid' + PropertyChanges { target: photosGridView; interactive: true } + PropertyChanges { target: albumsShade; opacity: 1 } + PropertyChanges { target: backButton; onClicked: albumWrapper.state = ''; y: 6 } + }, + State { + name: 'fullscreen'; extend: 'inGrid' + PropertyChanges { target: photosGridView; interactive: false } + PropertyChanges { target: photosListView; interactive: true } + PropertyChanges { target: photosShade; opacity: 1 } + PropertyChanges { target: backButton; y: -backButton.height - 8 } + } + ] + + GridView.onAdd: NumberAnimation { + target: albumWrapper; properties: "scale"; from: 0.0; to: 1.0; easing.type: Easing.OutQuad + } + GridView.onRemove: SequentialAnimation { + PropertyAction { target: albumWrapper; property: "GridView.delayRemove"; value: true } + NumberAnimation { target: albumWrapper; property: "scale"; from: 1.0; to: 0.0; easing.type: Easing.OutQuad } + PropertyAction { target: albumWrapper; property: "GridView.delayRemove"; value: false } + } + + transitions: [ + Transition { + from: '*'; to: 'inGrid' + SequentialAnimation { + NumberAnimation { properties: 'opacity'; duration: 250 } + PauseAnimation { duration: 350 } + NumberAnimation { target: backButton; properties: "y"; duration: 200; easing.type: Easing.OutQuad } + } + }, + Transition { + from: 'inGrid'; to: '*' + NumberAnimation { properties: "y,opacity"; easing.type: Easing.OutQuad; duration: 300 } + } + ] + } + } + } diff --cc examples/demos/photoviewer/PhotoViewerCore/BusyIndicator.qml index 0000000,2b1a75f..867c268 mode 000000,100644..100644 --- a/examples/demos/photoviewer/PhotoViewerCore/BusyIndicator.qml +++ b/examples/demos/photoviewer/PhotoViewerCore/BusyIndicator.qml @@@ -1,0 -1,50 +1,50 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Image { + id: container + property bool on: false + + source: "images/busy.png"; visible: container.on + NumberAnimation on rotation { running: container.on; from: 0; to: 360; loops: Animation.Infinite; duration: 1200 } + } diff --cc examples/demos/photoviewer/PhotoViewerCore/Button.qml index 0000000,fcce969..8f4177c mode 000000,100644..100644 --- a/examples/demos/photoviewer/PhotoViewerCore/Button.qml +++ b/examples/demos/photoviewer/PhotoViewerCore/Button.qml @@@ -1,0 -1,72 +1,72 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Item { + id: container + + property alias label: labelText.text + property color tint: "transparent" + signal clicked + + width: labelText.width + 70 ; height: labelText.height + 18 + + BorderImage { + anchors { fill: container; leftMargin: -6; topMargin: -6; rightMargin: -8; bottomMargin: -8 } + source: 'images/box-shadow.png'; smooth: true + border.left: 10; border.top: 10; border.right: 10; border.bottom: 10 + } + + Image { anchors.fill: parent; source: "images/cardboard.png"; smooth: true } + + Rectangle { + anchors.fill: container; color: container.tint; visible: container.tint != "" + opacity: 0.25; smooth: true + } + + Text { id: labelText; font.pixelSize: 15; anchors.centerIn: parent; smooth: true } + + MouseArea { + anchors { fill: parent; leftMargin: -20; topMargin: -20; rightMargin: -20; bottomMargin: -20 } + onClicked: container.clicked() + } + } diff --cc examples/demos/photoviewer/PhotoViewerCore/EditableButton.qml index 0000000,5d84593..435ad26 mode 000000,100644..100644 --- a/examples/demos/photoviewer/PhotoViewerCore/EditableButton.qml +++ b/examples/demos/photoviewer/PhotoViewerCore/EditableButton.qml @@@ -1,0 -1,86 +1,86 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Item { + id: container + + property string label + signal clicked + signal labelChanged(string label) + + width: textInput.width + 70 ; height: textInput.height + 18 + + BorderImage { + anchors { fill: container; leftMargin: -6; topMargin: -6; rightMargin: -8; bottomMargin: -8 } + source: 'images/box-shadow.png'; smooth: true + border.left: 10; border.top: 10; border.right: 10; border.bottom: 10 + } + + Image { anchors.fill: parent; source: "images/cardboard.png"; smooth: true } + + TextInput { + id: textInput; text: label; font.pixelSize: 15; anchors.centerIn: parent; smooth: true + Keys.onReturnPressed: { + container.labelChanged(textInput.text) + container.focus = true + } + Keys.onEnterPressed: { + container.labelChanged(textInput.text) + container.focus = true + } + Keys.onEscapePressed: { + textInput.text = container.label + container.focus = true + } + } + + Rectangle { + anchors.fill: container; border.color: "steelblue"; border.width: 4 + color: "transparent"; visible: textInput.focus; smooth: true + } + + MouseArea { + anchors { fill: parent; leftMargin: -20; topMargin: -20; rightMargin: -20; bottomMargin: -20 } + onClicked: { textInput.forceActiveFocus(); textInput.openSoftwareInputPanel(); } + } + } diff --cc examples/demos/photoviewer/PhotoViewerCore/PhotoDelegate.qml index 0000000,b972c93..5d4e5ae mode 000000,100644..100644 --- a/examples/demos/photoviewer/PhotoViewerCore/PhotoDelegate.qml +++ b/examples/demos/photoviewer/PhotoViewerCore/PhotoDelegate.qml @@@ -1,0 -1,188 +1,188 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + import "script/script.js" as Script + + Package { + Item { id: stackItem; Package.name: 'stack'; width: 160; height: 153; z: stackItem.PathView.z } + Item { id: listItem; Package.name: 'list'; width: mainWindow.width + 40; height: 153 } + Item { id: gridItem; Package.name: 'grid'; width: 160; height: 153 } + + Item { + width: 160; height: 153 + + Item { + id: photoWrapper + + property double randomAngle: Math.random() * (2 * 6 + 1) - 6 + property double randomAngle2: Math.random() * (2 * 6 + 1) - 6 + + x: 0; y: 0; width: 140; height: 133 + z: stackItem.PathView.z; rotation: photoWrapper.randomAngle + + BorderImage { + anchors { + fill: originalImage.status == Image.Ready ? border : placeHolder + leftMargin: -6; topMargin: -6; rightMargin: -8; bottomMargin: -8 + } + source: 'images/box-shadow.png'; smooth: true + border.left: 10; border.top: 10; border.right: 10; border.bottom: 10 + } + Rectangle { + id: placeHolder + + property int w: Script.getWidth(content) + property int h: Script.getHeight(content) + property double s: Script.calculateScale(w, h, photoWrapper.width) + + color: 'white'; anchors.centerIn: parent; smooth: true + width: w * s; height: h * s; visible: originalImage.status != Image.Ready + Rectangle { + color: "#878787"; smooth: true + anchors { fill: parent; topMargin: 3; bottomMargin: 3; leftMargin: 3; rightMargin: 3 } + } + } + Rectangle { + id: border; color: 'white'; anchors.centerIn: parent; smooth: true + width: originalImage.paintedWidth + 6; height: originalImage.paintedHeight + 6 + visible: !placeHolder.visible + } + BusyIndicator { anchors.centerIn: parent; on: originalImage.status != Image.Ready } + Image { + id: originalImage; smooth: true; source: "http://" + Script.getImagePath(content); cache: false + fillMode: Image.PreserveAspectFit; width: photoWrapper.width; height: photoWrapper.height + } + Image { + id: hqImage; smooth: true; source: ""; visible: false; cache: false + fillMode: Image.PreserveAspectFit; width: photoWrapper.width; height: photoWrapper.height + } + Binding { + target: mainWindow; property: "downloadProgress"; value: hqImage.progress + when: listItem.ListView.isCurrentItem + } + Binding { + target: mainWindow; property: "imageLoading" + value: (hqImage.status == Image.Loading) ? 1 : 0; when: listItem.ListView.isCurrentItem + } + MouseArea { + width: originalImage.paintedWidth; height: originalImage.paintedHeight; anchors.centerIn: originalImage + onClicked: { + if (albumWrapper.state == 'inGrid') { + gridItem.GridView.view.currentIndex = index; + albumWrapper.state = 'fullscreen' + } else { + gridItem.GridView.view.currentIndex = index; + albumWrapper.state = 'inGrid' + } + } + } + + states: [ + State { + name: 'stacked'; when: albumWrapper.state == '' + ParentChange { target: photoWrapper; parent: stackItem; x: 10; y: 10 } + PropertyChanges { target: photoWrapper; opacity: stackItem.PathView.onPath ? 1.0 : 0.0 } + }, + State { + name: 'inGrid'; when: albumWrapper.state == 'inGrid' + ParentChange { target: photoWrapper; parent: gridItem; x: 10; y: 10; rotation: photoWrapper.randomAngle2 } + }, + State { + name: 'fullscreen'; when: albumWrapper.state == 'fullscreen' + ParentChange { + target: photoWrapper; parent: listItem; x: 0; y: 0; rotation: 0 + width: mainWindow.width; height: mainWindow.height + } + PropertyChanges { target: border; opacity: 0 } + PropertyChanges { target: hqImage; source: listItem.ListView.isCurrentItem ? hq : ""; visible: true } + } + ] + + transitions: [ + Transition { + from: 'stacked'; to: 'inGrid' + SequentialAnimation { + PauseAnimation { duration: 10 * index } + ParentAnimation { + target: photoWrapper; via: foreground + NumberAnimation { + target: photoWrapper; properties: 'x,y,rotation,opacity'; duration: 600; easing.type: 'OutQuart' + } + } + } + }, + Transition { + from: 'inGrid'; to: 'stacked' + ParentAnimation { + target: photoWrapper; via: foreground + NumberAnimation { properties: 'x,y,rotation,opacity'; duration: 600; easing.type: 'OutQuart' } + } + }, + Transition { + from: 'inGrid'; to: 'fullscreen' + SequentialAnimation { + PauseAnimation { duration: gridItem.GridView.isCurrentItem ? 0 : 600 } + ParentAnimation { + target: photoWrapper; via: foreground + NumberAnimation { + targets: [ photoWrapper, border ] + properties: 'x,y,width,height,opacity,rotation' + duration: gridItem.GridView.isCurrentItem ? 600 : 1; easing.type: 'OutQuart' + } + } + } + }, + Transition { + from: 'fullscreen'; to: 'inGrid' + ParentAnimation { + target: photoWrapper; via: foreground + NumberAnimation { + targets: [ photoWrapper, border ] + properties: 'x,y,width,height,rotation,opacity' + duration: gridItem.GridView.isCurrentItem ? 600 : 1; easing.type: 'OutQuart' + } + } + } + ] + } + } + } diff --cc examples/demos/photoviewer/PhotoViewerCore/ProgressBar.qml index 0000000,43c936e..58beef5 mode 000000,100644..100644 --- a/examples/demos/photoviewer/PhotoViewerCore/ProgressBar.qml +++ b/examples/demos/photoviewer/PhotoViewerCore/ProgressBar.qml @@@ -1,0 -1,57 +1,57 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Item { + id: container + + property real progress: 0 + + Behavior on opacity { NumberAnimation { duration: 600 } } + + Rectangle { anchors.fill: parent; color: "black"; opacity: 0.5 } + + Rectangle { + id: fill; color: "white"; height: container.height + width: container.width * container.progress + } + } diff --cc examples/demos/photoviewer/PhotoViewerCore/RssModel.qml index 0000000,ab81892..1598977 mode 000000,100644..100644 --- a/examples/demos/photoviewer/PhotoViewerCore/RssModel.qml +++ b/examples/demos/photoviewer/PhotoViewerCore/RssModel.qml @@@ -1,0 -1,57 +1,57 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + import QtQuick.XmlListModel 2.0 + + XmlListModel { + property string tags : "" + + function encodeTags(x) { return encodeURIComponent(x.replace(' ',',')); } + + source: "http://api.flickr.com/services/feeds/photos_public.gne?"+(tags ? "tags="+encodeTags(tags)+"&" : "") + query: "/feed/entry" + namespaceDeclarations: "declare default element namespace 'http://www.w3.org/2005/Atom';" + + XmlRole { name: "title"; query: "title/string()" } + XmlRole { name: "content"; query: "content/string()" } + XmlRole { name: "hq"; query: "link[@rel='enclosure']/@href/string()" } + } diff --cc examples/demos/photoviewer/PhotoViewerCore/Tag.qml index 0000000,2b546a3..ed4a248 mode 000000,100644..100644 --- a/examples/demos/photoviewer/PhotoViewerCore/Tag.qml +++ b/examples/demos/photoviewer/PhotoViewerCore/Tag.qml @@@ -1,0 -1,91 +1,91 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Flipable { + id: flipable + + property alias frontLabel: frontButton.label + property alias backLabel: backButton.label + + property int angle: 0 + property int randomAngle: Math.random() * (2 * 6 + 1) - 6 + property bool flipped: false + + signal frontClicked + signal backClicked + signal tagChanged(string tag) + + front: EditableButton { + id: frontButton; rotation: flipable.randomAngle + anchors { centerIn: parent; verticalCenterOffset: -20 } + onClicked: flipable.frontClicked() + onLabelChanged: flipable.tagChanged(label) + } + + back: Button { + id: backButton; tint: "red"; rotation: flipable.randomAngle + anchors { centerIn: parent; verticalCenterOffset: -20 } + onClicked: flipable.backClicked() + } + + transform: Rotation { + origin.x: flipable.width / 2; origin.y: flipable.height / 2 + axis.x: 0; axis.y: 1; axis.z: 0 + angle: flipable.angle + } + + states: State { + name: "back"; when: flipable.flipped + PropertyChanges { target: flipable; angle: 180 } + } + + transitions: Transition { + ParallelAnimation { + NumberAnimation { properties: "angle"; duration: 400 } + SequentialAnimation { + NumberAnimation { target: flipable; property: "scale"; to: 0.8; duration: 200 } + NumberAnimation { target: flipable; property: "scale"; to: 1.0; duration: 200 } + } + } + } + } diff --cc examples/demos/photoviewer/photoviewer.qml index 0000000,9184388..208720b mode 000000,100644..100644 --- a/examples/demos/photoviewer/photoviewer.qml +++ b/examples/demos/photoviewer/photoviewer.qml @@@ -1,0 -1,110 +1,110 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + import "PhotoViewerCore" + + Rectangle { + id: mainWindow + + property real downloadProgress: 0 + property bool imageLoading: false + property bool editMode: false + + width: 800; height: 480; color: "#d5d6d8" + + ListModel { + id: photosModel + ListElement { tag: "Flowers" } + ListElement { tag: "Wildlife" } + ListElement { tag: "Prague" } + } + + VisualDataModel { id: albumVisualModel; model: photosModel; delegate: AlbumDelegate {} } + + GridView { + id: albumView; width: parent.width; height: parent.height; cellWidth: 210; cellHeight: 220 + model: albumVisualModel.parts.album; visible: albumsShade.opacity != 1.0 + } + + Column { + spacing: 20; anchors { bottom: parent.bottom; right: parent.right; rightMargin: 20; bottomMargin: 20 } + Button { + id: newButton; label: qsTr("Add"); rotation: 3 + anchors.horizontalCenter: parent.horizontalCenter + onClicked: { + mainWindow.editMode = false + photosModel.append( { tag: "" } ) + albumView.positionViewAtIndex(albumView.count - 1, GridView.Contain) + } + } + Button { + id: deleteButton; label: qsTr("Edit"); rotation: -2; + onClicked: mainWindow.editMode = !mainWindow.editMode + anchors.horizontalCenter: parent.horizontalCenter + } + Button { + id: quitButton; label: qsTr("Quit"); rotation: -2; + onClicked: Qt.quit() + anchors.horizontalCenter: parent.horizontalCenter + } + } + + Rectangle { + id: albumsShade; color: mainWindow.color + width: parent.width; height: parent.height; opacity: 0.0 + } + + ListView { anchors.fill: parent; model: albumVisualModel.parts.browser; interactive: false } + + Button { id: backButton; label: qsTr("Back"); rotation: 3; x: parent.width - backButton.width - 6; y: -backButton.height - 8 } + + Rectangle { id: photosShade; color: 'black'; width: parent.width; height: parent.height; opacity: 0; visible: opacity != 0.0 } + + ListView { anchors.fill: parent; model: albumVisualModel.parts.fullscreen; interactive: false } + + Item { id: foreground; anchors.fill: parent } + + ProgressBar { + progress: mainWindow.downloadProgress; width: parent.width; height: 4 + anchors.bottom: parent.bottom; opacity: mainWindow.imageLoading; visible: opacity != 0.0 + } + } diff --cc examples/demos/plasmapatrol/content/BlasterHardpoint.qml index 0000000,4ac30d0..10c50d4 mode 000000,100644..100644 --- a/examples/demos/plasmapatrol/content/BlasterHardpoint.qml +++ b/examples/demos/plasmapatrol/content/BlasterHardpoint.qml @@@ -1,0 -1,133 +1,133 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + import QtQuick 2.0 + import QtQuick.Particles 2.0 + + Item { + id: container + property variant target: {"y": -90, "x":12} + property Item targetObj: container + property Item hardpoint: container + property ParticleSystem system + property int blasts: 16 + property int bonusBlasts: 12 + property bool show: true + + width: 24 + height: 24 + Emitter { + id: visualization + group: "blaster" + system: container.system + enabled: show + anchors.fill: parent + shape: EllipseShape {} + speed: TargetDirection { targetX: width/2; targetY: width/2; magnitude: -1; proportionalMagnitude: true} + lifeSpan: 1000 + emitRate: 64 + + size: 24 + sizeVariation: 24 + endSize: 0 + } + + property int blastsLeft: 0 + function fireAt(targetArg, container) { + target = container.mapFromItem(targetArg, targetArg.width/2, targetArg.height/2); + targetObj = targetArg; + hardpoint = container; + blastsLeft = blasts; + rofTimer.repeat = true; + rofTimer.start(); + } + Timer { + id: rofTimer + interval: 30;//Has to be greater than 1 frame or they stack up + running: false + repeat: false + onTriggered: { + if (targetObj.hp <= 0) + return; + //TODO: calculate hit and damage at target, which must be a Ship + var hit; + if (blastsLeft >= bonusBlasts) + hit = Math.random() > targetObj.dodge; + else + hit = false; //purely aesthetic shots, because the damage isn't that fine grained + if (hit == true) { + switch (targetObj.shipType) { + case 1: hardpoint.damageDealt += 4; break; + case 2: hardpoint.damageDealt += 5; break; + case 3: hardpoint.damageDealt += 1; break; + default: hardpoint.damageDealt += 100; + } + } + blastVector.targetX = target.x; + blastVector.targetY = target.y; + if (!hit) {//TODO: Actual targetVariation + blastVector.targetX += (128 * Math.random() - 64); + blastVector.targetY += (128 * Math.random() - 64); + } + emitter.burst(1); + blastsLeft--; + if (!blastsLeft) + rofTimer.repeat = false; + } + } + Emitter { + id: emitter + group: "blaster" + enabled: false + system: container.system + anchors.centerIn: parent + + lifeSpan: 1000 + emitRate: 16 + maximumEmitted: blasts + size: 24 + endSize:16 + sizeVariation: 8 + speed: TargetDirection { + id: blastVector + targetX: target.x; targetY: target.y; magnitude: 1.1; proportionalMagnitude: true + } + } + } diff --cc examples/demos/plasmapatrol/content/Button.qml index 0000000,405b993..992be29 mode 000000,100644..100644 --- a/examples/demos/plasmapatrol/content/Button.qml +++ b/examples/demos/plasmapatrol/content/Button.qml @@@ -1,0 -1,66 +1,66 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + import QtQuick 2.0 + + //TODO: Add particles to this component too + Rectangle { + id: container + property alias text: txt.text + signal clicked + //color: "lightsteelblue" + gradient: Gradient { + GradientStop { position: 0.0; color: "lightsteelblue" } + GradientStop { position: 1.0; color: "steelblue" } + } + height: 64 + radius: 16 + width: 128 + Text { + id: txt + anchors.centerIn: parent + font.pixelSize: 24 + color: "white" + } + MouseArea { + anchors.fill: parent + onClicked: container.clicked() + } + } diff --cc examples/demos/plasmapatrol/content/CannonHardpoint.qml index 0000000,c4aa412..48eb9d1 mode 000000,100644..100644 --- a/examples/demos/plasmapatrol/content/CannonHardpoint.qml +++ b/examples/demos/plasmapatrol/content/CannonHardpoint.qml @@@ -1,0 -1,97 +1,97 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + import QtQuick 2.0 + import QtQuick.Particles 2.0 + + Item { + id: container + property variant target: {"y": -90, "x":12} + property ParticleSystem system + property bool show: true + + width: 24 + height: 24 + Emitter { + id: visualization + group: "cannon" + enabled: container.show + system: container.system + anchors.centerIn: parent + lifeSpan: 2000 + emitRate: 1 + + size: 4 + endSize: 0 + } + + function fireAt(targetArg, hardpoint) { + target = container.mapFromItem(targetArg, targetArg.width/2, targetArg.height/2); + if (container.hp <= 0 || targetArg.hp <= 0) + return; + //TODO: calculate hit and damage at target, which must be a Ship + var hit = Math.random() > targetArg.dodge + if (hit) { + switch (targetArg.shipType) { + case 1: hardpoint.damageDealt += 8; break; + case 2: hardpoint.damageDealt += 10; break; + case 3: hardpoint.damageDealt += 16; break; + default: hardpoint.damageDealt += 1000; + } + } + emitter.burst(1); + } + Emitter { + id: emitter + group: "cannon" + enabled: false + system: container.system + anchors.centerIn: parent + + lifeSpan: 1000 + emitRate: 1 + size: 8 + endSize: 4 + speed: TargetDirection { + id: blastVector + targetX: target.x; targetY: target.y; magnitude: 1.1; proportionalMagnitude: true + } + } + } diff --cc examples/demos/plasmapatrol/content/ChoiceBox.qml index 0000000,a678bc9..6e21101 mode 000000,100644..100644 --- a/examples/demos/plasmapatrol/content/ChoiceBox.qml +++ b/examples/demos/plasmapatrol/content/ChoiceBox.qml @@@ -1,0 -1,105 +1,105 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + import QtQuick 2.0 + import QtQuick.Particles 2.0 + + Item { + id: container + width: 360 + height: 160 + property ParticleSystem system + Ship { + id: nully + system: system + } + property Item target: nully + /* + Component.onCompleted: { + container.target.shipType = 1 + container.target.gunType = 1 + } + */ + Row { + anchors.horizontalCenter: parent.horizontalCenter + height: parent.height + spacing: 8 + Button { + width: 80 + height: 80 + anchors.verticalCenter: parent.verticalCenter + text: "Cycle\nShip" + onClicked: { + var nextVal = container.target.shipType; + if(nextVal == 3) + nextVal = 1; + else + nextVal++; + container.target.shipType = nextVal; + } + } + Item { + width: 128 + height: 128 + anchors.verticalCenter: parent.verticalCenter + Ship { + hp: 20 + anchors.centerIn: parent + shipType: container.target.shipType + gunType: container.target.gunType + system: container.system + } + } + Button { + width: 80 + height: 80 + anchors.verticalCenter: parent.verticalCenter + text: "Cycle\nGun" + onClicked: { + var nextVal = container.target.gunType; + if(nextVal == 3) + nextVal = 1; + else + nextVal++; + container.target.gunType = nextVal; + } + } + } + } diff --cc examples/demos/plasmapatrol/content/Cruiser.qml index 0000000,c689879..c469eb4 mode 000000,100644..100644 --- a/examples/demos/plasmapatrol/content/Cruiser.qml +++ b/examples/demos/plasmapatrol/content/Cruiser.qml @@@ -1,0 -1,146 +1,146 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + import QtQuick 2.0 + import QtQuick.Particles 2.0 + + Item { + id: container + property int maxHP: 100 + property int hp: maxHP + property real initialDodge: 0.01 + property real dodge: initialDodge + onHpChanged: if(hp <= 0) target = container; + property ParticleSystem system//TODO: Ship abstraction + property Item target: container + property string shipParticle: "default"//Per team colors? + property int gunType: 0 + width: 128 + height: 128 + Emitter { + //TODO: Cooler would be an 'orbiting' affector + //TODO: On the subject, opacity and size should be grouped type 'overLife' if we can cram that in the particles + system: container.system + group: container.shipParticle + anchors.centerIn: parent + width: 64 + height: 64 + shape: EllipseShape {} + + emitRate: hp > 0 ? hp * 1 + 20 : 0 + lifeSpan: 2400 + maximumEmitted: (maxHP * 1 + 20)*2.4 + + size: 48 + sizeVariation: 16 + endSize: 16 + + speed: AngleDirection {angleVariation:360; magnitudeVariation: 32} + } + Emitter { + system: container.system + group: "cruiserArmor" + anchors.fill: parent + shape: EllipseShape { fill: false } + enabled: hp>0 + + emitRate: 16 + lifeSpan: 2000 + + size: 48 + sizeVariation: 24 + + SpriteGoal { + id: destructor + system: container.system + enabled: container.hp <=0 + anchors.fill: parent + groups: ["cruiserArmor"] + goalState: "death" + // jump: true + once: true + } + } + + Timer { + id: fireControl + property int next: Math.floor(Math.random() * 3) + 1 + interval: 800 + running: root.readySetGo + repeat: true + onTriggered: { + if (next == 1) { + gun1.fireAt(container.target); + next = Math.floor(Math.random() * 3) + 1; + } else if (next == 2) { + gun2.fireAt(container.target); + next = Math.floor(Math.random() * 3) + 1; + } else if (next == 3) { + gun3.fireAt(container.target); + next = Math.floor(Math.random() * 3) + 1; + } + } + } + + Hardpoint {//TODO: Hardpoint abstraction + x: 112 - 12 - 8*2 + y: 128 - 12 - 12*2 + id: gun1 + system: container.system + show: hp > 0 + hardpointType: gunType + } + Hardpoint { + x: 64 - 12 + y: 0 - 12 + 12*2 + id: gun2 + system: container.system + show: hp > 0 + hardpointType: gunType + } + Hardpoint { + x: 16 - 12 + 8*2 + y: 128 - 12 - 12*2 + id: gun3 + system: container.system + show: hp > 0 + hardpointType: gunType + } + } diff --cc examples/demos/plasmapatrol/content/Frigate.qml index 0000000,de099be..92c63b8 mode 000000,100644..100644 --- a/examples/demos/plasmapatrol/content/Frigate.qml +++ b/examples/demos/plasmapatrol/content/Frigate.qml @@@ -1,0 -1,114 +1,114 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + import QtQuick 2.0 + import QtQuick.Particles 2.0 + + Item { + id: container + property int maxHP: 100 + property int hp: maxHP + property real initialDodge: 0.2 + property real dodge: initialDodge + onHpChanged: if(hp <= 0) target = container; + property ParticleSystem system//TODO: Ship abstraction + property Item target: container + property string shipParticle: "default"//Per team colors? + property int gunType: 0 + width: 128 + height: 128 + Emitter { + system: container.system + group: "frigateShield" + anchors.centerIn: parent + size: 92 + emitRate: 1 + lifeSpan: 4800 + enabled: hp > 0 + } + Emitter { + system: container.system + group: container.shipParticle + anchors.centerIn: parent + width: 64 + height: 16 + shape: EllipseShape {} + + size: 16 + sizeVariation: 8 + endSize: 8 + emitRate: hp > 0 ? hp * 1 + 20 : 0 + lifeSpan: 1200 + maximumEmitted: (maxHP * 1 + 20)*2 + } + Timer { + id: fireControl + property int next: Math.floor(Math.random() * 2) + 1 + interval: 800 + running: root.readySetGo + repeat: true + onTriggered: { + if (next == 1) { + gun1.fireAt(container.target); + next = Math.floor(Math.random() * 2) + 1; + } else if (next == 2) { + gun2.fireAt(container.target); + next = Math.floor(Math.random() * 2) + 1; + } + } + } + + Hardpoint { + x: 128 - 32 - 12 + y: 64 - 12 + id: gun1 + system: container.system + show: hp > 0 + hardpointType: gunType + } + Hardpoint { + x: 0 + 32 - 12 + y: 64 - 12 + id: gun2 + system: container.system + show: hp > 0 + hardpointType: gunType + } + } diff --cc examples/demos/plasmapatrol/content/Hardpoint.qml index 0000000,5c7fb55..9e60570 mode 000000,100644..100644 --- a/examples/demos/plasmapatrol/content/Hardpoint.qml +++ b/examples/demos/plasmapatrol/content/Hardpoint.qml @@@ -1,0 -1,114 +1,114 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + import QtQuick 2.0 + import QtQuick.Particles 2.0 + + Item { + id: container + //ReflectiveProperties + //TransferredProperties + property variant target: {"y": -90, "x":12} + property ParticleSystem system + property bool show: true + property int hardpointType: 0 //default is pea shooter - always bad. + + property Item targetObj: null + property int damageDealt: 0 + onDamageDealtChanged: dealDamageTimer.start(); + Timer { + id: dealDamageTimer + interval: 16 + running: false + repeat: false + onTriggered: {targetObj.hp -= damageDealt; damageDealt = 0;} + } + width: 24 + height: 24 + function fireAt(targetArg) {//Each implement own + if (targetArg != null) { + hardpointLoader.item.fireAt(targetArg, container); + targetObj = targetArg; + } + } + Loader { + id: hardpointLoader + sourceComponent: { + switch (hardpointType) { + case 1: laserComponent; break; + case 2: blasterComponent; break; + case 3: cannonComponent; break; + default: emptyComponent; + } + } + } + Component { + id: laserComponent + LaserHardpoint { + target: container.target + system: container.system + show: container.show + } + } + Component { + id: blasterComponent + BlasterHardpoint { + target: container.target + system: container.system + show: container.show + } + } + Component { + id: cannonComponent + CannonHardpoint { + target: container.target + system: container.system + show: container.show + } + } + Component { + id: emptyComponent + Item { + function fireAt(obj) { + console.log("Firing null weapon. It hurts."); + } + } + } + } diff --cc examples/demos/plasmapatrol/content/HelpScreens.qml index 0000000,9297f86..db70c6e mode 000000,100644..100644 --- a/examples/demos/plasmapatrol/content/HelpScreens.qml +++ b/examples/demos/plasmapatrol/content/HelpScreens.qml @@@ -1,0 -1,268 +1,268 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + import QtQuick 2.0 + import QtQuick.Particles 2.0 + + SequentialLoader { + id: hLdr + signal exitDesired + Component.onCompleted: advance(); + ParticleSystem { id: helpSystem } + PlasmaPatrolParticles { sys: helpSystem } + pages: [ + Component {Item { + id: story + Text { + color: "white" + text: "Story" + font.pixelSize: 48 + } + /* + Flickable { + y: 60 + width: 360 + height: 500 + contentHeight: txt1.height + contentWidth: 360//TODO: Less magic numbers? + */ + Text { + id: txt1 + color: "white" + y: 60 + font.pixelSize: 18 + text: " + In a remote nebula, a race of energy beings formed and lived prosperous lives for millenia. Until the schism - when they became constantly at each other's energy-throats. War soon followed, crippling both sides, until a truce was formed. But while governments knew the desparate need for peace, the soldiers in the ion-field were still filled with rampant bloodlust. On the border, patrols are constantly engaging in minor skirmishes whenever they cross paths. + + You must select one such patrol unit for the border, heading into an inevitable skirmish, in Plasma Patrol: the game of energy being spaceship combat! + " + width: 360 + wrapMode: Text.WordWrap + } + // } + Button { + x: 20 + y: 560 + height: 40 + width: 120 + text: "Next" + onClicked: hLdr.advance(); + } + Button { + x: 220 + y: 560 + height: 40 + width: 120 + text: "Menu" + onClicked: hLdr.exitDesired(); + } + }}, + Component {Item { + id: ships + Text { + color: "white" + text: "Vessels" + font.pixelSize: 48 + } + Column { + spacing: 16 + y: 60 + Row { + height: 128 + Sloop { + system: helpSystem + } + Text { + text: "The nimble sloop" + color: "white" + font.pixelSize: 18 + } + } + Row { + height: 128 + Frigate { + system: helpSystem + } + Text { + text: "The versitile shield frigate" + color: "white" + font.pixelSize: 18 + } + } + Row { + height: 128 + Cruiser { + system: helpSystem + } + Text { + text: "The armored cruiser" + color: "white" + font.pixelSize: 18 + } + } + } + Button { + x: 20 + y: 560 + height: 40 + width: 120 + text: "Next" + onClicked: hLdr.advance(); + } + Button { + x: 220 + y: 560 + height: 40 + width: 120 + text: "Menu" + onClicked: hLdr.exitDesired(); + } + }}, + Component {Item { + id: guns + Text { + color: "white" + text: "Hardpoints" + font.pixelSize: 48 + } + Column { + spacing: 16 + y: 60 + Row { + height: 128 + LaserHardpoint { + system: helpSystem + } + Text { + text: "The laser hardpoint almost always hits the target, even the nimble sloop, but loses much of its potency against the frigate's shields" + width: 332 + wrapMode: Text.WordWrap + color: "white" + font.pixelSize: 18 + } + } + Row { + height: 128 + BlasterHardpoint { + system: helpSystem + } + Text { + text: "The blaster passes right through the frigate's shields but loses much of its impact against the armor of the cruiser" + width: 332 + wrapMode: Text.WordWrap + color: "white" + font.pixelSize: 18 + } + } + Row { + height: 128 + CannonHardpoint { + system: helpSystem + } + Text { + text: "The cannon has poor accuracy, often missing the nimble sloop, but can punch right through the armor of the cruiser" + width: 332 + wrapMode: Text.WordWrap + color: "white" + font.pixelSize: 18 + } + } + } + Button { + x: 20 + y: 560 + height: 40 + width: 120 + text: "Next" + onClicked: hLdr.advance(); + } + Button { + x: 220 + y: 560 + height: 40 + width: 120 + text: "Menu" + onClicked: hLdr.exitDesired(); + } + }}, + Component {Item { + id: strategy + Text { + color: "white" + text: "Strategy" + font.pixelSize: 48 + } + Flickable { + y: 60 + width: 360 + height: 500 + contentHeight: txt1.height + contentWidth: 360//TODO: Less magic numbers? + Text { + id: txt1 + color: "white" + font.pixelSize: 18 + text: " + Basic Strategy: Good luck, have fun - don't die. + More to come after thorough playtesting. + " + width: 360 + wrapMode: Text.WordWrap + } + } + Button { + x: 20 + y: 560 + height: 40 + width: 120 + text: "Story" + onClicked: {hLdr.at=0; hLdr.advance();} + } + Button { + x: 220 + y: 560 + height: 40 + width: 120 + text: "Menu" + onClicked: hLdr.exitDesired(); + } + }} + ] + } diff --cc examples/demos/plasmapatrol/content/LaserHardpoint.qml index 0000000,87ac3e9..a7baed6 mode 000000,100644..100644 --- a/examples/demos/plasmapatrol/content/LaserHardpoint.qml +++ b/examples/demos/plasmapatrol/content/LaserHardpoint.qml @@@ -1,0 -1,108 +1,108 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + import QtQuick 2.0 + import QtQuick.Particles 2.0 + + Item { + id: container + property variant target: {"y": -90, "x":12} + property ParticleSystem system + property bool show: true + + width: 24 + height: 24 + Emitter { + id: visualization + group: "laser" + system: container.system + anchors.fill: parent + enabled: container.show + shape: EllipseShape {} + speed: TargetDirection { targetX: width/2; targetY: width/2; magnitude: -1; proportionalMagnitude: true } + lifeSpan: 1000 + emitRate: 64 + + size: 24 + sizeVariation: 8 + endSize: 8 + } + + function fireAt(targetArg, hardpoint) { + if (targetArg.hp <= 0) + return; + //TODO: calculate hit and damage at target, which must be a Ship + var offset = 0; + if (Math.random() < 0.99) { + switch (targetArg.shipType) { + case 1: hardpoint.damageDealt += 16; break; + case 2: hardpoint.damageDealt += 4; break; + case 3: hardpoint.damageDealt += 8; break; + default: hardpoint.damageDealt += 500; //Really effective against unregistered vessels + } + } else {//Misses with Lasers are really rare + offset = Math.random() * 100; + } + target = container.mapFromItem(targetArg, offset + targetArg.width/2, offset + targetArg.height/2); + emitter.pulse(100); + // console.log("Fire box: " + Math.min(container.width/2, target.x) + "," + Math.min(container.height/2, target.y) + " " + (Math.max(container.width/2, target.x) - Math.min(container.width/2, target.x)) + "," + (Math.max(container.height/2, target.y) - Math.min(container.height/2, target.y))); + } + Emitter { + id: emitter + group: "laser" + enabled: false + system: container.system + x: Math.min(container.width/2, target.x); + width: Math.max(container.width/2, target.x) - x; + y: Math.min(container.height/2, target.y); + height: Math.max(container.height/2, target.y) - y; + shape: LineShape { + mirrored: (emitter.y < 0 || emitter.x < 0) && !(emitter.y < 0 && emitter.x < 0 )//I just want XOR + } + + lifeSpan: 1000 + emitRate: 8000 + maximumEmitted: 800 + size: 16 + endSize: 0 + + speed: PointDirection {xVariation: 4; yVariation: 4} + } + } diff --cc examples/demos/plasmapatrol/content/PlasmaPatrolParticles.qml index 0000000,1d856b5..e1924c3 mode 000000,100644..100644 --- a/examples/demos/plasmapatrol/content/PlasmaPatrolParticles.qml +++ b/examples/demos/plasmapatrol/content/PlasmaPatrolParticles.qml @@@ -1,0 -1,173 +1,173 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + import QtQuick 2.0 + import QtQuick.Particles 2.0 + + Item { + property ParticleSystem sys + ImageParticle { + system: sys + groups: ["default"] + source: "pics/blur-circle3.png" + color: "#003A3A3A" + colorVariation: 0.1 + z: 0 + } + ImageParticle { + system: sys + groups: ["redTeam"] + source: "pics/blur-circle3.png" + color: "#0028060A" + colorVariation: 0.1 + z: 0 + } + ImageParticle { + system: sys + groups: ["greenTeam"] + source: "pics/blur-circle3.png" + color: "#0006280A" + colorVariation: 0.1 + z: 0 + } + ImageParticle { + system: sys + groups: ["blaster"] + source: "pics/star2.png" + //color: "#0F282406" + color: "#0F484416" + colorVariation: 0.2 + z: 2 + } + ImageParticle { + system: sys + groups: ["laser"] + source: "pics/star3.png" + //color: "#00123F68" + color: "#00428FF8" + colorVariation: 0.2 + z: 2 + } + ImageParticle { + system: sys + groups: ["cannon"] + source: "pics/particle.png" + color: "#80FFAAFF" + colorVariation: 0.1 + z: 2 + } + ImageParticle { + system: sys + groups: ["cannonCore"] + source: "pics/particle.png" + color: "#00666666" + colorVariation: 0.8 + z: 1 + } + ImageParticle { + system: sys + groups: ["cannonWake"] + source: "pics/star.png" + color: "#00CCCCCC" + colorVariation: 0.2 + z: 1 + } + ImageParticle { + system: sys + groups: ["frigateShield"] + source: "pics/blur-circle2.png" + color: "#00000000" + colorVariation: 0.05 + blueVariation: 0.5 + greenVariation: 0.1 + z: 3 + } + ImageParticle { + system: sys + groups: ["cruiserArmor"] + z: 1 + sprites:[Sprite { + id: spinState + name: "spinning" + source: "pics/meteor.png" + frameCount: 35 + frameDuration: 40 + to: {"death":0, "spinning":1} + },Sprite { + name: "death" + source: "pics/meteor_explo.png" + frameCount: 22 + frameDuration: 40 + to: {"null":1} + }, Sprite { + name: "null" + source: "pics/nullRock.png" + frameCount: 1 + frameDuration: 1000 + } + ] + } + TrailEmitter { + system: sys + group: "cannonWake" + follow: "cannon" + emitRatePerParticle: 64 + lifeSpan: 600 + speed: AngleDirection { angleVariation: 360; magnitude: 48} + size: 16 + endSize: 8 + sizeVariation: 2 + enabled: true + width: 1000//XXX: Terrible hack + height: 1000 + } + TrailEmitter { + system: sys + group: "cannonCore" + follow: "cannon" + emitRatePerParticle: 256 + lifeSpan: 128 + size: 24 + endSize: 8 + enabled: true + width: 1000//XXX: Terrible hack + height: 1000 + } + } diff --cc examples/demos/plasmapatrol/content/SequentialLoader.qml index 0000000,eaef87f..3707759 mode 000000,100644..100644 --- a/examples/demos/plasmapatrol/content/SequentialLoader.qml +++ b/examples/demos/plasmapatrol/content/SequentialLoader.qml @@@ -1,0 -1,54 +1,54 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + import QtQuick 2.0 + + Item { + id: container + //TODO: Somehow get particles into this? + property list pages + property Item cur: null + property int at: 0 + function advance() { + if(cur != null) + cur.destroy(); + cur = pages[at++].createObject(container); + } + } diff --cc examples/demos/plasmapatrol/content/Ship.qml index 0000000,a928cd2..bd023b1 mode 000000,100644..100644 --- a/examples/demos/plasmapatrol/content/Ship.qml +++ b/examples/demos/plasmapatrol/content/Ship.qml @@@ -1,0 -1,114 +1,114 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + import QtQuick 2.0 + import QtQuick.Particles 2.0 + + Item { + id: me + //Reflective Properties + width: shipLoader.width + height: shipLoader.height + //Transfered Properties + property int hp: 100//shipLoader.item.maxHP + property real dodge: shipLoader.item.initialDodge + property ParticleSystem system + property int targetIdx: 0 + property Item target: targets[targetIdx] == undefined?null:targets[targetIdx] + Connections { + target: me.target + onHpChanged: if (me.target.hp<=0) me.targetIdx++; + } + property list targets + property string shipParticle: "default"//Per team colors? + property int gunType: 0 + property int shipType: 0 + Component { + id: sloopComp + Sloop { + system: me.system + target: me.target + shipParticle: me.shipParticle + gunType: me.gunType + hp: me.hp + dodge: me.dodge + } + } + Component { + id: frigateComp + Frigate { + system: me.system + target: me.target + shipParticle: me.shipParticle + gunType: me.gunType + hp: me.hp + dodge: me.dodge + } + } + Component { + id: cruiserComp + Cruiser { + system: me.system + target: me.target + shipParticle: me.shipParticle + gunType: me.gunType + hp: me.hp + dodge: me.dodge + } + } + Component { + id: dumbComp + Item { + property int maxHP: 0 + property int initialDodge: 0 + } + } + Loader { + id: shipLoader + sourceComponent: { + switch (shipType) { + case 1: sloopComp; break; + case 2: frigateComp; break; + case 3: cruiserComp; break; + default: dumbComp; + } + } + } + } diff --cc examples/demos/plasmapatrol/content/Sloop.qml index 0000000,c6b1183..3bc58a2 mode 000000,100644..100644 --- a/examples/demos/plasmapatrol/content/Sloop.qml +++ b/examples/demos/plasmapatrol/content/Sloop.qml @@@ -1,0 -1,108 +1,108 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + import QtQuick 2.0 + import QtQuick.Particles 2.0 + + Item { + id: container + property int maxHP: 100 + property int hp: maxHP + property real initialDodge: 0.5 + property real dodge: initialDodge + property int blinkInterval: 800 + onHpChanged: if(hp <= 0) target = container; + property ParticleSystem system//TODO: Ship abstraction + property Item target: container + property string shipParticle: "default"//Per team colors? + property int gunType: 0 + width: 128 + height: 128 + Emitter { + id: emitter + //TODO: Cooler would be an 'orbiting' affector + //TODO: On the subject, opacity and size should be grouped type 'overLife' if we can cram that in the particles + system: container.system + group: container.shipParticle + shape: EllipseShape {} + + emitRate: hp > 0 ? hp + 20 : 0 + lifeSpan: blinkInterval + maximumEmitted: (maxHP + 20) + + acceleration: AngleDirection {angleVariation: 360; magnitude: 8} + + size: 24 + endSize: 4 + sizeVariation: 8 + width: 16 + height: 16 + x: 64 + y: 64 + Behavior on x {NumberAnimation {duration:blinkInterval}} + Behavior on y {NumberAnimation {duration:blinkInterval}} + Timer { + interval: blinkInterval + running: true + repeat: true + onTriggered: { + emitter.x = Math.random() * 48 + 32 + emitter.y = Math.random() * 48 + 32 + } + } + } + Hardpoint { + anchors.centerIn: parent + id: gun2 + system: container.system + show: container.hp > 0 + hardpointType: gunType + } + Timer { + id: fireControl + interval: 800 + running: root.readySetGo + repeat: true + onTriggered: { + gun2.fireAt(container.target); + } + } + + } diff --cc examples/demos/plasmapatrol/plasmapatrol.qml index 0000000,45f81c7..b14ac63 mode 000000,100644..100644 --- a/examples/demos/plasmapatrol/plasmapatrol.qml +++ b/examples/demos/plasmapatrol/plasmapatrol.qml @@@ -1,0 -1,386 +1,386 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + import QtQuick 2.0 + import QtQuick.Particles 2.0 + import "content" + + Rectangle { + id: root + property bool readySetGo: false + //Debugging + property int hits: 0 + property int misses: 0 + property real ratio: hits/(misses?misses:1) + //Move to JS file? + property Ship redVar1: Ship {shipType: 1; gunType: 1} + property Ship redVar2: Ship {shipType: 1; gunType: 2} + property Ship redVar3: Ship {shipType: 1; gunType: 3} + property Ship greenVar1: Ship {shipType: 3; gunType: 1} + property Ship greenVar2: Ship {shipType: 2; gunType: 2} + property Ship greenVar3: Ship {shipType: 1; gunType: 3} + property string winner: "0" + property int players: 0 + function aiSet(ship) { + ship.gunType = Math.floor(Math.random() * 3) + 1 + ship.shipType = Math.floor(Math.random() * 3) + 1 + } + + width: 360 + height: 600 + color: "black" + SequentialLoader { + anchors.fill: parent + //General Children + Image { + anchors.centerIn: parent + source: "../images/finalfrontier.png" + } + ParticleSystem { + id: particles + } + PlasmaPatrolParticles { sys: particles; z: 100 }//Renders all particles on the one plane + //Component parts + id: pageControl + Component.onCompleted: advance(); + pages:[ + Component {Item { + id: menu + width: root.width + height: root.height + Column { + anchors.verticalCenter: parent.verticalCenter + width: parent.width + spacing: 8 + Item { + id: title + width: root.width + height: 240 + Emitter { + anchors.fill: parent + system: particles + enabled: true + group: "default" + emitRate: 1200 + lifeSpan: 1200 + shape: MaskShape {source:"content/pics/TitleText.png"} + size: 16 + endSize: 0 + sizeVariation: 8 + speed: AngleDirection {angleVariation:360; magnitudeVariation: 6} + } + } + Button { + text: "1P" + onClicked: {root.players = 1; pageControl.advance();} + anchors.horizontalCenter: parent.horizontalCenter + } + Button { + text: "2P" + onClicked: {root.players = 2; pageControl.advance();} + anchors.horizontalCenter: parent.horizontalCenter + } + Button { + text: "Demo" + anchors.horizontalCenter: parent.horizontalCenter + onClicked: {root.players = 0; + aiSet(redVar1); + aiSet(redVar2); + aiSet(redVar3); + aiSet(greenVar1); + aiSet(greenVar2); + aiSet(greenVar3); + pageControl.at = 5;//TODO: Not a magic number + pageControl.advance();} + } + Button { + text: "Help" + anchors.horizontalCenter: parent.horizontalCenter + onClicked: { + pageControl.at = 7;//TODO: Not a magic number + pageControl.advance(); + } + } + Button { + text: "Quit" + anchors.horizontalCenter: parent.horizontalCenter + onClicked: Qt.quit(); + } + } + }}, + Component {Item { + id: p1Screen + z: 101 + width: root.width + height: root.height + Rectangle { + anchors.fill: parent + color: "red" + } + Text { + anchors.centerIn: parent + color: "white" + font.pixelSize: 64 + font.bold: true + text: "Player\n 1" + horizontalAlignment: Text.AlignHCenter + } + MouseArea { + anchors.fill: parent + onClicked: pageControl.advance() + } + }}, + Component {Item { + id: p1Choices + z: 3 + width: root.width + height: root.height + Rectangle { + color: "black" + anchors.fill: parent + } + Column { + spacing: 16 + width: root.width + anchors.horizontalCenter: parent.horizontalCenter + ChoiceBox { + target: redVar1 + system: particles + } + ChoiceBox { + target: redVar2 + system: particles + } + ChoiceBox { + target: redVar3 + system: particles + } + Button { + anchors.horizontalCenter: parent.horizontalCenter + text: "Next" + onClicked: { + if (root.players < 2) { + aiSet(greenVar1); + aiSet(greenVar2); + aiSet(greenVar3); + pageControl.at = 5;//TODO: Not a magic number + } + pageControl.advance(); + } + } + } + }}, + Component {Item { + id: p2Screen + z: 101 + width: root.width + height: root.height + Rectangle { + anchors.fill: parent + color: "green" + } + Text { + anchors.centerIn: parent + color: "white" + font.pixelSize: 64 + font.bold: true + text: "Player\n 2" + horizontalAlignment: Text.AlignHCenter + } + MouseArea { + anchors.fill: parent + onClicked: pageControl.advance() + } + }}, + Component {Item { + id: p2Choices + z: 1 + width: root.width + height: root.height + Rectangle { + color: "black" + anchors.fill: parent + } + Column { + spacing: 16 + width: root.width + anchors.horizontalCenter: parent.horizontalCenter + ChoiceBox { + target: greenVar1 + system: particles + } + ChoiceBox { + target: greenVar2 + system: particles + } + ChoiceBox { + target: greenVar3 + system: particles + } + Button { + anchors.horizontalCenter: parent.horizontalCenter + text: "Next" + onClicked: pageControl.advance() + } + } + }}, + Component {Item { + id: arena + width: root.width + height: root.height + z: 0 + Component.onCompleted: root.readySetGo = true + Component.onDestruction: root.readySetGo = false + property bool victory: redShip3.hp <= 0 || greenShip3.hp <=0 + onVictoryChanged: { + if (redShip3.hp <= 0) { + if (greenShip3.hp <= 0) { + root.winner = "1&2" + }else { + root.winner = "2" + } + } else { + root.winner = "1" + } + winTimer.start() + } + Timer { + id: winTimer + interval: 1200 + repeat: false + running: false + onTriggered: pageControl.advance(); + } + Ship { + id: redShip1 + shipParticle: "redTeam" + system: particles + x: 180-64 + y: 128 + shipType: redVar1.shipType + gunType: redVar1.gunType + targets: [greenShip1, greenShip2, greenShip3] + } + Ship { + id: redShip2 + shipParticle: "redTeam" + system: particles + x: 0 + y: 0 + shipType: redVar2.shipType + gunType: redVar2.gunType + targets: [greenShip1, greenShip2, greenShip3] + } + Ship { + id: redShip3 + shipParticle: "redTeam" + system: particles + x: 360-128 + y: 0 + shipType: redVar3.shipType + gunType: redVar3.gunType + targets: [greenShip1, greenShip2, greenShip3] + } + + Ship { + id: greenShip1 + shipParticle: "greenTeam" + system: particles + x: 180-64 + y: 600 - 128 - 128 + shipType: greenVar1.shipType + gunType: greenVar1.gunType + targets: [redShip1, redShip2, redShip3] + } + Ship { + id: greenShip2 + shipParticle: "greenTeam" + system: particles + x: 0 + y: 600-128 + shipType: greenVar2.shipType + gunType: greenVar2.gunType + targets: [redShip1, redShip2, redShip3] + } + Ship { + id: greenShip3 + shipParticle: "greenTeam" + system: particles + x: 360 - 128 + y: 600 - 128 + shipType: greenVar3.shipType + gunType: greenVar3.gunType + targets: [redShip1, redShip2, redShip3] + } + }}, + Component {Item { + id: winScreen + z: 101 + width: root.width + height: root.height + /* + Rectangle { + anchors.fill: parent + color: "black" + } + */ + Text {//TODO: Particle Text? + anchors.fill: parent + color: "white" + font.pixelSize: 64 + font.bold: true + text: "Player " + root.winner + " wins!" + wrapMode: Text.WordWrap + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + MouseArea { + anchors.fill: parent + onClicked: {pageControl.at = 0; pageControl.advance();} + } + }}, + Component { + HelpScreens { + onExitDesired: {pageControl.at = 0; pageControl.advance();} + } + } + ] + } + } diff --cc examples/demos/rssnews/content/BusyIndicator.qml index 0000000,b6264ea..f1abd11 mode 000000,100644..100644 --- a/examples/demos/rssnews/content/BusyIndicator.qml +++ b/examples/demos/rssnews/content/BusyIndicator.qml @@@ -1,0 -1,53 +1,53 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Image { + id: container + property bool on: false + + source: "images/busy.png"; visible: container.on + + NumberAnimation on rotation { + running: container.on; from: 0; to: 360; loops: Animation.Infinite; duration: 1200 + } + } diff --cc examples/demos/rssnews/content/CategoryDelegate.qml index 0000000,1a56184..fe64238 mode 000000,100644..100644 --- a/examples/demos/rssnews/content/CategoryDelegate.qml +++ b/examples/demos/rssnews/content/CategoryDelegate.qml @@@ -1,0 -1,82 +1,82 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Item { + id: delegate + + width: delegate.ListView.view.width; height: 60 + + Text { + text: name + color: delegate.ListView.isCurrentItem ? "white" : "black" + font { family: "Helvetica"; pixelSize: 16; bold: true } + anchors { + left: parent.left; leftMargin: 15 + verticalCenter: parent.verticalCenter + } + } + + BusyIndicator { + scale: 0.6 + on: delegate.ListView.isCurrentItem && window.loading + anchors { right: parent.right; rightMargin: 10; verticalCenter: parent.verticalCenter } + } + + Rectangle { + width: delegate.width; height: 1; color: "#cccccc" + anchors.bottom: delegate.bottom + visible: delegate.ListView.isCurrentItem ? false : true + } + Rectangle { + width: delegate.width; height: 1; color: "white" + visible: delegate.ListView.isCurrentItem ? false : true + } + + MouseArea { + anchors.fill: delegate + onClicked: { + delegate.ListView.view.currentIndex = index + window.currentFeed = feed + } + } + } diff --cc examples/demos/rssnews/content/NewsDelegate.qml index 0000000,84019a9..59ab269 mode 000000,100644..100644 --- a/examples/demos/rssnews/content/NewsDelegate.qml +++ b/examples/demos/rssnews/content/NewsDelegate.qml @@@ -1,0 -1,71 +1,71 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Item { + id: delegate + height: column.height + 40 + width: delegate.ListView.view.width + + Column { + id: column + x: 20; y: 20 + width: parent.width - 40 + + Text { + id: titleText + text: title; width: parent.width; wrapMode: Text.WordWrap + font { bold: true; family: "Helvetica"; pointSize: 16 } + } + + Text { + id: descriptionText + width: parent.width; text: description + wrapMode: Text.WordWrap; font.family: "Helvetica" + } + } + + Rectangle { + width: parent.width; height: 1; color: "#cccccc" + anchors.bottom: parent.bottom + } + } diff --cc examples/demos/rssnews/content/RssFeeds.qml index 0000000,278f057..ed58ef3 mode 000000,100644..100644 --- a/examples/demos/rssnews/content/RssFeeds.qml +++ b/examples/demos/rssnews/content/RssFeeds.qml @@@ -1,0 -1,59 +1,59 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + ListModel { + id: rssFeeds + + ListElement { name: "Top Stories"; feed: "rss.news.yahoo.com/rss/topstories" } + ListElement { name: "World"; feed: "rss.news.yahoo.com/rss/world" } + ListElement { name: "Europe"; feed: "rss.news.yahoo.com/rss/europe" } + ListElement { name: "Oceania"; feed: "rss.news.yahoo.com/rss/oceania" } + ListElement { name: "U.S. National"; feed: "rss.news.yahoo.com/rss/us" } + ListElement { name: "Politics"; feed: "rss.news.yahoo.com/rss/politics" } + ListElement { name: "Business"; feed: "rss.news.yahoo.com/rss/business" } + ListElement { name: "Technology"; feed: "rss.news.yahoo.com/rss/tech" } + ListElement { name: "Entertainment"; feed: "rss.news.yahoo.com/rss/entertainment" } + ListElement { name: "Health"; feed: "rss.news.yahoo.com/rss/health" } + ListElement { name: "Science"; feed: "rss.news.yahoo.com/rss/science" } + ListElement { name: "Sports"; feed: "rss.news.yahoo.com/rss/sports" } + } diff --cc examples/demos/rssnews/content/ScrollBar.qml index 0000000,4ca4132..7b1a2ac mode 000000,100644..100644 --- a/examples/demos/rssnews/content/ScrollBar.qml +++ b/examples/demos/rssnews/content/ScrollBar.qml @@@ -1,0 -1,107 +1,107 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Item { + id: container + + property variant scrollArea + property variant orientation: Qt.Vertical + + opacity: 0 + + function position() + { + var ny = 0; + if (container.orientation == Qt.Vertical) + ny = scrollArea.visibleArea.yPosition * container.height; + else + ny = scrollArea.visibleArea.xPosition * container.width; + if (ny > 2) return ny; else return 2; + } + + function size() + { + var nh, ny; + + if (container.orientation == Qt.Vertical) + nh = scrollArea.visibleArea.heightRatio * container.height; + else + nh = scrollArea.visibleArea.widthRatio * container.width; + + if (container.orientation == Qt.Vertical) + ny = scrollArea.visibleArea.yPosition * container.height; + else + ny = scrollArea.visibleArea.xPosition * container.width; + + if (ny > 3) { + var t; + if (container.orientation == Qt.Vertical) + t = Math.ceil(container.height - 3 - ny); + else + t = Math.ceil(container.width - 3 - ny); + if (nh > t) return t; else return nh; + } else return nh + ny; + } + + Rectangle { anchors.fill: parent; color: "Black"; opacity: 0.3 } + + BorderImage { + source: "images/scrollbar.png" + border { left: 1; right: 1; top: 1; bottom: 1 } + x: container.orientation == Qt.Vertical ? 2 : position() + width: container.orientation == Qt.Vertical ? container.width - 4 : size() + y: container.orientation == Qt.Vertical ? position() : 2 + height: container.orientation == Qt.Vertical ? size() : container.height - 4 + } + + states: State { + name: "visible" + when: container.orientation == Qt.Vertical ? scrollArea.movingVertically : scrollArea.movingHorizontally + PropertyChanges { target: container; opacity: 1.0 } + } + + transitions: Transition { + from: "visible"; to: "" + NumberAnimation { properties: "opacity"; duration: 600 } + } + } diff --cc examples/demos/rssnews/rssnews.qml index 0000000,491cefd..d26b94b mode 000000,100644..100644 --- a/examples/demos/rssnews/rssnews.qml +++ b/examples/demos/rssnews/rssnews.qml @@@ -1,0 -1,112 +1,112 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + import QtQuick.XmlListModel 2.0 + import "content" + + Rectangle { + id: window + width: 800; height: 480 + + property string currentFeed: "rss.news.yahoo.com/rss/topstories" + property bool loading: feedModel.status == XmlListModel.Loading + + RssFeeds { id: rssFeeds } + + XmlListModel { + id: feedModel + source: "http://" + window.currentFeed + query: "/rss/channel/item" + + XmlRole { name: "title"; query: "title/string()" } + XmlRole { name: "link"; query: "link/string()" } + XmlRole { name: "description"; query: "description/string()" } + } + + Row { + Rectangle { + width: 220; height: window.height + color: "#efefef" + + ListView { + focus: true + id: categories + anchors.fill: parent + model: rssFeeds + footer: quitButtonDelegate + delegate: CategoryDelegate {} + highlight: Rectangle { color: "steelblue" } + highlightMoveSpeed: 9999999 + } + ScrollBar { + scrollArea: categories; height: categories.height; width: 8 + anchors.right: categories.right + } + } + ListView { + id: list + width: window.width - 220; height: window.height + model: feedModel + delegate: NewsDelegate {} + } + } + Component { + id: quitButtonDelegate + Item { + width: categories.width; height: 60 + Text { + text: "Quit" + font { family: "Helvetica"; pixelSize: 16; bold: true } + anchors { + left: parent.left; leftMargin: 15 + verticalCenter: parent.verticalCenter + } + } + MouseArea { + anchors.fill: parent + onClicked: Qt.quit() + } + } + } + ScrollBar { scrollArea: list; height: list.height; width: 8; anchors.right: window.right } + Rectangle { x: 220; height: window.height; width: 1; color: "#cccccc" } + } diff --cc examples/demos/samegame/content/BoomBlock.qml index 0000000,47f86bd..a348368 mode 000000,100644..100644 --- a/examples/demos/samegame/content/BoomBlock.qml +++ b/examples/demos/samegame/content/BoomBlock.qml @@@ -1,0 -1,112 +1,112 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + import QtQuick.Particles 2.0 + + Item { + id: block + property bool dying: false + property bool spawned: false + property int type: 0 + property ParticleSystem particleSystem + + Behavior on x { + enabled: spawned; + SpringAnimation{ spring: 2; damping: 0.2 } + } + Behavior on y { + SpringAnimation{ spring: 2; damping: 0.2 } + } + + Image { + id: img + source: { + if(type == 0){ + "pics/redStone.png"; + } else if(type == 1) { + "pics/blueStone.png"; + } else { + "pics/greenStone.png"; + } + } + opacity: 0 + Behavior on opacity { NumberAnimation { duration: 200 } } + anchors.fill: parent + } + Emitter { + id: particles + system: particleSystem + group: { + if(type == 0){ + "red"; + } else if (type == 1) { + "blue"; + } else { + "green"; + } + } + anchors.fill: parent + + speed: TargetDirection{targetX: block.width/2; targetY: block.height/2; magnitude: -60; magnitudeVariation: 60} + shape: EllipseShape{fill:true} + enabled: false; + lifeSpan: 700; lifeSpanVariation: 100 + emitRate: 1000 + maximumEmitted: 100 //only fires 0.1s bursts (still 2x old number) + size: 28 + endSize: 14 + } + + states: [ + State { + name: "AliveState"; when: spawned == true && dying == false + PropertyChanges { target: img; opacity: 1 } + }, + + State { + name: "DeathState"; when: dying == true + StateChangeScript { script: {particleSystem.paused = false; particles.pulse(100);} } + PropertyChanges { target: img; opacity: 0 } + StateChangeScript { script: block.destroy(1000); } + } + ] + } diff --cc examples/demos/samegame/content/Button.qml index 0000000,b305455..2d1a993 mode 000000,100644..100644 --- a/examples/demos/samegame/content/Button.qml +++ b/examples/demos/samegame/content/Button.qml @@@ -1,0 -1,75 +1,75 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Rectangle { + id: container + + property string text: "Button" + + signal clicked + + width: buttonLabel.width + 20; height: buttonLabel.height + 20 + smooth: true + border { width: 1; color: Qt.darker(activePalette.button) } + radius: 8 + color: activePalette.button + + gradient: Gradient { + GradientStop { + position: 0.0 + color: { + if (mouseArea.pressed) + return activePalette.dark + else + return activePalette.light + } + } + GradientStop { position: 1.0; color: activePalette.button } + } + + MouseArea { id: mouseArea; anchors.fill: parent; onClicked: container.clicked() } + + Text { + id: buttonLabel; text: container.text; anchors.centerIn: container; color: activePalette.buttonText; font.pixelSize: 24 + } + } diff --cc examples/demos/samegame/content/Dialog.qml index 0000000,80e5984..c81580e mode 000000,100644..100644 --- a/examples/demos/samegame/content/Dialog.qml +++ b/examples/demos/samegame/content/Dialog.qml @@@ -1,0 -1,81 +1,81 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Rectangle { + id: page + anchors.centerIn: parent + + property Item text: dialogText + property bool open: false + + signal closed + signal opened + function forceClose() { + if(!open) + return; //already closed + page.open = false; + page.closed(); + page.opacity = 0; + } + + function show(txt) { + page.open = true; + page.opened(); + dialogText.text = txt; + page.opacity = 1; + } + + width: dialogText.width + 20; height: dialogText.height + 20 + color: "white" + border.width: 1 + opacity: 0 + visible: opacity > 0 + Behavior on opacity { + NumberAnimation { duration: 1000 } + } + + Text { id: dialogText; anchors.centerIn: parent; text: "Hello World!" } + + MouseArea { anchors.fill: parent; onClicked: forceClose(); } + } + diff --cc examples/demos/samegame/content/GameArea.qml index 0000000,a43d551..3422582 mode 000000,100644..100644 --- a/examples/demos/samegame/content/GameArea.qml +++ b/examples/demos/samegame/content/GameArea.qml @@@ -1,0 -1,92 +1,92 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + import QtQuick.Particles 2.0 + import "samegame.js" as Logic + + Item { + id: gameCanvas + property int score: 0 + property int blockSize: 40 + property ParticleSystem ps: particleSystem + Image { + id: background + anchors.fill: parent + z: -1 + source: "pics/background.png" + fillMode: Image.PreserveAspectCrop + } + + width: 480 + height: 800 + MouseArea { + anchors.fill: parent; onClicked: Logic.handleClick(mouse.x,mouse.y); + } + ParticleSystem{ + id: particleSystem; + onEmptyChanged: if (empty) paused = true; + z:2 + ImageParticle { + groups: ["red"] + color: Qt.darker("red");//Actually want desaturated... + source: "pics/particle.png" + colorVariation: 0.4 + alpha: 0.1 + } + ImageParticle { + groups: ["green"] + color: Qt.darker("green");//Actually want desaturated... + source: "pics/particle.png" + colorVariation: 0.4 + alpha: 0.1 + } + ImageParticle { + groups: ["blue"] + color: Qt.darker("blue");//Actually want desaturated... + source: "pics/particle.png" + colorVariation: 0.4 + alpha: 0.1 + } + anchors.fill: parent + } + } + diff --cc examples/demos/samegame/content/NameInputDialog.qml index 0000000,602e697..7c3bfa2 mode 000000,100644..100644 --- a/examples/demos/samegame/content/NameInputDialog.qml +++ b/examples/demos/samegame/content/NameInputDialog.qml @@@ -1,0 -1,93 +1,93 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + import QtQuick 2.0 + + Dialog { + id: nameInputDialog + + property int initialWidth: 0 + property alias name: nameInputText.text + + anchors.centerIn: parent + z: 22; + + Behavior on width { + NumberAnimation {} + enabled: nameInputDialog.initialWidth != 0 + } + + signal accepted(string name) + onClosed: { + if (nameInputText.text != "") + accepted(name); + } + Text { + id: dialogText + anchors { left: nameInputDialog.left; leftMargin: 20; verticalCenter: parent.verticalCenter } + text: "You won! Please enter your name: " + } + MouseArea { + anchors.fill: parent + onClicked: { + if (nameInputText.text == "") + nameInputText.openSoftwareInputPanel(); + else + nameInputDialog.forceClose(); + } + } + + TextInput { + id: nameInputText + anchors { verticalCenter: parent.verticalCenter; left: dialogText.right } + focus: visible + autoScroll: false + maximumLength: 24 + onTextChanged: { + var newWidth = nameInputText.width + dialogText.width + 40; + if ( (newWidth > nameInputDialog.width && newWidth < screen.width) + || (nameInputDialog.width > nameInputDialog.initialWidth) ) + nameInputDialog.width = newWidth; + } + onAccepted: { + nameInputDialog.forceClose(); + } + } + } diff --cc examples/demos/samegame/samegame.qml index 0000000,201f826..b98b6a0 mode 000000,100644..100644 --- a/examples/demos/samegame/samegame.qml +++ b/examples/demos/samegame/samegame.qml @@@ -1,0 -1,87 +1,87 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + import QtQuick.Particles 2.0 + import "content" + import "content/samegame.js" as Logic + + Rectangle { + id: screen + width: 480; height: 640 + + SystemPalette { id: activePalette } + + GameArea { + id: gameCanvas + width: parent.width + anchors { top: parent.top; bottom: toolBar.top } + } + + Rectangle { + id: toolBar + width: parent.width; height: 80 + color: activePalette.window + anchors.bottom: screen.bottom + + Button { + id: newGameButton + anchors { left: parent.left; leftMargin: 12; verticalCenter: parent.verticalCenter } + text: "New Game" + onClicked: Logic.startNewGame(gameCanvas) + } + + Button { + text: "Quit" + anchors { left: newGameButton.right; leftMargin: 12; verticalCenter: parent.verticalCenter } + onClicked: Qt.quit(); + } + + Text { + id: score + anchors { right: parent.right; rightMargin: 12; verticalCenter: parent.verticalCenter } + text: "Score: " + gameCanvas.score + font.bold: true + font.pixelSize: 24 + color: activePalette.windowText + } + } + } diff --cc examples/demos/snake/content/Button.qml index 0000000,dfac450..4f29455 mode 000000,100644..100644 --- a/examples/demos/snake/content/Button.qml +++ b/examples/demos/snake/content/Button.qml @@@ -1,0 -1,66 +1,66 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Rectangle { + id: container + + signal clicked + property string text: "Button" + + color: activePalette.button; smooth: true + width: txtItem.width + 20; height: txtItem.height + 6 + border.width: 1; border.color: Qt.darker(activePalette.button); radius: 8; + + gradient: Gradient { + GradientStop { + id: topGrad; position: 0.0 + color: if (mr.pressed) { activePalette.dark } else { activePalette.light } } + GradientStop { position: 1.0; color: activePalette.button } + } + + MouseArea { id: mr; anchors.fill: parent; onClicked: container.clicked() } + + Text { + id: txtItem; text: container.text; anchors.centerIn: container; color: activePalette.buttonText + } + } diff --cc examples/demos/snake/content/Cookie.qml index 0000000,cae53af..35ffe40 mode 000000,100644..100644 --- a/examples/demos/snake/content/Cookie.qml +++ b/examples/demos/snake/content/Cookie.qml @@@ -1,0 -1,102 +1,102 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + import QtQuick.Particles 2.0 + + Item { + id: root + property bool dying: false + property int row; + property int column; + x: margin + column * gridSize + y: margin + row * gridSize + + width: gridSize + height: gridSize + property int value : 1; + + Image { + id: img + anchors.fill: parent + source: "pics/cookie.png" + opacity: 0 + Text { + font.bold: true + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + text: value + } + } + + + ParticleSystem { + width:1; height:1; anchors.centerIn: parent; + ImageParticle { + groups: ["star"] + source: "pics/yellowStar.png" + } + Emitter { + id: particles + anchors.fill: parent + group: "star" + emitRate: 50 + enabled: false + lifeSpan: 700 + acceleration: AngleDirection { angleVariation: 360; magnitude: 200 } + } + } + + states: [ + State{ name: "AliveState"; when: dying == false + PropertyChanges { target: img; opacity: 1 } + }, + State{ name: "DeathState"; when: dying == true + StateChangeScript { script: particles.burst(50); } + PropertyChanges { target: img; opacity: 0 } + } + ] + transitions: [ + Transition { + NumberAnimation { target: img; property: "opacity"; duration: 100 } + } + ] + } diff --cc examples/demos/snake/content/HighScoreModel.qml index 0000000,af66b99..734a661 mode 000000,100644..100644 --- a/examples/demos/snake/content/HighScoreModel.qml +++ b/examples/demos/snake/content/HighScoreModel.qml @@@ -1,0 -1,140 +1,140 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + import QtQuick.LocalStorage 2.0 as Sql + + // Models a high score table. + // + // Use this component like this: + // + // HighScoreModel { + // id: highScores + // game: "MyCoolGame" + // } + // + // Then use either use the top-score properties: + // + // Text { text: "HI: " + highScores.topScore } + // + // or, use the model in a view: + // + // ListView { + // model: highScore + // delegate: Component { + // ... player ... score ... + // } + // } + // + // Add new scores via: + // + // saveScore(newScore) + // + // or: + // + // savePlayerScore(playerName,newScore) + // + // The best maxScore scores added by this method will be retained in an SQL database, + // and presented in the model and in the topScore/topPlayer properties. + // + + ListModel { + id: model + property string game: "" + property int topScore: 0 + property string topPlayer: "" + property int maxScores: 10 + + function __db() + { + return Sql.openDatabaseSync("HighScoreModel", "1.0", "Generic High Score Functionality for QML", 1000000); + } + function __ensureTables(tx) + { + tx.executeSql('CREATE TABLE IF NOT EXISTS HighScores(game TEXT, score INT, player TEXT)', []); + } + + function fillModel() { + __db().transaction( + function(tx) { + __ensureTables(tx); + var rs = tx.executeSql("SELECT score,player FROM HighScores WHERE game=? ORDER BY score DESC", [game]); + model.clear(); + if (rs.rows.length > 0) { + topScore = rs.rows.item(0).score + topPlayer = rs.rows.item(0).player + for (var i=0; i maxScores) + tx.executeSql("DELETE FROM HighScores WHERE game=? AND score <= ?", + [game, rs.rows.item(maxScores).score]); + } + } + ) + } + + function savePlayerScore(player,score) { + __db().transaction( + function(tx) { + __ensureTables(tx); + tx.executeSql("INSERT INTO HighScores VALUES(?,?,?)", [game,score,player]); + fillModel(); + } + ) + } + + function saveScore(score) { + savePlayerScore("player",score); + } + + function clearScores() { + __db().transaction( + function(tx) { + tx.executeSql("DELETE FROM HighScores WHERE game=?", [game]); + fillModel(); + } + ) + } + + Component.onCompleted: { fillModel() } + } diff --cc examples/demos/snake/content/Link.qml index 0000000,891adaf..aab005a mode 000000,100644..100644 --- a/examples/demos/snake/content/Link.qml +++ b/examples/demos/snake/content/Link.qml @@@ -1,0 -1,129 +1,129 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + import QtQuick.Particles 2.0 + + Item { id:link + property bool dying: false + property bool spawned: false + property int type: 0 + property int row: 0 + property int column: 0 + property int rotation; + + width: 40; + height: 40 + + x: margin - 3 + gridSize * column + y: margin - 3 + gridSize * row + Behavior on x { NumberAnimation { duration: spawned ? heartbeatInterval : 0} } + Behavior on y { NumberAnimation { duration: spawned ? heartbeatInterval : 0 } } + + + Item { + id: img + anchors.fill: parent + Image { + source: { + if(type == 1) { + "pics/blueStone.png"; + } else if (type == 2) { + "pics/head.png"; + } else { + "pics/redStone.png"; + } + } + + transform: Rotation { + id: actualImageRotation + origin.x: width/2; origin.y: height/2; + angle: rotation * 90 + Behavior on angle { + RotationAnimation{ + direction: RotationAnimation.Shortest + duration: spawned ? 200 : 0 + } + } + } + } + + Image { + source: "pics/stoneShadow.png" + } + + opacity: 0 + } + + ParticleSystem { + width:1; height:1; anchors.centerIn: parent; + ImageParticle { + groups: ["star"] + source: type == 1 ? "pics/blueStar.png" : "pics/redStar.png" + } + Emitter { + id: particles + anchors.fill: parent + group: "star" + emitRate: 50 + enabled: false + lifeSpan: 700 + acceleration: AngleDirection { angleVariation: 360; magnitude: 200 } + } + } + + states: [ + State{ name: "AliveState"; when: spawned == true && dying == false + PropertyChanges { target: img; opacity: 1 } + }, + State{ name: "DeathState"; when: dying == true + StateChangeScript { script: particles.burst(50); } + PropertyChanges { target: img; opacity: 0 } + } + ] + + transitions: [ + Transition { + NumberAnimation { target: img; property: "opacity"; duration: 200 } + } + ] + + } diff --cc examples/demos/snake/content/Skull.qml index 0000000,9026790..0c173be mode 000000,100644..100644 --- a/examples/demos/snake/content/Skull.qml +++ b/examples/demos/snake/content/Skull.qml @@@ -1,0 -1,62 +1,62 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Image { + property bool spawned: false + property int row; + property int column; + property int verticalMovement; + property int horizontalMovement; + + x: screen.margin + column * screen.gridSize + 2 + y: screen.margin + row * screen.gridSize - 3 + Behavior on x { NumberAnimation { duration: spawned ? screen.halfbeatInterval : 0} } + Behavior on y { NumberAnimation { duration: spawned ? screen.halfbeatInterval : 0 } } + + opacity: spawned ? 1 : 0 + Behavior on opacity { NumberAnimation { duration: 200 } } + + source: "pics/skull.png" + width: 24 + height: 40 + } diff --cc examples/demos/snake/snake.qml index 0000000,fca3273..efd5747 mode 000000,100644..100644 --- a/examples/demos/snake/snake.qml +++ b/examples/demos/snake/snake.qml @@@ -1,0 -1,273 +1,273 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + import "content" as Content + import "content/snake.js" as Logic + Item{ + Rectangle { + id: screen; + SystemPalette { id: activePalette } + color: activePalette.window + property bool activeGame: false + + property int gridSize : 34 + property int margin: 4 + property int numRowsAvailable: Math.floor((height-32-2*margin)/gridSize) + property int numColumnsAvailable: Math.floor((width-2*margin)/gridSize) + + property int lastScore : 0 + + property int score: 0; + property int heartbeatInterval: 200 + property int halfbeatInterval: 160 + + width: 480 + height: 750 + + property int direction + property int headDirection + + property variant head; + + Content.HighScoreModel { + id: highScores + game: "Snake" + } + + Timer { + id: heartbeat; + interval: screen.heartbeatInterval; + running: screen.activeGame + repeat: true + onTriggered: { Logic.move() } + } + Timer { + id: halfbeat; + interval: screen.halfbeatInterval; + repeat: true + running: heartbeat.running + onTriggered: { Logic.moveSkull() } + } + Timer { + id: startNewGameTimer; + interval: 700; + onTriggered: { Logic.startNewGame(); } + } + + Timer { + id: startHeartbeatTimer; + interval: 1000 ; + onTriggered: { screen.state = "running"; screen.activeGame = true; } + } + + Image{ + id: pauseDialog + z: 1 + source: "content/pics/pause.png" + anchors.centerIn: parent; + //opacity is deliberately not animated + opacity: 0 //Was !Qt.application.active && activeGame, but application doesn't work (QTBUG-23331) + } + + Image { + + Image { + id: title + source: "content/pics/snake.jpg" + fillMode: Image.PreserveAspectCrop + anchors.fill: parent + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + + Column { + spacing: 140 + anchors.verticalCenter: parent.verticalCenter; + anchors.left: parent.left; + anchors.right: parent.right; + + Text { + color: "white" + font.pointSize: 48 + font.italic: true; + font.bold: true; + text: "Snake" + anchors.horizontalCenter: parent.horizontalCenter; + } + + Text { + color: "white" + font.pointSize: 24 + anchors.horizontalCenter: parent.horizontalCenter; + //horizontalAlignment: Text.AlignHCenter + text: "Last Score:\t" + screen.lastScore + "\nHighscore:\t" + highScores.topScore; + } + } + } + + source: "content/pics/background.png" + fillMode: Image.PreserveAspectCrop + + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + anchors.bottom: toolbar.top + + Rectangle { + id: playfield + border.width: 1 + border.color: "white" + color: "transparent" + anchors.horizontalCenter: parent.horizontalCenter + y: (screen.height - 32 - height)/2; + width: screen.numColumnsAvailable * screen.gridSize + 2*screen.margin + height: screen.numRowsAvailable * screen.gridSize + 2*screen.margin + + + Content.Skull { + id: skull + } + + MouseArea { + anchors.fill: parent + onPressed: { + if (screen.state == "") { + Logic.startNewGame(); + return; + } + if (direction == 0 || direction == 2) + Logic.scheduleDirection((mouseX > (head.x + head.width/2)) ? 1 : 3); + else + Logic.scheduleDirection((mouseY > (head.y + head.height/2)) ? 2 : 0); + } + } + } + + } + + Rectangle { + id: progressBar + opacity: 0 + Behavior on opacity { NumberAnimation { duration: 200 } } + color: "transparent" + border.width: 2 + border.color: "#221edd" + x: 50 + y: 50 + width: 200 + height: 30 + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: 40 + + Rectangle { + id: progressIndicator + color: "#221edd"; + width: 0; + height: 30; + } + } + + Rectangle { + id: toolbar + color: activePalette.window + height: 32; width: parent.width + anchors.bottom: screen.bottom + + Content.Button { + id: btnA; text: "New Game"; onClicked: Logic.startNewGame(); + anchors.left: parent.left; anchors.leftMargin: 3 + anchors.verticalCenter: parent.verticalCenter + } + + Content.Button { + text: "Quit" + anchors { left: btnA.right; leftMargin: 3; verticalCenter: parent.verticalCenter } + onClicked: Qt.quit(); + } + + Text { + color: activePalette.text + text: "Score: " + screen.score; font.bold: true + anchors.right: parent.right; anchors.rightMargin: 3 + anchors.verticalCenter: parent.verticalCenter + } + } + + focus: true + Keys.onSpacePressed: Logic.startNewGame(); + Keys.onLeftPressed: if (state == "starting" || direction != 1) Logic.scheduleDirection(3); + Keys.onRightPressed: if (state == "starting" || direction != 3) Logic.scheduleDirection(1); + Keys.onUpPressed: if (state == "starting" || direction != 2) Logic.scheduleDirection(0); + Keys.onDownPressed: if (state == "starting" || direction != 0) Logic.scheduleDirection(2); + + states: [ + State { + name: "starting" + PropertyChanges {target: progressIndicator; width: 200} + PropertyChanges {target: title; opacity: 0} + PropertyChanges {target: progressBar; opacity: 1} + }, + State { + name: "running" + PropertyChanges {target: progressIndicator; width: 200} + PropertyChanges {target: title; opacity: 0} + PropertyChanges {target: skull; row: 0; column: 0; } + PropertyChanges {target: skull; spawned: 1} + } + ] + + transitions: [ + Transition { + from: "*" + to: "starting" + NumberAnimation { target: progressIndicator; property: "width"; duration: 1000 } + NumberAnimation { property: "opacity"; duration: 200 } + }, + Transition { + to: "starting" + NumberAnimation { target: progressIndicator; property: "width"; duration: 1000 } + NumberAnimation { property: "opacity"; duration: 200 } + } + ] + + } + } diff --cc examples/demos/twitter/TwitterCore/Button.qml index 0000000,064fd4b..353b993 mode 000000,100644..100644 --- a/examples/demos/twitter/TwitterCore/Button.qml +++ b/examples/demos/twitter/TwitterCore/Button.qml @@@ -1,0 -1,90 +1,90 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Item { + id: container + + signal clicked + + property string text + property bool keyUsing: false + + BorderImage { + id: buttonImage + source: "images/toolbutton.sci" + width: container.width; height: container.height + } + BorderImage { + id: pressed + opacity: 0 + source: "images/toolbutton.sci" + width: container.width; height: container.height + } + MouseArea { + id: mouseRegion + anchors.fill: buttonImage + onClicked: { container.clicked(); } + } + Text { + id: btnText + color: if(container.keyUsing){"#D0D0D0";} else {"#FFFFFF";} + anchors.centerIn: buttonImage; font.bold: true + text: container.text; style: Text.Raised; styleColor: "black" + font.pixelSize: 12 + } + states: [ + State { + name: "Pressed" + when: mouseRegion.pressed == true + PropertyChanges { target: pressed; opacity: 1 } + }, + State { + name: "Focused" + when: container.activeFocus == true + PropertyChanges { target: btnText; color: "#FFFFFF" } + } + ] + transitions: Transition { + ColorAnimation { target: btnText; } + } + } diff --cc examples/demos/twitter/TwitterCore/FatDelegate.qml index 0000000,5fd0d16..4cb0dfc mode 000000,100644..100644 --- a/examples/demos/twitter/TwitterCore/FatDelegate.qml +++ b/examples/demos/twitter/TwitterCore/FatDelegate.qml @@@ -1,0 -1,105 +1,105 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Component { + id: listDelegate + Item { + id: wrapper; width: wrapper.ListView.view.width; height: if(txt.height > 60){txt.height+10}else{60} //50+5+5 + function handleLink(link){ + if(link.slice(0,3) == 'app'){ + screen.setUser(link.slice(7)); + }else if(link.slice(0,4) == 'http'){ + Qt.openUrlExternally(link); + } + } + function addTags(str){ + var ret = str.replace(/@[a-zA-Z0-9_]+/g, '$&');//click to jump to user? + var ret2 = ret.replace(/http:\/\/[^ \n\t]+/g, '$&');//surrounds http links with html link tags + return ret2; + } + + // Strip away paranthesis + function userName(str) { + var user = str.replace(/\([\S|\s]*\)/gi, ""); + return user.trim(); + } + + Item { + id: moveMe; height: parent.height + Rectangle { + id: blackRect + color: "black"; opacity: wrapper.ListView.index % 2 ? 0.2 : 0.3; height: wrapper.height-2; width: wrapper.width; y: 1 + } + Item { + id: image; x: 6; width: 48; height: 48; smooth: true + anchors.verticalCenter: parent.verticalCenter + + Loading { x: 1; y: 1; width: 48; height: 48; visible: realImage.status != Image.Ready } + Image { + id: realImage; + source: userImage; x: 1; y: 1; + width:48; height:48; opacity:0 ; + onStatusChanged: { + if(status==Image.Ready) + image.state="loaded" + } + } + states: State { + name: "loaded"; + PropertyChanges { target: realImage ; opacity:1 } + } + transitions: Transition { NumberAnimation { target: realImage; property: "opacity"; duration: 200 } } + + } + Text { id:txt; y:4; x: 56 + text: '' + + ''+userName(name) + " from " +source + + "
" + statusText + ""; + textFormat: Text.StyledText + color: "#cccccc"; style: Text.Raised; styleColor: "black"; wrapMode: Text.WordWrap; linkColor: "#aaccaa" + anchors.left: image.right; anchors.right: blackRect.right; anchors.leftMargin: 6; anchors.rightMargin: 6 + onLinkActivated: wrapper.handleLink(link) + } + } + } + } diff --cc examples/demos/twitter/TwitterCore/Input.qml index 0000000,2987b9e..68b1c61 mode 000000,100644..100644 --- a/examples/demos/twitter/TwitterCore/Input.qml +++ b/examples/demos/twitter/TwitterCore/Input.qml @@@ -1,0 -1,65 +1,65 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + FocusScope { + id:container + width: 220 + height: 28 + BorderImage { source: "images/lineedit.sci"; anchors.fill: parent } + signal accepted + property alias text: input.text + property alias item:input + TextInput{ + id: input + width: parent.width - 12 + anchors.centerIn: parent + maximumLength:21 + font.pixelSize: 16; + font.bold: true + color: "#151515"; selectionColor: "mediumseagreen" + focus: true + onAccepted:{container.accepted()} + text: "" + selectByMouse: true + } + } diff --cc examples/demos/twitter/TwitterCore/Loading.qml index 0000000,8f7c868..566857b mode 000000,100644..100644 --- a/examples/demos/twitter/TwitterCore/Loading.qml +++ b/examples/demos/twitter/TwitterCore/Loading.qml @@@ -1,0 -1,49 +1,49 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Image { + id: loading; source: "images/loading.png" + NumberAnimation on rotation { + from: 0; to: 360; running: loading.visible == true; loops: Animation.Infinite; duration: 900 + } + } diff --cc examples/demos/twitter/TwitterCore/MultiTitleBar.qml index 0000000,f52ce5b..3920520 mode 000000,100644..100644 --- a/examples/demos/twitter/TwitterCore/MultiTitleBar.qml +++ b/examples/demos/twitter/TwitterCore/MultiTitleBar.qml @@@ -1,0 -1,60 +1,60 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Item { + TitleBar { id: titleBar; width: parent.width; height: 60; + y: -80 + untaggedString: "Latest tweets from everyone" + taggedString: "Latest tweets from " + } + states: [ + State { + name: "search"; when: screen.state!="search" + PropertyChanges { target: titleBar; y: 0 } + } + ] + transitions: [ + Transition { NumberAnimation { properties: "x,y"; duration: 500; easing.type: Easing.InOutQuad } } + ] + } + diff --cc examples/demos/twitter/TwitterCore/RssModel.qml index 0000000,c405099..27f7495 mode 000000,100644..100644 --- a/examples/demos/twitter/TwitterCore/RssModel.qml +++ b/examples/demos/twitter/TwitterCore/RssModel.qml @@@ -1,0 -1,80 +1,80 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + import QtQuick.XmlListModel 2.0 + + Item { id: wrapper + property variant model: xmlModel + property string from : "" + property string to : "" + property string phrase : "" + + property string mode : "everyone" + property int status: xmlModel.status + function reload() { xmlModel.reload(); } + + XmlListModel { + id: xmlModel + + function encodePhrase(x) { return encodeURIComponent(x); } + + source: (from=="" && to=="" && phrase=="") ? "" : + 'http://search.twitter.com/search.atom?from='+from+"&to="+to+"&phrase="+encodePhrase(phrase) + + namespaceDeclarations: "declare default element namespace 'http://www.w3.org/2005/Atom'; " + + "declare namespace twitter=\"http://api.twitter.com/\";"; + + query: "/feed/entry" + + XmlRole { name: "statusText"; query: "content/string()" } + XmlRole { name: "timestamp"; query: "published/string()" } + XmlRole { name: "source"; query: "twitter:source/string()" } + XmlRole { name: "name"; query: "author/name/string()" } + XmlRole { name: "userImage"; query: "link[@rel = 'image']/@href/string()" } + + } + Binding { + property: "mode" + target: wrapper + value: {if(wrapper.tags==''){"everyone";}else if(wrapper.tags=='my timeline'){"self";}else{"user";}} + } + } diff --cc examples/demos/twitter/TwitterCore/SearchView.qml index 0000000,82a8559..7732e6f mode 000000,100644..100644 --- a/examples/demos/twitter/TwitterCore/SearchView.qml +++ b/examples/demos/twitter/TwitterCore/SearchView.qml @@@ -1,0 -1,124 +1,124 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + FocusScope { + id: wrapper + Column { + anchors.centerIn: parent + spacing: 20 + Column{ + spacing: 4 + Text { + text: "Posted by:" + font.pixelSize: 16; font.bold: true; color: "white"; style: Text.Raised; styleColor: "black" + horizontalAlignment: Qt.AlignRight + } + Input{ + id: fromIn + KeyNavigation.backtab: searchbutton + KeyNavigation.tab:toIn + onAccepted:searchbutton.doSearch(); + focus: true + } + Text { + text: "In reply to:" + font.pixelSize: 16; font.bold: true; color: "white"; style: Text.Raised; styleColor: "black" + horizontalAlignment: Qt.AlignRight + } + Input{ + id: toIn + KeyNavigation.backtab: fromIn + KeyNavigation.tab:phraseIn + onAccepted:searchbutton.doSearch(); + } + Text { + text: "Search phrase:" + font.pixelSize: 16; font.bold: true; color: "white"; style: Text.Raised; styleColor: "black" + horizontalAlignment: Qt.AlignRight + } + Input{ + id: phraseIn + KeyNavigation.backtab: toIn + KeyNavigation.tab:searchbutton + onAccepted:searchbutton.doSearch(); + text: "Qt Quick" + } + } + Button { + width: 100 + height: 32 + id: searchbutton + keyUsing: true; + opacity: 1 + text: "Search" + KeyNavigation.tab: fromIn + Keys.onReturnPressed: searchbutton.doSearch(); + Keys.onEnterPressed: searchbutton.doSearch(); + Keys.onSelectPressed: searchbutton.doSearch(); + Keys.onSpacePressed: searchbutton.doSearch(); + onClicked: searchbutton.doSearch(); + + function doSearch() { + // Search ! allowed + if (wrapper.state=="invalidinput") + return; + + rssModel.from=fromIn.text; + rssModel.to= toIn.text; + rssModel.phrase = phraseIn.text; + screen.focus = true; + screen.state = "" + } + } + } + states: + State { + name: "invalidinput" + when: fromIn.text=="" && toIn.text=="" && phraseIn.text=="" + PropertyChanges { target: searchbutton ; opacity: 0.6 ; } + } + transitions: + Transition { + NumberAnimation { target: searchbutton; property: "opacity"; duration: 200 } + } + } diff --cc examples/demos/twitter/TwitterCore/TitleBar.qml index 0000000,3624048..3e0818b mode 000000,100644..100644 --- a/examples/demos/twitter/TwitterCore/TitleBar.qml +++ b/examples/demos/twitter/TwitterCore/TitleBar.qml @@@ -1,0 -1,130 +1,130 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Item { + id: titleBar + property string untaggedString: "Uploads from everyone" + property string taggedString: "Recent uploads tagged " + + BorderImage { source: "images/titlebar.sci"; width: parent.width; height: parent.height + 14; y: -7 } + + Item { + id: container + width: (parent.width * 2) - 55 ; height: parent.height + + function accept() { + titleBar.state = "" + background.state = "" + rssModel.tags = editor.text + } + + Item { + id:imageBox + x: 6; width: 0; height: 50; smooth: true + anchors.verticalCenter: parent.verticalCenter + + UserModel { user: rssModel.from; id: userModel } + Component { + id: imgDelegate; + Item { + id:imageitem + visible:true + Loading { width:48; height:48; visible: realImage.status != Image.Ready } + Image { id: realImage; source: image; width:48; height:48; opacity:0; } + states: + State { + name: "loaded" + when: (realImage.status == Image.Ready) + PropertyChanges { target: realImage; opacity:1 } + } + transitions: Transition { + NumberAnimation { target: realImage; property: "opacity"; duration: 200 } + } + } + } + ListView { id:view; model: userModel.model; x:1; y:1; delegate: imgDelegate } + states: + State { + when: !userModel.user=="" + PropertyChanges { target: imageBox; width: 50; } + } + transitions: + Transition { + NumberAnimation { target: imageBox; property: "width"; duration: 200 } + } + } + + Image { + id: quitButton + x: 5 + anchors.verticalCenter: parent.verticalCenter + source: "images/quit.png" + MouseArea { + anchors.fill: parent + onClicked: Qt.quit() + } + } + + Text { + id: categoryText + anchors { + left: quitButton.right; right: parent.right; leftMargin: 10; rightMargin: 10 + verticalCenter: parent.verticalCenter + } + elide: Text.ElideLeft + text: (rssModel.from=="" ? untaggedString : taggedString + rssModel.from) + font.bold: true; color: "White"; style: Text.Raised; styleColor: "Black" + font.pixelSize: 12 + } + } + + states: State { + name: "Tags" + PropertyChanges { target: container; x: -tagButton.x + 5 } + PropertyChanges { target: editor; focus: true } + } + + transitions: Transition { + NumberAnimation { properties: "x"; easing.type: Easing.InOutQuad } + } + } diff --cc examples/demos/twitter/TwitterCore/ToolBar.qml index 0000000,06d3324..d4265f3 mode 000000,100644..100644 --- a/examples/demos/twitter/TwitterCore/ToolBar.qml +++ b/examples/demos/twitter/TwitterCore/ToolBar.qml @@@ -1,0 -1,64 +1,64 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + + Item { + id: toolbar + + property alias button1Label: button1.text + property alias button2Label: button2.text + signal button1Clicked + signal button2Clicked + focus:true + BorderImage { source: "images/titlebar.sci"; width: parent.width; height: parent.height + 14; y: -7 } + Button { + id: button1 + anchors.left: parent.left; anchors.leftMargin: 5; y: 3; width: 140; height: 32 + onClicked: toolbar.button1Clicked() + focus:true + } + Button { + id: button2 + anchors.right: parent.right; anchors.rightMargin: 5; y: 3; width: 140; height: 32 + onClicked: toolbar.button2Clicked() + } + } diff --cc examples/demos/twitter/TwitterCore/UserModel.qml index 0000000,f88837c..428089b mode 000000,100644..100644 --- a/examples/demos/twitter/TwitterCore/UserModel.qml +++ b/examples/demos/twitter/TwitterCore/UserModel.qml @@@ -1,0 -1,66 +1,66 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + import QtQuick.XmlListModel 2.0 + + //This "model" gets the user information about the searched user. Mainly for the icon. + + Item { id: wrapper + property variant model: xmlModel + property string user : "" + property int status: xmlModel.status + function reload() { xmlModel.reload(); } + XmlListModel { + id: xmlModel + + source: user!= "" ? "http://twitter.com/users/show.xml?screen_name="+user : "" + query: "/user" + + XmlRole { name: "name"; query: "name/string()" } + XmlRole { name: "screenName"; query: "screen_name/string()" } + XmlRole { name: "image"; query: "profile_image_url/string()" } + XmlRole { name: "location"; query: "location/string()" } + XmlRole { name: "description"; query: "description/string()" } + XmlRole { name: "followers"; query: "followers_count/string()" } + //TODO: Could also get the user's color scheme, timezone and a few other things + } + } diff --cc examples/demos/twitter/twitter.qml index 0000000,26e4a70..aca0968 mode 000000,100644..100644 --- a/examples/demos/twitter/twitter.qml +++ b/examples/demos/twitter/twitter.qml @@@ -1,0 -1,135 +1,135 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + import QtQuick 2.0 + import QtQuick.XmlListModel 2.0 + import "TwitterCore" 2.0 as Twitter + + Item { + id: screen; width: 320; height: 480 + property bool userView : false + property variant tmpStr + function setUser(str){hack.running = true; tmpStr = str} + function reallySetUser(){rssModel.from = tmpStr;rssModel.to = ""; rssModel.phrase = ""} + state:"searchquery" + //Workaround for bug 260266 + Timer{ interval: 1; running: false; repeat: false; onTriggered: screen.reallySetUser(); id:hack } + Keys.onEscapePressed: screen.state="searchquery" + Keys.onBacktabPressed: screen.state="searchquery" + Rectangle { + id: background + anchors.fill: parent; color: "#343434"; + + state:"searchquery" + Image { source: "TwitterCore/images/stripes.png"; fillMode: Image.Tile; anchors.fill: parent; opacity: 0.3 } + + MouseArea { + anchors.fill: parent + onClicked: screen.focus = false; + } + + Twitter.RssModel { id: rssModel } + Twitter.Loading { anchors.centerIn: parent; visible: rssModel.status==XmlListModel.Loading && state!='unauthed'} + Text { + width: 180 + text: "Could not access twitter using this screen name and password pair."; + color: "#cccccc"; style: Text.Raised; styleColor: "black"; wrapMode: Text.WordWrap + visible: rssModel.status==XmlListModel.Error; anchors.centerIn: parent + } + + Item { + id: views + x: 2; width: parent.width - 4 + y:60 //Below the title bars + height: parent.height - 100 + + Text { + id:title + text: "Search Twitter" + anchors.horizontalCenter: parent.horizontalCenter + font.pixelSize: 20; font.bold: true; color: "#bbb"; style: Text.Raised; styleColor: "black" + opacity:0 + } + + Twitter.SearchView{ + id: searchView + anchors.verticalCenter: parent.verticalCenter + width: parent.width; height: parent.height-60; + x: -(screen.width * 1.5) + } + + Twitter.FatDelegate { id: fatDelegate } + ListView { + id: mainView; model: rssModel.model; delegate: fatDelegate; + width: parent.width; height: parent.height; x: 0; cacheBuffer: 100; + } + } + + Twitter.MultiTitleBar { id: titleBar; width: parent.width } + Twitter.ToolBar { id: toolBar; height: 40; + //anchors.bottom: parent.bottom; + //TODO: Use anchor changes instead of hard coding + y: screen.height - 40 + width: parent.width; opacity: 0.9 + button1Label: "New Search" + button2Label: "Update" + onButton1Clicked: + { + screen.state="searchquery" + } + onButton2Clicked: rssModel.reload(); + } + } + states: [ + State { + name: "searchquery"; + PropertyChanges { target: searchView; x: 0; focus:true} + PropertyChanges { target: mainView; x: -(parent.width * 1.5) } + PropertyChanges { target: titleBar; y: -80 } + PropertyChanges { target: toolBar; y: screen.height } + PropertyChanges { target: toolBar } + PropertyChanges { target: title; opacity:1} + } + ] + transitions: [ + Transition { NumberAnimation { properties: "x,y,opacity"; duration: 500; easing.type: Easing.InOutQuad } } + ] + } diff --cc examples/examples.pro index 3e5c4d0,2b78ed7..d3d2f55 --- a/examples/examples.pro +++ b/examples/examples.pro @@@ -1,3 -1,3 +1,3 @@@ TEMPLATE = subdirs - SUBDIRS += qml tutorials -SUBDIRS += demos shared localstorage particles qml qtquick tutorials window ++SUBDIRS += demos shared localstorage particles qml quick tutorials window contains(QT_CONFIG, qmltest): SUBDIRS += qmltest diff --cc examples/qml/cppextensions/imageprovider/imageprovider.cpp index 506d5b0,7fe4b72..f6632a8 --- a/examples/qml/cppextensions/imageprovider/imageprovider.cpp +++ b/examples/qml/cppextensions/imageprovider/imageprovider.cpp @@@ -84,9 -84,10 +84,10 @@@ public //![1] -class ImageProviderExtensionPlugin : public QDeclarativeExtensionPlugin +class ImageProviderExtensionPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDeclarativeExtensionInterface" FILE "imageprovider.json") ++ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "imageprovider.json") public: void registerTypes(const char *uri) { @@@ -101,7 -102,8 +102,8 @@@ }; - #include "imageprovider.moc" - Q_EXPORT_PLUGIN(ImageProviderExtensionPlugin); -#define QDeclarativeExtensionInterface_iid "org.qt-project.Qt.QDeclarativeExtensionInterface" ++#define QQmlExtensionInterface_iid "org.qt-project.Qt.QQmlExtensionInterface" + + #include "imageprovider.moc" diff --cc examples/qml/cppextensions/imageprovider/imageprovider.pro index f75a6eb,dd128d5..b4a832b --- a/examples/qml/cppextensions/imageprovider/imageprovider.pro +++ b/examples/qml/cppextensions/imageprovider/imageprovider.pro @@@ -7,10 -7,12 +7,12 @@@ TARGET = qmlimageproviderplugi SOURCES += imageprovider.cpp + OTHER_FILES += imageprovider.json + sources.files = $$SOURCES imageprovider.qml imageprovider.pro -sources.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/declarative/imageprovider +sources.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/imageprovider -target.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/declarative/imageprovider/ImageProviderCore +target.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/imageprovider/ImageProviderCore ImageProviderCore_sources.files = \ ImageProviderCore/qmldir diff --cc examples/qml/cppextensions/plugins/plugin.cpp index b53ef2c,4ba0a92..5e9900c --- a/examples/qml/cppextensions/plugins/plugin.cpp +++ b/examples/qml/cppextensions/plugins/plugin.cpp @@@ -138,9 -138,11 +138,11 @@@ int TimeModel::instances=0 MinuteTimer *TimeModel::timer=0; //![plugin] -class QExampleQmlPlugin : public QDeclarativeExtensionPlugin +class QExampleQmlPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDeclarativeExtensionInterface" FILE "plugin.json") ++ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "plugin.json") + public: void registerTypes(const char *uri) { diff --cc examples/qml/cppextensions/plugins/plugins.pro index e6c7fe6,a28582a..08a4d1a --- a/examples/qml/cppextensions/plugins/plugins.pro +++ b/examples/qml/cppextensions/plugins/plugins.pro @@@ -15,11 -17,11 +17,11 @@@ qdeclarativesources.files += com/nokia/TimeExample/hour.png \ com/nokia/TimeExample/minute.png - qqmlsources.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/plugins/com/nokia/TimeExample -qdeclarativesources.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/declarative/plugins/com/nokia/TimeExample ++qdeclarativesources.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/plugins/com/nokia/TimeExample sources.files += plugins.pro plugin.cpp plugins.qml README -sources.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/declarative/plugins -target.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/declarative/plugins/com/nokia/TimeExample +sources.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/plugins +target.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/plugins/com/nokia/TimeExample - INSTALLS += qqmlsources sources target + INSTALLS += qdeclarativesources sources target diff --cc examples/qml/cppextensions/referenceexamples/attached/birthdayparty.cpp index 6b784fd,feefef4..c4f9061 --- a/examples/qml/cppextensions/referenceexamples/attached/birthdayparty.cpp +++ b/examples/qml/cppextensions/referenceexamples/attached/birthdayparty.cpp @@@ -69,9 -69,9 +69,9 @@@ void BirthdayParty::setHost(Person *c m_host = c; } - QQmlListProperty BirthdayParty::guests() -QDeclarativeListProperty BirthdayParty::guests() ++QQmlListProperty BirthdayParty::guests() { - return QDeclarativeListProperty(this, m_guests); + return QQmlListProperty(this, m_guests); } int BirthdayParty::guestCount() const diff --cc examples/qml/cppextensions/referenceexamples/binding/birthdayparty.cpp index 9a38c3b,4f5acdf..6249986 --- a/examples/qml/cppextensions/referenceexamples/binding/birthdayparty.cpp +++ b/examples/qml/cppextensions/referenceexamples/binding/birthdayparty.cpp @@@ -75,9 -75,9 +75,9 @@@ void BirthdayParty::setHost(Person *c emit hostChanged(); } - QQmlListProperty BirthdayParty::guests() -QDeclarativeListProperty BirthdayParty::guests() ++QQmlListProperty BirthdayParty::guests() { - return QDeclarativeListProperty(this, m_guests); + return QQmlListProperty(this, m_guests); } int BirthdayParty::guestCount() const diff --cc examples/qml/cppextensions/referenceexamples/coercion/birthdayparty.cpp index d697ac2,1859ca9..e15ffe1 --- a/examples/qml/cppextensions/referenceexamples/coercion/birthdayparty.cpp +++ b/examples/qml/cppextensions/referenceexamples/coercion/birthdayparty.cpp @@@ -54,9 -54,9 +54,9 @@@ void BirthdayParty::setHost(Person *c m_host = c; } - QQmlListProperty BirthdayParty::guests() -QDeclarativeListProperty BirthdayParty::guests() ++QQmlListProperty BirthdayParty::guests() { - return QDeclarativeListProperty(this, m_guests); + return QQmlListProperty(this, m_guests); } int BirthdayParty::guestCount() const diff --cc examples/qml/cppextensions/referenceexamples/default/birthdayparty.cpp index d697ac2,1859ca9..e15ffe1 --- a/examples/qml/cppextensions/referenceexamples/default/birthdayparty.cpp +++ b/examples/qml/cppextensions/referenceexamples/default/birthdayparty.cpp @@@ -54,9 -54,9 +54,9 @@@ void BirthdayParty::setHost(Person *c m_host = c; } - QQmlListProperty BirthdayParty::guests() -QDeclarativeListProperty BirthdayParty::guests() ++QQmlListProperty BirthdayParty::guests() { - return QDeclarativeListProperty(this, m_guests); + return QQmlListProperty(this, m_guests); } int BirthdayParty::guestCount() const diff --cc examples/qml/cppextensions/referenceexamples/grouped/birthdayparty.cpp index d697ac2,1859ca9..e15ffe1 --- a/examples/qml/cppextensions/referenceexamples/grouped/birthdayparty.cpp +++ b/examples/qml/cppextensions/referenceexamples/grouped/birthdayparty.cpp @@@ -54,9 -54,9 +54,9 @@@ void BirthdayParty::setHost(Person *c m_host = c; } - QQmlListProperty BirthdayParty::guests() -QDeclarativeListProperty BirthdayParty::guests() ++QQmlListProperty BirthdayParty::guests() { - return QDeclarativeListProperty(this, m_guests); + return QQmlListProperty(this, m_guests); } int BirthdayParty::guestCount() const diff --cc examples/qml/cppextensions/referenceexamples/methods/birthdayparty.cpp index 0935d70,35444f5..c96f41d --- a/examples/qml/cppextensions/referenceexamples/methods/birthdayparty.cpp +++ b/examples/qml/cppextensions/referenceexamples/methods/birthdayparty.cpp @@@ -55,9 -55,9 +55,9 @@@ void BirthdayParty::setHost(Person *c m_host = c; } - QQmlListProperty BirthdayParty::guests() -QDeclarativeListProperty BirthdayParty::guests() ++QQmlListProperty BirthdayParty::guests() { - return QDeclarativeListProperty(this, m_guests); + return QQmlListProperty(this, m_guests); } int BirthdayParty::guestCount() const diff --cc examples/qml/cppextensions/referenceexamples/properties/birthdayparty.cpp index f728056,0038cd0..8e79d07 --- a/examples/qml/cppextensions/referenceexamples/properties/birthdayparty.cpp +++ b/examples/qml/cppextensions/referenceexamples/properties/birthdayparty.cpp @@@ -55,9 -55,9 +55,9 @@@ void BirthdayParty::setHost(Person *c m_host = c; } - QQmlListProperty BirthdayParty::guests() -QDeclarativeListProperty BirthdayParty::guests() ++QQmlListProperty BirthdayParty::guests() { - return QDeclarativeListProperty(this, m_guests); + return QQmlListProperty(this, m_guests); } int BirthdayParty::guestCount() const diff --cc examples/qml/cppextensions/referenceexamples/signal/birthdayparty.cpp index 078c5f9,d576c2a..b9f7e15 --- a/examples/qml/cppextensions/referenceexamples/signal/birthdayparty.cpp +++ b/examples/qml/cppextensions/referenceexamples/signal/birthdayparty.cpp @@@ -70,9 -70,9 +70,9 @@@ void BirthdayParty::setHost(Person *c m_host = c; } - QQmlListProperty BirthdayParty::guests() -QDeclarativeListProperty BirthdayParty::guests() ++QQmlListProperty BirthdayParty::guests() { - return QDeclarativeListProperty(this, m_guests); + return QQmlListProperty(this, m_guests); } int BirthdayParty::guestCount() const diff --cc examples/qml/cppextensions/referenceexamples/valuesource/birthdayparty.cpp index a69a585,09137c4..aa8bc77 --- a/examples/qml/cppextensions/referenceexamples/valuesource/birthdayparty.cpp +++ b/examples/qml/cppextensions/referenceexamples/valuesource/birthdayparty.cpp @@@ -70,9 -70,9 +70,9 @@@ void BirthdayParty::setHost(Person *c m_host = c; } - QQmlListProperty BirthdayParty::guests() -QDeclarativeListProperty BirthdayParty::guests() ++QQmlListProperty BirthdayParty::guests() { - return QDeclarativeListProperty(this, m_guests); + return QQmlListProperty(this, m_guests); } int BirthdayParty::guestCount() const diff --cc examples/quick/accessibility/accessibility.pro index 0000000,0000000..2826161 new file mode 100644 --- /dev/null +++ b/examples/quick/accessibility/accessibility.pro @@@ -1,0 -1,0 +1,10 @@@ ++TEMPLATE = app ++ ++QT += quick qml ++SOURCES += main.cpp ++ ++target.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qtquick/accessibility ++qml.files = accessibility.qml content ++qml.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qtquick/accessibility ++INSTALLS += target qml ++ diff --cc examples/quick/accessibility/accessibility.qml index 0000000,0000000..2804d2a new file mode 100644 --- /dev/null +++ b/examples/quick/accessibility/accessibility.qml @@@ -1,0 -1,0 +1,110 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the QtQml module of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL$ ++** GNU Lesser General Public License Usage ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** ++** ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++import "content" ++ ++/*! ++ \title QtQuick Examples - Accessibility ++ \example qtquick/accessibility ++ \brief This example has accessible buttons. ++ ++*/ ++ ++Rectangle { ++ id: window ++ ++ width: 320; height: 480 ++ color: "white" ++ ++ Column { ++ id: column ++ spacing: 6 ++ anchors.fill: parent ++ width: parent.width ++ Row { ++ spacing: 6 ++ width: column.width ++ Button { width: 100; height: column.h + 20; text: "Send" } ++ Button { width: 100; height: column.h + 20; text: "Discard" } ++ } ++ ++ Row { ++ spacing: 6 ++ width: column.width ++ height: column.h ++ Text { ++ id: subjectLabel ++ Accessible.role: Accessible.StaticText ++ Accessible.name: text ++ text: "Subject:" ++ } ++ Rectangle { ++ id: subjectBorder ++ Accessible.role: Accessible.EditableText ++ Accessible.name: subjectEdit.text ++ border.width: 1 ++ border.color: "black" ++ height: subjectEdit.height ++ width: 240 ++ TextInput { ++ id: subjectEdit ++ text: "Vacation plans" ++ } ++ } ++ } ++ Rectangle { ++ id: textBorder ++ Accessible.role: Accessible.EditableText ++ property alias text : textEdit.text ++ border.width: 1 ++ border.color: "black" ++ width: parent.width - 2 ++ height: parent.height - (textBorder.y + column.spacing) ++ TextEdit { ++ id: textEdit ++ text: "Hi, we're going to the Dolomites this summer. Weren't you also going to northern Italy? \n\nbest wishes, your friend Luke" ++ width: parent.width ++ wrapMode: TextEdit.WordWrap ++ } ++ } ++ } ++} diff --cc examples/quick/accessibility/accessibility.qmlproject index 0000000,04a3190..04a3190 mode 000000,100644..100644 --- a/examples/quick/accessibility/accessibility.qmlproject +++ b/examples/quick/accessibility/accessibility.qmlproject diff --cc examples/quick/accessibility/content/Button.qml index 0000000,0000000..2c203ab new file mode 100644 --- /dev/null +++ b/examples/quick/accessibility/content/Button.qml @@@ -1,0 -1,0 +1,80 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the QtQml module of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL$ ++** GNU Lesser General Public License Usage ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** ++** ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Rectangle { ++ id: button ++ ++ property bool checked: false ++ property alias text : buttonText.text ++ Accessible.name: text ++ Accessible.description: "This button does " + text ++ Accessible.role: Accessible.Button ++ ++ signal clicked ++ ++ width: buttonText.width + 20 ++ height: 30 ++ gradient: Gradient { ++ GradientStop { position: 0.0; color: "lightsteelblue" } ++ GradientStop { position: 1.0; color: "blue" } ++ } ++ border.width: 2 ++ border.color: "black"; ++ radius: 10 ++ ++ Text { ++ id: buttonText ++ text: parent.description ++ anchors.centerIn: parent ++ font.pixelSize: parent.height * .5 ++ style: Text.Sunken; color: "white"; styleColor: "black"; smooth: true ++ } ++ ++ MouseArea { ++ id: mouseArea ++ anchors.fill: parent ++ onClicked: { ++ checked = !checked; ++ } ++ } ++} diff --cc examples/quick/accessibility/main.cpp index 0000000,89e23b4..89e23b4 mode 000000,100644..100644 --- a/examples/quick/accessibility/main.cpp +++ b/examples/quick/accessibility/main.cpp diff --cc examples/quick/animation/animation.pro index 0000000,0000000..cdf83f8 new file mode 100644 --- /dev/null +++ b/examples/quick/animation/animation.pro @@@ -1,0 -1,0 +1,10 @@@ ++TEMPLATE = app ++ ++QT += quick qml ++SOURCES += main.cpp ++ ++target.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qtquick/animation ++qml.files = animation.qml basics behaviors easing pathanimation pathinterpolator states ++qml.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qtquick/animation ++INSTALLS += target qml ++ diff --cc examples/quick/animation/animation.qml index 0000000,bca6845..bca6845 mode 000000,100644..100644 --- a/examples/quick/animation/animation.qml +++ b/examples/quick/animation/animation.qml diff --cc examples/quick/animation/animation.qmlproject index 0000000,0000000..2e96daa new file mode 100644 --- /dev/null +++ b/examples/quick/animation/animation.qmlproject @@@ -1,0 -1,0 +1,16 @@@ ++import QmlProject 1.1 ++ ++Project { ++ mainFile: "animation.qml" ++ ++ /* Include .qml, .js, and image files from current directory and subdirectories */ ++ QmlFiles { ++ directory: "." ++ } ++ JavaScriptFiles { ++ directory: "." ++ } ++ ImageFiles { ++ directory: "." ++ } ++} diff --cc examples/quick/animation/basics/color-animation.qml index 0000000,f1bf40c..f1bf40c mode 000000,100644..100644 --- a/examples/quick/animation/basics/color-animation.qml +++ b/examples/quick/animation/basics/color-animation.qml diff --cc examples/quick/animation/basics/images/face-smile.png index 0000000,0000000..3d66d72 new file mode 100644 Binary files differ diff --cc examples/quick/animation/basics/images/moon.png index 0000000,0000000..9407b2b new file mode 100644 Binary files differ diff --cc examples/quick/animation/basics/images/shadow.png index 0000000,0000000..8270565 new file mode 100644 Binary files differ diff --cc examples/quick/animation/basics/images/star.png index 0000000,0000000..27ef924 new file mode 100644 Binary files differ diff --cc examples/quick/animation/basics/images/sun.png index 0000000,0000000..7713ca5 new file mode 100644 Binary files differ diff --cc examples/quick/animation/basics/property-animation.qml index 0000000,0000000..4a4d3e3 new file mode 100644 --- /dev/null +++ b/examples/quick/animation/basics/property-animation.qml @@@ -1,0 -1,0 +1,105 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Item { ++ id: window ++ width: 320; height: 480 ++ ++ // Let's draw the sky... ++ Rectangle { ++ anchors { left: parent.left; top: parent.top; right: parent.right; bottom: parent.verticalCenter } ++ gradient: Gradient { ++ GradientStop { position: 0.0; color: "DeepSkyBlue" } ++ GradientStop { position: 1.0; color: "LightSkyBlue" } ++ } ++ } ++ ++ // ...and the ground. ++ Rectangle { ++ anchors { left: parent.left; top: parent.verticalCenter; right: parent.right; bottom: parent.bottom } ++ gradient: Gradient { ++ GradientStop { position: 0.0; color: "ForestGreen" } ++ GradientStop { position: 1.0; color: "DarkGreen" } ++ } ++ } ++ ++ // The shadow for the smiley face ++ Image { ++ anchors.horizontalCenter: parent.horizontalCenter ++ y: smiley.minHeight + 58 ++ source: "images/shadow.png" ++ ++ // The scale property depends on the y position of the smiley face. ++ scale: smiley.y * 0.5 / (smiley.minHeight - smiley.maxHeight) ++ } ++ ++ Image { ++ id: smiley ++ property int maxHeight: window.height / 3 ++ property int minHeight: 2 * window.height / 3 ++ ++ anchors.horizontalCenter: parent.horizontalCenter ++ y: minHeight ++ source: "images/face-smile.png" ++ ++ // Animate the y property. Setting loops to Animation.Infinite makes the ++ // animation repeat indefinitely, otherwise it would only run once. ++ SequentialAnimation on y { ++ loops: Animation.Infinite ++ ++ // Move from minHeight to maxHeight in 300ms, using the OutExpo easing function ++ NumberAnimation { ++ from: smiley.minHeight; to: smiley.maxHeight ++ easing.type: Easing.OutExpo; duration: 300 ++ } ++ ++ // Then move back to minHeight in 1 second, using the OutBounce easing function ++ NumberAnimation { ++ from: smiley.maxHeight; to: smiley.minHeight ++ easing.type: Easing.OutBounce; duration: 1000 ++ } ++ ++ // Then pause for 500ms ++ PauseAnimation { duration: 500 } ++ } ++ } ++} diff --cc examples/quick/animation/behaviors/SideRect.qml index 0000000,0000000..623c696 new file mode 100644 --- /dev/null +++ b/examples/quick/animation/behaviors/SideRect.qml @@@ -1,0 -1,0 +1,62 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Rectangle { ++ id: myRect ++ ++ property string text ++ ++ width: 75; height: 50 ++ radius: 6 ++ color: "#646464" ++ border.width: 4; border.color: "white" ++ ++ MouseArea { ++ anchors.fill: parent ++ hoverEnabled: true ++ onEntered: { ++ focusRect.x = myRect.x; ++ focusRect.y = myRect.y; ++ focusRect.text = myRect.text; ++ } ++ } ++} diff --cc examples/quick/animation/behaviors/behavior-example.qml index 0000000,a88d7c8..a88d7c8 mode 000000,100644..100644 --- a/examples/quick/animation/behaviors/behavior-example.qml +++ b/examples/quick/animation/behaviors/behavior-example.qml diff --cc examples/quick/animation/behaviors/tvtennis.qml index 0000000,108f19a..108f19a mode 000000,100644..100644 --- a/examples/quick/animation/behaviors/tvtennis.qml +++ b/examples/quick/animation/behaviors/tvtennis.qml diff --cc examples/quick/animation/behaviors/wigglytext.qml index 0000000,4bb94da..4bb94da mode 000000,100644..100644 --- a/examples/quick/animation/behaviors/wigglytext.qml +++ b/examples/quick/animation/behaviors/wigglytext.qml diff --cc examples/quick/animation/easing/content/QuitButton.qml index 0000000,0000000..702b892 new file mode 100644 --- /dev/null +++ b/examples/quick/animation/easing/content/QuitButton.qml @@@ -1,0 -1,0 +1,52 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++Image { ++ source: "quit.png" ++ scale: quitMouse.pressed ? 0.8 : 1.0 ++ smooth: quitMouse.pressed ++ MouseArea { ++ id: quitMouse ++ anchors.fill: parent ++ anchors.margins: -10 ++ onClicked: Qt.quit() ++ } ++} diff --cc examples/quick/animation/easing/content/quit.png index 0000000,0000000..b822057 new file mode 100644 Binary files differ diff --cc examples/quick/animation/easing/easing.qml index 0000000,8977029..8977029 mode 000000,100644..100644 --- a/examples/quick/animation/easing/easing.qml +++ b/examples/quick/animation/easing/easing.qml diff --cc examples/quick/animation/main.cpp index 0000000,799dfd7..799dfd7 mode 000000,100644..100644 --- a/examples/quick/animation/main.cpp +++ b/examples/quick/animation/main.cpp diff --cc examples/quick/animation/pathanimation/pathanimation.qml index 0000000,f995218..f995218 mode 000000,100644..100644 --- a/examples/quick/animation/pathanimation/pathanimation.qml +++ b/examples/quick/animation/pathanimation/pathanimation.qml diff --cc examples/quick/animation/pathinterpolator/pathinterpolator.qml index 0000000,5a137c7..5a137c7 mode 000000,100644..100644 --- a/examples/quick/animation/pathinterpolator/pathinterpolator.qml +++ b/examples/quick/animation/pathinterpolator/pathinterpolator.qml diff --cc examples/quick/animation/states/qt-logo.png index 0000000,14ddf2a..14ddf2a mode 000000,100644..100644 Binary files differ diff --cc examples/quick/animation/states/states.qml index 0000000,0000000..7ca56a9 new file mode 100644 --- /dev/null +++ b/examples/quick/animation/states/states.qml @@@ -1,0 -1,0 +1,101 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Rectangle { ++ id: page ++ width: 640; height: 480 ++ color: "#343434" ++ ++ Image { ++ id: userIcon ++ x: topLeftRect.x; y: topLeftRect.y ++ source: "qt-logo.png" ++ } ++ ++ Rectangle { ++ id: topLeftRect ++ ++ anchors { left: parent.left; top: parent.top; leftMargin: 10; topMargin: 20 } ++ width: 46; height: 54 ++ color: "Transparent"; border.color: "Gray"; radius: 6 ++ ++ // Clicking in here sets the state to the default state, returning the image to ++ // its initial position ++ MouseArea { anchors.fill: parent; onClicked: page.state = '' } ++ } ++ ++ Rectangle { ++ id: middleRightRect ++ ++ anchors { right: parent.right; verticalCenter: parent.verticalCenter; rightMargin: 20 } ++ width: 46; height: 54 ++ color: "Transparent"; border.color: "Gray"; radius: 6 ++ ++ // Clicking in here sets the state to 'middleRight' ++ MouseArea { anchors.fill: parent; onClicked: page.state = 'middleRight' } ++ } ++ ++ Rectangle { ++ id: bottomLeftRect ++ ++ anchors { left: parent.left; bottom: parent.bottom; leftMargin: 10; bottomMargin: 20 } ++ width: 46; height: 54 ++ color: "Transparent"; border.color: "Gray"; radius: 6 ++ ++ // Clicking in here sets the state to 'bottomLeft' ++ MouseArea { anchors.fill: parent; onClicked: page.state = 'bottomLeft' } ++ } ++ ++ states: [ ++ // In state 'middleRight', move the image to middleRightRect ++ State { ++ name: "middleRight" ++ PropertyChanges { target: userIcon; x: middleRightRect.x; y: middleRightRect.y } ++ }, ++ ++ // In state 'bottomLeft', move the image to bottomLeftRect ++ State { ++ name: "bottomLeft" ++ PropertyChanges { target: userIcon; x: bottomLeftRect.x; y: bottomLeftRect.y } ++ } ++ ] ++} diff --cc examples/quick/animation/states/transitions.qml index 0000000,0000000..d57924d new file mode 100644 --- /dev/null +++ b/examples/quick/animation/states/transitions.qml @@@ -1,0 -1,0 +1,130 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++/* ++ This is exactly the same as states.qml, except that we have appended ++ a set of transitions to apply animations when the item changes ++ between each state. ++*/ ++ ++Rectangle { ++ id: page ++ width: 640; height: 480 ++ color: "#343434" ++ ++ Image { ++ id: userIcon ++ x: topLeftRect.x; y: topLeftRect.y ++ source: "qt-logo.png" ++ } ++ ++ Rectangle { ++ id: topLeftRect ++ ++ anchors { left: parent.left; top: parent.top; leftMargin: 10; topMargin: 20 } ++ width: 46; height: 54 ++ color: "Transparent"; border.color: "Gray"; radius: 6 ++ ++ // Clicking in here sets the state to the default state, returning the image to ++ // its initial position ++ MouseArea { anchors.fill: parent; onClicked: page.state = '' } ++ } ++ ++ Rectangle { ++ id: middleRightRect ++ ++ anchors { right: parent.right; verticalCenter: parent.verticalCenter; rightMargin: 20 } ++ width: 46; height: 54 ++ color: "Transparent"; border.color: "Gray"; radius: 6 ++ ++ // Clicking in here sets the state to 'middleRight' ++ MouseArea { anchors.fill: parent; onClicked: page.state = 'middleRight' } ++ } ++ ++ Rectangle { ++ id: bottomLeftRect ++ ++ anchors { left: parent.left; bottom: parent.bottom; leftMargin: 10; bottomMargin: 20 } ++ width: 46; height: 54 ++ color: "Transparent"; border.color: "Gray"; radius: 6 ++ ++ // Clicking in here sets the state to 'bottomLeft' ++ MouseArea { anchors.fill: parent; onClicked: page.state = 'bottomLeft' } ++ } ++ ++ states: [ ++ // In state 'middleRight', move the image to middleRightRect ++ State { ++ name: "middleRight" ++ PropertyChanges { target: userIcon; x: middleRightRect.x; y: middleRightRect.y } ++ }, ++ ++ // In state 'bottomLeft', move the image to bottomLeftRect ++ State { ++ name: "bottomLeft" ++ PropertyChanges { target: userIcon; x: bottomLeftRect.x; y: bottomLeftRect.y } ++ } ++ ] ++ ++ // Transitions define how the properties change when the item moves between each state ++ transitions: [ ++ ++ // When transitioning to 'middleRight' move x,y over a duration of 1 second, ++ // with OutBounce easing function. ++ Transition { ++ from: "*"; to: "middleRight" ++ NumberAnimation { properties: "x,y"; easing.type: Easing.OutBounce; duration: 1000 } ++ }, ++ ++ // When transitioning to 'bottomLeft' move x,y over a duration of 2 seconds, ++ // with InOutQuad easing function. ++ Transition { ++ from: "*"; to: "bottomLeft" ++ NumberAnimation { properties: "x,y"; easing.type: Easing.InOutQuad; duration: 2000 } ++ }, ++ ++ // For any other state changes move x,y linearly over duration of 200ms. ++ Transition { ++ NumberAnimation { properties: "x,y"; duration: 200 } ++ } ++ ] ++} diff --cc examples/quick/canvas/bezierCurve/bezierCurve.qml index 0000000,0000000..f57839b new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/bezierCurve/bezierCurve.qml @@@ -1,0 -1,0 +1,124 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++import "../contents" ++Item { ++ id:container ++ width:360 ++ height:600 ++ ++ Column { ++ spacing:5 ++ anchors.fill:parent ++ Text { font.pointSize:25; text:"Bezier Curve"; anchors.horizontalCenter:parent.horizontalCenter} ++ ++ Canvas { ++ id:canvas ++ width:360 ++ height:360 ++ property string strokeStyle:"red" ++ property string fillStyle:"red" ++ property int lineWidth:lineWidthCtrl.value ++ property bool fill:true ++ property bool stroke:true ++ property real alpha:alphaCtrl.value ++ property real scaleX : scaleXCtrl.value ++ property real scaleY : scaleYCtrl.value ++ property real rotate : rotateCtrl.value ++ smooth:true ++ renderTarget:Canvas.Image ++ renderStrategy: Canvas.Immediate ++ ++ ++ Behavior on scaleX { SpringAnimation { spring: 2; damping: 0.2; loops:Animation.Infinite } } ++ Behavior on scaleY { SpringAnimation { spring: 2; damping: 0.2; loops:Animation.Infinite} } ++ Behavior on rotate { SpringAnimation { spring: 2; damping: 0.2; loops:Animation.Infinite} } ++ ++ onLineWidthChanged:requestPaint(); ++ onFillChanged:requestPaint(); ++ onStrokeChanged:requestPaint(); ++ onAlphaChanged:requestPaint(); ++ onScaleXChanged:requestPaint(); ++ onScaleYChanged:requestPaint(); ++ onRotateChanged:requestPaint(); ++ ++ onPaint: { ++ var ctx = canvas.getContext('2d'); ++ ctx.save(); ++ ctx.clearRect(0, 0, canvas.width, canvas.height); ++ ctx.globalAlpha = canvas.alpha; ++ ctx.strokeStyle = canvas.strokeStyle; ++ ctx.fillStyle = canvas.fillStyle; ++ ctx.lineWidth = canvas.lineWidth; ++ ctx.scale(canvas.scaleX, canvas.scaleY); ++ ctx.rotate(canvas.rotate); ++ ctx.beginPath(); ++ ctx.moveTo(75,40); ++ ctx.bezierCurveTo(75,37,70,25,50,25); ++ ctx.bezierCurveTo(20,25,20,62.5,20,62.5); ++ ctx.bezierCurveTo(20,80,40,102,75,120); ++ ctx.bezierCurveTo(110,102,130,80,130,62.5); ++ ctx.bezierCurveTo(130,62.5,130,25,100,25); ++ ctx.bezierCurveTo(85,25,75,37,75,40); ++ ctx.closePath(); ++ if (canvas.fill) ++ ctx.fill(); ++ if (canvas.stroke) ++ ctx.stroke(); ++ ctx.restore(); ++ } ++ } ++ ++ Rectangle { ++ id:controls ++ width:360 ++ height:160 ++ Column { ++ spacing:3 ++ Slider {id:lineWidthCtrl; width:300; height:30; min:1; max:10; init:2; name:"Line width"} ++ Slider {id:scaleXCtrl; width:300; height:30; min:0.1; max:10; init:1; name:"ScaleX"} ++ Slider {id:scaleYCtrl; width:300; height:30; min:0.1; max:10; init:1; name:"ScaleY"} ++ Slider {id:rotateCtrl; width:300; height:30; min:0; max:Math.PI*2; init:0; name:"Rotate"} ++ Slider {id:alphaCtrl; width:300; height:30; min:0; max:1; init:1; name:"Alpha"} ++ } ++ } ++ } ++} diff --cc examples/quick/canvas/clip/clip.qml index 0000000,0000000..d861ff0 new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/clip/clip.qml @@@ -1,0 -1,0 +1,150 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++import "../contents" ++Item { ++ id:container ++ width:360 ++ height:600 ++ ++ Column { ++ spacing:5 ++ anchors.fill:parent ++ Text { font.pointSize:25; text:"Makes squircle icon with clip"; anchors.horizontalCenter:parent.horizontalCenter} ++ Canvas { ++ id:canvas ++ width:360 ++ height:360 ++ property string strokeStyle:"blue" ++ property string fillStyle:"steelblue" ++ property int lineWidth:2 ++ property int nSize:nCtrl.value ++ property real radius:rCtrl.value ++ property bool fill:true ++ property bool stroke:false ++ property real px:xCtrl.value ++ property real py:yCtrl.value ++ property real alpha:alphaCtrl.value ++ property string imagefile:"../contents/qt-logo.png" ++ smooth:true ++ renderTarget:Canvas.Image ++ renderStrategy: Canvas.Immediate ++ Component.onCompleted:loadImage(canvas.imagefile); ++ ++ onAlphaChanged:requestPaint(); ++ onRadiusChanged:requestPaint(); ++ onLineWidthChanged:requestPaint(); ++ onNSizeChanged:requestPaint(); ++ onFillChanged:requestPaint(); ++ onStrokeChanged:requestPaint(); ++ onPxChanged:requestPaint(); ++ onPyChanged:requestPaint(); ++ ++ onImageLoaded : requestPaint(); ++ ++ onPaint: squcirle(); ++ ++ function squcirle() { ++ var ctx = canvas.getContext("2d"); ++ var N = canvas.nSize; ++ var R = canvas.radius; ++ ++ N=Math.abs(N); ++ var M=N; ++ if (N>100) M=100; ++ if (N<0.00000000001) M=0.00000000001; ++ ++ ctx.save(); ++ ctx.globalAlpha =canvas.alpha; ++ ctx.fillStyle = "gray"; ++ ctx.fillRect(0, 0, canvas.width, canvas.height); ++ ++ ctx.strokeStyle = canvas.strokeStyle; ++ ctx.fillStyle = canvas.fillStyle; ++ ctx.lineWidth = canvas.lineWidth; ++ ++ ctx.beginPath(); ++ var i = 0, x, y; ++ for (i=0; i<(2*R+1); i++){ ++ x = Math.round(i-R) + canvas.px; ++ y = Math.round(Math.pow(Math.abs(Math.pow(R,M)-Math.pow(Math.abs(i-R),M)),1/M)) + canvas.py; ++ ++ if (i == 0) ++ ctx.moveTo(x, y); ++ else ++ ctx.lineTo(x, y); ++ } ++ ++ for (i=(2*R); i<(4*R+1); i++){ ++ x =Math.round(3*R-i)+canvas.px; ++ y = Math.round(-Math.pow(Math.abs(Math.pow(R,M)-Math.pow(Math.abs(3*R-i),M)),1/M)) + canvas.py; ++ ctx.lineTo(x, y); ++ } ++ ctx.closePath(); ++ if (canvas.stroke) { ++ ctx.stroke(); ++ } ++ ++ if (canvas.fill) { ++ ctx.fill(); ++ } ++ ctx.clip(); ++ ++ ctx.drawImage(canvas.imagefile, 0, 0); ++ ctx.restore(); ++ } ++ } ++ ++ Rectangle { ++ id:controls ++ width:360 ++ height:160 ++ Column { ++ spacing:3 ++ Slider {id:nCtrl; width:300; height:30; min:1; max:10; init:4; name:"N"} ++ Slider {id:rCtrl; width:300; height:30; min:30; max:180; init:100; name:"Radius"} ++ Slider {id:xCtrl; width:300; height:30; min:50; max:300; init:180; name:"X"} ++ Slider {id:yCtrl; width:300; height:30; min:30; max:300; init:220; name:"Y"} ++ Slider {id:alphaCtrl; width:300; height:30; min:0; max:1; init:1; name:"Alpha"} ++ } ++ } ++ } ++} diff --cc examples/quick/canvas/contents/Button.qml index 0000000,0000000..1413cdb new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/contents/Button.qml @@@ -1,0 -1,0 +1,87 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Item { ++ id: container ++ ++ signal clicked ++ ++ property string text ++ width: buttonText.width + 28 ++ height: buttonText.height + 14 ++ ++ BorderImage { ++ id: buttonImage ++ source: "images/toolbutton.sci" ++ width: container.width - 10 ++ height: container.height ++ } ++ BorderImage { ++ id: pressed ++ opacity: 0 ++ source: "images/toolbutton.sci" ++ width: container.width - 10 ++ height: container.height ++ } ++ MouseArea { ++ id: mouseRegion ++ anchors.fill: buttonImage ++ onClicked: { container.clicked(); } ++ } ++ Text { ++ id: buttonText ++ color: "white" ++ anchors.centerIn: buttonImage ++ font.bold: true ++ font.pointSize: 15 ++ text: container.text ++ style: Text.Raised ++ styleColor: "black" ++ } ++ states: [ ++ State { ++ name: "Pressed" ++ when: mouseRegion.pressed == true ++ PropertyChanges { target: pressed; opacity: 1 } ++ } ++ ] ++} diff --cc examples/quick/canvas/contents/ScrollBar.qml index 0000000,0000000..98b8efe new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/contents/ScrollBar.qml @@@ -1,0 -1,0 +1,74 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the Qt Mobility Components. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Item { ++ id: scrollBar ++ // The properties that define the scrollbar's state. ++ // position and pageSize are in the range 0.0 - 1.0. They are relative to the ++ // height of the page, i.e. a pageSize of 0.5 means that you can see 50% ++ // of the height of the view. ++ // orientation can be either 'Vertical' or 'Horizontal' ++ property real position ++ property real pageSize ++ property string orientation : "Vertical" ++ property alias bgColor: background.color ++ property alias fgColor: thumb.color ++ ++ // A light, semi-transparent background ++ Rectangle { ++ id: background ++ radius: orientation == 'Vertical' ? (width/2 - 1) : (height/2 - 1) ++ color: "white"; opacity: 0.3 ++ anchors.fill: parent ++ } ++ // Size the bar to the required size, depending upon the orientation. ++ Rectangle { ++ id: thumb ++ opacity: 0.7 ++ color: "black" ++ radius: orientation == 'Vertical' ? (width/2 - 1) : (height/2 - 1) ++ x: orientation == 'Vertical' ? 1 : (scrollBar.position * (scrollBar.width-2) + 1) ++ y: orientation == 'Vertical' ? (scrollBar.position * (scrollBar.height-2) + 1) : 1 ++ width: orientation == 'Vertical' ? (parent.width-2) : (scrollBar.pageSize * (scrollBar.width-2)) ++ height: orientation == 'Vertical' ? (scrollBar.pageSize * (scrollBar.height-2)) : (parent.height-2) ++ } ++} diff --cc examples/quick/canvas/contents/Slider.qml index 0000000,0000000..093b9e4 new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/contents/Slider.qml @@@ -1,0 -1,0 +1,115 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the QtQuick module of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL$ ++** GNU Lesser General Public License Usage ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** ++** ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Item { ++ id:slider ++ property real min:0 ++ property real max:1 ++ property real value: min + (max - min) * (bar.x / (foo.width - bar.width)) ++ property real init:min+(max-min)/2 ++ property string name:"Slider" ++ ++ Component.onCompleted: setValue(init) ++ function setValue(v) { ++ if (min < max) ++ bar.x = v/(max - min) * (foo.width - bar.width); ++ } ++ Rectangle { ++ id:sliderName ++ anchors.left:parent.left ++ height: childrenRect.height ++ width:childrenRect.width ++ anchors.verticalCenter:parent.verticalCenter ++ Text { ++ text:slider.name ++ font.pointSize:12 ++ } ++ } ++ Item { ++ id: foo ++ height: 6 ++ width: parent.width - 4 - sliderName.width ++ anchors.verticalCenter:parent.verticalCenter ++ anchors.left:sliderName.right ++ anchors.leftMargin:5 ++ Rectangle { ++ height: parent.height ++ anchors.left: parent.left ++ anchors.right: bar.horizontalCenter ++ color: "blue" ++ radius: 3 ++ } ++ Rectangle { ++ height: parent.height ++ anchors.left: bar.horizontalCenter ++ anchors.right: parent.right ++ color: "gray" ++ radius: 3 ++ } ++ Rectangle { ++ anchors.fill: parent ++ color: "transparent" ++ radius: 3 ++ border.width: 2 ++ border.color: "black" ++ } ++ ++ Rectangle { ++ id: bar ++ y: -7 ++ width: 20 ++ height: 20 ++ radius: 15 ++ color: "white" ++ border.width: 2 ++ border.color: "black" ++ MouseArea { ++ anchors.fill: parent ++ drag.target: parent ++ drag.axis: Drag.XAxis ++ drag.minimumX: 0 ++ drag.maximumX: foo.width - parent.width ++ } ++ } ++ } ++} diff --cc examples/quick/canvas/contents/Stocks.qml index 0000000,0000000..043bca1 new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/contents/Stocks.qml @@@ -1,0 -1,0 +1,147 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++ListModel { ++ id:stocks ++ //Data from : http://en.wikipedia.org/wiki/NASDAQ-100 ++ ++ ListElement {name:"Activision Blizzard"; stockId:"ATVI"} ++ ListElement {name:"Adobe Systems Incorporated"; stockId:"ADBE"} ++ ListElement {name:"Akamai Technologies, Inc"; stockId:"AKAM"} ++ ListElement {name:"Alexion Pharmaceuticals"; stockId:"ALXN"} ++ ListElement {name:"Altera Corporation"; stockId:"ALTR"} ++ ListElement {name:"Amazon.com, Inc."; stockId:"AMZN"} ++ ListElement {name:"Amgen Inc."; stockId:"AMGN"} ++ ListElement {name:"Apollo Group, Inc."; stockId:"APOL"} ++ ListElement {name:"Apple Inc."; stockId:"AAPL"} ++ ListElement {name:"Applied Materials, Inc."; stockId:"AMAT"} ++ ListElement {name:"Autodesk, Inc."; stockId:"ADSK"} ++ ListElement {name:"Automatic Data Processing, Inc."; stockId:"ADP"} ++ ListElement {name:"Baidu.com, Inc."; stockId:"BIDU"} ++ ListElement {name:"Bed Bath & Beyond Inc."; stockId:"BBBY"} ++ ListElement {name:"Biogen Idec, Inc"; stockId:"BIIB"} ++ ListElement {name:"BMC Software, Inc."; stockId:"BMC"} ++ ListElement {name:"Broadcom Corporation"; stockId:"BRCM"} ++ ListElement {name:"C. H. Robinson Worldwide, Inc."; stockId:"CHRW"} ++ ListElement {name:"CA, Inc."; stockId:"CA"} ++ ListElement {name:"Celgene Corporation"; stockId:"CELG"} ++ ListElement {name:"Cephalon, Inc."; stockId:"CEPH"} ++ ListElement {name:"Cerner Corporation"; stockId:"CERN"} ++ ListElement {name:"Check Point Software Technologies Ltd."; stockId:"CHKP"} ++ ListElement {name:"Cisco Systems, Inc."; stockId:"CSCO"} ++ ListElement {name:"Citrix Systems, Inc."; stockId:"CTXS"} ++ ListElement {name:"Cognizant Technology Solutions Corporation"; stockId:"CTSH"} ++ ListElement {name:"Comcast Corporation"; stockId:"CMCSA"} ++ ListElement {name:"Costco Wholesale Corporation"; stockId:"COST"} ++ ListElement {name:"Ctrip.com International, Ltd."; stockId:"CTRP"} ++ ListElement {name:"Dell Inc."; stockId:"DELL"} ++ ListElement {name:"DENTSPLY International Inc."; stockId:"XRAY"} ++ ListElement {name:"DirecTV"; stockId:"DTV"} ++ ListElement {name:"Dollar Tree, Inc."; stockId:"DLTR"} ++ ListElement {name:"eBay Inc."; stockId:"EBAY"} ++ ListElement {name:"Electronic Arts Inc."; stockId:"ERTS"} ++ ListElement {name:"Expedia, Inc."; stockId:"EXPE"} ++ ListElement {name:"Expeditors International of Washington, Inc."; stockId:"EXPD"} ++ ListElement {name:"Express Scripts, Inc."; stockId:"ESRX"} ++ ListElement {name:"F5 Networks, Inc."; stockId:"FFIV"} ++ ListElement {name:"Fastenal Company"; stockId:"FAST"} ++ ListElement {name:"First Solar, Inc."; stockId:"FSLR"} ++ ListElement {name:"Fiserv, Inc."; stockId:"FISV"} ++ ListElement {name:"Flextronics International Ltd."; stockId:"FLEX"} ++ ListElement {name:"FLIR Systems, Inc."; stockId:"FLIR"} ++ ListElement {name:"Garmin Ltd."; stockId:"GRMN"} ++ ListElement {name:"Gilead Sciences, Inc."; stockId:"GILD"} ++ ListElement {name:"Google Inc."; stockId:"GOOG"} ++ ListElement {name:"Green Mountain Coffee Roasters, Inc."; stockId:"GMCR"} ++ ListElement {name:"Henry Schein, Inc."; stockId:"HSIC"} ++ ListElement {name:"Illumina, Inc."; stockId:"ILMN"} ++ ListElement {name:"Infosys Technologies"; stockId:"INFY"} ++ ListElement {name:"Intel Corporation"; stockId:"INTC"} ++ ListElement {name:"Intuit, Inc."; stockId:"INTU"} ++ ListElement {name:"Intuitive Surgical Inc."; stockId:"ISRG"} ++ ListElement {name:"Joy Global Inc."; stockId:"JOYG"} ++ ListElement {name:"KLA Tencor Corporation"; stockId:"KLAC"} ++ ListElement {name:"Lam Research Corporation"; stockId:"LRCX"} ++ ListElement {name:"Liberty Media Corporation, Interactive Series A"; stockId:"LINTA"} ++ ListElement {name:"Life Technologies Corporation"; stockId:"LIFE"} ++ ListElement {name:"Linear Technology Corporation"; stockId:"LLTC"} ++ ListElement {name:"Marvell Technology Group, Ltd."; stockId:"MRVL"} ++ ListElement {name:"Mattel, Inc."; stockId:"MAT"} ++ ListElement {name:"Maxim Integrated Products"; stockId:"MXIM"} ++ ListElement {name:"Microchip Technology Incorporated"; stockId:"MCHP"} ++ ListElement {name:"Micron Technology, Inc."; stockId:"MU"} ++ ListElement {name:"Microsoft Corporation"; stockId:"MSFT"} ++ ListElement {name:"Mylan, Inc."; stockId:"MYL"} ++ ListElement {name:"NetApp, Inc."; stockId:"NTAP"} ++ ListElement {name:"Netflix, Inc."; stockId:"NFLX"} ++ ListElement {name:"News Corporation, Ltd."; stockId:"NWSA"} ++ ListElement {name:"NII Holdings, Inc."; stockId:"NIHD"} ++ ListElement {name:"NVIDIA Corporation"; stockId:"NVDA"} ++ ListElement {name:"O'Reilly Automotive, Inc."; stockId:"ORLY"} ++ ListElement {name:"Oracle Corporation"; stockId:"ORCL"} ++ ListElement {name:"PACCAR Inc."; stockId:"PCAR"} ++ ListElement {name:"Paychex, Inc."; stockId:"PAYX"} ++ ListElement {name:"Priceline.com, Incorporated"; stockId:"PCLN"} ++ ListElement {name:"Qiagen N.V."; stockId:"QGEN"} ++ ListElement {name:"QUALCOMM Incorporated"; stockId:"QCOM"} ++ ListElement {name:"Research in Motion Limited"; stockId:"RIMM"} ++ ListElement {name:"Ross Stores Inc."; stockId:"ROST"} ++ ListElement {name:"SanDisk Corporation"; stockId:"SNDK"} ++ ListElement {name:"Seagate Technology Holdings"; stockId:"STX"} ++ ListElement {name:"Sears Holdings Corporation"; stockId:"SHLD"} ++ ListElement {name:"Sigma-Aldrich Corporation"; stockId:"SIAL"} ++ ListElement {name:"Staples Inc."; stockId:"SPLS"} ++ ListElement {name:"Starbucks Corporation"; stockId:"SBUX"} ++ ListElement {name:"Stericycle, Inc"; stockId:"SRCL"} ++ ListElement {name:"Symantec Corporation"; stockId:"SYMC"} ++ ListElement {name:"Teva Pharmaceutical Industries Ltd."; stockId:"TEVA"} ++ ListElement {name:"Urban Outfitters, Inc."; stockId:"URBN"} ++ ListElement {name:"VeriSign, Inc."; stockId:"VRSN"} ++ ListElement {name:"Vertex Pharmaceuticals"; stockId:"VRTX"} ++ ListElement {name:"Virgin Media, Inc."; stockId:"VMED"} ++ ListElement {name:"Vodafone Group, plc."; stockId:"VOD"} ++ ListElement {name:"Warner Chilcott, Ltd."; stockId:"WCRX"} ++ ListElement {name:"Whole Foods Market, Inc."; stockId:"WFM"} ++ ListElement {name:"Wynn Resorts Ltd."; stockId:"WYNN"} ++ ListElement {name:"Xilinx, Inc."; stockId:"XLNX"} ++ ListElement {name:"Yahoo! Inc."; stockId:"YHOO"} ++} diff --cc examples/quick/canvas/contents/TitleBar.qml index 0000000,0000000..28edda2 new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/contents/TitleBar.qml @@@ -1,0 -1,0 +1,70 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Item { ++ id: titleBar ++ property string title: "" ++ ++ BorderImage { source: "images/titlebar.sci"; width: parent.width; height: parent.height + 14; y: -7 } ++ ++ Image { ++ id: quitButton ++ anchors.left: parent.left//; anchors.leftMargin: 0 ++ anchors.verticalCenter: parent.verticalCenter ++ source: "images/quit.png" ++ MouseArea { ++ anchors.fill: parent ++ onClicked: Qt.quit() ++ } ++ } ++ ++ Text { ++ id: categoryText ++ anchors { ++ left: quitButton.right; right: parent.right; //leftMargin: 10; rightMargin: 10 ++ verticalCenter: parent.verticalCenter ++ } ++ elide: Text.ElideLeft ++ text: title ++ font.bold: true; font.pointSize: 20; color: "White"; style: Text.Raised; styleColor: "Black" ++ } ++} diff --cc examples/quick/canvas/contents/ToolBar.qml index 0000000,0000000..7ae7391 new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/contents/ToolBar.qml @@@ -1,0 -1,0 +1,69 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Item { ++ id: toolbar ++ ++ property variant labels ++ signal buttonClicked(int index) ++ ++ BorderImage { ++ source: "images/titlebar.sci" ++ width: parent.width ++ height: parent.height + 14 ++ y: -7 ++ } ++ ++ Row { ++ y: 3 ++ anchors.horizontalCenter: parent.horizontalCenter ++ Repeater { ++ model: toolbar.labels ++ delegate: ++ Button { ++ text: modelData ++ onClicked: toolbar.buttonClicked(model.index) ++ } ++ } ++ } ++ ++} diff --cc examples/quick/canvas/contents/images/button-pressed.png index 0000000,0000000..e434d32 new file mode 100644 Binary files differ diff --cc examples/quick/canvas/contents/images/button.png index 0000000,0000000..56a63ce new file mode 100644 Binary files differ diff --cc examples/quick/canvas/contents/images/default.svg index 0000000,0000000..248199c new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/contents/images/default.svg @@@ -1,0 -1,0 +1,82 @@@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ image/svg+xml ++ ++ weather-clear ++ January 2006 ++ ++ ++ Ryan Collier (pseudo) ++ ++ ++ ++ ++ http://www.tango-project.org ++ ++ ++ http://www.pseudocode.org ++ ++ ++ weather ++ applet ++ notification ++ ++ ++ ++ ++ ++ Garrett LeSage ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ diff --cc examples/quick/canvas/contents/images/gloss.png index 0000000,0000000..5d370cd new file mode 100755 Binary files differ diff --cc examples/quick/canvas/contents/images/lineedit.png index 0000000,0000000..2cc38dc new file mode 100755 Binary files differ diff --cc examples/quick/canvas/contents/images/lineedit.sci index 0000000,0000000..054bff7 new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/contents/images/lineedit.sci @@@ -1,0 -1,0 +1,5 @@@ ++border.left: 10 ++border.top: 10 ++border.bottom: 10 ++border.right: 10 ++source: lineedit.png diff --cc examples/quick/canvas/contents/images/quit.png index 0000000,0000000..5bda1b6 new file mode 100755 Binary files differ diff --cc examples/quick/canvas/contents/images/stripes.png index 0000000,0000000..9f36727e new file mode 100755 Binary files differ diff --cc examples/quick/canvas/contents/images/titlebar.png index 0000000,0000000..51c9008 new file mode 100755 Binary files differ diff --cc examples/quick/canvas/contents/images/titlebar.sci index 0000000,0000000..0418d94 new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/contents/images/titlebar.sci @@@ -1,0 -1,0 +1,5 @@@ ++border.left: 10 ++border.top: 12 ++border.bottom: 12 ++border.right: 10 ++source: titlebar.png diff --cc examples/quick/canvas/contents/images/toolbutton.png index 0000000,0000000..1131001 new file mode 100755 Binary files differ diff --cc examples/quick/canvas/contents/images/toolbutton.sci index 0000000,0000000..9e4f965 new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/contents/images/toolbutton.sci @@@ -1,0 -1,0 +1,5 @@@ ++border.left: 15 ++border.top: 4 ++border.bottom: 4 ++border.right: 15 ++source: toolbutton.png diff --cc examples/quick/canvas/contents/qt-logo.png index 0000000,0000000..5ab3a1b new file mode 100644 Binary files differ diff --cc examples/quick/canvas/quadraticCurveTo/quadraticCurveTo.qml index 0000000,0000000..bc3ca00 new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/quadraticCurveTo/quadraticCurveTo.qml @@@ -1,0 -1,0 +1,128 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++import "../contents" ++Item { ++ id:container ++ width:360 ++ height:600 ++ ++ Column { ++ spacing:5 ++ anchors.fill:parent ++ Text { font.pointSize:25; text:"Quadratic Curve"; anchors.horizontalCenter:parent.horizontalCenter} ++ ++ Canvas { ++ id:canvas ++ width:360 ++ height:360 ++ property string strokeStyle:"steelblue" ++ property string fillStyle:"yellow" ++ property int lineWidth:lineWidthCtrl.value ++ property bool fill:true ++ property bool stroke:true ++ property real alpha:alphaCtrl.value ++ property real scaleX : scaleXCtrl.value ++ property real scaleY : scaleYCtrl.value ++ property real rotate : rotateCtrl.value ++ smooth:true ++ renderTarget:Canvas.Image ++ renderStrategy: Canvas.Immediate ++ ++ onLineWidthChanged:requestPaint(); ++ onFillChanged:requestPaint(); ++ onStrokeChanged:requestPaint(); ++ onAlphaChanged:requestPaint(); ++ onScaleXChanged:requestPaint(); ++ onScaleYChanged:requestPaint(); ++ onRotateChanged:requestPaint(); ++ Behavior on scaleX { SpringAnimation { spring: 2; damping: 0.2; loops:Animation.Infinite } } ++ Behavior on scaleY { SpringAnimation { spring: 2; damping: 0.2; loops:Animation.Infinite} } ++ Behavior on rotate { SpringAnimation { spring: 2; damping: 0.2; loops:Animation.Infinite} } ++ ++ onPaint: { ++ var ctx = canvas.getContext('2d'); ++ ctx.save(); ++ ctx.clearRect(0, 0, canvas.width, canvas.height); ++ ctx.globalAlpha = canvas.alpha; ++ ctx.strokeStyle = canvas.strokeStyle; ++ ctx.fillStyle = canvas.fillStyle; ++ ctx.lineWidth = canvas.lineWidth; ++ ctx.scale(canvas.scaleX, canvas.scaleY); ++ ctx.rotate(canvas.rotate); ++ ctx.beginPath(); ++ ctx.moveTo(75,25); ++ ctx.quadraticCurveTo(25,25,25,62.5); ++ ctx.quadraticCurveTo(25,100,50,100); ++ ctx.quadraticCurveTo(50,120,30,125); ++ ctx.quadraticCurveTo(60,120,65,100); ++ ctx.quadraticCurveTo(125,100,125,62.5); ++ ctx.quadraticCurveTo(125,25,75,25); ++ ctx.closePath(); ++ if (canvas.fill) ++ ctx.fill(); ++ if (canvas.stroke) ++ ctx.stroke(); ++ ++ ++ ctx.fillStyle="green"; ++ ctx.font = "Bold 15px"; ++ ++ ctx.fillText("QML酷毙了", 30, 60); ++ ctx.restore(); ++ } ++ } ++ ++ Rectangle { ++ id:controls ++ width:360 ++ height:160 ++ Column { ++ spacing:3 ++ Slider {id:lineWidthCtrl; width:300; height:30; min:1; max:10; init:2; name:"Line width"} ++ Slider {id:scaleXCtrl; width:300; height:30; min:0.1; max:10; init:1; name:"ScaleX"} ++ Slider {id:scaleYCtrl; width:300; height:30; min:0.1; max:10; init:1; name:"ScaleY"} ++ Slider {id:rotateCtrl; width:300; height:30; min:0; max:Math.PI*2; init:0; name:"Rotate"} ++ Slider {id:alphaCtrl; width:300; height:30; min:0; max:1; init:1; name:"Alpha"} ++ } ++ } ++ } ++} diff --cc examples/quick/canvas/roundedrect/roundedrect.qml index 0000000,0000000..fd86c63 new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/roundedrect/roundedrect.qml @@@ -1,0 -1,0 +1,125 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++import "../contents" ++Item { ++ id:container ++ width:360 ++ height:600 ++ ++ Column { ++ spacing:5 ++ anchors.fill:parent ++ Text { font.pointSize:25; text:"Rounded rectangle"; anchors.horizontalCenter:parent.horizontalCenter} ++ Canvas { ++ id:canvas ++ width:360 ++ height:360 ++ smooth:true ++ renderTarget:Canvas.Image ++ renderStrategy: Canvas.Immediate ++ ++ property int radius: rCtrl.value ++ property int rectx: rxCtrl.value ++ property int recty: ryCtrl.value ++ property int rectWidth: width - 2*rectx ++ property int rectHeight: height - 2*recty ++ property string strokeStyle:"blue" ++ property string fillStyle:"steelblue" ++ property int lineWidth:lineWidthCtrl.value ++ property bool fill:true ++ property bool stroke:true ++ property real alpha:alphaCtrl.value ++ ++ onLineWidthChanged:requestPaint(); ++ onFillChanged:requestPaint(); ++ onStrokeChanged:requestPaint(); ++ onRadiusChanged:requestPaint(); ++ onRectxChanged:requestPaint(); ++ onRectyChanged:requestPaint(); ++ onAlphaChanged:requestPaint(); ++ ++ onPaint: { ++ var ctx = getContext("2d"); ++ ctx.save(); ++ ctx.clearRect(0,0,canvas.width, canvas.height); ++ ctx.strokeStyle = canvas.strokeStyle; ++ ctx.lineWidth = canvas.lineWidth ++ ctx.fillStyle = canvas.fillStyle ++ ctx.globalAlpha = canvas.alpha ++ ctx.beginPath(); ++ ctx.moveTo(rectx+radius,recty); // top side ++ ctx.lineTo(rectx+rectWidth-radius,recty); ++ // draw top right corner ++ ctx.arcTo(rectx+rectWidth,recty,rectx+rectWidth,recty+radius,radius); ++ ctx.lineTo(rectx+rectWidth,recty+rectHeight-radius); // right side ++ // draw bottom right corner ++ ctx.arcTo(rectx+rectWidth,recty+rectHeight,rectx+rectWidth-radius,recty+rectHeight,radius); ++ ctx.lineTo(rectx+radius,recty+rectHeight); // bottom side ++ // draw bottom left corner ++ ctx.arcTo(rectx,recty+rectHeight,rectx,recty+rectHeight-radius,radius); ++ ctx.lineTo(rectx,recty+radius); // left side ++ // draw top left corner ++ ctx.arcTo(rectx,recty,rectx+radius,recty,radius); ++ ctx.closePath(); ++ if (canvas.fill) ++ ctx.fill(); ++ if (canvas.stroke) ++ ctx.stroke(); ++ ctx.restore(); ++ } ++ } ++ ++ Rectangle { ++ id:controls ++ width:360 ++ height:160 ++ Column { ++ spacing:3 ++ Slider {id:lineWidthCtrl; width:300; height:30; min:1; max:10; init:2; name:"Line width"} ++ Slider {id:rxCtrl; width:300; height:30; min:5; max:30; init:10; name:"rectx"} ++ Slider {id:ryCtrl; width:300; height:30; min:5; max:30; init:10; name:"recty"} ++ Slider {id:rCtrl; width:300; height:30; min:10; max:100; init:40; name:"Radius"} ++ Slider {id:alphaCtrl; width:300; height:30; min:0; max:1; init:1; name:"Alpha"} ++ } ++ } ++ } ++} diff --cc examples/quick/canvas/smile/smile.qml index 0000000,0000000..28a48a6 new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/smile/smile.qml @@@ -1,0 -1,0 +1,128 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++import "../contents" ++Item { ++ id:container ++ width:360 ++ height:600 ++ ++ Column { ++ spacing:5 ++ anchors.fill:parent ++ Text { font.pointSize:25; text:"Smile with arcs"; anchors.horizontalCenter:parent.horizontalCenter} ++ ++ Canvas { ++ id:canvas ++ width:360 ++ height:360 ++ smooth:true ++ renderTarget:Canvas.Image ++ renderStrategy: Canvas.Immediate ++ ++ property string strokeStyle:"green" ++ property string fillStyle:"yellow" ++ property int lineWidth:lineWidthCtrl.value ++ property bool fill:true ++ property bool stroke:true ++ property real alpha:alphaCtrl.value ++ property real scaleX : scaleXCtrl.value ++ property real scaleY : scaleYCtrl.value ++ property real rotate : rotateCtrl.value ++ ++ onLineWidthChanged:requestPaint(); ++ onFillChanged:requestPaint(); ++ onStrokeChanged:requestPaint(); ++ onAlphaChanged:requestPaint(); ++ onScaleXChanged:requestPaint(); ++ onScaleYChanged:requestPaint(); ++ onRotateChanged:requestPaint(); ++ ++ Behavior on scaleX { SpringAnimation { spring: 2; damping: 0.2; loops:Animation.Infinite } } ++ Behavior on scaleY { SpringAnimation { spring: 2; damping: 0.2; loops:Animation.Infinite} } ++ Behavior on rotate { SpringAnimation { spring: 2; damping: 0.2; loops:Animation.Infinite} } ++ ++ onPaint: { ++ var ctx = canvas.getContext('2d'); ++ ctx.save(); ++ ctx.clearRect(0, 0, canvas.width, canvas.height); ++ ctx.globalAlpha = canvas.alpha; ++ ctx.strokeStyle = canvas.strokeStyle; ++ ctx.fillStyle = canvas.fillStyle; ++ ctx.lineWidth = canvas.lineWidth; ++ ctx.scale(canvas.scaleX, canvas.scaleY); ++ ctx.rotate(canvas.rotate); ++ ctx.beginPath(); ++ ctx.moveTo(75 + 50 * Math.cos(0), ++ 75 - 50 * Math.sin(Math.PI*2)); ++ ctx.arc(75,75,50,0,Math.PI*2,true); // Outer circle ++ ctx.moveTo(75,70); ++ ctx.arc(75,70,35,0,Math.PI,false); // Mouth (clockwise) ++ ctx.moveTo(60,65); ++ ctx.arc(60,65,5,0,Math.PI*2,true); // Left eye ++ ctx.moveTo(90 + 5 * Math.cos(0), ++ 65 - 5 * Math.sin(Math.PI*2)); ++ ctx.moveTo(90,65); ++ ctx.arc(90,65,5,0,Math.PI*2,true); // Right eye ++ ctx.closePath(); ++ if (canvas.fill) ++ ctx.fill(); ++ if (canvas.stroke) ++ ctx.stroke(); ++ ctx.restore(); ++ } ++ } ++ ++ Rectangle { ++ id:controls ++ width:360 ++ height:160 ++ Column { ++ spacing:3 ++ Slider {id:lineWidthCtrl; width:300; height:30; min:1; max:10; init:2; name:"Line width"} ++ Slider {id:scaleXCtrl; width:300; height:30; min:0.1; max:10; init:1; name:"ScaleX"} ++ Slider {id:scaleYCtrl; width:300; height:30; min:0.1; max:10; init:1; name:"ScaleY"} ++ Slider {id:rotateCtrl; width:300; height:30; min:0; max:Math.PI*2; init:0; name:"Rotate"} ++ Slider {id:alphaCtrl; width:300; height:30; min:0; max:1; init:1; name:"Alpha"} ++ } ++ } ++ } ++} diff --cc examples/quick/canvas/squircle/squircle.png index 0000000,0000000..86c69d9 new file mode 100644 Binary files differ diff --cc examples/quick/canvas/squircle/squircle.qml index 0000000,0000000..2fc65b6 new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/squircle/squircle.qml @@@ -1,0 -1,0 +1,155 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++import "../contents" ++Item { ++ id:container ++ width:360 ++ height:600 ++ ++ Column { ++ spacing:5 ++ anchors.fill:parent ++ Text { font.pointSize:25; text:"Squircles"; anchors.horizontalCenter:parent.horizontalCenter} ++ Image { ++ anchors.horizontalCenter:parent.horizontalCenter ++ source:"squircle.png" ++ width:250 ++ height:25 ++ } ++ Canvas { ++ id:canvas ++ width:360 ++ height:360 ++ smooth:true ++ renderTarget:Canvas.Image ++ renderStrategy: Canvas.Immediate ++ ++ property string strokeStyle:"blue" ++ property string fillStyle:"steelblue" ++ property int lineWidth:2 ++ property int nSize:nCtrl.value ++ property real radius:rCtrl.value ++ property bool fill:true ++ property bool stroke:false ++ property real px:xCtrl.value ++ property real py:yCtrl.value ++ property real alpha:alphaCtrl.value ++ ++ onAlphaChanged:requestPaint(); ++ onRadiusChanged:requestPaint(); ++ onLineWidthChanged:requestPaint(); ++ onNSizeChanged:requestPaint(); ++ onFillChanged:requestPaint(); ++ onStrokeChanged:requestPaint(); ++ onPxChanged:requestPaint(); ++ onPyChanged:requestPaint(); ++ ++ ++ onPaint: squcirle(); ++ ++ function squcirle() { ++ var ctx = canvas.getContext("2d"); ++ var N = canvas.nSize; ++ var R = canvas.radius; ++ ++ N=Math.abs(N); ++ var M=N; ++ if (N>100) M=100; ++ if (N<0.00000000001) M=0.00000000001; ++ ++ ctx.save(); ++ ctx.globalAlpha =canvas.alpha; ++ ctx.fillStyle = "gray"; ++ ctx.fillRect(0, 0, canvas.width, canvas.height); ++ ++ ctx.strokeStyle = canvas.strokeStyle; ++ ctx.fillStyle = canvas.fillStyle; ++ ctx.lineWidth = canvas.lineWidth; ++ ++ ctx.beginPath(); ++ var i = 0, x, y; ++ for (i=0; i<(2*R+1); i++){ ++ x = Math.round(i-R) + canvas.px; ++ y = Math.round(Math.pow(Math.abs(Math.pow(R,M)-Math.pow(Math.abs(i-R),M)),1/M)) + canvas.py; ++ ++ if (i == 0) ++ ctx.moveTo(x, y); ++ else ++ ctx.lineTo(x, y); ++ } ++ ++ for (i=(2*R); i<(4*R+1); i++){ ++ x =Math.round(3*R-i)+canvas.px; ++ y = Math.round(-Math.pow(Math.abs(Math.pow(R,M)-Math.pow(Math.abs(3*R-i),M)),1/M)) + canvas.py; ++ ctx.lineTo(x, y); ++ } ++ ctx.closePath(); ++ if (canvas.stroke) { ++ ctx.stroke(); ++ } ++ ++ if (canvas.fill) { ++ ctx.fill(); ++ } ++ ++ ctx.fillStyle = "yellow"; ++ ctx.font = "Helvetica 16px"; ++ ctx.fillText("|X-" + Math.round(canvas.px) + "|^" + N + " + |Y-"+Math.round(canvas.py)+"|^" + N + " = |" + Math.round(R) + "|^" + N, canvas.px - 125, canvas.py); ++ ctx.restore(); ++ } ++ } ++ ++ Rectangle { ++ id:controls ++ width:360 ++ height:160 ++ Column { ++ spacing:3 ++ Slider {id:nCtrl; width:300; height:30; min:1; max:10; init:4; name:"N"} ++ Slider {id:rCtrl; width:300; height:30; min:30; max:180; init:100; name:"Radius"} ++ Slider {id:xCtrl; width:300; height:30; min:50; max:300; init:180; name:"X"} ++ Slider {id:yCtrl; width:300; height:30; min:30; max:300; init:220; name:"Y"} ++ Slider {id:alphaCtrl; width:300; height:30; min:0; max:1; init:1; name:"Alpha"} ++ } ++ } ++ } ++} diff --cc examples/quick/canvas/stockchart/README index 0000000,0000000..2652866 new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/stockchart/README @@@ -1,0 -1,0 +1,5 @@@ ++To run: ++ ++ make install ++ QML_IMPORT_PATH=$PWD qmlscene stock.qml ++ diff --cc examples/quick/canvas/stockchart/com/nokia/StockChartExample/qmldir index 0000000,0000000..4c60e55 new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/stockchart/com/nokia/StockChartExample/qmldir @@@ -1,0 -1,0 +1,1 @@@ ++plugin qmlstockchartexampleplugin diff --cc examples/quick/canvas/stockchart/model.cpp index 0000000,0000000..42eb2d5 new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/stockchart/model.cpp @@@ -1,0 -1,0 +1,255 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++#include "model.h" ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++StockModel::StockModel(QObject *parent) ++ : QAbstractListModel(parent) ++ , _startDate(QDate(1995, 4, 25)) ++ , _endDate(QDate::currentDate()) ++ , _dataCycle(StockModel::Daily) ++ , _manager(0) ++ , _updating(false) ++{ ++ QHash roles; ++ roles[StockModel::DateRole] = "date"; ++ roles[StockModel::SectionRole] = "year"; ++ roles[StockModel::OpenPriceRole] = "openPrice"; ++ roles[StockModel::ClosePriceRole] = "closePrice"; ++ roles[StockModel::HighPriceRole] = "highPrice"; ++ roles[StockModel::LowPriceRole] = "lowPrice"; ++ roles[StockModel::VolumeRole] = "volume"; ++ roles[StockModel::AdjustedPriceRole] = "adjustedPrice"; ++ setRoleNames(roles); ++ ++ connect(this, SIGNAL(stockNameChanged()), SLOT(requestData())); ++ connect(this, SIGNAL(startDateChanged()), SLOT(requestData())); ++ connect(this, SIGNAL(endDateChanged()), SLOT(requestData())); ++ connect(this, SIGNAL(dataCycleChanged()), SLOT(requestData())); ++ ++ _manager = new QNetworkAccessManager(this); ++ connect(_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(update(QNetworkReply*))); ++ ++} ++ ++int StockModel::rowCount(const QModelIndex & parent) const { ++ Q_UNUSED(parent); ++ return _prices.count(); ++} ++ ++StockPrice* StockModel::stockPriceAtIndex(int idx) const ++{ ++ if (idx >=0 && idx < _prices.size()) { ++ return _prices[idx]; ++ } ++ return 0; ++} ++ ++ ++void StockModel::requestData() ++{ ++ if (!_updating) { ++ _updating = true; ++ QMetaObject::invokeMethod(this, "doRequest", Qt::QueuedConnection); ++ } ++} ++ ++void StockModel::doRequest() ++{ ++ /* ++ Fetch stock data from yahoo finance: ++ url: http://ichart.finance.yahoo.com/table.csv?s=NOK&a=5&b=11&c=2010&d=7&e=23&f=2010&g=d&ignore=.csv ++ s:stock name/id, a:start day, b:start month, c:start year default: 25 April 1995, oldest c= 1962 ++ d:end day, e:end month, f:end year, default:today (data only available 3 days before today) ++ g:data cycle(d daily, w weekly, m monthly, v Dividend) ++ */ ++ if (_manager && !_stockName.isEmpty() && _endDate > _startDate) { ++ QString query("http://ichart.finance.yahoo.com/table.csv?s=%1&a=%2&b=%3&c=%4&d=%5&e=%6&f=%7&g=%8&ignore=.csv"); ++ query = query.arg(_stockName) ++ .arg(_startDate.day()).arg(_startDate.month()).arg(_startDate.year()) ++ .arg(_endDate.day()).arg(_endDate.month()).arg(_endDate.year()) ++ .arg(dataCycleString()); ++ ++ qDebug() << "request stock data:" << query; ++ QNetworkReply* reply = _manager->get(QNetworkRequest(QUrl(query))); ++ connect(reply, SIGNAL(downloadProgress(qint64,qint64)), SIGNAL(downloadProgress(qint64,qint64))); ++ } ++} ++ ++void StockModel::update(QNetworkReply *reply) ++{ ++ _updating = false; ++ ++ if (reply) { ++ if (reply->error() == QNetworkReply::NoError) { ++ beginResetModel(); ++ ++ foreach (StockPrice* p, _prices) { ++ p->deleteLater(); ++ } ++ ++ _prices.clear(); ++ ++ while (!reply->atEnd()) { ++ QString line = reply->readLine(); ++ QStringList fields = line.split(','); ++ ++ //data format:Date,Open,High,Low,Close,Volume,Adjusted close price ++ //example: 2011-06-24,6.03,6.04,5.88,5.88,20465200,5.88 ++ if (fields.size() == 7) { ++ StockPrice* price = new StockPrice(this); ++ price->setDate(QDate::fromString(fields[0], Qt::ISODate)); ++ price->setOpenPrice(fields[1].toFloat()); ++ price->setHighPrice(fields[2].toFloat()); ++ price->setLowPrice(fields[3].toFloat()); ++ price->setClosePrice(fields[4].toFloat()); ++ price->setVolume(fields[5].toInt()); ++ price->setAdjustedPrice(fields[6].toFloat()); ++ _prices.prepend(price); ++ } ++ } ++ qDebug() << "get stock data successfully, total:" << _prices.count() << "records."; ++ } else { ++ qDebug() << "get stock data failed:" << reply->errorString(); ++ } ++ reply->deleteLater(); ++ endResetModel(); ++ emit dataChanged(QModelIndex(), QModelIndex()); ++ } ++} ++ ++QVariant StockModel::data(const QModelIndex & index, int role) const { ++ if (index.row() < 0 || index.row() > _prices.count()) ++ return QVariant(); ++ ++ const StockPrice* price = _prices[index.row()]; ++ if (role == StockModel::DateRole) ++ return price->date(); ++ else if (role == StockModel::OpenPriceRole) ++ return price->openPrice(); ++ else if (role == StockModel::ClosePriceRole) ++ return price->closePrice(); ++ else if (role == StockModel::HighPriceRole) ++ return price->highPrice(); ++ else if (role == StockModel::LowPriceRole) ++ return price->lowPrice(); ++ else if (role == StockModel::AdjustedPriceRole) ++ return price->adjustedPrice(); ++ else if (role == StockModel::VolumeRole) ++ return price->volume(); ++ else if (role == StockModel::SectionRole) ++ return price->date().year(); ++ return QVariant(); ++} ++ ++QString StockModel::stockName() const ++{ ++ return _stockName; ++} ++void StockModel::setStockName(const QString& name) ++{ ++ if (_stockName != name) { ++ _stockName = name; ++ emit stockNameChanged(); ++ } ++} ++ ++QDate StockModel::startDate() const ++{ ++ return _startDate; ++} ++void StockModel::setStartDate(const QDate& date) ++{ ++ if (_startDate.isValid() && _startDate != date) { ++ _startDate = date; ++ emit startDateChanged(); ++ } ++} ++ ++QDate StockModel::endDate() const ++{ ++ return _endDate; ++} ++void StockModel::setEndDate(const QDate& date) ++{ ++ if (_endDate.isValid() && _endDate != date) { ++ _endDate = date; ++ emit endDateChanged(); ++ } ++} ++ ++StockModel::StockDataCycle StockModel::dataCycle() const ++{ ++ return _dataCycle; ++} ++ ++QString StockModel::dataCycleString() const ++{ ++ switch (_dataCycle) { ++ case StockModel::Daily: ++ return QString('d'); ++ break; ++ case StockModel::Weekly: ++ return QString('w'); ++ case StockModel::Monthly: ++ return QString('m'); ++ case StockModel::Dividend: ++ return QString('v'); ++ } ++ ++ return QString('d'); ++} ++ ++ ++void StockModel::setDataCycle(StockModel::StockDataCycle cycle) ++{ ++ if (_dataCycle != cycle) { ++ _dataCycle = cycle; ++ emit dataCycleChanged(); ++ } ++} diff --cc examples/quick/canvas/stockchart/model.h index 0000000,0000000..95e6f48 new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/stockchart/model.h @@@ -1,0 -1,0 +1,166 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++#include ++#include ++ ++class StockPrice : public QObject ++{ ++ Q_OBJECT ++ Q_PROPERTY(QDate date READ date) ++ Q_PROPERTY(qreal openPrice READ openPrice) ++ Q_PROPERTY(qreal closePrice READ closePrice) ++ Q_PROPERTY(qreal highPrice READ highPrice) ++ Q_PROPERTY(qreal lowPrice READ lowPrice) ++ Q_PROPERTY(qint32 volume READ volume) ++ Q_PROPERTY(qreal adjustedPrice READ adjustedPrice) ++public: ++ ++ StockPrice(QObject *parent = 0) ++ : QObject(parent) ++ , _openPrice(-1) ++ , _closePrice(-1) ++ , _highPrice(-1) ++ , _lowPrice(-1) ++ , _volume(-1) ++ , _adjustedPrice(-1) ++ { ++ } ++ QDate date() const {return _date;} ++ qreal openPrice() const {return _openPrice; } ++ qreal closePrice() const {return _closePrice;} ++ qreal highPrice() const {return _highPrice;} ++ qreal lowPrice() const{return _lowPrice;} ++ qreal adjustedPrice() const{return _adjustedPrice;} ++ qint32 volume() const{return _volume;} ++ ++ void setDate(const QDate& date){_date = date;} ++ void setOpenPrice(qreal price){_openPrice = price;} ++ void setClosePrice(qreal price){_closePrice = price;} ++ void setHighPrice(qreal price){_highPrice = price;} ++ void setLowPrice(qreal price){_lowPrice = price;} ++ void setAdjustedPrice(qreal price) {_adjustedPrice = price;} ++ void setVolume(qint32 volume) {_volume = volume;} ++ ++private: ++ QDate _date; ++ qreal _openPrice; ++ qreal _closePrice; ++ qreal _highPrice; ++ qreal _lowPrice; ++ qint32 _volume; ++ qreal _adjustedPrice; ++}; ++ ++class QNetworkReply; ++class QNetworkAccessManager; ++class StockModel : public QAbstractListModel ++{ ++ Q_OBJECT ++ ++ Q_PROPERTY(QString stockName READ stockName WRITE setStockName NOTIFY stockNameChanged) ++ Q_PROPERTY(QDate startDate READ startDate WRITE setStartDate NOTIFY startDateChanged) ++ Q_PROPERTY(QDate endDate READ endDate WRITE setEndDate NOTIFY endDateChanged) ++ Q_PROPERTY(StockDataCycle dataCycle READ dataCycle WRITE setDataCycle NOTIFY dataCycleChanged) ++ ++ Q_ENUMS(StockDataCycle) ++public: ++ enum StockDataCycle { ++ Daily, ++ Weekly, ++ Monthly, ++ Dividend ++ }; ++ ++ enum StockModelRoles { ++ DateRole = Qt::UserRole + 1, ++ SectionRole, ++ OpenPriceRole, ++ ClosePriceRole, ++ HighPriceRole, ++ LowPriceRole, ++ VolumeRole, ++ AdjustedPriceRole ++ }; ++ ++ StockModel(QObject *parent = 0); ++ ++ QString stockName() const; ++ void setStockName(const QString& name); ++ ++ QDate startDate() const; ++ void setStartDate(const QDate& date); ++ ++ QDate endDate() const; ++ void setEndDate(const QDate& date); ++ ++ StockDataCycle dataCycle() const; ++ void setDataCycle(StockDataCycle cycle); ++ ++ int rowCount(const QModelIndex & parent = QModelIndex()) const; ++ ++ QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; ++ ++signals: ++ void stockNameChanged(); ++ void startDateChanged(); ++ void endDateChanged(); ++ void dataCycleChanged(); ++ void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); ++ ++public slots: ++ void requestData(); ++ StockPrice* stockPriceAtIndex(int idx) const; ++private slots: ++ void doRequest(); ++ void update(QNetworkReply* reply); ++private: ++ QString dataCycleString() const; ++ QList _prices; ++ QString _stockName; ++ QDate _startDate; ++ QDate _endDate; ++ StockDataCycle _dataCycle; ++ QNetworkAccessManager* _manager; ++ bool _updating; ++}; ++ ++ ++ ++ diff --cc examples/quick/canvas/stockchart/plugin.cpp index 0000000,0000000..3b354e2 new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/stockchart/plugin.cpp @@@ -1,0 -1,0 +1,60 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++#include ++#include ++#include ++#include "model.h" ++ ++class QStockChartExampleQmlPlugin : public QQmlExtensionPlugin ++{ ++ Q_OBJECT ++public: ++ void registerTypes(const char *uri) ++ { ++ Q_ASSERT(uri == QLatin1String("com.nokia.StockChartExample")); ++ qmlRegisterType(uri, 1, 0, "StockModel"); ++ qmlRegisterType(uri, 1, 0, "StockPrice"); ++ } ++}; ++ ++#include "plugin.moc" ++ ++Q_EXPORT_PLUGIN2(qmlstockchartexampleplugin, QStockChartExampleQmlPlugin); diff --cc examples/quick/canvas/stockchart/stock.qml index 0000000,0000000..1c95fde new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/stockchart/stock.qml @@@ -1,0 -1,0 +1,726 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++import QtQuick 2.0 ++import com.nokia.StockChartExample 1.0 ++import "../contents" ++ ++Rectangle { ++ id:container ++ width: 360; height: 600 ++ color: "#343434"; ++ Image { source: "contents/images/stripes.png"; fillMode: Image.Tile; anchors.fill: parent; opacity: 1 } ++ ++ ++ TitleBar { ++ id: titleBar ++ width: parent.width ++ anchors.top : container.top ++ height: 40 ++ opacity: 0.9 ++ } ++ ++ StockModel { ++ id:stockModel ++ dataCycle: StockModel.Daily ++ function dataCycleName() { ++ if (dataCycle === StockModel.Weekly) ++ return "Weekly"; ++ else if (dataCycle === StockModel.Monthly) ++ return "Monthly"; ++ return "Daily"; ++ } ++ ++ onDataChanged: { ++ if (view.viewType == "chart") { ++ canvas.requestPaint(); ++ } ++ } ++ onDownloadProgress: { ++ if (bytesReceived == bytesTotal && bytesTotal != -1) { ++ progress.opacity = 0; ++ } else { ++ progress.opacity = 0.8; ++ progress.text = "downloading " + stockModel.dataCycleName() + " data ..."+ Math.round(bytesReceived/1000) + " KB"; ++ } ++ } ++ ++ property string description:""; ++ } ++ ++ Stocks {id:stocks} ++ ++ Rectangle { ++ id: header ++ width: parent.width ++ height: 20 ++ color: "steelblue" ++ opacity: 0 ++ Row { ++ spacing: 2 ++ Text { ++ id:t ++ font.pointSize:15 ++ horizontalAlignment:Text.AlignHCenter ++ font.bold: true ++ font.underline:true ++ } ++ Rectangle { ++ height:20 ++ width:50 ++ Text {text:"Stock list"; font.pointSize:15; font.bold: true} ++ } ++ } ++ } ++ ++ ListView { ++ id:stockList ++ width: parent.width ++ anchors.bottom: container.bottom ++ anchors.top : titleBar.bottom ++ focus: true ++ keyNavigationWraps: true ++ spacing:1 ++ opacity: 1 ++ model: stocks ++ ++ Component.onCompleted: opacity = 0.9; ++ onOpacityChanged: { ++ titleBar.title = "Top 100 NASDAQ stocks" ++ } ++ ++ ++ delegate : Rectangle { ++ height: 30 ++ width: view.width ++ color: { ++ if (ListView.isCurrentItem) ++ return focus ? "lightyellow" : "pink"; ++ return index % 2 == 0 ? "lightblue" : "lightsteelblue" ++ } ++ Text { ++ font.pointSize:20 ++ text: index + ". " + stockId + " \t(" + name + ")"; ++ } ++ MouseArea { ++ anchors.fill: parent; ++ onDoubleClicked: { ++ stockList.opacity = 0; ++ stockModel.stockName = stockId; ++ stockModel.description = "NASDAQ:" + stockId + " (" + name + ")"; ++ view.opacity = 1; ++ view.viewType = "chart"; ++ canvas.opacity = 0.7; ++ } ++ onClicked: stockList.currentIndex = index ++ }//mousearea ++ }//delegate ++ } ++ ++ ListView { ++ id:view ++ width: container.width ++ height: container.height - 50 ++ anchors.bottom: container.bottom ++ focus: true ++ keyNavigationWraps: true ++ ++ spacing:1 ++ opacity: 0 ++ model: stockModel ++ highlightFollowsCurrentItem: false ++ highlightRangeMode: ListView.StrictlyEnforceRange ++ preferredHighlightBegin:50 ++ preferredHighlightEnd : height - 50 ++ highlight: listHighlight ++ ++ //header : Text {} ++ delegate: listDelegate ++ snapMode: ListView.SnapToItem ++ ++ property string viewType : "list" ++ property int topIndex:indexAt(0,contentY); ++ property int bottomIndex:indexAt(0, contentY+height); ++ ++ onCountChanged: { ++ ++ titleBar.title = stockModel.description + " " + Qt.formatDate(stockModel.startDate, "yyyy-MM-dd") + " - " + ++ Qt.formatDate(stockModel.endDate, "yyyy-MM-dd") + " " + stockModel.dataCycleName() + ++ " records:" + view.count; ++ ++ } ++ ++ Component { ++ id: listDelegate ++ Rectangle { ++ height: 20 ++ width: view.width ++ border.color: "lightsteelblue" ++ border.width: 1 ++ color: { ++ if (ListView.isCurrentItem) ++ return focus ? "lightyellow" : "pink"; ++ ++ return index % 2 == 0 ? "lightblue" : "lightsteelblue" ++ } ++ Text { ++ font.pointSize:13 ++ text: index + ". " + Qt.formatDate(date, "yyyy-MM-dd") ++ + "\t " + Math.round(openPrice*100)/100 ++ + "\t " + Math.round(highPrice*100)/100 ++ + "\t " + Math.round(lowPrice*100)/100 ++ + "\t " + Math.round(closePrice*100)/100 ++ + "\t " + volume + "\t " ++ + Math.round(adjustedPrice*100)/100; ++ } ++ MouseArea {anchors.fill: parent; onClicked: view.currentIndex = index} ++ } ++ } ++ ++ Component { ++ id: chartDelegate ++ Rectangle { ++ height: 20 ++ width: view.width/view.count * canvas.scaleX ++ border.color: "lightsteelblue" ++ border.width: 1 ++ color: { ++ if (ListView.isCurrentItem) ++ return focus ? "lightyellow" : "pink"; ++ ++ return index % 2 == 0 ? "lightblue" : "lightsteelblue" ++ } ++ ++ Text { ++ anchors.bottom: parent.bottom ++ font.pointSize: { ++ if (parent.width <= 4) ++ return 1; ++ if (parent.width <= 50) ++ return parent.width/4; ++ return 15; ++ } ++ horizontalAlignment:Text.AlignHCenter ++ verticalAlignment:Text.AlignBottom ++ text:font.pointSize > 1 ? Qt.formatDate(date, "d/M/yy") : "" ++ } ++ MouseArea {anchors.fill: parent; onClicked: view.currentIndex = index} ++ } ++ } ++ ++ Component { ++ id:chartHighlight ++ Rectangle { radius: 5; width:40; height: 20; color: "lightsteelblue" } ++ } ++ ++ Component { ++ id:listHighlight ++ Rectangle { radius: 5; width:container.width; height: 20; color: "lightsteelblue" } ++ } ++ ++ ++ ++ ++ onViewTypeChanged : { ++ if (viewType == "list") { ++ view.orientation = ListView.Vertical; ++ view.delegate = listDelegate; ++// view.section.property = "year"; ++// view.section.criteria = ViewSection.FullString; ++// view.section.delegate = sectionHeading; ++ view.highlight = listHighlight; ++ view.opacity = 1; ++ canvas.opacity = 0; ++ // comment.opacity = 0; ++ ++ } else if (viewType == "chart") { ++ view.orientation = ListView.Horizontal; ++ view.delegate = chartDelegate; ++ //comment.opacity = 0.6; ++ ++ view.opacity = 1; ++ view.height = 30 ++ ++ canvas.opacity = 0.7; ++ canvas.requestPaint(); ++ } else { ++ viewType = "list"; ++ } ++ } ++ ++ ++ onCurrentIndexChanged: { ++ //header.updateCurrent(stockModel.stockPriceAtIndex(view.currentIndex)); ++ if (viewType == "chart") { ++ canvas.first = Math.round(view.currentIndex - view.currentIndex / canvas.scaleX); ++ canvas.last = Math.round(view.currentIndex + (view.count - view.currentIndex) / canvas.scaleX); ++ ++ canvas.requestPaint(); ++ } ++ } ++ onContentYChanged: { // keep "current" item visible ++ topIndex = indexAt(0,contentY); ++ bottomIndex = indexAt(0, contentY+height); ++ ++ if (topIndex != -1 && currentIndex <= topIndex) ++ currentIndex = topIndex+1; ++ else if (bottomIndex != -1 && currentIndex >= bottomIndex) ++ currentIndex = bottomIndex-1; ++ if (viewType == "chart") ++ canvas.requestPaint(); ++ } ++ ++ onContentXChanged: { // keep "current" item visible ++ topIndex = indexAt(contentX,0); ++ bottomIndex = indexAt(contentX+width, 0); ++ ++ if (topIndex != -1 && currentIndex <= topIndex) ++ currentIndex = topIndex+1; ++ else if (bottomIndex != -1 && currentIndex >= bottomIndex) ++ currentIndex = bottomIndex-1; ++ if (viewType == "chart") ++ canvas.requestPaint(); ++ } ++ ++ MouseArea { ++ anchors.fill: parent ++ onDoubleClicked: { ++ if (view.viewType == "list") ++ view.viewType = "chart"; ++ else ++ view.viewType = "list"; ++ } ++ } ++ } ++ ++ ++ ++ Canvas { ++ id:canvas ++ anchors.top : titleBar.bottom ++ anchors.bottom : view.top ++ width:container.width; ++ opacity:0 ++ renderTarget: Canvas.Image ++ renderStrategy: Canvas.Immediate ++ property bool running:false ++ property int frames:first ++ property int mouseX:0; ++ property int mouseY:0; ++ property int mousePressedX:0; ++ property int mousePressedY:0; ++ property int movedY:0 ++ property real scaleX:1.0; ++ property real scaleY:1.0; ++ property int first:0; ++ property int last:view.count - 1; ++ ++ onOpacityChanged: { ++ if (opacity > 0) ++ requestPaint(); ++ } ++ Text { ++ id:comment ++ x:100 ++ y:50 ++ font.pointSize: 20 ++ color:"white" ++ opacity: 0.7 ++ focus:false ++ text: stockModel.description ++ function updateCurrent(price) ++ { ++ if (price !== undefined) { ++ text =stockModel.description + "\n" ++ + Qt.formatDate(price.date, "yyyy-MM-dd") + " OPEN:" ++ + Math.round(price.openPrice*100)/100 + " HIGH:" ++ + Math.round(price.highPrice*100)/100 + " LOW:" ++ + Math.round(price.lowPrice*100)/100 + " CLOSE:" ++ + Math.round(price.closePrice*100)/100 + " VOLUME:" ++ + price.volume; ++ } ++ } ++ } ++ ++ Text { ++ id:priceAxis ++ x:25 ++ y:25 ++ font.pointSize: 15 ++ color:"yellow" ++ opacity: 0.7 ++ focus: false ++ } ++ Text { ++ id:volumeAxis ++ x:canvas.width - 200 ++ y:25 ++ font.pointSize: 15 ++ color:"yellow" ++ opacity: 0.7 ++ } ++ ++ Rectangle { ++ id:progress ++ x:canvas.width/2 - 100 ++ y:canvas.height/2 ++ width:childrenRect.width ++ height: childrenRect.height ++ opacity: 0 ++ color:"white" ++ property string text; ++ Text { ++ text:parent.text ++ font.pointSize: 20 ++ } ++ } ++ ++ Button { ++ id:runButton ++ text:"Run this chart" ++ y:0 ++ x:canvas.width/2 - 50 ++ opacity: 0.5 ++ onClicked: { ++ if (canvas.running) { ++ canvas.running = false; ++ canvas.frames = canvas.first; ++ canvas.requestPaint(); ++ text = "Run this chart"; ++ comment.text = stockModel.description; ++ } else { ++ text = " Stop running "; ++ canvas.runChart(); ++ } ++ } ++ } ++ Button { ++ id:returnButton ++ text:"Stocks" ++ y:0 ++ anchors.left : runButton.right ++ anchors.leftMargin : 20 ++ opacity: 0.5 ++ onClicked: { ++ stockList.opacity = 1; ++ canvas.opacity = 0; ++ } ++ } ++ PinchArea { ++ anchors.fill: parent ++ onPinchUpdated : { ++ var current = pinch.center; ++ var scale = pinch.scale; ++ console.log("center:" + pinch.center + " scale:" + pinch.scale); ++ //canvas.requestPaint(); ++ } ++ } ++ ++ MouseArea { ++ anchors.fill: parent ++ ++ onDoubleClicked: { ++ if (stockModel.dataCycle == StockModel.Daily) ++ stockModel.dataCycle = StockModel.Weekly; ++ else if (stockModel.dataCycle == StockModel.Weekly) ++ stockModel.dataCycle = StockModel.Monthly; ++ else ++ stockModel.dataCycle = StockModel.Daily; ++ } ++ ++ onPositionChanged: { ++ if (mouse.modifiers & Qt.ControlModifier) { ++ if (canvas.mouseX == 0 && canvas.mouseY == 0) { ++ canvas.mouseX = mouse.x; ++ canvas.mouseY = mouse.y; ++ } ++ } else{ ++ var w = (view.width/view.count)*canvas.scaleX; ++ ++ //canvas.movedY += Math.round((canvas.mousePressedY - mouse.y)/2); ++ ++ var movedX = Math.round((canvas.mousePressedX - mouse.x)/w); ++ if (movedX != 0 || canvas.movedY != 0) { ++ if (canvas.first + movedX >= 0 && canvas.last + movedX < view.count) { ++ canvas.first += movedX; ++ canvas.last += movedX; ++ } ++ canvas.requestPaint(); ++ } ++ } ++ } ++ ++ onPressed: { ++ canvas.mousePressedX = mouse.x; ++ canvas.mousePressedY = mouse.y; ++ } ++ ++ onReleased : { ++ if (mouse.modifiers & Qt.ControlModifier) { ++ var sx = mouse.x - canvas.mouseX; ++ var sy = canvas.mouseY - mouse.y; ++ ++ if (Math.abs(sx) < 50) sx = 0; ++ if (Math.abs(sy) < 50) sy = 0; ++ ++ if (sx > 0) ++ canvas.scaleX *= sx/100 +1; ++ else ++ canvas.scaleX *= 1/(-sx/100 + 1); ++ ++ if (sy > 0) ++ canvas.scaleY *= sy/100 +1; ++ else ++ canvas.scaleY *= 1/(-sy/100 + 1); ++ ++ if (canvas.scaleX < 1) ++ canvas.scaleX = 1; ++ ++ //console.log("scaleX:" + canvas.scaleX + ", scaleY:" + canvas.scaleY); ++ ++ canvas.first = Math.round(view.currentIndex - view.currentIndex / canvas.scaleX); ++ canvas.last = Math.round(view.currentIndex + (view.count - view.currentIndex) / canvas.scaleX); ++ ++ canvas.mouseX = 0; ++ canvas.mouseY = 0; ++ canvas.mousePressedX = 0; ++ canvas.mousePressedY = 0; ++ canvas.requestPaint(); ++ } ++ } ++ } ++ ++ function runChart() { ++ canvas.running = true; ++ requestPaint(); ++ } ++ ++ function showPriceAt(x) { ++ var w = (view.width/view.count)*canvas.scaleX; ++ //header.updateCurrent(stockModel.stockPriceAtIndex(canvas.first + Math.round(x/w))); ++ //console.log("x:" + x + " w:" + w + " index:" + (canvas.first + Math.round(x/w))); ++ } ++ ++ function drawPrice(ctx, from, to, color, price, points, highest) ++ { ++ ctx.globalAlpha = 0.7; ++ ctx.strokeStyle = color; ++ ctx.lineWidth = 1; ++ ctx.beginPath(); ++ ++ //price x axis ++ priceAxis.text = "price:" + Math.round(highest); ++ ctx.font = "bold 12px sans-serif"; ++ ++ ctx.strokeText("price", 25, 25); ++ for (var j = 1; j < 30; j++) { ++ var val = (highest * j) / 30; ++ val = canvas.height * (1 - val/highest); ++ ctx.beginPath(); ++ ++ ctx.moveTo(10, val); ++ if (j % 5) ++ ctx.lineTo(15, val); ++ else ++ ctx.lineTo(20, val); ++ ctx.stroke(); ++ } ++ ++ ctx.beginPath(); ++ ctx.moveTo(10, 0); ++ ctx.lineTo(10, canvas.height); ++ ctx.stroke(); ++ ++ ++ var w = canvas.width/points.length; ++ var end = canvas.running? canvas.frames - canvas.first :points.length; ++ for (var i = 0; i < end; i++) { ++ var x = points[i].x; ++ var y = points[i][price]; ++ y += canvas.movedY; ++ ++ y = canvas.height * (1 - y/highest); ++ if (i == 0) { ++ ctx.moveTo(x+w/2, y); ++ } else { ++ ctx.lineTo(x+w/2, y); ++ } ++ } ++ ctx.stroke(); ++ } ++ ++ function drawKLine(ctx, from, to, points, highest) ++ { ++ ctx.globalAlpha = 0.4; ++ ctx.lineWidth = 2; ++ var end = canvas.running? canvas.frames - canvas.first :points.length; ++ for (var i = 0; i < end; i++) { ++ var x = points[i].x; ++ var open = canvas.height * (1 - points[i].open/highest) - canvas.movedY; ++ var close = canvas.height * (1 - points[i].close/highest) - canvas.movedY; ++ var high = canvas.height * (1 - points[i].high/highest) - canvas.movedY; ++ var low = canvas.height * (1 - points[i].low/highest) - canvas.movedY; ++ ++ var top, bottom; ++ if (close <= open) { ++ ctx.fillStyle = Qt.rgba(1, 0, 0, 1); ++ ctx.strokeStyle = Qt.rgba(1, 0, 0, 1); ++ top = close; ++ bottom = open; ++ } else { ++ ctx.fillStyle = Qt.rgba(0, 1, 0, 1); ++ ctx.strokeStyle = Qt.rgba(0, 1, 0, 1); ++ top = open; ++ bottom = close; ++ } ++ ++ var w1, w2; ++ w1 = canvas.width/points.length; ++ w2 = w1 > 10 ? w1/2 : w1; ++ ++ ctx.fillRect(x + (w1 - w2)/2, top, w2, bottom - top); ++ ctx.beginPath(); ++ ctx.moveTo(x+w1/2, high); ++ ctx.lineTo(x+w1/2, low); ++ ctx.stroke(); ++ } ++ ctx.globalAlpha = 1; ++ ++ } ++ ++ function drawVolume(ctx, from, to, color, price, points, highest) ++ { ++ ctx.fillStyle = color; ++ ctx.globalAlpha = 0.6; ++ ctx.strokeStyle = Qt.rgba(0.8, 0.8, 0.8, 1); ++ ctx.lineWidth = 1; ++ ++ //volume x axis ++ volumeAxis.text = "volume:" + Math.round(highest/(1000*100)) + "M"; ++ for (var j = 1; j < 30; j++) { ++ var val = (highest * j) / 30; ++ val = canvas.height * (1 - val/highest); ++ ctx.beginPath(); ++ if (j % 5) ++ ctx.moveTo(canvas.width - 15, val); ++ else ++ ctx.moveTo(canvas.width - 20, val); ++ ctx.lineTo(canvas.width - 10, val); ++ ctx.stroke(); ++ } ++ ++ ctx.beginPath(); ++ ctx.moveTo(canvas.width - 10, 0); ++ ctx.lineTo(canvas.width - 10, canvas.height); ++ ctx.stroke(); ++ ++ var end = canvas.running? canvas.frames - canvas.first :points.length; ++ for (var i = 0; i < end; i++) { ++ var x = points[i].x; ++ var y = points[i][price]; ++ y = canvas.height * (1 - y/highest); ++ ctx.fillRect(x, y, canvas.width/points.length, canvas.height - y); ++ } ++ } ++/* ++ onPainted : { ++ if (canvas.running) { ++ if (frames >= last) { ++ canvas.running = false; ++ canvas.frames = first; ++ runButton.text = "Run this chart"; ++ comment.text = stockModel.description; ++ requestPaint(); ++ } else { ++ frames += Math.round(view.count / 100); ++ if (frames > last) frames = last; ++ var price = stockModel.stockPriceAtIndex(frames); ++ if (price) { ++ comment.updateCurrent(price); ++ } ++ ++ requestPaint(); ++ } ++ } ++ } ++*/ ++ onPaint: { ++ if (view.currentIndex <= 0) ++ first = 0; ++ if (last >= view.count) ++ last = view.count - 1; ++ ++ //console.log("painting... first:" + first + ", last:" + last + " current:" + view.currentIndex); ++ var ctx = canvas.getContext("2d"); ++ ctx.save(); ++ ++ ctx.globalCompositeOperation = "source-over"; ++ ctx.lineWidth = 1; ++ ctx.lineJoin = "round"; ++ ctx.fillStyle = "rgba(0,0,0,0)"; ++ ++ ctx.fillRect(0, 0, canvas.width, canvas.height); ++ ++ ++ ++ var highestPrice = 500/canvas.scaleY; ++ var highestValume = 600 * 1000 * 1000/canvas.scaleY; ++ var points = []; ++ for (var i = 0; i <= last - first; i++) { ++ var price = stockModel.stockPriceAtIndex(i + first); ++ points.push({ ++ x: i*canvas.width/(last-first+1), ++ open: price.openPrice, ++ close: price.closePrice, ++ high:price.highPrice, ++ low:price.lowPrice, ++ volume:price.volume ++ }); ++ } ++ ++ drawPrice(ctx, first, last, Qt.rgba(1, 0, 0, 1),"high", points, highestPrice); ++ drawPrice(ctx, first, last, Qt.rgba(0, 1, 0, 1),"low", points, highestPrice); ++ drawPrice(ctx, first, last, Qt.rgba(0, 0, 1, 1),"open", points, highestPrice); ++ drawPrice(ctx, first, last, Qt.rgba(0.5, 0.5, 0.5, 1),"close", points, highestPrice); ++ drawVolume(ctx, first, last, Qt.rgba(0.3, 0.5, 0.7, 1),"volume", points, highestValume); ++ drawKLine(ctx, first, last, points, highestPrice); ++ ctx.restore(); ++ } ++ } ++} diff --cc examples/quick/canvas/stockchart/stockchart.pro index 0000000,0000000..e368746 new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/stockchart/stockchart.pro @@@ -1,0 -1,0 +1,20 @@@ ++TEMPLATE = lib ++CONFIG += qt plugin ++QT += qml network ++ ++DESTDIR = com/nokia/StockChartExample ++TARGET = qmlstockchartexampleplugin ++ ++SOURCES += model.cpp plugin.cpp ++HEADERS += model.h ++qdeclarativesources.files += \ ++ com/nokia/StockChartExample/qmldir \ ++ stock.qml ++ ++qdeclarativesources.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/plugins/com/nokia/StockChartExample ++ ++sources.files += stockchart.pro model.h model.cpp plugin.cpp README ++sources.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/plugins ++target.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/plugins/com/nokia/StockChartExample ++ ++INSTALLS += qdeclarativesources sources target diff --cc examples/quick/canvas/tiger/tiger.js index 0000000,0000000..4be0d26 new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/tiger/tiger.js @@@ -1,0 -1,0 +1,721 @@@ ++var tiger = [ ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.172, ++ "path":"M-122.304 84.285C-122.304 84.285 -122.203 86.179 -123.027 86.16C-123.851 86.141 -140.305 38.066 -160.833 40.309C-160.833 40.309 -143.05 32.956 -122.304 84.285z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.172, ++ "path":"M-118.774 81.262C-118.774 81.262 -119.323 83.078 -120.092 82.779C-120.86 82.481 -119.977 31.675 -140.043 26.801C-140.043 26.801 -120.82 25.937 -118.774 81.262z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.172, ++ "path":"M-91.284 123.59C-91.284 123.59 -89.648 124.55 -90.118 125.227C-90.589 125.904 -139.763 113.102 -149.218 131.459C-149.218 131.459 -145.539 112.572 -91.284 123.59z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.172, ++ "path":"M-94.093 133.801C-94.093 133.801 -92.237 134.197 -92.471 134.988C-92.704 135.779 -143.407 139.121 -146.597 159.522C-146.597 159.522 -149.055 140.437 -94.093 133.801z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.172, ++ "path":"M-98.304 128.276C-98.304 128.276 -96.526 128.939 -96.872 129.687C-97.218 130.435 -147.866 126.346 -153.998 146.064C-153.998 146.064 -153.646 126.825 -98.304 128.276z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.172, ++ "path":"M-109.009 110.072C-109.009 110.072 -107.701 111.446 -108.34 111.967C-108.979 112.488 -152.722 86.634 -166.869 101.676C-166.869 101.676 -158.128 84.533 -109.009 110.072z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.172, ++ "path":"M-116.554 114.263C-116.554 114.263 -115.098 115.48 -115.674 116.071C-116.25 116.661 -162.638 95.922 -174.992 112.469C-174.992 112.469 -168.247 94.447 -116.554 114.263z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.172, ++ "path":"M-119.154 118.335C-119.154 118.335 -117.546 119.343 -118.036 120.006C-118.526 120.669 -167.308 106.446 -177.291 124.522C-177.291 124.522 -173.066 105.749 -119.154 118.335z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.172, ++ "path":"M-108.42 118.949C-108.42 118.949 -107.298 120.48 -107.999 120.915C-108.7 121.35 -148.769 90.102 -164.727 103.207C-164.727 103.207 -153.862 87.326 -108.42 118.949z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.172, ++ "path":"M-128.2 90C-128.2 90 -127.6 91.8 -128.4 92C-129.2 92.2 -157.8 50.2 -177.001 57.8C-177.001 57.8 -161.8 46 -128.2 90z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.172, ++ "path":"M-127.505 96.979C-127.505 96.979 -126.53 98.608 -127.269 98.975C-128.007 99.343 -164.992 64.499 -182.101 76.061C-182.101 76.061 -169.804 61.261 -127.505 96.979z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.172, ++ "path":"M-127.62 101.349C-127.62 101.349 -126.498 102.88 -127.199 103.315C-127.9 103.749 -167.969 72.502 -183.927 85.607C-183.927 85.607 -173.062 69.726 -127.62 101.349z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", ++ "path":"M-129.83 103.065C-129.327 109.113 -128.339 115.682 -126.6 118.801C-126.6 118.801 -130.2 131.201 -121.4 144.401C-121.4 144.401 -121.8 151.601 -120.2 154.801C-120.2 154.801 -116.2 163.201 -111.4 164.001C-107.516 164.648 -98.793 167.717 -88.932 169.121C-88.932 169.121 -71.8 183.201 -75 196.001C-75 196.001 -75.4 212.401 -79 214.001C-79 214.001 -67.4 202.801 -77 219.601L-81.4 238.401C-81.4 238.401 -55.8 216.801 -71.4 235.201L-81.4 261.201C-81.4 261.201 -61.8 242.801 -69 251.201L-72.2 260.001C-72.2 260.001 -29 232.801 -59.8 262.401C-59.8 262.401 -51.8 258.801 -47.4 261.601C-47.4 261.601 -40.6 260.401 -41.4 262.001C-41.4 262.001 -62.2 272.401 -65.8 290.801C-65.8 290.801 -57.4 280.801 -60.6 291.601L-60.2 303.201C-60.2 303.201 -56.2 281.601 -56.6 319.201C-56.6 319.201 -37.4 301.201 -49 322.001L-49 338.801C-49 338.801 -33.8 322.401 -40.2 335.201C-40.2 335.201 -30.2 326.401 -34.2 341.601C-34.2 341.601 -35 352.001 -30.6 340.801C-30.6 340.801 -14.6 310.201 -20.6 336.401C-20.6 336.401 -21.4 355.601 -16.6 340.801C-16.6 340.801 -16.2 351.201 -7 358.401C-7 358.401 -8.2 307.601 4.6 343.601L8.6 360.001C8.6 360.001 11.4 350.801 11 345.601C11 345.601 25.8 329.201 19 353.601C19 353.601 34.2 330.801 31 344.001C31 344.001 23.4 360.001 25 364.801C25 364.801 41.8 330.001 43 328.401C43 328.401 41 370.802 51.8 334.801C51.8 334.801 57.4 346.801 54.6 351.201C54.6 351.201 62.6 343.201 61.8 340.001C61.8 340.001 66.4 331.801 69.2 345.401C69.2 345.401 71 354.801 72.6 351.601C72.6 351.601 76.6 375.602 77.8 352.801C77.8 352.801 79.4 339.201 72.2 327.601C72.2 327.601 73 324.401 70.2 320.401C70.2 320.401 83.8 342.001 76.6 313.201C76.6 313.201 87.801 321.201 89.001 321.201C89.001 321.201 75.4 298.001 84.2 302.801C84.2 302.801 79 292.401 97.001 304.401C97.001 304.401 81 288.401 98.601 298.001C98.601 298.001 106.601 304.401 99.001 294.401C99.001 294.401 84.6 278.401 106.601 296.401C106.601 296.401 118.201 312.801 119.001 315.601C119.001 315.601 109.001 286.401 104.601 283.601C104.601 283.601 113.001 247.201 154.201 262.801C154.201 262.801 161.001 280.001 165.401 261.601C165.401 261.601 178.201 255.201 189.401 282.801C189.401 282.801 193.401 269.201 192.601 266.401C192.601 266.401 199.401 267.601 198.601 266.401C198.601 266.401 211.801 270.801 213.001 270.001C213.001 270.001 219.801 276.801 220.201 273.201C220.201 273.201 229.401 276.001 227.401 272.401C227.401 272.401 236.201 288.001 236.601 291.601L239.001 277.601L241.001 280.401C241.001 280.401 242.601 272.801 241.801 271.601C241.001 270.401 261.801 278.401 266.601 299.201L268.601 307.601C268.601 307.601 274.601 292.801 273.001 288.801C273.001 288.801 278.201 289.601 278.601 294.001C278.601 294.001 282.601 270.801 277.801 264.801C277.801 264.801 282.201 264.001 283.401 267.601L283.401 260.401C283.401 260.401 290.601 261.201 290.601 258.801C290.601 258.801 295.001 254.801 297.001 259.601C297.001 259.601 284.601 224.401 303.001 243.601C303.001 243.601 310.201 254.401 306.601 235.601C303.001 216.801 299.001 215.201 303.801 214.801C303.801 214.801 304.601 211.201 302.601 209.601C300.601 208.001 303.801 209.601 303.801 209.601C303.801 209.601 308.601 213.601 303.401 191.601C303.401 191.601 309.801 193.201 297.801 164.001C297.801 164.001 300.601 161.601 296.601 153.201C296.601 153.201 304.601 157.601 307.401 156.001C307.401 156.001 307.001 154.401 303.801 150.401C303.801 150.401 282.201 95.6 302.601 117.601C302.601 117.601 314.451 131.151 308.051 108.351C308.051 108.351 298.94 84.341 299.717 80.045L-129.83 103.065z"} ++ , ++ {"fill": "#cc7226", "stroke":"#000000", ++ "path":"M299.717 80.245C300.345 80.426 302.551 81.55 303.801 83.2C303.801 83.2 310.601 94 305.401 75.6C305.401 75.6 296.201 46.8 305.001 58C305.001 58 311.001 65.2 307.801 51.6C303.936 35.173 301.401 28.8 301.401 28.8C301.401 28.8 313.001 33.6 286.201 -6L295.001 -2.4C295.001 -2.4 275.401 -42 253.801 -47.2L245.801 -53.2C245.801 -53.2 284.201 -91.2 271.401 -128C271.401 -128 264.601 -133.2 255.001 -124C255.001 -124 248.601 -119.2 242.601 -120.8C242.601 -120.8 211.801 -119.6 209.801 -119.6C207.801 -119.6 173.001 -156.8 107.401 -139.2C107.401 -139.2 102.201 -137.2 97.801 -138.4C97.801 -138.4 79.4 -154.4 30.6 -131.6C30.6 -131.6 20.6 -129.6 19 -129.6C17.4 -129.6 14.6 -129.6 6.6 -123.2C-1.4 -116.8 -1.8 -116 -3.8 -114.4C-3.8 -114.4 -20.2 -103.2 -25 -102.4C-25 -102.4 -36.6 -96 -41 -86L-44.6 -84.8C-44.6 -84.8 -46.2 -77.6 -46.6 -76.4C-46.6 -76.4 -51.4 -72.8 -52.2 -67.2C-52.2 -67.2 -61 -61.2 -60.6 -56.8C-60.6 -56.8 -62.2 -51.6 -63 -46.8C-63 -46.8 -70.2 -42 -69.4 -39.2C-69.4 -39.2 -77 -25.2 -75.8 -18.4C-75.8 -18.4 -82.2 -18.8 -85 -16.4C-85 -16.4 -85.8 -11.6 -87.4 -11.2C-87.4 -11.2 -90.2 -10 -87.8 -6C-87.8 -6 -89.4 -3.2 -89.8 -1.6C-89.8 -1.6 -89 1.2 -93.4 6.8C-93.4 6.8 -99.8 25.6 -97.8 30.8C-97.8 30.8 -97.4 35.6 -100.2 37.2C-100.2 37.2 -103.8 36.8 -95.4 48.8C-95.4 48.8 -94.6 50 -97.8 52.4C-97.8 52.4 -115 56 -117.4 72.4C-117.4 72.4 -131 87.2 -131 92.4C-131 94.705 -130.729 97.852 -130.03 102.465C-130.03 102.465 -130.6 110.801 -103 111.601C-75.4 112.401 299.717 80.245 299.717 80.245z"} ++ , ++ {"fill": "#cc7226", ++ "path":"M-115.6 102.6C-140.6 63.2 -126.2 119.601 -126.2 119.601C-117.4 154.001 12.2 116.401 12.2 116.401C12.2 116.401 181.001 86 192.201 82C203.401 78 298.601 84.4 298.601 84.4L293.001 67.6C228.201 21.2 209.001 44.4 195.401 40.4C181.801 36.4 184.201 46 181.001 46.8C177.801 47.6 138.601 22.8 132.201 23.6C125.801 24.4 100.459 0.649 115.401 32.4C131.401 66.4 57 71.6 40.2 60.4C23.4 49.2 47.4 78.8 47.4 78.8C65.8 98.8 31.4 82 31.4 82C-3 69.2 -27 94.8 -30.2 95.6C-33.4 96.4 -38.2 99.6 -39 93.2C-39.8 86.8 -47.31 70.099 -79 96.4C-99 113.001 -112.8 91 -112.8 91L-115.6 102.6z"} ++ , ++ {"fill": "#e87f3a", ++ "path":"M133.51 25.346C127.11 26.146 101.743 2.407 116.71 34.146C133.31 69.346 58.31 73.346 41.51 62.146C24.709 50.946 48.71 80.546 48.71 80.546C67.11 100.546 32.709 83.746 32.709 83.746C-1.691 70.946 -25.691 96.546 -28.891 97.346C-32.091 98.146 -36.891 101.346 -37.691 94.946C-38.491 88.546 -45.87 72.012 -77.691 98.146C-98.927 115.492 -112.418 94.037 -112.418 94.037L-115.618 104.146C-140.618 64.346 -125.546 122.655 -125.546 122.655C-116.745 157.056 13.509 118.146 13.509 118.146C13.509 118.146 182.31 87.746 193.51 83.746C204.71 79.746 299.038 86.073 299.038 86.073L293.51 68.764C228.71 22.364 210.31 46.146 196.71 42.146C183.11 38.146 185.51 47.746 182.31 48.546C179.11 49.346 139.91 24.546 133.51 25.346z"} ++ , ++ {"fill": "#ea8c4d", ++ "path":"M134.819 27.091C128.419 27.891 103.685 3.862 118.019 35.891C134.219 72.092 59.619 75.092 42.819 63.892C26.019 52.692 50.019 82.292 50.019 82.292C68.419 102.292 34.019 85.492 34.019 85.492C-0.381 72.692 -24.382 98.292 -27.582 99.092C-30.782 99.892 -35.582 103.092 -36.382 96.692C-37.182 90.292 -44.43 73.925 -76.382 99.892C-98.855 117.983 -112.036 97.074 -112.036 97.074L-115.636 105.692C-139.436 66.692 -124.891 125.71 -124.891 125.71C-116.091 160.11 14.819 119.892 14.819 119.892C14.819 119.892 183.619 89.492 194.819 85.492C206.019 81.492 299.474 87.746 299.474 87.746L294.02 69.928C229.219 23.528 211.619 47.891 198.019 43.891C184.419 39.891 186.819 49.491 183.619 50.292C180.419 51.092 141.219 26.291 134.819 27.091z"} ++ , ++ {"fill": "#ec9961", ++ "path":"M136.128 28.837C129.728 29.637 104.999 5.605 119.328 37.637C136.128 75.193 60.394 76.482 44.128 65.637C27.328 54.437 51.328 84.037 51.328 84.037C69.728 104.037 35.328 87.237 35.328 87.237C0.928 74.437 -23.072 100.037 -26.272 100.837C-29.472 101.637 -34.272 104.837 -35.072 98.437C-35.872 92.037 -42.989 75.839 -75.073 101.637C-98.782 120.474 -111.655 100.11 -111.655 100.11L-115.655 107.237C-137.455 70.437 -124.236 128.765 -124.236 128.765C-115.436 163.165 16.128 121.637 16.128 121.637C16.128 121.637 184.928 91.237 196.129 87.237C207.329 83.237 299.911 89.419 299.911 89.419L294.529 71.092C229.729 24.691 212.929 49.637 199.329 45.637C185.728 41.637 188.128 51.237 184.928 52.037C181.728 52.837 142.528 28.037 136.128 28.837z"} ++ , ++ {"fill": "#eea575", ++ "path":"M137.438 30.583C131.037 31.383 106.814 7.129 120.637 39.383C137.438 78.583 62.237 78.583 45.437 67.383C28.637 56.183 52.637 85.783 52.637 85.783C71.037 105.783 36.637 88.983 36.637 88.983C2.237 76.183 -21.763 101.783 -24.963 102.583C-28.163 103.383 -32.963 106.583 -33.763 100.183C-34.563 93.783 -41.548 77.752 -73.763 103.383C-98.709 122.965 -111.273 103.146 -111.273 103.146L-115.673 108.783C-135.473 73.982 -123.582 131.819 -123.582 131.819C-114.782 166.22 17.437 123.383 17.437 123.383C17.437 123.383 186.238 92.983 197.438 88.983C208.638 84.983 300.347 91.092 300.347 91.092L295.038 72.255C230.238 25.855 214.238 51.383 200.638 47.383C187.038 43.383 189.438 52.983 186.238 53.783C183.038 54.583 143.838 29.783 137.438 30.583z"} ++ , ++ {"fill": "#f1b288", ++ "path":"M138.747 32.328C132.347 33.128 106.383 9.677 121.947 41.128C141.147 79.928 63.546 80.328 46.746 69.128C29.946 57.928 53.946 87.528 53.946 87.528C72.346 107.528 37.946 90.728 37.946 90.728C3.546 77.928 -20.454 103.528 -23.654 104.328C-26.854 105.128 -31.654 108.328 -32.454 101.928C-33.254 95.528 -40.108 79.665 -72.454 105.128C-98.636 125.456 -110.891 106.183 -110.891 106.183L-115.691 110.328C-133.691 77.128 -122.927 134.874 -122.927 134.874C-114.127 169.274 18.746 125.128 18.746 125.128C18.746 125.128 187.547 94.728 198.747 90.728C209.947 86.728 300.783 92.764 300.783 92.764L295.547 73.419C230.747 27.019 215.547 53.128 201.947 49.128C188.347 45.128 190.747 54.728 187.547 55.528C184.347 56.328 145.147 31.528 138.747 32.328z"} ++ , ++ {"fill": "#f3bf9c", ++ "path":"M140.056 34.073C133.655 34.873 107.313 11.613 123.255 42.873C143.656 82.874 64.855 82.074 48.055 70.874C31.255 59.674 55.255 89.274 55.255 89.274C73.655 109.274 39.255 92.474 39.255 92.474C4.855 79.674 -19.145 105.274 -22.345 106.074C-25.545 106.874 -30.345 110.074 -31.145 103.674C-31.945 97.274 -38.668 81.578 -71.145 106.874C-98.564 127.947 -110.509 109.219 -110.509 109.219L-115.709 111.874C-131.709 81.674 -122.273 137.929 -122.273 137.929C-113.473 172.329 20.055 126.874 20.055 126.874C20.055 126.874 188.856 96.474 200.056 92.474C211.256 88.474 301.22 94.437 301.22 94.437L296.056 74.583C231.256 28.183 216.856 54.874 203.256 50.874C189.656 46.873 192.056 56.474 188.856 57.274C185.656 58.074 146.456 33.273 140.056 34.073z"} ++ , ++ {"fill": "#f5ccb0", ++ "path":"M141.365 35.819C134.965 36.619 107.523 13.944 124.565 44.619C146.565 84.219 66.164 83.819 49.364 72.619C32.564 61.419 56.564 91.019 56.564 91.019C74.964 111.019 40.564 94.219 40.564 94.219C6.164 81.419 -17.836 107.019 -21.036 107.819C-24.236 108.619 -29.036 111.819 -29.836 105.419C-30.636 99.019 -37.227 83.492 -69.836 108.619C-98.491 130.438 -110.127 112.256 -110.127 112.256L-115.727 113.419C-130.128 85.019 -121.618 140.983 -121.618 140.983C-112.818 175.384 21.364 128.619 21.364 128.619C21.364 128.619 190.165 98.219 201.365 94.219C212.565 90.219 301.656 96.11 301.656 96.11L296.565 75.746C231.765 29.346 218.165 56.619 204.565 52.619C190.965 48.619 193.365 58.219 190.165 59.019C186.965 59.819 147.765 35.019 141.365 35.819z"} ++ , ++ {"fill": "#f8d8c4", ++ "path":"M142.674 37.565C136.274 38.365 108.832 15.689 125.874 46.365C147.874 85.965 67.474 85.565 50.674 74.365C33.874 63.165 57.874 92.765 57.874 92.765C76.274 112.765 41.874 95.965 41.874 95.965C7.473 83.165 -16.527 108.765 -19.727 109.565C-22.927 110.365 -27.727 113.565 -28.527 107.165C-29.327 100.765 -35.786 85.405 -68.527 110.365C-98.418 132.929 -109.745 115.293 -109.745 115.293L-115.745 114.965C-129.346 88.564 -120.963 144.038 -120.963 144.038C-112.163 178.438 22.673 130.365 22.673 130.365C22.673 130.365 191.474 99.965 202.674 95.965C213.874 91.965 302.093 97.783 302.093 97.783L297.075 76.91C232.274 30.51 219.474 58.365 205.874 54.365C192.274 50.365 194.674 59.965 191.474 60.765C188.274 61.565 149.074 36.765 142.674 37.565z"} ++ , ++ {"fill": "#fae5d7", ++ "path":"M143.983 39.31C137.583 40.11 110.529 17.223 127.183 48.11C149.183 88.91 68.783 87.31 51.983 76.11C35.183 64.91 59.183 94.51 59.183 94.51C77.583 114.51 43.183 97.71 43.183 97.71C8.783 84.91 -15.217 110.51 -18.417 111.31C-21.618 112.11 -26.418 115.31 -27.218 108.91C-28.018 102.51 -34.346 87.318 -67.218 112.11C-98.345 135.42 -109.363 118.329 -109.363 118.329L-115.764 116.51C-128.764 92.51 -120.309 147.093 -120.309 147.093C-111.509 181.493 23.983 132.11 23.983 132.11C23.983 132.11 192.783 101.71 203.983 97.71C215.183 93.71 302.529 99.456 302.529 99.456L297.583 78.074C232.783 31.673 220.783 60.11 207.183 56.11C193.583 52.11 195.983 61.71 192.783 62.51C189.583 63.31 150.383 38.51 143.983 39.31z"} ++ , ++ {"fill": "#fcf2eb", ++ "path":"M145.292 41.055C138.892 41.855 112.917 18.411 128.492 49.855C149.692 92.656 70.092 89.056 53.292 77.856C36.492 66.656 60.492 96.256 60.492 96.256C78.892 116.256 44.492 99.456 44.492 99.456C10.092 86.656 -13.908 112.256 -17.108 113.056C-20.308 113.856 -25.108 117.056 -25.908 110.656C-26.708 104.256 -32.905 89.232 -65.908 113.856C-98.273 137.911 -108.982 121.365 -108.982 121.365L-115.782 118.056C-128.582 94.856 -119.654 150.147 -119.654 150.147C-110.854 184.547 25.292 133.856 25.292 133.856C25.292 133.856 194.093 103.456 205.293 99.456C216.493 95.456 302.965 101.128 302.965 101.128L298.093 79.237C233.292 32.837 222.093 61.856 208.493 57.856C194.893 53.855 197.293 63.456 194.093 64.256C190.892 65.056 151.692 40.255 145.292 41.055z"} ++ , ++ {"fill": "#ffffff", ++ "path":"M-115.8 119.601C-128.6 97.6 -119 153.201 -119 153.201C-110.2 187.601 26.6 135.601 26.6 135.601C26.6 135.601 195.401 105.2 206.601 101.2C217.801 97.2 303.401 102.8 303.401 102.8L298.601 80.4C233.801 34 223.401 63.6 209.801 59.6C196.201 55.6 198.601 65.2 195.401 66C192.201 66.8 153.001 42 146.601 42.8C140.201 43.6 114.981 19.793 129.801 51.6C152.028 99.307 69.041 89.227 54.6 79.6C37.8 68.4 61.8 98 61.8 98C80.2 118.001 45.8 101.2 45.8 101.2C11.4 88.4 -12.6 114.001 -15.8 114.801C-19 115.601 -23.8 118.801 -24.6 112.401C-25.4 106 -31.465 91.144 -64.6 115.601C-98.2 140.401 -108.6 124.401 -108.6 124.401L-115.8 119.601z"} ++ , ++ {"fill": "#000000", ++ "path":"M-74.2 149.601C-74.2 149.601 -81.4 161.201 -60.6 174.401C-60.6 174.401 -59.2 175.801 -77.2 171.601C-77.2 171.601 -83.4 169.601 -85 159.201C-85 159.201 -89.8 154.801 -94.6 149.201C-99.4 143.601 -74.2 149.601 -74.2 149.601z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M65.8 102C65.8 102 83.498 128.821 82.9 133.601C81.6 144.001 81.4 153.601 84.6 157.601C87.801 161.601 96.601 194.801 96.601 194.801C96.601 194.801 96.201 196.001 108.601 158.001C108.601 158.001 120.201 142.001 100.201 123.601C100.201 123.601 65 94.8 65.8 102z"} ++ , ++ {"fill": "#000000", ++ "path":"M-54.2 176.401C-54.2 176.401 -43 183.601 -57.4 214.801L-51 212.401C-51 212.401 -51.8 223.601 -55 226.001L-47.8 222.801C-47.8 222.801 -43 230.801 -47 235.601C-47 235.601 -30.2 243.601 -31 250.001C-31 250.001 -24.6 242.001 -28.6 235.601C-32.6 229.201 -39.8 233.201 -39 214.801L-47.8 218.001C-47.8 218.001 -42.2 209.201 -42.2 202.801L-50.2 205.201C-50.2 205.201 -34.731 178.623 -45.4 177.201C-51.4 176.401 -54.2 176.401 -54.2 176.401z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M-21.8 193.201C-21.8 193.201 -19 188.801 -21.8 189.601C-24.6 190.401 -55.8 205.201 -61.8 214.801C-61.8 214.801 -27.4 190.401 -21.8 193.201z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M-11.4 201.201C-11.4 201.201 -8.6 196.801 -11.4 197.601C-14.2 198.401 -45.4 213.201 -51.4 222.801C-51.4 222.801 -17 198.401 -11.4 201.201z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M1.8 186.001C1.8 186.001 4.6 181.601 1.8 182.401C-1 183.201 -32.2 198.001 -38.2 207.601C-38.2 207.601 -3.8 183.201 1.8 186.001z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M-21.4 229.601C-21.4 229.601 -21.4 223.601 -24.2 224.401C-27 225.201 -63 242.801 -69 252.401C-69 252.401 -27 226.801 -21.4 229.601z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M-20.2 218.801C-20.2 218.801 -19 214.001 -21.8 214.801C-23.8 214.801 -50.2 226.401 -56.2 236.001C-56.2 236.001 -26.6 214.401 -20.2 218.801z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M-34.6 266.401L-44.6 274.001C-44.6 274.001 -34.2 266.401 -30.6 267.601C-30.6 267.601 -37.4 278.801 -38.2 284.001C-38.2 284.001 -27.8 271.201 -22.2 271.601C-22.2 271.601 -14.6 272.001 -14.6 282.801C-14.6 282.801 -9 272.401 -5.8 272.801C-5.8 272.801 -4.6 279.201 -5.8 286.001C-5.8 286.001 -1.8 278.401 2.2 280.001C2.2 280.001 8.6 278.001 7.8 289.601C7.8 289.601 7.8 300.001 7 302.801C7 302.801 12.6 276.401 15 276.001C15 276.001 23 274.801 27.8 283.601C27.8 283.601 23.8 276.001 28.6 278.001C28.6 278.001 39.4 279.601 42.6 286.401C42.6 286.401 35.8 274.401 41.4 277.601C41.4 277.601 48.2 277.601 49.4 284.001C49.4 284.001 57.8 305.201 59.8 306.801C59.8 306.801 52.2 285.201 53.8 285.201C53.8 285.201 51.8 273.201 57 288.001C57 288.001 53.8 274.001 59.4 274.801C65 275.601 69.4 285.601 77.8 283.201C77.8 283.201 87.401 288.801 89.401 219.601L-34.6 266.401z"} ++ , ++ {"fill": "#000000", ++ "path":"M-29.8 173.601C-29.8 173.601 -15 167.601 25 173.601C25 173.601 32.2 174.001 39 165.201C45.8 156.401 72.6 149.201 79 151.201L88.601 157.601L89.401 158.801C89.401 158.801 101.801 169.201 102.201 176.801C102.601 184.401 87.801 232.401 78.2 248.401C68.6 264.401 59 276.801 39.8 274.401C39.8 274.401 19 270.401 -6.6 274.401C-6.6 274.401 -35.8 272.801 -38.6 264.801C-41.4 256.801 -27.4 241.601 -27.4 241.601C-27.4 241.601 -23 233.201 -24.2 218.801C-25.4 204.401 -25 176.401 -29.8 173.601z"} ++ , ++ {"fill": "#e5668c", ++ "path":"M-7.8 175.601C0.6 194.001 -29 259.201 -29 259.201C-31 260.801 -16.34 266.846 -6.2 264.401C4.746 261.763 45 266.001 45 266.001C68.6 250.401 81.4 206.001 81.4 206.001C81.4 206.001 91.801 182.001 74.2 178.801C56.6 175.601 -7.8 175.601 -7.8 175.601z"} ++ , ++ {"fill": "#b23259", ++ "path":"M-9.831 206.497C-6.505 193.707 -4.921 181.906 -7.8 175.601C-7.8 175.601 54.6 182.001 65.8 161.201C70.041 153.326 84.801 184.001 84.4 193.601C84.4 193.601 21.4 208.001 6.6 196.801L-9.831 206.497z"} ++ , ++ {"fill": "#a5264c", ++ "path":"M-5.4 222.801C-5.4 222.801 -3.4 230.001 -5.8 234.001C-5.8 234.001 -7.4 234.801 -8.6 235.201C-8.6 235.201 -7.4 238.801 -1.4 240.401C-1.4 240.401 0.6 244.801 3 245.201C5.4 245.601 10.2 251.201 14.2 250.001C18.2 248.801 29.4 244.801 29.4 244.801C29.4 244.801 35 241.601 43.8 245.201C43.8 245.201 46.175 244.399 46.6 240.401C47.1 235.701 50.2 232.001 52.2 230.001C54.2 228.001 63.8 215.201 62.6 214.801C61.4 214.401 -5.4 222.801 -5.4 222.801z"} ++ , ++ {"fill": "#ff727f", "stroke":"#000000", ++ "path":"M-9.8 174.401C-9.8 174.401 -12.6 196.801 -9.4 205.201C-6.2 213.601 -7 215.601 -7.8 219.601C-8.6 223.601 -4.2 233.601 1.4 239.601L13.4 241.201C13.4 241.201 28.6 237.601 37.8 240.401C37.8 240.401 46.794 241.744 50.2 226.801C50.2 226.801 55 220.401 62.2 217.601C69.4 214.801 76.6 173.201 72.6 165.201C68.6 157.201 54.2 152.801 38.2 168.401C22.2 184.001 20.2 167.201 -9.8 174.401z"} ++ , ++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5, ++ "path":"M-8.2 249.201C-8.2 249.201 -9 247.201 -13.4 246.801C-13.4 246.801 -35.8 243.201 -44.2 230.801C-44.2 230.801 -51 225.201 -46.6 236.801C-46.6 236.801 -36.2 257.201 -29.4 260.001C-29.4 260.001 -13 264.001 -8.2 249.201z"} ++ , ++ {"fill": "#cc3f4c", ++ "path":"M71.742 185.229C72.401 177.323 74.354 168.709 72.6 165.201C66.154 152.307 49.181 157.695 38.2 168.401C22.2 184.001 20.2 167.201 -9.8 174.401C-9.8 174.401 -11.545 188.364 -10.705 198.376C-10.705 198.376 26.6 186.801 27.4 192.401C27.4 192.401 29 189.201 38.2 189.201C47.4 189.201 70.142 188.029 71.742 185.229z"} ++ , ++ {"stroke":"#a51926", "width":2, ++ "path":"M28.6 175.201C28.6 175.201 33.4 180.001 29.8 189.601C29.8 189.601 15.4 205.601 17.4 219.601"} ++ , ++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5, ++ "path":"M-19.4 260.001C-19.4 260.001 -23.8 247.201 -15 254.001C-15 254.001 -10.2 256.001 -11.4 257.601C-12.6 259.201 -18.2 263.201 -19.4 260.001z"} ++ , ++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5, ++ "path":"M-14.36 261.201C-14.36 261.201 -17.88 250.961 -10.84 256.401C-10.84 256.401 -6.419 258.849 -7.96 259.281C-12.52 260.561 -7.96 263.121 -14.36 261.201z"} ++ , ++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5, ++ "path":"M-9.56 261.201C-9.56 261.201 -13.08 250.961 -6.04 256.401C-6.04 256.401 -1.665 258.711 -3.16 259.281C-6.52 260.561 -3.16 263.121 -9.56 261.201z"} ++ , ++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5, ++ "path":"M-2.96 261.401C-2.96 261.401 -6.48 251.161 0.56 256.601C0.56 256.601 4.943 258.933 3.441 259.481C0.48 260.561 3.441 263.321 -2.96 261.401z"} ++ , ++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5, ++ "path":"M3.52 261.321C3.52 261.321 0 251.081 7.041 256.521C7.041 256.521 10.881 258.121 9.921 259.401C8.961 260.681 9.921 263.241 3.52 261.321z"} ++ , ++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5, ++ "path":"M10.2 262.001C10.2 262.001 5.4 249.601 14.6 256.001C14.6 256.001 19.4 258.001 18.2 259.601C17 261.201 18.2 264.401 10.2 262.001z"} ++ , ++ {"stroke":"#a5264c", "width":2, ++ "path":"M-18.2 244.801C-18.2 244.801 -5 242.001 1 245.201C1 245.201 7 246.401 8.2 246.001C9.4 245.601 12.6 245.201 12.6 245.201"} ++ , ++ {"stroke":"#a5264c", "width":2, ++ "path":"M15.8 253.601C15.8 253.601 27.8 240.001 39.8 244.401C46.816 246.974 45.8 243.601 46.6 240.801C47.4 238.001 47.6 233.801 52.6 230.801"} ++ , ++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5, ++ "path":"M33 237.601C33 237.601 29 226.801 26.2 239.601C23.4 252.401 20.2 256.001 18.6 258.801C18.6 258.801 18.6 264.001 27 263.601C27 263.601 37.8 263.201 38.2 260.401C38.6 257.601 37 246.001 33 237.601z"} ++ , ++ {"stroke":"#a5264c", "width":2, ++ "path":"M47 244.801C47 244.801 50.6 242.401 53 243.601"} ++ , ++ {"stroke":"#a5264c", "width":2, ++ "path":"M53.5 228.401C53.5 228.401 56.4 223.501 61.2 222.701"} ++ , ++ {"fill": "#b2b2b2", ++ "path":"M-25.8 265.201C-25.8 265.201 -7.8 268.401 -3.4 266.801C-3.4 266.801 5.4 266.801 -3 268.801C-3 268.801 -15.8 268.801 -23.8 267.601C-23.8 267.601 -35.4 262.001 -25.8 265.201z"} ++ , ++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5, ++ "path":"M-11.8 172.001C-11.8 172.001 5.8 172.001 7.8 172.801C7.8 172.801 15 203.601 11.4 211.201C11.4 211.201 10.2 214.001 7.4 208.401C7.4 208.401 -11 175.601 -14.2 173.601C-17.4 171.601 -13 172.001 -11.8 172.001z"} ++ , ++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5, ++ "path":"M-88.9 169.301C-88.9 169.301 -80 171.001 -67.4 173.601C-67.4 173.601 -62.6 196.001 -59.4 200.801C-56.2 205.601 -59.8 205.601 -63.4 202.801C-67 200.001 -81.8 186.001 -83.8 181.601C-85.8 177.201 -88.9 169.301 -88.9 169.301z"} ++ , ++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5, ++ "path":"M-67.039 173.818C-67.039 173.818 -61.239 175.366 -60.23 177.581C-59.222 179.795 -61.432 183.092 -61.432 183.092C-61.432 183.092 -62.432 186.397 -63.634 184.235C-64.836 182.072 -67.708 174.412 -67.039 173.818z"} ++ , ++ {"fill": "#000000", ++ "path":"M-67 173.601C-67 173.601 -63.4 178.801 -59.8 178.801C-56.2 178.801 -55.818 178.388 -53 179.001C-48.4 180.001 -48.8 178.001 -42.2 179.201C-39.56 179.681 -37 178.801 -34.2 180.001C-31.4 181.201 -28.2 180.401 -27 178.401C-25.8 176.401 -21 172.201 -21 172.201C-21 172.201 -33.8 174.001 -36.6 174.801C-36.6 174.801 -59 176.001 -67 173.601z"} ++ , ++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5, ++ "path":"M-22.4 173.801C-22.4 173.801 -28.85 177.301 -29.25 179.701C-29.65 182.101 -24 185.801 -24 185.801C-24 185.801 -21.25 190.401 -20.65 188.001C-20.05 185.601 -21.6 174.201 -22.4 173.801z"} ++ , ++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5, ++ "path":"M-59.885 179.265C-59.885 179.265 -52.878 190.453 -52.661 179.242C-52.661 179.242 -52.104 177.984 -53.864 177.962C-59.939 177.886 -58.418 173.784 -59.885 179.265z"} ++ , ++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5, ++ "path":"M-52.707 179.514C-52.707 179.514 -44.786 190.701 -45.422 179.421C-45.422 179.421 -45.415 179.089 -47.168 178.936C-51.915 178.522 -51.57 174.004 -52.707 179.514z"} ++ , ++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5, ++ "path":"M-45.494 179.522C-45.494 179.522 -37.534 190.15 -38.203 180.484C-38.203 180.484 -38.084 179.251 -39.738 178.95C-43.63 178.244 -43.841 174.995 -45.494 179.522z"} ++ , ++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5, ++ "path":"M-38.618 179.602C-38.618 179.602 -30.718 191.163 -30.37 181.382C-30.37 181.382 -28.726 180.004 -30.472 179.782C-36.29 179.042 -35.492 174.588 -38.618 179.602z"} ++ , ++ {"fill": "#e5e5b2", ++ "path":"M-74.792 183.132L-82.45 181.601C-85.05 176.601 -87.15 170.451 -87.15 170.451C-87.15 170.451 -80.8 171.451 -68.3 174.251C-68.3 174.251 -67.424 177.569 -65.952 183.364L-74.792 183.132z"} ++ , ++ {"fill": "#e5e5b2", ++ "path":"M-9.724 178.47C-11.39 175.964 -12.707 174.206 -13.357 173.8C-16.37 171.917 -12.227 172.294 -11.098 172.294C-11.098 172.294 5.473 172.294 7.356 173.047C7.356 173.047 7.88 175.289 8.564 178.68C8.564 178.68 -1.524 176.67 -9.724 178.47z"} ++ , ++ {"fill": "#cc7226", ++ "path":"M43.88 40.321C71.601 44.281 97.121 8.641 98.881 -1.04C100.641 -10.72 90.521 -22.6 90.521 -22.6C91.841 -25.68 87.001 -39.76 81.721 -49C76.441 -58.24 60.54 -57.266 43 -58.24C27.16 -59.12 8.68 -35.8 7.36 -34.04C6.04 -32.28 12.2 6.001 13.52 11.721C14.84 17.441 12.2 43.841 12.2 43.841C46.44 34.741 16.16 36.361 43.88 40.321z"} ++ , ++ {"fill": "#ea8e51", ++ "path":"M8.088 -33.392C6.792 -31.664 12.84 5.921 14.136 11.537C15.432 17.153 12.84 43.073 12.84 43.073C45.512 34.193 16.728 35.729 43.944 39.617C71.161 43.505 96.217 8.513 97.945 -0.992C99.673 -10.496 89.737 -22.16 89.737 -22.16C91.033 -25.184 86.281 -39.008 81.097 -48.08C75.913 -57.152 60.302 -56.195 43.08 -57.152C27.528 -58.016 9.384 -35.12 8.088 -33.392z"} ++ , ++ {"fill": "#efaa7c", ++ "path":"M8.816 -32.744C7.544 -31.048 13.48 5.841 14.752 11.353C16.024 16.865 13.48 42.305 13.48 42.305C44.884 33.145 17.296 35.097 44.008 38.913C70.721 42.729 95.313 8.385 97.009 -0.944C98.705 -10.272 88.953 -21.72 88.953 -21.72C90.225 -24.688 85.561 -38.256 80.473 -47.16C75.385 -56.064 60.063 -55.125 43.16 -56.064C27.896 -56.912 10.088 -34.44 8.816 -32.744z"} ++ , ++ {"fill": "#f4c6a8", ++ "path":"M9.544 -32.096C8.296 -30.432 14.12 5.761 15.368 11.169C16.616 16.577 14.12 41.537 14.12 41.537C43.556 32.497 17.864 34.465 44.072 38.209C70.281 41.953 94.409 8.257 96.073 -0.895C97.737 -10.048 88.169 -21.28 88.169 -21.28C89.417 -24.192 84.841 -37.504 79.849 -46.24C74.857 -54.976 59.824 -54.055 43.24 -54.976C28.264 -55.808 10.792 -33.76 9.544 -32.096z"} ++ , ++ {"fill": "#f9e2d3", ++ "path":"M10.272 -31.448C9.048 -29.816 14.76 5.681 15.984 10.985C17.208 16.289 14.76 40.769 14.76 40.769C42.628 31.849 18.432 33.833 44.136 37.505C69.841 41.177 93.505 8.129 95.137 -0.848C96.769 -9.824 87.385 -20.84 87.385 -20.84C88.609 -23.696 84.121 -36.752 79.225 -45.32C74.329 -53.888 59.585 -52.985 43.32 -53.888C28.632 -54.704 11.496 -33.08 10.272 -31.448z"} ++ , ++ {"fill": "#ffffff", ++ "path":"M44.2 36.8C69.4 40.4 92.601 8 94.201 -0.8C95.801 -9.6 86.601 -20.4 86.601 -20.4C87.801 -23.2 83.4 -36 78.6 -44.4C73.8 -52.8 59.346 -51.914 43.4 -52.8C29 -53.6 12.2 -32.4 11 -30.8C9.8 -29.2 15.4 5.6 16.6 10.8C17.8 16 15.4 40 15.4 40C40.9 31.4 19 33.2 44.2 36.8z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M90.601 2.8C90.601 2.8 62.8 10.4 51.2 8.8C51.2 8.8 35.4 2.2 26.6 24C26.6 24 23 31.2 21 33.2C19 35.2 90.601 2.8 90.601 2.8z"} ++ , ++ {"fill": "#000000", ++ "path":"M94.401 0.6C94.401 0.6 65.4 12.8 55.4 12.4C55.4 12.4 39 7.8 30.6 22.4C30.6 22.4 22.2 31.6 19 33.2C19 33.2 18.6 34.8 25 30.8L35.4 36C35.4 36 50.2 45.6 59.8 29.6C59.8 29.6 63.8 18.4 63.8 16.4C63.8 14.4 85 8.8 86.601 8.4C88.201 8 94.801 3.8 94.401 0.6z"} ++ , ++ {"fill": "#99cc32", ++ "path":"M47 36.514C40.128 36.514 31.755 32.649 31.755 26.4C31.755 20.152 40.128 13.887 47 13.887C53.874 13.887 59.446 18.952 59.446 25.2C59.446 31.449 53.874 36.514 47 36.514z"} ++ , ++ {"fill": "#659900", ++ "path":"M43.377 19.83C38.531 20.552 33.442 22.055 33.514 21.839C35.054 17.22 41.415 13.887 47 13.887C51.296 13.887 55.084 15.865 57.32 18.875C57.32 18.875 52.004 18.545 43.377 19.83z"} ++ , ++ {"fill": "#ffffff", ++ "path":"M55.4 19.6C55.4 19.6 51 16.4 51 18.6C51 18.6 54.6 23 55.4 19.6z"} ++ , ++ {"fill": "#000000", ++ "path":"M45.4 27.726C42.901 27.726 40.875 25.7 40.875 23.2C40.875 20.701 42.901 18.675 45.4 18.675C47.9 18.675 49.926 20.701 49.926 23.2C49.926 25.7 47.9 27.726 45.4 27.726z"} ++ , ++ {"fill": "#cc7226", ++ "path":"M-58.6 14.4C-58.6 14.4 -61.8 -6.8 -59.4 -11.2C-59.4 -11.2 -48.6 -21.2 -49 -24.8C-49 -24.8 -49.4 -42.8 -50.6 -43.6C-51.8 -44.4 -59.4 -50.4 -65.4 -44C-65.4 -44 -75.8 -26 -75 -19.6L-75 -17.6C-75 -17.6 -82.6 -18 -84.2 -16C-84.2 -16 -85.4 -10.8 -86.6 -10.4C-86.6 -10.4 -89.4 -8 -87.4 -5.2C-87.4 -5.2 -89.4 -2.8 -89 1.2L-81.4 5.2C-81.4 5.2 -79.4 19.6 -68.6 24.8C-63.764 27.129 -60.6 20.4 -58.6 14.4z"} ++ , ++ {"fill": "#ffffff", ++ "path":"M-59.6 12.56C-59.6 12.56 -62.48 -6.52 -60.32 -10.48C-60.32 -10.48 -50.6 -19.48 -50.96 -22.72C-50.96 -22.72 -51.32 -38.92 -52.4 -39.64C-53.48 -40.36 -60.32 -45.76 -65.72 -40C-65.72 -40 -75.08 -23.8 -74.36 -18.04L-74.36 -16.24C-74.36 -16.24 -81.2 -16.6 -82.64 -14.8C-82.64 -14.8 -83.72 -10.12 -84.8 -9.76C-84.8 -9.76 -87.32 -7.6 -85.52 -5.08C-85.52 -5.08 -87.32 -2.92 -86.96 0.68L-80.12 4.28C-80.12 4.28 -78.32 17.24 -68.6 21.92C-64.248 24.015 -61.4 17.96 -59.6 12.56z"} ++ , ++ {"fill": "#eb955c", ++ "path":"M-51.05 -42.61C-52.14 -43.47 -59.63 -49.24 -65.48 -43C-65.48 -43 -75.62 -25.45 -74.84 -19.21L-74.84 -17.26C-74.84 -17.26 -82.25 -17.65 -83.81 -15.7C-83.81 -15.7 -84.98 -10.63 -86.15 -10.24C-86.15 -10.24 -88.88 -7.9 -86.93 -5.17C-86.93 -5.17 -88.88 -2.83 -88.49 1.07L-81.08 4.97C-81.08 4.97 -79.13 19.01 -68.6 24.08C-63.886 26.35 -60.8 19.79 -58.85 13.94C-58.85 13.94 -61.97 -6.73 -59.63 -11.02C-59.63 -11.02 -49.1 -20.77 -49.49 -24.28C-49.49 -24.28 -49.88 -41.83 -51.05 -42.61z"} ++ , ++ {"fill": "#f2b892", ++ "path":"M-51.5 -41.62C-52.48 -42.54 -59.86 -48.08 -65.56 -42C-65.56 -42 -75.44 -24.9 -74.68 -18.82L-74.68 -16.92C-74.68 -16.92 -81.9 -17.3 -83.42 -15.4C-83.42 -15.4 -84.56 -10.46 -85.7 -10.08C-85.7 -10.08 -88.36 -7.8 -86.46 -5.14C-86.46 -5.14 -88.36 -2.86 -87.98 0.94L-80.76 4.74C-80.76 4.74 -78.86 18.42 -68.6 23.36C-64.006 25.572 -61 19.18 -59.1 13.48C-59.1 13.48 -62.14 -6.66 -59.86 -10.84C-59.86 -10.84 -49.6 -20.34 -49.98 -23.76C-49.98 -23.76 -50.36 -40.86 -51.5 -41.62z"} ++ , ++ {"fill": "#f8dcc8", ++ "path":"M-51.95 -40.63C-52.82 -41.61 -60.09 -46.92 -65.64 -41C-65.64 -41 -75.26 -24.35 -74.52 -18.43L-74.52 -16.58C-74.52 -16.58 -81.55 -16.95 -83.03 -15.1C-83.03 -15.1 -84.14 -10.29 -85.25 -9.92C-85.25 -9.92 -87.84 -7.7 -85.99 -5.11C-85.99 -5.11 -87.84 -2.89 -87.47 0.81L-80.44 4.51C-80.44 4.51 -78.59 17.83 -68.6 22.64C-64.127 24.794 -61.2 18.57 -59.35 13.02C-59.35 13.02 -62.31 -6.59 -60.09 -10.66C-60.09 -10.66 -50.1 -19.91 -50.47 -23.24C-50.47 -23.24 -50.84 -39.89 -51.95 -40.63z"} ++ , ++ {"fill": "#ffffff", ++ "path":"M-59.6 12.46C-59.6 12.46 -62.48 -6.52 -60.32 -10.48C-60.32 -10.48 -50.6 -19.48 -50.96 -22.72C-50.96 -22.72 -51.32 -38.92 -52.4 -39.64C-53.16 -40.68 -60.32 -45.76 -65.72 -40C-65.72 -40 -75.08 -23.8 -74.36 -18.04L-74.36 -16.24C-74.36 -16.24 -81.2 -16.6 -82.64 -14.8C-82.64 -14.8 -83.72 -10.12 -84.8 -9.76C-84.8 -9.76 -87.32 -7.6 -85.52 -5.08C-85.52 -5.08 -87.32 -2.92 -86.96 0.68L-80.12 4.28C-80.12 4.28 -78.32 17.24 -68.6 21.92C-64.248 24.015 -61.4 17.86 -59.6 12.46z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M-62.7 6.2C-62.7 6.2 -84.3 -4 -85.2 -4.8C-85.2 -4.8 -76.1 3.4 -75.3 3.4C-74.5 3.4 -62.7 6.2 -62.7 6.2z"} ++ , ++ {"fill": "#000000", ++ "path":"M-79.8 0C-79.8 0 -61.4 3.6 -61.4 8C-61.4 10.912 -61.643 24.331 -67 22.8C-75.4 20.4 -71.8 6 -79.8 0z"} ++ , ++ {"fill": "#99cc32", ++ "path":"M-71.4 3.8C-71.4 3.8 -62.422 5.274 -61.4 8C-60.8 9.6 -60.137 17.908 -65.6 19C-70.152 19.911 -72.382 9.69 -71.4 3.8z"} ++ , ++ {"fill": "#000000", ++ "path":"M14.595 46.349C14.098 44.607 15.409 44.738 17.2 44.2C19.2 43.6 31.4 39.8 32.2 37.2C33 34.6 46.2 39 46.2 39C48 39.8 52.4 42.4 52.4 42.4C57.2 43.6 63.8 44 63.8 44C66.2 45 69.6 47.8 69.6 47.8C84.2 58 96.601 50.8 96.601 50.8C116.601 44.2 110.601 27 110.601 27C107.601 18 110.801 14.6 110.801 14.6C111.001 10.8 118.201 17.2 118.201 17.2C120.801 21.4 121.601 26.4 121.601 26.4C129.601 37.6 126.201 19.8 126.201 19.8C126.401 18.8 123.601 15.2 123.601 14C123.601 12.8 121.801 9.4 121.801 9.4C118.801 6 121.201 -1 121.201 -1C123.001 -14.8 120.801 -13 120.801 -13C119.601 -14.8 110.401 -4.8 110.401 -4.8C108.201 -1.4 102.201 0.2 102.201 0.2C99.401 2 96.001 0.6 96.001 0.6C93.401 0.2 87.801 7.2 87.801 7.2C90.601 7 93.001 11.4 95.401 11.6C97.801 11.8 99.601 9.2 101.201 8.6C102.801 8 105.601 13.8 105.601 13.8C106.001 16.4 100.401 21.2 100.401 21.2C100.001 25.8 98.401 24.2 98.401 24.2C95.401 23.6 94.201 27.4 93.201 32C92.201 36.6 88.001 37 88.001 37C86.401 44.4 85.2 41.4 85.2 41.4C85 35.8 79 41.6 79 41.6C77.8 43.6 73.2 41.4 73.2 41.4C66.4 39.4 68.8 37.4 68.8 37.4C70.6 35.2 81.8 37.4 81.8 37.4C84 35.8 76 31.8 76 31.8C75.4 30 76.4 25.6 76.4 25.6C77.6 22.4 84.4 16.8 84.4 16.8C93.801 15.6 91.001 14 91.001 14C84.801 8.8 79 16.4 79 16.4C76.8 22.6 59.4 37.6 59.4 37.6C54.6 41 57.2 34.2 53.2 37.6C49.2 41 28.6 32 28.6 32C17.038 30.807 14.306 46.549 10.777 43.429C10.777 43.429 16.195 51.949 14.595 46.349z"} ++ , ++ {"fill": "#000000", ++ "path":"M209.401 -120C209.401 -120 183.801 -112 181.001 -93.2C181.001 -93.2 178.601 -70.4 199.001 -52.8C199.001 -52.8 199.401 -46.4 201.401 -43.2C201.401 -43.2 199.801 -38.4 218.601 -46L245.801 -54.4C245.801 -54.4 252.201 -56.8 257.401 -65.6C262.601 -74.4 277.801 -93.2 274.201 -118.4C274.201 -118.4 275.401 -129.6 269.401 -130C269.401 -130 261.001 -131.6 253.801 -124C253.801 -124 247.001 -120.8 244.601 -121.2L209.401 -120z"} ++ , ++ {"fill": "#000000", ++ "path":"M264.022 -120.99C264.022 -120.99 266.122 -129.92 261.282 -125.08C261.282 -125.08 254.242 -119.36 246.761 -119.36C246.761 -119.36 232.241 -117.16 227.841 -103.96C227.841 -103.96 223.881 -77.12 231.801 -71.4C231.801 -71.4 236.641 -63.92 243.681 -70.52C250.722 -77.12 266.222 -107.35 264.022 -120.99z"} ++ , ++ {"fill": "#323232", ++ "path":"M263.648 -120.632C263.648 -120.632 265.738 -129.376 260.986 -124.624C260.986 -124.624 254.074 -119.008 246.729 -119.008C246.729 -119.008 232.473 -116.848 228.153 -103.888C228.153 -103.888 224.265 -77.536 232.041 -71.92C232.041 -71.92 236.793 -64.576 243.705 -71.056C250.618 -77.536 265.808 -107.24 263.648 -120.632z"} ++ , ++ {"fill": "#666666", ++ "path":"M263.274 -120.274C263.274 -120.274 265.354 -128.832 260.69 -124.168C260.69 -124.168 253.906 -118.656 246.697 -118.656C246.697 -118.656 232.705 -116.536 228.465 -103.816C228.465 -103.816 224.649 -77.952 232.281 -72.44C232.281 -72.44 236.945 -65.232 243.729 -71.592C250.514 -77.952 265.394 -107.13 263.274 -120.274z"} ++ , ++ {"fill": "#999999", ++ "path":"M262.9 -119.916C262.9 -119.916 264.97 -128.288 260.394 -123.712C260.394 -123.712 253.738 -118.304 246.665 -118.304C246.665 -118.304 232.937 -116.224 228.777 -103.744C228.777 -103.744 225.033 -78.368 232.521 -72.96C232.521 -72.96 237.097 -65.888 243.753 -72.128C250.41 -78.368 264.98 -107.02 262.9 -119.916z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M262.526 -119.558C262.526 -119.558 264.586 -127.744 260.098 -123.256C260.098 -123.256 253.569 -117.952 246.633 -117.952C246.633 -117.952 233.169 -115.912 229.089 -103.672C229.089 -103.672 225.417 -78.784 232.761 -73.48C232.761 -73.48 237.249 -66.544 243.777 -72.664C250.305 -78.784 264.566 -106.91 262.526 -119.558z"} ++ , ++ {"fill": "#ffffff", ++ "path":"M262.151 -119.2C262.151 -119.2 264.201 -127.2 259.801 -122.8C259.801 -122.8 253.401 -117.6 246.601 -117.6C246.601 -117.6 233.401 -115.6 229.401 -103.6C229.401 -103.6 225.801 -79.2 233.001 -74C233.001 -74 237.401 -67.2 243.801 -73.2C250.201 -79.2 264.151 -106.8 262.151 -119.2z"} ++ , ++ {"fill": "#992600", ++ "path":"M50.6 84C50.6 84 30.2 64.8 22.2 64C22.2 64 -12.2 60 -27 78C-27 78 -9.4 57.6 18.2 63.2C18.2 63.2 -3.4 58.8 -15.8 62C-15.8 62 -32.6 62 -42.2 76L-45 80.8C-45 80.8 -41 66 -22.6 60C-22.6 60 0.2 55.2 11 60C11 60 -10.6 53.2 -20.6 55.2C-20.6 55.2 -51 52.8 -63.8 79.2C-63.8 79.2 -59.8 64.8 -45 57.6C-45 57.6 -31.4 48.8 -11 51.6C-11 51.6 3.4 54.8 8.6 57.2C13.8 59.6 12.6 56.8 4.2 52C4.2 52 -1.4 42 -15.4 42.4C-15.4 42.4 -58.2 46 -68.6 58C-68.6 58 -55 46.8 -44.6 44C-44.6 44 -22.2 36 -13.8 36.8C-13.8 36.8 11 37.8 18.6 33.8C18.6 33.8 7.4 38.8 10.6 42C13.8 45.2 20.6 52.8 20.6 54C20.6 55.2 44.8 77.3 48.4 81.7L50.6 84z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M189 278C189 278 173.5 241.5 161 232C161 232 187 248 190.5 266C190.5 266 190.5 276 189 278z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M236 285.5C236 285.5 209.5 230.5 191 206.5C191 206.5 234.5 244 239.5 270.5L240 276L237 273.5C237 273.5 236.5 282.5 236 285.5z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M292.5 237C292.5 237 230 177.5 228.5 175C228.5 175 289 241 292 248.5C292 248.5 290 239.5 292.5 237z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M104 280.5C104 280.5 123.5 228.5 142.5 251C142.5 251 157.5 261 157 264C157 264 153 257.5 135 258C135 258 116 255 104 280.5z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M294.5 153C294.5 153 249.5 124.5 242 123C230.193 120.639 291.5 152 296.5 162.5C296.5 162.5 298.5 160 294.5 153z"} ++ , ++ {"fill": "#000000", ++ "path":"M143.801 259.601C143.801 259.601 164.201 257.601 171.001 250.801L175.401 254.401L193.001 216.001L196.601 221.201C196.601 221.201 211.001 206.401 210.201 198.401C209.401 190.401 223.001 204.401 223.001 204.401C223.001 204.401 222.201 192.801 229.401 199.601C229.401 199.601 227.001 184.001 235.401 192.001C235.401 192.001 224.864 161.844 247.401 187.601C253.001 194.001 248.601 187.201 248.601 187.201C248.601 187.201 222.601 139.201 244.201 153.601C244.201 153.601 246.201 130.801 245.001 126.401C243.801 122.001 241.801 99.6 237.001 94.4C232.201 89.2 237.401 87.6 243.001 92.8C243.001 92.8 231.801 68.8 245.001 80.8C245.001 80.8 241.401 65.6 237.001 62.8C237.001 62.8 231.401 45.6 246.601 56.4C246.601 56.4 242.201 44 239.001 40.8C239.001 40.8 227.401 13.2 234.601 18L239.001 21.6C239.001 21.6 232.201 7.6 238.601 12C245.001 16.4 245.001 16 245.001 16C245.001 16 223.801 -17.2 244.201 0.4C244.201 0.4 236.042 -13.518 232.601 -20.4C232.601 -20.4 213.801 -40.8 228.201 -34.4L233.001 -32.8C233.001 -32.8 224.201 -42.8 216.201 -44.4C208.201 -46 218.601 -52.4 225.001 -50.4C231.401 -48.4 247.001 -40.8 247.001 -40.8C247.001 -40.8 259.801 -22 263.801 -21.6C263.801 -21.6 243.801 -29.2 249.801 -21.2C249.801 -21.2 264.201 -7.2 257.001 -7.6C257.001 -7.6 251.001 -0.4 255.801 8.4C255.801 8.4 237.342 -9.991 252.201 15.6L259.001 32C259.001 32 234.601 7.2 245.801 29.2C245.801 29.2 263.001 52.8 265.001 53.2C267.001 53.6 271.401 62.4 271.401 62.4L267.001 60.4L272.201 69.2C272.201 69.2 261.001 57.2 267.001 70.4L272.601 84.8C272.601 84.8 252.201 62.8 265.801 92.4C265.801 92.4 249.401 87.2 258.201 104.4C258.201 104.4 256.601 120.401 257.001 125.601C257.401 130.801 258.601 159.201 254.201 167.201C249.801 175.201 260.201 194.401 262.201 198.401C264.201 202.401 267.801 213.201 259.001 204.001C250.201 194.801 254.601 200.401 256.601 209.201C258.601 218.001 264.601 233.601 263.801 239.201C263.801 239.201 262.601 240.401 259.401 236.801C259.401 236.801 244.601 214.001 246.201 228.401C246.201 228.401 245.001 236.401 241.801 245.201C241.801 245.201 238.601 256.001 238.601 247.201C238.601 247.201 235.401 230.401 232.601 238.001C229.801 245.601 226.201 251.601 223.401 254.001C220.601 256.401 215.401 233.601 214.201 244.001C214.201 244.001 202.201 231.601 197.401 248.001L185.801 264.401C185.801 264.401 185.401 252.001 184.201 258.001C184.201 258.001 154.201 264.001 143.801 259.601z"} ++ , ++ {"fill": "#000000", ++ "path":"M109.401 -97.2C109.401 -97.2 97.801 -105.2 93.801 -104.8C89.801 -104.4 121.401 -113.6 162.601 -86C162.601 -86 167.401 -83.2 171.001 -83.6C171.001 -83.6 174.201 -81.2 171.401 -77.6C171.401 -77.6 162.601 -68 173.801 -56.8C173.801 -56.8 192.201 -50 186.601 -58.8C186.601 -58.8 197.401 -54.8 199.801 -50.8C202.201 -46.8 201.001 -50.8 201.001 -50.8C201.001 -50.8 194.601 -58 188.601 -63.2C188.601 -63.2 183.401 -65.2 180.601 -73.6C177.801 -82 175.401 -92 179.801 -95.2C179.801 -95.2 175.801 -90.8 176.601 -94.8C177.401 -98.8 181.001 -102.4 182.601 -102.8C184.201 -103.2 200.601 -119 207.401 -119.4C207.401 -119.4 198.201 -118 195.201 -119C192.201 -120 165.601 -131.4 159.601 -132.6C159.601 -132.6 142.801 -139.2 154.801 -137.2C154.801 -137.2 190.601 -133.4 208.801 -120.2C208.801 -120.2 201.601 -128.6 183.201 -135.6C183.201 -135.6 161.001 -148.2 125.801 -143.2C125.801 -143.2 108.001 -140 100.201 -138.2C100.201 -138.2 97.601 -138.8 97.001 -139.2C96.401 -139.6 84.6 -148.6 57 -141.6C57 -141.6 40 -137 31.4 -132.2C31.4 -132.2 16.2 -131 12.6 -127.8C12.6 -127.8 -6 -113.2 -8 -112.4C-10 -111.6 -21.4 -104 -22.2 -103.6C-22.2 -103.6 2.4 -110.2 4.8 -112.6C7.2 -115 24.6 -117.6 27 -116.2C29.4 -114.8 37.8 -115.4 28.2 -114.8C28.2 -114.8 103.801 -100 104.601 -98C105.401 -96 109.401 -97.2 109.401 -97.2z"} ++ , ++ {"fill": "#cc7226", ++ "path":"M180.801 -106.4C180.801 -106.4 170.601 -113.8 168.601 -113.8C166.601 -113.8 154.201 -124 150.001 -123.6C145.801 -123.2 133.601 -133.2 106.201 -125C106.201 -125 105.601 -127 109.201 -127.8C109.201 -127.8 115.601 -130 116.001 -130.6C116.001 -130.6 136.201 -134.8 143.401 -131.2C143.401 -131.2 152.601 -128.6 158.801 -122.4C158.801 -122.4 170.001 -119.2 173.201 -120.2C173.201 -120.2 182.001 -118 182.401 -116.2C182.401 -116.2 188.201 -113.2 186.401 -110.6C186.401 -110.6 186.801 -109 180.801 -106.4z"} ++ , ++ {"fill": "#cc7226", ++ "path":"M168.33 -108.509C169.137 -107.877 170.156 -107.779 170.761 -106.97C170.995 -106.656 170.706 -106.33 170.391 -106.233C169.348 -105.916 168.292 -106.486 167.15 -105.898C166.748 -105.691 166.106 -105.873 165.553 -106.022C163.921 -106.463 162.092 -106.488 160.401 -105.8C158.416 -106.929 156.056 -106.345 153.975 -107.346C153.917 -107.373 153.695 -107.027 153.621 -107.054C150.575 -108.199 146.832 -107.916 144.401 -110.2C141.973 -110.612 139.616 -111.074 137.188 -111.754C135.37 -112.263 133.961 -113.252 132.341 -114.084C130.964 -114.792 129.507 -115.314 127.973 -115.686C126.11 -116.138 124.279 -116.026 122.386 -116.546C122.293 -116.571 122.101 -116.227 122.019 -116.254C121.695 -116.362 121.405 -116.945 121.234 -116.892C119.553 -116.37 118.065 -117.342 116.401 -117C115.223 -118.224 113.495 -117.979 111.949 -118.421C108.985 -119.269 105.831 -117.999 102.801 -119C106.914 -120.842 111.601 -119.61 115.663 -121.679C117.991 -122.865 120.653 -121.763 123.223 -122.523C123.71 -122.667 124.401 -122.869 124.801 -122.2C124.935 -122.335 125.117 -122.574 125.175 -122.546C127.625 -121.389 129.94 -120.115 132.422 -119.049C132.763 -118.903 133.295 -119.135 133.547 -118.933C135.067 -117.717 137.01 -117.82 138.401 -116.6C140.099 -117.102 141.892 -116.722 143.621 -117.346C143.698 -117.373 143.932 -117.032 143.965 -117.054C145.095 -117.802 146.25 -117.531 147.142 -117.227C147.48 -117.112 148.143 -116.865 148.448 -116.791C149.574 -116.515 150.43 -116.035 151.609 -115.852C151.723 -115.834 151.908 -116.174 151.98 -116.146C153.103 -115.708 154.145 -115.764 154.801 -114.6C154.936 -114.735 155.101 -114.973 155.183 -114.946C156.21 -114.608 156.859 -113.853 157.96 -113.612C158.445 -113.506 159.057 -112.88 159.633 -112.704C162.025 -111.973 163.868 -110.444 166.062 -109.549C166.821 -109.239 167.697 -109.005 168.33 -108.509z"} ++ , ++ {"fill": "#cc7226", ++ "path":"M91.696 -122.739C89.178 -124.464 86.81 -125.57 84.368 -127.356C84.187 -127.489 83.827 -127.319 83.625 -127.441C82.618 -128.05 81.73 -128.631 80.748 -129.327C80.209 -129.709 79.388 -129.698 78.88 -129.956C76.336 -131.248 73.707 -131.806 71.2 -133C71.882 -133.638 73.004 -133.394 73.6 -134.2C73.795 -133.92 74.033 -133.636 74.386 -133.827C76.064 -134.731 77.914 -134.884 79.59 -134.794C81.294 -134.702 83.014 -134.397 84.789 -134.125C85.096 -134.078 85.295 -133.555 85.618 -133.458C87.846 -132.795 90.235 -133.32 92.354 -132.482C93.945 -131.853 95.515 -131.03 96.754 -129.755C97.006 -129.495 96.681 -129.194 96.401 -129C96.789 -129.109 97.062 -128.903 97.173 -128.59C97.257 -128.351 97.257 -128.049 97.173 -127.81C97.061 -127.498 96.782 -127.397 96.408 -127.346C95.001 -127.156 96.773 -128.536 96.073 -128.088C94.8 -127.274 95.546 -125.868 94.801 -124.6C94.521 -124.794 94.291 -125.012 94.401 -125.4C94.635 -124.878 94.033 -124.588 93.865 -124.272C93.48 -123.547 92.581 -122.132 91.696 -122.739z"} ++ , ++ {"fill": "#cc7226", ++ "path":"M59.198 -115.391C56.044 -116.185 52.994 -116.07 49.978 -117.346C49.911 -117.374 49.688 -117.027 49.624 -117.054C48.258 -117.648 47.34 -118.614 46.264 -119.66C45.351 -120.548 43.693 -120.161 42.419 -120.648C42.095 -120.772 41.892 -121.284 41.591 -121.323C40.372 -121.48 39.445 -122.429 38.4 -123C40.736 -123.795 43.147 -123.764 45.609 -124.148C45.722 -124.166 45.867 -123.845 46 -123.845C46.136 -123.845 46.266 -124.066 46.4 -124.2C46.595 -123.92 46.897 -123.594 47.154 -123.848C47.702 -124.388 48.258 -124.198 48.798 -124.158C48.942 -124.148 49.067 -123.845 49.2 -123.845C49.336 -123.845 49.467 -124.156 49.6 -124.156C49.736 -124.155 49.867 -123.845 50 -123.845C50.136 -123.845 50.266 -124.066 50.4 -124.2C51.092 -123.418 51.977 -123.972 52.799 -123.793C53.837 -123.566 54.104 -122.418 55.178 -122.12C59.893 -120.816 64.03 -118.671 68.393 -116.584C68.7 -116.437 68.91 -116.189 68.8 -115.8C69.067 -115.8 69.38 -115.888 69.57 -115.756C70.628 -115.024 71.669 -114.476 72.366 -113.378C72.582 -113.039 72.253 -112.632 72.02 -112.684C67.591 -113.679 63.585 -114.287 59.198 -115.391z"} ++ , ++ {"fill": "#cc7226", ++ "path":"M45.338 -71.179C43.746 -72.398 43.162 -74.429 42.034 -76.221C41.82 -76.561 42.094 -76.875 42.411 -76.964C42.971 -77.123 43.514 -76.645 43.923 -76.443C45.668 -75.581 47.203 -74.339 49.2 -74.2C51.19 -71.966 55.45 -71.581 55.457 -68.2C55.458 -67.341 54.03 -68.259 53.6 -67.4C51.149 -68.403 48.76 -68.3 46.38 -69.767C45.763 -70.148 46.093 -70.601 45.338 -71.179z"} ++ , ++ {"fill": "#cc7226", ++ "path":"M17.8 -123.756C17.935 -123.755 24.966 -123.522 24.949 -123.408C24.904 -123.099 17.174 -122.05 16.81 -122.22C16.646 -122.296 9.134 -119.866 9 -120C9.268 -120.135 17.534 -123.756 17.8 -123.756z"} ++ , ++ {"fill": "#000000", ++ "path":"M33.2 -114C33.2 -114 18.4 -112.2 14 -111C9.6 -109.8 -9 -102.2 -12 -100.2C-12 -100.2 -25.4 -94.8 -42.4 -74.8C-42.4 -74.8 -34.8 -78.2 -32.6 -81C-32.6 -81 -19 -93.6 -19.2 -91C-19.2 -91 -7 -99.6 -7.6 -97.4C-7.6 -97.4 16.8 -108.6 14.8 -105.4C14.8 -105.4 36.4 -110 35.4 -108C35.4 -108 54.2 -103.6 51.4 -103.4C51.4 -103.4 45.6 -102.2 52 -98.6C52 -98.6 48.6 -94.2 43.2 -98.2C37.8 -102.2 40.8 -100 35.8 -99C35.8 -99 33.2 -98.2 28.6 -102.2C28.6 -102.2 23 -106.8 14.2 -103.2C14.2 -103.2 -16.4 -90.6 -18.4 -90C-18.4 -90 -22 -87.2 -24.4 -83.6C-24.4 -83.6 -30.2 -79.2 -33.2 -77.8C-33.2 -77.8 -46 -66.2 -47.2 -64.8C-47.2 -64.8 -50.6 -59.6 -51.4 -59.2C-51.4 -59.2 -45 -63 -43 -65C-43 -65 -29 -75 -23.6 -75.8C-23.6 -75.8 -19.2 -78.8 -18.4 -80.2C-18.4 -80.2 -4 -89.4 0.2 -89.4C0.2 -89.4 9.4 -84.2 11.8 -91.2C11.8 -91.2 17.6 -93 23.2 -91.8C23.2 -91.8 26.4 -94.4 25.6 -96.6C25.6 -96.6 27.2 -98.4 28.2 -94.6C28.2 -94.6 31.6 -91 36.4 -93C36.4 -93 40.4 -93.2 38.4 -90.8C38.4 -90.8 34 -87 22.2 -86.8C22.2 -86.8 9.8 -86.2 -6.6 -78.6C-6.6 -78.6 -36.4 -68.2 -45.6 -57.8C-45.6 -57.8 -52 -49 -57.4 -47.8C-57.4 -47.8 -63.2 -47 -69.2 -39.6C-69.2 -39.6 -59.4 -45.4 -50.4 -45.4C-50.4 -45.4 -46.4 -47.8 -50.2 -44.2C-50.2 -44.2 -53.8 -36.6 -52.2 -31.2C-52.2 -31.2 -52.8 -26 -53.6 -24.4C-53.6 -24.4 -61.4 -11.6 -61.4 -9.2C-61.4 -6.8 -60.2 3 -59.8 3.6C-59.4 4.2 -60.8 2 -57 4.4C-53.2 6.8 -50.4 8.4 -49.6 11.2C-48.8 14 -51.6 5.8 -51.8 4C-52 2.2 -56.2 -5 -55.4 -7.4C-55.4 -7.4 -54.4 -6.4 -53.6 -5C-53.6 -5 -54.2 -5.6 -53.6 -9.2C-53.6 -9.2 -52.8 -14.4 -51.4 -17.6C-50 -20.8 -48 -24.6 -47.6 -25.4C-47.2 -26.2 -47.2 -32 -45.8 -29.4L-42.4 -26.8C-42.4 -26.8 -45.2 -29.4 -43 -31.6C-43 -31.6 -44 -37.2 -42.2 -39.8C-42.2 -39.8 -35.2 -48.2 -33.6 -49.2C-32 -50.2 -33.4 -49.8 -33.4 -49.8C-33.4 -49.8 -27.4 -54 -33.2 -52.4C-33.2 -52.4 -37.2 -50.8 -40.2 -50.8C-40.2 -50.8 -47.8 -48.8 -43.8 -53C-39.8 -57.2 -29.8 -62.6 -26 -62.4L-25.2 -60.8L-14 -63.2L-15.2 -62.4C-15.2 -62.4 -15.4 -62.6 -11.2 -63C-7 -63.4 -1.2 -62 0.2 -63.8C1.6 -65.6 5 -66.6 4.6 -65.2C4.2 -63.8 4 -61.8 4 -61.8C4 -61.8 9 -67.6 8.4 -65.4C7.8 -63.2 -0.4 -58 -1.8 -51.8L8.6 -60L12.2 -63C12.2 -63 15.8 -60.8 16 -62.4C16.2 -64 20.8 -69.8 22 -69.6C23.2 -69.4 25.2 -72.2 25 -69.6C24.8 -67 32.4 -61.6 32.4 -61.6C32.4 -61.6 35.6 -63.4 37 -62C38.4 -60.6 42.6 -81.8 42.6 -81.8L67.6 -92.4L111.201 -95.8L94.201 -102.6L33.2 -114z"} ++ , ++ {"stroke":"#4c0000", "width":2, ++ "path":"M51.4 85C51.4 85 36.4 68.2 28 65.6C28 65.6 14.6 58.8 -10 66.6"} ++ , ++ {"stroke":"#4c0000", "width":2, ++ "path":"M24.8 64.2C24.8 64.2 -0.4 56.2 -15.8 60.4C-15.8 60.4 -34.2 62.4 -42.6 76.2"} ++ , ++ {"stroke":"#4c0000", "width":2, ++ "path":"M21.2 63C21.2 63 4.2 55.8 -10.6 53.6C-10.6 53.6 -27.2 51 -43.8 58.2C-43.8 58.2 -56 64.2 -61.4 74.4"} ++ , ++ {"stroke":"#4c0000", "width":2, ++ "path":"M22.2 63.4C22.2 63.4 6.8 52.4 5.8 51C5.8 51 -1.2 40 -14.2 39.6C-14.2 39.6 -35.6 40.4 -52.8 48.4"} ++ , ++ {"fill": "#000000", ++ "path":"M20.895 54.407C22.437 55.87 49.4 84.8 49.4 84.8C84.6 121.401 56.6 87.2 56.6 87.2C49 82.4 39.8 63.6 39.8 63.6C38.6 60.8 53.8 70.8 53.8 70.8C57.8 71.6 71.4 90.8 71.4 90.8C64.6 88.4 69.4 95.6 69.4 95.6C72.2 97.6 92.601 113.201 92.601 113.201C96.201 117.201 100.201 118.801 100.201 118.801C114.201 113.601 107.801 126.801 107.801 126.801C110.201 133.601 115.801 122.001 115.801 122.001C127.001 105.2 110.601 107.601 110.601 107.601C80.6 110.401 73.8 94.4 73.8 94.4C71.4 92 80.2 94.4 80.2 94.4C88.601 96.4 73 82 73 82C75.4 82 84.6 88.8 84.6 88.8C95.001 98 97.001 96 97.001 96C115.001 87.2 125.401 94.8 125.401 94.8C127.401 96.4 121.801 103.2 123.401 108.401C125.001 113.601 129.801 126.001 129.801 126.001C127.401 127.601 127.801 138.401 127.801 138.401C144.601 161.601 135.001 159.601 135.001 159.601C119.401 159.201 134.201 166.801 134.201 166.801C137.401 168.801 146.201 176.001 146.201 176.001C143.401 174.801 141.801 180.001 141.801 180.001C146.601 184.001 143.801 188.801 143.801 188.801C137.801 190.001 136.601 194.001 136.601 194.001C143.401 202.001 133.401 202.401 133.401 202.401C137.001 206.801 132.201 218.801 132.201 218.801C127.401 218.801 121.001 224.401 121.001 224.401C123.401 229.201 113.001 234.801 113.001 234.801C104.601 236.401 107.401 243.201 107.401 243.201C99.401 249.201 97.001 265.201 97.001 265.201C96.201 275.601 93.801 278.801 99.001 276.801C104.201 274.801 103.401 262.401 103.401 262.401C98.601 246.801 141.401 230.801 141.401 230.801C145.401 229.201 146.201 224.001 146.201 224.001C148.201 224.401 157.001 232.001 157.001 232.001C164.601 243.201 165.001 234.001 165.001 234.001C166.201 230.401 164.601 224.401 164.601 224.401C170.601 202.801 156.601 196.401 156.601 196.401C146.601 162.801 160.601 171.201 160.601 171.201C163.401 176.801 174.201 182.001 174.201 182.001L177.801 179.601C176.201 174.801 184.601 168.801 184.601 168.801C187.401 175.201 193.401 167.201 193.401 167.201C197.001 142.801 209.401 157.201 209.401 157.201C213.401 158.401 214.601 151.601 214.601 151.601C218.201 141.201 214.601 127.601 214.601 127.601C218.201 127.201 227.801 133.201 227.801 133.201C230.601 129.601 221.401 112.801 225.401 115.201C229.401 117.601 233.801 119.201 233.801 119.201C234.601 117.201 224.601 104.801 224.601 104.801C220.201 102 215.001 81.6 215.001 81.6C222.201 85.2 212.201 70 212.201 70C212.201 66.8 218.201 55.6 218.201 55.6C217.401 48.8 218.201 49.2 218.201 49.2C221.001 50.4 229.001 52 222.201 45.6C215.401 39.2 223.001 34.4 223.001 34.4C227.401 31.6 213.801 32 213.801 32C208.601 27.6 209.001 23.6 209.001 23.6C217.001 25.6 202.601 11.2 200.201 7.6C197.801 4 207.401 -1.2 207.401 -1.2C220.601 -4.8 209.001 -8 209.001 -8C189.401 -7.6 200.201 -18.4 200.201 -18.4C206.201 -18 204.601 -20.4 204.601 -20.4C199.401 -21.6 189.801 -28 189.801 -28C185.801 -31.6 189.401 -30.8 189.401 -30.8C206.201 -29.6 177.401 -40.8 177.401 -40.8C185.401 -40.8 167.401 -51.2 167.401 -51.2C165.401 -52.8 162.201 -60.4 162.201 -60.4C156.201 -65.6 151.401 -72.4 151.401 -72.4C151.001 -76.8 146.201 -81.6 146.201 -81.6C134.601 -95.2 129.001 -94.8 129.001 -94.8C114.201 -98.4 109.001 -97.6 109.001 -97.6L56.2 -93.2C29.8 -80.4 37.6 -59.4 37.6 -59.4C44 -51 53.2 -54.8 53.2 -54.8C57.8 -61 69.4 -58.8 69.4 -58.8C89.801 -55.6 87.201 -59.2 87.201 -59.2C84.801 -63.8 68.6 -70 68.4 -70.6C68.2 -71.2 59.4 -74.6 59.4 -74.6C56.4 -75.8 52 -85 52 -85C48.8 -88.4 64.6 -82.6 64.6 -82.6C63.4 -81.6 70.8 -77.6 70.8 -77.6C88.201 -78.6 98.801 -67.8 98.801 -67.8C109.601 -51.2 109.801 -59.4 109.801 -59.4C112.601 -68.8 100.801 -90 100.801 -90C101.201 -92 109.401 -85.4 109.401 -85.4C110.801 -87.4 111.601 -81.6 111.601 -81.6C111.801 -79.2 115.601 -71.2 115.601 -71.2C118.401 -58.2 122.001 -65.6 122.001 -65.6L126.601 -56.2C128.001 -53.6 122.001 -46 122.001 -46C121.801 -43.2 122.601 -43.4 117.001 -35.8C111.401 -28.2 114.801 -23.8 114.801 -23.8C113.401 -17.2 122.201 -17.6 122.201 -17.6C124.801 -15.4 128.201 -15.4 128.201 -15.4C130.001 -13.4 132.401 -14 132.401 -14C134.001 -17.8 140.201 -15.8 140.201 -15.8C141.601 -18.2 149.801 -18.6 149.801 -18.6C150.801 -21.2 151.201 -22.8 154.601 -23.4C158.001 -24 133.401 -67 133.401 -67C139.801 -67.8 131.601 -80.2 131.601 -80.2C129.401 -86.8 140.801 -72.2 143.001 -70.8C145.201 -69.4 146.201 -67.2 144.601 -67.4C143.001 -67.6 141.201 -65.4 142.601 -65.2C144.001 -65 157.001 -50 160.401 -39.8C163.801 -29.6 169.801 -25.6 176.001 -19.6C182.201 -13.6 181.401 10.6 181.401 10.6C181.001 19.4 187.001 30 187.001 30C189.001 33.8 184.801 52 184.801 52C182.801 54.2 184.201 55 184.201 55C185.201 56.2 192.001 69.4 192.001 69.4C190.201 69.2 193.801 72.8 193.801 72.8C199.001 78.8 192.601 75.8 192.601 75.8C186.601 74.2 193.601 84 193.601 84C194.801 85.8 185.801 81.2 185.801 81.2C176.601 80.6 188.201 87.8 188.201 87.8C196.801 95 185.401 90.6 185.401 90.6C180.801 88.8 184.001 95.6 184.001 95.6C187.201 97.2 204.401 104.2 204.401 104.2C204.801 108.001 201.801 113.001 201.801 113.001C202.201 117.001 200.001 120.401 200.001 120.401C198.801 128.601 198.201 129.401 198.201 129.401C194.001 129.601 186.601 143.401 186.601 143.401C184.801 146.001 174.601 158.001 174.601 158.001C172.601 165.001 154.601 157.801 154.601 157.801C148.001 161.201 150.001 157.801 150.001 157.801C149.601 155.601 154.401 149.601 154.401 149.601C161.401 147.001 158.801 136.201 158.801 136.201C162.801 134.801 151.601 132.001 151.801 130.801C152.001 129.601 157.801 128.201 157.801 128.201C165.801 126.201 161.401 123.801 161.401 123.801C160.801 119.801 163.801 114.201 163.801 114.201C175.401 113.401 163.801 97.2 163.801 97.2C153.001 89.6 152.001 83.8 152.001 83.8C164.601 75.6 156.401 63.2 156.601 59.6C156.801 56 158.001 34.4 158.001 34.4C156.001 28.2 153.001 14.6 153.001 14.6C155.201 9.4 162.601 -3.2 162.601 -3.2C165.401 -7.4 174.201 -12.2 172.001 -15.2C169.801 -18.2 162.001 -16.4 162.001 -16.4C154.201 -17.8 154.801 -12.6 154.801 -12.6C153.201 -11.6 152.401 -6.6 152.401 -6.6C151.68 1.333 142.801 7.6 142.801 7.6C131.601 13.8 140.801 17.8 140.801 17.8C146.801 24.4 137.001 24.6 137.001 24.6C126.001 22.8 134.201 33 134.201 33C145.001 45.8 142.001 48.6 142.001 48.6C131.801 49.6 144.401 58.8 144.401 58.8C144.401 58.8 143.601 56.8 143.801 58.6C144.001 60.4 147.001 64.6 147.801 66.6C148.601 68.6 144.601 68.8 144.601 68.8C145.201 78.4 129.801 74.2 129.801 74.2C129.801 74.2 129.801 74.2 128.201 74.4C126.601 74.6 115.401 73.8 109.601 71.6C103.801 69.4 97.001 69.4 97.001 69.4C97.001 69.4 93.001 71.2 85.4 71C77.8 70.8 69.8 73.6 69.8 73.6C65.4 73.2 74 68.8 74.2 69C74.4 69.2 80 63.6 72 64.2C50.203 65.835 39.4 55.6 39.4 55.6C37.4 54.2 34.8 51.4 34.8 51.4C24.8 49.4 36.2 63.8 36.2 63.8C37.4 65.2 36 66.2 36 66.2C35.2 64.6 27.4 59.2 27.4 59.2C24.589 58.227 23.226 56.893 20.895 54.407z"} ++ , ++ {"fill": "#4c0000", ++ "path":"M-3 42.8C-3 42.8 8.6 48.4 11.2 51.2C13.8 54 27.8 65.4 27.8 65.4C27.8 65.4 22.4 63.4 19.8 61.6C17.2 59.8 6.4 51.6 6.4 51.6C6.4 51.6 2.6 45.6 -3 42.8z"} ++ , ++ {"fill": "#99cc32", ++ "path":"M-61.009 11.603C-60.672 11.455 -61.196 8.743 -61.4 8.2C-62.422 5.474 -71.4 4 -71.4 4C-71.627 5.365 -71.682 6.961 -71.576 8.599C-71.576 8.599 -66.708 14.118 -61.009 11.603z"} ++ , ++ {"fill": "#659900", ++ "path":"M-61.009 11.403C-61.458 11.561 -61.024 8.669 -61.2 8.2C-62.222 5.474 -71.4 3.9 -71.4 3.9C-71.627 5.265 -71.682 6.861 -71.576 8.499C-71.576 8.499 -67.308 13.618 -61.009 11.403z"} ++ , ++ {"fill": "#000000", ++ "path":"M-65.4 11.546C-66.025 11.546 -66.531 10.406 -66.531 9C-66.531 7.595 -66.025 6.455 -65.4 6.455C-64.775 6.455 -64.268 7.595 -64.268 9C-64.268 10.406 -64.775 11.546 -65.4 11.546z"} ++ , ++ {"fill": "#000000", ++ "path":"M-65.4 9z"} ++ , ++ {"fill": "#000000", ++ "path":"M-111 109.601C-111 109.601 -116.6 119.601 -91.8 113.601C-91.8 113.601 -77.8 112.401 -75.4 110.001C-74.2 110.801 -65.834 113.734 -63 114.401C-56.2 116.001 -47.8 106 -47.8 106C-47.8 106 -43.2 95.5 -40.4 95.5C-37.6 95.5 -40.8 97.1 -40.8 97.1C-40.8 97.1 -47.4 107.201 -47 108.801C-47 108.801 -52.2 128.801 -68.2 129.601C-68.2 129.601 -84.35 130.551 -83 136.401C-83 136.401 -74.2 134.001 -71.8 136.401C-71.8 136.401 -61 136.001 -69 142.401L-75.8 154.001C-75.8 154.001 -75.66 157.919 -85.8 154.401C-95.6 151.001 -105.9 138.101 -105.9 138.101C-105.9 138.101 -121.85 123.551 -111 109.601z"} ++ , ++ {"fill": "#e59999", ++ "path":"M-112.2 113.601C-112.2 113.601 -114.2 123.201 -77.4 112.801C-77.4 112.801 -73 112.801 -70.6 113.601C-68.2 114.401 -56.2 117.201 -54.2 116.001C-54.2 116.001 -61.4 129.601 -73 128.001C-73 128.001 -86.2 129.601 -85.8 134.401C-85.8 134.401 -81.8 141.601 -77 144.001C-77 144.001 -74.2 146.401 -74.6 149.601C-75 152.801 -77.8 154.401 -79.8 155.201C-81.8 156.001 -85 152.801 -86.6 152.801C-88.2 152.801 -96.6 146.401 -101 141.601C-105.4 136.801 -113.8 124.801 -113.4 122.001C-113 119.201 -112.2 113.601 -112.2 113.601z"} ++ , ++ {"fill": "#b26565", ++ "path":"M-109 131.051C-106.4 135.001 -103.2 139.201 -101 141.601C-96.6 146.401 -88.2 152.801 -86.6 152.801C-85 152.801 -81.8 156.001 -79.8 155.201C-77.8 154.401 -75 152.801 -74.6 149.601C-74.2 146.401 -77 144.001 -77 144.001C-80.066 142.468 -82.806 138.976 -84.385 136.653C-84.385 136.653 -84.2 139.201 -89.4 138.401C-94.6 137.601 -99.8 134.801 -101.4 131.601C-103 128.401 -105.4 126.001 -103.8 129.601C-102.2 133.201 -99.8 136.801 -98.2 137.201C-96.6 137.601 -97 138.801 -99.4 138.401C-101.8 138.001 -104.6 137.601 -109 132.401z"} ++ , ++ {"fill": "#992600", ++ "path":"M-111.6 110.001C-111.6 110.001 -109.8 96.4 -108.6 92.4C-108.6 92.4 -109.4 85.6 -107 81.4C-104.6 77.2 -102.6 71 -99.6 65.6C-96.6 60.2 -96.4 56.2 -92.4 54.6C-88.4 53 -82.4 44.4 -79.6 43.4C-76.8 42.4 -77 43.2 -77 43.2C-77 43.2 -70.2 28.4 -56.6 32.4C-56.6 32.4 -72.8 29.6 -57 20.2C-57 20.2 -61.8 21.3 -58.5 14.3C-56.299 9.632 -56.8 16.4 -67.8 28.2C-67.8 28.2 -72.8 36.8 -78 39.8C-83.2 42.8 -95.2 49.8 -96.4 53.6C-97.6 57.4 -100.8 63.2 -102.8 64.8C-104.8 66.4 -107.6 70.6 -108 74C-108 74 -109.2 78 -110.6 79.2C-112 80.4 -112.2 83.6 -112.2 85.6C-112.2 87.6 -114.2 90.4 -114 92.8C-114 92.8 -113.2 111.801 -113.6 113.801L-111.6 110.001z"} ++ , ++ {"fill": "#ffffff", ++ "path":"M-120.2 114.601C-120.2 114.601 -122.2 113.201 -126.6 119.201C-126.6 119.201 -119.3 152.201 -119.3 153.601C-119.3 153.601 -118.2 151.501 -119.5 144.301C-120.8 137.101 -121.7 124.401 -121.7 124.401L-120.2 114.601z"} ++ , ++ {"fill": "#992600", ++ "path":"M-98.6 54C-98.6 54 -116.2 57.2 -115.8 86.4L-116.6 111.201C-116.6 111.201 -117.8 85.6 -119 84C-120.2 82.4 -116.2 71.2 -119.4 77.2C-119.4 77.2 -133.4 91.2 -125.4 112.401C-125.4 112.401 -123.9 115.701 -126.9 111.101C-126.9 111.101 -131.5 98.5 -130.4 92.1C-130.4 92.1 -130.2 89.9 -128.3 87.1C-128.3 87.1 -119.7 75.4 -117 73.1C-117 73.1 -115.2 58.7 -99.8 53.5C-99.8 53.5 -94.1 51.2 -98.6 54z"} ++ , ++ {"fill": "#000000", ++ "path":"M40.8 -12.2C41.46 -12.554 41.451 -13.524 42.031 -13.697C43.18 -14.041 43.344 -15.108 43.862 -15.892C44.735 -17.211 44.928 -18.744 45.51 -20.235C45.782 -20.935 45.809 -21.89 45.496 -22.55C44.322 -25.031 43.62 -27.48 42.178 -29.906C41.91 -30.356 41.648 -31.15 41.447 -31.748C40.984 -33.132 39.727 -34.123 38.867 -35.443C38.579 -35.884 39.104 -36.809 38.388 -36.893C37.491 -36.998 36.042 -37.578 35.809 -36.552C35.221 -33.965 36.232 -31.442 37.2 -29C36.418 -28.308 36.752 -27.387 36.904 -26.62C37.614 -23.014 36.416 -19.662 35.655 -16.188C35.632 -16.084 35.974 -15.886 35.946 -15.824C34.724 -13.138 33.272 -10.693 31.453 -8.312C30.695 -7.32 29.823 -6.404 29.326 -5.341C28.958 -4.554 28.55 -3.588 28.8 -2.6C25.365 0.18 23.115 4.025 20.504 7.871C20.042 8.551 20.333 9.76 20.884 10.029C21.697 10.427 22.653 9.403 23.123 8.557C23.512 7.859 23.865 7.209 24.356 6.566C24.489 6.391 24.31 5.972 24.445 5.851C27.078 3.504 28.747 0.568 31.2 -1.8C33.15 -2.129 34.687 -3.127 36.435 -4.14C36.743 -4.319 37.267 -4.07 37.557 -4.265C39.31 -5.442 39.308 -7.478 39.414 -9.388C39.464 -10.272 39.66 -11.589 40.8 -12.2z"} ++ , ++ {"fill": "#000000", ++ "path":"M31.959 -16.666C32.083 -16.743 31.928 -17.166 32.037 -17.382C32.199 -17.706 32.602 -17.894 32.764 -18.218C32.873 -18.434 32.71 -18.814 32.846 -18.956C35.179 -21.403 35.436 -24.427 34.4 -27.4C35.424 -28.02 35.485 -29.282 35.06 -30.129C34.207 -31.829 34.014 -33.755 33.039 -35.298C32.237 -36.567 30.659 -37.811 29.288 -36.508C28.867 -36.108 28.546 -35.321 28.824 -34.609C28.888 -34.446 29.173 -34.3 29.146 -34.218C29.039 -33.894 28.493 -33.67 28.487 -33.398C28.457 -31.902 27.503 -30.391 28.133 -29.062C28.905 -27.433 29.724 -25.576 30.4 -23.8C29.166 -21.684 30.199 -19.235 28.446 -17.358C28.31 -17.212 28.319 -16.826 28.441 -16.624C28.733 -16.138 29.139 -15.732 29.625 -15.44C29.827 -15.319 30.175 -15.317 30.375 -15.441C30.953 -15.803 31.351 -16.29 31.959 -16.666z"} ++ , ++ {"fill": "#000000", ++ "path":"M94.771 -26.977C96.16 -25.185 96.45 -22.39 94.401 -21C94.951 -17.691 98.302 -19.67 100.401 -20.2C100.292 -20.588 100.519 -20.932 100.802 -20.937C101.859 -20.952 102.539 -21.984 103.601 -21.8C104.035 -23.357 105.673 -24.059 106.317 -25.439C108.043 -29.134 107.452 -33.407 104.868 -36.653C104.666 -36.907 104.883 -37.424 104.759 -37.786C104.003 -39.997 101.935 -40.312 100.001 -41C98.824 -44.875 98.163 -48.906 96.401 -52.6C94.787 -52.85 94.089 -54.589 92.752 -55.309C91.419 -56.028 90.851 -54.449 90.892 -53.403C90.899 -53.198 91.351 -52.974 91.181 -52.609C91.105 -52.445 90.845 -52.334 90.845 -52.2C90.846 -52.065 91.067 -51.934 91.201 -51.8C90.283 -50.98 88.86 -50.503 88.565 -49.358C87.611 -45.648 90.184 -42.523 91.852 -39.322C92.443 -38.187 91.707 -36.916 90.947 -35.708C90.509 -35.013 90.617 -33.886 90.893 -33.03C91.645 -30.699 93.236 -28.96 94.771 -26.977z"} ++ , ++ {"fill": "#000000", ++ "path":"M57.611 -8.591C56.124 -6.74 52.712 -4.171 55.629 -2.243C55.823 -2.114 56.193 -2.11 56.366 -2.244C58.387 -3.809 60.39 -4.712 62.826 -5.294C62.95 -5.323 63.224 -4.856 63.593 -5.017C65.206 -5.72 67.216 -5.662 68.4 -7C72.167 -6.776 75.732 -7.892 79.123 -9.2C80.284 -9.648 81.554 -10.207 82.755 -10.709C84.131 -11.285 85.335 -12.213 86.447 -13.354C86.58 -13.49 86.934 -13.4 87.201 -13.4C87.161 -14.263 88.123 -14.39 88.37 -15.012C88.462 -15.244 88.312 -15.64 88.445 -15.742C90.583 -17.372 91.503 -19.39 90.334 -21.767C90.049 -22.345 89.8 -22.963 89.234 -23.439C88.149 -24.35 87.047 -23.496 86 -23.8C85.841 -23.172 85.112 -23.344 84.726 -23.146C83.867 -22.707 82.534 -23.292 81.675 -22.854C80.313 -22.159 79.072 -21.99 77.65 -21.613C77.338 -21.531 76.56 -21.627 76.4 -21C76.266 -21.134 76.118 -21.368 76.012 -21.346C74.104 -20.95 72.844 -20.736 71.543 -19.044C71.44 -18.911 70.998 -19.09 70.839 -18.955C69.882 -18.147 69.477 -16.913 68.376 -16.241C68.175 -16.118 67.823 -16.286 67.629 -16.157C66.983 -15.726 66.616 -15.085 65.974 -14.638C65.645 -14.409 65.245 -14.734 65.277 -14.99C65.522 -16.937 66.175 -18.724 65.6 -20.6C67.677 -23.12 70.194 -25.069 72 -27.8C72.015 -29.966 72.707 -32.112 72.594 -34.189C72.584 -34.382 72.296 -35.115 72.17 -35.462C71.858 -36.316 72.764 -37.382 71.92 -38.106C70.516 -39.309 69.224 -38.433 68.4 -37C66.562 -36.61 64.496 -35.917 62.918 -37.151C61.911 -37.938 61.333 -38.844 60.534 -39.9C59.549 -41.202 59.884 -42.638 59.954 -44.202C59.96 -44.33 59.645 -44.466 59.645 -44.6C59.646 -44.735 59.866 -44.866 60 -45C59.294 -45.626 59.019 -46.684 58 -47C58.305 -48.092 57.629 -48.976 56.758 -49.278C54.763 -49.969 53.086 -48.057 51.194 -47.984C50.68 -47.965 50.213 -49.003 49.564 -49.328C49.132 -49.544 48.428 -49.577 48.066 -49.311C47.378 -48.807 46.789 -48.693 46.031 -48.488C44.414 -48.052 43.136 -46.958 41.656 -46.103C40.171 -45.246 39.216 -43.809 38.136 -42.489C37.195 -41.337 37.059 -38.923 38.479 -38.423C40.322 -37.773 41.626 -40.476 43.592 -40.15C43.904 -40.099 44.11 -39.788 44 -39.4C44.389 -39.291 44.607 -39.52 44.8 -39.8C45.658 -38.781 46.822 -38.444 47.76 -37.571C48.73 -36.667 50.476 -37.085 51.491 -36.088C53.02 -34.586 52.461 -31.905 54.4 -30.6C53.814 -29.287 53.207 -28.01 52.872 -26.583C52.59 -25.377 53.584 -24.18 54.795 -24.271C56.053 -24.365 56.315 -25.124 56.8 -26.2C57.067 -25.933 57.536 -25.636 57.495 -25.42C57.038 -23.033 56.011 -21.04 55.553 -18.609C55.494 -18.292 55.189 -18.09 54.8 -18.2C54.332 -14.051 50.28 -11.657 47.735 -8.492C47.332 -7.99 47.328 -6.741 47.737 -6.338C49.14 -4.951 51.1 -6.497 52.8 -7C53.013 -8.206 53.872 -9.148 55.204 -9.092C55.46 -9.082 55.695 -9.624 56.019 -9.754C56.367 -9.892 56.869 -9.668 57.155 -9.866C58.884 -11.061 60.292 -12.167 62.03 -13.356C62.222 -13.487 62.566 -13.328 62.782 -13.436C63.107 -13.598 63.294 -13.985 63.617 -14.17C63.965 -14.37 64.207 -14.08 64.4 -13.8C63.754 -13.451 63.75 -12.494 63.168 -12.292C62.393 -12.024 61.832 -11.511 61.158 -11.064C60.866 -10.871 60.207 -11.119 60.103 -10.94C59.505 -9.912 58.321 -9.474 57.611 -8.591z"} ++ , ++ {"fill": "#000000", ++ "path":"M2.2 -58C2.2 -58 -7.038 -60.872 -18.2 -35.2C-18.2 -35.2 -20.6 -30 -23 -28C-25.4 -26 -36.6 -22.4 -38.6 -18.4L-49 -2.4C-49 -2.4 -34.2 -18.4 -31 -20.8C-31 -20.8 -23 -29.2 -26.2 -22.4C-26.2 -22.4 -40.2 -11.6 -39 -2.4C-39 -2.4 -44.6 12 -45.4 14C-45.4 14 -29.4 -18 -27 -19.2C-24.6 -20.4 -23.4 -20.4 -24.6 -16.8C-25.8 -13.2 -26.2 3.2 -29 5.2C-29 5.2 -21 -15.2 -21.8 -18.4C-21.8 -18.4 -18.6 -22 -16.2 -16.8L-17.4 -0.8L-13 11.2C-13 11.2 -15.4 0 -13.8 -15.6C-13.8 -15.6 -15.8 -26 -11.8 -20.4C-7.8 -14.8 1.8 -8.8 1.8 -4C1.8 -4 -3.4 -21.6 -12.6 -26.4L-16.6 -20.4L-17.8 -22.4C-17.8 -22.4 -21.4 -23.2 -17 -30C-12.6 -36.8 -13 -37.6 -13 -37.6C-13 -37.6 -6.6 -30.4 -5 -30.4C-5 -30.4 8.2 -38 9.4 -13.6C9.4 -13.6 16.2 -28 7 -34.8C7 -34.8 -7.8 -36.8 -6.6 -42L0.6 -54.4C4.2 -59.6 2.6 -56.8 2.6 -56.8z"} ++ , ++ {"fill": "#000000", ++ "path":"M-17.8 -41.6C-17.8 -41.6 -30.6 -41.6 -33.8 -36.4L-41 -26.8C-41 -26.8 -23.8 -36.8 -19.8 -38C-15.8 -39.2 -17.8 -41.6 -17.8 -41.6z"} ++ , ++ {"fill": "#000000", ++ "path":"M-57.8 -35.2C-57.8 -35.2 -59.8 -34 -60.2 -31.2C-60.6 -28.4 -63 -28 -62.2 -25.2C-61.4 -22.4 -59.4 -20 -59.4 -24C-59.4 -28 -57.8 -30 -57 -31.2C-56.2 -32.4 -54.6 -36.8 -57.8 -35.2z"} ++ , ++ {"fill": "#000000", ++ "path":"M-66.6 26C-66.6 26 -75 22 -78.2 18.4C-81.4 14.8 -80.948 19.966 -85.8 19.6C-91.647 19.159 -90.6 3.2 -90.6 3.2L-94.6 10.8C-94.6 10.8 -95.8 25.2 -87.8 22.8C-83.893 21.628 -82.6 23.2 -84.2 24C-85.8 24.8 -78.6 25.2 -81.4 26.8C-84.2 28.4 -69.8 23.2 -72.2 33.6L-66.6 26z"} ++ , ++ {"fill": "#000000", ++ "path":"M-79.2 40.4C-79.2 40.4 -94.6 44.8 -98.2 35.2C-98.2 35.2 -103 37.6 -100.8 40.6C-98.6 43.6 -97.4 44 -97.4 44C-97.4 44 -92 45.2 -92.6 46C-93.2 46.8 -95.6 50.2 -95.6 50.2C-95.6 50.2 -85.4 44.2 -79.2 40.4z"} ++ , ++ {"fill": "#ffffff", ++ "path":"M149.201 118.601C148.774 120.735 147.103 121.536 145.201 122.201C143.284 121.243 140.686 118.137 138.801 120.201C138.327 119.721 137.548 119.661 137.204 118.999C136.739 118.101 137.011 117.055 136.669 116.257C136.124 114.985 135.415 113.619 135.601 112.201C137.407 111.489 138.002 109.583 137.528 107.82C137.459 107.563 137.03 107.366 137.23 107.017C137.416 106.694 137.734 106.467 138.001 106.2C137.866 106.335 137.721 106.568 137.61 106.548C137 106.442 137.124 105.805 137.254 105.418C137.839 103.672 139.853 103.408 141.201 104.6C141.457 104.035 141.966 104.229 142.401 104.2C142.351 103.621 142.759 103.094 142.957 102.674C143.475 101.576 145.104 102.682 145.901 102.07C146.977 101.245 148.04 100.546 149.118 101.149C150.927 102.162 152.636 103.374 153.835 105.115C154.41 105.949 154.65 107.23 154.592 108.188C154.554 108.835 153.173 108.483 152.83 109.412C152.185 111.16 154.016 111.679 154.772 113.017C154.97 113.366 154.706 113.67 154.391 113.768C153.98 113.896 153.196 113.707 153.334 114.16C154.306 117.353 151.55 118.031 149.201 118.601z"} ++ , ++ {"fill": "#ffffff", ++ "path":"M139.6 138.201C139.593 136.463 137.992 134.707 139.201 133.001C139.336 133.135 139.467 133.356 139.601 133.356C139.736 133.356 139.867 133.135 140.001 133.001C141.496 135.217 145.148 136.145 145.006 138.991C144.984 139.438 143.897 140.356 144.801 141.001C142.988 142.349 142.933 144.719 142.001 146.601C140.763 146.315 139.551 145.952 138.401 145.401C138.753 143.915 138.636 142.231 139.456 140.911C139.89 140.213 139.603 139.134 139.6 138.201z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M-26.6 129.201C-26.6 129.201 -43.458 139.337 -29.4 124.001C-20.6 114.401 -10.6 108.801 -10.6 108.801C-10.6 108.801 -0.2 104.4 3.4 103.2C7 102 22.2 96.8 25.4 96.4C28.6 96 38.2 92 45 96C51.8 100 59.8 104.4 59.8 104.4C59.8 104.4 43.4 96 39.8 98.4C36.2 100.8 29 100.4 23 103.6C23 103.6 8.2 108.001 5 110.001C1.8 112.001 -8.6 123.601 -10.2 122.801C-11.8 122.001 -9.8 121.601 -8.6 118.801C-7.4 116.001 -9.4 114.401 -17.4 120.801C-25.4 127.201 -26.6 129.201 -26.6 129.201z"} ++ , ++ {"fill": "#000000", ++ "path":"M-19.195 123.234C-19.195 123.234 -17.785 110.194 -9.307 111.859C-9.307 111.859 -1.081 107.689 1.641 105.721C1.641 105.721 9.78 104.019 11.09 103.402C29.569 94.702 44.288 99.221 44.835 98.101C45.381 96.982 65.006 104.099 68.615 108.185C69.006 108.628 58.384 102.588 48.686 100.697C40.413 99.083 18.811 100.944 7.905 106.48C4.932 107.989 -4.013 113.773 -6.544 113.662C-9.075 113.55 -19.195 123.234 -19.195 123.234z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M-23 148.801C-23 148.801 -38.2 146.401 -21.4 144.801C-21.4 144.801 -3.4 142.801 0.6 137.601C0.6 137.601 14.2 128.401 17 128.001C19.8 127.601 49.8 120.401 50.2 118.001C50.6 115.601 56.2 115.601 57.8 116.401C59.4 117.201 58.6 118.401 55.8 119.201C53 120.001 21.8 136.401 15.4 137.601C9 138.801 -2.6 146.401 -7.4 147.601C-12.2 148.801 -23 148.801 -23 148.801z"} ++ , ++ {"fill": "#000000", ++ "path":"M-3.48 141.403C-3.48 141.403 -12.062 140.574 -3.461 139.755C-3.461 139.755 5.355 136.331 7.403 133.668C7.403 133.668 14.367 128.957 15.8 128.753C17.234 128.548 31.194 124.861 31.399 123.633C31.604 122.404 65.67 109.823 70.09 113.013C73.001 115.114 63.1 113.437 53.466 117.847C52.111 118.467 18.258 133.054 14.981 133.668C11.704 134.283 5.765 138.174 3.307 138.788C0.85 139.403 -3.48 141.403 -3.48 141.403z"} ++ , ++ {"fill": "#000000", ++ "path":"M-11.4 143.601C-11.4 143.601 -6.2 143.201 -7.4 144.801C-8.6 146.401 -11 145.601 -11 145.601L-11.4 143.601z"} ++ , ++ {"fill": "#000000", ++ "path":"M-18.6 145.201C-18.6 145.201 -13.4 144.801 -14.6 146.401C-15.8 148.001 -18.2 147.201 -18.2 147.201L-18.6 145.201z"} ++ , ++ {"fill": "#000000", ++ "path":"M-29 146.801C-29 146.801 -23.8 146.401 -25 148.001C-26.2 149.601 -28.6 148.801 -28.6 148.801L-29 146.801z"} ++ , ++ {"fill": "#000000", ++ "path":"M-36.6 147.601C-36.6 147.601 -31.4 147.201 -32.6 148.801C-33.8 150.401 -36.2 149.601 -36.2 149.601L-36.6 147.601z"} ++ , ++ {"fill": "#000000", ++ "path":"M1.8 108.001C1.8 108.001 6.2 108.001 5 109.601C3.8 111.201 0.6 110.801 0.6 110.801L1.8 108.001z"} ++ , ++ {"fill": "#000000", ++ "path":"M-8.2 113.601C-8.2 113.601 -1.694 111.46 -4.2 114.801C-5.4 116.401 -7.8 115.601 -7.8 115.601L-8.2 113.601z"} ++ , ++ {"fill": "#000000", ++ "path":"M-19.4 118.401C-19.4 118.401 -14.2 118.001 -15.4 119.601C-16.6 121.201 -19 120.401 -19 120.401L-19.4 118.401z"} ++ , ++ {"fill": "#000000", ++ "path":"M-27 124.401C-27 124.401 -21.8 124.001 -23 125.601C-24.2 127.201 -26.6 126.401 -26.6 126.401L-27 124.401z"} ++ , ++ {"fill": "#000000", ++ "path":"M-33.8 129.201C-33.8 129.201 -28.6 128.801 -29.8 130.401C-31 132.001 -33.4 131.201 -33.4 131.201L-33.8 129.201z"} ++ , ++ {"fill": "#000000", ++ "path":"M5.282 135.598C5.282 135.598 12.203 135.066 10.606 137.195C9.009 139.325 5.814 138.26 5.814 138.26L5.282 135.598z"} ++ , ++ {"fill": "#000000", ++ "path":"M15.682 130.798C15.682 130.798 22.603 130.266 21.006 132.395C19.409 134.525 16.214 133.46 16.214 133.46L15.682 130.798z"} ++ , ++ {"fill": "#000000", ++ "path":"M26.482 126.398C26.482 126.398 33.403 125.866 31.806 127.995C30.209 130.125 27.014 129.06 27.014 129.06L26.482 126.398z"} ++ , ++ {"fill": "#000000", ++ "path":"M36.882 121.598C36.882 121.598 43.803 121.066 42.206 123.195C40.609 125.325 37.414 124.26 37.414 124.26L36.882 121.598z"} ++ , ++ {"fill": "#000000", ++ "path":"M9.282 103.598C9.282 103.598 16.203 103.066 14.606 105.195C13.009 107.325 9.014 107.06 9.014 107.06L9.282 103.598z"} ++ , ++ {"fill": "#000000", ++ "path":"M19.282 100.398C19.282 100.398 26.203 99.866 24.606 101.995C23.009 104.125 18.614 103.86 18.614 103.86L19.282 100.398z"} ++ , ++ {"fill": "#000000", ++ "path":"M-3.4 140.401C-3.4 140.401 1.8 140.001 0.6 141.601C-0.6 143.201 -3 142.401 -3 142.401L-3.4 140.401z"} ++ , ++ {"fill": "#992600", ++ "path":"M-76.6 41.2C-76.6 41.2 -81 50 -81.4 53.2C-81.4 53.2 -80.6 44.4 -79.4 42.4C-78.2 40.4 -76.6 41.2 -76.6 41.2z"} ++ , ++ {"fill": "#992600", ++ "path":"M-95 55.2C-95 55.2 -98.2 69.6 -97.8 72.4C-97.8 72.4 -99 60.8 -98.6 59.6C-98.2 58.4 -95 55.2 -95 55.2z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M-74.2 -19.4L-74.4 -16.2L-76.6 -16C-76.6 -16 -62.4 -3.4 -61.8 4.2C-61.8 4.2 -61 -4 -74.2 -19.4z"} ++ , ++ {"fill": "#000000", ++ "path":"M-70.216 -18.135C-70.647 -18.551 -70.428 -19.296 -70.836 -19.556C-71.645 -20.072 -69.538 -20.129 -69.766 -20.845C-70.149 -22.051 -69.962 -22.072 -70.084 -23.348C-70.141 -23.946 -69.553 -25.486 -69.168 -25.926C-67.722 -27.578 -69.046 -30.51 -67.406 -32.061C-67.102 -32.35 -66.726 -32.902 -66.441 -33.32C-65.782 -34.283 -64.598 -34.771 -63.648 -35.599C-63.33 -35.875 -63.531 -36.702 -62.962 -36.61C-62.248 -36.495 -61.007 -36.625 -61.052 -35.784C-61.165 -33.664 -62.494 -31.944 -63.774 -30.276C-63.323 -29.572 -63.781 -28.937 -64.065 -28.38C-65.4 -25.76 -65.211 -22.919 -65.385 -20.079C-65.39 -19.994 -65.697 -19.916 -65.689 -19.863C-65.336 -17.528 -64.752 -15.329 -63.873 -13.1C-63.507 -12.17 -63.036 -11.275 -62.886 -10.348C-62.775 -9.662 -62.672 -8.829 -63.08 -8.124C-61.045 -5.234 -62.354 -2.583 -61.185 0.948C-60.978 1.573 -59.286 3.487 -59.749 3.326C-62.262 2.455 -62.374 2.057 -62.551 1.304C-62.697 0.681 -63.027 -0.696 -63.264 -1.298C-63.328 -1.462 -63.499 -3.346 -63.577 -3.468C-65.09 -5.85 -63.732 -5.674 -65.102 -8.032C-66.53 -8.712 -67.496 -9.816 -68.619 -10.978C-68.817 -11.182 -67.674 -11.906 -67.855 -12.119C-68.947 -13.408 -70.1 -14.175 -69.764 -15.668C-69.609 -16.358 -69.472 -17.415 -70.216 -18.135z"} ++ , ++ {"fill": "#000000", ++ "path":"M-73.8 -16.4C-73.8 -16.4 -73.4 -9.6 -71 -8C-68.6 -6.4 -69.8 -7.2 -73 -8.4C-76.2 -9.6 -75 -10.4 -75 -10.4C-75 -10.4 -77.8 -10 -75.4 -8C-73 -6 -69.4 -3.6 -71 -3.6C-72.6 -3.6 -80.2 -7.6 -80.2 -10.4C-80.2 -13.2 -81.2 -17.3 -81.2 -17.3C-81.2 -17.3 -80.1 -18.1 -75.3 -18C-75.3 -18 -73.9 -17.3 -73.8 -16.4z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M-74.6 2.2C-74.6 2.2 -83.12 -0.591 -101.6 2.8C-101.6 2.8 -92.569 0.722 -73.8 3C-63.5 4.25 -74.6 2.2 -74.6 2.2z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M-72.502 2.129C-72.502 2.129 -80.748 -1.389 -99.453 0.392C-99.453 0.392 -90.275 -0.897 -71.774 2.995C-61.62 5.131 -72.502 2.129 -72.502 2.129z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M-70.714 2.222C-70.714 2.222 -78.676 -1.899 -97.461 -1.514C-97.461 -1.514 -88.213 -2.118 -70.052 3.14C-60.086 6.025 -70.714 2.222 -70.714 2.222z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M-69.444 2.445C-69.444 2.445 -76.268 -1.862 -93.142 -2.96C-93.142 -2.96 -84.803 -2.79 -68.922 3.319C-60.206 6.672 -69.444 2.445 -69.444 2.445z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M45.84 12.961C45.84 12.961 44.91 13.605 45.124 12.424C45.339 11.243 73.547 -1.927 77.161 -1.677C77.161 -1.677 46.913 11.529 45.84 12.961z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M42.446 13.6C42.446 13.6 41.57 14.315 41.691 13.121C41.812 11.927 68.899 -3.418 72.521 -3.452C72.521 -3.452 43.404 12.089 42.446 13.6z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M39.16 14.975C39.16 14.975 38.332 15.747 38.374 14.547C38.416 13.348 58.233 -2.149 68.045 -4.023C68.045 -4.023 50.015 4.104 39.16 14.975z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M36.284 16.838C36.284 16.838 35.539 17.532 35.577 16.453C35.615 15.373 53.449 1.426 62.28 -0.26C62.28 -0.26 46.054 7.054 36.284 16.838z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M4.6 164.801C4.6 164.801 -10.6 162.401 6.2 160.801C6.2 160.801 24.2 158.801 28.2 153.601C28.2 153.601 41.8 144.401 44.6 144.001C47.4 143.601 63.8 140.001 64.2 137.601C64.6 135.201 70.6 132.801 72.2 133.601C73.8 134.401 73.8 143.601 71 144.401C68.2 145.201 49.4 152.401 43 153.601C36.6 154.801 25 162.401 20.2 163.601C15.4 164.801 4.6 164.801 4.6 164.801z"} ++ , ++ {"fill": "#000000", ++ "path":"M77.6 127.401C77.6 127.401 74.6 129.001 73.4 131.601C73.4 131.601 67 142.201 52.8 145.401C52.8 145.401 29.8 154.401 22 156.401C22 156.401 8.6 161.401 1.2 160.601C1.2 160.601 -5.8 160.801 0.4 162.401C0.4 162.401 20.6 160.401 24 158.601C24 158.601 39.6 153.401 42.6 150.801C45.6 148.201 63.8 143.201 66 141.201C68.2 139.201 78 130.801 77.6 127.401z"} ++ , ++ {"fill": "#000000", ++ "path":"M18.882 158.911C18.882 158.911 24.111 158.685 22.958 160.234C21.805 161.784 19.357 160.91 19.357 160.91L18.882 158.911z"} ++ , ++ {"fill": "#000000", ++ "path":"M11.68 160.263C11.68 160.263 16.908 160.037 15.756 161.586C14.603 163.136 12.155 162.263 12.155 162.263L11.68 160.263z"} ++ , ++ {"fill": "#000000", ++ "path":"M1.251 161.511C1.251 161.511 6.48 161.284 5.327 162.834C4.174 164.383 1.726 163.51 1.726 163.51L1.251 161.511z"} ++ , ++ {"fill": "#000000", ++ "path":"M-6.383 162.055C-6.383 162.055 -1.154 161.829 -2.307 163.378C-3.46 164.928 -5.908 164.054 -5.908 164.054L-6.383 162.055z"} ++ , ++ {"fill": "#000000", ++ "path":"M35.415 151.513C35.415 151.513 42.375 151.212 40.84 153.274C39.306 155.336 36.047 154.174 36.047 154.174L35.415 151.513z"} ++ , ++ {"fill": "#000000", ++ "path":"M45.73 147.088C45.73 147.088 51.689 143.787 51.155 148.849C50.885 151.405 46.362 149.749 46.362 149.749L45.73 147.088z"} ++ , ++ {"fill": "#000000", ++ "path":"M54.862 144.274C54.862 144.274 62.021 140.573 60.287 146.035C59.509 148.485 55.493 146.935 55.493 146.935L54.862 144.274z"} ++ , ++ {"fill": "#000000", ++ "path":"M64.376 139.449C64.376 139.449 68.735 134.548 69.801 141.21C70.207 143.748 65.008 142.11 65.008 142.11L64.376 139.449z"} ++ , ++ {"fill": "#000000", ++ "path":"M26.834 155.997C26.834 155.997 32.062 155.77 30.91 157.32C29.757 158.869 27.308 157.996 27.308 157.996L26.834 155.997z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M62.434 34.603C62.434 34.603 61.708 35.268 61.707 34.197C61.707 33.127 79.191 19.863 88.034 18.479C88.034 18.479 71.935 25.208 62.434 34.603z"} ++ , ++ {"fill": "#000000", ++ "path":"M65.4 98.4C65.4 98.4 87.401 120.801 96.601 124.401C96.601 124.401 105.801 135.601 101.801 161.601C101.801 161.601 98.601 169.201 95.401 148.401C95.401 148.401 98.601 123.201 87.401 139.201C87.401 139.201 79 129.301 85.4 129.601C85.4 129.601 88.601 131.601 89.001 130.001C89.401 128.401 81.4 114.801 64.2 100.4C47 86 65.4 98.4 65.4 98.4z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M7 137.201C7 137.201 6.8 135.401 8.6 136.201C10.4 137.001 104.601 143.201 136.201 167.201C136.201 167.201 91.001 144.001 7 137.201z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M17.4 132.801C17.4 132.801 17.2 131.001 19 131.801C20.8 132.601 157.401 131.601 181.001 164.001C181.001 164.001 159.001 138.801 17.4 132.801z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M29 128.801C29 128.801 28.8 127.001 30.6 127.801C32.4 128.601 205.801 115.601 229.401 148.001C229.401 148.001 219.801 122.401 29 128.801z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M39 124.001C39 124.001 38.8 122.201 40.6 123.001C42.4 123.801 164.601 85.2 188.201 117.601C188.201 117.601 174.801 93 39 124.001z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M-19 146.801C-19 146.801 -19.2 145.001 -17.4 145.801C-15.6 146.601 2.2 148.801 4.2 187.601C4.2 187.601 -3 145.601 -19 146.801z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M-27.8 148.401C-27.8 148.401 -28 146.601 -26.2 147.401C-24.4 148.201 -10.2 143.601 -13 182.401C-13 182.401 -11.8 147.201 -27.8 148.401z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M-35.8 148.801C-35.8 148.801 -36 147.001 -34.2 147.801C-32.4 148.601 -17 149.201 -29.4 171.601C-29.4 171.601 -19.8 147.601 -35.8 148.801z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M11.526 104.465C11.526 104.465 11.082 106.464 12.631 105.247C28.699 92.622 61.141 33.72 116.826 28.086C116.826 28.086 78.518 15.976 11.526 104.465z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M22.726 102.665C22.726 102.665 21.363 101.472 23.231 100.847C25.099 100.222 137.541 27.72 176.826 35.686C176.826 35.686 149.719 28.176 22.726 102.665z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M1.885 108.767C1.885 108.767 1.376 110.366 3.087 109.39C12.062 104.27 15.677 47.059 59.254 45.804C59.254 45.804 26.843 31.09 1.885 108.767z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M-18.038 119.793C-18.038 119.793 -19.115 121.079 -17.162 120.825C-6.916 119.493 14.489 78.222 58.928 83.301C58.928 83.301 26.962 68.955 -18.038 119.793z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M-6.8 113.667C-6.8 113.667 -7.611 115.136 -5.742 114.511C4.057 111.237 17.141 66.625 61.729 63.078C61.729 63.078 27.603 55.135 -6.8 113.667z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M-25.078 124.912C-25.078 124.912 -25.951 125.954 -24.369 125.748C-16.07 124.669 1.268 91.24 37.264 95.354C37.264 95.354 11.371 83.734 -25.078 124.912z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M-32.677 130.821C-32.677 130.821 -33.682 131.866 -32.091 131.748C-27.923 131.439 2.715 98.36 21.183 113.862C21.183 113.862 9.168 95.139 -32.677 130.821z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M36.855 98.898C36.855 98.898 35.654 97.543 37.586 97.158C39.518 96.774 160.221 39.061 198.184 51.927C198.184 51.927 172.243 41.053 36.855 98.898z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M3.4 163.201C3.4 163.201 3.2 161.401 5 162.201C6.8 163.001 22.2 163.601 9.8 186.001C9.8 186.001 19.4 162.001 3.4 163.201z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M13.8 161.601C13.8 161.601 13.6 159.801 15.4 160.601C17.2 161.401 35 163.601 37 202.401C37 202.401 29.8 160.401 13.8 161.601z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M20.6 160.001C20.6 160.001 20.4 158.201 22.2 159.001C24 159.801 48.6 163.201 72.2 195.601C72.2 195.601 36.6 158.801 20.6 160.001z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M28.225 157.972C28.225 157.972 27.788 156.214 29.678 156.768C31.568 157.322 52.002 155.423 90.099 189.599C90.099 189.599 43.924 154.656 28.225 157.972z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M38.625 153.572C38.625 153.572 38.188 151.814 40.078 152.368C41.968 152.922 76.802 157.423 128.499 192.399C128.499 192.399 54.324 150.256 38.625 153.572z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M-1.8 142.001C-1.8 142.001 -2 140.201 -0.2 141.001C1.6 141.801 55 144.401 85.4 171.201C85.4 171.201 50.499 146.426 -1.8 142.001z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M-11.8 146.001C-11.8 146.001 -12 144.201 -10.2 145.001C-8.4 145.801 16.2 149.201 39.8 181.601C39.8 181.601 4.2 144.801 -11.8 146.001z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M49.503 148.962C49.503 148.962 48.938 147.241 50.864 147.655C52.79 148.068 87.86 150.004 141.981 181.098C141.981 181.098 64.317 146.704 49.503 148.962z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M57.903 146.562C57.903 146.562 57.338 144.841 59.264 145.255C61.19 145.668 96.26 147.604 150.381 178.698C150.381 178.698 73.317 143.904 57.903 146.562z"} ++ , ++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1, ++ "path":"M67.503 141.562C67.503 141.562 66.938 139.841 68.864 140.255C70.79 140.668 113.86 145.004 203.582 179.298C203.582 179.298 82.917 138.904 67.503 141.562z"} ++ , ++ {"fill": "#000000", ++ "path":"M-43.8 148.401C-43.8 148.401 -38.6 148.001 -39.8 149.601C-41 151.201 -43.4 150.401 -43.4 150.401L-43.8 148.401z"} ++ , ++ {"fill": "#000000", ++ "path":"M-13 162.401C-13 162.401 -7.8 162.001 -9 163.601C-10.2 165.201 -12.6 164.401 -12.6 164.401L-13 162.401z"} ++ , ++ {"fill": "#000000", ++ "path":"M-21.8 162.001C-21.8 162.001 -16.6 161.601 -17.8 163.201C-19 164.801 -21.4 164.001 -21.4 164.001L-21.8 162.001z"} ++ , ++ {"fill": "#000000", ++ "path":"M-117.169 150.182C-117.169 150.182 -112.124 151.505 -113.782 152.624C-115.439 153.744 -117.446 152.202 -117.446 152.202L-117.169 150.182z"} ++ , ++ {"fill": "#000000", ++ "path":"M-115.169 140.582C-115.169 140.582 -110.124 141.905 -111.782 143.024C-113.439 144.144 -115.446 142.602 -115.446 142.602L-115.169 140.582z"} ++ , ++ {"fill": "#000000", ++ "path":"M-122.369 136.182C-122.369 136.182 -117.324 137.505 -118.982 138.624C-120.639 139.744 -122.646 138.202 -122.646 138.202L-122.369 136.182z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M-42.6 211.201C-42.6 211.201 -44.2 211.201 -48.2 213.201C-50.2 213.201 -61.4 216.801 -67 226.801C-67 226.801 -54.6 217.201 -42.6 211.201z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M45.116 303.847C45.257 304.105 45.312 304.525 45.604 304.542C46.262 304.582 47.495 304.883 47.37 304.247C46.522 299.941 45.648 295.004 41.515 293.197C40.876 292.918 39.434 293.331 39.36 294.215C39.233 295.739 39.116 297.088 39.425 298.554C39.725 299.975 41.883 299.985 42.8 298.601C43.736 300.273 44.168 302.116 45.116 303.847z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M34.038 308.581C34.786 309.994 34.659 311.853 36.074 312.416C36.814 312.71 38.664 311.735 38.246 310.661C37.444 308.6 37.056 306.361 35.667 304.55C35.467 304.288 35.707 303.755 35.547 303.427C34.953 302.207 33.808 301.472 32.4 301.801C31.285 304.004 32.433 306.133 33.955 307.842C34.091 307.994 33.925 308.37 34.038 308.581z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M-5.564 303.391C-5.672 303.014 -5.71 302.551 -5.545 302.23C-5.014 301.197 -4.221 300.075 -4.558 299.053C-4.906 297.997 -6.022 298.179 -6.672 298.748C-7.807 299.742 -7.856 301.568 -8.547 302.927C-8.743 303.313 -8.692 303.886 -9.133 304.277C-9.607 304.698 -10.047 306.222 -9.951 306.793C-9.898 307.106 -10.081 317.014 -9.859 316.751C-9.24 316.018 -6.19 306.284 -6.121 305.392C-6.064 304.661 -5.332 304.196 -5.564 303.391z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M-31.202 296.599C-28.568 294.1 -25.778 291.139 -26.22 287.427C-26.336 286.451 -28.111 286.978 -28.298 287.824C-29.1 291.449 -31.139 294.11 -33.707 296.502C-35.903 298.549 -37.765 304.893 -38 305.401C-34.303 300.145 -32.046 297.399 -31.202 296.599z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M-44.776 290.635C-44.253 290.265 -44.555 289.774 -44.338 289.442C-43.385 287.984 -42.084 286.738 -42.066 285C-42.063 284.723 -42.441 284.414 -42.776 284.638C-43.053 284.822 -43.395 284.952 -43.503 285.082C-45.533 287.531 -46.933 290.202 -48.376 293.014C-48.559 293.371 -49.703 297.862 -49.39 297.973C-49.151 298.058 -47.431 293.877 -47.221 293.763C-45.958 293.077 -45.946 291.462 -44.776 290.635z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M-28.043 310.179C-27.599 309.31 -26.023 308.108 -26.136 307.219C-26.254 306.291 -25.786 304.848 -26.698 305.536C-27.955 306.484 -31.404 307.833 -31.674 313.641C-31.7 314.212 -28.726 311.519 -28.043 310.179z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M-13.6 293.001C-13.2 292.333 -12.492 292.806 -12.033 292.543C-11.385 292.171 -10.774 291.613 -10.482 290.964C-9.512 288.815 -7.743 286.995 -7.6 284.601C-9.091 283.196 -9.77 285.236 -10.4 286.201C-11.723 284.554 -12.722 286.428 -14.022 286.947C-14.092 286.975 -14.305 286.628 -14.38 286.655C-15.557 287.095 -16.237 288.176 -17.235 288.957C-17.406 289.091 -17.811 288.911 -17.958 289.047C-18.61 289.65 -19.583 289.975 -19.863 290.657C-20.973 293.364 -24.113 295.459 -26 303.001C-25.619 303.91 -21.488 296.359 -21.001 295.661C-20.165 294.465 -20.047 297.322 -18.771 296.656C-18.72 296.629 -18.534 296.867 -18.4 297.001C-18.206 296.721 -17.988 296.492 -17.6 296.601C-17.6 296.201 -17.734 295.645 -17.533 295.486C-16.296 294.509 -16.38 293.441 -15.6 292.201C-15.142 292.99 -14.081 292.271 -13.6 293.001z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M46.2 347.401C46.2 347.401 53.6 327.001 49.2 315.801C49.2 315.801 60.6 337.401 56 348.601C56 348.601 55.6 338.201 51.6 333.201C51.6 333.201 47.6 346.001 46.2 347.401z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M31.4 344.801C31.4 344.801 36.8 336.001 28.8 317.601C28.8 317.601 28 338.001 21.2 349.001C21.2 349.001 35.4 328.801 31.4 344.801z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M21.4 342.801C21.4 342.801 21.2 322.801 21.6 319.801C21.6 319.801 17.8 336.401 7.6 346.001C7.6 346.001 22 334.001 21.4 342.801z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M11.8 310.801C11.8 310.801 17.8 324.401 7.8 342.801C7.8 342.801 14.2 330.601 9.4 323.601C9.4 323.601 12 320.201 11.8 310.801z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M-7.4 342.401C-7.4 342.401 -8.4 326.801 -6.6 324.601C-6.6 324.601 -6.4 318.201 -6.8 317.201C-6.8 317.201 -2.8 311.001 -2.6 318.401C-2.6 318.401 -1.2 326.201 1.6 330.801C1.6 330.801 5.2 336.201 5 342.601C5 342.601 -5 312.401 -7.4 342.401z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M-11 314.801C-11 314.801 -17.6 325.601 -19.4 344.601C-19.4 344.601 -20.8 338.401 -17 324.001C-17 324.001 -12.8 308.601 -11 314.801z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M-32.8 334.601C-32.8 334.601 -27.8 329.201 -26.4 324.201C-26.4 324.201 -22.8 308.401 -29.2 317.001C-29.2 317.001 -29 325.001 -37.2 332.401C-37.2 332.401 -32.4 330.001 -32.8 334.601z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M-38.6 329.601C-38.6 329.601 -35.2 312.201 -34.4 311.401C-34.4 311.401 -32.6 308.001 -35.4 311.201C-35.4 311.201 -44.2 330.401 -48.2 337.001C-48.2 337.001 -40.2 327.801 -38.6 329.601z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M-44.4 313.001C-44.4 313.001 -32.8 290.601 -54.6 316.401C-54.6 316.401 -43.6 306.601 -44.4 313.001z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M-59.8 298.401C-59.8 298.401 -55 279.601 -52.4 279.801C-52.4 279.801 -44.2 270.801 -50.8 281.401C-50.8 281.401 -56.8 291.001 -56.2 300.801C-56.2 300.801 -56.8 291.201 -59.8 298.401z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M270.5 287C270.5 287 258.5 277 256 273.5C256 273.5 269.5 292 269.5 299C269.5 299 272 291.5 270.5 287z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M276 265C276 265 255 250 251.5 242.5C251.5 242.5 278 272 278 276.5C278 276.5 278.5 267.5 276 265z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M293 111C293 111 281 103 279.5 105C279.5 105 290 111.5 292.5 120C292.5 120 291 111 293 111z"} ++ , ++ {"fill": "#cccccc", ++ "path":"M301.5 191.5L284 179.5C284 179.5 303 196.5 303.5 200.5L301.5 191.5z"} ++ , ++ {"stroke":"#000000", ++ "path":"M-89.25 169L-67.25 173.75"} ++ , ++ {"stroke":"#000000", ++ "path":"M-39 331C-39 331 -39.5 327.5 -48.5 338"} ++ , ++ {"stroke":"#000000", ++ "path":"M-33.5 336C-33.5 336 -31.5 329.5 -38 334"} ++ , ++ {"stroke":"#000000", ++ "path":"M20.5 344.5C20.5 344.5 22 333.5 10.5 346.5"} ++]; diff --cc examples/quick/canvas/tiger/tiger.qml index 0000000,0000000..2eb1bb2 new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/tiger/tiger.qml @@@ -1,0 -1,0 +1,129 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++import "../contents" ++import "tiger.js" as Tiger ++Item { ++ id:container ++ width:360 ++ height:600 ++ ++ Column { ++ spacing:5 ++ anchors.fill:parent ++ Text { font.pointSize:25; text:"Tiger with SVG path"; anchors.horizontalCenter:parent.horizontalCenter} ++ ++ Canvas { ++ id:canvas ++ width:360 ++ height:360 ++ smooth:true ++ renderTarget:Canvas.FramebufferObject ++ renderStrategy: Canvas.Cooperative ++ property string strokeStyle:"steelblue" ++ property string fillStyle:"yellow" ++ property bool fill:true ++ property bool stroke:true ++ property real alpha:alphaCtrl.value ++ property real scaleX : scaleXCtrl.value ++ property real scaleY : scaleYCtrl.value ++ property real rotate : rotateCtrl.value ++ property int frame:0 ++ ++ onFillChanged: requestPaint(); ++ onStrokeChanged: requestPaint(); ++ onAlphaChanged: requestPaint(); ++ onScaleXChanged: requestPaint(); ++ onScaleYChanged: requestPaint(); ++ onRotateChanged: requestPaint(); ++ ++ onPainted : { ++ canvas.frame++; ++ if (canvas.frame < Tiger.tiger.length) ++ requestPaint(); ++ } ++ onPaint: { ++ var ctx = canvas.getContext('2d'); ++ ctx.save(); ++ ctx.clearRect(0, 0, canvas.width, canvas.height); ++ ctx.globalAlpha = canvas.alpha; ++ ctx.scale(canvas.scaleX, canvas.scaleY); ++ ctx.rotate(canvas.rotate); ++ ctx.globalCompositeOperation = "source-over"; ++ ctx.translate(canvas.width/2, canvas.height/2); ++ ctx.strokeStyle = Qt.rgba(.3, .3, .3,1); ++ ctx.lineWidth = 1; ++ ++ ++ for (var i = 0; i < canvas.frame && i < Tiger.tiger.length; i++) { ++ if (Tiger.tiger[i].width != undefined) ++ ctx.lineWidth = Tiger.tiger[i].width; ++ ++ if (Tiger.tiger[i].path != undefined) ++ ctx.path = Tiger.tiger[i].path; ++ ++ if (Tiger.tiger[i].fill != undefined) { ++ ctx.fillStyle = Tiger.tiger[i].fill; ++ ctx.fill(); ++ } ++ ++ if (Tiger.tiger[i].stroke != undefined) { ++ ctx.strokeStyle = Tiger.tiger[i].stroke; ++ ctx.stroke(); ++ } ++ } ++ ctx.restore(); ++ } ++ } ++ Rectangle { ++ id:controls ++ width:360 ++ height:160 ++ Column { ++ spacing:3 ++ Slider {id:scaleXCtrl; width:300; height:30; min:0.1; max:10; init:0.5; name:"ScaleX"} ++ Slider {id:scaleYCtrl; width:300; height:30; min:0.1; max:10; init:0.5; name:"ScaleY"} ++ Slider {id:rotateCtrl; width:300; height:30; min:0; max:Math.PI*2; init:0; name:"Rotate"} ++ Slider {id:alphaCtrl; width:300; height:30; min:0; max:1; init:1; name:"Alpha"} ++ } ++ } ++ } ++} diff --cc examples/quick/canvas/twitterfriends/TwitterUser.qml index 0000000,0000000..8b90621 new file mode 100644 --- /dev/null +++ b/examples/quick/canvas/twitterfriends/TwitterUser.qml @@@ -1,0 -1,0 +1,294 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Item { ++ id:twitterUser ++ property variant friends : []; ++ property string name : ""; ++ property string twitterId : ""; ++ property string image : ""; ++ property string url : ""; ++ property string desc : ""; ++ width : 0; ++ height : 0; ++ property int posX:0; ++ property int posY:0; ++ property bool hasFocus : false; ++ property variant canvas; ++ property variant manager; ++ property variant linkColor; ++ property bool selected : false; ++ ++ Rectangle { ++ id:twitterStatus ++ x:twitterUser.width ++ y:twitterUser.height ++ width:250 ++ height:60 ++ opacity: 0 ++ border.color:"steelblue" ++ border.width:3 ++ Column { ++ spacing:2 ++ Text {color:"steelblue"; font.pointSize:15; width:250; height:30; text:twitterUser.name; wrapMode: Text.WrapAnywhere} ++ Text {color:"steelblue"; font.pointSize:8; width:250; height:30; text:twitterUser.url; wrapMode: Text.WrapAnywhere} ++ } ++ } ++ ++ function moved() { ++ twitterUser.posX = twitterUser.x; ++ twitterUser.posY = twitterUser.y; ++ twitterUser.canvas.requestPaint(); ++ } ++ ++ onXChanged: moved(); ++ onYChanged: moved(); ++ ++ MouseArea { ++ anchors.fill:parent ++ drag.target : twitterUser ++ drag.axis : Drag.XandYAxis ++ ++ onClicked: { ++ if (!twitterUser.selected) { ++ twitterUser.selected = true; ++ twitterStatus.opacity = 1; ++ twitterStatus.visible = true; ++ } else { ++ twitterUser.selected = false; ++ twitterStatus.opacity = 0; ++ } ++ } ++ ++ onDoubleClicked : { ++ twitterStatus.opacity = 0; ++ twitterUser.selected = false; ++ twitterUser.hasFocus = true; ++ twitterUser.canvas.twitterName = twitterUser.name; ++ twitterUser.canvas.twitterId = twitterUser.twitterId; ++ twitterUser.canvas.loading = true; ++ twitterUser.createFriends(); ++ } ++ } ++ ++ function show(ctx, layoutChanged) { ++ var w = canvas.width; ++ var h = canvas.height; ++ if (twitterUser.hasFocus) { ++ twitterUser.width = 60 ++ twitterUser.height = 60 ++ twitterUser.posX = w/2; ++ twitterUser.posY = h/2; ++ } else { ++ twitterUser.width = 40 ++ twitterUser.height = 40 ++ } ++ ++ ++ if (twitterUser.hasFocus) { ++ if (layoutChanged) ++ twitterUser.layoutFriends(); ++ twitterUser.linkFriends(ctx); ++ twitterUser.showFriends(ctx); ++ ctx.shadowOffsetX = 5; ++ ctx.shadowOffsetY = 5; ++ ctx.shadowBlur = 7; ++ ctx.shadowColor = "blue"; ++ ctx.globalAlpha = 1; ++ } else { ++ ctx.shadowOffsetX = 5; ++ ctx.shadowOffsetY = 5; ++ ctx.shadowBlur = 7; ++ ctx.shadowColor = twitterUser.linkColor; ++ ctx.globalAlpha = 0.6; ++ } ++ ++ if (twitterUser.canvas.isImageLoaded(twitterUser.image)) { ++ ctx.drawImage(twitterUser.image, twitterUser.posX, twitterUser.posY, twitterUser.width, twitterUser.height); ++ } ++// ctx.font = "15px"; ++// var nameSize = ctx.measureText(twitterUser.name).width; ++// ctx.fillText(twitterUser.name, twitterUser.posX + nameSize/2 - twitterUser.width/2, twitterUser.posY + twitterUser.height/2 + 10); ++ } ++ function dump() { ++ console.log("name:" + twitterUser.name ++ + " x:" + twitterUser.posX ++ + " y:" + twitterUser.posY ++ + " width:" + twitterUser.width ++ + " height:" + twitterUser.height ++ + " id:" + twitterUser.twitterId ++ + " image:" + twitterUser.image ++ + " url:" + twitterUser.url + "\n" + twitterUser.desc); ++ } ++ ++ function layoutFriends() { ++ var w = canvas.width; ++ var h = canvas.height; ++ for (var i=0; i < twitterUser.friends.length; i++) { ++ var friend = manager.getById(twitterUser.friends[i]); ++ if (friend) { ++ friend.x = Math.random() *w; ++ friend.y = Math.random() *h; ++ } ++ } ++ } ++ ++ function showFriends(ctx) { ++ var w = canvas.width; ++ var h = canvas.height; ++ for (var i=0; i < twitterUser.friends.length && i < 15; i++) { ++ var friend = manager.getById(twitterUser.friends[i]); ++ if (friend && twitterUser.canvas.isImageLoaded(friend.image)) { ++ friend.hasFocus = false; ++ friend.show(ctx, false); ++ } ++ } ++ } ++ ++ function linkFriends(ctx) { ++ var w = canvas.width; ++ var h = canvas.height; ++ for (var i=0; i < twitterUser.friends.length && i < 15; i++) { ++ var friend = manager.getById(twitterUser.friends[i]); ++ if (friend && twitterUser.canvas.isImageLoaded(friend.image)) { ++ if (!friend.linkColor) ++ friend.linkColor = Qt.rgba( ((Math.random() * 200) +55)/255 ++ , ((Math.random() * 200) +55)/255 ++ , ((Math.random() * 200) +55)/255, 0.8); ++ ctx.strokeStyle = friend.linkColor; ++ ctx.lineWidth = 8; ++ ctx.beginPath(); ++ ctx.moveTo(twitterUser.posX + twitterUser.width/2, twitterUser.posY + twitterUser.height/2); ++ ctx.lineTo(friend.x + friend.width/2, friend.y + friend.height/2); ++ ctx.stroke(); ++ } ++ } ++ } ++ ++ ++ function create(url) { ++ var x = new XMLHttpRequest; ++ x.open("GET", url); ++ ++ x.onreadystatechange = function() { ++ if (x.readyState == XMLHttpRequest.DONE) { ++ var user = eval('(' + x.responseText +')')[0]; ++ twitterUser.name = user.name; ++ twitterUser.twitterId = user.id; ++ twitterUser.image = user.profile_image_url; ++ twitterUser.canvas.loadImage(twitterUser.image); ++ twitterUser.url = user.url; ++ twitterUser.desc = user.description; ++ twitterUser.createFriends(); ++ } ++ } ++ x.send(); ++ } ++ ++ function createByName(name) { ++ if (twitterUser.name === "" && twitterUser.twitterId === "") { ++ twitterUser.name = name; ++ var userUrl = "http://api.twitter.com/1/users/lookup.json?stringify_ids=true&screen_name=" + name; ++ twitterUser.create(userUrl); ++ } ++ } ++ ++ function createById(id) { ++ if (twitterUser.name === "" && twitterUser.twitterId === "") { ++ twitterUser.twitterId = id; ++ var userUrl = "http://api.twitter.com/1/users/lookup.json?stringify_ids=true&user_id=" + id; ++ twitterUser.create(userUrl); ++ } ++ } ++ ++ function createFriends() { ++ if (twitterUser.friends.length === 0) { ++ var x = new XMLHttpRequest; ++ var friendsUrl = "https://api.twitter.com/1/friends/ids.json?cursor=-1&stringify_ids=true&user_id=" + twitterUser.twitterId; ++ x.open("GET", friendsUrl); ++ ++ x.onreadystatechange = function() { ++ if (x.readyState == XMLHttpRequest.DONE) { ++ twitterUser.friends = eval('(' + x.responseText +')').ids; ++ var doRequest = false; ++ var userUrl = "http://api.twitter.com/1/users/lookup.json?stringify_ids=true&user_id="; ++ ++ for (var i=0; i ++ ++ view.qml ++ ++ ++ diff --cc examples/quick/modelviews/abstractitemmodel/main.cpp index 0000000,0000000..f5930ce new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/abstractitemmodel/main.cpp @@@ -1,0 -1,0 +1,70 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++#include "model.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++//![0] ++int main(int argc, char ** argv) ++{ ++ QGuiApplication app(argc, argv); ++ ++ AnimalModel model; ++ model.addAnimal(Animal("Wolf", "Medium")); ++ model.addAnimal(Animal("Polar bear", "Large")); ++ model.addAnimal(Animal("Quoll", "Small")); ++ ++ QQuickView view; ++ view.setResizeMode(QQuickView::SizeRootObjectToView); ++ QQmlContext *ctxt = view.rootContext(); ++ ctxt->setContextProperty("myModel", &model); ++//![0] ++ ++ view.setSource(QUrl("qrc:view.qml")); ++ view.show(); ++ ++ return app.exec(); ++} ++ diff --cc examples/quick/modelviews/abstractitemmodel/model.cpp index 0000000,0000000..8f7649c new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/abstractitemmodel/model.cpp @@@ -1,0 -1,0 +1,90 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++#include "model.h" ++ ++Animal::Animal(const QString &type, const QString &size) ++ : m_type(type), m_size(size) ++{ ++} ++ ++QString Animal::type() const ++{ ++ return m_type; ++} ++ ++QString Animal::size() const ++{ ++ return m_size; ++} ++ ++//![0] ++AnimalModel::AnimalModel(QObject *parent) ++ : QAbstractListModel(parent) ++{ ++ QHash roles; ++ roles[TypeRole] = "type"; ++ roles[SizeRole] = "size"; ++ setRoleNames(roles); ++} ++//![0] ++ ++void AnimalModel::addAnimal(const Animal &animal) ++{ ++ beginInsertRows(QModelIndex(), rowCount(), rowCount()); ++ m_animals << animal; ++ endInsertRows(); ++} ++ ++int AnimalModel::rowCount(const QModelIndex & parent) const { ++ return m_animals.count(); ++} ++ ++QVariant AnimalModel::data(const QModelIndex & index, int role) const { ++ if (index.row() < 0 || index.row() >= m_animals.count()) ++ return QVariant(); ++ ++ const Animal &animal = m_animals[index.row()]; ++ if (role == TypeRole) ++ return animal.type(); ++ else if (role == SizeRole) ++ return animal.size(); ++ return QVariant(); ++} ++ diff --cc examples/quick/modelviews/abstractitemmodel/model.h index 0000000,0000000..1378c44 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/abstractitemmodel/model.h @@@ -1,0 -1,0 +1,83 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++#include ++#include ++ ++//![0] ++class Animal ++{ ++public: ++ Animal(const QString &type, const QString &size); ++//![0] ++ ++ QString type() const; ++ QString size() const; ++ ++private: ++ QString m_type; ++ QString m_size; ++//![1] ++}; ++ ++class AnimalModel : public QAbstractListModel ++{ ++ Q_OBJECT ++public: ++ enum AnimalRoles { ++ TypeRole = Qt::UserRole + 1, ++ SizeRole ++ }; ++ ++ AnimalModel(QObject *parent = 0); ++//![1] ++ ++ void addAnimal(const Animal &animal); ++ ++ int rowCount(const QModelIndex & parent = QModelIndex()) const; ++ ++ QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; ++ ++private: ++ QList m_animals; ++//![2] ++}; ++//![2] ++ ++ diff --cc examples/quick/modelviews/abstractitemmodel/view.qml index 0000000,0000000..64f5871 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/abstractitemmodel/view.qml @@@ -1,0 -1,0 +1,50 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++import QtQuick 2.0 ++ ++//![0] ++ListView { ++ width: 200; height: 250 ++ ++ model: myModel ++ delegate: Text { text: "Animal: " + type + ", " + size } ++} ++//![0] ++ diff --cc examples/quick/modelviews/gridview/gridview-example.qml index 0000000,0000000..ea3bb5c new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/gridview/gridview-example.qml @@@ -1,0 -1,0 +1,93 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Rectangle { ++ width: 300; height: 400 ++ color: "white" ++ ++ ListModel { ++ id: appModel ++ ListElement { name: "Music"; icon: "pics/AudioPlayer_48.png" } ++ ListElement { name: "Movies"; icon: "pics/VideoPlayer_48.png" } ++ ListElement { name: "Camera"; icon: "pics/Camera_48.png" } ++ ListElement { name: "Calendar"; icon: "pics/DateBook_48.png" } ++ ListElement { name: "Messaging"; icon: "pics/EMail_48.png" } ++ ListElement { name: "Todo List"; icon: "pics/TodoList_48.png" } ++ ListElement { name: "Contacts"; icon: "pics/AddressBook_48.png" } ++ } ++ ++ Component { ++ id: appDelegate ++ ++ Item { ++ width: 100; height: 100 ++ ++ Image { ++ id: myIcon ++ y: 20; anchors.horizontalCenter: parent.horizontalCenter ++ source: icon ++ } ++ Text { ++ anchors { top: myIcon.bottom; horizontalCenter: parent.horizontalCenter } ++ text: name ++ } ++ MouseArea { ++ anchors.fill: parent ++ onClicked: parent.GridView.view.currentIndex = index ++ } ++ } ++ } ++ ++ Component { ++ id: appHighlight ++ Rectangle { width: 80; height: 80; color: "lightsteelblue" } ++ } ++ ++ GridView { ++ anchors.fill: parent ++ cellWidth: 100; cellHeight: 100 ++ highlight: appHighlight ++ focus: true ++ model: appModel ++ delegate: appDelegate ++ } ++} diff --cc examples/quick/modelviews/gridview/pics/AddressBook_48.png index 0000000,0000000..1ab7c8e new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/gridview/pics/AudioPlayer_48.png index 0000000,0000000..f4b8689 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/gridview/pics/Camera_48.png index 0000000,0000000..c76b524 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/gridview/pics/DateBook_48.png index 0000000,0000000..58f5787 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/gridview/pics/EMail_48.png index 0000000,0000000..d6d84a6 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/gridview/pics/TodoList_48.png index 0000000,0000000..0988448 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/gridview/pics/VideoPlayer_48.png index 0000000,0000000..52638c5 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/listview/content/PetsModel.qml index 0000000,0000000..4f2087d new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/listview/content/PetsModel.qml @@@ -1,0 -1,0 +1,98 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++ListModel { ++ ListElement { ++ name: "Polly" ++ type: "Parrot" ++ age: 12 ++ size: "Small" ++ } ++ ListElement { ++ name: "Penny" ++ type: "Turtle" ++ age: 4 ++ size: "Small" ++ } ++ ListElement { ++ name: "Warren" ++ type: "Rabbit" ++ age: 2 ++ size: "Small" ++ } ++ ListElement { ++ name: "Spot" ++ type: "Dog" ++ age: 9 ++ size: "Medium" ++ } ++ ListElement { ++ name: "Schrödinger" ++ type: "Cat" ++ age: 2 ++ size: "Medium" ++ } ++ ListElement { ++ name: "Joey" ++ type: "Kangaroo" ++ age: 1 ++ size: "Medium" ++ } ++ ListElement { ++ name: "Kimba" ++ type: "Bunny" ++ age: 65 ++ size: "Large" ++ } ++ ListElement { ++ name: "Rover" ++ type: "Dog" ++ age: 5 ++ size: "Large" ++ } ++ ListElement { ++ name: "Tiny" ++ type: "Elephant" ++ age: 15 ++ size: "Large" ++ } ++} diff --cc examples/quick/modelviews/listview/content/PressAndHoldButton.qml index 0000000,0000000..b20d8f6 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/listview/content/PressAndHoldButton.qml @@@ -1,0 -1,0 +1,82 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Image { ++ id: container ++ ++ property int repeatDelay: 300 ++ property int repeatDuration: 75 ++ property bool pressed: false ++ ++ signal clicked ++ ++ scale: pressed ? 0.9 : 1 ++ ++ function release() { ++ autoRepeatClicks.stop() ++ container.pressed = false ++ } ++ ++ SequentialAnimation on pressed { ++ id: autoRepeatClicks ++ running: false ++ ++ PropertyAction { target: container; property: "pressed"; value: true } ++ ScriptAction { script: container.clicked() } ++ PauseAnimation { duration: repeatDelay } ++ ++ SequentialAnimation { ++ loops: Animation.Infinite ++ ScriptAction { script: container.clicked() } ++ PauseAnimation { duration: repeatDuration } ++ } ++ } ++ ++ MouseArea { ++ anchors.fill: parent ++ ++ onPressed: autoRepeatClicks.start() ++ onReleased: container.release() ++ onCanceled: container.release() ++ } ++} ++ diff --cc examples/quick/modelviews/listview/content/RecipesModel.qml index 0000000,0000000..86210ba new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/listview/content/RecipesModel.qml @@@ -1,0 -1,0 +1,129 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++ListModel { ++ ListElement { ++ title: "Pancakes" ++ picture: "content/pics/pancakes.jpg" ++ ingredients: " ++
    ++
  • 1 cup (150g) self-raising flour ++
  • 1 tbs caster sugar ++
  • 3/4 cup (185ml) milk ++
  • 1 egg ++
++ " ++ method: " ++
    ++
  1. Sift flour and sugar together into a bowl. Add a pinch of salt. ++
  2. Beat milk and egg together, then add to dry ingredients. Beat until smooth. ++
  3. Pour mixture into a pan on medium heat and cook until bubbles appear on the surface. ++
  4. Turn over and cook other side until golden. ++
++ " ++ } ++ ListElement { ++ title: "Fruit Salad" ++ picture: "content/pics/fruit-salad.jpg" ++ ingredients: "* Seasonal Fruit" ++ method: "* Chop fruit and place in a bowl." ++ } ++ ListElement { ++ title: "Vegetable Soup" ++ picture: "content/pics/vegetable-soup.jpg" ++ ingredients: " ++
    ++
  • 1 onion ++
  • 1 turnip ++
  • 1 potato ++
  • 1 carrot ++
  • 1 head of celery ++
  • 1 1/2 litres of water ++
++ " ++ method: " ++
    ++
  1. Chop vegetables. ++
  2. Boil in water until vegetables soften. ++
  3. Season with salt and pepper to taste. ++
++ " ++ } ++ ListElement { ++ title: "Hamburger" ++ picture: "content/pics/hamburger.jpg" ++ ingredients: " ++
    ++
  • 500g minced beef ++
  • Seasoning ++
  • lettuce, tomato, onion, cheese ++
  • 1 hamburger bun for each burger ++
++ " ++ method: " ++
    ++
  1. Mix the beef, together with seasoning, in a food processor. ++
  2. Shape the beef into burgers. ++
  3. Grill the burgers for about 5 mins on each side (until cooked through) ++
  4. Serve each burger on a bun with ketchup, cheese, lettuce, tomato and onion. ++
++ " ++ } ++ ListElement { ++ title: "Lemonade" ++ picture: "content/pics/lemonade.jpg" ++ ingredients: " ++
    ++
  • 1 cup Lemon Juice ++
  • 1 cup Sugar ++
  • 6 Cups of Water (2 cups warm water, 4 cups cold water) ++
++ " ++ method: " ++
    ++
  1. Pour 2 cups of warm water into a pitcher and stir in sugar until it dissolves. ++
  2. Pour in lemon juice, stir again, and add 4 cups of cold water. ++
  3. Chill or serve over ice cubes. ++
++ " ++ } ++} diff --cc examples/quick/modelviews/listview/content/TextButton.qml index 0000000,0000000..980ee21 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/listview/content/TextButton.qml @@@ -1,0 -1,0 +1,78 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Rectangle { ++ id: container ++ ++ property alias text: label.text ++ ++ signal clicked ++ ++ width: label.width + 20; height: label.height + 6 ++ smooth: true ++ radius: 10 ++ ++ gradient: Gradient { ++ GradientStop { id: gradientStop; position: 0.0; color: palette.light } ++ GradientStop { position: 1.0; color: palette.button } ++ } ++ ++ SystemPalette { id: palette } ++ ++ MouseArea { ++ id: mouseArea ++ anchors.fill: parent ++ onClicked: { container.clicked() } ++ } ++ ++ Text { ++ id: label ++ anchors.centerIn: parent ++ } ++ ++ states: State { ++ name: "pressed" ++ when: mouseArea.pressed ++ PropertyChanges { target: gradientStop; color: palette.dark } ++ } ++} ++ diff --cc examples/quick/modelviews/listview/content/ToggleButton.qml index 0000000,0000000..52f4988 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/listview/content/ToggleButton.qml @@@ -1,0 -1,0 +1,58 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the QtQml module of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Rectangle { ++ id: root ++ property alias label: text.text ++ property bool active: false ++ signal toggled ++ width: 149 ++ height: 30 ++ radius: 3 ++ color: active ? "green" : "lightgray" ++ border.width: 1 ++ Text { id: text; anchors.centerIn: parent; font.pixelSize: 14 } ++ MouseArea { ++ anchors.fill: parent ++ onClicked: { active = !active; root.toggled() } ++ } ++} diff --cc examples/quick/modelviews/listview/content/pics/arrow-down.png index 0000000,0000000..29d1d44 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/listview/content/pics/arrow-up.png index 0000000,0000000..e437312 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/listview/content/pics/fruit-salad.jpg index 0000000,0000000..da5a6b1 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/listview/content/pics/hamburger.jpg index 0000000,0000000..d0a15be new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/listview/content/pics/lemonade.jpg index 0000000,0000000..db445c9 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/listview/content/pics/list-delete.png index 0000000,0000000..df2a147 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/listview/content/pics/minus-sign.png index 0000000,0000000..d6f233d new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/listview/content/pics/moreDown.png index 0000000,0000000..31a35d5 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/listview/content/pics/moreUp.png index 0000000,0000000..fefb9c9 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/listview/content/pics/pancakes.jpg index 0000000,0000000..60c4396 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/listview/content/pics/plus-sign.png index 0000000,0000000..40df113 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/listview/content/pics/vegetable-soup.jpg index 0000000,0000000..9dce332 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/listview/dynamiclist.qml index 0000000,0000000..ee7c632 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/listview/dynamiclist.qml @@@ -1,0 -1,0 +1,203 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++import QtQuick 2.0 ++import "content" ++ ++// This example shows how items can be dynamically added to and removed from ++// a ListModel, and how these list modifications can be animated. ++ ++Rectangle { ++ id: container ++ width: 500; height: 400 ++ color: "#343434" ++ ++ // The model: ++ ListModel { ++ id: fruitModel ++ ++ ListElement { ++ name: "Apple"; cost: 2.45 ++ attributes: [ ++ ListElement { description: "Core" }, ++ ListElement { description: "Deciduous" } ++ ] ++ } ++ ListElement { ++ name: "Banana"; cost: 1.95 ++ attributes: [ ++ ListElement { description: "Tropical" }, ++ ListElement { description: "Seedless" } ++ ] ++ } ++ ListElement { ++ name: "Cumquat"; cost: 3.25 ++ attributes: [ ++ ListElement { description: "Citrus" } ++ ] ++ } ++ ListElement { ++ name: "Durian"; cost: 9.95 ++ attributes: [ ++ ListElement { description: "Tropical" }, ++ ListElement { description: "Smelly" } ++ ] ++ } ++ } ++ ++ // The delegate for each fruit in the model: ++ Component { ++ id: listDelegate ++ ++ Item { ++ id: delegateItem ++ width: listView.width; height: 55 ++ clip: true ++ ++ Row { ++ anchors.verticalCenter: parent.verticalCenter ++ spacing: 10 ++ ++ Column { ++ Image { ++ source: "content/pics/arrow-up.png" ++ MouseArea { anchors.fill: parent; onClicked: fruitModel.move(index, index-1, 1) } ++ } ++ Image { source: "content/pics/arrow-down.png" ++ MouseArea { anchors.fill: parent; onClicked: fruitModel.move(index, index+1, 1) } ++ } ++ } ++ ++ Column { ++ anchors.verticalCenter: parent.verticalCenter ++ ++ Text { ++ text: name ++ font.pixelSize: 15 ++ color: "white" ++ } ++ Row { ++ spacing: 5 ++ Repeater { ++ model: attributes ++ Text { text: description; color: "White" } ++ } ++ } ++ } ++ } ++ ++ Row { ++ anchors.verticalCenter: parent.verticalCenter ++ anchors.right: parent.right ++ spacing: 10 ++ ++ PressAndHoldButton { ++ anchors.verticalCenter: parent.verticalCenter ++ source: "content/pics/plus-sign.png" ++ onClicked: fruitModel.setProperty(index, "cost", cost + 0.25) ++ } ++ ++ Text { ++ id: costText ++ anchors.verticalCenter: parent.verticalCenter ++ text: '$' + Number(cost).toFixed(2) ++ font.pixelSize: 15 ++ color: "white" ++ font.bold: true ++ } ++ ++ PressAndHoldButton { ++ anchors.verticalCenter: parent.verticalCenter ++ source: "content/pics/minus-sign.png" ++ onClicked: fruitModel.setProperty(index, "cost", Math.max(0,cost-0.25)) ++ } ++ ++ Image { ++ source: "content/pics/list-delete.png" ++ MouseArea { anchors.fill:parent; onClicked: fruitModel.remove(index) } ++ } ++ } ++ ++ // Animate adding and removing of items: ++ ++ ListView.onAdd: SequentialAnimation { ++ PropertyAction { target: delegateItem; property: "height"; value: 0 } ++ NumberAnimation { target: delegateItem; property: "height"; to: 55; duration: 250; easing.type: Easing.InOutQuad } ++ } ++ ++ ListView.onRemove: SequentialAnimation { ++ PropertyAction { target: delegateItem; property: "ListView.delayRemove"; value: true } ++ NumberAnimation { target: delegateItem; property: "height"; to: 0; duration: 250; easing.type: Easing.InOutQuad } ++ ++ // Make sure delayRemove is set back to false so that the item can be destroyed ++ PropertyAction { target: delegateItem; property: "ListView.delayRemove"; value: false } ++ } ++ } ++ } ++ ++ // The view: ++ ListView { ++ id: listView ++ anchors.fill: parent; anchors.margins: 20 ++ model: fruitModel ++ delegate: listDelegate ++ } ++ ++ Row { ++ anchors { left: parent.left; bottom: parent.bottom; margins: 20 } ++ spacing: 10 ++ ++ TextButton { ++ text: "Add an item" ++ onClicked: { ++ fruitModel.append({ ++ "name": "Pizza Margarita", ++ "cost": 5.95, ++ "attributes": [{"description": "Cheese"}, {"description": "Tomato"}] ++ }) ++ } ++ } ++ ++ TextButton { ++ text: "Remove all items" ++ onClicked: fruitModel.clear() ++ } ++ } ++} ++ diff --cc examples/quick/modelviews/listview/expandingdelegates.qml index 0000000,0000000..43a9662 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/listview/expandingdelegates.qml @@@ -1,0 -1,0 +1,202 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++import "content" ++ ++// This example illustrates expanding a list item to show a more detailed view. ++ ++Rectangle { ++ id: page ++ width: 400; height: 240 ++ color: "black" ++ ++ // Delegate for the recipes. This delegate has two modes: ++ // 1. List mode (default), which just shows the picture and title of the recipe. ++ // 2. Details mode, which also shows the ingredients and method. ++ Component { ++ id: recipeDelegate ++ ++ Item { ++ id: recipe ++ ++ // Create a property to contain the visibility of the details. ++ // We can bind multiple element's opacity to this one property, ++ // rather than having a "PropertyChanges" line for each element we ++ // want to fade. ++ property real detailsOpacity : 0 ++ ++ width: listView.width ++ height: 70 ++ ++ // A simple rounded rectangle for the background ++ Rectangle { ++ id: background ++ x: 2; y: 2; width: parent.width - x*2; height: parent.height - y*2 ++ color: "ivory" ++ border.color: "orange" ++ radius: 5 ++ } ++ ++ // This mouse region covers the entire delegate. ++ // When clicked it changes mode to 'Details'. If we are already ++ // in Details mode, then no change will happen. ++ MouseArea { ++ anchors.fill: parent ++ onClicked: recipe.state = 'Details'; ++ } ++ ++ // Lay out the page: picture, title and ingredients at the top, and method at the ++ // bottom. Note that elements that should not be visible in the list ++ // mode have their opacity set to recipe.detailsOpacity. ++ Row { ++ id: topLayout ++ x: 10; y: 10; height: recipeImage.height; width: parent.width ++ spacing: 10 ++ ++ Image { ++ id: recipeImage ++ width: 50; height: 50 ++ source: picture ++ } ++ ++ Column { ++ width: background.width - recipeImage.width - 20; height: recipeImage.height ++ spacing: 5 ++ ++ Text { ++ text: title ++ font.bold: true; font.pointSize: 16 ++ } ++ ++ Text { ++ text: "Ingredients" ++ font.pointSize: 12; font.bold: true ++ opacity: recipe.detailsOpacity ++ } ++ ++ Text { ++ text: ingredients ++ wrapMode: Text.WordWrap ++ width: parent.width ++ opacity: recipe.detailsOpacity ++ } ++ } ++ } ++ ++ Item { ++ id: details ++ x: 10; width: parent.width - 20 ++ anchors { top: topLayout.bottom; topMargin: 10; bottom: parent.bottom; bottomMargin: 10 } ++ opacity: recipe.detailsOpacity ++ ++ Text { ++ id: methodTitle ++ anchors.top: parent.top ++ text: "Method" ++ font.pointSize: 12; font.bold: true ++ } ++ ++ Flickable { ++ id: flick ++ width: parent.width ++ anchors { top: methodTitle.bottom; bottom: parent.bottom } ++ contentHeight: methodText.height ++ clip: true ++ ++ Text { id: methodText; text: method; wrapMode: Text.WordWrap; width: details.width } ++ } ++ ++ Image { ++ anchors { right: flick.right; top: flick.top } ++ source: "content/pics/moreUp.png" ++ opacity: flick.atYBeginning ? 0 : 1 ++ } ++ ++ Image { ++ anchors { right: flick.right; bottom: flick.bottom } ++ source: "content/pics/moreDown.png" ++ opacity: flick.atYEnd ? 0 : 1 ++ } ++ } ++ ++ // A button to close the detailed view, i.e. set the state back to default (''). ++ TextButton { ++ y: 10 ++ anchors { right: background.right; rightMargin: 10 } ++ opacity: recipe.detailsOpacity ++ text: "Close" ++ ++ onClicked: recipe.state = ''; ++ } ++ ++ states: State { ++ name: "Details" ++ ++ PropertyChanges { target: background; color: "white" } ++ PropertyChanges { target: recipeImage; width: 130; height: 130 } // Make picture bigger ++ PropertyChanges { target: recipe; detailsOpacity: 1; x: 0 } // Make details visible ++ PropertyChanges { target: recipe; height: listView.height } // Fill the entire list area with the detailed view ++ ++ // Move the list so that this item is at the top. ++ PropertyChanges { target: recipe.ListView.view; explicit: true; contentY: recipe.y } ++ ++ // Disallow flicking while we're in detailed view ++ PropertyChanges { target: recipe.ListView.view; interactive: false } ++ } ++ ++ transitions: Transition { ++ // Make the state changes smooth ++ ParallelAnimation { ++ ColorAnimation { property: "color"; duration: 500 } ++ NumberAnimation { duration: 300; properties: "detailsOpacity,x,contentY,height,width" } ++ } ++ } ++ } ++ } ++ ++ // The actual list ++ ListView { ++ id: listView ++ anchors.fill: parent ++ model: RecipesModel {} ++ delegate: recipeDelegate ++ } ++} diff --cc examples/quick/modelviews/listview/highlight.qml index 0000000,0000000..d8f7608 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/listview/highlight.qml @@@ -1,0 -1,0 +1,99 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++// This example shows how to create your own highlight delegate for a ListView ++// that uses a SpringAnimation to provide custom movement when the ++// highlight bar is moved between items. ++ ++import QtQuick 2.0 ++import "content" ++ ++Rectangle { ++ width: 200; height: 300 ++ ++ // Define a delegate component. A component will be ++ // instantiated for each visible item in the list. ++ Component { ++ id: petDelegate ++ Item { ++ id: wrapper ++ width: 200; height: 55 ++ Column { ++ Text { text: 'Name: ' + name } ++ Text { text: 'Type: ' + type } ++ Text { text: 'Age: ' + age } ++ } ++ // indent the item if it is the current item ++ states: State { ++ name: "Current" ++ when: wrapper.ListView.isCurrentItem ++ PropertyChanges { target: wrapper; x: 20 } ++ } ++ transitions: Transition { ++ NumberAnimation { properties: "x"; duration: 200 } ++ } ++ } ++ } ++ ++ // Define a highlight with customised movement between items. ++ Component { ++ id: highlightBar ++ Rectangle { ++ width: 200; height: 50 ++ color: "#FFFF88" ++ y: listView.currentItem.y; ++ Behavior on y { SpringAnimation { spring: 2; damping: 0.1 } } ++ } ++ } ++ ++ ListView { ++ id: listView ++ width: 200; height: parent.height ++ ++ model: PetsModel {} ++ delegate: petDelegate ++ focus: true ++ ++ // Set the highlight delegate. Note we must also set highlightFollowsCurrentItem ++ // to false so the highlight delegate can control how the highlight is moved. ++ highlight: highlightBar ++ highlightFollowsCurrentItem: false ++ } ++} diff --cc examples/quick/modelviews/listview/highlightranges.qml index 0000000,0000000..a536ddc new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/listview/highlightranges.qml @@@ -1,0 -1,0 +1,122 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++import "content" ++ ++Rectangle { ++ id: root ++ property int current: 0 ++ width: 600; height: 300 ++ ++ // This example shows the same model in three different ListView items, ++ // with different highlight ranges. The highlight ranges are set by the ++ // preferredHighlightBegin and preferredHighlightEnd properties in ListView. ++ // ++ // The first ListView does not set a highlight range, so its currentItem ++ // can move freely within the visible area. If it moves outside the ++ // visible area, the view is automatically scrolled to keep the current ++ // item visible. ++ // ++ // The second ListView sets a highlight range which attempts to keep the ++ // current item within the the bounds of the range. However, ++ // items will not scroll beyond the beginning or end of the view, ++ // forcing the highlight to move outside the range at the ends. ++ // ++ // The third ListView sets the highlightRangeMode to StrictlyEnforceRange ++ // and sets a range smaller than the height of an item. This ++ // forces the current item to change when the view is flicked, ++ // since the highlight is unable to move. ++ // ++ // All ListViews bind their currentIndex to the root.current property. ++ // The first ListView sets root.current whenever its currentIndex changes ++ // due to keyboard interaction. ++ // Flicking the third ListView with the mouse also changes root.current. ++ ++ ListView { ++ id: list1 ++ width: 200; height: parent.height ++ model: PetsModel {} ++ delegate: petDelegate ++ ++ highlight: Rectangle { color: "lightsteelblue" } ++ currentIndex: root.current ++ onCurrentIndexChanged: root.current = currentIndex ++ focus: true ++ } ++ ++ ListView { ++ id: list2 ++ x: list1.width ++ width: 200; height: parent.height ++ model: PetsModel {} ++ delegate: petDelegate ++ ++ highlight: Rectangle { color: "yellow" } ++ currentIndex: root.current ++ preferredHighlightBegin: 80; preferredHighlightEnd: 220 ++ highlightRangeMode: ListView.ApplyRange ++ } ++ ++ ListView { ++ id: list3 ++ x: list1.width + list2.width ++ width: 200; height: parent.height ++ model: PetsModel {} ++ delegate: petDelegate ++ ++ highlight: Rectangle { color: "yellow" } ++ currentIndex: root.current ++ onCurrentIndexChanged: root.current = currentIndex ++ preferredHighlightBegin: 125; preferredHighlightEnd: 125 ++ highlightRangeMode: ListView.StrictlyEnforceRange ++ } ++ ++ // The delegate for each list ++ Component { ++ id: petDelegate ++ Column { ++ width: 200 ++ Text { text: 'Name: ' + name } ++ Text { text: 'Type: ' + type } ++ Text { text: 'Age: ' + age } ++ } ++ } ++} diff --cc examples/quick/modelviews/listview/sections.qml index 0000000,0000000..2e63a86 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/listview/sections.qml @@@ -1,0 -1,0 +1,127 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++// This example shows how a ListView can be separated into sections using ++// the ListView.section attached property. ++ ++import QtQuick 2.0 ++import "content" ++ ++Rectangle { ++ id: container ++ width: 300 ++ height: 360 ++ ++ ListModel { ++ id: animalsModel ++ ListElement { name: "Ant"; size: "Tiny" } ++ ListElement { name: "Flea"; size: "Tiny" } ++ ListElement { name: "Parrot"; size: "Small" } ++ ListElement { name: "Guinea pig"; size: "Small" } ++ ListElement { name: "Rat"; size: "Small" } ++ ListElement { name: "Butterfly"; size: "Small" } ++ ListElement { name: "Dog"; size: "Medium" } ++ ListElement { name: "Cat"; size: "Medium" } ++ ListElement { name: "Pony"; size: "Medium" } ++ ListElement { name: "Koala"; size: "Medium" } ++ ListElement { name: "Horse"; size: "Large" } ++ ListElement { name: "Tiger"; size: "Large" } ++ ListElement { name: "Giraffe"; size: "Large" } ++ ListElement { name: "Elephant"; size: "Huge" } ++ ListElement { name: "Whale"; size: "Huge" } ++ } ++ ++//! [0] ++ // The delegate for each section header ++ Component { ++ id: sectionHeading ++ Rectangle { ++ width: container.width ++ height: childrenRect.height ++ color: "lightsteelblue" ++ ++ Text { ++ text: section ++ font.bold: true ++ font.pixelSize: 20 ++ } ++ } ++ } ++ ++ ListView { ++ id: view ++ anchors.top: parent.top ++ anchors.bottom: buttonBar.top ++ width: parent.width ++ model: animalsModel ++ delegate: Text { text: name; font.pixelSize: 18 } ++ ++ section.property: "size" ++ section.criteria: ViewSection.FullString ++ section.delegate: sectionHeading ++ } ++//! [0] ++ ++ Row { ++ id: buttonBar ++ anchors.bottom: parent.bottom ++ anchors.bottomMargin: 1 ++ spacing: 1 ++ ToggleButton { ++ label: "CurrentLabelAtStart" ++ onToggled: { ++ if (active) ++ view.section.labelPositioning |= ViewSection.CurrentLabelAtStart ++ else ++ view.section.labelPositioning &= ~ViewSection.CurrentLabelAtStart ++ } ++ } ++ ToggleButton { ++ label: "NextLabelAtEnd" ++ onToggled: { ++ if (active) ++ view.section.labelPositioning |= ViewSection.NextLabelAtEnd ++ else ++ view.section.labelPositioning &= ~ViewSection.NextLabelAtEnd ++ } ++ } ++ } ++} ++ diff --cc examples/quick/modelviews/modelviews.pro index 0000000,0000000..7748da0 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/modelviews.pro @@@ -1,0 -1,0 +1,8 @@@ ++TEMPLATE = subdirs ++ ++SUBDIRS += \ ++ abstractitemmodel \ ++ objectlistmodel \ ++ stringlistmodel ++ ++ diff --cc examples/quick/modelviews/modelviews.qml index 0000000,f11608b..f11608b mode 000000,100644..100644 --- a/examples/quick/modelviews/modelviews.qml +++ b/examples/quick/modelviews/modelviews.qml diff --cc examples/quick/modelviews/modelviews.qmlproject index 0000000,0000000..40f9e56 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/modelviews.qmlproject @@@ -1,0 -1,0 +1,16 @@@ ++import QmlProject 1.1 ++ ++Project { ++ mainFile: "modelviews.qml" ++ ++ /* Include .qml, .js, and image files from current directory and subdirectories */ ++ QmlFiles { ++ directory: "." ++ } ++ JavaScriptFiles { ++ directory: "." ++ } ++ ImageFiles { ++ directory: "." ++ } ++} diff --cc examples/quick/modelviews/objectlistmodel/dataobject.cpp index 0000000,0000000..7216283 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/objectlistmodel/dataobject.cpp @@@ -1,0 -1,0 +1,78 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++#include ++#include "dataobject.h" ++ ++DataObject::DataObject(QObject *parent) ++ : QObject(parent) ++{ ++} ++ ++DataObject::DataObject(const QString &name, const QString &color, QObject *parent) ++ : QObject(parent), m_name(name), m_color(color) ++{ ++} ++ ++QString DataObject::name() const ++{ ++ return m_name; ++} ++ ++void DataObject::setName(const QString &name) ++{ ++ if (name != m_name) { ++ m_name = name; ++ emit nameChanged(); ++ } ++} ++ ++QString DataObject::color() const ++{ ++ return m_color; ++} ++ ++void DataObject::setColor(const QString &color) ++{ ++ if (color != m_color) { ++ m_color = color; ++ emit colorChanged(); ++ } ++} diff --cc examples/quick/modelviews/objectlistmodel/dataobject.h index 0000000,0000000..bea92a2 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/objectlistmodel/dataobject.h @@@ -1,0 -1,0 +1,76 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++#ifndef DATAOBJECT_H ++#define DATAOBJECT_H ++ ++#include ++ ++//![0] ++class DataObject : public QObject ++{ ++ Q_OBJECT ++ ++ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) ++ Q_PROPERTY(QString color READ color WRITE setColor NOTIFY colorChanged) ++//![0] ++ ++public: ++ DataObject(QObject *parent=0); ++ DataObject(const QString &name, const QString &color, QObject *parent=0); ++ ++ QString name() const; ++ void setName(const QString &name); ++ ++ QString color() const; ++ void setColor(const QString &color); ++ ++signals: ++ void nameChanged(); ++ void colorChanged(); ++ ++private: ++ QString m_name; ++ QString m_color; ++//![1] ++}; ++//![1] ++ ++#endif // DATAOBJECT_H diff --cc examples/quick/modelviews/objectlistmodel/main.cpp index 0000000,0000000..bb3895f new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/objectlistmodel/main.cpp @@@ -1,0 -1,0 +1,78 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the demonstration applications of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "dataobject.h" ++ ++/* ++ This example illustrates exposing a QList as a ++ model in QML ++*/ ++ ++//![0] ++int main(int argc, char ** argv) ++{ ++ QGuiApplication app(argc, argv); ++ ++ QList dataList; ++ dataList.append(new DataObject("Item 1", "red")); ++ dataList.append(new DataObject("Item 2", "green")); ++ dataList.append(new DataObject("Item 3", "blue")); ++ dataList.append(new DataObject("Item 4", "yellow")); ++ ++ QQuickView view; ++ view.setResizeMode(QQuickView::SizeRootObjectToView); ++ QQmlContext *ctxt = view.rootContext(); ++ ctxt->setContextProperty("myModel", QVariant::fromValue(dataList)); ++//![0] ++ ++ view.setSource(QUrl("qrc:view.qml")); ++ view.show(); ++ ++ return app.exec(); ++} ++ diff --cc examples/quick/modelviews/objectlistmodel/objectlistmodel.pro index 0000000,0000000..7f323c3 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/objectlistmodel/objectlistmodel.pro @@@ -1,0 -1,0 +1,6 @@@ ++QT += qml quick ++ ++SOURCES += main.cpp \ ++ dataobject.cpp ++HEADERS += dataobject.h ++RESOURCES += objectlistmodel.qrc diff --cc examples/quick/modelviews/objectlistmodel/objectlistmodel.qmlproject index 0000000,0000000..2bb4016 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/objectlistmodel/objectlistmodel.qmlproject @@@ -1,0 -1,0 +1,14 @@@ ++import QmlProject 1.0 ++ ++Project { ++ /* Include .qml, .js, and image files from current directory and subdirectories */ ++ QmlFiles { ++ directory: "." ++ } ++ JavaScriptFiles { ++ directory: "." ++ } ++ ImageFiles { ++ directory: "." ++ } ++} diff --cc examples/quick/modelviews/objectlistmodel/objectlistmodel.qrc index 0000000,0000000..17e9301 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/objectlistmodel/objectlistmodel.qrc @@@ -1,0 -1,0 +1,5 @@@ ++ ++ ++ view.qml ++ ++ diff --cc examples/quick/modelviews/objectlistmodel/view.qml index 0000000,0000000..3954e79 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/objectlistmodel/view.qml @@@ -1,0 -1,0 +1,55 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++//![0] ++ListView { ++ width: 100; height: 100 ++ ++ model: myModel ++ delegate: Rectangle { ++ height: 25 ++ width: 100 ++ color: model.modelData.color ++ Text { text: name } ++ } ++} ++//![0] diff --cc examples/quick/modelviews/package/Delegate.qml index 0000000,0000000..97c7840 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/package/Delegate.qml @@@ -1,0 -1,0 +1,88 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++//![0] ++Package { ++ Text { id: listDelegate; width: 200; height: 25; text: 'Empty'; Package.name: 'list' } ++ Text { id: gridDelegate; width: 100; height: 50; text: 'Empty'; Package.name: 'grid' } ++ ++ Rectangle { ++ id: wrapper ++ width: 200; height: 25 ++ color: 'lightsteelblue' ++ ++ Text { text: display; anchors.centerIn: parent } ++ MouseArea { ++ anchors.fill: parent ++ onClicked: { ++ if (wrapper.state == 'inList') ++ wrapper.state = 'inGrid'; ++ else ++ wrapper.state = 'inList'; ++ } ++ } ++ ++ state: 'inList' ++ states: [ ++ State { ++ name: 'inList' ++ ParentChange { target: wrapper; parent: listDelegate } ++ }, ++ State { ++ name: 'inGrid' ++ ParentChange { ++ target: wrapper; parent: gridDelegate ++ x: 0; y: 0; width: gridDelegate.width; height: gridDelegate.height ++ } ++ } ++ ] ++ ++ transitions: [ ++ Transition { ++ ParentAnimation { ++ NumberAnimation { properties: 'x,y,width,height'; duration: 300 } ++ } ++ } ++ ] ++ } ++} ++//![0] diff --cc examples/quick/modelviews/package/view.qml index 0000000,7ba6664..7ba6664 mode 000000,100644..100644 --- a/examples/quick/modelviews/package/view.qml +++ b/examples/quick/modelviews/package/view.qml diff --cc examples/quick/modelviews/parallax/content/Clock.qml index 0000000,0000000..7f0e8cb new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/parallax/content/Clock.qml @@@ -1,0 -1,0 +1,143 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Item { ++ id : clock ++ width: { ++ if (ListView.view && ListView.view.width >= 200) ++ return ListView.view.width / Math.floor(ListView.view.width / 200.0); ++ else ++ return 200; ++ } ++ ++ height: { ++ if (ListView.view && ListView.view.height >= 240) ++ return ListView.view.height; ++ else ++ return 240; ++ } ++ ++ property alias city: cityLabel.text ++ property int hours ++ property int minutes ++ property int seconds ++ property real shift ++ property bool night: false ++ property bool internationalTime: true //Unset for local time ++ ++ function timeChanged() { ++ var date = new Date; ++ hours = internationalTime ? date.getUTCHours() + Math.floor(clock.shift) : date.getHours() ++ night = ( hours < 7 || hours > 19 ) ++ minutes = internationalTime ? date.getUTCMinutes() + ((clock.shift % 1) * 60) : date.getMinutes() ++ seconds = date.getUTCSeconds(); ++ } ++ ++ Timer { ++ interval: 100; running: true; repeat: true; ++ onTriggered: clock.timeChanged() ++ } ++ ++ Item { ++ anchors.centerIn: parent ++ width: 200; height: 240 ++ ++ Image { id: background; source: "clock.png"; visible: clock.night == false } ++ Image { source: "clock-night.png"; visible: clock.night == true } ++ ++ ++ Image { ++ x: 92.5; y: 27 ++ source: "hour.png" ++ smooth: true ++ transform: Rotation { ++ id: hourRotation ++ origin.x: 7.5; origin.y: 73; ++ angle: (clock.hours * 30) + (clock.minutes * 0.5) ++ Behavior on angle { ++ SpringAnimation { spring: 2; damping: 0.2; modulus: 360 } ++ } ++ } ++ } ++ ++ Image { ++ x: 93.5; y: 17 ++ source: "minute.png" ++ smooth: true ++ transform: Rotation { ++ id: minuteRotation ++ origin.x: 6.5; origin.y: 83; ++ angle: clock.minutes * 6 ++ Behavior on angle { ++ SpringAnimation { spring: 2; damping: 0.2; modulus: 360 } ++ } ++ } ++ } ++ ++ Image { ++ x: 97.5; y: 20 ++ source: "second.png" ++ smooth: true ++ transform: Rotation { ++ id: secondRotation ++ origin.x: 2.5; origin.y: 80; ++ angle: clock.seconds * 6 ++ Behavior on angle { ++ SpringAnimation { spring: 2; damping: 0.2; modulus: 360 } ++ } ++ } ++ } ++ ++ Image { ++ anchors.centerIn: background; source: "center.png" ++ } ++ ++ Text { ++ id: cityLabel ++ y: 210; anchors.horizontalCenter: parent.horizontalCenter ++ color: "white" ++ font.family: "Helvetica" ++ font.bold: true; font.pixelSize: 16 ++ style: Text.Raised; styleColor: "black" ++ } ++ } ++} diff --cc examples/quick/modelviews/parallax/content/ParallaxView.qml index 0000000,0000000..2acf50d new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/parallax/content/ParallaxView.qml @@@ -1,0 -1,0 +1,123 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Item { ++ id: root ++ ++ property alias background: background.source ++ property int currentIndex: 0 ++ default property alias content: visualModel.children ++ ++ Image { ++ id: background ++ fillMode: Image.TileHorizontally ++ x: -list.contentX / 2 ++ width: Math.max(list.contentWidth, parent.width) ++ } ++ ++ ListView { ++ id: list ++ anchors.fill: parent ++ ++ currentIndex: root.currentIndex ++ onCurrentIndexChanged: root.currentIndex = currentIndex ++ ++ orientation: Qt.Horizontal ++ boundsBehavior: Flickable.DragOverBounds ++ model: VisualItemModel { id: visualModel } ++ ++ highlightRangeMode: ListView.StrictlyEnforceRange ++ snapMode: ListView.SnapOneItem ++ } ++ ++ ListView { ++ id: selector ++ ++ height: 50 ++ anchors.bottom: parent.bottom ++ anchors.horizontalCenter: parent.horizontalCenter ++ width: Math.min(count * 50, parent.width - 20) ++ interactive: width == parent.width - 20 ++ orientation: Qt.Horizontal ++ ++ currentIndex: root.currentIndex ++ onCurrentIndexChanged: root.currentIndex = currentIndex ++ ++ model: visualModel.children ++ delegate: Item { ++ width: 50; height: 50 ++ id: delegateRoot ++ ++ Image { ++ id: image ++ source: modelData.icon ++ smooth: true ++ scale: 0.8 ++ } ++ ++ MouseArea { ++ anchors.fill: parent ++ onClicked: { root.currentIndex = index } ++ } ++ ++ states: State { ++ name: "Selected" ++ when: delegateRoot.ListView.isCurrentItem == true ++ PropertyChanges { ++ target: image ++ scale: 1 ++ y: -5 ++ } ++ } ++ transitions: Transition { ++ NumberAnimation { properties: "scale,y" } ++ } ++ } ++ ++ Rectangle { ++ color: "#60FFFFFF" ++ x: -10; y: -10; z: -1 ++ width: parent.width + 20; height: parent.height + 20 ++ radius: 10 ++ } ++ } ++} diff --cc examples/quick/modelviews/parallax/content/QuitButton.qml index 0000000,0000000..702b892 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/parallax/content/QuitButton.qml @@@ -1,0 -1,0 +1,52 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++Image { ++ source: "quit.png" ++ scale: quitMouse.pressed ? 0.8 : 1.0 ++ smooth: quitMouse.pressed ++ MouseArea { ++ id: quitMouse ++ anchors.fill: parent ++ anchors.margins: -10 ++ onClicked: Qt.quit() ++ } ++} diff --cc examples/quick/modelviews/parallax/content/Smiley.qml index 0000000,0000000..982b6c5 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/parallax/content/Smiley.qml @@@ -1,0 -1,0 +1,84 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++// This is taken from the declarative animation/basics/property-animation.qml ++// example ++ ++Item { ++ id: window ++ width: 320; height: 480 ++ ++ Image { ++ anchors.horizontalCenter: parent.horizontalCenter ++ y: smiley.minHeight + 58 ++ source: "pics/shadow.png" ++ ++ scale: smiley.y * 0.5 / (smiley.minHeight - smiley.maxHeight) ++ } ++ ++ Image { ++ id: smiley ++ property int maxHeight: window.height / 3 ++ property int minHeight: 2 * window.height / 3 ++ ++ anchors.horizontalCenter: parent.horizontalCenter ++ y: minHeight ++ source: "pics/face-smile.png" ++ ++ SequentialAnimation on y { ++ loops: Animation.Infinite ++ ++ NumberAnimation { ++ from: smiley.minHeight; to: smiley.maxHeight ++ easing.type: Easing.OutExpo; duration: 300 ++ } ++ ++ NumberAnimation { ++ from: smiley.maxHeight; to: smiley.minHeight ++ easing.type: Easing.OutBounce; duration: 1000 ++ } ++ ++ PauseAnimation { duration: 500 } ++ } ++ } ++} ++ diff --cc examples/quick/modelviews/parallax/content/background.png index 0000000,0000000..a885950 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/parallax/content/center.png index 0000000,0000000..7fbd802 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/parallax/content/clock-night.png index 0000000,0000000..cc7151a new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/parallax/content/clock.png index 0000000,0000000..462edac new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/parallax/content/hour.png index 0000000,0000000..f8061a1 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/parallax/content/minute.png index 0000000,0000000..1297ec7 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/parallax/content/pics/background.jpg index 0000000,0000000..61cca2f new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/parallax/content/pics/face-smile.png index 0000000,0000000..3d66d72 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/parallax/content/pics/home-page.png index 0000000,0000000..bd090c3 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/parallax/content/pics/home-page.svg index 0000000,0000000..4f16958 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/parallax/content/pics/home-page.svg @@@ -1,0 -1,0 +1,445 @@@ ++ ++image/svg+xmlGo HomeJakub Steinerhttp://jimmac.musichall.czhomereturngodefaultuserdirectoryTuomas Kuosmanen ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ diff --cc examples/quick/modelviews/parallax/content/pics/shadow.png index 0000000,0000000..8270565 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/parallax/content/pics/yast-joystick.png index 0000000,0000000..858cea0 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/parallax/content/pics/yast-wol.png index 0000000,0000000..7712180 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/parallax/content/quit.png index 0000000,0000000..b822057 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/parallax/content/second.png index 0000000,0000000..4aa9fb5 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/parallax/parallax.qml index 0000000,30578e5..30578e5 mode 000000,100644..100644 --- a/examples/quick/modelviews/parallax/parallax.qml +++ b/examples/quick/modelviews/parallax/parallax.qml diff --cc examples/quick/modelviews/pathview/pathview-example.qml index 0000000,0000000..6161343 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/pathview/pathview-example.qml @@@ -1,0 -1,0 +1,107 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Rectangle { ++ width: 400; height: 240 ++ color: "white" ++ ++ ListModel { ++ id: appModel ++ ListElement { name: "Music"; icon: "pics/AudioPlayer_48.png" } ++ ListElement { name: "Movies"; icon: "pics/VideoPlayer_48.png" } ++ ListElement { name: "Camera"; icon: "pics/Camera_48.png" } ++ ListElement { name: "Calendar"; icon: "pics/DateBook_48.png" } ++ ListElement { name: "Messaging"; icon: "pics/EMail_48.png" } ++ ListElement { name: "Todo List"; icon: "pics/TodoList_48.png" } ++ ListElement { name: "Contacts"; icon: "pics/AddressBook_48.png" } ++ } ++ ++ Component { ++ id: appDelegate ++ Item { ++ width: 100; height: 100 ++ scale: PathView.iconScale ++ ++ Image { ++ id: myIcon ++ y: 20; anchors.horizontalCenter: parent.horizontalCenter ++ source: icon ++ smooth: true ++ } ++ Text { ++ anchors { top: myIcon.bottom; horizontalCenter: parent.horizontalCenter } ++ text: name ++ smooth: true ++ } ++ ++ MouseArea { ++ anchors.fill: parent ++ onClicked: view.currentIndex = index ++ } ++ } ++ } ++ ++ Component { ++ id: appHighlight ++ Rectangle { width: 80; height: 80; color: "lightsteelblue" } ++ } ++ ++ PathView { ++ id: view ++ anchors.fill: parent ++ highlight: appHighlight ++ preferredHighlightBegin: 0.5 ++ preferredHighlightEnd: 0.5 ++ focus: true ++ model: appModel ++ delegate: appDelegate ++ path: Path { ++ startX: 10 ++ startY: 50 ++ PathAttribute { name: "iconScale"; value: 0.5 } ++ PathQuad { x: 200; y: 150; controlX: 50; controlY: 200 } ++ PathAttribute { name: "iconScale"; value: 1.0 } ++ PathQuad { x: 390; y: 50; controlX: 350; controlY: 200 } ++ PathAttribute { name: "iconScale"; value: 0.5 } ++ } ++ } ++} diff --cc examples/quick/modelviews/pathview/pics/AddressBook_48.png index 0000000,0000000..1ab7c8e new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/pathview/pics/AudioPlayer_48.png index 0000000,0000000..f4b8689 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/pathview/pics/Camera_48.png index 0000000,0000000..c76b524 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/pathview/pics/DateBook_48.png index 0000000,0000000..58f5787 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/pathview/pics/EMail_48.png index 0000000,0000000..d6d84a6 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/pathview/pics/TodoList_48.png index 0000000,0000000..0988448 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/pathview/pics/VideoPlayer_48.png index 0000000,0000000..52638c5 new file mode 100644 Binary files differ diff --cc examples/quick/modelviews/stringlistmodel/main.cpp index 0000000,0000000..1285931 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/stringlistmodel/main.cpp @@@ -1,0 -1,0 +1,77 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the demonstration applications of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++ ++/* ++ This example illustrates exposing a QStringList as a ++ model in QML ++*/ ++ ++int main(int argc, char ** argv) ++{ ++ QGuiApplication app(argc, argv); ++ ++//![0] ++ QStringList dataList; ++ dataList.append("Item 1"); ++ dataList.append("Item 2"); ++ dataList.append("Item 3"); ++ dataList.append("Item 4"); ++ ++ QQuickView view; ++ QQmlContext *ctxt = view.rootContext(); ++ ctxt->setContextProperty("myModel", QVariant::fromValue(dataList)); ++//![0] ++ ++ view.setSource(QUrl("qrc:view.qml")); ++ view.show(); ++ ++ return app.exec(); ++} ++ diff --cc examples/quick/modelviews/stringlistmodel/stringlistmodel.pro index 0000000,0000000..19e62cd new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/stringlistmodel/stringlistmodel.pro @@@ -1,0 -1,0 +1,4 @@@ ++QT += qml quick ++ ++SOURCES += main.cpp ++RESOURCES += stringlistmodel.qrc diff --cc examples/quick/modelviews/stringlistmodel/stringlistmodel.qrc index 0000000,0000000..17e9301 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/stringlistmodel/stringlistmodel.qrc @@@ -1,0 -1,0 +1,5 @@@ ++ ++ ++ view.qml ++ ++ diff --cc examples/quick/modelviews/stringlistmodel/view.qml index 0000000,0000000..945763c new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/stringlistmodel/view.qml @@@ -1,0 -1,0 +1,54 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++//![0] ++ ++ListView { ++ width: 100; height: 100 ++ ++ model: myModel ++ delegate: Rectangle { ++ height: 25 ++ width: 100 ++ Text { text: modelData } ++ } ++} ++//![0] diff --cc examples/quick/modelviews/visualdatamodel/dragselection.qml index 0000000,0000000..c3186a5 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/visualdatamodel/dragselection.qml @@@ -1,0 -1,0 +1,200 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Item { ++ id: root ++ ++ width: 320 ++ height: 480 ++ ++ property bool dragging: false ++ ++ Component { ++ id: packageDelegate ++ Package { ++ id: packageRoot ++ ++ MouseArea { ++ id: visibleContainer ++ Package.name: "visible" ++ ++ width: 64 ++ height: 64 ++ enabled: packageRoot.VisualDataModel.inSelected ++ ++ drag.target: draggable ++ ++ Item { ++ id: draggable ++ ++ width: 64 ++ height: 64 ++ ++ Drag.active: visibleContainer.drag.active ++ ++ anchors { horizontalCenter: parent.horizontalCenter; verticalCenter: parent.verticalCenter } ++ ++ states: State { ++ when: visibleContainer.drag.active ++ AnchorChanges { target: draggable; anchors { horizontalCenter: undefined; verticalCenter: undefined} } ++ ParentChange { target: selectionView; parent: draggable; x: 0; y: 0 } ++ PropertyChanges { target: root; dragging: true } ++ ParentChange { target: draggable; parent: root } ++ } ++ } ++ DropArea { ++ anchors.fill: parent ++ onEntered: selectedItems.move(0, visualModel.items.get(packageRoot.VisualDataModel.itemsIndex), selectedItems.count) ++ } ++ } ++ Item { ++ id: selectionContainer ++ Package.name: "selection" ++ ++ width: 64 ++ height: 64 ++ ++ visible: PathView.onPath ++ } ++ Rectangle { ++ id: content ++ parent: visibleContainer ++ ++ width: 58 ++ height: 58 ++ ++ radius: 8 ++ ++ gradient: Gradient { ++ GradientStop { id: gradientStart; position: 0.0; color: "#8AC953" } ++ GradientStop { id: gradientEnd; position: 1.0; color: "#8BC953" } ++ } ++ ++ border.width: 2 ++ border.color: "#007423" ++ ++ state: root.dragging && packageRoot.VisualDataModel.inSelected ? "selected" : "visible" ++ ++ Text { ++ anchors.fill: parent ++ horizontalAlignment: Text.AlignHCenter ++ verticalAlignment: Text.AlignVCenter ++ color: "white" ++ text: modelData ++ font.pixelSize: 18 ++ } ++ ++ Rectangle { ++ anchors { right: parent.right; top: parent.top; margins: 3 } ++ width: 12; height: 12 ++ color: packageRoot.VisualDataModel.inSelected ? "black" : "white" ++ radius: 6 ++ ++ border.color: "white" ++ border.width: 2 ++ ++ MouseArea { ++ anchors.fill: parent ++ onClicked: packageRoot.VisualDataModel.inSelected = !packageRoot.VisualDataModel.inSelected ++ } ++ } ++ ++ states: [ ++ State { ++ name: "selected" ++ ParentChange { target: content; parent: selectionContainer; x: 3; y: 3 } ++ PropertyChanges { target: packageRoot; VisualDataModel.inItems: visibleContainer.drag.active } ++ PropertyChanges { target: gradientStart; color: "#017423" } ++ PropertyChanges { target: gradientStart; color: "#007423" } ++ }, State { ++ name: "visible" ++ PropertyChanges { target: packageRoot; VisualDataModel.inItems: true } ++ ParentChange { target: content; parent: visibleContainer; x: 3; y: 3 } ++ PropertyChanges { target: gradientStart; color: "#8AC953" } ++ PropertyChanges { target: gradientStart; color: "#8BC953" } ++ } ++ ] ++ transitions: Transition { ++ PropertyAction { target: packageRoot; properties: "VisualDataModel.inItems" } ++ ParentAnimation { ++ target: content ++ NumberAnimation { target: content; properties: "x,y"; duration: 500 } ++ } ++ ColorAnimation { targets: [gradientStart, gradientEnd]; duration: 500 } ++ } ++ } ++ } ++ } ++ ++ VisualDataModel { ++ id: visualModel ++ model: 35 ++ delegate: packageDelegate ++ ++ groups: VisualDataGroup { id: selectedItems; name: "selected" } ++ ++ Component.onCompleted: parts.selection.filterOnGroup = "selected" ++ } ++ ++ PathView { ++ id: selectionView ++ ++ height: 64 ++ width: 64 ++ ++ model: visualModel.parts.selection ++ ++ path: Path { ++ startX: 0 ++ startY: 0 ++ PathLine { x: 64; y: 64 } ++ } ++ } ++ ++ GridView { ++ id: itemsView ++ anchors { fill: parent } ++ cellWidth: 64 ++ cellHeight: 64 ++ model: visualModel.parts.visible ++ } ++} diff --cc examples/quick/modelviews/visualdatamodel/slideshow.qml index 0000000,0000000..040c6be new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/visualdatamodel/slideshow.qml @@@ -1,0 -1,0 +1,156 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++import QtQuick.XmlListModel 2.0 ++ ++Rectangle { ++ id: root ++ ++ property Item displayItem: null ++ ++ width: 300; height: 400 ++ ++ color: "black" ++ ++ VisualDataModel { ++ id: visualModel ++ ++ model: XmlListModel { ++ source: "http://api.flickr.com/services/feeds/photos_public.gne?format=rss2" ++ query: "/rss/channel/item" ++ namespaceDeclarations: "declare namespace media=\"http://search.yahoo.com/mrss/\";" ++ ++ XmlRole { name: "imagePath"; query: "media:thumbnail/@url/string()" } ++ XmlRole { name: "url"; query: "media:content/@url/string()" } ++ } ++ ++ delegate: Item { ++ id: delegateItem ++ ++ width: 76; height: 76 ++ ++ Rectangle { ++ id: image ++ x: 0; y: 0; width: 76; height: 76 ++ border.width: 1 ++ border.color: "white" ++ color: "black" ++ ++ Image { ++ anchors.fill: parent ++ anchors.leftMargin: 1 ++ anchors.topMargin: 1 ++ ++ source: imagePath ++ fillMode: Image.PreserveAspectFit ++ ++ } ++ ++ MouseArea { ++ id: clickArea ++ anchors.fill: parent ++ ++ onClicked: root.displayItem = root.displayItem !== delegateItem ? delegateItem : null ++ } ++ ++ states: [ ++ State { ++ when: root.displayItem === delegateItem ++ name: "inDisplay"; ++ ParentChange { target: image; parent: imageContainer; x: 75; y: 75; width: 150; height: 150 } ++ PropertyChanges { target: image; z: 2 } ++ PropertyChanges { target: delegateItem; VisualDataModel.inItems: false } ++ }, ++ State { ++ when: root.displayItem !== delegateItem ++ name: "inList"; ++ ParentChange { target: image; parent: delegateItem; x: 2; y: 2; width: 75; height: 75 } ++ PropertyChanges { target: image; z: 1 } ++ PropertyChanges { target: delegateItem; VisualDataModel.inItems: true } ++ } ++ ] ++ ++ transitions: [ ++ Transition { ++ from: "inList" ++ SequentialAnimation { ++ PropertyAction { target: delegateItem; property: "VisualDataModel.inPersistedItems"; value: true } ++ ParentAnimation { ++ target: image; ++ via: root ++ NumberAnimation { target: image; properties: "x,y,width,height"; duration: 1000 } ++ } ++ } ++ }, Transition { ++ from: "inDisplay" ++ SequentialAnimation { ++ ParentAnimation { ++ target: image ++ NumberAnimation { target: image; properties: "x,y,width,height"; duration: 1000 } ++ } ++ PropertyAction { target: delegateItem; property: "VisualDataModel.inPersistedItems"; value: false } ++ } ++ } ++ ] ++ } ++ } ++ } ++ ++ ++ PathView { ++ id: imagePath ++ ++ anchors { left: parent.left; top: imageContainer.bottom; right: parent.right; bottom: parent.bottom } ++ model: visualModel ++ ++ pathItemCount: 7 ++ path: Path { ++ startX: -50; startY: 0 ++ PathQuad { x: 150; y: 50; controlX: 0; controlY: 50 } ++ PathQuad { x: 350; y: 0; controlX: 300; controlY: 50 } ++ } ++ } ++ ++ Item { ++ id: imageContainer ++ anchors { fill: parent; bottomMargin: 100 } ++ } ++} diff --cc examples/quick/modelviews/visualdatamodel/sortedmodel.qml index 0000000,0000000..8d3b0a5 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/visualdatamodel/sortedmodel.qml @@@ -1,0 -1,0 +1,141 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Rectangle { ++ width: 480; height: 640 ++ ++ Component { ++ id: numberDelegate ++ ++ Text { ++ id: numberText ++ anchors { left: parent.left; right: parent.right } ++ text: number ++ ++ horizontalAlignment: Text.AlignHCenter ++ font.pixelSize: 18 ++ ++ Text { ++ anchors { left: parent.left; baseline: parent.baseline } ++ text: index ++ ++ horizontalAlignment: Text.AlignLeft ++ font.pixelSize: 12 ++ } ++ Text { ++ anchors { right: parent.right; baseline: parent.baseline } ++ text: numberText.VisualDataModel.itemsIndex ++ ++ horizontalAlignment: Text.AlignRight ++ font.pixelSize: 12 ++ } ++ } ++ } ++ ++ ListView { ++ anchors { ++ left: parent.left; top: parent.top; ++ right: parent.horizontalCenter; bottom: button.top ++ leftMargin: 2; topMargin: 2; rightMargin: 1; bottomMargin: 2 ++ } ++ ++ model: ListModel { ++ id: unsortedModel ++ } ++ delegate: numberDelegate ++ } ++ ListView { ++ anchors { ++ left: parent.horizontalCenter; top: parent.top; ++ right: parent.right; bottom: button.top ++ leftMargin: 1; topMargin: 2; rightMargin: 2; bottomMargin: 2 ++ } ++ model: VisualDataModel { ++ model: unsortedModel ++ delegate: numberDelegate ++ ++ items.onChanged: { ++ for (var i = 0; i < inserted.length; ++i) { ++ for (var j = inserted[i].index; j < inserted[i].index + inserted[i].count; ++j) { ++ var number = items.get(j).model.number ++ for (var l = 0, k = 0; l < unsortedModel.count; ++l) { ++ if (l == inserted[k].index) { ++ l += inserted[k].count - 1 ++ ++k ++ } else if (number < items.get(l).model.number) { ++ items.move(j, l, 1) ++ break ++ } ++ } ++ inserted[i].index += 1; ++ inserted[i].count -= 1; ++ } ++ } ++ } ++ } ++ } ++ ++ Rectangle { ++ id: button ++ ++ anchors { left: parent.left; right: parent.right; bottom: parent.bottom; margins: 2 } ++ height: moreText.implicitHeight + 4 ++ ++ color: "black" ++ ++ Text { ++ id: moreText ++ ++ anchors.fill: parent ++ text: "More" ++ color: "white" ++ font.pixelSize: 18 ++ horizontalAlignment: Text.AlignHCenter ++ verticalAlignment: Text.AlignVCenter ++ } ++ MouseArea { ++ anchors.fill: parent ++ ++ onClicked: unsortedModel.append({ "number": Math.floor(Math.random() * 100) }) ++ } ++ } ++} diff --cc examples/quick/modelviews/visualdatamodel/visualdatamodel.qmlproject index 0000000,0000000..2bb4016 new file mode 100644 --- /dev/null +++ b/examples/quick/modelviews/visualdatamodel/visualdatamodel.qmlproject @@@ -1,0 -1,0 +1,14 @@@ ++import QmlProject 1.0 ++ ++Project { ++ /* Include .qml, .js, and image files from current directory and subdirectories */ ++ QmlFiles { ++ directory: "." ++ } ++ JavaScriptFiles { ++ directory: "." ++ } ++ ImageFiles { ++ directory: "." ++ } ++} diff --cc examples/quick/modelviews/visualitemmodel/visualitemmodel.qml index 0000000,2e012ad..2e012ad mode 000000,100644..100644 --- a/examples/quick/modelviews/visualitemmodel/visualitemmodel.qml +++ b/examples/quick/modelviews/visualitemmodel/visualitemmodel.qml diff --cc examples/quick/mousearea/mousearea-example.qml index 0000000,0000000..30e3e62 new file mode 100644 --- /dev/null +++ b/examples/quick/mousearea/mousearea-example.qml @@@ -1,0 -1,0 +1,176 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Rectangle { ++ id: box ++ width: 400; height: 300 ++ ++ Rectangle { ++ id: redSquare ++ width: 120; height: 120 ++ anchors.top: parent.top; anchors.left: parent.left; anchors.margins: 10 ++ color: "red" ++ ++ Text { text: "Click"; font.pixelSize: 16; anchors.centerIn: parent } ++ ++ MouseArea { ++ anchors.fill: parent ++ hoverEnabled: true ++ property string buttonID ++ ++ acceptedButtons: Qt.AllButtons ++ // Value 'All.Buttons' is eqivalent to: ++ // 'Qt::LeftButton | Qt::RightButton | Qt::MiddleButton .... | Qt::ExtraButton24' ++ ++ onEntered: info.text = 'Entered' ++ onExited: info.text = 'Exited (pressed=' + pressed + ')' ++ ++ onPressed: { ++ if (mouse.button == Qt.LeftButton) ++ buttonID = 'LeftButton' ++ else if (mouse.button == Qt.RightButton) ++ buttonID = 'RightButton' ++ else if (mouse.button == Qt.MidButton) ++ buttonID = 'MiddleButton' ++ else if (mouse.button == Qt.BackButton) ++ buttonID = 'BackButton' ++ else if (mouse.button == Qt.ForwardButton) ++ buttonID = 'ForwardButton' ++ else if (mouse.button == Qt.TaskButton) ++ buttonID = 'TaskButton' ++ else if (mouse.button == Qt.ExtraButton4) ++ buttonID = 'ExtraButton4' ++ else if (mouse.button == Qt.ExtraButton5) ++ buttonID = 'ExtraButton5' ++ else if (mouse.button == Qt.ExtraButton6) ++ buttonID = 'ExtraButton6' ++ else if (mouse.button == Qt.ExtraButton7) ++ buttonID = 'ExtraButton7' ++ else if (mouse.button == Qt.ExtraButton8) ++ buttonID = 'ExtraButton8' ++ else if (mouse.button == Qt.ExtraButton9) ++ buttonID = 'ExtraButton9' ++ else if (mouse.button == Qt.ExtraButton10) ++ buttonID = 'ExtraButton10' ++ else if (mouse.button == Qt.ExtraButton11) ++ buttonID = 'ExtraButton11' ++ else if (mouse.button == Qt.ExtraButton12) ++ buttonID = 'ExtraButton12' ++ else if (mouse.button == Qt.ExtraButton13) ++ buttonID = 'ExtraButton13' ++ else if (mouse.button == Qt.ExtraButton14) ++ buttonID = 'ExtraButton14' ++ else if (mouse.button == Qt.ExtraButton15) ++ buttonID = 'ExtraButton15' ++ else if (mouse.button == Qt.ExtraButton16) ++ buttonID = 'ExtraButton16' ++ else if (mouse.button == Qt.ExtraButton17) ++ buttonID = 'ExtraButton17' ++ else if (mouse.button == Qt.ExtraButton18) ++ buttonID = 'ExtraButton18' ++ else if (mouse.button == Qt.ExtraButton19) ++ buttonID = 'ExtraButton19' ++ else if (mouse.button == Qt.ExtraButton20) ++ buttonID = 'ExtraButton20' ++ else if (mouse.button == Qt.ExtraButton21) ++ buttonID = 'ExtraButton21' ++ else if (mouse.button == Qt.ExtraButton22) ++ buttonID = 'ExtraButton22' ++ else if (mouse.button == Qt.ExtraButton23) ++ buttonID = 'ExtraButton23' ++ else if (mouse.button == Qt.ExtraButton24) ++ buttonID = 'ExtraButton24' ++ ++ info.text = 'Pressed (' + buttonID + ' shift=' ++ + (mouse.modifiers & Qt.ShiftModifier ? 'true' : 'false') + ')' ++ var posInBox = redSquare.mapToItem(box, mouse.x, mouse.y) ++ posInfo.text = + mouse.x + ',' + mouse.y + ' in square' ++ + ' (' + posInBox.x + ',' + posInBox.y + ' in window)' ++ } ++ ++ onReleased: { ++ btn.text = 'Released (isClick=' + mouse.isClick + ' wasHeld=' + mouse.wasHeld + ')' ++ posInfo.text = '' ++ } ++ ++ onPressAndHold: btn.text = 'Press and hold' ++ onClicked: btn.text = 'Clicked (wasHeld=' + mouse.wasHeld + ')' ++ onDoubleClicked: btn.text = 'Double clicked' ++ } ++ } ++ ++ Rectangle { ++ id: blueSquare ++ width: 120; height: 120 ++ x: box.width - width - 10; y: 10 // making this item draggable, so don't use anchors ++ color: "blue" ++ ++ Text { text: "Drag"; font.pixelSize: 16; color: "white"; anchors.centerIn: parent } ++ ++ MouseArea { ++ anchors.fill: parent ++ drag.target: blueSquare ++ drag.axis: Drag.XandYAxis ++ drag.minimumX: 0 ++ drag.maximumX: box.width - parent.width ++ drag.minimumY: 0 ++ drag.maximumY: box.height - parent.width ++ } ++ } ++ ++ Text { ++ id: info ++ anchors.bottom: btn.top; anchors.horizontalCenter: parent.horizontalCenter; anchors.margins: 20 ++ ++ onTextChanged: console.log(text) ++ } ++ ++ Text { ++ id: btn ++ anchors.bottom: posInfo.top; anchors.horizontalCenter: parent.horizontalCenter; anchors.margins: 20 ++ } ++ ++ Text { ++ id: posInfo ++ anchors.bottom: parent.bottom; anchors.horizontalCenter: parent.horizontalCenter; anchors.margins: 20 ++ } ++} diff --cc examples/quick/openglunderqml/main.cpp index 0000000,0000000..3b682de new file mode 100644 --- /dev/null +++ b/examples/quick/openglunderqml/main.cpp @@@ -1,0 -1,0 +1,60 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the demonstration applications of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL$ ++** GNU Lesser General Public License Usage ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** ++** ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++#include ++ ++#include ++ ++#include "squircle.h" ++ ++int main(int argc, char **argv) ++{ ++ QGuiApplication app(argc, argv); ++ ++ qmlRegisterType("QtQuick", 2, 0, "Squircle"); ++ ++ QQuickView view; ++ view.setSource(QUrl("main.qml")); ++ view.show(); ++ ++ return app.exec(); ++ ++} diff --cc examples/quick/openglunderqml/main.qml index 0000000,0000000..1485cbb new file mode 100644 --- /dev/null +++ b/examples/quick/openglunderqml/main.qml @@@ -1,0 -1,0 +1,78 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the demonstration applications of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL$ ++** GNU Lesser General Public License Usage ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** ++** ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Item { ++ ++ width: 400 ++ height: 300 ++ ++ Squircle { ++ SequentialAnimation on t { ++ NumberAnimation { to: 1; duration: 2500; easing.type: Easing.InQuad } ++ NumberAnimation { to: 0; duration: 2500; easing.type: Easing.OutQuad } ++ loops: Animation.Infinite ++ running: true ++ } ++ } ++ ++ Rectangle { ++ color: Qt.rgba(1, 1, 1, 0.8); ++ radius: 10 ++ border.width: 1 ++ border.color: "white" ++ anchors.fill: label ++ anchors.margins: -10 ++ } ++ ++ Text { ++ id: label ++ color: "black" ++ wrapMode: Text.WordWrap ++ text: "The background here is a squircle rendered with raw OpenGL using the 'beforeRender()' signal in QQuickCanvas. This text label and its border is rendered using QML" ++ anchors.right: parent.right ++ anchors.left: parent.left ++ anchors.bottom: parent.bottom ++ anchors.margins: 20 ++ } ++ ++} diff --cc examples/quick/openglunderqml/openglunderqml.pro index 0000000,0000000..64a58b3 new file mode 100644 --- /dev/null +++ b/examples/quick/openglunderqml/openglunderqml.pro @@@ -1,0 -1,0 +1,6 @@@ ++QT += qml quick ++ ++HEADERS += squircle.h ++SOURCES += squircle.cpp main.cpp ++ ++OTHER_FILES += main.qml diff --cc examples/quick/openglunderqml/squircle.cpp index 0000000,0000000..b56f0ba new file mode 100644 --- /dev/null +++ b/examples/quick/openglunderqml/squircle.cpp @@@ -1,0 -1,0 +1,123 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the demonstration applications of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL$ ++** GNU Lesser General Public License Usage ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** ++** ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++#include "squircle.h" ++ ++#include ++#include ++#include ++ ++Squircle::Squircle() ++ : m_program(0) ++{ ++ setFlag(ItemHasContents); ++} ++ ++void Squircle::itemChange(ItemChange change, const ItemChangeData &) ++{ ++ // The ItemSceneChange event is sent when we are first attached to a canvas. ++ if (change == ItemSceneChange) { ++ QQuickCanvas *c = canvas(); ++ ++ // Connect our the beforeRendering signal to our paint function. ++ // Since this call is executed on the rendering thread it must be ++ // a Qt::DirectConnection ++ connect(c, SIGNAL(beforeRendering()), this, SLOT(paint()), Qt::DirectConnection); ++ ++ // If we allow QML to do the clearing, they would clear what we paint ++ // and nothing would show. ++ c->setClearBeforeRendering(false); ++ } ++} ++ ++ ++void Squircle::paint() ++{ ++ if (!m_program) { ++ m_program = new QOpenGLShaderProgram(); ++ m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, ++ "attribute highp vec4 vertices;" ++ "varying highp vec2 coords;" ++ "void main() {" ++ " gl_Position = vertices;" ++ " coords = vertices.xy;" ++ "}"); ++ m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, ++ "uniform lowp float t;" ++ "varying highp vec2 coords;" ++ "void main() {" ++ " lowp float i = 1. - (pow(coords.x, 4.) + pow(coords.y, 4.));" ++ " i = smoothstep(t - 0.3, t + 0.3, i);" ++ " gl_FragColor = vec4(coords / 2. + .5, i, i);" ++ "}"); ++ ++ m_program->bindAttributeLocation("vertices", 0); ++ m_program->link(); ++ } ++ ++ m_program->bind(); ++ ++ m_program->enableAttributeArray(0); ++ ++ float values[] = { ++ -1, -1, ++ 1, -1, ++ -1, 1, ++ 1, 1 ++ }; ++ m_program->setAttributeArray(0, GL_FLOAT, values, 2); ++ m_program->setUniformValue("t", (float) m_t); ++ ++ glDisable(GL_DEPTH_TEST); ++ ++ glClearColor(0, 0, 0, 1); ++ glClear(GL_COLOR_BUFFER_BIT); ++ ++ glEnable(GL_BLEND); ++ glBlendFunc(GL_SRC_ALPHA, GL_ONE); ++ ++ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); ++ ++ m_program->disableAttributeArray(0); ++ m_program->release(); ++} ++ ++ diff --cc examples/quick/openglunderqml/squircle.h index 0000000,0000000..283131a new file mode 100644 --- /dev/null +++ b/examples/quick/openglunderqml/squircle.h @@@ -1,0 -1,0 +1,76 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the demonstration applications of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL$ ++** GNU Lesser General Public License Usage ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** ++** ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++#ifndef SQUIRCLE_H ++#define SQUIRCLE_H ++ ++#include ++#include ++ ++class Squircle : public QQuickItem ++{ ++ Q_OBJECT ++ ++ Q_PROPERTY(qreal t READ t WRITE setT NOTIFY tChanged) ++ ++public: ++ Squircle(); ++ ++ qreal t() const { return m_t; } ++ void setT(qreal t) { m_t = t; emit tChanged(); } ++ ++ void itemChange(ItemChange change, const ItemChangeData &); ++ ++signals: ++ void tChanged(); ++ ++public slots: ++ void paint(); ++ ++private: ++ QOpenGLShaderProgram *m_program; ++ ++ qreal m_t; ++ bool m_render_under; ++ bool m_render_over; ++}; ++ ++#endif // SQUIRCLE_H diff --cc examples/quick/painteditem/painteditem.pro index 0000000,0000000..e3afd6b new file mode 100644 --- /dev/null +++ b/examples/quick/painteditem/painteditem.pro @@@ -1,0 -1,0 +1,5 @@@ ++TEMPLATE = subdirs ++ ++SUBDIRS = \ ++ smile \ ++ textballoons diff --cc examples/quick/painteditem/smile/main.cpp index 0000000,0000000..1c7888b new file mode 100644 --- /dev/null +++ b/examples/quick/painteditem/smile/main.cpp @@@ -1,0 -1,0 +1,96 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++class MyPaintItem : public QQuickPaintedItem ++{ ++ Q_OBJECT ++ Q_PROPERTY(QString face READ face WRITE setFace NOTIFY faceChanged) ++public: ++ MyPaintItem() ++ : QQuickPaintedItem() ++ , m_face(QLatin1String(":-)")) ++ { ++ setAntialiasing(true); ++ } ++ QString face() const {return m_face;} ++ void setFace(const QString &face) { ++ if (m_face != face) { ++ m_face = face; ++ emit faceChanged(); ++ } ++ } ++ virtual void paint(QPainter *p) ++ { ++ QRectF rect(0, 0, width(), height()); ++ rect.adjust(10, 10, -10, -10); ++ p->setPen(QPen(Qt::black, 20)); ++ p->setBrush(Qt::yellow); ++ p->drawEllipse(rect); ++ p->setPen(Qt::black); ++ p->setFont(QFont(QLatin1String("Times"), qRound(rect.height() / 2))); ++ p->drawText(rect, Qt::AlignCenter, m_face); ++ } ++signals: ++ void faceChanged(); ++private: ++ QString m_face; ++}; ++ ++int main(int argc, char ** argv) ++{ ++ QGuiApplication app(argc, argv); ++ ++ qmlRegisterType("MyModule", 1, 0, "MyPaintItem"); ++ ++ QQuickView view; ++ view.setResizeMode(QQuickView::SizeRootObjectToView); ++ view.setSource(QUrl::fromLocalFile("smile.qml")); ++ view.show(); ++ view.raise(); ++ ++ return app.exec(); ++} ++ ++#include "main.moc" diff --cc examples/quick/painteditem/smile/smile.pro index 0000000,0000000..b1af4ee new file mode 100644 --- /dev/null +++ b/examples/quick/painteditem/smile/smile.pro @@@ -1,0 -1,0 +1,11 @@@ ++TEMPLATE = app ++TARGET = painteditem ++ ++QT += qml quick ++ ++macx: CONFIG -= app_bundle ++ ++SOURCES += main.cpp ++ ++CONFIG += console ++ diff --cc examples/quick/painteditem/smile/smile.qml index 0000000,0000000..33919bc new file mode 100644 --- /dev/null +++ b/examples/quick/painteditem/smile/smile.qml @@@ -1,0 -1,0 +1,132 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++import MyModule 1.0 ++ ++Rectangle { ++ width: 500 ++ height: 500 ++ gradient: Gradient { ++ GradientStop { position: 0.0; color: "#00249a" } ++ GradientStop { position: 0.7; color: "#ffd94f" } ++ GradientStop { position: 1.0; color: "#ffa322" } ++ } ++ MyPaintItem { ++ renderTarget:PaintedItem.Image ++ clip:true ++ width:240 ++ height:240 ++ anchors.left : parent.left ++ anchors.top :parent.top ++ anchors.margins: 10 ++ smooth: true ++ MouseArea { ++ anchors.fill:parent ++ onClicked: { ++ if (parent.face == ":-)") ++ parent.face = ":-("; ++ else ++ parent.face = ":-)"; ++ parent.update() ++ } ++ } ++ } ++ MyPaintItem { ++ clip:true ++ renderTarget:PaintedItem.Image ++ width:240 ++ height:240 ++ anchors.right : parent.right ++ anchors.top :parent.top ++ anchors.margins: 10 ++ smooth: true ++ MouseArea { ++ anchors.fill:parent ++ onClicked: { ++ if (parent.face == ":-)") ++ parent.face = ":-("; ++ else ++ parent.face = ":-)"; ++ parent.update() ++ } ++ } ++ } ++ MyPaintItem { ++ clip:true ++ renderTarget:PaintedItem.Image ++ width:240 ++ height:240 ++ anchors.left : parent.left ++ anchors.bottom :parent.bottom ++ anchors.margins: 10 ++ smooth: true ++ MouseArea { ++ anchors.fill:parent ++ onClicked: { ++ if (parent.face == ":-)") ++ parent.face = ":-("; ++ else ++ parent.face = ":-)"; ++ parent.update() ++ } ++ } ++ } ++ MyPaintItem { ++ clip:true ++ renderTarget:PaintedItem.Image ++ width:240 ++ height:240 ++ anchors.right : parent.right ++ anchors.bottom :parent.bottom ++ anchors.margins: 10 ++ smooth: true ++ MouseArea { ++ anchors.fill:parent ++ onClicked: { ++ if (parent.face == ":-)") ++ parent.face = ":-("; ++ else ++ parent.face = ":-)"; ++ parent.update() ++ } ++ } ++ } ++} diff --cc examples/quick/painteditem/textballoons/TextBalloonPlugin/plugin.h index 0000000,0000000..c500c1c new file mode 100644 --- /dev/null +++ b/examples/quick/painteditem/textballoons/TextBalloonPlugin/plugin.h @@@ -1,0 -1,0 +1,55 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the demonstration applications of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL$ ++** GNU Lesser General Public License Usage ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** ++** ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++#include ++ ++#include "../textballoon.h" ++ ++class TextBalloonPlugin : public QQmlExtensionPlugin ++{ ++ Q_OBJECT ++ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "textballoon.json") ++public: ++ void registerTypes(const char *uri) ++ { ++ qmlRegisterType(uri, 1, 0, "TextBalloon"); ++ } ++}; diff --cc examples/quick/painteditem/textballoons/TextBalloonPlugin/qmldir index 0000000,0000000..e8a08ae new file mode 100644 --- /dev/null +++ b/examples/quick/painteditem/textballoons/TextBalloonPlugin/qmldir @@@ -1,0 -1,0 +1,1 @@@ ++plugin qmltextballoonplugin diff --cc examples/quick/painteditem/textballoons/textballoon.cpp index 0000000,0000000..d097adf new file mode 100644 --- /dev/null +++ b/examples/quick/painteditem/textballoons/textballoon.cpp @@@ -1,0 -1,0 +1,92 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the demonstration applications of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL$ ++** GNU Lesser General Public License Usage ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** ++** ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++#include "textballoon.h" ++ ++//! [0] ++TextBalloon::TextBalloon(QQuickItem *parent) ++ : QQuickPaintedItem(parent) ++ , rightAligned(false) ++{ ++} ++//! [0] ++ ++//! [1] ++void TextBalloon::paint(QPainter *painter) ++{ ++ QBrush brush(QColor("#007430")); ++ ++ painter->setBrush(brush); ++ painter->setPen(Qt::NoPen); ++ painter->setRenderHint(QPainter::Antialiasing); ++ ++ painter->drawRoundedRect(0, 0, boundingRect().width(), boundingRect().height() - 10, 10, 10); ++ ++ if (rightAligned) ++ { ++ const QPointF points[3] = { ++ QPointF(boundingRect().width() - 10.0, boundingRect().height() - 10.0), ++ QPointF(boundingRect().width() - 20.0, boundingRect().height()), ++ QPointF(boundingRect().width() - 30.0, boundingRect().height() - 10.0), ++ }; ++ painter->drawConvexPolygon(points, 3); ++ } ++ else ++ { ++ const QPointF points[3] = { ++ QPointF(10.0, boundingRect().height() - 10.0), ++ QPointF(20.0, boundingRect().height()), ++ QPointF(30.0, boundingRect().height() - 10.0), ++ }; ++ painter->drawConvexPolygon(points, 3); ++ } ++} ++//! [1] ++ ++bool TextBalloon::isRightAligned() ++{ ++ return this->rightAligned; ++} ++ ++void TextBalloon::setRightAligned(bool rightAligned) ++{ ++ this->rightAligned = rightAligned; ++} diff --cc examples/quick/painteditem/textballoons/textballoon.h index 0000000,0000000..93ed0a7 new file mode 100644 --- /dev/null +++ b/examples/quick/painteditem/textballoons/textballoon.h @@@ -1,0 -1,0 +1,68 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the demonstration applications of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL$ ++** GNU Lesser General Public License Usage ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** ++** ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++#ifndef TEXTBALLOON_H ++#define TEXTBALLOON_H ++ ++#include ++ ++//! [0] ++class TextBalloon : public QQuickPaintedItem ++{ ++ Q_OBJECT ++ Q_PROPERTY(bool rightAligned READ isRightAligned WRITE setRightAligned NOTIFY rightAlignedChanged) ++ ++ public: ++ TextBalloon(QQuickItem *parent = 0); ++ void paint(QPainter *painter); ++ ++ bool isRightAligned(); ++ void setRightAligned(bool rightAligned); ++ ++ private: ++ bool rightAligned; ++ ++ signals: ++ void rightAlignedChanged(); ++}; ++//! [0] ++ ++#endif diff --cc examples/quick/painteditem/textballoons/textballoon.json index 0000000,0967ef4..0967ef4 mode 000000,100644..100644 --- a/examples/quick/painteditem/textballoons/textballoon.json +++ b/examples/quick/painteditem/textballoons/textballoon.json diff --cc examples/quick/painteditem/textballoons/textballoons.pro index 0000000,0000000..d612048 new file mode 100644 --- /dev/null +++ b/examples/quick/painteditem/textballoons/textballoons.pro @@@ -1,0 -1,0 +1,25 @@@ ++TEMPLATE = lib ++CONFIG += qt plugin ++QT += qml quick ++ ++TARGET = qmltextballoonplugin ++ ++HEADERS += TextBalloonPlugin/plugin.h \ ++ textballoon.h ++ ++SOURCES += textballoon.cpp ++ ++OTHER_FILES += textballoon.json ++ ++DESTDIR = TextBalloonPlugin ++ ++qdeclarativesources.files += \ ++ TextBalloonPlugin/qmldir ++ ++qdeclarativesources.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/painteditem/textballoons/TextBalloonPlugin ++ ++sources.files = textballoons.qml ++sources.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/painteditem/textballoons ++target.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/painteditem/textballoons/TextBalloonPlugin ++ ++INSTALLS = qdeclarativesources sources target diff --cc examples/quick/painteditem/textballoons/textballoons.qml index 0000000,0000000..b00ce2b new file mode 100644 --- /dev/null +++ b/examples/quick/painteditem/textballoons/textballoons.qml @@@ -1,0 -1,0 +1,110 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the demonstration applications of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL$ ++** GNU Lesser General Public License Usage ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** ++** ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++import TextBalloonPlugin 1.0 ++ ++Item { ++ height: 480 ++ width: 640 ++ ++ //! [0] ++ ListModel { ++ id: balloonModel ++ ListElement { ++ balloonWidth: 200 ++ } ++ ListElement { ++ balloonWidth: 350 ++ } ++ } ++ ++ ListView { ++ anchors.bottom: controls.top ++ anchors.bottomMargin: 2 ++ anchors.top: parent.top ++ id: balloonView ++ delegate: TextBalloon { ++ anchors.right: index % 2 == 0 ? undefined : parent.right ++ height: 60 ++ rightAligned: index % 2 == 0 ? false : true ++ width: balloonWidth ++ } ++ model: balloonModel ++ spacing: 5 ++ width: parent.width ++ } ++ //! [0] ++ ++ //! [1] ++ Rectangle { ++ id: controls ++ ++ anchors.bottom: parent.bottom ++ anchors.left: parent.left ++ anchors.margins: 1 ++ anchors.right: parent.right ++ border.width: 2 ++ color: "white" ++ height: parent.height * 0.15 ++ ++ Text { ++ anchors.centerIn: parent ++ text: "Add another balloon" ++ } ++ ++ MouseArea { ++ anchors.fill: parent ++ hoverEnabled: true ++ onClicked: { ++ balloonModel.append({"balloonWidth": Math.floor(Math.random() * 300 + 100)}) ++ balloonView.positionViewAtIndex(balloonView.count -1, ListView.End) ++ } ++ onEntered: { ++ parent.color = "#8ac953" ++ } ++ onExited: { ++ parent.color = "white" ++ } ++ } ++ } ++ //! [1] ++} diff --cc examples/quick/positioners/content/Button.qml index 0000000,0000000..ee3aa90 new file mode 100644 --- /dev/null +++ b/examples/quick/positioners/content/Button.qml @@@ -1,0 -1,0 +1,78 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Rectangle { ++ id: page ++ ++ property string text ++ property string icon ++ signal clicked ++ ++ border.color: "black"; color: "steelblue"; radius: 5 ++ width: pix.width + textelement.width + 13 ++ height: pix.height + 10 ++ ++ Image { id: pix; x: 5; y:5; source: parent.icon } ++ ++ Text { ++ id: textelement ++ text: page.text; color: "white" ++ x: pix.width + pix.x + 3 ++ anchors.verticalCenter: pix.verticalCenter ++ } ++ ++ MouseArea { ++ id: mr ++ anchors.fill: parent ++ onClicked: { parent.focus = true; page.clicked() } ++ } ++ ++ states: State { ++ name: "pressed"; when: mr.pressed ++ PropertyChanges { target: textelement; x: 5 } ++ PropertyChanges { target: pix; x: textelement.x + textelement.width + 3 } ++ } ++ ++ transitions: Transition { ++ NumberAnimation { properties: "x,left"; easing.type: Easing.InOutQuad; duration: 200 } ++ } ++} diff --cc examples/quick/positioners/content/add.png index 0000000,0000000..1ee4542 new file mode 100644 Binary files differ diff --cc examples/quick/positioners/content/del.png index 0000000,0000000..8d2eaed new file mode 100644 Binary files differ diff --cc examples/quick/positioners/positioners-attachedproperties.qml index 0000000,0000000..a05927f new file mode 100644 --- /dev/null +++ b/examples/quick/positioners/positioners-attachedproperties.qml @@@ -1,0 -1,0 +1,106 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Rectangle { ++ width: 400 ++ height: 100 ++ ++ // Create row with four rectangles, the fourth one is hidden ++ Row { ++ id: row ++ ++ Rectangle { ++ id: red ++ color: "red" ++ width: 100 ++ height: 100 ++ ++ // When mouse is clicked, display the values of the positioner ++ MouseArea { ++ anchors.fill: parent ++ onClicked: row.showInfo(red.Positioner) ++ } ++ } ++ ++ Rectangle { ++ id: green ++ color: "green" ++ width: 100 ++ height: 100 ++ ++ // When mouse is clicked, display the values of the positioner ++ MouseArea { ++ anchors.fill: parent ++ onClicked: row.showInfo(green.Positioner) ++ } ++ } ++ ++ Rectangle { ++ id: blue ++ color: "blue" ++ width: 100 ++ height: 100 ++ ++ // When mouse is clicked, display the values of the positioner ++ MouseArea { ++ anchors.fill: parent ++ onClicked: row.showInfo(blue.Positioner) ++ } ++ } ++ ++ // This rectangle is not visible, so it doesn't have a positioner value ++ Rectangle { ++ color: "black" ++ width: 100 ++ height: 100 ++ visible: false ++ } ++ ++ // Print the index of the child item in the positioner and convenience ++ // properties showing if it's the first or last item. ++ function showInfo(positioner) { ++ console.log("Item Index = " + positioner.index) ++ console.log(" isFirstItem = " + positioner.isFirstItem) ++ console.log(" isLastItem = " + positioner.isLastItem) ++ } ++ } ++} diff --cc examples/quick/positioners/positioners.qml index 0000000,6627ad7..6627ad7 mode 000000,100644..100644 --- a/examples/quick/positioners/positioners.qml +++ b/examples/quick/positioners/positioners.qml diff --cc examples/quick/quick.pro index 0000000,529f65a..529f65a mode 000000,100644..100644 --- a/examples/quick/quick.pro +++ b/examples/quick/quick.pro diff --cc examples/quick/righttoleft/layoutdirection/layoutdirection.qml index 0000000,0000000..0c65647 new file mode 100644 --- /dev/null +++ b/examples/quick/righttoleft/layoutdirection/layoutdirection.qml @@@ -1,0 -1,0 +1,246 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Rectangle { ++ id: root ++ property bool mirror ++ property int direction: Qt.application.layoutDirection ++ LayoutMirroring.enabled: mirror ++ LayoutMirroring.childrenInherit: true ++ width: column.width + 80 ++ height: column.height + 40 ++ Column { ++ id: column ++ width: 190 ++ spacing: 10 ++ anchors.centerIn: parent ++ ++ Text { ++ text: "Row" ++ anchors.horizontalCenter: parent.horizontalCenter ++ } ++ ++ Row { ++ layoutDirection: root.direction ++ spacing: 10 ++ move: Transition { ++ NumberAnimation { ++ properties: "x" ++ } ++ } ++ Repeater { ++ model: 4 ++ Loader { ++ property int value: index ++ sourceComponent: positionerDelegate ++ } ++ } ++ } ++ ++ Text { ++ text: "Grid" ++ anchors.horizontalCenter: parent.horizontalCenter ++ } ++ ++ Grid { ++ layoutDirection: root.direction ++ spacing: 10; columns: 4 ++ move: Transition { ++ NumberAnimation { ++ properties: "x" ++ } ++ } ++ Repeater { ++ model: 11 ++ Loader { ++ property int value: index ++ sourceComponent: positionerDelegate ++ } ++ } ++ } ++ ++ Text { ++ text: "Flow" ++ anchors.horizontalCenter: parent.horizontalCenter ++ } ++ ++ Flow { ++ layoutDirection: root.direction ++ spacing: 10; width: parent.width ++ move: Transition { ++ NumberAnimation { ++ properties: "x" ++ } ++ } ++ Repeater { ++ model: 10 ++ Loader { ++ property int value: index ++ sourceComponent: positionerDelegate ++ } ++ } ++ } ++ ++ Text { ++ text: "ListView" ++ anchors.horizontalCenter: parent.horizontalCenter ++ } ++ ++ ListView { ++ id: listView ++ clip: true ++ width: parent.width; height: 40 ++ layoutDirection: root.direction ++ orientation: Qt.Horizontal ++ model: 48 ++ delegate: viewDelegate ++ } ++ ++ Text { ++ text: "GridView" ++ anchors.horizontalCenter: parent.horizontalCenter ++ } ++ ++ GridView { ++ clip: true ++ width: 200; height: 160 ++ cellWidth: 50; cellHeight: 50 ++ layoutDirection: root.direction ++ model: 48 ++ delegate: viewDelegate ++ } ++ ++ Rectangle { ++ height: 50; width: parent.width ++ color: mouseArea.pressed ? "black" : "gray" ++ Column { ++ anchors.centerIn: parent ++ Text { ++ text: root.direction ? "Right to left" : "Left to right" ++ color: "white" ++ font.pixelSize: 16 ++ anchors.horizontalCenter: parent.horizontalCenter ++ } ++ Text { ++ text: "(click here to toggle)" ++ color: "white" ++ font.pixelSize: 10 ++ font.italic: true ++ anchors.horizontalCenter: parent.horizontalCenter ++ } ++ } ++ MouseArea { ++ id: mouseArea ++ anchors.fill: parent ++ onClicked: { ++ if (root.direction == Qt.LeftToRight) { ++ root.direction = Qt.RightToLeft; ++ } else { ++ root.direction = Qt.LeftToRight; ++ } ++ } ++ } ++ } ++ ++ Rectangle { ++ height: 50; width: parent.width ++ color: mouseArea2.pressed ? "black" : "gray" ++ Column { ++ anchors.centerIn: parent ++ Text { ++ text: root.mirror ? "Mirrored" : "Not mirrored" ++ color: "white" ++ font.pixelSize: 16 ++ anchors.horizontalCenter: parent.horizontalCenter ++ } ++ Text { ++ text: "(click here to toggle)" ++ color: "white" ++ font.pixelSize: 10 ++ font.italic: true ++ anchors.horizontalCenter: parent.horizontalCenter ++ } ++ } ++ MouseArea { ++ id: mouseArea2 ++ anchors.fill: parent ++ onClicked: { ++ root.mirror = !root.mirror; ++ } ++ } ++ } ++ } ++ ++ Component { ++ id: positionerDelegate ++ Rectangle { ++ width: 40; height: 40 ++ color: Qt.rgba(0.8/(parent.value+1),0.8/(parent.value+1),0.8/(parent.value+1),1.0) ++ Text { ++ text: parent.parent.value+1 ++ color: "white" ++ font.pixelSize: 18 ++ anchors.centerIn: parent ++ } ++ } ++ } ++ Component { ++ id: viewDelegate ++ Item { ++ width: (listView.effectiveLayoutDirection == Qt.LeftToRight ? (index == 48 - 1) : (index == 0)) ? 40 : 50 ++ Rectangle { ++ width: 40; height: 40 ++ color: Qt.rgba(0.5+(48 - index)*Math.random()/48, ++ 0.3+index*Math.random()/48, ++ 0.3*Math.random(), ++ 1.0) ++ Text { ++ text: index+1 ++ color: "white" ++ font.pixelSize: 18 ++ anchors.centerIn: parent ++ } ++ } ++ } ++ } ++} ++ diff --cc examples/quick/righttoleft/layoutdirection/layoutdirection.qmlproject index 0000000,0000000..33cbb3c new file mode 100644 --- /dev/null +++ b/examples/quick/righttoleft/layoutdirection/layoutdirection.qmlproject @@@ -1,0 -1,0 +1,16 @@@ ++import QmlProject 1.1 ++ ++Project { ++ mainFile: "layoutdirection.qml" ++ ++ /* Include .qml, .js, and image files from current directory and subdirectories */ ++ QmlFiles { ++ directory: "." ++ } ++ JavaScriptFiles { ++ directory: "." ++ } ++ ImageFiles { ++ directory: "." ++ } ++} diff --cc examples/quick/righttoleft/layoutmirroring/layoutmirroring.qml index 0000000,0000000..5c4739b new file mode 100644 --- /dev/null +++ b/examples/quick/righttoleft/layoutmirroring/layoutmirroring.qml @@@ -1,0 -1,0 +1,313 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Rectangle { ++ id: root ++ property bool mirror: Qt.application.layoutDirection == Qt.RightToLeft ++ LayoutMirroring.enabled: mirror ++ LayoutMirroring.childrenInherit: true ++ width: 400 ++ height: 875 ++ color: "lightsteelblue" ++ ++ Column { ++ spacing: 10 ++ anchors { left: parent.left; right: parent.right; top: parent.top; margins: 10 } ++ ++ Text { ++ text: "Positioners" ++ anchors.left: parent.left ++ } ++ ++ Column { ++ id: positioners ++ spacing: 5 ++ anchors.left: parent.left ++ Row { ++ id: row ++ spacing: 4 ++ property string text: "THISISROW" ++ anchors.left: parent.left ++ Repeater { ++ model: parent.text.length ++ delegate: positionerDelegate ++ } ++ } ++ Flow { ++ id: flow ++ spacing: 4 ++ width: 90 ++ property string text: "THISISFLOW" ++ anchors.left: parent.left ++ Repeater { ++ model: parent.text.length ++ delegate: positionerDelegate ++ } ++ } ++ Grid { ++ id: grid ++ spacing: 4 ++ columns: 6 ++ property string text: "THISISGRID" ++ anchors.left: parent.left ++ Repeater { ++ model: parent.text.length ++ delegate: positionerDelegate ++ } ++ } ++ Component { ++ id: positionerDelegate ++ Text { ++ color: "white" ++ font.pixelSize: 20 ++ text: parent.text[index] ++ Rectangle { ++ z: -1 ++ opacity: 0.7 ++ color: "black" ++ anchors.fill: parent ++ } ++ } ++ } ++ } ++ ++ Text { ++ text: "Text alignment" ++ anchors.left: parent.left ++ } ++ ++ Rectangle { ++ id: textStrings ++ width: 148 ++ height: 85 ++ color: "white" ++ anchors.left: parent.left ++ Column { ++ spacing: 5 ++ width: parent.width ++ anchors { fill: parent; margins: 5 } ++ Text { ++ id: englishText ++ width: parent.width ++ text: "English text" ++ } ++ Text { ++ id: arabicText ++ width: parent.width ++ text: "النص العربي" ++ } ++ Text { ++ id: leftAlignedText ++ width: parent.width ++ text: "Text aligned to left" ++ horizontalAlignment: Text.AlignLeft ++ } ++ Text { ++ id: rightAlignedText ++ width: parent.width ++ text: "Text aligned to right" ++ horizontalAlignment: Text.AlignRight ++ } ++ } ++ } ++ ++ Text { ++ text: "Model views" ++ anchors.left: parent.left ++ } ++ ++ Column { ++ id: views ++ spacing: 10 ++ anchors.left: parent.left ++ ListView { ++ id: listView ++ z: -1 ++ clip: true ++ model: text.length ++ width: 360; height: 45 ++ orientation: Qt.Horizontal ++ property string text: "LISTVIEWLISTVIEWLISTVIEWLISTVIEWLISTVIEWLISTVIEW" ++ delegate: Rectangle { ++ color: "black" ++ width: 45; height: 45 ++ Rectangle { ++ anchors { fill: parent; margins: 1 } ++ color: "red" ++ } ++ Text { ++ text: listView.text[index] ++ font.pixelSize: 30 ++ anchors.centerIn: parent ++ } ++ } ++ } ++ GridView { ++ id: gridView ++ z: -1 ++ clip: true ++ model: text.length ++ width: 180; height: 90 ++ cellWidth: 45; cellHeight: 45 ++ property string text: "GRIDVIEWGRIDVIEWGRIDVIEWGRIDVIEWGRIDVIEWGRIDVIEW" ++ anchors.left: parent.left ++ delegate: Rectangle { ++ color: "black" ++ width: 45; height: 45 ++ Rectangle { ++ anchors { fill: parent; margins: 1 } ++ color: "red" ++ } ++ Text { ++ anchors.centerIn: parent ++ font.pixelSize: 30 ++ text: gridView.text[index] ++ } ++ } ++ } ++ } ++ ++ Text { ++ text: "Item x" ++ anchors.left: parent.left ++ } ++ Rectangle { ++ id: items ++ color: Qt.rgba(0.2, 0.2, 0.2, 0.6) ++ width: 275; height: 95 ++ anchors.left: parent.left ++ Rectangle { ++ y: 5; x: 5 ++ width: 130; height: 40 ++ Text { ++ text: "Item with x: 5\n(not mirrored)" ++ anchors.centerIn: parent ++ } ++ } ++ Rectangle { ++ color: Qt.rgba(0.7, 0.7, 0.7) ++ y: 50; x: mirror(5) ++ width: 130; height: 40 ++ function mirror(value) { ++ return LayoutMirroring.enabled ? (parent.width - width - value) : value; ++ } ++ Text { ++ text: "Item with x: " + parent.x + "\n(manually mirrored)" ++ anchors.centerIn: parent ++ } ++ } ++ } ++ Text { ++ text: "Item anchors" ++ anchors.left: parent.left ++ } ++ ++ Rectangle { ++ id: anchoredItems ++ color: Qt.rgba(0.2, 0.2, 0.2, 0.6) ++ width: 270; height: 170 ++ anchors.left: parent.left ++ Rectangle { ++ id: blackRectangle ++ color: "black" ++ width: 180; height: 90 ++ anchors { horizontalCenter: parent.horizontalCenter; horizontalCenterOffset: 30 } ++ Text { ++ text: "Horizontal center anchored\nwith offset 30\nto the horizontal center\nof the parent." ++ color: "white" ++ anchors.centerIn: parent ++ } ++ } ++ Rectangle { ++ id: whiteRectangle ++ color: "white" ++ width: 120; height: 70 ++ anchors { left: parent.left; bottom: parent.bottom } ++ Text { ++ text: "Left side anchored\nto the left side\nof the parent." ++ color: "black" ++ anchors.centerIn: parent ++ } ++ } ++ Rectangle { ++ id: grayRectangle ++ color: Qt.rgba(0.7, 0.7, 0.7) ++ width: 140; height: 90 ++ anchors { right: parent.right; bottom: parent.bottom } ++ Text { ++ text: "Right side anchored\nto the right side\nof the parent." ++ anchors.centerIn: parent ++ } ++ } ++ } ++ Rectangle { ++ id: mirrorButton ++ color: mouseArea2.pressed ? "black" : "gray" ++ height: 50; width: parent.width ++ anchors.left: parent.left ++ Column { ++ anchors.centerIn: parent ++ Text { ++ text: root.mirror ? "Mirrored" : "Not mirrored" ++ color: "white" ++ font.pixelSize: 16 ++ anchors.horizontalCenter: parent.horizontalCenter ++ } ++ Text { ++ text: "(click here to toggle)" ++ color: "white" ++ font.pixelSize: 10 ++ font.italic: true ++ anchors.horizontalCenter: parent.horizontalCenter ++ } ++ } ++ MouseArea { ++ id: mouseArea2 ++ anchors.fill: parent ++ onClicked: { ++ root.mirror = !root.mirror; ++ } ++ } ++ } ++ } ++} ++ diff --cc examples/quick/righttoleft/layoutmirroring/layoutmirroring.qmlproject index 0000000,0000000..72bc04a new file mode 100644 --- /dev/null +++ b/examples/quick/righttoleft/layoutmirroring/layoutmirroring.qmlproject @@@ -1,0 -1,0 +1,16 @@@ ++import QmlProject 1.1 ++ ++Project { ++ mainFile: "layoutmirroring.qml" ++ ++ /* Include .qml, .js, and image files from current directory and subdirectories */ ++ QmlFiles { ++ directory: "." ++ } ++ JavaScriptFiles { ++ directory: "." ++ } ++ ImageFiles { ++ directory: "." ++ } ++} diff --cc examples/quick/righttoleft/textalignment/textalignment.qml index 0000000,0000000..ef5b97b new file mode 100644 --- /dev/null +++ b/examples/quick/righttoleft/textalignment/textalignment.qml @@@ -1,0 -1,0 +1,427 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Rectangle { ++ id: root ++ color: "white" ++ width: containerColumn.width ++ height: containerColumn.height + containerColumn.anchors.topMargin ++ ++ property bool mirror: false ++ property variant horizontalAlignment: undefined ++ ++ property variant editorType: ["Plain Text", "Styled Text", "Plain Rich Text", "Italic Rich Text", "Plain TextEdit", "Italic TextEdit", "TextInput"] ++ property variant text: ["", " ", "Hello world!", "مرحبا العالم!", "Hello world! Hello!\nHello world! Hello!", "مرحبا العالم! مرحبا! مرحبا العالم! مرحبا!" ,"مرحبا العالم! مرحبا! مرحبا Hello world!\nالعالم! مرحبا!"] ++ property variant description: ["empty text", "white-space-only text", "left-to-right text", "right-to-left text", "multi-line left-to-right text", "multi-line right-to-left text", "multi-line bidi text"] ++ property variant textComponents: [plainTextComponent, styledTextComponent, richTextComponent, italicRichTextComponent, plainTextEdit, italicTextEdit, textInput] ++ ++ function shortText(horizontalAlignment) { ++ ++ // all the different QML editors have ++ // the same alignment values ++ switch (horizontalAlignment) { ++ case Text.AlignLeft: ++ return "L"; ++ case Text.AlignRight: ++ return "R"; ++ case Text.AlignHCenter: ++ return "C"; ++ case Text.AlignJustify: ++ return "J"; ++ default: ++ return "Error"; ++ } ++ } ++ Column { ++ id: containerColumn ++ spacing: 10 ++ width: editorTypeRow.width ++ anchors { top: parent.top; topMargin: 5 } ++ Row { ++ id: editorTypeRow ++ Repeater { ++ model: editorType.length ++ Item { ++ width: editorColumn.width ++ height: editorColumn.height ++ Column { ++ id: editorColumn ++ spacing: 5 ++ width: textColumn.width+10 ++ Text { ++ text: root.editorType[index] ++ font.pixelSize: 16 ++ anchors.horizontalCenter: parent.horizontalCenter ++ } ++ Column { ++ id: textColumn ++ spacing: 5 ++ anchors.horizontalCenter: parent.horizontalCenter ++ Repeater { ++ model: textComponents.length ++ delegate: textComponents[index] ++ } ++ } ++ } ++ } ++ } ++ } ++ Column { ++ spacing: 2 ++ width: parent.width ++ Rectangle { ++ // button ++ height: 50; width: parent.width ++ color: mouseArea.pressed ? "black" : "lightgray" ++ Column { ++ anchors.centerIn: parent ++ Text { ++ text: root.mirror ? "Mirrored" : "Not mirrored" ++ color: "white" ++ font.pixelSize: 16 ++ anchors.horizontalCenter: parent.horizontalCenter ++ } ++ Text { ++ text: "(click here to toggle)" ++ color: "white" ++ font.pixelSize: 10 ++ font.italic: true ++ anchors.horizontalCenter: parent.horizontalCenter ++ } ++ } ++ MouseArea { ++ id: mouseArea ++ property int index: 0 ++ anchors.fill: parent ++ onClicked: root.mirror = !root.mirror ++ } ++ } ++ Rectangle { ++ // button ++ height: 50; width: parent.width ++ color: mouseArea2.pressed ? "black" : "gray" ++ Column { ++ anchors.centerIn: parent ++ Text { ++ text: { ++ if (root.horizontalAlignment == undefined) ++ return "Implict alignment"; ++ switch (root.horizontalAlignment) { ++ case Text.AlignLeft: ++ return "Left alignment"; ++ case Text.AlignRight: ++ return "Right alignment"; ++ case Text.AlignHCenter: ++ return "Center alignment"; ++ case Text.AlignJustify: ++ return "Justify alignment"; ++ } ++ } ++ color: "white" ++ font.pixelSize: 16 ++ anchors.horizontalCenter: parent.horizontalCenter ++ } ++ Text { ++ text: "(click here to toggle)" ++ color: "white" ++ font.pixelSize: 10 ++ font.italic: true ++ anchors.horizontalCenter: parent.horizontalCenter ++ } ++ } ++ MouseArea { ++ id: mouseArea2 ++ property int index: 0 ++ anchors.fill: parent ++ onClicked: { ++ if (index < 0) { ++ root.horizontalAlignment = undefined; ++ } else { ++ root.horizontalAlignment = Math.pow(2, index); ++ } ++ index = (index + 2) % 5 - 1; ++ } ++ } ++ } ++ } ++ } ++ ++ Component { ++ id: plainTextComponent ++ Text { ++ width: 180 ++ text: root.text[index] ++ font.pixelSize: 24 ++ wrapMode: Text.WordWrap ++ horizontalAlignment: root.horizontalAlignment ++ LayoutMirroring.enabled: root.mirror ++ textFormat: Text.RichText ++ Rectangle { ++ z: -1 ++ color: Qt.rgba(0.8, 0.2, 0.2, 0.3) ++ anchors.fill: parent ++ } ++ Text { ++ text: root.description[index] ++ color: Qt.rgba(1,1,1,1.0) ++ anchors.centerIn: parent ++ Rectangle { ++ z: -1 ++ color: Qt.rgba(0.3, 0, 0, 0.3) ++ anchors { fill: parent; margins: -3 } ++ } ++ } ++ Text { ++ color: "white" ++ text: shortText(parent.horizontalAlignment) ++ anchors { top: parent.top; right: parent.right; margins: 2 } ++ } ++ } ++ } ++ ++ Component { ++ id: styledTextComponent ++ Text { ++ width: 180 ++ text: root.text[index] ++ font.pixelSize: 24 ++ wrapMode: Text.WordWrap ++ horizontalAlignment: root.horizontalAlignment ++ LayoutMirroring.enabled: root.mirror ++ textFormat: Text.RichText ++ style: Text.Sunken ++ styleColor: "white" ++ Rectangle { ++ z: -1 ++ color: Qt.rgba(0.8, 0.2, 0.2, 0.3) ++ anchors.fill: parent ++ } ++ Text { ++ text: root.description[index] ++ color: Qt.rgba(1,1,1,1.0) ++ anchors.centerIn: parent ++ Rectangle { ++ z: -1 ++ color: Qt.rgba(0.3, 0, 0, 0.3) ++ anchors { fill: parent; margins: -3 } ++ } ++ } ++ Text { ++ color: "white" ++ text: shortText(parent.horizontalAlignment) ++ anchors { top: parent.top; right: parent.right; margins: 2 } ++ } ++ } ++ } ++ ++ Component { ++ id: richTextComponent ++ Text { ++ width: 180 ++ text: root.text[index] ++ font.pixelSize: 24 ++ wrapMode: Text.WordWrap ++ horizontalAlignment: root.horizontalAlignment ++ LayoutMirroring.enabled: root.mirror ++ textFormat: Text.RichText ++ Rectangle { ++ z: -1 ++ color: Qt.rgba(0.8, 0.2, 0.2, 0.3) ++ anchors.fill: parent ++ } ++ Text { ++ text: root.description[index] ++ color: Qt.rgba(1,1,1,1.0) ++ anchors.centerIn: parent ++ Rectangle { ++ z: -1 ++ color: Qt.rgba(0.3, 0, 0, 0.3) ++ anchors { fill: parent; margins: -3 } ++ } ++ } ++ Text { ++ color: "white" ++ text: shortText(parent.horizontalAlignment) ++ anchors { top: parent.top; right: parent.right; margins: 2 } ++ } ++ } ++ } ++ ++ Component { ++ id: italicRichTextComponent ++ Text { ++ width: 180 ++ text: "" + root.text[index] + "" ++ font.pixelSize: 24 ++ wrapMode: Text.WordWrap ++ horizontalAlignment: root.horizontalAlignment ++ LayoutMirroring.enabled: root.mirror ++ textFormat: Text.RichText ++ property variant backgroundColor: Qt.rgba(0.8, 0.2, 0.2, 0.3) ++ Rectangle { ++ z: -1 ++ color: parent.backgroundColor ++ anchors.fill: parent ++ } ++ Text { ++ text: root.description[index] ++ color: Qt.rgba(1,1,1,1.0) ++ anchors.centerIn: parent ++ Rectangle { ++ z: -1 ++ color: Qt.rgba(0.3, 0, 0, 0.3) ++ anchors { fill: parent; margins: -3 } ++ } ++ } ++ Text { ++ color: "white" ++ text: shortText(parent.horizontalAlignment) ++ anchors { top: parent.top; right: parent.right; margins: 2 } ++ } ++ } ++ } ++ ++ Component { ++ id: plainTextEdit ++ TextEdit { ++ width: 180 ++ text: root.text[index] ++ font.pixelSize: 24 ++ cursorVisible: true ++ wrapMode: TextEdit.WordWrap ++ horizontalAlignment: root.horizontalAlignment ++ LayoutMirroring.enabled: root.mirror ++ Rectangle { ++ z: -1 ++ color: Qt.rgba(0.5, 0.5, 0.2, 0.3) ++ anchors.fill: parent ++ } ++ Text { ++ text: root.description[index] ++ color: Qt.rgba(1,1,1,1.0) ++ anchors.centerIn: parent ++ Rectangle { ++ z: -1 ++ color: Qt.rgba(0.3, 0, 0, 0.3) ++ anchors { fill: parent; margins: -3 } ++ } ++ } ++ Text { ++ color: "white" ++ text: shortText(parent.horizontalAlignment) ++ anchors { top: parent.top; right: parent.right; margins: 2 } ++ } ++ } ++ } ++ ++ Component { ++ id: italicTextEdit ++ TextEdit { ++ width: 180 ++ text: "" + root.text[index] + "" ++ font.pixelSize: 24 ++ cursorVisible: true ++ wrapMode: TextEdit.WordWrap ++ textFormat: TextEdit.RichText ++ horizontalAlignment: root.horizontalAlignment ++ LayoutMirroring.enabled: root.mirror ++ Rectangle { ++ z: -1 ++ color: Qt.rgba(0.5, 0.5, 0.2, 0.3) ++ anchors.fill: parent ++ } ++ Text { ++ text: root.description[index] ++ color: Qt.rgba(1,1,1,1.0) ++ anchors.centerIn: parent ++ Rectangle { ++ z: -1 ++ color: Qt.rgba(0.3, 0, 0, 0.3) ++ anchors { fill: parent; margins: -3 } ++ } ++ } ++ Text { ++ color: "white" ++ text: shortText(parent.horizontalAlignment) ++ anchors { top: parent.top; right: parent.right; margins: 2 } ++ } ++ } ++ } ++ ++ Component { ++ id: textInput ++ Item { ++ width: 180 ++ height: textInput.text.length > 20 ? 3*textInput.height : textInput.height ++ TextInput { ++ id: textInput ++ width: 180 ++ text: root.text[index] ++ font.pixelSize: 24 ++ cursorVisible: true ++ horizontalAlignment: root.horizontalAlignment ++ LayoutMirroring.enabled: root.mirror ++ Rectangle { ++ z: -1 ++ color: Qt.rgba(0.6, 0.4, 0.2, 0.3) ++ anchors.fill: parent ++ } ++ Text { ++ text: root.description[index] ++ color: Qt.rgba(1,1,1,1.0) ++ anchors.centerIn: parent ++ Rectangle { ++ z: -1 ++ color: Qt.rgba(0.3, 0, 0, 0.3) ++ anchors { fill: parent; margins: -3 } ++ } ++ } ++ Text { ++ color: "white" ++ text: shortText(parent.horizontalAlignment) ++ anchors { top: parent.top; right: parent.right; margins: 2 } ++ } ++ } ++ } ++ } ++} ++ diff --cc examples/quick/righttoleft/textalignment/textalignment.qmlproject index 0000000,0000000..e4b5061 new file mode 100644 --- /dev/null +++ b/examples/quick/righttoleft/textalignment/textalignment.qmlproject @@@ -1,0 -1,0 +1,16 @@@ ++import QmlProject 1.1 ++ ++Project { ++ mainFile: "textalignment.qml" ++ ++ /* Include .qml, .js, and image files from current directory and subdirectories */ ++ QmlFiles { ++ directory: "." ++ } ++ JavaScriptFiles { ++ directory: "." ++ } ++ ImageFiles { ++ directory: "." ++ } ++} diff --cc examples/quick/shadereffects/content/Slider.qml index 0000000,0000000..ff5f628 new file mode 100644 --- /dev/null +++ b/examples/quick/shadereffects/content/Slider.qml @@@ -1,0 -1,0 +1,93 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the QtQuick module of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL$ ++** GNU Lesser General Public License Usage ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** ++** ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Item { ++ property real value: bar.x / (foo.width - bar.width) ++ Item { ++ id: foo ++ width: parent.width - 4 ++ height: 6 ++ anchors.centerIn: parent ++ ++ Rectangle { ++ height: parent.height ++ anchors.left: parent.left ++ anchors.right: bar.horizontalCenter ++ color: "blue" ++ radius: 3 ++ } ++ Rectangle { ++ height: parent.height ++ anchors.left: bar.horizontalCenter ++ anchors.right: parent.right ++ color: "gray" ++ radius: 3 ++ } ++ Rectangle { ++ anchors.fill: parent ++ color: "transparent" ++ radius: 3 ++ border.width: 2 ++ border.color: "black" ++ } ++ ++ Rectangle { ++ id: bar ++ y: -7 ++ width: 20 ++ height: 20 ++ radius: 15 ++ color: "white" ++ border.width: 2 ++ border.color: "black" ++ MouseArea { ++ anchors.fill: parent ++ drag.target: parent ++ drag.axis: Drag.XAxis ++ drag.minimumX: 0 ++ drag.maximumX: foo.width - parent.width ++ } ++ } ++ } ++} ++ diff --cc examples/quick/shadereffects/content/face-smile.png index 0000000,0000000..3d66d72 new file mode 100644 Binary files differ diff --cc examples/quick/shadereffects/content/qt-logo.png index 0000000,0000000..7d3e97e new file mode 100644 Binary files differ diff --cc examples/quick/shadereffects/shadereffects.qml index 0000000,0000000..b820c81 new file mode 100644 --- /dev/null +++ b/examples/quick/shadereffects/shadereffects.qml @@@ -1,0 -1,0 +1,315 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the QtQuick module of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL$ ++** GNU Lesser General Public License Usage ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** ++** ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++import "content" ++ ++Image { ++ width: 320 ++ height: 480 ++/*! ++ \title QML Examples - Shader Effects ++ \example declarative/shadereffects ++ \image qml-shadereffects-example.png ++ \brief This is a shader effects example ++ ++ This example demonstrates a couple of visual effects that you can perform ++ with shaders in QtQuick 2.0 ++*/ ++ source: "../snake/content/pics/background.png" ++ ++ Flickable { ++ anchors.fill: parent ++ contentWidth: 640 ++ contentHeight: 360 ++ ++ ShaderEffectSource { ++ id: theSource ++ sourceItem: theItem ++ smooth: true ++ } ++ ++ function saturate(x) { ++ return Math.min(Math.max(x, 0), 1) ++ } ++ ++ function sliderToColor(x) { ++ return Qt.rgba(saturate(Math.max(2 - 6 * x, 6 * x - 4)), ++ saturate(Math.min(6 * x, 4 - 6 * x)), ++ saturate(Math.min(6 * x - 2, 6 - 6 * x))) ++ } ++ ++ Grid { ++ anchors.centerIn: parent ++ columns: 3 ++ ++ Item { ++ id: theItem ++ width: 180 ++ height: 180 ++ ListView { ++ anchors.centerIn: parent ++ width: 160 ++ height: 140 ++ clip: true ++ snapMode: ListView.SnapOneItem ++ model: VisualItemModel { ++ Text { ++ width: 160 ++ height: 140 ++ horizontalAlignment: Text.AlignHCenter ++ verticalAlignment: Text.AlignVCenter ++ font.pixelSize: 120 ++ font.family: "Times" ++ color: "blue" ++ text: "Qt" ++ } ++ Image { ++ width: 160 ++ height: 140 ++ source: "content/qt-logo.png" ++ smooth: true ++ } ++ Image { ++ width: 160 ++ height: 140 ++ source: "content/face-smile.png" ++ smooth: true ++ } ++ } ++ } ++ } ++ ShaderEffect { ++ width: 180 ++ height: 180 ++ property variant source: theSource ++ property real amplitude: 0.04 * wobbleSlider.value ++ property real frequency: 20 ++ property real time: 0 ++ NumberAnimation on time { loops: Animation.Infinite; from: 0; to: Math.PI * 2; duration: 600 } ++ fragmentShader: ++ "uniform lowp float qt_Opacity;" + ++ "uniform highp float amplitude;" + ++ "uniform highp float frequency;" + ++ "uniform highp float time;" + ++ "uniform sampler2D source;" + ++ "varying highp vec2 qt_TexCoord0;" + ++ "void main() {" + ++ " highp vec2 p = sin(time + frequency * qt_TexCoord0);" + ++ " gl_FragColor = texture2D(source, qt_TexCoord0 + amplitude * vec2(p.y, -p.x)) * qt_Opacity;" + ++ "}" ++ Slider { ++ id: wobbleSlider ++ anchors.left: parent.left ++ anchors.right: parent.right ++ anchors.bottom: parent.bottom ++ height: 40 ++ } ++ } ++ ShaderEffect { ++ width: 180 ++ height: 180 ++ property variant source: theSource ++ property variant shadow: ShaderEffectSource { ++ smooth: true ++ sourceItem: ShaderEffect { ++ width: theItem.width ++ height: theItem.height ++ property variant delta: Qt.size(0.0, 1.0 / height) ++ property variant source: ShaderEffectSource { ++ smooth: true ++ sourceItem: ShaderEffect { ++ width: theItem.width ++ height: theItem.height ++ property variant delta: Qt.size(1.0 / width, 0.0) ++ property variant source: theSource ++ fragmentShader: " ++ uniform lowp float qt_Opacity; ++ uniform sampler2D source; ++ uniform highp vec2 delta; ++ varying highp vec2 qt_TexCoord0; ++ void main() { ++ gl_FragColor =(0.0538 * texture2D(source, qt_TexCoord0 - 3.182 * delta) ++ + 0.3229 * texture2D(source, qt_TexCoord0 - 1.364 * delta) ++ + 0.2466 * texture2D(source, qt_TexCoord0) ++ + 0.3229 * texture2D(source, qt_TexCoord0 + 1.364 * delta) ++ + 0.0538 * texture2D(source, qt_TexCoord0 + 3.182 * delta)) * qt_Opacity; ++ }" ++ } ++ } ++ fragmentShader: " ++ uniform lowp float qt_Opacity; ++ uniform sampler2D source; ++ uniform highp vec2 delta; ++ varying highp vec2 qt_TexCoord0; ++ void main() { ++ gl_FragColor =(0.0538 * texture2D(source, qt_TexCoord0 - 3.182 * delta) ++ + 0.3229 * texture2D(source, qt_TexCoord0 - 1.364 * delta) ++ + 0.2466 * texture2D(source, qt_TexCoord0) ++ + 0.3229 * texture2D(source, qt_TexCoord0 + 1.364 * delta) ++ + 0.0538 * texture2D(source, qt_TexCoord0 + 3.182 * delta)) * qt_Opacity; ++ }" ++ } ++ } ++ property real angle: 0 ++ property variant offset: Qt.point(15.0 * Math.cos(angle), 15.0 * Math.sin(angle)) ++ NumberAnimation on angle { loops: Animation.Infinite; from: 0; to: Math.PI * 2; duration: 6000 } ++ property variant delta: Qt.size(offset.x / width, offset.y / height) ++ property real darkness: shadowSlider.value ++ fragmentShader: " ++ uniform lowp float qt_Opacity; ++ uniform highp vec2 offset; ++ uniform sampler2D source; ++ uniform sampler2D shadow; ++ uniform highp float darkness; ++ uniform highp vec2 delta; ++ varying highp vec2 qt_TexCoord0; ++ void main() { ++ lowp vec4 fg = texture2D(source, qt_TexCoord0); ++ lowp vec4 bg = texture2D(shadow, qt_TexCoord0 + delta); ++ gl_FragColor = (fg + vec4(0., 0., 0., darkness * bg.a) * (1. - fg.a)) * qt_Opacity; ++ }" ++ Slider { ++ id: shadowSlider ++ anchors.left: parent.left ++ anchors.right: parent.right ++ anchors.bottom: parent.bottom ++ height: 40 ++ } ++ } ++ ShaderEffect { ++ width: 180 ++ height: 180 ++ property variant source: theSource ++ property variant delta: Qt.size(0.5 / width, 0.5 / height) ++ fragmentShader: " ++ uniform sampler2D source; ++ uniform highp vec2 delta; ++ uniform highp float qt_Opacity; ++ varying highp vec2 qt_TexCoord0; ++ void main() { ++ lowp vec4 tl = texture2D(source, qt_TexCoord0 - delta); ++ lowp vec4 tr = texture2D(source, qt_TexCoord0 + vec2(delta.x, -delta.y)); ++ lowp vec4 bl = texture2D(source, qt_TexCoord0 - vec2(delta.x, -delta.y)); ++ lowp vec4 br = texture2D(source, qt_TexCoord0 + delta); ++ lowp vec4 gx = (tl + bl) - (tr + br); ++ lowp vec4 gy = (tl + tr) - (bl + br); ++ gl_FragColor.xyz = vec3(0.); ++ gl_FragColor.w = clamp(dot(sqrt(gx * gx + gy * gy), vec4(1.)), 0., 1.) * qt_Opacity; ++ }" ++ } ++ ShaderEffect { ++ width: 180 ++ height: 180 ++ property variant source: theSource ++ property color tint: sliderToColor(colorizeSlider.value) ++ fragmentShader: " ++ uniform sampler2D source; ++ uniform lowp vec4 tint; ++ uniform lowp float qt_Opacity; ++ varying highp vec2 qt_TexCoord0; ++ void main() { ++ lowp vec4 c = texture2D(source, qt_TexCoord0); ++ lowp float lo = min(min(c.x, c.y), c.z); ++ lowp float hi = max(max(c.x, c.y), c.z); ++ gl_FragColor = qt_Opacity * vec4(mix(vec3(lo), vec3(hi), tint.xyz), c.w); ++ }" ++ Slider { ++ id: colorizeSlider ++ anchors.left: parent.left ++ anchors.right: parent.right ++ anchors.bottom: parent.bottom ++ height: 40 ++ } ++ } ++ ShaderEffect { ++ width: 180 ++ height: 180 ++ mesh: Qt.size(10, 10) ++ property variant source: theSource ++ property real bend: 0 ++ property real minimize: 0 ++ property real side: genieSlider.value ++ SequentialAnimation on bend { ++ loops: Animation.Infinite ++ NumberAnimation { to: 1; duration: 700; easing.type: Easing.InOutSine } ++ PauseAnimation { duration: 1600 } ++ NumberAnimation { to: 0; duration: 700; easing.type: Easing.InOutSine } ++ PauseAnimation { duration: 1000 } ++ } ++ SequentialAnimation on minimize { ++ loops: Animation.Infinite ++ PauseAnimation { duration: 300 } ++ NumberAnimation { to: 1; duration: 700; easing.type: Easing.InOutSine } ++ PauseAnimation { duration: 1000 } ++ NumberAnimation { to: 0; duration: 700; easing.type: Easing.InOutSine } ++ PauseAnimation { duration: 1300 } ++ } ++ vertexShader: " ++ uniform highp mat4 qt_Matrix; ++ uniform highp float bend; ++ uniform highp float minimize; ++ uniform highp float side; ++ uniform highp float width; ++ uniform highp float height; ++ attribute highp vec4 qt_Vertex; ++ attribute highp vec2 qt_MultiTexCoord0; ++ varying highp vec2 qt_TexCoord0; ++ void main() { ++ qt_TexCoord0 = qt_MultiTexCoord0; ++ highp vec4 pos = qt_Vertex; ++ pos.y = mix(qt_Vertex.y, height, minimize); ++ highp float t = pos.y / height; ++ t = (3. - 2. * t) * t * t; ++ pos.x = mix(qt_Vertex.x, side * width, t * bend); ++ gl_Position = qt_Matrix * pos; ++ }" ++ Slider { ++ id: genieSlider ++ anchors.left: parent.left ++ anchors.right: parent.right ++ anchors.bottom: parent.bottom ++ height: 40 ++ } ++ } ++ } ++ } ++} diff --cc examples/quick/text/fonts/availableFonts.qml index 0000000,0000000..0b87259 new file mode 100644 --- /dev/null +++ b/examples/quick/text/fonts/availableFonts.qml @@@ -1,0 -1,0 +1,57 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Rectangle { ++ width: 480; height: 640; color: "steelblue" ++ ++ ListView { ++ anchors.fill: parent; model: Qt.fontFamilies() ++ ++ delegate: Item { ++ height: 40; width: ListView.view.width ++ Text { ++ anchors.centerIn: parent ++ text: modelData; font.family: modelData; font.pixelSize: 24; color: "white" ++ } ++ } ++ } ++} diff --cc examples/quick/text/fonts/banner.qml index 0000000,0000000..6c9aa25 new file mode 100644 --- /dev/null +++ b/examples/quick/text/fonts/banner.qml @@@ -1,0 -1,0 +1,61 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Rectangle { ++ id: screen ++ ++ property int pixelSize: screen.height * 1.25 ++ property color textColor: "lightsteelblue" ++ property string text: "Hello world! " ++ ++ width: 640; height: 320 ++ color: "steelblue" ++ ++ Row { ++ y: -screen.height / 4.5 ++ ++ NumberAnimation on x { from: 0; to: -text.width; duration: 6000; loops: Animation.Infinite } ++ Text { id: text; font.pixelSize: screen.pixelSize; color: screen.textColor; text: screen.text } ++ Text { font.pixelSize: screen.pixelSize; color: screen.textColor; text: screen.text } ++ Text { font.pixelSize: screen.pixelSize; color: screen.textColor; text: screen.text } ++ } ++} diff --cc examples/quick/text/fonts/content/fonts/tarzeau_ocr_a.ttf index 0000000,cf93f96..cf93f96 mode 000000,100644..100644 Binary files differ diff --cc examples/quick/text/fonts/fonts.qml index 0000000,0000000..78cef25 new file mode 100644 --- /dev/null +++ b/examples/quick/text/fonts/fonts.qml @@@ -1,0 -1,0 +1,104 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Rectangle { ++ property string myText: "The quick brown fox jumps over the lazy dog." ++ ++ width: 800; height: 480 ++ color: "steelblue" ++ ++ FontLoader { id: fixedFont; name: "Courier" } ++ FontLoader { id: localFont; source: "content/fonts/tarzeau_ocr_a.ttf" } ++ FontLoader { id: webFont; source: "http://www.princexml.com/fonts/steffmann/Starburst.ttf" } ++ ++ Column { ++ anchors { fill: parent; leftMargin: 10; rightMargin: 10 } ++ spacing: 15 ++ ++ Text { ++ text: myText ++ color: "lightsteelblue" ++ width: parent.width ++ elide: Text.ElideRight ++ font.family: "Times"; font.pointSize: 42 ++ } ++ Text { ++ text: myText ++ color: "lightsteelblue" ++ width: parent.width ++ elide: Text.ElideLeft ++ font { family: "Times"; pointSize: 42; capitalization: Font.AllUppercase } ++ } ++ Text { ++ text: myText ++ color: "lightsteelblue" ++ width: parent.width ++ elide: Text.ElideMiddle ++ font { family: fixedFont.name; pointSize: 42; weight: Font.Bold; capitalization: Font.AllLowercase } ++ } ++ Text { ++ text: myText ++ color: "lightsteelblue" ++ width: parent.width ++ elide: Text.ElideRight ++ font { family: fixedFont.name; pointSize: 42; italic: true; capitalization: Font.SmallCaps } ++ } ++ Text { ++ text: myText ++ color: "lightsteelblue" ++ width: parent.width ++ elide: Text.ElideLeft ++ font { family: localFont.name; pointSize: 42; capitalization: Font.Capitalize } ++ } ++ Text { ++ text: { ++ if (webFont.status == FontLoader.Ready) myText ++ else if (webFont.status == FontLoader.Loading) "Loading..." ++ else if (webFont.status == FontLoader.Error) "Error loading font" ++ } ++ color: "lightsteelblue" ++ width: parent.width ++ elide: Text.ElideMiddle ++ font.family: webFont.name; font.pointSize: 42 ++ } ++ } ++} diff --cc examples/quick/text/fonts/hello.qml index 0000000,0000000..d9479fb new file mode 100644 --- /dev/null +++ b/examples/quick/text/fonts/hello.qml @@@ -1,0 -1,0 +1,79 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Rectangle { ++ id: screen ++ ++ width: 800; height: 480 ++ color: "black" ++ ++ Item { ++ id: container ++ x: screen.width / 2; y: screen.height / 2 ++ ++ Text { ++ id: text ++ anchors.centerIn: parent ++ color: "white" ++ text: "Hello world!" ++ font.pixelSize: 60 ++ smooth: true ++ ++ SequentialAnimation on font.letterSpacing { ++ loops: Animation.Infinite; ++ NumberAnimation { from: 0; to: 150; easing.type: Easing.InQuad; duration: 3000 } ++ ScriptAction { ++ script: { ++ container.y = (screen.height / 4) + (Math.random() * screen.height / 2) ++ container.x = (screen.width / 4) + (Math.random() * screen.width / 2) ++ } ++ } ++ } ++ ++ SequentialAnimation on opacity { ++ loops: Animation.Infinite; ++ NumberAnimation { from: 1; to: 0; duration: 2600 } ++ PauseAnimation { duration: 400 } ++ } ++ } ++ } ++} diff --cc examples/quick/text/imgtag/TextWithImage.qml index 0000000,0000000..bc09aa2 new file mode 100644 --- /dev/null +++ b/examples/quick/text/imgtag/TextWithImage.qml @@@ -1,0 -1,0 +1,55 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Text { ++ width: parent.width ++ font.pointSize: 14 ++ wrapMode: Text.WordWrap ++ textFormat: Text.StyledText ++ horizontalAlignment: main.hAlign ++ ++ Rectangle { ++ border.color: "#efefef" ++ color: "transparent" ++ anchors.fill: parent ++ } ++} diff --cc examples/quick/text/imgtag/images/face-sad.png index 0000000,24188b7..24188b7 mode 000000,100644..100644 Binary files differ diff --cc examples/quick/text/imgtag/images/face-smile-big.png index 0000000,0000000..d05e0bf new file mode 100644 Binary files differ diff --cc examples/quick/text/imgtag/images/face-smile.png index 0000000,0000000..e5e1d13 new file mode 100644 Binary files differ diff --cc examples/quick/text/imgtag/images/heart200.png index 0000000,cedd3ea..cedd3ea mode 000000,100644..100644 Binary files differ diff --cc examples/quick/text/imgtag/images/qtlogo.png index 0000000,0000000..996719a new file mode 100644 Binary files differ diff --cc examples/quick/text/imgtag/images/starfish_2.png index 0000000,132c20f..132c20f mode 000000,100644..100644 Binary files differ diff --cc examples/quick/text/imgtag/imgtag.qml index 0000000,0000000..9d181af new file mode 100644 --- /dev/null +++ b/examples/quick/text/imgtag/imgtag.qml @@@ -1,0 -1,0 +1,101 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Rectangle { ++ id: main ++ width: 320; height: 480 ++ focus: true ++ ++ property var hAlign: Text.AlignLeft ++ ++ Flickable { ++ anchors.fill: parent ++ contentWidth: parent.width ++ contentHeight: col.height + 20 ++ ++ Column { ++ id: col ++ x: 10; y: 10 ++ spacing: 20 ++ width: parent.width - 20 ++ ++ TextWithImage { ++ text: "This is a happy face" ++ } ++ TextWithImage { ++ text: "This is a veryhappy face aligned in the middle." ++ } ++ TextWithImage { ++ elide: Text.ElideRight ++ maximumLineCount: 2 ++ text: "This is a sad face aligned to the top. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc rutrum dui pretium ipsum malesuada venenatis. Nulla sed turpis risus. Integer sit amet odio quis mauris varius venenatisLorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc rutrum dui pretium ipsum malesuada venenatis. Nulla sed turpis risus. Integer sit amet odio quis mauris varius venenatis." ++ } ++ TextWithImage { ++ text: "This is a tinyhappy face." ++ } ++ TextWithImage { ++ text: "This is a starfishaligned to the top and another onealigned to the bottom." ++ } ++ TextWithImage { ++ text: "Qt logosaligned in the middle with different sizes." ++ } ++ TextWithImage { ++ text: "Some hearts with different sizes." ++ } ++ TextWithImage { ++ text: "Resized imagefrom the internet." ++ } ++ TextWithImage { ++ text: "Imagefrom the internet." ++ } ++ TextWithImage { ++ height: 120 ++ verticalAlignment: Text.AlignVCenter ++ text: "This is a happy face with an explicit height." ++ } ++ } ++ } ++ ++ Keys.onUpPressed: main.hAlign = Text.AlignHCenter ++ Keys.onLeftPressed: main.hAlign = Text.AlignLeft ++ Keys.onRightPressed: main.hAlign = Text.AlignRight ++} diff --cc examples/quick/text/styledtext-layout.qml index 0000000,0000000..4571330 new file mode 100644 --- /dev/null +++ b/examples/quick/text/styledtext-layout.qml @@@ -1,0 -1,0 +1,107 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Rectangle { ++ id: main ++ width: 320; height: 480 ++ focus: true ++ ++ property real offset: 0 ++ property real margin: 10 ++ ++ Keys.onLeftPressed: myText.horizontalAlignment = Text.AlignLeft ++ Keys.onUpPressed: myText.horizontalAlignment = Text.AlignHCenter ++ Keys.onRightPressed: myText.horizontalAlignment = Text.AlignRight ++ Keys.onDownPressed: myText.horizontalAlignment = Text.AlignJustify ++ ++ Text { ++ id: myText ++ anchors.fill: parent ++ anchors.margins: 10 ++ wrapMode: Text.WordWrap ++ font.family: "Times New Roman" ++ font.pixelSize: 13 ++ textFormat: Text.StyledText ++ horizontalAlignment: Text.AlignJustify ++ ++ text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer at ante dui sed eu egestas est facilis www.nokia.com.
Curabitur ante est, pulvinar quis adipiscing a, iaculis id ipsum. Phasellus id neque id velit facilisis cursus ac sit amet nibh. Donec enim arcu, pharetra non semper nec, iaculis eget elit. Nunc blandit condimentum odio vel egestas.
  • Coffee
    1. Espresso
    2. Cappuccino
    3. Flat White
    4. Latte
  • Juice
    1. Orange
    2. Apple
    3. Pineapple
    4. Tomato

Proin consectetur sapien in ipsum lacinia sit amet mattis orci interdum. Quisque vitae accumsan lectus. Ut nisi turpis, sollicitudin ut dignissim id, fermentum ac est. Maecenas nec libero leo. Sed ac leo eget ipsum ultricies viverra sit amet eu orci. Praesent et tortor risus, viverra accumsan sapien. Sed faucibus eleifend lectus, sed euismod urna porta eu. Aenean ultricies lectus ut orci dictum quis convallis nisi ultrices. Nunc elit mi, iaculis a porttitor rutrum, venenatis malesuada nisi. Suspendisse turpis quam, euismod non imperdiet et, rutrum nec ligula. Lorem ipsum dolor sit amet, consectetur adipiscing elit." ++ ++ onLineLaidOut: { ++ line.width = width / 2 - (2 * margin) ++ if (line.number === 30) { ++ main.offset = line.y ++ } ++ if (line.number >= 30) { ++ line.x = width / 2 + margin ++ line.y -= main.offset ++ } ++ if ((line.y + line.height) > rect.y && line.y < (rect.y + rect.height)) { ++ if (line.number < 30) ++ line.width = Math.min((rect.x - line.x), line.width) ++ else { ++ line.x = Math.max((rect.x + rect.width), width / 2 + margin) ++ line.width = Math.min((width - margin - line.x), line.width) ++ } ++ } ++ } ++ ++ Item { ++ id: rect ++ x: 28; y: 20 ++ width: 60; height: 60 ++ ++ Rectangle { ++ anchors { fill: parent; leftMargin: 2; rightMargin: 2 } ++ color: "lightsteelblue"; opacity: 0.3 ++ } ++ ++ MouseArea { ++ anchors.fill: parent ++ drag.target: rect ++ acceptedButtons: Qt.LeftButton | Qt.RightButton ++ onClicked: mouse.button == Qt.RightButton ? myText.font.pixelSize -= 1 : myText.font.pixelSize += 1 ++ onPositionChanged: myText.doLayout() ++ } ++ } ++ } ++ ++} diff --cc examples/quick/text/text.qml index 0000000,9bfd290..9bfd290 mode 000000,100644..100644 --- a/examples/quick/text/text.qml +++ b/examples/quick/text/text.qml diff --cc examples/quick/text/text.qmlproject index 0000000,0000000..c08d9b9 new file mode 100644 --- /dev/null +++ b/examples/quick/text/text.qmlproject @@@ -1,0 -1,0 +1,16 @@@ ++import QmlProject 1.1 ++ ++Project { ++ mainFile: "text.qml" ++ ++ /* Include .qml, .js, and image files from current directory and subdirectories */ ++ QmlFiles { ++ directory: "." ++ } ++ JavaScriptFiles { ++ directory: "." ++ } ++ ImageFiles { ++ directory: "." ++ } ++} diff --cc examples/quick/text/textselection/pics/endHandle.png index 0000000,0000000..1a4bc5d new file mode 100644 Binary files differ diff --cc examples/quick/text/textselection/pics/endHandle.sci index 0000000,0000000..4f51f24 new file mode 100644 --- /dev/null +++ b/examples/quick/text/textselection/pics/endHandle.sci @@@ -1,0 -1,0 +1,5 @@@ ++border.left: 0 ++border.top: 6 ++border.bottom: 6 ++border.right: 6 ++source: endHandle.png diff --cc examples/quick/text/textselection/pics/startHandle.png index 0000000,0000000..deedcd5 new file mode 100644 Binary files differ diff --cc examples/quick/text/textselection/pics/startHandle.sci index 0000000,0000000..f9eae20 new file mode 100644 --- /dev/null +++ b/examples/quick/text/textselection/pics/startHandle.sci @@@ -1,0 -1,0 +1,5 @@@ ++border.left: 6 ++border.top: 6 ++border.bottom: 6 ++border.right: 0 ++source: startHandle.png diff --cc examples/quick/text/textselection/textselection.qml index 0000000,0000000..7938ce5 new file mode 100644 --- /dev/null +++ b/examples/quick/text/textselection/textselection.qml @@@ -1,0 -1,0 +1,211 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++import QtQuick 2.0 ++ ++Rectangle { ++ id: editor ++ color: "lightGrey" ++ width: 640; height: 480 ++ ++ Rectangle { ++ color: "white" ++ anchors.fill: parent ++ anchors.margins: 20 ++ ++ BorderImage { ++ id: startHandle ++ source: "pics/startHandle.sci" ++ opacity: 0.0 ++ width: 10 ++ x: edit.positionToRectangle(edit.selectionStart).x - flick.contentX-width ++ y: edit.positionToRectangle(edit.selectionStart).y - flick.contentY ++ height: edit.positionToRectangle(edit.selectionStart).height ++ } ++ ++ BorderImage { ++ id: endHandle ++ source: "pics/endHandle.sci" ++ opacity: 0.0 ++ width: 10 ++ x: edit.positionToRectangle(edit.selectionEnd).x - flick.contentX ++ y: edit.positionToRectangle(edit.selectionEnd).y - flick.contentY ++ height: edit.positionToRectangle(edit.selectionEnd).height ++ } ++ ++ Flickable { ++ id: flick ++ ++ anchors.fill: parent ++ contentWidth: edit.paintedWidth ++ contentHeight: edit.paintedHeight ++ interactive: true ++ clip: true ++ ++ function ensureVisible(r) { ++ if (contentX >= r.x) ++ contentX = r.x; ++ else if (contentX+width <= r.x+r.width) ++ contentX = r.x+r.width-width; ++ if (contentY >= r.y) ++ contentY = r.y; ++ else if (contentY+height <= r.y+r.height) ++ contentY = r.y+r.height-height; ++ } ++ ++ TextEdit { ++ id: edit ++ width: flick.width ++ height: flick.height ++ focus: true ++ wrapMode: TextEdit.Wrap ++ textFormat: TextEdit.RichText ++ ++ onCursorRectangleChanged: flick.ensureVisible(cursorRectangle) ++ ++ text: "

Text Selection

" ++ +"

This example is a whacky text selection mechanisms, showing how these can be implemented in the TextEdit element, to cater for whatever style is appropriate for the target platform." ++ +"

Press-and-hold to select a word, then drag the selection handles." ++ +"

Drag outside the selection to scroll the text." ++ +"

Click inside the selection to cut/copy/paste/cancel selection." ++ +"

It's too whacky to let you paste if there is no current selection." ++ ++ } ++ } ++ ++ Item { ++ id: menu ++ opacity: 0.0 ++ width: 100 ++ height: 120 ++ anchors.centerIn: parent ++ ++ Rectangle { ++ border.width: 1 ++ border.color: "darkBlue" ++ radius: 15 ++ color: "#806080FF" ++ anchors.fill: parent ++ } ++ ++ Column { ++ anchors.centerIn: parent ++ spacing: 8 ++ ++ Rectangle { ++ border.width: 1 ++ border.color: "darkBlue" ++ color: "#ff7090FF" ++ width: 60 ++ height: 16 ++ ++ Text { anchors.centerIn: parent; text: "Cut" } ++ ++ MouseArea { ++ anchors.fill: parent ++ onClicked: { edit.cut(); editor.state = "" } ++ } ++ } ++ ++ Rectangle { ++ border.width: 1 ++ border.color: "darkBlue" ++ color: "#ff7090FF" ++ width: 60 ++ height: 16 ++ ++ Text { anchors.centerIn: parent; text: "Copy" } ++ ++ MouseArea { ++ anchors.fill: parent ++ onClicked: { edit.copy(); editor.state = "selection" } ++ } ++ } ++ ++ Rectangle { ++ border.width: 1 ++ border.color: "darkBlue" ++ color: "#ff7090FF" ++ width: 60 ++ height: 16 ++ ++ Text { anchors.centerIn: parent; text: "Paste" } ++ ++ MouseArea { ++ anchors.fill: parent ++ onClicked: { edit.paste(); edit.cursorPosition = edit.selectionEnd; editor.state = "" } ++ } ++ } ++ ++ Rectangle { ++ border.width: 1 ++ border.color: "darkBlue" ++ color: "#ff7090FF" ++ width: 60 ++ height: 16 ++ ++ Text { anchors.centerIn: parent; text: "Deselect" } ++ ++ MouseArea { ++ anchors.fill: parent ++ onClicked: { ++ edit.cursorPosition = edit.selectionEnd; ++ edit.deselect(); ++ editor.state = "" ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ states: [ ++ State { ++ name: "selection" ++ PropertyChanges { target: startHandle; opacity: 1.0 } ++ PropertyChanges { target: endHandle; opacity: 1.0 } ++ }, ++ State { ++ name: "menu" ++ PropertyChanges { target: startHandle; opacity: 0.5 } ++ PropertyChanges { target: endHandle; opacity: 0.5 } ++ PropertyChanges { target: menu; opacity: 1.0 } ++ } ++ ] ++} diff --cc examples/quick/threading/threadedlistmodel/dataloader.js index 0000000,0000000..4d2aab3 new file mode 100644 --- /dev/null +++ b/examples/quick/threading/threadedlistmodel/dataloader.js @@@ -1,0 -1,0 +1,49 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++// ![0] ++WorkerScript.onMessage = function(msg) { ++ if (msg.action == 'appendCurrentTime') { ++ var data = {'time': new Date().toTimeString()}; ++ msg.model.append(data); ++ msg.model.sync(); // updates the changes to the list ++ } ++} ++// ![0] diff --cc examples/quick/threading/threadedlistmodel/threadedlistmodel.qmlproject index 0000000,0000000..e7c8e69 new file mode 100644 --- /dev/null +++ b/examples/quick/threading/threadedlistmodel/threadedlistmodel.qmlproject @@@ -1,0 -1,0 +1,56 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QmlProject 1.1 ++ ++Project { ++ mainFile: "timedisplay.qml" ++ ++ /* Include .qml, .js, and image files from current directory and subdirectories */ ++ QmlFiles { ++ directory: "." ++ } ++ JavaScriptFiles { ++ directory: "." ++ } ++ ImageFiles { ++ directory: "." ++ } ++} diff --cc examples/quick/threading/threadedlistmodel/timedisplay.qml index 0000000,0000000..48d0f65 new file mode 100644 --- /dev/null +++ b/examples/quick/threading/threadedlistmodel/timedisplay.qml @@@ -1,0 -1,0 +1,76 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++// ![0] ++import QtQuick 2.0 ++ ++Rectangle { ++ color: "white" ++ width: 200 ++ height: 300 ++ ++ ListView { ++ anchors.fill: parent ++ model: listModel ++ delegate: Component { ++ Text { text: time } ++ } ++ ++ ListModel { id: listModel } ++ ++ WorkerScript { ++ id: worker ++ source: "dataloader.js" ++ } ++ ++ Timer { ++ id: timer ++ interval: 2000; repeat: true ++ running: true ++ triggeredOnStart: true ++ ++ onTriggered: { ++ var msg = {'action': 'appendCurrentTime', 'model': listModel}; ++ worker.sendMessage(msg); ++ } ++ } ++ } ++} ++// ![0] diff --cc examples/quick/threading/workerscript/workerscript.js index 0000000,0000000..f76471f new file mode 100644 --- /dev/null +++ b/examples/quick/threading/workerscript/workerscript.js @@@ -1,0 -1,0 +1,15 @@@ ++var lastx = 0; ++var lasty = 0; ++ ++WorkerScript.onMessage = function(message) { ++ var ydiff = message.y - lasty; ++ var xdiff = message.x - lastx; ++ ++ var total = Math.sqrt(ydiff * ydiff + xdiff * xdiff); ++ ++ lastx = message.x; ++ lasty = message.y; ++ ++ WorkerScript.sendMessage( {xmove: xdiff, ymove: ydiff, move: total} ); ++} ++ diff --cc examples/quick/threading/workerscript/workerscript.qml index 0000000,0000000..7fced81 new file mode 100644 --- /dev/null +++ b/examples/quick/threading/workerscript/workerscript.qml @@@ -1,0 -1,0 +1,83 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Rectangle { ++ width: 480; height: 320 ++ ++ WorkerScript { ++ id: myWorker ++ source: "workerscript.js" ++ ++ onMessage: { ++ console.log("Moved " + messageObject.xmove + " along the X axis."); ++ console.log("Moved " + messageObject.ymove + " along the Y axis."); ++ console.log("Moved " + messageObject.move + " pixels."); ++ } ++ } ++ ++ Rectangle { ++ width: 200; height: 200 ++ anchors.left: parent.left; anchors.leftMargin: 20 ++ color: "red" ++ ++ MouseArea { ++ anchors.fill: parent ++ onClicked: myWorker.sendMessage( { rectangle: "red", x: mouse.x, y: mouse.y } ); ++ } ++ } ++ ++ Rectangle { ++ width: 200; height: 200 ++ anchors.right: parent.right; anchors.rightMargin: 20 ++ color: "blue" ++ ++ MouseArea { ++ anchors.fill: parent ++ onClicked: myWorker.sendMessage( { rectangle: "blue", x: mouse.x, y: mouse.y } ); ++ } ++ } ++ ++ Text { ++ text: "Click a Rectangle!" ++ anchors { horizontalCenter: parent.horizontalCenter; bottom: parent.bottom; bottomMargin: 50 } ++ } ++} diff --cc examples/quick/threading/workerscript/workerscript.qmlproject index 0000000,0000000..6d7a91f new file mode 100644 --- /dev/null +++ b/examples/quick/threading/workerscript/workerscript.qmlproject @@@ -1,0 -1,0 +1,16 @@@ ++import QmlProject 1.1 ++ ++Project { ++ mainFile: "workerscript.qml" ++ ++ /* Include .qml, .js, and image files from current directory and subdirectories */ ++ QmlFiles { ++ directory: "." ++ } ++ JavaScriptFiles { ++ directory: "." ++ } ++ ImageFiles { ++ directory: "." ++ } ++} diff --cc examples/quick/touchinteraction/flickable/content/Day.qml index 0000000,0000000..7fe625c new file mode 100644 --- /dev/null +++ b/examples/quick/touchinteraction/flickable/content/Day.qml @@@ -1,0 -1,0 +1,153 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Component { ++ Item { ++ property variant stickies ++ ++ id: page ++ width: ListView.view.width+40; height: ListView.view.height ++ ++ ++ Image { ++ source: "cork.jpg" ++ width: page.ListView.view.width ++ height: page.ListView.view.height ++ fillMode: Image.PreserveAspectCrop ++ clip: true ++ } ++ ++ MouseArea { ++ anchors.fill: parent ++ onClicked: page.focus = false; ++ } ++ ++ Text { ++ text: name; x: 15; y: 8; height: 40; width: 370 ++ font.pixelSize: 18; font.bold: true; color: "white" ++ style: Text.Outline; styleColor: "black" ++ } ++ ++ Repeater { ++ model: notes ++ Item { ++ id: stickyPage ++ ++ property int randomX: Math.random() * (page.ListView.view.width-0.5*stickyImage.width) +100 ++ property int randomY: Math.random() * (page.ListView.view.height-0.5*stickyImage.height) +50 ++ ++ x: randomX; y: randomY ++ ++ rotation: -flickable.horizontalVelocity / 100; ++ Behavior on rotation { ++ SpringAnimation { spring: 2.0; damping: 0.15 } ++ } ++ ++ Item { ++ id: sticky ++ scale: 0.7 ++ ++ Image { ++ id: stickyImage ++ x: 8 + -width * 0.6 / 2; y: -20 ++ source: "note-yellow.png" ++ scale: 0.6; transformOrigin: Item.TopLeft ++ smooth: true ++ } ++ ++ TextEdit { ++ id: myText ++ x: -104; y: 36; width: 215; height: 200 ++ smooth: true ++ font.pixelSize: 24 ++ readOnly: false ++ rotation: -8 ++ text: noteText ++ } ++ ++ Item { ++ x: stickyImage.x; y: -20 ++ width: stickyImage.width * stickyImage.scale ++ height: stickyImage.height * stickyImage.scale ++ ++ MouseArea { ++ id: mouse ++ anchors.fill: parent ++ drag.target: stickyPage ++ drag.axis: Drag.XandYAxis ++ drag.minimumY: 0 ++ drag.maximumY: page.height - 80 ++ drag.minimumX: 100 ++ drag.maximumX: page.width - 140 ++ onClicked: { myText.focus = true; myText.openSoftwareInputPanel(); } ++ } ++ } ++ } ++ ++ Image { ++ x: -width / 2; y: -height * 0.5 / 2 ++ source: "tack.png" ++ scale: 0.7; transformOrigin: Item.TopLeft ++ } ++ ++ states: State { ++ name: "pressed" ++ when: mouse.pressed ++ PropertyChanges { target: sticky; rotation: 8; scale: 1 } ++ PropertyChanges { target: page; z: 8 } ++ } ++ ++ transitions: Transition { ++ NumberAnimation { properties: "rotation,scale"; duration: 200 } ++ } ++ } ++ } ++ } ++} ++ ++ ++ ++ ++ ++ ++ ++ diff --cc examples/quick/touchinteraction/flickable/content/cork.jpg index 0000000,0000000..160bc00 new file mode 100644 Binary files differ diff --cc examples/quick/touchinteraction/flickable/content/note-yellow.png index 0000000,0000000..8ddecc8 new file mode 100644 Binary files differ diff --cc examples/quick/touchinteraction/flickable/content/tack.png index 0000000,0000000..cef2d1c new file mode 100644 Binary files differ diff --cc examples/quick/touchinteraction/flickable/corkboards.qml index 0000000,0000000..dc3aa6b new file mode 100644 --- /dev/null +++ b/examples/quick/touchinteraction/flickable/corkboards.qml @@@ -1,0 -1,0 +1,116 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++import "content" ++ ++Rectangle { ++ width: 800; height: 480 ++ color: "#464646" ++ ++ ListModel { ++ id: list ++ ++ ListElement { ++ name: "Sunday" ++ notes: [ ++ ListElement { noteText: "Lunch" }, ++ ListElement { noteText: "Birthday Party" } ++ ] ++ } ++ ++ ListElement { ++ name: "Monday" ++ notes: [ ++ ListElement { noteText: "Pickup kids from\nschool\n4.30pm" }, ++ ListElement { noteText: "Checkout Qt" }, ListElement { noteText: "Read email" } ++ ] ++ } ++ ++ ListElement { ++ name: "Tuesday" ++ notes: [ ++ ListElement { noteText: "Walk dog" }, ++ ListElement { noteText: "Buy newspaper" } ++ ] ++ } ++ ++ ListElement { ++ name: "Wednesday" ++ notes: [ ListElement { noteText: "Cook dinner" } ] ++ } ++ ++ ListElement { ++ name: "Thursday" ++ notes: [ ++ ListElement { noteText: "Meeting\n5.30pm" }, ++ ListElement { noteText: "Weed garden" } ++ ] ++ } ++ ++ ListElement { ++ name: "Friday" ++ notes: [ ++ ListElement { noteText: "More work" }, ++ ListElement { noteText: "Grocery shopping" } ++ ] ++ } ++ ++ ListElement { ++ name: "Saturday" ++ notes: [ ++ ListElement { noteText: "Drink" }, ++ ListElement { noteText: "Download Qt\nPlay with QML" } ++ ] ++ } ++ } ++ ++ ListView { ++ id: flickable ++ ++ anchors.fill: parent ++ focus: true ++ highlightRangeMode: ListView.StrictlyEnforceRange ++ orientation: ListView.Horizontal ++ snapMode: ListView.SnapOneItem ++ model: list ++ delegate: Day { } ++ } ++} diff --cc examples/quick/touchinteraction/multipointtouch/bearwhack.qml index 0000000,0000000..db46473 new file mode 100644 --- /dev/null +++ b/examples/quick/touchinteraction/multipointtouch/bearwhack.qml @@@ -1,0 -1,0 +1,133 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++import QtQuick 2.0 ++import QtQuick.Particles 2.0 ++import "content" ++ ++Item { ++ id: root ++ height: 640 ++ width: 320 ++ Item { ++ id: startScreen ++ anchors.fill: parent ++ z: 1000 ++ Image { ++ source: "content/title.png" ++ anchors.centerIn: parent ++ } ++ MouseArea{ ++ anchors.fill: parent ++ onClicked: {//Game Start ++ parent.visible = false; ++ } ++ } ++ } ++ Rectangle { ++ id: bg ++ anchors.fill: parent ++ gradient: Gradient { ++ GradientStop { position: 0.0; color: "DarkBlue" } ++ GradientStop { position: 0.8; color: "SkyBlue" } ++ GradientStop { position: 0.81; color: "ForestGreen" } ++ GradientStop { position: 1.0; color: "DarkGreen" } ++ } ++ } ++ ++ BearWhackParticleSystem { ++ id: particleSystem ++ anchors.fill: parent ++ running: !startScreen.visible ++ } ++ ++ property int score: 0 ++ ++ Text { ++ anchors.right: parent.right ++ anchors.margins: 4 ++ anchors.top: parent.top ++ color: "white" ++ function padded(num) { ++ var ret = num.toString(); ++ while (ret.length < 6) ++ ret = "0" + ret; ++ return ret; ++ } ++ text: "Score: " + padded(score) ++ } ++ MultiPointTouchArea { ++ anchors.fill: parent ++ touchPoints: [//Support up to 4 touches at once? ++ AugmentedTouchPoint{ system: particleSystem }, ++ AugmentedTouchPoint{ system: particleSystem }, ++ AugmentedTouchPoint{ system: particleSystem }, ++ AugmentedTouchPoint{ system: particleSystem } ++ ] ++ } ++ MouseArea{ ++ anchors.fill: parent ++ id: ma ++ onPressedChanged: { ++ if (pressed) { ++ timer.restart(); ++ sgoal.enabled = true; ++ particleSystem.explode(mouseX,mouseY); ++ } ++ } ++ Timer { ++ id: timer ++ interval: 100 ++ running: false ++ repeat: false ++ onTriggered: sgoal.enabled = false ++ } ++ SpriteGoal { ++ id: sgoal ++ x: ma.mouseX - 16 ++ y: ma.mouseY - 16 ++ width: 32 ++ height: 32 ++ system: particleSystem ++ parent: particleSystem ++ goalState: "falling" ++ enabled: false ++ } ++ } ++} diff --cc examples/quick/touchinteraction/multipointtouch/content/AugmentedTouchPoint.qml index 0000000,0000000..aede1a8 new file mode 100644 --- /dev/null +++ b/examples/quick/touchinteraction/multipointtouch/content/AugmentedTouchPoint.qml @@@ -1,0 -1,0 +1,70 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++import QtQuick 2.0 ++import QtQuick.Particles 2.0 ++ ++TouchPoint { ++ id: container ++ property ParticleSystem system ++ onPressedChanged: { ++ if (pressed) { ++ timer.restart(); ++ child.enabled = true; ++ system.explode(x,y); ++ } ++ } ++ property QtObject obj: Timer { ++ id: timer ++ interval: 100 ++ running: false ++ repeat: false ++ onTriggered: child.enabled = false ++ } ++ property Item child: SpriteGoal { ++ enabled: false ++ x: container.area.x - 16 ++ y: container.area.y - 16 ++ width: container.area.width + 32 ++ height: container.area.height + 32 //+32 so it doesn't have to hit the exact center ++ system: container.system ++ parent: container.system ++ goalState: "falling" ++ } ++} diff --cc examples/quick/touchinteraction/multipointtouch/content/Bear0.png index 0000000,0000000..64a02ce new file mode 100644 Binary files differ diff --cc examples/quick/touchinteraction/multipointtouch/content/Bear1.png index 0000000,0000000..3b88f3b new file mode 100644 Binary files differ diff --cc examples/quick/touchinteraction/multipointtouch/content/Bear2.png index 0000000,0000000..337b636 new file mode 100644 Binary files differ diff --cc examples/quick/touchinteraction/multipointtouch/content/Bear3.png index 0000000,0000000..f0e6859 new file mode 100644 Binary files differ diff --cc examples/quick/touchinteraction/multipointtouch/content/BearB.png index 0000000,0000000..c9a84ae new file mode 100644 Binary files differ diff --cc examples/quick/touchinteraction/multipointtouch/content/BearWhackParticleSystem.qml index 0000000,bed03e9..bed03e9 mode 000000,100644..100644 --- a/examples/quick/touchinteraction/multipointtouch/content/BearWhackParticleSystem.qml +++ b/examples/quick/touchinteraction/multipointtouch/content/BearWhackParticleSystem.qml diff --cc examples/quick/touchinteraction/multipointtouch/content/ParticleFlame.qml index 0000000,0000000..9788c5c new file mode 100644 --- /dev/null +++ b/examples/quick/touchinteraction/multipointtouch/content/ParticleFlame.qml @@@ -1,0 -1,0 +1,65 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++import QtQuick.Particles 2.0 ++ ++ParticleSystem { ++ property alias color: img.color ++ property alias emitting: emitter.enabled ++ ImageParticle { ++ id: img ++ source: "blur-circle.png" ++ colorVariation: 0.1 ++ color: "#ff521d" ++ alpha: 0 ++ } ++ Emitter { ++ id: emitter ++ speedFromMovement: 20 ++ emitRate: 80 ++ lifeSpan: 1500 ++ speed: PointDirection{ y: -90; yVariation: 50; } ++ acceleration: PointDirection{ xVariation: 100; yVariation: 90; } ++ size: 51 ++ sizeVariation: 53 ++ endSize: 64 ++ } ++} diff --cc examples/quick/touchinteraction/multipointtouch/content/blur-circle.png index 0000000,0000000..1b03cd0 new file mode 100644 Binary files differ diff --cc examples/quick/touchinteraction/multipointtouch/content/blur-circle3.png index 0000000,0000000..dbc39cb new file mode 100644 Binary files differ diff --cc examples/quick/touchinteraction/multipointtouch/content/heart-blur.png index 0000000,0000000..dbc3880 new file mode 100644 Binary files differ diff --cc examples/quick/touchinteraction/multipointtouch/content/title.png index 0000000,0000000..d630ea2 new file mode 100644 Binary files differ diff --cc examples/quick/touchinteraction/multipointtouch/multiflame.qml index 0000000,0000000..72a0ce2 new file mode 100644 --- /dev/null +++ b/examples/quick/touchinteraction/multipointtouch/multiflame.qml @@@ -1,0 -1,0 +1,91 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++import QtQuick 2.0 ++import "content" ++ ++Rectangle { ++ width: 360 ++ height: 480 ++ color: "black" ++ ++ MultiPointTouchArea { ++ anchors.fill: parent ++ minimumTouchPoints: 1 ++ maximumTouchPoints: 5 ++ touchPoints: [ ++ TouchPoint { id: touch1 }, ++ TouchPoint { id: touch2 }, ++ TouchPoint { id: touch11 }, ++ TouchPoint { id: touch21 }, ++ TouchPoint { id: touch31 } ++ ] ++ } ++ ++ ParticleFlame { ++ color: "red" ++ x: touch1.x ++ y: touch1.y ++ emitting: touch1.pressed ++ } ++ ParticleFlame { ++ color: "green" ++ x: touch2.x ++ y: touch2.y ++ emitting: touch2.pressed ++ } ++ ParticleFlame { ++ color: "yellow" ++ x: touch11.x ++ y: touch11.y ++ emitting: touch11.pressed ++ } ++ ParticleFlame { ++ color: "blue" ++ x: touch21.x ++ y: touch21.y ++ emitting: touch21.pressed ++ } ++ ParticleFlame { ++ color: "violet" ++ x: touch31.x ++ y: touch31.y ++ emitting: touch31.pressed ++ } ++} diff --cc examples/quick/touchinteraction/pincharea/flickresize.qml index 0000000,0000000..037766e new file mode 100644 --- /dev/null +++ b/examples/quick/touchinteraction/pincharea/flickresize.qml @@@ -1,0 -1,0 +1,97 @@@ ++/**************************************************************************** ++** ++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/ ++** ++** This file is part of the examples of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:BSD$ ++** You may use this file under the terms of the BSD license as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ++** the names of its contributors may be used to endorse or promote ++** products derived from this software without specific prior written ++** permission. ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2.0 ++ ++Rectangle { ++ width: 640 ++ height: 360 ++ color: "gray" ++ ++ Flickable { ++ id: flick ++ anchors.fill: parent ++ contentWidth: 500 ++ contentHeight: 500 ++ ++ PinchArea { ++ width: Math.max(flick.contentWidth, flick.width) ++ height: Math.max(flick.contentHeight, flick.height) ++ ++ property real initialWidth ++ property real initialHeight ++ onPinchStarted: { ++ initialWidth = flick.contentWidth ++ initialHeight = flick.contentHeight ++ } ++ ++ onPinchUpdated: { ++ // adjust content pos due to drag ++ flick.contentX += pinch.previousCenter.x - pinch.center.x ++ flick.contentY += pinch.previousCenter.y - pinch.center.y ++ ++ // resize content ++ flick.resizeContent(initialWidth * pinch.scale, initialHeight * pinch.scale, pinch.center) ++ } ++ ++ onPinchFinished: { ++ // Move its content within bounds. ++ flick.returnToBounds() ++ } ++ ++ Rectangle { ++ width: flick.contentWidth ++ height: flick.contentHeight ++ color: "white" ++ Image { ++ anchors.fill: parent ++ source: "qt-logo.jpg" ++ MouseArea { ++ anchors.fill: parent ++ onDoubleClicked: { ++ flick.contentWidth = 500 ++ flick.contentHeight = 500 ++ } ++ } ++ } ++ } ++ } ++ } ++} diff --cc examples/quick/touchinteraction/pincharea/qt-logo.jpg index 0000000,0000000..4014b46 new file mode 100644 Binary files differ diff --cc examples/quick/touchinteraction/touchinteraction.qml index 0000000,b4a930c..b4a930c mode 000000,100644..100644 --- a/examples/quick/touchinteraction/touchinteraction.qml +++ b/examples/quick/touchinteraction/touchinteraction.qml diff --cc examples/quick/touchinteraction/touchinteraction.qmlproject index 0000000,0000000..a9aa9d2 new file mode 100644 --- /dev/null +++ b/examples/quick/touchinteraction/touchinteraction.qmlproject @@@ -1,0 -1,0 +1,16 @@@ ++import QmlProject 1.1 ++ ++Project { ++ mainFile: "touchinteraction.qml" ++ ++ /* Include .qml, .js, and image files from current directory and subdirectories */ ++ QmlFiles { ++ directory: "." ++ } ++ JavaScriptFiles { ++ directory: "." ++ } ++ ImageFiles { ++ directory: "." ++ } ++} diff --cc examples/tutorials/extending/chapter1-basics/chapter1-basics.pro index 0000000,affc57c..8ed66f8 mode 000000,100644..100644 --- a/examples/tutorials/extending/chapter1-basics/chapter1-basics.pro +++ b/examples/tutorials/extending/chapter1-basics/chapter1-basics.pro @@@ -1,0 -1,5 +1,5 @@@ -QT += declarative quick ++QT += qml quick + + HEADERS += piechart.h + SOURCES += piechart.cpp \ + main.cpp diff --cc examples/tutorials/extending/chapter2-methods/chapter2-methods.pro index 0000000,affc57c..8ed66f8 mode 000000,100644..100644 --- a/examples/tutorials/extending/chapter2-methods/chapter2-methods.pro +++ b/examples/tutorials/extending/chapter2-methods/chapter2-methods.pro @@@ -1,0 -1,5 +1,5 @@@ -QT += declarative quick ++QT += qml quick + + HEADERS += piechart.h + SOURCES += piechart.cpp \ + main.cpp diff --cc examples/tutorials/extending/chapter3-bindings/chapter3-bindings.pro index 0000000,affc57c..8ed66f8 mode 000000,100644..100644 --- a/examples/tutorials/extending/chapter3-bindings/chapter3-bindings.pro +++ b/examples/tutorials/extending/chapter3-bindings/chapter3-bindings.pro @@@ -1,0 -1,5 +1,5 @@@ -QT += declarative quick ++QT += qml quick + + HEADERS += piechart.h + SOURCES += piechart.cpp \ + main.cpp diff --cc examples/tutorials/extending/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pro index 0000000,6724fa0..23eb222 mode 000000,100644..100644 --- a/examples/tutorials/extending/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pro +++ b/examples/tutorials/extending/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pro @@@ -1,0 -1,7 +1,7 @@@ -QT += declarative quick ++QT += qml quick + + HEADERS += piechart.h \ + pieslice.h + SOURCES += piechart.cpp \ + pieslice.cpp \ + main.cpp diff --cc examples/tutorials/extending/chapter5-listproperties/chapter5-listproperties.pro index 0000000,6724fa0..23eb222 mode 000000,100644..100644 --- a/examples/tutorials/extending/chapter5-listproperties/chapter5-listproperties.pro +++ b/examples/tutorials/extending/chapter5-listproperties/chapter5-listproperties.pro @@@ -1,0 -1,7 +1,7 @@@ -QT += declarative quick ++QT += qml quick + + HEADERS += piechart.h \ + pieslice.h + SOURCES += piechart.cpp \ + pieslice.cpp \ + main.cpp diff --cc examples/tutorials/extending/chapter5-listproperties/piechart.cpp index 0000000,bfcb607..9109165 mode 000000,100644..100644 --- a/examples/tutorials/extending/chapter5-listproperties/piechart.cpp +++ b/examples/tutorials/extending/chapter5-listproperties/piechart.cpp @@@ -1,0 -1,72 +1,72 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** + ** This file is part of the documentation of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:BSD$ + ** You may use this file under the terms of the BSD license as follows: + ** + ** "Redistribution and use in source and binary forms, with or without + ** modification, are permitted provided that the following conditions are + ** met: + ** * Redistributions of source code must retain the above copyright + ** notice, this list of conditions and the following disclaimer. + ** * Redistributions in binary form must reproduce the above copyright + ** notice, this list of conditions and the following disclaimer in + ** the documentation and/or other materials provided with the + ** distribution. + ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor + ** the names of its contributors may be used to endorse or promote + ** products derived from this software without specific prior written + ** permission. + ** + ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + #include "piechart.h" + #include "pieslice.h" + + PieChart::PieChart(QQuickItem *parent) + : QQuickItem(parent) + { + } + + QString PieChart::name() const + { + return m_name; + } + + void PieChart::setName(const QString &name) + { + m_name = name; + } + + //![0] -QDeclarativeListProperty PieChart::slices() ++QQmlListProperty PieChart::slices() + { - return QDeclarativeListProperty(this, 0, &PieChart::append_slice); ++ return QQmlListProperty(this, 0, &PieChart::append_slice); + } + -void PieChart::append_slice(QDeclarativeListProperty *list, PieSlice *slice) ++void PieChart::append_slice(QQmlListProperty *list, PieSlice *slice) + { + PieChart *chart = qobject_cast(list->object); + if (chart) { + slice->setParentItem(chart); + chart->m_slices.append(slice); + } + } + //![0] diff --cc examples/tutorials/extending/chapter5-listproperties/piechart.h index 0000000,9beabda..6c17bc1 mode 000000,100644..100644 --- a/examples/tutorials/extending/chapter5-listproperties/piechart.h +++ b/examples/tutorials/extending/chapter5-listproperties/piechart.h @@@ -1,0 -1,75 +1,75 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** + ** This file is part of the documentation of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:BSD$ + ** You may use this file under the terms of the BSD license as follows: + ** + ** "Redistribution and use in source and binary forms, with or without + ** modification, are permitted provided that the following conditions are + ** met: + ** * Redistributions of source code must retain the above copyright + ** notice, this list of conditions and the following disclaimer. + ** * Redistributions in binary form must reproduce the above copyright + ** notice, this list of conditions and the following disclaimer in + ** the documentation and/or other materials provided with the + ** distribution. + ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor + ** the names of its contributors may be used to endorse or promote + ** products derived from this software without specific prior written + ** permission. + ** + ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + #ifndef PIECHART_H + #define PIECHART_H + + #include + + class PieSlice; + + //![0] + class PieChart : public QQuickItem + { + Q_OBJECT - Q_PROPERTY(QDeclarativeListProperty slices READ slices) ++ Q_PROPERTY(QQmlListProperty slices READ slices) + //![0] + Q_PROPERTY(QString name READ name WRITE setName) + + //![1] + public: + //![1] + PieChart(QQuickItem *parent = 0); + + QString name() const; + void setName(const QString &name); + + //![2] - QDeclarativeListProperty slices(); ++ QQmlListProperty slices(); + + private: - static void append_slice(QDeclarativeListProperty *list, PieSlice *slice); ++ static void append_slice(QQmlListProperty *list, PieSlice *slice); + + QString m_name; + QList m_slices; + }; + //![2] + + #endif + diff --cc examples/tutorials/extending/chapter6-plugins/chapter6-plugins.pro index 0000000,c243ec4..75f88b2 mode 000000,100644..100644 --- a/examples/tutorials/extending/chapter6-plugins/chapter6-plugins.pro +++ b/examples/tutorials/extending/chapter6-plugins/chapter6-plugins.pro @@@ -1,0 -1,18 +1,18 @@@ + TEMPLATE = lib + CONFIG += qt plugin -QT += declarative quick ++QT += qml quick + + DESTDIR = ChartsPlugin + TARGET = chartsplugin + + OBJECTS_DIR = tmp + MOC_DIR = tmp + + HEADERS += piechart.h \ + pieslice.h \ + chartsplugin.h + + SOURCES += piechart.cpp \ + pieslice.cpp \ + chartsplugin.cpp + diff --cc examples/tutorials/extending/chapter6-plugins/chartsplugin.cpp index 0000000,d75f810..0cead52 mode 000000,100644..100644 --- a/examples/tutorials/extending/chapter6-plugins/chartsplugin.cpp +++ b/examples/tutorials/extending/chapter6-plugins/chartsplugin.cpp @@@ -1,0 -1,53 +1,53 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** + ** This file is part of the documentation of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:BSD$ + ** You may use this file under the terms of the BSD license as follows: + ** + ** "Redistribution and use in source and binary forms, with or without + ** modification, are permitted provided that the following conditions are + ** met: + ** * Redistributions of source code must retain the above copyright + ** notice, this list of conditions and the following disclaimer. + ** * Redistributions in binary form must reproduce the above copyright + ** notice, this list of conditions and the following disclaimer in + ** the documentation and/or other materials provided with the + ** distribution. + ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor + ** the names of its contributors may be used to endorse or promote + ** products derived from this software without specific prior written + ** permission. + ** + ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + #include "chartsplugin.h" + //![0] + #include "piechart.h" + #include "pieslice.h" -#include ++#include + + void ChartsPlugin::registerTypes(const char *uri) + { + qmlRegisterType(uri, 1, 0, "PieChart"); + qmlRegisterType(uri, 1, 0, "PieSlice"); + } + + //![0] + diff --cc examples/tutorials/extending/chapter6-plugins/chartsplugin.h index 0000000,863564b..4db1b01 mode 000000,100644..100644 --- a/examples/tutorials/extending/chapter6-plugins/chartsplugin.h +++ b/examples/tutorials/extending/chapter6-plugins/chartsplugin.h @@@ -1,0 -1,57 +1,57 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** + ** This file is part of the documentation of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:BSD$ + ** You may use this file under the terms of the BSD license as follows: + ** + ** "Redistribution and use in source and binary forms, with or without + ** modification, are permitted provided that the following conditions are + ** met: + ** * Redistributions of source code must retain the above copyright + ** notice, this list of conditions and the following disclaimer. + ** * Redistributions in binary form must reproduce the above copyright + ** notice, this list of conditions and the following disclaimer in + ** the documentation and/or other materials provided with the + ** distribution. + ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor + ** the names of its contributors may be used to endorse or promote + ** products derived from this software without specific prior written + ** permission. + ** + ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + #ifndef CHARTSPLUGIN_H + #define CHARTSPLUGIN_H + + //![0] -#include ++#include + -class ChartsPlugin : public QDeclarativeExtensionPlugin ++class ChartsPlugin : public QQmlExtensionPlugin + { + Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDeclarativeExtensionInterface" FILE "chartsplugin.json") ++ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "chartsplugin.json") + + public: + void registerTypes(const char *uri); + }; + //![0] + + #endif + diff --cc examples/tutorials/extending/chapter6-plugins/piechart.cpp index 0000000,2a8f402..b188e39 mode 000000,100644..100644 --- a/examples/tutorials/extending/chapter6-plugins/piechart.cpp +++ b/examples/tutorials/extending/chapter6-plugins/piechart.cpp @@@ -1,0 -1,71 +1,71 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** + ** This file is part of the documentation of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:BSD$ + ** You may use this file under the terms of the BSD license as follows: + ** + ** "Redistribution and use in source and binary forms, with or without + ** modification, are permitted provided that the following conditions are + ** met: + ** * Redistributions of source code must retain the above copyright + ** notice, this list of conditions and the following disclaimer. + ** * Redistributions in binary form must reproduce the above copyright + ** notice, this list of conditions and the following disclaimer in + ** the documentation and/or other materials provided with the + ** distribution. + ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor + ** the names of its contributors may be used to endorse or promote + ** products derived from this software without specific prior written + ** permission. + ** + ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + #include "piechart.h" + #include "pieslice.h" + + PieChart::PieChart(QQuickItem *parent) + : QQuickItem(parent) + { + } + + QString PieChart::name() const + { + return m_name; + } + + void PieChart::setName(const QString &name) + { + m_name = name; + } + -QDeclarativeListProperty PieChart::slices() ++QQmlListProperty PieChart::slices() + { - return QDeclarativeListProperty(this, 0, &PieChart::append_slice); ++ return QQmlListProperty(this, 0, &PieChart::append_slice); + } + -void PieChart::append_slice(QDeclarativeListProperty *list, PieSlice *slice) ++void PieChart::append_slice(QQmlListProperty *list, PieSlice *slice) + { + PieChart *chart = qobject_cast(list->object); + if (chart) { + slice->setParentItem(chart); + chart->m_slices.append(slice); + } + } + diff --cc examples/tutorials/extending/chapter6-plugins/piechart.h index 0000000,fe6b96a..2ee8108 mode 000000,100644..100644 --- a/examples/tutorials/extending/chapter6-plugins/piechart.h +++ b/examples/tutorials/extending/chapter6-plugins/piechart.h @@@ -1,0 -1,69 +1,69 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** + ** This file is part of the documentation of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:BSD$ + ** You may use this file under the terms of the BSD license as follows: + ** + ** "Redistribution and use in source and binary forms, with or without + ** modification, are permitted provided that the following conditions are + ** met: + ** * Redistributions of source code must retain the above copyright + ** notice, this list of conditions and the following disclaimer. + ** * Redistributions in binary form must reproduce the above copyright + ** notice, this list of conditions and the following disclaimer in + ** the documentation and/or other materials provided with the + ** distribution. + ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor + ** the names of its contributors may be used to endorse or promote + ** products derived from this software without specific prior written + ** permission. + ** + ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + #ifndef PIECHART_H + #define PIECHART_H + + #include + + class PieSlice; + + class PieChart : public QQuickItem + { + Q_OBJECT - Q_PROPERTY(QDeclarativeListProperty slices READ slices) ++ Q_PROPERTY(QQmlListProperty slices READ slices) + Q_PROPERTY(QString name READ name WRITE setName) + + public: + PieChart(QQuickItem *parent = 0); + + QString name() const; + void setName(const QString &name); + - QDeclarativeListProperty slices(); ++ QQmlListProperty slices(); + + private: - static void append_slice(QDeclarativeListProperty *list, PieSlice *slice); ++ static void append_slice(QQmlListProperty *list, PieSlice *slice); + + QString m_name; + QList m_slices; + }; + + #endif + diff --cc examples/tutorials/gettingStartedQml/filedialog/dialogPlugin.h index 1aed6ab,7ad707f..fcaa210 --- a/examples/tutorials/gettingStartedQml/filedialog/dialogPlugin.h +++ b/examples/tutorials/gettingStartedQml/filedialog/dialogPlugin.h @@@ -41,14 -41,15 +41,15 @@@ #ifndef DIALOGPLUGIN_H #define DIALOGPLUGIN_H -#include +#include -class DialogPlugin : public QDeclarativeExtensionPlugin +class DialogPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDeclarativeExtensionInterface" FILE "dialogplugin.json") ++ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "dialogplugin.json") public: - //registerTypes is inherited from QDeclarativeExtensionPlugin + //registerTypes is inherited from QQmlExtensionPlugin void registerTypes(const char *uri); }; diff --cc examples/window/window.cpp index 0000000,4854256..2112ab8 mode 000000,100644..100644 --- a/examples/window/window.cpp +++ b/examples/window/window.cpp @@@ -1,0 -1,58 +1,58 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** + ** This file is part of the examples of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:BSD$ + ** You may use this file under the terms of the BSD license as follows: + ** + ** "Redistribution and use in source and binary forms, with or without + ** modification, are permitted provided that the following conditions are + ** met: + ** * Redistributions of source code must retain the above copyright + ** notice, this list of conditions and the following disclaimer. + ** * Redistributions in binary form must reproduce the above copyright + ** notice, this list of conditions and the following disclaimer in + ** the documentation and/or other materials provided with the + ** distribution. + ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor + ** the names of its contributors may be used to endorse or promote + ** products derived from this software without specific prior written + ** permission. + ** + ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + #include -#include -#include ++#include ++#include + #include + #include + + int main(int argc, char* argv[]) + { + QGuiApplication app(argc, argv); - QDeclarativeEngine engine; - QDeclarativeComponent component(&engine); ++ QQmlEngine engine; ++ QQmlComponent component(&engine); + component.loadUrl(QUrl::fromLocalFile("Window.qml")); + if ( component.isReady() ) + component.create(); + else + qWarning() << component.errorString(); + return app.exec(); + } diff --cc examples/window/window.pro index 0000000,74804bd..c451841 mode 000000,100644..100644 --- a/examples/window/window.pro +++ b/examples/window/window.pro @@@ -1,0 -1,5 +1,5 @@@ + TEMPLATE = app + CONFIG += qt -QT += declarative ++QT += qml + + SOURCES += window.cpp diff --cc src/imports/folderlistmodel/folderlistmodel.pro index b4cfcea,9727b51..592d837 --- a/src/imports/folderlistmodel/folderlistmodel.pro +++ b/src/imports/folderlistmodel/folderlistmodel.pro @@@ -2,12 -2,15 +2,15 @@@ TARGET = qmlfolderlistmodelplugi TARGETPATH = Qt/labs/folderlistmodel include(../qimportbase.pri) - QT += widgets qml -QT += declarative ++QT += qml - SOURCES += qquickfolderlistmodel.cpp plugin.cpp - HEADERS += qquickfolderlistmodel.h -SOURCES += qdeclarativefolderlistmodel.cpp plugin.cpp \ ++SOURCES += qquickfolderlistmodel.cpp plugin.cpp \ + fileinfothread.cpp -HEADERS += qdeclarativefolderlistmodel.h \ ++HEADERS += qquickfolderlistmodel.h \ + fileproperty_p.h \ + fileinfothread_p.h -DESTDIR = $$QT.declarative.imports/$$TARGETPATH +DESTDIR = $$QT.qml.imports/$$TARGETPATH target.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH qmldir.files += $$PWD/qmldir diff --cc src/imports/folderlistmodel/plugin.cpp index 78fc230,767f8f6..bc90451 --- a/src/imports/folderlistmodel/plugin.cpp +++ b/src/imports/folderlistmodel/plugin.cpp @@@ -47,9 -47,11 +47,11 @@@ QT_BEGIN_NAMESPACE //![class decl] -class QmlFolderListModelPlugin : public QDeclarativeExtensionPlugin +class QmlFolderListModelPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDeclarativeExtensionInterface" FILE "folderlistmodel.json") ++ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "folderlistmodel.json") + public: virtual void registerTypes(const char *uri) { diff --cc src/imports/folderlistmodel/qquickfolderlistmodel.cpp index 5621622,0000000..d68d7af mode 100644,000000..100644 --- a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp +++ b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp @@@ -1,529 -1,0 +1,697 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//![code] +#include "qquickfolderlistmodel.h" - #include ++#include "fileinfothread_p.h" ++#include "fileproperty_p.h" +#include +#include + - #ifndef QT_NO_DIRMODEL - +QT_BEGIN_NAMESPACE + +class QQuickFolderListModelPrivate +{ ++ Q_DECLARE_PUBLIC(QQuickFolderListModel) ++ +public: - QQuickFolderListModelPrivate() - : sortField(QQuickFolderListModel::Name), sortReversed(false), count(0), showDirs(true), showDots(false), showOnlyReadable(false), insideRefresh(false) { ++ QQuickFolderListModelPrivate(QQuickFolderListModel *q) ++ : q_ptr(q), ++ sortField(QQuickFolderListModel::Name), sortReversed(false), showDirs(true), showDirsFirst(false), showDots(false), showOnlyReadable(false) ++ { + nameFilters << QLatin1String("*"); + } + - void updateSorting() { - QDir::SortFlags flags = 0; - switch(sortField) { ++ ++ QQuickFolderListModel *q_ptr; ++ QUrl currentDir; ++ QUrl rootDir; ++ FileInfoThread fileInfoThread; ++ QList data; ++ QHash roleNames; ++ QQuickFolderListModel::SortField sortField; ++ QStringList nameFilters; ++ bool sortReversed; ++ bool showDirs; ++ bool showDirsFirst; ++ bool showDots; ++ bool showOnlyReadable; ++ ++ ~QQuickFolderListModelPrivate() {} ++ void init(); ++ void updateSorting(); ++ ++ // private slots ++ void _q_directoryChanged(const QString &directory, const QList &list); ++ void _q_directoryUpdated(const QString &directory, const QList &list, int fromIndex, int toIndex); ++ void _q_sortFinished(const QList &list); ++}; ++ ++ ++void QQuickFolderListModelPrivate::init() ++{ ++ Q_Q(QQuickFolderListModel); ++ qRegisterMetaType >("QList"); ++ q->connect(&fileInfoThread, SIGNAL(directoryChanged(QString, QList)), ++ q, SLOT(_q_directoryChanged(QString, QList))); ++ q->connect(&fileInfoThread, SIGNAL(directoryUpdated(QString, QList, int, int)), ++ q, SLOT(_q_directoryUpdated(QString, QList, int, int))); ++ q->connect(&fileInfoThread, SIGNAL(sortFinished(QList)), ++ q, SLOT(_q_sortFinished(QList))); ++} ++ ++ ++void QQuickFolderListModelPrivate::updateSorting() ++{ ++ Q_Q(QQuickFolderListModel); ++ ++ QDir::SortFlags flags = 0; ++ ++ switch (sortField) { + case QQuickFolderListModel::Unsorted: + flags |= QDir::Unsorted; + break; + case QQuickFolderListModel::Name: + flags |= QDir::Name; + break; + case QQuickFolderListModel::Time: + flags |= QDir::Time; + break; + case QQuickFolderListModel::Size: + flags |= QDir::Size; + break; + case QQuickFolderListModel::Type: + flags |= QDir::Type; + break; - } ++ default: ++ break; ++ } ++ ++ emit q->layoutAboutToBeChanged(); ++ ++ if (sortReversed) ++ flags |= QDir::Reversed; ++ ++ fileInfoThread.setSortFlags(flags); ++} ++ ++void QQuickFolderListModelPrivate::_q_directoryChanged(const QString &directory, const QList &list) ++{ ++ Q_Q(QQuickFolderListModel); ++ Q_UNUSED(directory); ++ ++ data = list; ++ q->endResetModel(); ++ emit q->rowCountChanged(); ++ emit q->folderChanged(); ++} + - if (sortReversed) - flags |= QDir::Reversed; + - model.setSorting(flags); ++void QQuickFolderListModelPrivate::_q_directoryUpdated(const QString &directory, const QList &list, int fromIndex, int toIndex) ++{ ++ Q_Q(QQuickFolderListModel); ++ Q_UNUSED(directory); ++ ++ QModelIndex parent; ++ if (data.size() > list.size()) { ++ //File(s) removed. Since I do not know how many ++ //or where I need to update the whole list from the first item. ++ data = list; ++ q->beginRemoveRows(parent, fromIndex, toIndex); ++ q->endRemoveRows(); ++ q->beginInsertRows(parent, fromIndex, list.size()-1); ++ q->endInsertRows(); ++ emit q->rowCountChanged(); ++ } else if (data.size() < list.size()) { ++ //qDebug() << "File added. FromIndex: " << fromIndex << " toIndex: " << toIndex << " list size: " << list.size(); ++ //File(s) added. Calculate how many and insert ++ //from the first changed one. ++ toIndex = fromIndex + (list.size() - data.size()-1); ++ q->beginInsertRows(parent, fromIndex, toIndex); ++ q->endInsertRows(); ++ data = list; ++ emit q->rowCountChanged(); ++ QModelIndex modelIndexFrom = q->createIndex(fromIndex, 0); ++ QModelIndex modelIndexTo = q->createIndex(toIndex, 0); ++ emit q->dataChanged(modelIndexFrom, modelIndexTo); ++ } else { ++ //qDebug() << "File has been updated"; ++ QModelIndex modelIndexFrom = q->createIndex(fromIndex, 0); ++ QModelIndex modelIndexTo = q->createIndex(toIndex, 0); ++ data = list; ++ emit q->dataChanged(modelIndexFrom, modelIndexTo); + } ++} ++ ++void QQuickFolderListModelPrivate::_q_sortFinished(const QList &list) ++{ ++ Q_Q(QQuickFolderListModel); ++ ++ QModelIndex parent; ++ q->beginRemoveRows(parent, 0, data.size()-1); ++ data.clear(); ++ q->endRemoveRows(); ++ ++ q->beginInsertRows(parent, 0, list.size()-1); ++ data = list; ++ q->endInsertRows(); ++} + - QDirModel model; - QUrl folder; - QStringList nameFilters; - QModelIndex folderIndex; - QQuickFolderListModel::SortField sortField; - bool sortReversed; - int count; - bool showDirs; - bool showDots; - bool showOnlyReadable; - bool insideRefresh; - }; + +/*! + \qmlclass FolderListModel QQuickFolderListModel + \ingroup qml-working-with-data + \brief The FolderListModel provides a model of the contents of a file system folder. + + FolderListModel provides access to information about the contents of a folder + in the local file system, exposing a list of files to views and other data components. + + \note This type is made available by importing the \c Qt.labs.folderlistmodel module. + \e{Elements in the Qt.labs module are not guaranteed to remain compatible + in future versions.} + + \bold{import Qt.labs.folderlistmodel 1.0} + + The \l folder property specifies the folder to access. Information about the + files and directories in the folder is supplied via the model's interface. + Components access names and paths via the following roles: + + \list - \o fileName - \o filePath ++ \o \c fileName ++ \o \c filePath ++ \o \c fileBaseName ++ \o \c fileSuffix ++ \o \c fileSize ++ \o \c fileModified ++ \o \c fileAccessed ++ \o \c fileIsDir + \endlist + + Additionally a file entry can be differentiated from a folder entry via the + isFolder() method. + + \section1 Filtering + + Various properties can be set to filter the number of files and directories + exposed by the model. + + The \l nameFilters property can be set to contain a list of wildcard filters + that are applied to names of files and directories, causing only those that + match the filters to be exposed. + + Directories can be included or excluded using the \l showDirs property, and + navigation directories can also be excluded by setting the \l showDotAndDotDot + property to false. + + It is sometimes useful to limit the files and directories exposed to those + that the user can access. The \l showOnlyReadable property can be set to + enable this feature. + + \section1 Example Usage + + The following example shows a FolderListModel being used to provide a list + of QML files in a \l ListView: + + \snippet doc/src/snippets/qml/folderlistmodel.qml 0 + + \section1 Path Separators + + Qt uses "/" as a universal directory separator in the same way that "/" is + used as a path separator in URLs. If you always use "/" as a directory + separator, Qt will translate your paths to conform to the underlying + operating system. + + \sa {QML Data Models} +*/ + +QQuickFolderListModel::QQuickFolderListModel(QObject *parent) - : QAbstractListModel(parent) ++ : QAbstractListModel(parent), d_ptr(new QQuickFolderListModelPrivate(this)) +{ - QHash roles; - roles[FileNameRole] = "fileName"; - roles[FilePathRole] = "filePath"; - setRoleNames(roles); - - d = new QQuickFolderListModelPrivate; - d->model.setFilter(QDir::AllDirs | QDir::Files | QDir::Drives | QDir::NoDotAndDotDot); - connect(&d->model, SIGNAL(rowsInserted(const QModelIndex&,int,int)) - , this, SLOT(inserted(const QModelIndex&,int,int))); - connect(&d->model, SIGNAL(rowsRemoved(const QModelIndex&,int,int)) - , this, SLOT(removed(const QModelIndex&,int,int))); - connect(&d->model, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)) - , this, SLOT(handleDataChanged(const QModelIndex&,const QModelIndex&))); - connect(&d->model, SIGNAL(modelReset()), this, SLOT(refresh())); - connect(&d->model, SIGNAL(layoutChanged()), this, SLOT(refresh())); ++ Q_D(QQuickFolderListModel); ++ d->roleNames[FileNameRole] = "fileName"; ++ d->roleNames[FilePathRole] = "filePath"; ++ d->roleNames[FileBaseNameRole] = "fileBaseName"; ++ d->roleNames[FileSuffixRole] = "fileSuffix"; ++ d->roleNames[FileSizeRole] = "fileSize"; ++ d->roleNames[FileLastModifiedRole] = "fileModified"; ++ d->roleNames[FileLastReadRole] = "fileAccessed"; ++ d->roleNames[FileIsDirRole] = "fileIsDir"; ++ setRoleNames(d->roleNames); ++ ++ d->init(); +} + +QQuickFolderListModel::~QQuickFolderListModel() +{ - delete d; +} + +QVariant QQuickFolderListModel::data(const QModelIndex &index, int role) const +{ ++ Q_D(const QQuickFolderListModel); + QVariant rv; - QModelIndex modelIndex = d->model.index(index.row(), 0, d->folderIndex); - if (modelIndex.isValid()) { - if (role == FileNameRole) - rv = d->model.data(modelIndex, QDirModel::FileNameRole).toString(); - else if (role == FilePathRole) - rv = QUrl::fromLocalFile(d->model.data(modelIndex, QDirModel::FilePathRole).toString()); ++ ++ if (index.row() >= d->data.size()) ++ return rv; ++ ++ switch (role) ++ { ++ case FileNameRole: ++ rv = d->data.at(index.row()).fileName(); ++ break; ++ case FilePathRole: ++ rv = d->data.at(index.row()).filePath(); ++ break; ++ case FileBaseNameRole: ++ rv = d->data.at(index.row()).baseName(); ++ break; ++ case FileSuffixRole: ++ rv = d->data.at(index.row()).suffix(); ++ break; ++ case FileSizeRole: ++ rv = d->data.at(index.row()).size(); ++ break; ++ case FileLastModifiedRole: ++ rv = d->data.at(index.row()).lastModified().date().toString(Qt::ISODate) + " " + d->data.at(index.row()).lastModified().time().toString(); ++ break; ++ case FileLastReadRole: ++ rv = d->data.at(index.row()).lastRead().date().toString(Qt::ISODate) + " " + d->data.at(index.row()).lastRead().time().toString(); ++ break; ++ case FileIsDirRole: ++ rv = d->data.at(index.row()).isDir(); ++ break; ++ default: ++ break; + } + return rv; +} + +/*! + \qmlproperty int FolderListModel::count + + Returns the number of items in the current folder that match the + filter criteria. +*/ +int QQuickFolderListModel::rowCount(const QModelIndex &parent) const +{ ++ Q_D(const QQuickFolderListModel); + Q_UNUSED(parent); - return d->count; ++ return d->data.size(); ++} ++ ++QModelIndex QQuickFolderListModel::index(int row, int , const QModelIndex &) const ++{ ++ return createIndex(row, 0); +} + +/*! + \qmlproperty string FolderListModel::folder + + The \a folder property holds a URL for the folder that the model is + currently providing. + + The value is a URL expressed as a string, and must be a \c file: or \c qrc: + URL, or a relative URL. + + By default, the value is an invalid URL. +*/ +QUrl QQuickFolderListModel::folder() const +{ - return d->folder; ++ Q_D(const QQuickFolderListModel); ++ return d->currentDir; +} + +void QQuickFolderListModel::setFolder(const QUrl &folder) +{ - if (folder == d->folder) ++ Q_D(QQuickFolderListModel); ++ ++ if (folder == d->currentDir) + return; + - QModelIndex index = d->model.index(folder.toLocalFile()); // This can modify the filtering rules. - if ((index.isValid() && d->model.isDir(index)) || folder.toLocalFile().isEmpty()) { - d->folder = folder; - QMetaObject::invokeMethod(this, "resetFiltering", Qt::QueuedConnection); // resetFiltering will invoke refresh(). - emit folderChanged(); ++ QString resolvedPath = QDir::cleanPath(folder.path()); ++ ++ beginResetModel(); ++ ++ //Remove the old path for the file system watcher ++ if (!d->currentDir.isEmpty()) ++ d->fileInfoThread.removePath(d->currentDir.path()); ++ ++ d->currentDir = folder; ++ ++ QFileInfo info(resolvedPath); ++ if (!info.exists() || !info.isDir()) { ++ d->data.clear(); ++ endResetModel(); ++ emit rowCountChanged(); ++ return; + } ++ ++ d->fileInfoThread.setPath(resolvedPath); ++} ++ ++ ++/*! ++ \qmlproperty string QQuickFolderListModel::rootFolder ++ ++ When the rootFolder is set, then this folder will ++ be threated as the root in the file system, so that ++ you can only travers sub folders from this rootFolder. ++*/ ++QUrl QQuickFolderListModel::rootFolder() const ++{ ++ Q_D(const QQuickFolderListModel); ++ return d->rootDir; +} + - void QQuickFolderListModel::resetFiltering() ++void QQuickFolderListModel::setRootFolder(const QUrl &path) +{ - // ensure that we reset the filtering rules, because the QDirModel::index() - // function isn't quite as const as it claims to be. - QDir::Filters filt = d->model.filter(); ++ Q_D(QQuickFolderListModel); + - if (d->showDirs) - filt |= (QDir::AllDirs | QDir::Drives); - else - filt &= ~(QDir::AllDirs | QDir::Drives); ++ if (path.isEmpty()) ++ return; + - if (d->showDots) - filt &= ~QDir::NoDotAndDotDot; - else - filt |= QDir::NoDotAndDotDot; ++ QString resolvedPath = QDir::cleanPath(path.path()); + - if (d->showOnlyReadable) - filt |= QDir::Readable; - else - filt &= ~QDir::Readable; ++ QFileInfo info(resolvedPath); ++ if (!info.exists() || !info.isDir()) ++ return; + - d->model.setFilter(filt); // this causes a refresh(). ++ d->fileInfoThread.setRootPath(resolvedPath); ++ d->rootDir = path; +} + ++ +/*! + \qmlproperty url FolderListModel::parentFolder + + Returns the URL of the parent of of the current \l folder. +*/ +QUrl QQuickFolderListModel::parentFolder() const +{ - QString localFile = d->folder.toLocalFile(); ++ Q_D(const QQuickFolderListModel); ++ ++ QString localFile = d->currentDir.toLocalFile(); + if (!localFile.isEmpty()) { + QDir dir(localFile); +#if defined(Q_OS_WIN) + if (dir.isRoot()) + dir.setPath(""); + else +#endif + dir.cdUp(); + localFile = dir.path(); + } else { - int pos = d->folder.path().lastIndexOf(QLatin1Char('/')); ++ int pos = d->currentDir.path().lastIndexOf(QLatin1Char('/')); + if (pos == -1) + return QUrl(); - localFile = d->folder.path().left(pos); ++ localFile = d->currentDir.path().left(pos); + } + return QUrl::fromLocalFile(localFile); +} + +/*! + \qmlproperty list FolderListModel::nameFilters + + The \a nameFilters property contains a list of file name filters. + The filters may include the ? and * wildcards. + + The example below filters on PNG and JPEG files: + + \qml + FolderListModel { + nameFilters: [ "*.png", "*.jpg" ] + } + \endqml + + \note Directories are not excluded by filters. +*/ +QStringList QQuickFolderListModel::nameFilters() const +{ ++ Q_D(const QQuickFolderListModel); + return d->nameFilters; +} + +void QQuickFolderListModel::setNameFilters(const QStringList &filters) +{ ++ Q_D(QQuickFolderListModel); ++ d->fileInfoThread.setNameFilters(filters); + d->nameFilters = filters; - d->model.setNameFilters(d->nameFilters); +} + +void QQuickFolderListModel::classBegin() +{ +} + +void QQuickFolderListModel::componentComplete() +{ - if (!d->folder.isValid() || d->folder.toLocalFile().isEmpty() || !QDir().exists(d->folder.toLocalFile())) - setFolder(QUrl(QLatin1String("file://")+QDir::currentPath())); ++ Q_D(QQuickFolderListModel); + - if (!d->folderIndex.isValid()) - QMetaObject::invokeMethod(this, "refresh", Qt::QueuedConnection); ++ if (!d->currentDir.isValid() || d->currentDir.toLocalFile().isEmpty() || !QDir().exists(d->currentDir.toLocalFile())) ++ setFolder(QUrl(QLatin1String("file://")+QDir::currentPath())); +} + +/*! + \qmlproperty enumeration FolderListModel::sortField + + The \a sortField property contains field to use for sorting. sortField + may be one of: + \list - \o Unsorted - no sorting is applied. The order is system default. ++ \o Unsorted - no sorting is applied. + \o Name - sort by filename - \o Time - sort by time modified ++ \o LastModified - sort by time modified + \o Size - sort by file size + \o Type - sort by file type (extension) + \endlist + + \sa sortReversed +*/ +QQuickFolderListModel::SortField QQuickFolderListModel::sortField() const +{ ++ Q_D(const QQuickFolderListModel); + return d->sortField; +} + +void QQuickFolderListModel::setSortField(SortField field) +{ ++ Q_D(QQuickFolderListModel); + if (field != d->sortField) { + d->sortField = field; + d->updateSorting(); + } +} + ++int QQuickFolderListModel::roleFromString(const QString &roleName) const ++{ ++ Q_D(const QQuickFolderListModel); ++ return d->roleNames.key(roleName.toLatin1(), -1); ++} ++ +/*! + \qmlproperty bool FolderListModel::sortReversed + + If set to true, reverses the sort order. The default is false. + + \sa sortField +*/ +bool QQuickFolderListModel::sortReversed() const +{ ++ Q_D(const QQuickFolderListModel); + return d->sortReversed; +} + +void QQuickFolderListModel::setSortReversed(bool rev) +{ ++ Q_D(QQuickFolderListModel); ++ + if (rev != d->sortReversed) { + d->sortReversed = rev; + d->updateSorting(); + } +} + +/*! + \qmlmethod bool FolderListModel::isFolder(int index) + + Returns true if the entry \a index is a folder; otherwise + returns false. +*/ +bool QQuickFolderListModel::isFolder(int index) const +{ + if (index != -1) { - QModelIndex idx = d->model.index(index, 0, d->folderIndex); - if (idx.isValid()) - return d->model.isDir(idx); ++ QModelIndex idx = createIndex(index, 0); ++ if (idx.isValid()) { ++ QVariant var = data(idx, FileIsDirRole); ++ if (var.isValid()) ++ return var.toBool(); ++ } + } + return false; +} + - void QQuickFolderListModel::refresh() - { - if (d->insideRefresh) - return; - d->insideRefresh = true; ++/*! ++ \qmlproperty bool FolderListModel::showDirs + - d->folderIndex = QModelIndex(); - if (d->count) { - emit beginRemoveRows(QModelIndex(), 0, d->count-1); - d->count = 0; - emit endRemoveRows(); - } ++ If true, directories are included in the model; otherwise only files ++ are included. + - d->folderIndex = d->model.index(d->folder.toLocalFile()); - int newcount = d->model.rowCount(d->folderIndex); - if (newcount) { - emit beginInsertRows(QModelIndex(), 0, newcount-1); - d->count = newcount; - emit endInsertRows(); - } ++ By default, this property is true. + - d->insideRefresh = false; // finished refreshing. - } ++ Note that the nameFilters are not applied to directories. + - void QQuickFolderListModel::inserted(const QModelIndex &index, int start, int end) ++ \sa showDotAndDotDot ++*/ ++bool QQuickFolderListModel::showDirs() const +{ - if (index == d->folderIndex) { - emit beginInsertRows(QModelIndex(), start, end); - d->count = d->model.rowCount(d->folderIndex); - emit endInsertRows(); - } ++ Q_D(const QQuickFolderListModel); ++ return d->showDirs; +} + - void QQuickFolderListModel::removed(const QModelIndex &index, int start, int end) ++void QQuickFolderListModel::setShowDirs(bool on) +{ - if (index == d->folderIndex) { - emit beginRemoveRows(QModelIndex(), start, end); - d->count = d->model.rowCount(d->folderIndex); - emit endRemoveRows(); - } - } ++ Q_D(QQuickFolderListModel); + - void QQuickFolderListModel::handleDataChanged(const QModelIndex &start, const QModelIndex &end) - { - if (start.parent() == d->folderIndex) - emit dataChanged(index(start.row(),0), index(end.row(),0)); ++ d->fileInfoThread.setShowDirs(on); ++ d->showDirs = on; +} + +/*! - \qmlproperty bool FolderListModel::showDirs ++ \qmlproperty bool FolderListModel::showDirsFirst + - If true, directories are included in the model; otherwise only files - are included. ++ If true, if directories are included in the model they will ++ always be shown first, then the files. + - By default, this property is true. - - Note that the nameFilters are not applied to directories. ++ By default, this property is false. + - \sa showDotAndDotDot +*/ - bool QQuickFolderListModel::showDirs() const ++bool QQuickFolderListModel::showDirsFirst() const +{ - return d->model.filter() & QDir::AllDirs; ++ Q_D(const QQuickFolderListModel); ++ return d->showDirsFirst; +} + - void QQuickFolderListModel::setShowDirs(bool on) ++void QQuickFolderListModel::setShowDirsFirst(bool on) +{ - if (!(d->model.filter() & QDir::AllDirs) == !on) - return; - if (on) { - d->showDirs = true; - d->model.setFilter(d->model.filter() | QDir::AllDirs | QDir::Drives); - } else { - d->showDirs = false; - d->model.setFilter(d->model.filter() & ~(QDir::AllDirs | QDir::Drives)); - } ++ Q_D(QQuickFolderListModel); ++ ++ d->fileInfoThread.setShowDirsFirst(on); ++ d->showDirsFirst = on; +} + ++ +/*! + \qmlproperty bool FolderListModel::showDotAndDotDot + + If true, the "." and ".." directories are included in the model; otherwise + they are excluded. + + By default, this property is false. + + \sa showDirs +*/ +bool QQuickFolderListModel::showDotAndDotDot() const +{ - return !(d->model.filter() & QDir::NoDotAndDotDot); ++ Q_D(const QQuickFolderListModel); ++ return d->showDots; +} + +void QQuickFolderListModel::setShowDotAndDotDot(bool on) +{ - if (!(d->model.filter() & QDir::NoDotAndDotDot) == on) - return; - if (on) { - d->showDots = true; - d->model.setFilter(d->model.filter() & ~QDir::NoDotAndDotDot); - } else { - d->showDots = false; - d->model.setFilter(d->model.filter() | QDir::NoDotAndDotDot); ++ Q_D(QQuickFolderListModel); ++ ++ if (on != d->showDots) { ++ d->fileInfoThread.setShowDotDot(on); + } +} + +/*! + \qmlproperty bool FolderListModel::showOnlyReadable + + If true, only readable files and directories are shown; otherwise all files + and directories are shown. + + By default, this property is false. + + \sa showDirs +*/ +bool QQuickFolderListModel::showOnlyReadable() const +{ - return d->model.filter() & QDir::Readable; ++ Q_D(const QQuickFolderListModel); ++ return d->showOnlyReadable; +} + +void QQuickFolderListModel::setShowOnlyReadable(bool on) +{ - if (!(d->model.filter() & QDir::Readable) == !on) - return; - if (on) { - d->showOnlyReadable = true; - d->model.setFilter(d->model.filter() | QDir::Readable); - } else { - d->showOnlyReadable = false; - d->model.setFilter(d->model.filter() & ~QDir::Readable); ++ Q_D(QQuickFolderListModel); ++ ++ if (on != d->showOnlyReadable) { ++ d->fileInfoThread.setShowOnlyReadable(on); + } +} + ++/*! ++ \qmlmethod QVariant QQuickFolderListModel::get(int idx, const QString &property) const ++ ++ Get the folder property for the given index. The following properties ++ are available. ++ ++ \list ++ \o \c fileName ++ \o \c filePath ++ \o \c fileBaseName ++ \o \c fileSuffix ++ \o \c fileSize ++ \o \c fileModified ++ \o \c fileAccessed ++ \o \c fileIsDir ++ \endlist ++*/ ++QVariant QQuickFolderListModel::get(int idx, const QString &property) const ++{ ++ int role = roleFromString(property); ++ if (role >= 0 && idx >= 0) ++ return data(index(idx, 0), role); ++ else ++ return QVariant(); ++} ++ ++#include "moc_qquickfolderlistmodel.cpp" ++ +//![code] +QT_END_NAMESPACE - - #endif // QT_NO_DIRMODEL diff --cc src/imports/folderlistmodel/qquickfolderlistmodel.h index 10af7c8,0000000..830a30b mode 100644,000000..100644 --- a/src/imports/folderlistmodel/qquickfolderlistmodel.h +++ b/src/imports/folderlistmodel/qquickfolderlistmodel.h @@@ -1,159 -1,0 +1,169 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKFOLDERLISTMODEL_H +#define QQUICKFOLDERLISTMODEL_H + +#include +#include +#include +#include + - #ifndef QT_NO_DIRMODEL - +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + + +class QQmlContext; +class QModelIndex; + +class QQuickFolderListModelPrivate; + +//![class begin] +class QQuickFolderListModel : public QAbstractListModel, public QQmlParserStatus +{ + Q_OBJECT + Q_INTERFACES(QQmlParserStatus) +//![class begin] + +//![class props] + Q_PROPERTY(QUrl folder READ folder WRITE setFolder NOTIFY folderChanged) ++ Q_PROPERTY(QUrl rootFolder READ rootFolder WRITE setRootFolder) + Q_PROPERTY(QUrl parentFolder READ parentFolder NOTIFY folderChanged) + Q_PROPERTY(QStringList nameFilters READ nameFilters WRITE setNameFilters) + Q_PROPERTY(SortField sortField READ sortField WRITE setSortField) + Q_PROPERTY(bool sortReversed READ sortReversed WRITE setSortReversed) + Q_PROPERTY(bool showDirs READ showDirs WRITE setShowDirs) ++ Q_PROPERTY(bool showDirsFirst READ showDirsFirst WRITE setShowDirsFirst) + Q_PROPERTY(bool showDotAndDotDot READ showDotAndDotDot WRITE setShowDotAndDotDot) + Q_PROPERTY(bool showOnlyReadable READ showOnlyReadable WRITE setShowOnlyReadable) - Q_PROPERTY(int count READ count) ++ Q_PROPERTY(int count READ count NOTIFY rowCountChanged) +//![class props] + +//![abslistmodel] +public: + QQuickFolderListModel(QObject *parent = 0); + ~QQuickFolderListModel(); + - enum Roles { FileNameRole = Qt::UserRole+1, FilePathRole = Qt::UserRole+2 }; - - int rowCount(const QModelIndex &parent) const; - QVariant data(const QModelIndex &index, int role) const; ++ enum Roles { ++ FileNameRole = Qt::UserRole + 1, ++ FilePathRole = Qt::UserRole + 2, ++ FileBaseNameRole = Qt::UserRole + 3, ++ FileSuffixRole = Qt::UserRole + 4, ++ FileSizeRole = Qt::UserRole + 5, ++ FileLastModifiedRole = Qt::UserRole + 6, ++ FileLastReadRole = Qt::UserRole +7, ++ FileIsDirRole = Qt::UserRole + 8 ++ }; ++ ++ virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; ++ virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; ++ virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; +//![abslistmodel] + +//![count] + int count() const { return rowCount(QModelIndex()); } +//![count] + +//![prop funcs] + QUrl folder() const; + void setFolder(const QUrl &folder); ++ QUrl rootFolder() const; ++ void setRootFolder(const QUrl &path); + + QUrl parentFolder() const; + + QStringList nameFilters() const; + void setNameFilters(const QStringList &filters); + + enum SortField { Unsorted, Name, Time, Size, Type }; + SortField sortField() const; + void setSortField(SortField field); + Q_ENUMS(SortField) + + bool sortReversed() const; + void setSortReversed(bool rev); + + bool showDirs() const; - void setShowDirs(bool); ++ void setShowDirs(bool showDirs); ++ bool showDirsFirst() const; ++ void setShowDirsFirst(bool showDirsFirst); + bool showDotAndDotDot() const; - void setShowDotAndDotDot(bool); ++ void setShowDotAndDotDot(bool on); + bool showOnlyReadable() const; - void setShowOnlyReadable(bool); ++ void setShowOnlyReadable(bool on); +//![prop funcs] + - //![isfolder] + Q_INVOKABLE bool isFolder(int index) const; - //![isfolder] ++ Q_INVOKABLE QVariant get(int idx, const QString &property) const; + +//![parserstatus] + virtual void classBegin(); + virtual void componentComplete(); +//![parserstatus] + ++ int roleFromString(const QString &roleName) const; ++ +//![notifier] +Q_SIGNALS: + void folderChanged(); ++ void rowCountChanged() const; +//![notifier] + +//![class end] - private Q_SLOTS: - void refresh(); - void resetFiltering(); - void inserted(const QModelIndex &index, int start, int end); - void removed(const QModelIndex &index, int start, int end); - void handleDataChanged(const QModelIndex &start, const QModelIndex &end); ++ + +private: + Q_DISABLE_COPY(QQuickFolderListModel) - QQuickFolderListModelPrivate *d; ++ Q_DECLARE_PRIVATE(QQuickFolderListModel) ++ QScopedPointer d_ptr; ++ ++ Q_PRIVATE_SLOT(d_func(), void _q_directoryChanged(const QString &directory, const QList &list)) ++ Q_PRIVATE_SLOT(d_func(), void _q_directoryUpdated(const QString &directory, const QList &list, int fromIndex, int toIndex)) ++ Q_PRIVATE_SLOT(d_func(), void _q_sortFinished(const QList &list)) +}; +//![class end] + +QT_END_NAMESPACE + - //![qml decl] - QML_DECLARE_TYPE(QQuickFolderListModel) - //![qml decl] - +QT_END_HEADER + - #endif // QT_NO_DIRMODEL - +#endif // QQUICKFOLDERLISTMODEL_H diff --cc src/imports/localstorage/localstorage.pro index c54bc56,5164e88..fa1718d --- a/src/imports/localstorage/localstorage.pro +++ b/src/imports/localstorage/localstorage.pro @@@ -6,7 -6,9 +6,9 @@@ QT += sql qml qml-private v8-private co SOURCES += plugin.cpp + OTHER_FILES += localstorage.json + -DESTDIR = $$QT.declarative.imports/$$TARGETPATH +DESTDIR = $$QT.qml.imports/$$TARGETPATH target.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH qmldir.files += $$PWD/qmldir diff --cc src/imports/localstorage/plugin.cpp index 77e6887,0ab47c1..7c55225 --- a/src/imports/localstorage/plugin.cpp +++ b/src/imports/localstorage/plugin.cpp @@@ -648,11 -648,13 +648,13 @@@ static QObject *module_api_factory(QQml return api; } -class QDeclarativeLocalStoragePlugin : public QDeclarativeExtensionPlugin +class QQmlLocalStoragePlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDeclarativeExtensionInterface" FILE "localstorage.json") ++ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "localstorage.json") + public: - QDeclarativeLocalStoragePlugin() + QQmlLocalStoragePlugin() { } diff --cc src/imports/testlib/main.cpp index 8ab745a,ec32d7c..6473d21 --- a/src/imports/testlib/main.cpp +++ b/src/imports/testlib/main.cpp @@@ -132,9 -132,11 +132,11 @@@ QML_DECLARE_TYPE(QuickTestUtil QT_BEGIN_NAMESPACE -class QTestQmlModule : public QDeclarativeExtensionPlugin +class QTestQmlModule : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDeclarativeExtensionInterface" FILE "testlib.json") ++ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "testlib.json") + public: virtual void registerTypes(const char *uri) { diff --cc src/imports/testlib/testlib.pro index a4cb034,7e8f601..dfb23ce --- a/src/imports/testlib/testlib.pro +++ b/src/imports/testlib/testlib.pro @@@ -4,12 -4,13 +4,13 @@@ include(../qimportbase.pri CONFIG += qt plugin -QT += declarative quick qmltest qmltest-private v8-private declarative-private core-private testlib +QT += qml quick qmltest qmltest-private v8-private qml-private core-private testlib SOURCES += main.cpp - HEADERS += + + OTHER_FILES += testlib.json -DESTDIR = $$QT.declarative.imports/$$TARGETPATH +DESTDIR = $$QT.qml.imports/$$TARGETPATH target.path += $$[QT_INSTALL_IMPORTS]/QtTest OTHER_IMPORT_FILES = \ diff --cc src/imports/xmllistmodel/plugin.cpp index 54a6d5e,07f59b8..5825349 --- a/src/imports/xmllistmodel/plugin.cpp +++ b/src/imports/xmllistmodel/plugin.cpp @@@ -46,9 -46,11 +46,11 @@@ QT_BEGIN_NAMESPACE -class QmlXmlListModelPlugin : public QDeclarativeExtensionPlugin +class QmlXmlListModelPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDeclarativeExtensionInterface" FILE "xmllistmodel.json") ++ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "xmllistmodel.json") + public: virtual void registerTypes(const char *uri) { diff --cc src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro index 014f964,24efee8..f051413 --- a/src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro +++ b/src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro @@@ -24,8 -24,10 +24,10 @@@ HEADERS += qquickviewinspector.h \ ../shared/abstracttool.h \ ../shared/abstractviewinspector.h \ - ../shared/qdeclarativeinspectorprotocol.h \ + ../shared/qqmlinspectorprotocol.h \ ../shared/qmlinspectorconstants.h + OTHER_FILES += qtquick2plugin.json + target.path += $$[QT_INSTALL_PLUGINS]/qmltooling INSTALLS += target diff --cc src/plugins/qmltooling/qmldbg_qtquick2/qtquick2plugin.h index d78aac6,f6f668d..6c3f3d6 --- a/src/plugins/qmltooling/qmldbg_qtquick2/qtquick2plugin.h +++ b/src/plugins/qmltooling/qmldbg_qtquick2/qtquick2plugin.h @@@ -55,7 -55,8 +55,8 @@@ class QtQuick2Plugin : public QObject, { Q_OBJECT Q_DISABLE_COPY(QtQuick2Plugin) - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDeclarativeInspectorInterface" FILE "qtquick2plugin.json") - Q_INTERFACES(QDeclarativeInspectorInterface) ++ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlInspectorInterface" FILE "qtquick2plugin.json") + Q_INTERFACES(QQmlInspectorInterface) public: QtQuick2Plugin(); diff --cc src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp index 63a3297,216c2c3..1c5ec37 --- a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp +++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp @@@ -190,10 -190,8 +190,8 @@@ void QTcpServerConnection::newConnectio void QTcpServerConnection::invalidPacket() { - qWarning("QDeclarativeDebugServer: Received a corrupted packet! Giving up ..."); + qWarning("QQmlDebugServer: Received a corrupted packet! Giving up ..."); } - Q_EXPORT_PLUGIN2(tcpserver, QTcpServerConnection) - QT_END_NAMESPACE diff --cc src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h index 74c6b95,1154a0a..e81c9f7 --- a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h +++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h @@@ -54,9 -54,9 +54,9 @@@ class QTcpServerConnection : public QOb Q_OBJECT Q_DECLARE_PRIVATE(QTcpServerConnection) Q_DISABLE_COPY(QTcpServerConnection) - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDeclarativeDebugServerConnection" FILE "qtcpserverconnection.json") - Q_INTERFACES(QDeclarativeDebugServerConnection) ++ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlDebugServerConnection" FILE "qtcpserverconnection.json") + Q_INTERFACES(QQmlDebugServerConnection) - public: QTcpServerConnection(); ~QTcpServerConnection(); diff --cc src/qml/debugger/qdebugmessageservice.cpp index 2c52809,0000000..dcaa514 mode 100644,000000..100644 --- a/src/qml/debugger/qdebugmessageservice.cpp +++ b/src/qml/debugger/qdebugmessageservice.cpp @@@ -1,124 -1,0 +1,126 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdebugmessageservice_p.h" +#include "qqmldebugservice_p_p.h" + ++#include ++ +QT_BEGIN_NAMESPACE + +Q_GLOBAL_STATIC(QDebugMessageService, qmlDebugMessageService) + +void DebugMessageHandler(QtMsgType type, const QMessageLogContext &ctxt, + const char *buf) +{ + QDebugMessageService::instance()->sendDebugMessage(type, ctxt, buf); +} + +class QDebugMessageServicePrivate : public QQmlDebugServicePrivate +{ +public: + QDebugMessageServicePrivate() + : oldMsgHandler(0) + , prevState(QQmlDebugService::NotConnected) + { + } + + QMessageHandler oldMsgHandler; + QQmlDebugService::State prevState; +}; + +QDebugMessageService::QDebugMessageService(QObject *parent) : + QQmlDebugService(*(new QDebugMessageServicePrivate()), + QLatin1String("DebugMessages"), 2, parent) +{ + Q_D(QDebugMessageService); + + registerService(); + if (state() == Enabled) { + d->oldMsgHandler = qInstallMessageHandler(DebugMessageHandler); + d->prevState = Enabled; + } +} + +QDebugMessageService *QDebugMessageService::instance() +{ + return qmlDebugMessageService(); +} + +void QDebugMessageService::sendDebugMessage(QtMsgType type, + const QMessageLogContext &ctxt, + const char *buf) +{ + Q_D(QDebugMessageService); + + //We do not want to alter the message handling mechanism + //We just eavesdrop and forward the messages to a port + //only if a client is connected to it. + QByteArray message; + QDataStream ws(&message, QIODevice::WriteOnly); + ws << QByteArray("MESSAGE") << type << QString::fromLocal8Bit(buf).toUtf8(); + ws << QString::fromLatin1(ctxt.file).toUtf8(); + ws << ctxt.line << QString::fromLatin1(ctxt.function).toUtf8(); + + sendMessage(message); + if (d->oldMsgHandler) + (*d->oldMsgHandler)(type, ctxt, buf); +} + +void QDebugMessageService::stateChanged(State state) +{ + Q_D(QDebugMessageService); + + if (state != Enabled && d->prevState == Enabled) { + QMessageHandler handler = qInstallMessageHandler(d->oldMsgHandler); + // has our handler been overwritten in between? + if (handler != DebugMessageHandler) + qInstallMessageHandler(handler); + + } else if (state == Enabled && d->prevState != Enabled) { + d->oldMsgHandler = qInstallMessageHandler(DebugMessageHandler); + + } + + d->prevState = state; +} + +QT_END_NAMESPACE diff --cc src/qml/debugger/qqmldebugserverconnection_p.h index c9092f1,0000000..ab9e7bd mode 100644,000000..100644 --- a/src/qml/debugger/qqmldebugserverconnection_p.h +++ b/src/qml/debugger/qqmldebugserverconnection_p.h @@@ -1,85 -1,0 +1,87 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLDEBUGSERVERCONNECTION_H +#define QQMLDEBUGSERVERCONNECTION_H + +#include - #include ++#include + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + + +class QQmlDebugServer; +class Q_QML_EXPORT QQmlDebugServerConnection +{ +public: + QQmlDebugServerConnection() {} + virtual ~QQmlDebugServerConnection() {} + + virtual void setServer(QQmlDebugServer *server) = 0; + virtual void setPort(int port, bool bock) = 0; + virtual bool isConnected() const = 0; + virtual void send(const QList &messages) = 0; + virtual void disconnect() = 0; + virtual bool waitForMessage() = 0; +}; + - Q_DECLARE_INTERFACE(QQmlDebugServerConnection, "com.trolltech.Qt.QQmlDebugServerConnection/1.0") ++#define QQmlDebugServerConnection_iid "org.qt-project.Qt.QQmlDebugServerConnection" ++ ++Q_DECLARE_INTERFACE(QQmlDebugServerConnection, QQmlDebugServerConnection_iid) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QQMLDEBUGSERVERCONNECTION_H diff --cc src/qml/debugger/qqmlinspectorinterface_p.h index 7f52dff,0000000..5b015d3 mode 100644,000000..100644 --- a/src/qml/debugger/qqmlinspectorinterface_p.h +++ b/src/qml/debugger/qqmlinspectorinterface_p.h @@@ -1,83 -1,0 +1,86 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLINSPECTORINTERFACE_H +#define QQMLINSPECTORINTERFACE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include ++#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + + +class Q_QML_EXPORT QQmlInspectorInterface +{ +public: + QQmlInspectorInterface() {} + virtual ~QQmlInspectorInterface() {} + + virtual bool canHandleView(QObject *view) = 0; + + virtual void activate(QObject *view) = 0; + virtual void deactivate() = 0; + + virtual void clientMessage(const QByteArray &message) = 0; +}; + - Q_DECLARE_INTERFACE(QQmlInspectorInterface, "com.trolltech.Qt.QQmlInspectorInterface/1.0") ++#define QQmlInspectorInterface_iid "org.qt-project.Qt.QQmlInspectorInterface" ++ ++Q_DECLARE_INTERFACE(QQmlInspectorInterface, QQmlInspectorInterface_iid) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QQMLINSPECTORINTERFACE_H diff --cc src/qml/debugger/qqmlprofilerservice.cpp index d6a0307,0000000..2731d20 mode 100644,000000..100644 --- a/src/qml/debugger/qqmlprofilerservice.cpp +++ b/src/qml/debugger/qqmlprofilerservice.cpp @@@ -1,357 -1,0 +1,315 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmlprofilerservice_p.h" + +#include +#include +#include +#include +#include + +// this contains QUnifiedTimer +#include + +QT_BEGIN_NAMESPACE + ++// instance will be set, unset in constructor. Allows static methods to be inlined. ++QQmlProfilerService *QQmlProfilerService::instance = 0; +Q_GLOBAL_STATIC(QQmlProfilerService, profilerInstance) + - QQmlBindingProfiler::QQmlBindingProfiler(const QString &url, int line, int column) - { - QQmlProfilerService::startRange(QQmlProfilerService::Binding); - QQmlProfilerService::rangeLocation(QQmlProfilerService::Binding, url, line, column); - } - - QQmlBindingProfiler::~QQmlBindingProfiler() - { - QQmlProfilerService::endRange(QQmlProfilerService::Binding); - } - - void QQmlBindingProfiler::addDetail(const QString &details) - { - QQmlProfilerService::rangeData(QQmlProfilerService::Binding, details); - } + +// convert to a QByteArray that can be sent to the debug client +// use of QDataStream can skew results +// (see tst_qqmldebugtrace::trace() benchmark) +QByteArray QQmlProfilerData::toByteArray() const +{ + QByteArray data; + //### using QDataStream is relatively expensive + QDataStream ds(&data, QIODevice::WriteOnly); + ds << time << messageType << detailType; + if (messageType == (int)QQmlProfilerService::RangeData) + ds << detailData; + if (messageType == (int)QQmlProfilerService::RangeLocation) + ds << detailData << line << column; + if (messageType == (int)QQmlProfilerService::Event && + detailType == (int)QQmlProfilerService::AnimationFrame) + ds << framerate << animationcount; + return data; +} + +QQmlProfilerService::QQmlProfilerService() + : QQmlDebugService(QLatin1String("CanvasFrameRate"), 1), + m_enabled(false), m_messageReceived(false) +{ + m_timer.start(); + + if (registerService() == Enabled) { + // wait for first message indicating whether to trace or not + while (!m_messageReceived) + waitForMessage(); + + QUnifiedTimer::instance()->registerProfilerCallback( &animationFrame ); + } +} + +QQmlProfilerService::~QQmlProfilerService() +{ ++ instance = 0; +} + +void QQmlProfilerService::initialize() +{ + // just make sure that the service is properly registered - profilerInstance(); ++ instance = profilerInstance(); +} + +bool QQmlProfilerService::startProfiling() +{ + return profilerInstance()->startProfilingImpl(); +} + +bool QQmlProfilerService::stopProfiling() +{ + return profilerInstance()->stopProfilingImpl(); +} + +void QQmlProfilerService::sendStartedProfilingMessage() +{ + profilerInstance()->sendStartedProfilingMessageImpl(); +} + +void QQmlProfilerService::addEvent(EventType t) +{ + profilerInstance()->addEventImpl(t); +} + - void QQmlProfilerService::startRange(RangeType t) - { - profilerInstance()->startRangeImpl(t); - } - - void QQmlProfilerService::rangeData(RangeType t, const QString &data) - { - profilerInstance()->rangeDataImpl(t, data); - } - - void QQmlProfilerService::rangeData(RangeType t, const QUrl &data) - { - profilerInstance()->rangeDataImpl(t, data); - } - - void QQmlProfilerService::rangeLocation(RangeType t, const QString &fileName, int line, int column) - { - profilerInstance()->rangeLocationImpl(t, fileName, line, column); - } - - void QQmlProfilerService::rangeLocation(RangeType t, const QUrl &fileName, int line, int column) - { - profilerInstance()->rangeLocationImpl(t, fileName, line, column); - } - - void QQmlProfilerService::endRange(RangeType t) - { - profilerInstance()->endRangeImpl(t); - } - +void QQmlProfilerService::animationFrame(qint64 delta) +{ + profilerInstance()->animationFrameImpl(delta); +} + +void QQmlProfilerService::sendProfilingData() +{ + profilerInstance()->sendMessages(); +} + +bool QQmlProfilerService::startProfilingImpl() +{ + bool success = false; + if (!profilingEnabled()) { + setProfilingEnabled(true); + sendStartedProfilingMessageImpl(); + success = true; + } + return success; +} + +bool QQmlProfilerService::stopProfilingImpl() +{ + bool success = false; + if (profilingEnabled()) { + addEventImpl(EndTrace); + setProfilingEnabled(false); + success = true; + } + return success; +} + +void QQmlProfilerService::sendStartedProfilingMessageImpl() +{ + if (!QQmlDebugService::isDebuggingEnabled() || !m_enabled) + return; + + QQmlProfilerData ed = {m_timer.nsecsElapsed(), (int)Event, (int)StartTrace, QString(), -1, -1, 0, 0}; + QQmlDebugService::sendMessage(ed.toByteArray()); +} + +void QQmlProfilerService::addEventImpl(EventType event) +{ + if (!QQmlDebugService::isDebuggingEnabled() || !m_enabled) + return; + + QQmlProfilerData ed = {m_timer.nsecsElapsed(), (int)Event, (int)event, QString(), -1, -1, 0, 0}; + processMessage(ed); +} + - void QQmlProfilerService::startRangeImpl(RangeType range) ++void QQmlProfilerService::startRange(RangeType range) +{ + if (!QQmlDebugService::isDebuggingEnabled() || !m_enabled) + return; + + QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeStart, (int)range, QString(), -1, -1, 0, 0}; + processMessage(rd); +} + - void QQmlProfilerService::rangeDataImpl(RangeType range, const QString &rData) ++void QQmlProfilerService::rangeData(RangeType range, const QString &rData) +{ + if (!QQmlDebugService::isDebuggingEnabled() || !m_enabled) + return; + + QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range, rData, -1, -1, 0, 0}; + processMessage(rd); +} + - void QQmlProfilerService::rangeDataImpl(RangeType range, const QUrl &rData) ++void QQmlProfilerService::rangeData(RangeType range, const QUrl &rData) +{ + if (!QQmlDebugService::isDebuggingEnabled() || !m_enabled) + return; + + QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range, rData.toString(QUrl::FormattingOption(0x100)), -1, -1, 0, 0}; + processMessage(rd); +} + - void QQmlProfilerService::rangeLocationImpl(RangeType range, const QString &fileName, int line, int column) ++void QQmlProfilerService::rangeLocation(RangeType range, const QString &fileName, int line, int column) +{ + if (!QQmlDebugService::isDebuggingEnabled() || !m_enabled) + return; + + QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range, fileName, line, column, 0, 0}; + processMessage(rd); +} + - void QQmlProfilerService::rangeLocationImpl(RangeType range, const QUrl &fileName, int line, int column) ++void QQmlProfilerService::rangeLocation(RangeType range, const QUrl &fileName, int line, int column) +{ + if (!QQmlDebugService::isDebuggingEnabled() || !m_enabled) + return; + + QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range, fileName.toString(QUrl::FormattingOption(0x100)), line, column, 0, 0}; + processMessage(rd); +} + - void QQmlProfilerService::endRangeImpl(RangeType range) ++void QQmlProfilerService::endRange(RangeType range) +{ + if (!QQmlDebugService::isDebuggingEnabled() || !m_enabled) + return; + + QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeEnd, (int)range, QString(), -1, -1, 0, 0}; + processMessage(rd); +} + +void QQmlProfilerService::animationFrameImpl(qint64 delta) +{ + Q_ASSERT(QQmlDebugService::isDebuggingEnabled()); + if (!m_enabled) + return; + + int animCount = QUnifiedTimer::instance()->runningAnimationCount(); + + if (animCount > 0 && delta > 0) { + // trim fps to integer + int fps = 1000 / delta; + QQmlProfilerData ed = {m_timer.nsecsElapsed(), (int)Event, (int)AnimationFrame, QString(), -1, -1, fps, animCount}; + processMessage(ed); + } +} + +/* + Either send the message directly, or queue up + a list of messages to send later (via sendMessages) +*/ +void QQmlProfilerService::processMessage(const QQmlProfilerData &message) +{ + QMutexLocker locker(&m_mutex); + m_data.append(message); +} + +bool QQmlProfilerService::profilingEnabled() +{ + return m_enabled; +} + +void QQmlProfilerService::setProfilingEnabled(bool enable) +{ + m_enabled = enable; +} + +/* + Send the messages queued up by processMessage +*/ +void QQmlProfilerService::sendMessages() +{ + QMutexLocker locker(&m_mutex); + QList messages; + for (int i = 0; i < m_data.count(); ++i) + messages << m_data.at(i).toByteArray(); + m_data.clear(); + + //indicate completion + QByteArray data; + QDataStream ds(&data, QIODevice::WriteOnly); + ds << (qint64)-1 << (int)Complete; + messages << data; + + QQmlDebugService::sendMessages(messages); +} + +void QQmlProfilerService::stateAboutToBeChanged(QQmlDebugService::State newState) +{ + if (state() == newState) + return; + + if (state() == Enabled + && m_enabled) { + stopProfilingImpl(); + sendMessages(); + } +} + +void QQmlProfilerService::messageReceived(const QByteArray &message) +{ + QByteArray rwData = message; + QDataStream stream(&rwData, QIODevice::ReadOnly); + + bool enabled; + stream >> enabled; + + m_messageReceived = true; + + if (enabled) { + startProfilingImpl(); + } else { + if (stopProfilingImpl()) + sendMessages(); + } +} + +QT_END_NAMESPACE diff --cc src/qml/debugger/qqmlprofilerservice_p.h index a74ce10,0000000..7a70845 mode 100644,000000..100644 --- a/src/qml/debugger/qqmlprofilerservice_p.h +++ b/src/qml/debugger/qqmlprofilerservice_p.h @@@ -1,183 -1,0 +1,303 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLPROFILERSERVICE_P_H +#define QQMLPROFILERSERVICE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include ++#include +#include +#include +#include ++#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +struct Q_AUTOTEST_EXPORT QQmlProfilerData +{ + qint64 time; + int messageType; + int detailType; + + //### + QString detailData; //used by RangeData and RangeLocation + int line; //used by RangeLocation + int column; //used by RangeLocation + int framerate; //used by animation events + int animationcount; //used by animation events + + QByteArray toByteArray() const; +}; + +Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE); + +class QUrl; +class QQmlEngine; + - // RAII - class Q_AUTOTEST_EXPORT QQmlBindingProfiler { - public: - QQmlBindingProfiler(const QString &url, int line, int column); - ~QQmlBindingProfiler(); - void addDetail(const QString &details); - }; + +class Q_QML_EXPORT QQmlProfilerService : public QQmlDebugService +{ +public: + enum Message { + Event, + RangeStart, + RangeData, + RangeLocation, + RangeEnd, + Complete, // end of transmission + + MaximumMessage + }; + + enum EventType { + FramePaint, + Mouse, + Key, + AnimationFrame, + EndTrace, + StartTrace, + + MaximumEventType + }; + + enum RangeType { + Painting, + Compiling, + Creating, + Binding, //running a binding + HandlingSignal, //running a signal handler + + MaximumRangeType + }; + + static void initialize(); + + static bool startProfiling(); + static bool stopProfiling(); + static void sendStartedProfilingMessage(); + static void addEvent(EventType); - static void startRange(RangeType); - static void rangeData(RangeType, const QString &); - static void rangeData(RangeType, const QUrl &); - static void rangeLocation(RangeType, const QString &, int, int); - static void rangeLocation(RangeType, const QUrl &, int, int); - static void endRange(RangeType); + static void animationFrame(qint64); + + static void sendProfilingData(); + + QQmlProfilerService(); + ~QQmlProfilerService(); + +protected: + virtual void stateAboutToBeChanged(State state); + virtual void messageReceived(const QByteArray &); + +private: + bool startProfilingImpl(); + bool stopProfilingImpl(); + void sendStartedProfilingMessageImpl(); + void addEventImpl(EventType); - void startRangeImpl(RangeType); - void rangeDataImpl(RangeType, const QString &); - void rangeDataImpl(RangeType, const QUrl &); - void rangeLocationImpl(RangeType, const QString &, int, int); - void rangeLocationImpl(RangeType, const QUrl &, int, int); - void endRangeImpl(RangeType); + void animationFrameImpl(qint64); + ++ void startRange(RangeType); ++ void rangeData(RangeType, const QString &); ++ void rangeData(RangeType, const QUrl &); ++ void rangeLocation(RangeType, const QString &, int, int); ++ void rangeLocation(RangeType, const QUrl &, int, int); ++ void endRange(RangeType); ++ ++ + bool profilingEnabled(); + void setProfilingEnabled(bool enable); + void sendMessages(); + void processMessage(const QQmlProfilerData &); + +private: + QElapsedTimer m_timer; + bool m_enabled; + bool m_messageReceived; + QVector m_data; + QMutex m_mutex; ++ ++ static QQmlProfilerService *instance; ++ ++ friend struct QQmlBindingProfiler; ++ friend struct QQmlHandlingSignalProfiler; ++ friend struct QQmlObjectCreatingProfiler; ++ friend struct QQmlCompilingProfiler; ++}; ++ ++// ++// RAII helper structs ++// ++ ++struct QQmlBindingProfiler { ++ QQmlBindingProfiler(const QString &url, int line, int column) ++ { ++ QQmlProfilerService *instance = QQmlProfilerService::instance; ++ enabled = instance ? instance->profilingEnabled() : false; ++ if (enabled) { ++ instance->startRange(QQmlProfilerService::Binding); ++ instance->rangeLocation(QQmlProfilerService::Binding, url, line, column); ++ } ++ } ++ ++ ~QQmlBindingProfiler() ++ { ++ if (enabled) ++ QQmlProfilerService::instance->endRange(QQmlProfilerService::Binding); ++ } ++ ++ void addDetail(const QString &details) ++ { ++ if (enabled) ++ QQmlProfilerService::instance->rangeData(QQmlProfilerService::Binding, ++ details); ++ } ++\ ++ bool enabled; ++}; ++ ++struct QQmlHandlingSignalProfiler { ++ QQmlHandlingSignalProfiler() ++ { ++ enabled = QQmlProfilerService::instance ++ ? QQmlProfilerService::instance->profilingEnabled() : false; ++ if (enabled) { ++ QQmlProfilerService::instance->startRange( ++ QQmlProfilerService::HandlingSignal); ++ } ++ } ++ ++ void setSignalInfo(const QString &name, const QString &expression) ++ { ++ if (enabled) ++ QQmlProfilerService::instance->rangeData( ++ QQmlProfilerService::HandlingSignal, ++ name % QLatin1String(": ") % expression); ++ } ++ ++ void setLocation(const QString &file, int line, int column) ++ { ++ if (enabled) ++ QQmlProfilerService::instance->rangeLocation( ++ QQmlProfilerService::HandlingSignal, file, line, column); ++ } ++ ++ ~QQmlHandlingSignalProfiler() ++ { ++ if (enabled) ++ QQmlProfilerService::instance->endRange( ++ QQmlProfilerService::HandlingSignal); ++ } ++ ++ bool enabled; ++}; ++ ++struct QQmlObjectCreatingProfiler { ++ QQmlObjectCreatingProfiler() ++ { ++ QQmlProfilerService *instance = QQmlProfilerService::instance; ++ enabled = instance ? ++ instance->profilingEnabled() : false; ++ if (enabled) ++ instance->startRange(QQmlProfilerService::Creating); ++ } ++ ++ void setTypeName(const QString &typeName) ++ { ++ if (enabled) ++ QQmlProfilerService::instance->rangeData( ++ QQmlProfilerService::Creating, typeName); ++ } ++ ++ void setLocation(const QUrl &url, int line, int column) ++ { ++ if (enabled) ++ QQmlProfilerService::instance->rangeLocation( ++ QQmlProfilerService::Creating, url, line, column); ++ } ++ ++ ~QQmlObjectCreatingProfiler() ++ { ++ if (enabled) ++ QQmlProfilerService::instance->endRange(QQmlProfilerService::Creating); ++ } ++ ++ bool enabled; ++}; ++ ++struct QQmlCompilingProfiler { ++ QQmlCompilingProfiler(const QString &name) ++ { ++ QQmlProfilerService *instance = QQmlProfilerService::instance; ++ enabled = instance ? ++ instance->profilingEnabled() : false; ++ if (enabled) { ++ instance->startRange(QQmlProfilerService::Compiling); ++ instance->rangeLocation(QQmlProfilerService::Compiling, name, 1, 1); ++ instance->rangeData(QQmlProfilerService::Compiling, name); ++ } ++ } ++ ++ ~QQmlCompilingProfiler() ++ { ++ if (enabled) ++ QQmlProfilerService::instance->endRange(QQmlProfilerService::Compiling); ++ } ++ ++ bool enabled; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QQMLPROFILERSERVICE_P_H + diff --cc src/qml/debugger/qv8profilerservice.cpp index eba8b0f,0000000..6473a2f mode 100644,000000..100644 --- a/src/qml/debugger/qv8profilerservice.cpp +++ b/src/qml/debugger/qv8profilerservice.cpp @@@ -1,287 -1,0 +1,301 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qv8profilerservice_p.h" +#include "qqmldebugservice_p_p.h" +#include "private/qjsconverter_impl_p.h" +#include + +#include + +QT_BEGIN_NAMESPACE + +Q_GLOBAL_STATIC(QV8ProfilerService, v8ProfilerInstance) + +class DebugServiceOutputStream : public v8::OutputStream +{ + QQmlDebugService &_service; +public: + DebugServiceOutputStream(QQmlDebugService &service) + : v8::OutputStream(), + _service(service) {} + void EndOfStream() {} + WriteResult WriteAsciiChunk(char *rawData, int size) + { + QByteArray data; + QDataStream ds(&data, QIODevice::WriteOnly); + ds << QV8ProfilerService::V8SnapshotChunk << QByteArray(rawData, size); + _service.sendMessage(data); + return kContinue; + } +}; + +// convert to a QByteArray that can be sent to the debug client +QByteArray QV8ProfilerData::toByteArray() const +{ + QByteArray data; + //### using QDataStream is relatively expensive + QDataStream ds(&data, QIODevice::WriteOnly); + ds << messageType << filename << functionname << lineNumber << totalTime << selfTime << treeLevel; + + return data; +} + +class QV8ProfilerServicePrivate : public QQmlDebugServicePrivate +{ + Q_DECLARE_PUBLIC(QV8ProfilerService) + +public: + QV8ProfilerServicePrivate() + :initialized(false) + { + } + + void takeSnapshot(v8::HeapSnapshot::Type); + + void printProfileTree(const v8::CpuProfileNode *node, int level = 0); + void sendMessages(); + + QList m_data; + + bool initialized; + QList m_ongoing; +}; + +QV8ProfilerService::QV8ProfilerService(QObject *parent) + : QQmlDebugService(*(new QV8ProfilerServicePrivate()), QLatin1String("V8Profiler"), 1, parent) +{ + Q_D(QV8ProfilerService); + + if (registerService() == Enabled) { + // ,block mode, client attached + while (!d->initialized) + waitForMessage(); + } +} + +QV8ProfilerService::~QV8ProfilerService() +{ +} + +QV8ProfilerService *QV8ProfilerService::instance() +{ + return v8ProfilerInstance(); +} + +void QV8ProfilerService::initialize() +{ + // just make sure that the service is properly registered + v8ProfilerInstance(); +} + +void QV8ProfilerService::stateAboutToBeChanged(QQmlDebugService::State newState) +{ + Q_D(QV8ProfilerService); + + if (state() == newState) + return; + + if (state() == Enabled) { + foreach (const QString &title, d->m_ongoing) + QMetaObject::invokeMethod(this, "stopProfiling", Qt::QueuedConnection, Q_ARG(QString, title)); + sendProfilingData(); + } +} + +void QV8ProfilerService::messageReceived(const QByteArray &message) +{ + Q_D(QV8ProfilerService); + + QDataStream ds(message); + QByteArray command; + QByteArray option; + QByteArray title; + ds >> command >> option; + + if (command == "V8PROFILER") { + ds >> title; + QString titleStr = QString::fromUtf8(title); + if (option == "start") { + QMetaObject::invokeMethod(this, "startProfiling", Qt::QueuedConnection, Q_ARG(QString, titleStr)); + } else if (option == "stop" && d->initialized) { + QMetaObject::invokeMethod(this, "stopProfiling", Qt::QueuedConnection, Q_ARG(QString, titleStr)); + QMetaObject::invokeMethod(this, "sendProfilingData", Qt::QueuedConnection); + } + d->initialized = true; + } + + if (command == "V8SNAPSHOT") { + if (option == "full") + QMetaObject::invokeMethod(this, "takeSnapshot", Qt::QueuedConnection); + else if (option == "delete") { + QMetaObject::invokeMethod(this, "deleteSnapshots", Qt::QueuedConnection); + } + } + + QQmlDebugService::messageReceived(message); +} + +void QV8ProfilerService::startProfiling(const QString &title) +{ + Q_D(QV8ProfilerService); + // Start Profiling + + if (d->m_ongoing.contains(title)) + return; + + v8::HandleScope handle_scope; + v8::Handle v8title = v8::String::New(reinterpret_cast(title.data()), title.size()); + v8::CpuProfiler::StartProfiling(v8title); + + d->m_ongoing.append(title); ++ ++ // indicate profiling started ++ QByteArray data; ++ QDataStream ds(&data, QIODevice::WriteOnly); ++ ds << (int)QV8ProfilerService::V8Started; ++ ++ sendMessage(data); +} + +void QV8ProfilerService::stopProfiling(const QString &title) +{ + Q_D(QV8ProfilerService); + // Stop profiling + + if (!d->m_ongoing.contains(title)) + return; + d->m_ongoing.removeOne(title); + + v8::HandleScope handle_scope; + v8::Handle v8title = v8::String::New(reinterpret_cast(title.data()), title.size()); + const v8::CpuProfile *cpuProfile = v8::CpuProfiler::StopProfiling(v8title); + if (cpuProfile) { + // can happen at start + const v8::CpuProfileNode *rootNode = cpuProfile->GetTopDownRoot(); + d->printProfileTree(rootNode); ++ } else { ++ // indicate completion, even without data ++ QByteArray data; ++ QDataStream ds(&data, QIODevice::WriteOnly); ++ ds << (int)QV8ProfilerService::V8Complete; ++ ++ sendMessage(data); + } +} + +void QV8ProfilerService::takeSnapshot() +{ + Q_D(QV8ProfilerService); + d->takeSnapshot(v8::HeapSnapshot::kFull); +} + +void QV8ProfilerService::deleteSnapshots() +{ + v8::HeapProfiler::DeleteAllSnapshots(); +} + +void QV8ProfilerService::sendProfilingData() +{ + Q_D(QV8ProfilerService); + // Send messages to client + d->sendMessages(); +} + +void QV8ProfilerServicePrivate::printProfileTree(const v8::CpuProfileNode *node, int level) +{ + for (int index = 0 ; index < node->GetChildrenCount() ; index++) { + const v8::CpuProfileNode* childNode = node->GetChild(index); + QString scriptResourceName = QJSConverter::toString(childNode->GetScriptResourceName()); + if (scriptResourceName.length() > 0) { + + QV8ProfilerData rd = {(int)QV8ProfilerService::V8Entry, scriptResourceName, + QJSConverter::toString(childNode->GetFunctionName()), + childNode->GetLineNumber(), childNode->GetTotalTime(), childNode->GetSelfTime(), level}; + m_data.append(rd); + + // different nodes might have common children: fix at client side + if (childNode->GetChildrenCount() > 0) { + printProfileTree(childNode, level+1); + } + } + } +} + +void QV8ProfilerServicePrivate::takeSnapshot(v8::HeapSnapshot::Type snapshotType) +{ + Q_Q(QV8ProfilerService); + + v8::HandleScope scope; + v8::Local title = v8::String::New(""); + + DebugServiceOutputStream outputStream(*q); + const v8::HeapSnapshot *snapshot = v8::HeapProfiler::TakeSnapshot(title, snapshotType); + snapshot->Serialize(&outputStream, v8::HeapSnapshot::kJSON); + + //indicate completion + QByteArray data; + QDataStream ds(&data, QIODevice::WriteOnly); + ds << (int)QV8ProfilerService::V8SnapshotComplete; + + q->sendMessage(data); +} + +void QV8ProfilerServicePrivate::sendMessages() +{ + Q_Q(QV8ProfilerService); + + QList messages; + for (int i = 0; i < m_data.count(); ++i) + messages << m_data.at(i).toByteArray(); + q->sendMessages(messages); + m_data.clear(); + + //indicate completion + QByteArray data; + QDataStream ds(&data, QIODevice::WriteOnly); + ds << (int)QV8ProfilerService::V8Complete; + + q->sendMessage(data); +} + + +QT_END_NAMESPACE diff --cc src/qml/debugger/qv8profilerservice_p.h index d408d9e,0000000..b706d17 mode 100644,000000..100644 --- a/src/qml/debugger/qv8profilerservice_p.h +++ b/src/qml/debugger/qv8profilerservice_p.h @@@ -1,119 -1,0 +1,120 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QV8PROFILERSERVICE_P_H +#define QV8PROFILERSERVICE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + + +struct Q_AUTOTEST_EXPORT QV8ProfilerData +{ + int messageType; + QString filename; + QString functionname; + int lineNumber; + double totalTime; + double selfTime; + int treeLevel; + + QByteArray toByteArray() const; +}; + +class QQmlEngine; +class QV8ProfilerServicePrivate; + +class Q_AUTOTEST_EXPORT QV8ProfilerService : public QQmlDebugService +{ + Q_OBJECT +public: + enum MessageType { + V8Entry, + V8Complete, + V8SnapshotChunk, + V8SnapshotComplete, ++ V8Started, + + V8MaximumMessage + }; + + QV8ProfilerService(QObject *parent = 0); + ~QV8ProfilerService(); + + static QV8ProfilerService *instance(); + static void initialize(); + +public slots: + void startProfiling(const QString &title); + void stopProfiling(const QString &title); + void takeSnapshot(); + void deleteSnapshots(); + + void sendProfilingData(); + +protected: + void stateAboutToBeChanged(State state); + void messageReceived(const QByteArray &); + +private: + Q_DISABLE_COPY(QV8ProfilerService) + Q_DECLARE_PRIVATE(QV8ProfilerService) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QV8PROFILERSERVICE_P_H diff --cc src/qml/qml/ftw/qfastmetabuilder.cpp index 9663c1e,0000000..02f5091 mode 100644,000000..100644 --- a/src/qml/qml/ftw/qfastmetabuilder.cpp +++ b/src/qml/qml/ftw/qfastmetabuilder.cpp @@@ -1,369 -1,0 +1,313 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qfastmetabuilder_p.h" + +#include ++#include ++#include + +QT_BEGIN_NAMESPACE + +struct QFastMetaBuilderHeader +{ + int fieldCount; +}; + - struct QMetaObjectPrivate - { - int revision; - int className; - int classInfoCount, classInfoData; - int methodCount, methodData; - int propertyCount, propertyData; - int enumeratorCount, enumeratorData; - int constructorCount, constructorData; //since revision 2 - int flags; //since revision 3 - int signalCount; //since revision 4 - }; - - enum MetaObjectFlag { - DynamicMetaObject = 0x01 - }; - - enum PropertyFlags { - Invalid = 0x00000000, - Readable = 0x00000001, - Writable = 0x00000002, - Resettable = 0x00000004, - EnumOrFlag = 0x00000008, - StdCppSet = 0x00000100, - // Override = 0x00000200, - Constant = 0x00000400, - Final = 0x00000800, - Designable = 0x00001000, - ResolveDesignable = 0x00002000, - Scriptable = 0x00004000, - ResolveScriptable = 0x00008000, - Stored = 0x00010000, - ResolveStored = 0x00020000, - Editable = 0x00040000, - ResolveEditable = 0x00080000, - User = 0x00100000, - ResolveUser = 0x00200000, - Notify = 0x00400000, - Revisioned = 0x00800000 - }; - - enum MethodFlags { - AccessPrivate = 0x00, - AccessProtected = 0x01, - AccessPublic = 0x02, - AccessMask = 0x03, //mask - - MethodMethod = 0x00, - MethodSignal = 0x04, - MethodSlot = 0x08, - MethodConstructor = 0x0c, - MethodTypeMask = 0x0c, - - MethodCompatibility = 0x10, - MethodCloned = 0x20, - MethodScriptable = 0x40, - MethodRevisioned = 0x80 - }; - +#define FMBHEADER_FIELD_COUNT 1 + +#define HEADER_FIELD_COUNT 14 +#define CLASSINFO_FIELD_COUNT 2 +#define METHOD_FIELD_COUNT 5 +#define PROPERTY_FIELD_COUNT 3 +#define PROPERTY_NOTIFY_FIELD_COUNT 1 + +static inline uint *fieldPointer(QByteArray &data) +{ return reinterpret_cast(data.data()) + FMBHEADER_FIELD_COUNT; } + +static inline const uint *fieldPointer(const QByteArray &data) +{ return reinterpret_cast(data.constData()) + FMBHEADER_FIELD_COUNT; } + +static inline QMetaObjectPrivate *priv(QByteArray &data) +{ return reinterpret_cast(fieldPointer(data)); } + +static inline const QMetaObjectPrivate *priv(const QByteArray &data) +{ return reinterpret_cast(fieldPointer(data)); } + +static inline QFastMetaBuilderHeader *header(QByteArray &data) +{ return reinterpret_cast(data.data()); } + +static inline const QFastMetaBuilderHeader *header(const QByteArray &data) +{ return reinterpret_cast(data.constData()); } + +QFastMetaBuilder::QFastMetaBuilder() +: m_zeroPtr(0), m_stringData(0), m_stringDataLength(0), m_stringDataAllocated(0) +{ +} + +QFastMetaBuilder::~QFastMetaBuilder() +{ +} + +QFastMetaBuilder::StringRef QFastMetaBuilder::init(int classNameLength, + int propertyCount, int methodCount, + int signalCount, int classInfoCount) +{ + Q_ASSERT(m_data.isEmpty()); + Q_ASSERT(classNameLength > 0); + Q_ASSERT(propertyCount >= 0); + Q_ASSERT(methodCount >= 0); + Q_ASSERT(signalCount >= 0); + Q_ASSERT(classInfoCount >= 0); + + int fieldCount = FMBHEADER_FIELD_COUNT + + HEADER_FIELD_COUNT + + propertyCount * (PROPERTY_FIELD_COUNT + PROPERTY_NOTIFY_FIELD_COUNT) + + methodCount * (METHOD_FIELD_COUNT) + + signalCount * (METHOD_FIELD_COUNT) + + classInfoCount * CLASSINFO_FIELD_COUNT; + + m_data.resize(fieldCount * sizeof(uint) + classNameLength + 1); + m_stringData = m_data.data() + m_data.size() - classNameLength - 1; + m_stringDataLength = classNameLength + 1; + m_stringDataAllocated = classNameLength + 1; + m_stringData[classNameLength] = 0; + m_zeroPtr = classNameLength; + + header(m_data)->fieldCount = fieldCount; + + QMetaObjectPrivate *p = priv(m_data); + + int dataIndex = HEADER_FIELD_COUNT; + - p->revision = 4; ++ p->revision = 6; + p->className = 0; + + // Class infos + p->classInfoCount = classInfoCount; + if (p->classInfoCount) { + p->classInfoData = dataIndex; + dataIndex += p->classInfoCount * CLASSINFO_FIELD_COUNT; + } else { + p->classInfoData = 0; + } + + // Methods + p->methodCount = methodCount + signalCount; + if (p->methodCount) { + p->methodData = dataIndex; + dataIndex += p->methodCount * METHOD_FIELD_COUNT; + } else { + p->methodData = 0; + } + p->signalCount = signalCount; + + // Properties + p->propertyCount = propertyCount; + if (p->propertyCount) { + p->propertyData = dataIndex; + dataIndex += p->propertyCount * (PROPERTY_FIELD_COUNT + PROPERTY_NOTIFY_FIELD_COUNT); + } else { + p->propertyData = 0; + } + + // Flags + p->flags = DynamicMetaObject; // Always dynamic + + // Enums and constructors not supported + p->enumeratorCount = 0; + p->enumeratorData = 0; + p->constructorCount = 0; + p->constructorData = 0; + + StringRef className; + className._b = this; + className._o = 0; + className._l = classNameLength; + return className; +} + +// Allocate a string of \a length. \a length should *not* include the null terminator. +QFastMetaBuilder::StringRef QFastMetaBuilder::newString(int length) +{ + Q_ASSERT(length > 0); + + StringRef sr; + sr._b = this; + sr._o = m_stringDataLength; + sr._l = length; + + m_stringDataLength += length + 1 /* for null terminator */; + + return sr; +} + +void QFastMetaBuilder::setClassInfo(int index, const StringRef &key, const StringRef &value) +{ + Q_ASSERT(!m_data.isEmpty()); + Q_ASSERT(!key.isEmpty() && !value.isEmpty()); + + QMetaObjectPrivate *p = priv(m_data); + Q_ASSERT(index < p->classInfoCount); + + uint *ptr = fieldPointer(m_data) + p->classInfoData + index * CLASSINFO_FIELD_COUNT; + // classinfo: key, value + ptr[0] = key.offset(); ptr[1] = value.offset(); +} + +void QFastMetaBuilder::setProperty(int index, const StringRef &name, const StringRef &type, + QMetaType::Type mtype, PropertyFlag flags, int notifySignal) +{ + Q_ASSERT(!m_data.isEmpty()); + Q_ASSERT(!name.isEmpty() && !type.isEmpty()); + + QMetaObjectPrivate *p = priv(m_data); + Q_ASSERT(index < p->propertyCount); + + uint *ptr = fieldPointer(m_data) + p->propertyData + index * PROPERTY_FIELD_COUNT; + // properties: name, type, flags + ptr[0] = name.offset(); + ptr[1] = type.offset(); + if (notifySignal == -1) { + ptr[2] = mtype << 24; + ptr[2] |= flags | Scriptable | Readable; + *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = 0; + } else { + ptr[2] = mtype << 24; + ptr[2] |= flags | Scriptable | Readable | Notify; + *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = notifySignal; + } +} + +void QFastMetaBuilder::setProperty(int index, const StringRef &name, const StringRef &type, + QFastMetaBuilder::PropertyFlag flags, int notifySignal) +{ + Q_ASSERT(!m_data.isEmpty()); + Q_ASSERT(!name.isEmpty() && !type.isEmpty()); + + QMetaObjectPrivate *p = priv(m_data); + Q_ASSERT(index < p->propertyCount); + + uint *ptr = fieldPointer(m_data) + p->propertyData + index * PROPERTY_FIELD_COUNT; + // properties: name, type, flags + ptr[0] = name.offset(); + ptr[1] = type.offset(); + if (notifySignal == -1) { + ptr[2] = flags | Scriptable | Readable; + *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = 0; + } else { + ptr[2] = flags | Scriptable | Readable | Notify; + *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = notifySignal; + } +} + +void QFastMetaBuilder::setSignal(int index, const StringRef &signature, + const StringRef ¶meterNames, + const StringRef &type) +{ + Q_ASSERT(!m_data.isEmpty()); + Q_ASSERT(!signature.isEmpty()); + + QMetaObjectPrivate *p = priv(m_data); + int mindex = metaObjectIndexForSignal(index); + + uint *ptr = fieldPointer(m_data) + p->methodData + mindex * METHOD_FIELD_COUNT; + // methods: signature, parameters, type, tag, flags + ptr[0] = signature.offset(); + ptr[1] = parameterNames.isEmpty()?m_zeroPtr:parameterNames.offset(); + ptr[2] = type.isEmpty()?m_zeroPtr:type.offset(); + ptr[3] = m_zeroPtr; + ptr[4] = AccessProtected | MethodSignal; +} + +void QFastMetaBuilder::setMethod(int index, const StringRef &signature, + const StringRef ¶meterNames, + const StringRef &type) +{ + Q_ASSERT(!m_data.isEmpty()); + Q_ASSERT(!signature.isEmpty()); + + QMetaObjectPrivate *p = priv(m_data); + int mindex = metaObjectIndexForMethod(index); + + uint *ptr = fieldPointer(m_data) + p->methodData + mindex * METHOD_FIELD_COUNT; + // methods: signature, parameters, type, tag, flags + ptr[0] = signature.offset(); + ptr[1] = parameterNames.isEmpty()?m_zeroPtr:parameterNames.offset(); + ptr[2] = type.isEmpty()?m_zeroPtr:type.offset(); + ptr[3] = m_zeroPtr; + ptr[4] = AccessProtected | MethodSlot; +} + +int QFastMetaBuilder::metaObjectIndexForSignal(int index) const +{ + Q_ASSERT(!m_data.isEmpty()); + Q_ASSERT(index < priv(m_data)->signalCount); + return index; +} + +int QFastMetaBuilder::metaObjectIndexForMethod(int index) const +{ + Q_ASSERT(!m_data.isEmpty()); + + const QMetaObjectPrivate *p = priv(m_data); + Q_ASSERT(index < (p->methodCount - p->signalCount)); + return index + p->signalCount; +} + +void QFastMetaBuilder::allocateStringData() +{ + if (m_stringDataAllocated < m_stringDataLength) { + m_data.resize(m_data.size() + m_stringDataLength - m_stringDataAllocated); + m_stringDataAllocated = m_stringDataLength; + m_stringData = m_data.data() + header(m_data)->fieldCount * sizeof(uint); + } +} + +void QFastMetaBuilder::fromData(QMetaObject *output, const QMetaObject *parent, const QByteArray &data) +{ + output->d.superdata = parent; + output->d.stringdata = data.constData() + header(data)->fieldCount * sizeof(uint); + output->d.data = fieldPointer(data); ++ output->d.extradata = 0; +} + +QT_END_NAMESPACE diff --cc src/qml/qml/qqmlboundsignal.cpp index 6f55245,0000000..ca6b13e mode 100644,000000..100644 --- a/src/qml/qml/qqmlboundsignal.cpp +++ b/src/qml/qml/qqmlboundsignal.cpp @@@ -1,300 -1,0 +1,305 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmlboundsignal_p.h" + +#include +#include "qqmlengine_p.h" +#include "qqmlexpression_p.h" +#include "qqmlcontext_p.h" +#include "qqmlmetatype_p.h" +#include "qqml.h" +#include "qqmlcontext.h" +#include "qqmlglobal_p.h" +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class QQmlBoundSignalParameters : public QObject +{ +Q_OBJECT +public: + QQmlBoundSignalParameters(const QMetaMethod &, QObject * = 0); + ~QQmlBoundSignalParameters(); + + void setValues(void **); + void clearValues(); + +private: + friend class MetaObject; + int metaCall(QMetaObject::Call, int _id, void **); + struct MetaObject : public QAbstractDynamicMetaObject { + MetaObject(QQmlBoundSignalParameters *b) + : parent(b) {} + + int metaCall(QMetaObject::Call c, int id, void **a) { + return parent->metaCall(c, id, a); + } + QQmlBoundSignalParameters *parent; + }; + + int *types; + void **values; + QMetaObject *myMetaObject; +}; + +static int evaluateIdx = -1; + +QQmlAbstractBoundSignal::QQmlAbstractBoundSignal(QObject *parent) +: QObject(parent) +{ +} + +QQmlAbstractBoundSignal::~QQmlAbstractBoundSignal() +{ +} + +QQmlBoundSignal::QQmlBoundSignal(QObject *scope, const QMetaMethod &signal, + QObject *parent) +: m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0) +{ + // This is thread safe. Although it may be updated by two threads, they + // will both set it to the same value - so the worst thing that can happen + // is that they both do the work to figure it out. Boo hoo. + if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount(); + + QQml_setParent_noEvent(this, parent); + QQmlPropertyPrivate::connect(scope, m_signal.methodIndex(), this, evaluateIdx); +} + +QQmlBoundSignal::QQmlBoundSignal(QQmlContext *ctxt, const QString &val, + QObject *scope, const QMetaMethod &signal, + QObject *parent) +: m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0) +{ + // This is thread safe. Although it may be updated by two threads, they + // will both set it to the same value - so the worst thing that can happen + // is that they both do the work to figure it out. Boo hoo. + if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount(); + + QQml_setParent_noEvent(this, parent); + QQmlPropertyPrivate::connect(scope, m_signal.methodIndex(), this, evaluateIdx); + + m_expression = new QQmlExpression(ctxt, scope, val); +} + +QQmlBoundSignal::~QQmlBoundSignal() +{ + delete m_expression; + m_expression = 0; +} + +int QQmlBoundSignal::index() const +{ + return m_signal.methodIndex(); +} + +/*! + Returns the signal expression. +*/ +QQmlExpression *QQmlBoundSignal::expression() const +{ + return m_expression; +} + +/*! + Sets the signal expression to \a e. Returns the current signal expression, + or null if there is no signal expression. + + The QQmlBoundSignal instance takes ownership of \a e. The caller is + assumes ownership of the returned QQmlExpression. +*/ +QQmlExpression *QQmlBoundSignal::setExpression(QQmlExpression *e) +{ + QQmlExpression *rv = m_expression; + m_expression = e; + if (m_expression) m_expression->setNotifyOnValueChanged(false); + return rv; +} + +QQmlBoundSignal *QQmlBoundSignal::cast(QObject *o) +{ + QQmlAbstractBoundSignal *s = qobject_cast(o); + return static_cast(s); +} + +int QQmlBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a) +{ + if (c == QMetaObject::InvokeMetaMethod && id == evaluateIdx) { + if (!m_expression) + return -1; - if (QQmlDebugService::isDebuggingEnabled()) { - QQmlProfilerService::startRange(QQmlProfilerService::HandlingSignal); - QQmlProfilerService::rangeData(QQmlProfilerService::HandlingSignal, QLatin1String(m_signal.signature()) % QLatin1String(": ") % m_expression->expression()); - QQmlProfilerService::rangeLocation(QQmlProfilerService::HandlingSignal, m_expression->sourceFile(), m_expression->lineNumber(), m_expression->columnNumber()); ++ ++ if (QQmlDebugService::isDebuggingEnabled()) + QV8DebugService::instance()->signalEmitted(QString::fromAscii(m_signal.signature())); ++ ++ QQmlHandlingSignalProfiler prof; ++ if (prof.enabled) { ++ prof.setSignalInfo(QString::fromLatin1(m_signal.signature()), ++ m_expression->expression()); ++ prof.setLocation(m_expression->sourceFile(), m_expression->lineNumber(), ++ m_expression->columnNumber()); + } ++ + m_isEvaluating = true; + if (!m_paramsValid) { + if (!m_signal.parameterTypes().isEmpty()) + m_params = new QQmlBoundSignalParameters(m_signal, this); + m_paramsValid = true; + } + + if (m_params) m_params->setValues(a); + if (m_expression && m_expression->engine()) { + QQmlExpressionPrivate::get(m_expression)->value(m_params); + if (m_expression && m_expression->hasError()) + QQmlEnginePrivate::warning(m_expression->engine(), m_expression->error()); + } + if (m_params) m_params->clearValues(); + m_isEvaluating = false; - QQmlProfilerService::endRange(QQmlProfilerService::HandlingSignal); + return -1; + } else { + return QObject::qt_metacall(c, id, a); + } +} + +QQmlBoundSignalParameters::QQmlBoundSignalParameters(const QMetaMethod &method, + QObject *parent) +: QObject(parent), types(0), values(0) +{ + MetaObject *mo = new MetaObject(this); + + // ### Optimize! + QMetaObjectBuilder mob; + mob.setSuperClass(&QQmlBoundSignalParameters::staticMetaObject); + mob.setClassName("QQmlBoundSignalParameters"); + + QList paramTypes = method.parameterTypes(); + QList paramNames = method.parameterNames(); + types = new int[paramTypes.count()]; + for (int ii = 0; ii < paramTypes.count(); ++ii) { + const QByteArray &type = paramTypes.at(ii); + const QByteArray &name = paramNames.at(ii); + + if (name.isEmpty() || type.isEmpty()) { + types[ii] = 0; + continue; + } + + QVariant::Type t = (QVariant::Type)QMetaType::type(type.constData()); + if (QQmlMetaType::isQObject(t)) { + types[ii] = QMetaType::QObjectStar; + QMetaPropertyBuilder prop = mob.addProperty(name, "QObject*"); + prop.setWritable(false); + } else { + QByteArray propType = type; + if (t >= QVariant::UserType || t == QVariant::Invalid) { + QByteArray scope; + QByteArray name; + int scopeIdx = propType.lastIndexOf("::"); + if (scopeIdx != -1) { + scope = propType.left(scopeIdx); + name = propType.mid(scopeIdx + 2); + } else { + name = propType; + } + const QMetaObject *meta; + if (scope == "Qt") + meta = &QObject::staticQtMetaObject; + else + meta = parent->parent()->metaObject(); //### assumes parent->parent() + for (int i = meta->enumeratorCount() - 1; i >= 0; --i) { + QMetaEnum m = meta->enumerator(i); + if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope))) { + t = QVariant::Int; + propType = "int"; + break; + } + } + } + types[ii] = t; + QMetaPropertyBuilder prop = mob.addProperty(name, propType); + prop.setWritable(false); + } + } + myMetaObject = mob.toMetaObject(); + *static_cast(mo) = *myMetaObject; + + d_ptr->metaObject = mo; +} + +QQmlBoundSignalParameters::~QQmlBoundSignalParameters() +{ + delete [] types; + free(myMetaObject); +} + +void QQmlBoundSignalParameters::setValues(void **v) +{ + values = v; +} + +void QQmlBoundSignalParameters::clearValues() +{ + values = 0; +} + +int QQmlBoundSignalParameters::metaCall(QMetaObject::Call c, int id, void **a) +{ + if (!values) + return -1; + + if (c == QMetaObject::ReadProperty && id >= 1) { + int t = types[id - 1]; + void *p = a[0]; + QMetaType::destruct(t, p); + QMetaType::construct(t, p, values[id]); + return -1; + } else { + return qt_metacall(c, id, a); + } +} + +QT_END_NAMESPACE + +#include diff --cc src/qml/qml/qqmlcompiler.cpp index 65247e1,0000000..23c4adc mode 100644,000000..100644 --- a/src/qml/qml/qqmlcompiler.cpp +++ b/src/qml/qml/qqmlcompiler.cpp @@@ -1,3882 -1,0 +1,3904 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmlcompiler_p.h" + +#include "qqmlpropertyvaluesource.h" +#include "qqmlcomponent.h" +#include +#include +#include "qqmlstringconverters_p.h" +#include "qqmlengine_p.h" +#include "qqmlengine.h" +#include "qqmlcontext.h" +#include "qqmlmetatype_p.h" +#include "qqmlcustomparser_p_p.h" +#include "qqmlcontext_p.h" +#include "qqmlcomponent_p.h" +#include +#include "qqmlvmemetaobject_p.h" +#include "qqmlexpression_p.h" +#include "qqmlproperty_p.h" +#include "qqmlrewrite_p.h" +#include "qqmlscriptstring.h" +#include "qqmlglobal_p.h" +#include "qqmlbinding_p.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QList) + +QT_BEGIN_NAMESPACE + +DEFINE_BOOL_CONFIG_OPTION(compilerDump, QML_COMPILER_DUMP); +DEFINE_BOOL_CONFIG_OPTION(compilerStatDump, QML_COMPILER_STATS); + +using namespace QQmlJS; +using namespace QQmlScript; +using namespace QQmlCompilerTypes; + +static QString id_string(QLatin1String("id")); +static QString on_string(QLatin1String("on")); +static QString Changed_string(QLatin1String("Changed")); +static QString Component_string(QLatin1String("Component")); +static QString Component_import_string(QLatin1String("QML/Component")); +static QString qsTr_string(QLatin1String("qsTr")); +static QString qsTrId_string(QLatin1String("qsTrId")); + +/*! + Instantiate a new QQmlCompiler. +*/ +QQmlCompiler::QQmlCompiler(QQmlPool *pool) +: pool(pool), output(0), engine(0), unitRoot(0), unit(0), cachedComponentTypeRef(-1), + cachedTranslationContextIndex(-1), componentStats(0) +{ + if (compilerStatDump()) + componentStats = pool->New(); +} + +/*! + Returns true if the last call to compile() caused errors. + + \sa errors() +*/ +bool QQmlCompiler::isError() const +{ + return !exceptions.isEmpty(); +} + +/*! + Return the list of errors from the last call to compile(), or an empty list + if there were no errors. +*/ +QList QQmlCompiler::errors() const +{ + return exceptions; +} + +/*! + Returns true if \a name refers to an attached property, false otherwise. + + Attached property names are those that start with a capital letter. +*/ +bool QQmlCompiler::isAttachedPropertyName(const QString &name) +{ + return isAttachedPropertyName(QHashedStringRef(&name)); +} + +bool QQmlCompiler::isAttachedPropertyName(const QHashedStringRef &name) +{ + return !name.isEmpty() && name.at(0).isUpper(); +} + +/*! + Returns true if \a name refers to a signal property, false otherwise. + + Signal property names are those that start with "on", followed by a first + character which is either a capital letter or one or more underscores followed + by a capital letter, which is then followed by other allowed characters. + + Note that although ECMA-262r3 supports dollarsigns and escaped unicode + character codes in property names, for simplicity and performance reasons + QML only supports letters, numbers and underscores. +*/ +bool QQmlCompiler::isSignalPropertyName(const QString &name) +{ + return isSignalPropertyName(QStringRef(&name)); +} + +bool QQmlCompiler::isSignalPropertyName(const QHashedStringRef &name) +{ + if (name.length() < 3) return false; + if (!name.startsWith(on_string)) return false; + int ns = name.length(); + for (int i = 2; i < ns; ++i) { + const QChar curr = name.at(i); + if (curr.unicode() == '_') continue; + if (curr.isUpper()) return true; + return false; + } + return false; // consists solely of underscores - invalid. +} + +/*! + \macro COMPILE_EXCEPTION + \internal + Inserts an error into the QQmlCompiler error list, and returns false + (failure). + + \a token is used to source the error line and column, and \a desc is the + error itself. \a desc can be an expression that can be piped into QDebug. + + For example: + + \code + COMPILE_EXCEPTION(property, tr("Error for property \"%1\"").arg(property->name)); + \endcode +*/ +#define COMPILE_EXCEPTION_LOCATION(line, column, desc) \ + { \ + QQmlError error; \ + error.setUrl(output->url); \ + error.setLine(line); \ + error.setColumn(column); \ + error.setDescription(desc.trimmed()); \ + exceptions << error; \ + return false; \ + } + +#define COMPILE_EXCEPTION(token, desc) \ + COMPILE_EXCEPTION_LOCATION((token)->location.start.line, (token)->location.start.column, desc) + +/*! + \macro COMPILE_CHECK + \internal + Returns false if \a is false, otherwise does nothing. +*/ +#define COMPILE_CHECK(a) \ + { \ + if (!a) return false; \ + } + +/*! + Returns true if literal \a v can be assigned to property \a prop, otherwise + false. + + This test corresponds to action taken by genLiteralAssignment(). Any change + made here, must have a corresponding action in genLiteralAssigment(). +*/ +bool QQmlCompiler::testLiteralAssignment(QQmlScript::Property *prop, + QQmlScript::Value *v) +{ + const QQmlScript::Variant &value = v->value; + + if (!prop->core.isWritable() && !prop->isReadOnlyDeclaration) + COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString())); + + if (prop->core.isEnum()) { + QMetaProperty p = prop->parent->metaObject()->property(prop->index); + int enumValue; + bool ok; + if (p.isFlagType()) { + enumValue = p.enumerator().keysToValue(value.asString().toUtf8().constData(), &ok); + } else + enumValue = p.enumerator().keyToValue(value.asString().toUtf8().constData(), &ok); + + if (!ok) + COMPILE_EXCEPTION(v, tr("Invalid property assignment: unknown enumeration")); + + v->value = QQmlScript::Variant((double)enumValue); + return true; + } + + int type = prop->type; + + switch(type) { + case QMetaType::QVariant: + break; + case QVariant::String: + if (!v->value.isString()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: string expected")); + break; + case QVariant::StringList: // we expect a string literal. A string list is not a literal assignment. + if (!v->value.isString()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: string or string list expected")); + break; + case QVariant::ByteArray: + if (!v->value.isString()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: byte array expected")); + break; + case QVariant::Url: + if (!v->value.isString()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: url expected")); + break; + case QVariant::RegExp: + COMPILE_EXCEPTION(v, tr("Invalid property assignment: regular expression expected; use /pattern/ syntax")); + break; + case QVariant::UInt: + { + bool ok = v->value.isNumber(); + if (ok) { + double n = v->value.asNumber(); + if (double(uint(n)) != n) + ok = false; + } + if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: unsigned int expected")); + } + break; + case QVariant::Int: + { + bool ok = v->value.isNumber(); + if (ok) { + double n = v->value.asNumber(); + if (double(int(n)) != n) + ok = false; + } + if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: int expected")); + } + break; + case QMetaType::Float: + if (!v->value.isNumber()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: number expected")); + break; + case QVariant::Double: + if (!v->value.isNumber()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: number expected")); + break; + case QVariant::Color: + { + bool ok; + QQmlStringConverters::colorFromString(value.asString(), &ok); + if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: color expected")); + } + break; +#ifndef QT_NO_DATESTRING + case QVariant::Date: + { + bool ok; + QQmlStringConverters::dateFromString(value.asString(), &ok); + if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: date expected")); + } + break; + case QVariant::Time: + { + bool ok; + QQmlStringConverters::timeFromString(value.asString(), &ok); + if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: time expected")); + } + break; + case QVariant::DateTime: + { + bool ok; + QQmlStringConverters::dateTimeFromString(value.asString(), &ok); + if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: datetime expected")); + } + break; +#endif // QT_NO_DATESTRING + case QVariant::Point: + case QVariant::PointF: + { + bool ok; + QQmlStringConverters::pointFFromString(value.asString(), &ok); + if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: point expected")); + } + break; + case QVariant::Size: + case QVariant::SizeF: + { + bool ok; + QQmlStringConverters::sizeFFromString(value.asString(), &ok); + if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: size expected")); + } + break; + case QVariant::Rect: + case QVariant::RectF: + { + bool ok; + QQmlStringConverters::rectFFromString(value.asString(), &ok); + if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: rect expected")); + } + break; + case QVariant::Bool: + { + if (!v->value.isBoolean()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: boolean expected")); + } + break; + case QVariant::Vector3D: + { + bool ok; + QQmlStringConverters::vector3DFromString(value.asString(), &ok); + if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: 3D vector expected")); + } + break; + case QVariant::Vector4D: + { + bool ok; + QQmlStringConverters::vector4DFromString(value.asString(), &ok); + if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: 4D vector expected")); + } + break; + default: + { + // check if assigning a literal value to a list property. + // in each case, check the singular, since an Array of the specified type + // will not go via this literal assignment codepath. + if (type == qMetaTypeId >()) { + if (!v->value.isNumber()) { + COMPILE_EXCEPTION(v, tr("Invalid property assignment: real or array of reals expected")); + } + break; + } else if (type == qMetaTypeId >()) { + bool ok = v->value.isNumber(); + if (ok) { + double n = v->value.asNumber(); + if (double(int(n)) != n) + ok = false; + } + if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: int or array of ints expected")); + break; + } else if (type == qMetaTypeId >()) { + if (!v->value.isBoolean()) { + COMPILE_EXCEPTION(v, tr("Invalid property assignment: bool or array of bools expected")); + } + break; + } else if (type == qMetaTypeId >()) { // we expect a string literal. A string list is not a literal assignment. + if (!v->value.isString()) { + COMPILE_EXCEPTION(v, tr("Invalid property assignment: string or array of strings expected")); + } + break; + } else if (type == qMetaTypeId >()) { + if (!v->value.isString()) { + COMPILE_EXCEPTION(v, tr("Invalid property assignment: url or array of urls expected")); + } + break; + } + + // otherwise, check for existence of string converter to custom type + QQmlMetaType::StringConverter converter = QQmlMetaType::customStringConverter(type); + if (!converter) + COMPILE_EXCEPTION(v, tr("Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QVariant::typeToName((QVariant::Type)type)))); + } + break; + } + return true; +} + +static QUrl urlFromUserString(const QString &data) +{ + QUrl u; + // Preserve any valid percent-encoded octets supplied by the source + u.setEncodedUrl(data.toUtf8(), QUrl::TolerantMode); + return u; +} + +/*! + Generate a store instruction for assigning literal \a v to property \a prop. + + Any literal assignment that is approved in testLiteralAssignment() must have + a corresponding action in this method. +*/ +void QQmlCompiler::genLiteralAssignment(QQmlScript::Property *prop, + QQmlScript::Value *v) +{ + if (prop->core.isEnum()) { + Q_ASSERT(v->value.isNumber()); + // Preresolved value + int value = (int)v->value.asNumber(); + + Instruction::StoreInteger instr; + instr.propertyIndex = prop->index; + instr.value = value; + output->addInstruction(instr); + return; + } + + int type = prop->type; + switch(type) { + case QMetaType::QVariant: + { + if (v->value.isNumber()) { + double n = v->value.asNumber(); + if (double(int(n)) == n) { + if (prop->core.isVMEProperty()) { + Instruction::StoreVarInteger instr; + instr.propertyIndex = prop->index; + instr.value = int(n); + output->addInstruction(instr); + } else { + Instruction::StoreVariantInteger instr; + instr.propertyIndex = prop->index; + instr.value = int(n); + output->addInstruction(instr); + } + } else { + if (prop->core.isVMEProperty()) { + Instruction::StoreVarDouble instr; + instr.propertyIndex = prop->index; + instr.value = n; + output->addInstruction(instr); + } else { + Instruction::StoreVariantDouble instr; + instr.propertyIndex = prop->index; + instr.value = n; + output->addInstruction(instr); + } + } + } else if (v->value.isBoolean()) { + if (prop->core.isVMEProperty()) { + Instruction::StoreVarBool instr; + instr.propertyIndex = prop->index; + instr.value = v->value.asBoolean(); + output->addInstruction(instr); + } else { + Instruction::StoreVariantBool instr; + instr.propertyIndex = prop->index; + instr.value = v->value.asBoolean(); + output->addInstruction(instr); + } + } else { + if (prop->core.isVMEProperty()) { + Instruction::StoreVar instr; + instr.propertyIndex = prop->index; + instr.value = output->indexForString(v->value.asString()); + output->addInstruction(instr); + } else { + Instruction::StoreVariant instr; + instr.propertyIndex = prop->index; + instr.value = output->indexForString(v->value.asString()); + output->addInstruction(instr); + } + } + } + break; + case QVariant::String: + { + Instruction::StoreString instr; + instr.propertyIndex = prop->index; + instr.value = output->indexForString(v->value.asString()); + output->addInstruction(instr); + } + break; + case QVariant::StringList: + { + Instruction::StoreStringList instr; + instr.propertyIndex = prop->index; + instr.value = output->indexForString(v->value.asString()); + output->addInstruction(instr); + } + break; + case QVariant::ByteArray: + { + Instruction::StoreByteArray instr; + instr.propertyIndex = prop->index; + instr.value = output->indexForByteArray(v->value.asString().toLatin1()); + output->addInstruction(instr); + } + break; + case QVariant::Url: + { + Instruction::StoreUrl instr; + QString string = v->value.asString(); + QUrl u = string.isEmpty() ? QUrl() : output->url.resolved(urlFromUserString(string)); + instr.propertyIndex = prop->index; + instr.value = output->indexForUrl(u); + output->addInstruction(instr); + } + break; + case QVariant::UInt: + { + Instruction::StoreInteger instr; + instr.propertyIndex = prop->index; + instr.value = uint(v->value.asNumber()); + output->addInstruction(instr); + } + break; + case QVariant::Int: + { + Instruction::StoreInteger instr; + instr.propertyIndex = prop->index; + instr.value = int(v->value.asNumber()); + output->addInstruction(instr); + } + break; + case QMetaType::Float: + { + Instruction::StoreFloat instr; + instr.propertyIndex = prop->index; + instr.value = float(v->value.asNumber()); + output->addInstruction(instr); + } + break; + case QVariant::Double: + { + Instruction::StoreDouble instr; + instr.propertyIndex = prop->index; + instr.value = v->value.asNumber(); + output->addInstruction(instr); + } + break; + case QVariant::Color: + { + Instruction::StoreColor instr; + QColor c = QQmlStringConverters::colorFromString(v->value.asString()); + instr.propertyIndex = prop->index; + instr.value = c.rgba(); + output->addInstruction(instr); + } + break; +#ifndef QT_NO_DATESTRING + case QVariant::Date: + { + Instruction::StoreDate instr; + QDate d = QQmlStringConverters::dateFromString(v->value.asString()); + instr.propertyIndex = prop->index; + instr.value = d.toJulianDay(); + output->addInstruction(instr); + } + break; + case QVariant::Time: + { + Instruction::StoreTime instr; + QTime time = QQmlStringConverters::timeFromString(v->value.asString()); + instr.propertyIndex = prop->index; + Q_ASSERT(sizeof(instr.time) == sizeof(QTime)); + ::memcpy(&instr.time, &time, sizeof(QTime)); + output->addInstruction(instr); + } + break; + case QVariant::DateTime: + { + Instruction::StoreDateTime instr; + QDateTime dateTime = QQmlStringConverters::dateTimeFromString(v->value.asString()); + QTime time = dateTime.time(); + instr.propertyIndex = prop->index; + instr.date = dateTime.date().toJulianDay(); + Q_ASSERT(sizeof(instr.time) == sizeof(QTime)); + ::memcpy(&instr.time, &time, sizeof(QTime)); + output->addInstruction(instr); + } + break; +#endif // QT_NO_DATESTRING + case QVariant::Point: + { + Instruction::StorePoint instr; + bool ok; + QPoint point = QQmlStringConverters::pointFFromString(v->value.asString(), &ok).toPoint(); + instr.propertyIndex = prop->index; + instr.point.xp = point.x(); + instr.point.yp = point.y(); + output->addInstruction(instr); + } + break; + case QVariant::PointF: + { + Instruction::StorePointF instr; + bool ok; + QPointF point = QQmlStringConverters::pointFFromString(v->value.asString(), &ok); + instr.propertyIndex = prop->index; + instr.point.xp = point.x(); + instr.point.yp = point.y(); + output->addInstruction(instr); + } + break; + case QVariant::Size: + { + Instruction::StoreSize instr; + bool ok; + QSize size = QQmlStringConverters::sizeFFromString(v->value.asString(), &ok).toSize(); + instr.propertyIndex = prop->index; + instr.size.wd = size.width(); + instr.size.ht = size.height(); + output->addInstruction(instr); + } + break; + case QVariant::SizeF: + { + Instruction::StoreSizeF instr; + bool ok; + QSizeF size = QQmlStringConverters::sizeFFromString(v->value.asString(), &ok); + instr.propertyIndex = prop->index; + instr.size.wd = size.width(); + instr.size.ht = size.height(); + output->addInstruction(instr); + } + break; + case QVariant::Rect: + { + Instruction::StoreRect instr; + bool ok; + QRect rect = QQmlStringConverters::rectFFromString(v->value.asString(), &ok).toRect(); + instr.propertyIndex = prop->index; + instr.rect.x1 = rect.left(); + instr.rect.y1 = rect.top(); + instr.rect.x2 = rect.right(); + instr.rect.y2 = rect.bottom(); + output->addInstruction(instr); + } + break; + case QVariant::RectF: + { + Instruction::StoreRectF instr; + bool ok; + QRectF rect = QQmlStringConverters::rectFFromString(v->value.asString(), &ok); + instr.propertyIndex = prop->index; + instr.rect.xp = rect.left(); + instr.rect.yp = rect.top(); + instr.rect.w = rect.width(); + instr.rect.h = rect.height(); + output->addInstruction(instr); + } + break; + case QVariant::Bool: + { + Instruction::StoreBool instr; + bool b = v->value.asBoolean(); + instr.propertyIndex = prop->index; + instr.value = b; + output->addInstruction(instr); + } + break; + case QVariant::Vector3D: + { + Instruction::StoreVector3D instr; + bool ok; + QVector3D vector = QQmlStringConverters::vector3DFromString(v->value.asString(), &ok); + instr.propertyIndex = prop->index; + instr.vector.xp = vector.x(); + instr.vector.yp = vector.y(); + instr.vector.zp = vector.z(); + output->addInstruction(instr); + } + break; + case QVariant::Vector4D: + { + Instruction::StoreVector4D instr; + bool ok; + QVector4D vector = QQmlStringConverters::vector4DFromString(v->value.asString(), &ok); + instr.propertyIndex = prop->index; + instr.vector.xp = vector.x(); + instr.vector.yp = vector.y(); + instr.vector.zp = vector.z(); + instr.vector.wp = vector.w(); + output->addInstruction(instr); + } + break; + default: + { + // generate single literal value assignment to a list property if required + if (type == qMetaTypeId >()) { + Instruction::StoreDoubleQList instr; + instr.propertyIndex = prop->index; + instr.value = v->value.asNumber(); + output->addInstruction(instr); + break; + } else if (type == qMetaTypeId >()) { + Instruction::StoreIntegerQList instr; + instr.propertyIndex = prop->index; + instr.value = int(v->value.asNumber()); + output->addInstruction(instr); + break; + } else if (type == qMetaTypeId >()) { + Instruction::StoreBoolQList instr; + bool b = v->value.asBoolean(); + instr.propertyIndex = prop->index; + instr.value = b; + output->addInstruction(instr); + break; + } else if (type == qMetaTypeId >()) { + Instruction::StoreUrlQList instr; + QString string = v->value.asString(); + QUrl u = string.isEmpty() ? QUrl() : output->url.resolved(urlFromUserString(string)); + instr.propertyIndex = prop->index; + instr.value = output->indexForUrl(u); + output->addInstruction(instr); + break; + } else if (type == qMetaTypeId >()) { + Instruction::StoreStringQList instr; + instr.propertyIndex = prop->index; + instr.value = output->indexForString(v->value.asString()); + output->addInstruction(instr); + break; + } + + // otherwise, generate custom type literal assignment + Instruction::AssignCustomType instr; + instr.propertyIndex = prop->index; + instr.primitive = output->indexForString(v->value.asString()); + instr.type = type; + output->addInstruction(instr); + } + break; + } +} + +/*! + Resets data by clearing the lists that the QQmlCompiler modifies. +*/ +void QQmlCompiler::reset(QQmlCompiledData *data) +{ + data->types.clear(); + data->primitives.clear(); + data->datas.clear(); + data->bytecode.resize(0); +} + +/*! + Compile \a unit, and store the output in \a out. \a engine is the QQmlEngine + with which the QQmlCompiledData will be associated. + + Returns true on success, false on failure. On failure, the compile errors + are available from errors(). + + If the environment variant QML_COMPILER_DUMP is set + (eg. QML_COMPILER_DUMP=1) the compiled instructions will be dumped to stderr + on a successful compiler. +*/ +bool QQmlCompiler::compile(QQmlEngine *engine, + QQmlTypeData *unit, + QQmlCompiledData *out) +{ + exceptions.clear(); + + Q_ASSERT(out); + reset(out); + + QQmlScript::Object *root = unit->parser().tree(); + Q_ASSERT(root); + + this->engine = engine; + this->enginePrivate = QQmlEnginePrivate::get(engine); + this->unit = unit; + this->unitRoot = root; + this->output = out; + + // Compile types + const QList &resolvedTypes = unit->resolvedTypes(); + QList referencedTypes = unit->parser().referencedTypes(); + + for (int ii = 0; ii < resolvedTypes.count(); ++ii) { + QQmlCompiledData::TypeReference ref; + + const QQmlTypeData::TypeReference &tref = resolvedTypes.at(ii); + QQmlScript::TypeReference *parserRef = referencedTypes.at(ii); + + if (tref.type) { + ref.type = tref.type; + if (!ref.type->isCreatable()) { + QString err = ref.type->noCreationReason(); + if (err.isEmpty()) + err = tr( "Element is not creatable."); + COMPILE_EXCEPTION(parserRef->refObjects.first(), err); + } + + if (ref.type->containsRevisionedAttributes()) { + QQmlError cacheError; + ref.typePropertyCache = enginePrivate->cache(ref.type, resolvedTypes.at(ii).minorVersion, + cacheError); + if (!ref.typePropertyCache) + COMPILE_EXCEPTION(parserRef->refObjects.first(), cacheError.description()); + ref.typePropertyCache->addref(); + } + + } else if (tref.typeData) { + ref.component = tref.typeData->compiledData(); + } + ref.className = parserRef->name; + out->types << ref; + } + + compileTree(root); + + if (!isError()) { + if (compilerDump()) + out->dumpInstructions(); + if (componentStats) + dumpStats(); + Q_ASSERT(out->rootPropertyCache); + } else { + reset(out); + } + + compileState = 0; + output = 0; + this->engine = 0; + this->enginePrivate = 0; + this->unit = 0; + this->cachedComponentTypeRef = -1; + this->cachedTranslationContextIndex = -1; + this->unitRoot = 0; + + return !isError(); +} + +void QQmlCompiler::compileTree(QQmlScript::Object *tree) +{ + compileState = pool->New(); + + compileState->root = tree; + if (componentStats) + componentStats->componentStat.lineNumber = tree->location.start.line; + + // We generate the importCache before we build the tree so that + // it can be used in the binding compiler. Given we "expect" the + // QML compilation to succeed, this isn't a waste. + output->importCache = new QQmlTypeNameCache(); + foreach (const QString &ns, unit->namespaces()) { + output->importCache->add(ns); + } + + int scriptIndex = 0; + foreach (const QQmlTypeData::ScriptReference &script, unit->resolvedScripts()) { + QString qualifier = script.qualifier; + QString enclosingNamespace; + + const int lastDotIndex = qualifier.lastIndexOf(QLatin1Char('.')); + if (lastDotIndex != -1) { + enclosingNamespace = qualifier.left(lastDotIndex); + qualifier = qualifier.mid(lastDotIndex+1); + } + + output->importCache->add(qualifier, scriptIndex++, enclosingNamespace); + } + + unit->imports().populateCache(output->importCache, engine); + + if (!buildObject(tree, BindingContext()) || !completeComponentBuild()) + return; + + Instruction::Init init; + init.bindingsSize = compileState->totalBindingsCount; + init.parserStatusSize = compileState->parserStatusCount; + init.contextCache = genContextCache(); + init.objectStackSize = compileState->objectDepth.maxDepth(); + init.listStackSize = compileState->listDepth.maxDepth(); + if (compileState->compiledBindingData.isEmpty()) + init.compiledBinding = -1; + else + init.compiledBinding = output->indexForByteArray(compileState->compiledBindingData); + output->addInstruction(init); + + foreach (const QQmlTypeData::ScriptReference &script, unit->resolvedScripts()) { + Instruction::StoreImportedScript import; + import.value = output->scripts.count(); + + QQmlScriptData *scriptData = script.script->scriptData(); + scriptData->addref(); + output->scripts << scriptData; + output->addInstruction(import); + } + + if (!compileState->v8BindingProgram.isEmpty()) { + Instruction::InitV8Bindings bindings; + int index = output->programs.count(); + + typedef QQmlCompiledData::V8Program V8Program; + output->programs.append(V8Program(compileState->v8BindingProgram, output)); + + bindings.programIndex = index; + bindings.line = compileState->v8BindingProgramLine; + output->addInstruction(bindings); + } + + genObject(tree); + + Instruction::SetDefault def; + output->addInstruction(def); + + Instruction::Done done; + output->addInstruction(done); + + Q_ASSERT(tree->metatype); + + if (tree->metadata.isEmpty()) { + output->root = tree->metatype; + } else { + static_cast(output->rootData) = *tree->metaObject(); + output->root = &output->rootData; + } + if (!tree->metadata.isEmpty()) + enginePrivate->registerCompositeType(output); +} + +static bool QStringList_contains(const QStringList &list, const QHashedStringRef &string) +{ + for (int ii = 0; ii < list.count(); ++ii) + if (string == list.at(ii)) + return true; + + return false; +} + +bool QQmlCompiler::buildObject(QQmlScript::Object *obj, const BindingContext &ctxt) +{ + if (componentStats) + componentStats->componentStat.objects++; + + Q_ASSERT (obj->type != -1); + const QQmlCompiledData::TypeReference &tr = output->types.at(obj->type); + obj->metatype = tr.metaObject(); + + if (tr.type) + obj->typeName = tr.type->qmlTypeName(); + + // This object is a "Component" element + if (tr.type && obj->metatype == &QQmlComponent::staticMetaObject) { + COMPILE_CHECK(buildComponent(obj, ctxt)); + return true; + } + + if (tr.component) { + typedef QQmlInstruction I; + const I *init = ((const I *)tr.component->bytecode.constData()); + Q_ASSERT(init && tr.component->instructionType(init) == QQmlInstruction::Init); + + // Adjust stack depths to include nested components + compileState->objectDepth.pushPop(init->init.objectStackSize); + compileState->listDepth.pushPop(init->init.listStackSize); + compileState->parserStatusCount += init->init.parserStatusSize; + compileState->totalBindingsCount += init->init.bindingsSize; + } + + compileState->objectDepth.push(); + + // Object instantiations reset the binding context + BindingContext objCtxt(obj); + + // Create the synthesized meta object, ignoring aliases + COMPILE_CHECK(checkDynamicMeta(obj)); + COMPILE_CHECK(mergeDynamicMetaProperties(obj)); + COMPILE_CHECK(buildDynamicMeta(obj, IgnoreAliases)); + + // Find the native type and check for the QQmlParserStatus interface + QQmlType *type = toQmlType(obj); + Q_ASSERT(type); + obj->parserStatusCast = type->parserStatusCast(); + if (obj->parserStatusCast != -1) + compileState->parserStatusCount++; + + // Check if this is a custom parser type. Custom parser types allow + // assignments to non-existent properties. These assignments are then + // compiled by the type. + bool isCustomParser = output->types.at(obj->type).type && + output->types.at(obj->type).type->customParser() != 0; + QList customProps; + + // Fetch the list of deferred properties + QStringList deferredList = deferredProperties(obj); + + // Must do id property first. This is to ensure that the id given to any + // id reference created matches the order in which the objects are + // instantiated + for (Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) { + if (prop->name() == id_string) { + COMPILE_CHECK(buildProperty(prop, obj, objCtxt)); + break; + } + } + + // Merge + Property *defaultProperty = 0; + Property *skipProperty = 0; + if (obj->defaultProperty) { + defaultProperty = obj->defaultProperty; + + Property *explicitProperty = 0; + + const QMetaObject *mo = obj->metatype; + int idx = mo->indexOfClassInfo("DefaultProperty"); + if (idx != -1) { + QMetaClassInfo info = mo->classInfo(idx); + const char *p = info.value(); + if (p) { + int plen = 0; + char ord = 0; + while (char c = p[plen++]) { ord |= c; }; + --plen; + + if (ord & 0x80) { + // Utf8 - unoptimal, but seldom hit + QString *s = pool->NewString(QString::fromUtf8(p, plen)); + QHashedStringRef r(*s); + + if (obj->propertiesHashField.test(r.hash())) { + for (Property *ep = obj->properties.first(); ep; ep = obj->properties.next(ep)) { + if (ep->name() == r) { + explicitProperty = ep; + break; + } + } + } + + if (!explicitProperty) + defaultProperty->setName(r); + + } else { + QHashedCStringRef r(p, plen); + + if (obj->propertiesHashField.test(r.hash())) { + for (Property *ep = obj->properties.first(); ep; ep = obj->properties.next(ep)) { + if (ep->name() == r) { + explicitProperty = ep; + break; + } + } + } + + if (!explicitProperty) { + // Set the default property name + QChar *buffer = pool->NewRawArray(r.length()); + r.writeUtf16(buffer); + defaultProperty->setName(QHashedStringRef(buffer, r.length(), r.hash())); + } + } + } + } + + if (explicitProperty && !explicitProperty->value && !explicitProperty->values.isEmpty()) { + + skipProperty = explicitProperty; // We merge the values into defaultProperty + + // Find the correct insertion point + Value *insertPos = 0; + + for (Value *v = defaultProperty->values.first(); v; v = Property::ValueList::next(v)) { + if (!(v->location.start < explicitProperty->values.first()->location.start)) + break; + insertPos = v; + } + + defaultProperty->values.insertAfter(insertPos, explicitProperty->values); + } + } + + QQmlCustomParser *cp = 0; + if (isCustomParser) + cp = output->types.at(obj->type).type->customParser(); + + // Build all explicit properties specified + for (Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) { + + if (prop == skipProperty) + continue; + if (prop->name() == id_string) + continue; + + bool canDefer = false; + if (isCustomParser) { + if (doesPropertyExist(prop, obj) && + (!(cp->flags() & QQmlCustomParser::AcceptsAttachedProperties) || + !isAttachedPropertyName(prop->name()))) { + int ids = compileState->ids.count(); + COMPILE_CHECK(buildProperty(prop, obj, objCtxt)); + canDefer = ids == compileState->ids.count(); + } else if (isSignalPropertyName(prop->name()) && + (cp->flags() & QQmlCustomParser::AcceptsSignalHandlers)) { + COMPILE_CHECK(buildSignal(prop,obj,objCtxt)); + } else { + customProps << QQmlCustomParserNodePrivate::fromProperty(prop); + } + } else { + if (isSignalPropertyName(prop->name())) { + COMPILE_CHECK(buildSignal(prop,obj,objCtxt)); + } else { + int ids = compileState->ids.count(); + COMPILE_CHECK(buildProperty(prop, obj, objCtxt)); + canDefer = ids == compileState->ids.count(); + } + } + + if (canDefer && !deferredList.isEmpty() && QStringList_contains(deferredList, prop->name())) + prop->isDeferred = true; + + } + + // Build the default property + if (defaultProperty) { + Property *prop = defaultProperty; + + bool canDefer = false; + if (isCustomParser) { + if (doesPropertyExist(prop, obj)) { + int ids = compileState->ids.count(); + COMPILE_CHECK(buildProperty(prop, obj, objCtxt)); + canDefer = ids == compileState->ids.count(); + } else { + customProps << QQmlCustomParserNodePrivate::fromProperty(prop); + } + } else { + int ids = compileState->ids.count(); + COMPILE_CHECK(buildProperty(prop, obj, objCtxt)); + canDefer = ids == compileState->ids.count(); + } + + if (canDefer && !deferredList.isEmpty() && QStringList_contains(deferredList, prop->name())) + prop->isDeferred = true; + } + + // Compile custom parser parts + if (isCustomParser && !customProps.isEmpty()) { + cp->clearErrors(); + cp->compiler = this; + cp->object = obj; + obj->custom = cp->compile(customProps); + cp->compiler = 0; + cp->object = 0; + foreach (QQmlError err, cp->errors()) { + err.setUrl(output->url); + exceptions << err; + } + } + + compileState->objectDepth.pop(); + + return true; +} + +void QQmlCompiler::genObject(QQmlScript::Object *obj) +{ + QQmlCompiledData::TypeReference &tr = output->types[obj->type]; + if (tr.type && obj->metatype == &QQmlComponent::staticMetaObject) { + genComponent(obj); + return; + } + + // Create the object + if (obj->custom.isEmpty() && output->types.at(obj->type).type && + !output->types.at(obj->type).type->isExtendedType() && obj != compileState->root) { + + Instruction::CreateSimpleObject create; + create.create = output->types.at(obj->type).type->createFunction(); + create.typeSize = output->types.at(obj->type).type->createSize(); + create.type = obj->type; + create.line = obj->location.start.line; + create.column = obj->location.start.column; + output->addInstruction(create); + + } else { + + if (output->types.at(obj->type).type) { + Instruction::CreateCppObject create; + create.line = obj->location.start.line; + create.column = obj->location.start.column; + create.data = -1; + if (!obj->custom.isEmpty()) + create.data = output->indexForByteArray(obj->custom); + create.type = obj->type; + create.isRoot = (compileState->root == obj); + output->addInstruction(create); + } else { + Instruction::CreateQMLObject create; + create.type = obj->type; + create.isRoot = (compileState->root == obj); + + if (!obj->bindingBitmask.isEmpty()) { + Q_ASSERT(obj->bindingBitmask.size() % 4 == 0); + create.bindingBits = output->indexForByteArray(obj->bindingBitmask); + } else { + create.bindingBits = -1; + } + output->addInstruction(create); + + Instruction::CompleteQMLObject complete; + complete.line = obj->location.start.line; + complete.column = obj->location.start.column; + complete.isRoot = (compileState->root == obj); + output->addInstruction(complete); + } + } + + // Setup the synthesized meta object if necessary + if (!obj->metadata.isEmpty()) { + Instruction::StoreMetaObject meta; + meta.data = output->indexForByteArray(obj->metadata); + meta.aliasData = output->indexForByteArray(obj->synthdata); + meta.propertyCache = output->propertyCaches.count(); + + QQmlPropertyCache *propertyCache = obj->synthCache; + Q_ASSERT(propertyCache); + propertyCache->addref(); + + // Add flag for alias properties + if (!obj->synthdata.isEmpty()) { + const QQmlVMEMetaData *vmeMetaData = + reinterpret_cast(obj->synthdata.constData()); + for (int ii = 0; ii < vmeMetaData->aliasCount; ++ii) { + int index = obj->metaObject()->propertyOffset() + vmeMetaData->propertyCount + ii; + QQmlPropertyData *data = propertyCache->property(index); + data->setFlags(data->getFlags() | QQmlPropertyData::IsAlias); + } + } + + if (obj == unitRoot) { + propertyCache->addref(); + output->rootPropertyCache = propertyCache; + } + + output->propertyCaches << propertyCache; + output->addInstruction(meta); + } else if (obj == unitRoot) { + output->rootPropertyCache = tr.createPropertyCache(engine); + output->rootPropertyCache->addref(); + } + + // Set the object id + if (!obj->id.isEmpty()) { + Instruction::SetId id; + id.value = output->indexForString(obj->id); + id.index = obj->idIndex; + output->addInstruction(id); + } + + // Begin the class + if (tr.type && obj->parserStatusCast != -1) { + Instruction::BeginObject begin; + begin.castValue = obj->parserStatusCast; + output->addInstruction(begin); + } + + genObjectBody(obj); +} + +void QQmlCompiler::genObjectBody(QQmlScript::Object *obj) +{ + for (Property *prop = obj->scriptStringProperties.first(); prop; prop = Object::PropertyList::next(prop)) { + Q_ASSERT(prop->scriptStringScope != -1); + const QString &script = prop->values.first()->value.asScript(); + Instruction::StoreScriptString ss; + ss.propertyIndex = prop->index; + ss.value = output->indexForString(script); + ss.scope = prop->scriptStringScope; +// ss.bindingId = rewriteBinding(script, prop->name()); + ss.bindingId = rewriteBinding(prop->values.first()->value, QString()); // XXX + ss.line = prop->location.start.line; + ss.column = prop->location.start.column; + output->addInstruction(ss); + } + + bool seenDefer = false; + for (Property *prop = obj->valueProperties.first(); prop; prop = Object::PropertyList::next(prop)) { + if (prop->isDeferred) { + seenDefer = true; + continue; + } + if (!prop->isAlias) + genValueProperty(prop, obj); + } + if (seenDefer) { + Instruction::Defer defer; + defer.deferCount = 0; + int deferIdx = output->addInstruction(defer); + int nextInstructionIndex = output->nextInstructionIndex(); + + Instruction::DeferInit dinit; + // XXX - these are now massive over allocations + dinit.bindingsSize = compileState->totalBindingsCount; + dinit.parserStatusSize = compileState->parserStatusCount; + dinit.objectStackSize = compileState->objectDepth.maxDepth(); + dinit.listStackSize = compileState->listDepth.maxDepth(); + output->addInstruction(dinit); + + for (Property *prop = obj->valueProperties.first(); prop; prop = Object::PropertyList::next(prop)) { + if (!prop->isDeferred) + continue; + genValueProperty(prop, obj); + } + + Instruction::Done done; + output->addInstruction(done); + + output->instruction(deferIdx)->defer.deferCount = output->nextInstructionIndex() - nextInstructionIndex; + } + + for (Property *prop = obj->signalProperties.first(); prop; prop = Object::PropertyList::next(prop)) { + + QQmlScript::Value *v = prop->values.first(); + + if (v->type == Value::SignalObject) { + + genObject(v->object); + + Instruction::AssignSignalObject assign; + assign.line = v->location.start.line; + assign.signal = output->indexForString(prop->name().toString()); + output->addInstruction(assign); + + } else if (v->type == Value::SignalExpression) { + + Instruction::StoreSignal store; + store.signalIndex = prop->index; + const QString &rewrite = rewriteSignalHandler(v->value, prop->name().toString()); + store.value = output->indexForByteArray(rewrite.toUtf8()); + store.context = v->signalExpressionContextStack; + store.line = v->location.start.line; + store.column = v->location.start.column; + output->addInstruction(store); + + } + + } + + for (Property *prop = obj->attachedProperties.first(); prop; prop = Object::PropertyList::next(prop)) { + Instruction::FetchAttached fetch; + fetch.id = prop->index; + fetch.line = prop->location.start.line; + output->addInstruction(fetch); + + genObjectBody(prop->value); + + Instruction::PopFetchedObject pop; + output->addInstruction(pop); + } + + for (Property *prop = obj->groupedProperties.first(); prop; prop = Object::PropertyList::next(prop)) { + Instruction::FetchObject fetch; + fetch.property = prop->index; + fetch.line = prop->location.start.line; + output->addInstruction(fetch); + + if (!prop->value->metadata.isEmpty()) { + Instruction::StoreMetaObject meta; + meta.data = output->indexForByteArray(prop->value->metadata); + meta.aliasData = output->indexForByteArray(prop->value->synthdata); + meta.propertyCache = -1; + output->addInstruction(meta); + } + + genObjectBody(prop->value); + + Instruction::PopFetchedObject pop; + output->addInstruction(pop); + } + + for (Property *prop = obj->valueTypeProperties.first(); prop; prop = Object::PropertyList::next(prop)) { + if (!prop->isAlias) + genValueTypeProperty(obj, prop); + } + + for (Property *prop = obj->valueProperties.first(); prop; prop = Object::PropertyList::next(prop)) { + if (prop->isDeferred) + continue; + if (prop->isAlias) + genValueProperty(prop, obj); + } + + for (Property *prop = obj->valueTypeProperties.first(); prop; prop = Object::PropertyList::next(prop)) { + if (prop->isAlias) + genValueTypeProperty(obj, prop); + } +} + +void QQmlCompiler::genValueTypeProperty(QQmlScript::Object *obj,QQmlScript::Property *prop) +{ + Instruction::FetchValueType fetch; + fetch.property = prop->index; + fetch.type = prop->type; + fetch.bindingSkipList = 0; + + if (obj->type == -1 || output->types.at(obj->type).component) { + // We only have to do this if this is a composite type. If it is a builtin + // type it can't possibly already have bindings that need to be cleared. + for (Property *vprop = prop->value->valueProperties.first(); vprop; vprop = Object::PropertyList::next(vprop)) { + if (!vprop->values.isEmpty()) { + Q_ASSERT(vprop->index >= 0 && vprop->index < 32); + fetch.bindingSkipList |= (1 << vprop->index); + } + } + } + + output->addInstruction(fetch); + + for (Property *vprop = prop->value->valueProperties.first(); vprop; vprop = Object::PropertyList::next(vprop)) { + genPropertyAssignment(vprop, prop->value, prop); + } + + Instruction::PopValueType pop; + pop.property = prop->index; + pop.type = prop->type; + pop.bindingSkipList = 0; + output->addInstruction(pop); +} + +void QQmlCompiler::genComponent(QQmlScript::Object *obj) +{ + QQmlScript::Object *root = obj->defaultProperty->values.first()->object; + Q_ASSERT(root); + + Instruction::CreateComponent create; + create.line = root->location.start.line; + create.column = root->location.start.column; + create.endLine = root->location.end.line; + create.isRoot = (compileState->root == obj); + int createInstruction = output->addInstruction(create); + int nextInstructionIndex = output->nextInstructionIndex(); + + ComponentCompileState *oldCompileState = compileState; + compileState = componentState(root); + + Instruction::Init init; + init.bindingsSize = compileState->totalBindingsCount; + init.parserStatusSize = compileState->parserStatusCount; + init.contextCache = genContextCache(); + init.objectStackSize = compileState->objectDepth.maxDepth(); + init.listStackSize = compileState->listDepth.maxDepth(); + if (compileState->compiledBindingData.isEmpty()) + init.compiledBinding = -1; + else + init.compiledBinding = output->indexForByteArray(compileState->compiledBindingData); + output->addInstruction(init); + + if (!compileState->v8BindingProgram.isEmpty()) { + Instruction::InitV8Bindings bindings; + int index = output->programs.count(); + + typedef QQmlCompiledData::V8Program V8Program; + output->programs.append(V8Program(compileState->v8BindingProgram, output)); + + bindings.programIndex = index; + bindings.line = compileState->v8BindingProgramLine; + output->addInstruction(bindings); + } + + genObject(root); + + Instruction::SetDefault def; + output->addInstruction(def); + + Instruction::Done done; + output->addInstruction(done); + + output->instruction(createInstruction)->createComponent.count = + output->nextInstructionIndex() - nextInstructionIndex; + + compileState = oldCompileState; + + if (!obj->id.isEmpty()) { + Instruction::SetId id; + id.value = output->indexForString(obj->id); + id.index = obj->idIndex; + output->addInstruction(id); + } + + if (obj == unitRoot) { + output->rootPropertyCache = output->types[obj->type].createPropertyCache(engine); + output->rootPropertyCache->addref(); + } +} + +bool QQmlCompiler::buildComponent(QQmlScript::Object *obj, + const BindingContext &ctxt) +{ + // The special "Component" element can only have the id property and a + // default property, that actually defines the component's tree + + compileState->objectDepth.push(); + + // Find, check and set the "id" property (if any) + Property *idProp = 0; + if (obj->properties.isMany() || + (obj->properties.isOne() && obj->properties.first()->name() != id_string)) + COMPILE_EXCEPTION(obj->properties.first(), tr("Component elements may not contain properties other than id")); + + if (!obj->properties.isEmpty()) + idProp = obj->properties.first(); + + if (idProp) { + if (idProp->value || idProp->values.isMany() || idProp->values.first()->object) + COMPILE_EXCEPTION(idProp, tr("Invalid component id specification")); + COMPILE_CHECK(checkValidId(idProp->values.first(), idProp->values.first()->primitive())) + + QString idVal = idProp->values.first()->primitive(); + + if (compileState->ids.value(idVal)) + COMPILE_EXCEPTION(idProp, tr("id is not unique")); + + obj->id = idVal; + addId(idVal, obj); + } + + // Check the Component tree is well formed + if (obj->defaultProperty && + (obj->defaultProperty->value || obj->defaultProperty->values.isMany() || + (obj->defaultProperty->values.isOne() && !obj->defaultProperty->values.first()->object))) + COMPILE_EXCEPTION(obj, tr("Invalid component body specification")); + + if (!obj->dynamicProperties.isEmpty()) + COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new properties.")); + if (!obj->dynamicSignals.isEmpty()) + COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new signals.")); + if (!obj->dynamicSlots.isEmpty()) + COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new functions.")); + + QQmlScript::Object *root = 0; + if (obj->defaultProperty && !obj->defaultProperty->values.isEmpty()) + root = obj->defaultProperty->values.first()->object; + + if (!root) + COMPILE_EXCEPTION(obj, tr("Cannot create empty component specification")); + + // Build the component tree + COMPILE_CHECK(buildComponentFromRoot(root, ctxt)); + + compileState->objectDepth.pop(); + + return true; +} + +bool QQmlCompiler::buildComponentFromRoot(QQmlScript::Object *obj, + const BindingContext &ctxt) +{ + ComponentCompileState *oldComponentCompileState = compileState; + compileState = pool->New(); + compileState->root = obj; + compileState->nested = true; + + if (componentStats) { + ComponentStat oldComponentStat = componentStats->componentStat; + + componentStats->componentStat = ComponentStat(); + componentStats->componentStat.lineNumber = obj->location.start.line; + + if (obj) + COMPILE_CHECK(buildObject(obj, ctxt)); + + COMPILE_CHECK(completeComponentBuild()); + + componentStats->componentStat = oldComponentStat; + } else { + if (obj) + COMPILE_CHECK(buildObject(obj, ctxt)); + + COMPILE_CHECK(completeComponentBuild()); + } + + compileState = oldComponentCompileState; + + return true; +} + + +// Build a sub-object. A sub-object is one that was not created directly by +// QML - such as a grouped property object, or an attached object. Sub-object's +// can't have an id, involve a custom parser, have attached properties etc. +bool QQmlCompiler::buildSubObject(QQmlScript::Object *obj, const BindingContext &ctxt) +{ + Q_ASSERT(obj->metatype); + Q_ASSERT(!obj->defaultProperty); + Q_ASSERT(ctxt.isSubContext()); // sub-objects must always be in a binding + // sub-context + + for (Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) { + if (isSignalPropertyName(prop->name())) { + COMPILE_CHECK(buildSignal(prop, obj, ctxt)); + } else { + COMPILE_CHECK(buildProperty(prop, obj, ctxt)); + } + } + + return true; +} + +int QQmlCompiler::componentTypeRef() +{ + if (cachedComponentTypeRef == -1) { + QQmlType *t = QQmlMetaType::qmlType(Component_import_string,1,0); + for (int ii = output->types.count() - 1; ii >= 0; --ii) { + if (output->types.at(ii).type == t) { + cachedComponentTypeRef = ii; + return ii; + } + } + QQmlCompiledData::TypeReference ref; + ref.className = Component_string; + ref.type = t; + output->types << ref; + cachedComponentTypeRef = output->types.count() - 1; + } + return cachedComponentTypeRef; +} + +int QQmlCompiler::translationContextIndex() +{ + if (cachedTranslationContextIndex == -1) { + // This code must match that in the qsTr() implementation + const QString &path = output->name; + int lastSlash = path.lastIndexOf(QLatin1Char('/')); + QString context = (lastSlash > -1) ? path.mid(lastSlash + 1, path.length()-lastSlash-5) : + QString(); + QByteArray contextUtf8 = context.toUtf8(); + cachedTranslationContextIndex = output->indexForByteArray(contextUtf8); + } + return cachedTranslationContextIndex; +} + +bool QQmlCompiler::buildSignal(QQmlScript::Property *prop, QQmlScript::Object *obj, + const BindingContext &ctxt) +{ + Q_ASSERT(obj->metaObject()); + + const QHashedStringRef &propName = prop->name(); + + Q_ASSERT(propName.startsWith(on_string)); + QString name = propName.mid(2, -1).toString(); + + // Note that the property name could start with any alpha or '_' or '$' character, + // so we need to do the lower-casing of the first alpha character. + for (int firstAlphaIndex = 0; firstAlphaIndex < name.size(); ++firstAlphaIndex) { + if (name.at(firstAlphaIndex).isUpper()) { + name[firstAlphaIndex] = name.at(firstAlphaIndex).toLower(); + break; + } + } + + bool notInRevision = false; + + QQmlPropertyData *sig = signal(obj, QStringRef(&name), ¬InRevision); + + if (sig == 0) { + + if (notInRevision && 0 == property(obj, propName, 0)) { + Q_ASSERT(obj->type != -1); + const QList &resolvedTypes = unit->resolvedTypes(); + const QQmlTypeData::TypeReference &type = resolvedTypes.at(obj->type); + if (type.type) { + COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(elementName(obj)).arg(prop->name().toString()).arg(type.type->module()).arg(type.majorVersion).arg(type.minorVersion)); + } else { + COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available due to component versioning.").arg(elementName(obj)).arg(prop->name().toString())); + } + } + + // If the "on" name doesn't resolve into a signal, try it as a + // property. + COMPILE_CHECK(buildProperty(prop, obj, ctxt)); + + } else { + + if (prop->value || !prop->values.isOne()) + COMPILE_EXCEPTION(prop, tr("Incorrectly specified signal assignment")); + + prop->index = sig->coreIndex; + prop->core = *sig; + + obj->addSignalProperty(prop); + + if (prop->values.first()->object) { + COMPILE_CHECK(buildObject(prop->values.first()->object, ctxt)); + prop->values.first()->type = Value::SignalObject; + } else { + prop->values.first()->type = Value::SignalExpression; + + if (!prop->values.first()->value.isScript()) + COMPILE_EXCEPTION(prop, tr("Cannot assign a value to a signal (expecting a script to be run)")); + + QString script = prop->values.first()->value.asScript().trimmed(); + if (script.isEmpty()) + COMPILE_EXCEPTION(prop, tr("Empty signal assignment")); + + prop->values.first()->signalExpressionContextStack = ctxt.stack; + } + } + + return true; +} + + +/*! + Returns true if (value) property \a prop exists on obj, false otherwise. +*/ +bool QQmlCompiler::doesPropertyExist(QQmlScript::Property *prop, + QQmlScript::Object *obj) +{ + if (prop->name().isEmpty()) + return false; + if(isAttachedPropertyName(prop->name()) || prop->name() == id_string) + return true; + + return property(obj, prop->name()) != 0; +} + +bool QQmlCompiler::buildProperty(QQmlScript::Property *prop, + QQmlScript::Object *obj, + const BindingContext &ctxt) +{ + if (prop->isEmpty()) + COMPILE_EXCEPTION(prop, tr("Empty property assignment")); + + const QMetaObject *metaObject = obj->metaObject(); + Q_ASSERT(metaObject); + + if (isAttachedPropertyName(prop->name())) { + // Setup attached property data + + if (ctxt.isSubContext()) { + // Attached properties cannot be used on sub-objects. Sub-objects + // always exist in a binding sub-context, which is what we test + // for here. + COMPILE_EXCEPTION(prop, tr("Attached properties cannot be used here")); + } + + QQmlType *type = 0; + QQmlImportedNamespace *typeNamespace = 0; + unit->imports().resolveType(prop->name().toString(), &type, 0, 0, 0, &typeNamespace); + + if (typeNamespace) { + COMPILE_CHECK(buildPropertyInNamespace(typeNamespace, prop, obj, + ctxt)); + return true; + } else if (!type || !type->attachedPropertiesType()) { + COMPILE_EXCEPTION(prop, tr("Non-existent attached object")); + } + + if (!prop->value) + COMPILE_EXCEPTION(prop, tr("Invalid attached object assignment")); + + Q_ASSERT(type->attachedPropertiesFunction()); + prop->index = type->attachedPropertiesId(); + prop->value->metatype = type->attachedPropertiesType(); + } else { + // Setup regular property data + bool notInRevision = false; + QQmlPropertyData *d = + prop->name().isEmpty()?0:property(obj, prop->name(), ¬InRevision); + + if (d == 0 && notInRevision) { + const QList &resolvedTypes = unit->resolvedTypes(); + const QQmlTypeData::TypeReference &type = resolvedTypes.at(obj->type); + if (type.type) { + COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(elementName(obj)).arg(prop->name().toString()).arg(type.type->module()).arg(type.majorVersion).arg(type.minorVersion)); + } else { + COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available due to component versioning.").arg(elementName(obj)).arg(prop->name().toString())); + } + } else if (d) { + prop->index = d->coreIndex; + prop->core = *d; + } else if (prop->isDefault) { + QMetaProperty p = QQmlMetaType::defaultProperty(metaObject); + QQmlPropertyData defaultPropertyData; + defaultPropertyData.load(p, engine); + if (p.name()) + prop->setName(QLatin1String(p.name())); + prop->core = defaultPropertyData; + prop->index = prop->core.coreIndex; + } + + // We can't error here as the "id" property does not require a + // successful index resolution + if (prop->index != -1) + prop->type = prop->core.propType; + + // Check if this is an alias + if (prop->index != -1 && + prop->parent && + prop->parent->type != -1 && + output->types.at(prop->parent->type).component) { + + QQmlPropertyCache *cache = output->types.at(prop->parent->type).component->rootPropertyCache; + if (cache && cache->property(prop->index) && cache->property(prop->index)->isAlias()) + prop->isAlias = true; + } + + if (prop->index != -1 && !prop->values.isEmpty()) + prop->parent->setBindingBit(prop->index); + } + + if (!prop->isDefault && prop->name() == id_string && !ctxt.isSubContext()) { + + // The magic "id" behavior doesn't apply when "id" is resolved as a + // default property or to sub-objects (which are always in binding + // sub-contexts) + COMPILE_CHECK(buildIdProperty(prop, obj)); + if (prop->type == QVariant::String && + prop->values.first()->value.isString()) + COMPILE_CHECK(buildPropertyAssignment(prop, obj, ctxt)); + + } else if (isAttachedPropertyName(prop->name())) { + + COMPILE_CHECK(buildAttachedProperty(prop, obj, ctxt)); + + } else if (prop->index == -1) { + + if (prop->isDefault) { + COMPILE_EXCEPTION(prop->values.first(), tr("Cannot assign to non-existent default property")); + } else { + COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(prop->name().toString())); + } + + } else if (prop->value) { + + COMPILE_CHECK(buildGroupedProperty(prop, obj, ctxt)); + + } else if (prop->core.isQList()) { + + COMPILE_CHECK(buildListProperty(prop, obj, ctxt)); + + } else if (prop->type == qMetaTypeId()) { + + COMPILE_CHECK(buildScriptStringProperty(prop, obj, ctxt)); + + } else { + + COMPILE_CHECK(buildPropertyAssignment(prop, obj, ctxt)); + + } + + return true; +} + +bool QQmlCompiler::buildPropertyInNamespace(QQmlImportedNamespace *ns, + QQmlScript::Property *nsProp, + QQmlScript::Object *obj, + const BindingContext &ctxt) +{ + if (!nsProp->value) + COMPILE_EXCEPTION(nsProp, tr("Invalid use of namespace")); + + for (Property *prop = nsProp->value->properties.first(); prop; prop = nsProp->value->properties.next(prop)) { + + if (!isAttachedPropertyName(prop->name())) + COMPILE_EXCEPTION(prop, tr("Not an attached property name")); + + // Setup attached property data + + QQmlType *type = 0; + unit->imports().resolveType(ns, prop->name().toString(), &type, 0, 0, 0); + + if (!type || !type->attachedPropertiesType()) + COMPILE_EXCEPTION(prop, tr("Non-existent attached object")); + + if (!prop->value) + COMPILE_EXCEPTION(prop, tr("Invalid attached object assignment")); + + Q_ASSERT(type->attachedPropertiesFunction()); + prop->index = type->index(); + prop->value->metatype = type->attachedPropertiesType(); + + COMPILE_CHECK(buildAttachedProperty(prop, obj, ctxt)); + } + + return true; +} + +void QQmlCompiler::genValueProperty(QQmlScript::Property *prop, + QQmlScript::Object *obj) +{ + if (prop->core.isQList()) { + genListProperty(prop, obj); + } else { + genPropertyAssignment(prop, obj); + } +} + +void QQmlCompiler::genListProperty(QQmlScript::Property *prop, + QQmlScript::Object *obj) +{ + int listType = enginePrivate->listType(prop->type); + + Instruction::FetchQList fetch; + fetch.property = prop->index; + bool listTypeIsInterface = QQmlMetaType::isInterface(listType); + fetch.type = listType; + output->addInstruction(fetch); + + for (Value *v = prop->values.first(); v; v = Property::ValueList::next(v)) { + + if (v->type == Value::CreatedObject) { + + genObject(v->object); + if (listTypeIsInterface) { + Instruction::AssignObjectList assign; + assign.line = prop->location.start.line; + output->addInstruction(assign); + } else { + Instruction::StoreObjectQList store; + output->addInstruction(store); + } + + } else if (v->type == Value::PropertyBinding) { + + genBindingAssignment(v, prop, obj); + + } + + } + + Instruction::PopQList pop; + output->addInstruction(pop); +} + +void QQmlCompiler::genPropertyAssignment(QQmlScript::Property *prop, + QQmlScript::Object *obj, + QQmlScript::Property *valueTypeProperty) +{ + for (Value *v = prop->values.first(); v; v = Property::ValueList::next(v)) { + + Q_ASSERT(v->type == Value::CreatedObject || + v->type == Value::PropertyBinding || + v->type == Value::Literal); + + if (v->type == Value::CreatedObject) { + + genObject(v->object); + + if (QQmlMetaType::isInterface(prop->type)) { + + Instruction::StoreInterface store; + store.line = v->object->location.start.line; + store.propertyIndex = prop->index; + output->addInstruction(store); + + } else if (prop->type == QMetaType::QVariant) { + + if (prop->core.isVMEProperty()) { + Instruction::StoreVarObject store; + store.line = v->object->location.start.line; + store.propertyIndex = prop->index; + output->addInstruction(store); + } else { + Instruction::StoreVariantObject store; + store.line = v->object->location.start.line; + store.propertyIndex = prop->index; + output->addInstruction(store); + } + + + } else { + + Instruction::StoreObject store; + store.line = v->object->location.start.line; + store.propertyIndex = prop->index; + output->addInstruction(store); + + } + } else if (v->type == Value::PropertyBinding) { + + genBindingAssignment(v, prop, obj, valueTypeProperty); + + } else if (v->type == Value::Literal) { + + genLiteralAssignment(prop, v); + + } + + } + + for (Value *v = prop->onValues.first(); v; v = Property::ValueList::next(v)) { + + Q_ASSERT(v->type == Value::ValueSource || + v->type == Value::ValueInterceptor); + + if (v->type == Value::ValueSource) { + genObject(v->object); + + Instruction::StoreValueSource store; + if (valueTypeProperty) { + store.property = genValueTypeData(prop, valueTypeProperty); + store.owner = 1; + } else { + store.property = prop->core; + store.owner = 0; + } + QQmlType *valueType = toQmlType(v->object); + store.castValue = valueType->propertyValueSourceCast(); + output->addInstruction(store); + + } else if (v->type == Value::ValueInterceptor) { + genObject(v->object); + + Instruction::StoreValueInterceptor store; + if (valueTypeProperty) { + store.property = genValueTypeData(prop, valueTypeProperty); + store.owner = 1; + } else { + store.property = prop->core; + store.owner = 0; + } + QQmlType *valueType = toQmlType(v->object); + store.castValue = valueType->propertyValueInterceptorCast(); + output->addInstruction(store); + } + + } +} + +bool QQmlCompiler::buildIdProperty(QQmlScript::Property *prop, + QQmlScript::Object *obj) +{ + if (prop->value || + prop->values.isMany() || + prop->values.first()->object) + COMPILE_EXCEPTION(prop, tr("Invalid use of id property")); + + QQmlScript::Value *idValue = prop->values.first(); + QString val = idValue->primitive(); + + COMPILE_CHECK(checkValidId(idValue, val)); + + if (compileState->ids.value(val)) + COMPILE_EXCEPTION(prop, tr("id is not unique")); + + prop->values.first()->type = Value::Id; + + obj->id = val; + addId(val, obj); + + return true; +} + +void QQmlCompiler::addId(const QString &id, QQmlScript::Object *obj) +{ + Q_UNUSED(id); + Q_ASSERT(!compileState->ids.value(id)); + Q_ASSERT(obj->id == id); + obj->idIndex = compileState->ids.count(); + compileState->ids.append(obj); +} + +void QQmlCompiler::addBindingReference(JSBindingReference *ref) +{ + Q_ASSERT(ref->value && !ref->value->bindingReference); + ref->value->bindingReference = ref; + compileState->totalBindingsCount++; + compileState->bindings.prepend(ref); +} + +void QQmlCompiler::saveComponentState() +{ + Q_ASSERT(compileState->root); + Q_ASSERT(compileState->root->componentCompileState == 0); + + compileState->root->componentCompileState = compileState; + + if (componentStats) + componentStats->savedComponentStats.append(componentStats->componentStat); +} + +QQmlCompilerTypes::ComponentCompileState * +QQmlCompiler::componentState(QQmlScript::Object *obj) +{ + Q_ASSERT(obj->componentCompileState); + return obj->componentCompileState; +} + +// Build attached property object. In this example, +// Text { +// GridView.row: 10 +// } +// GridView is an attached property object. +bool QQmlCompiler::buildAttachedProperty(QQmlScript::Property *prop, + QQmlScript::Object *obj, + const BindingContext &ctxt) +{ + Q_ASSERT(prop->value); + Q_ASSERT(prop->index != -1); // This is set in buildProperty() + + compileState->objectDepth.push(); + + obj->addAttachedProperty(prop); + + COMPILE_CHECK(buildSubObject(prop->value, ctxt.incr())); + + compileState->objectDepth.pop(); + + return true; +} + + +// Build "grouped" properties. In this example: +// Text { +// font.pointSize: 12 +// font.family: "Helvetica" +// } +// font is a nested property. pointSize and family are not. +bool QQmlCompiler::buildGroupedProperty(QQmlScript::Property *prop, + QQmlScript::Object *obj, + const BindingContext &ctxt) +{ + Q_ASSERT(prop->type != 0); + Q_ASSERT(prop->index != -1); + + if (QQmlValueTypeFactory::isValueType(prop->type)) { + if (prop->type >= 0 && enginePrivate->valueTypes[prop->type]) { + + if (!prop->values.isEmpty()) { + if (prop->values.first()->location < prop->value->location) { + COMPILE_EXCEPTION(prop->value, tr( "Property has already been assigned a value")); + } else { + COMPILE_EXCEPTION(prop->values.first(), tr( "Property has already been assigned a value")); + } + } + + if (!prop->core.isWritable() && !prop->isReadOnlyDeclaration) { + COMPILE_EXCEPTION(prop, tr( "Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString())); + } + + + if (prop->isAlias) { + for (Property *vtProp = prop->value->properties.first(); vtProp; vtProp = prop->value->properties.next(vtProp)) { + vtProp->isAlias = true; + } + } + + COMPILE_CHECK(buildValueTypeProperty(enginePrivate->valueTypes[prop->type], + prop->value, obj, ctxt.incr())); + obj->addValueTypeProperty(prop); + } else { + COMPILE_EXCEPTION(prop, tr("Invalid grouped property access")); + } + + } else { + // Load the nested property's meta type + prop->value->metatype = enginePrivate->metaObjectForType(prop->type); + if (!prop->value->metatype) + COMPILE_EXCEPTION(prop, tr("Invalid grouped property access")); + + if (!prop->values.isEmpty()) + COMPILE_EXCEPTION(prop->values.first(), tr( "Cannot assign a value directly to a grouped property")); + + obj->addGroupedProperty(prop); + + compileState->objectDepth.push(); + + COMPILE_CHECK(buildSubObject(prop->value, ctxt.incr())); + + compileState->objectDepth.pop(); + } + + return true; +} + +bool QQmlCompiler::buildValueTypeProperty(QObject *type, + QQmlScript::Object *obj, + QQmlScript::Object *baseObj, + const BindingContext &ctxt) +{ + compileState->objectDepth.push(); + + if (obj->defaultProperty) + COMPILE_EXCEPTION(obj, tr("Invalid property use")); + obj->metatype = type->metaObject(); + + for (Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) { + + QQmlPropertyData *d = property(obj, prop->name()); + if (d == 0) + COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(prop->name().toString())); + + prop->index = d->coreIndex; + prop->type = d->propType; + prop->core = *d; + prop->isValueTypeSubProperty = true; + + if (prop->value) + COMPILE_EXCEPTION(prop, tr("Property assignment expected")); + + if (prop->values.isMany()) { + COMPILE_EXCEPTION(prop, tr("Single property assignment expected")); + } else if (!prop->values.isEmpty()) { + QQmlScript::Value *value = prop->values.first(); + + if (value->object) { + COMPILE_EXCEPTION(prop, tr("Unexpected object assignment")); + } else if (value->value.isScript()) { + // ### Check for writability + + //optimization for . enum assignments + bool isEnumAssignment = false; + + if (prop->core.isEnum()) + COMPILE_CHECK(testQualifiedEnumAssignment(prop, obj, value, &isEnumAssignment)); + + if (isEnumAssignment) { + value->type = Value::Literal; + } else { + JSBindingReference *reference = pool->New(); + reference->expression = value->value; + reference->property = prop; + reference->value = value; + reference->bindingContext = ctxt; + reference->bindingContext.owner++; + addBindingReference(reference); + value->type = Value::PropertyBinding; + } + } else { + COMPILE_CHECK(testLiteralAssignment(prop, value)); + value->type = Value::Literal; + } + } + + for (Value *v = prop->onValues.first(); v; v = Property::ValueList::next(v)) { + Q_ASSERT(v->object); + + COMPILE_CHECK(buildPropertyOnAssignment(prop, obj, baseObj, v, ctxt)); + } + + obj->addValueProperty(prop); + } + + compileState->objectDepth.pop(); + + return true; +} + +// Build assignments to QML lists. QML lists are properties of type +// QQmlListProperty. List properties can accept a list of +// objects, or a single binding. +bool QQmlCompiler::buildListProperty(QQmlScript::Property *prop, + QQmlScript::Object *obj, + const BindingContext &ctxt) +{ + Q_ASSERT(prop->core.isQList()); + + compileState->listDepth.push(); + + int t = prop->type; + + obj->addValueProperty(prop); + + int listType = enginePrivate->listType(t); + bool listTypeIsInterface = QQmlMetaType::isInterface(listType); + + bool assignedBinding = false; + for (Value *v = prop->values.first(); v; v = Property::ValueList::next(v)) { + if (v->object) { + v->type = Value::CreatedObject; + COMPILE_CHECK(buildObject(v->object, ctxt)); + + // We check object coercian here. We check interface assignment + // at runtime. + if (!listTypeIsInterface) { + if (!canCoerce(listType, v->object)) { + COMPILE_EXCEPTION(v, tr("Cannot assign object to list")); + } + } + + } else if (v->value.isScript()) { + if (assignedBinding) + COMPILE_EXCEPTION(v, tr("Can only assign one binding to lists")); + + assignedBinding = true; + COMPILE_CHECK(buildBinding(v, prop, ctxt)); + v->type = Value::PropertyBinding; + } else { + COMPILE_EXCEPTION(v, tr("Cannot assign primitives to lists")); + } + } + + compileState->listDepth.pop(); + + return true; +} + +// Compiles an assignment to a QQmlScriptString property +bool QQmlCompiler::buildScriptStringProperty(QQmlScript::Property *prop, + QQmlScript::Object *obj, + const BindingContext &ctxt) +{ + if (prop->values.isMany()) + COMPILE_EXCEPTION(prop->values.first()->nextValue, tr( "Cannot assign multiple values to a script property")); + + if (prop->values.first()->object) + COMPILE_EXCEPTION(prop->values.first(), tr( "Invalid property assignment: script expected")); + + prop->scriptStringScope = ctxt.stack; + obj->addScriptStringProperty(prop); + + return true; +} + +// Compile regular property assignments of the form "property: " +bool QQmlCompiler::buildPropertyAssignment(QQmlScript::Property *prop, + QQmlScript::Object *obj, + const BindingContext &ctxt) +{ + obj->addValueProperty(prop); + + if (prop->values.isMany()) + COMPILE_EXCEPTION(prop->values.first(), tr( "Cannot assign multiple values to a singular property") ); + + for (Value *v = prop->values.first(); v; v = Property::ValueList::next(v)) { + if (v->object) { + + COMPILE_CHECK(buildPropertyObjectAssignment(prop, obj, v, ctxt)); + + } else { + + COMPILE_CHECK(buildPropertyLiteralAssignment(prop, obj, v, ctxt)); + + } + } + + for (Value *v = prop->onValues.first(); v; v = Property::ValueList::next(v)) { + Q_ASSERT(v->object); + COMPILE_CHECK(buildPropertyOnAssignment(prop, obj, obj, v, ctxt)); + } + + return true; +} + +// Compile assigning a single object instance to a regular property +bool QQmlCompiler::buildPropertyObjectAssignment(QQmlScript::Property *prop, + QQmlScript::Object *obj, + QQmlScript::Value *v, + const BindingContext &ctxt) +{ + Q_ASSERT(prop->index != -1); + Q_ASSERT(v->object->type != -1); + + if (!prop->core.isWritable() && !prop->isReadOnlyDeclaration) + COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString())); + + if (QQmlMetaType::isInterface(prop->type)) { + + // Assigning an object to an interface ptr property + COMPILE_CHECK(buildObject(v->object, ctxt)); + + v->type = Value::CreatedObject; + + } else if (prop->type == QMetaType::QVariant) { + + // Assigning an object to a QVariant + COMPILE_CHECK(buildObject(v->object, ctxt)); + + v->type = Value::CreatedObject; + } else { + // Normally buildObject() will set this up, but we need the static + // meta object earlier to test for assignability. It doesn't matter + // that there may still be outstanding synthesized meta object changes + // on this type, as they are not relevant for assignability testing + v->object->metatype = output->types.at(v->object->type).metaObject(); + Q_ASSERT(v->object->metaObject()); + + // We want to raw metaObject here as the raw metaobject is the + // actual property type before we applied any extensions that might + // effect the properties on the type, but don't effect assignability + const QMetaObject *propertyMetaObject = enginePrivate->rawMetaObjectForType(prop->type); + + // Will be true if the assgned type inherits propertyMetaObject + bool isAssignable = false; + // Determine isAssignable value + if (propertyMetaObject) { + const QMetaObject *c = v->object->metatype; + while(c) { + isAssignable |= (QQmlPropertyPrivate::equal(c, propertyMetaObject)); + c = c->superClass(); + } + } + + if (isAssignable) { + // Simple assignment + COMPILE_CHECK(buildObject(v->object, ctxt)); + + v->type = Value::CreatedObject; + } else if (propertyMetaObject == &QQmlComponent::staticMetaObject) { + // Automatic "Component" insertion + QQmlScript::Object *root = v->object; + QQmlScript::Object *component = pool->New(); + component->type = componentTypeRef(); + component->typeName = QStringLiteral("Qt/Component"); + component->metatype = &QQmlComponent::staticMetaObject; + component->location = root->location; + QQmlScript::Value *componentValue = pool->New(); + componentValue->object = root; + component->getDefaultProperty()->addValue(componentValue); + v->object = component; + COMPILE_CHECK(buildPropertyObjectAssignment(prop, obj, v, ctxt)); + } else { + COMPILE_EXCEPTION(v->object, tr("Cannot assign object to property")); + } + } + + return true; +} + +// Compile assigning a single object instance to a regular property using the "on" syntax. +// +// For example: +// Item { +// NumberAnimation on x { } +// } +bool QQmlCompiler::buildPropertyOnAssignment(QQmlScript::Property *prop, + QQmlScript::Object *obj, + QQmlScript::Object *baseObj, + QQmlScript::Value *v, + const BindingContext &ctxt) +{ + Q_ASSERT(prop->index != -1); + Q_ASSERT(v->object->type != -1); + + Q_UNUSED(obj); + + if (!prop->core.isWritable()) + COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString())); + + + // Normally buildObject() will set this up, but we need the static + // meta object earlier to test for assignability. It doesn't matter + // that there may still be outstanding synthesized meta object changes + // on this type, as they are not relevant for assignability testing + v->object->metatype = output->types.at(v->object->type).metaObject(); + Q_ASSERT(v->object->metaObject()); + + // Will be true if the assigned type inherits QQmlPropertyValueSource + bool isPropertyValue = false; + // Will be true if the assigned type inherits QQmlPropertyValueInterceptor + bool isPropertyInterceptor = false; + if (QQmlType *valueType = toQmlType(v->object)) { + isPropertyValue = valueType->propertyValueSourceCast() != -1; + isPropertyInterceptor = valueType->propertyValueInterceptorCast() != -1; + } + + if (isPropertyValue || isPropertyInterceptor) { + // Assign as a property value source + COMPILE_CHECK(buildObject(v->object, ctxt)); + + if (isPropertyInterceptor && prop->parent->synthdata.isEmpty()) + buildDynamicMeta(baseObj, ForceCreation); + v->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor; + } else { + COMPILE_EXCEPTION(v, tr("\"%1\" cannot operate on \"%2\"").arg(v->object->typeName).arg(prop->name().toString())); + } + + return true; +} + +// Compile assigning a literal or binding to a regular property +bool QQmlCompiler::buildPropertyLiteralAssignment(QQmlScript::Property *prop, + QQmlScript::Object *obj, + QQmlScript::Value *v, + const BindingContext &ctxt) +{ + Q_ASSERT(prop->index != -1); + + if (v->value.isScript()) { + + //optimization for . enum assignments + if (prop->core.isEnum()) { + bool isEnumAssignment = false; + COMPILE_CHECK(testQualifiedEnumAssignment(prop, obj, v, &isEnumAssignment)); + if (isEnumAssignment) { + v->type = Value::Literal; + return true; + } + } + + // Test for other binding optimizations + if (!buildLiteralBinding(v, prop, ctxt)) + COMPILE_CHECK(buildBinding(v, prop, ctxt)); + + v->type = Value::PropertyBinding; + + } else { + + COMPILE_CHECK(testLiteralAssignment(prop, v)); + + v->type = Value::Literal; + } + + return true; +} + +bool QQmlCompiler::testQualifiedEnumAssignment(QQmlScript::Property *prop, + QQmlScript::Object *obj, + QQmlScript::Value *v, + bool *isAssignment) +{ + *isAssignment = false; + if (!prop->core.isEnum()) + return true; + + QMetaProperty mprop = obj->metaObject()->property(prop->index); + + if (!prop->core.isWritable() && !prop->isReadOnlyDeclaration) + COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString())); + + QString string = v->value.asString(); + if (!string.at(0).isUpper()) + return true; + + QStringList parts = string.split(QLatin1Char('.')); + if (parts.count() != 2) + return true; + + QString typeName = parts.at(0); + QQmlType *type = 0; + unit->imports().resolveType(typeName, &type, 0, 0, 0, 0); + + //handle enums on value types (where obj->typeName is empty) + QString objTypeName = obj->typeName; + if (objTypeName.isEmpty()) { + QQmlType *objType = toQmlType(obj); + if (objType) + objTypeName = objType->qmlTypeName(); + } + + if (!type) + return true; + + QString enumValue = parts.at(1); + int value; + bool ok; + + if (objTypeName == type->qmlTypeName()) { + // When these two match, we can short cut the search + if (mprop.isFlagType()) { + value = mprop.enumerator().keysToValue(enumValue.toUtf8().constData(), &ok); + } else { + value = mprop.enumerator().keyToValue(enumValue.toUtf8().constData(), &ok); + } + } else { + // Otherwise we have to search the whole type + // This matches the logic in QV8TypeWrapper + QByteArray enumName = enumValue.toUtf8(); + const QMetaObject *metaObject = type->baseMetaObject(); + ok = false; + for (int ii = metaObject->enumeratorCount() - 1; !ok && ii >= 0; --ii) { + QMetaEnum e = metaObject->enumerator(ii); + value = e.keyToValue(enumName.constData(), &ok); + } + } + + if (!ok) + return true; + + v->type = Value::Literal; + v->value = QQmlScript::Variant((double)value); + *isAssignment = true; + + return true; +} + +struct StaticQtMetaObject : public QObject +{ + static const QMetaObject *get() + { return &static_cast (0)->staticQtMetaObject; } +}; + +// Similar logic to above, but not knowing target property. +int QQmlCompiler::evaluateEnum(const QByteArray& script) const +{ + int dot = script.indexOf('.'); + if (dot > 0) { + const QByteArray &scope = script.left(dot); + QQmlType *type = 0; + unit->imports().resolveType(QString::fromUtf8(script.left(dot)), &type, 0, 0, 0, 0); + if (!type && scope != "Qt") + return -1; + const QMetaObject *mo = type ? type->metaObject() : StaticQtMetaObject::get(); + const char *key = script.constData() + dot+1; + int i = mo->enumeratorCount(); + while (i--) { + bool ok; + int v = mo->enumerator(i).keyToValue(key, &ok); + if (ok) + return v; + } + } + return -1; +} + +const QMetaObject *QQmlCompiler::resolveType(const QString& name) const +{ + QQmlType *qmltype = 0; + if (!unit->imports().resolveType(name, &qmltype, 0, 0, 0, 0)) + return 0; + if (!qmltype) + return 0; + return qmltype->metaObject(); +} + +// similar to logic of completeComponentBuild, but also sticks data +// into primitives at the end +int QQmlCompiler::rewriteBinding(const QQmlScript::Variant& value, const QString& name) +{ + QQmlRewrite::RewriteBinding rewriteBinding; + rewriteBinding.setName(QLatin1Char('$') + name.mid(name.lastIndexOf(QLatin1Char('.')) + 1)); + + QString rewrite = rewriteBinding(value.asAST(), value.asScript(), 0); + + return output->indexForString(rewrite); +} + +QString QQmlCompiler::rewriteSignalHandler(const QQmlScript::Variant& value, const QString &name) +{ + QQmlRewrite::RewriteSignalHandler rewriteSignalHandler; + return rewriteSignalHandler(value.asAST(), value.asScript(), name); +} + +// Ensures that the dynamic meta specification on obj is valid +bool QQmlCompiler::checkDynamicMeta(QQmlScript::Object *obj) +{ + bool seenDefaultProperty = false; + + // We use a coarse grain, 31 bit hash to check if there are duplicates. + // Calculating the hash for the names is not a waste as we have to test + // them against the illegalNames set anyway. + QHashField propNames; + QHashField methodNames; + + // Check properties + for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) { + const QQmlScript::Object::DynamicProperty &prop = *p; + + if (prop.isDefaultProperty) { + if (seenDefaultProperty) + COMPILE_EXCEPTION(&prop, tr("Duplicate default property")); + seenDefaultProperty = true; + } + + if (propNames.testAndSet(prop.name.hash())) { + for (Object::DynamicProperty *p2 = obj->dynamicProperties.first(); p2 != p; + p2 = obj->dynamicProperties.next(p2)) { + if (p2->name == prop.name) { + COMPILE_EXCEPTION_LOCATION(prop.nameLocation.line, + prop.nameLocation.column, + tr("Duplicate property name")); + } + } + } + + if (prop.name.at(0).isUpper()) { + COMPILE_EXCEPTION_LOCATION(prop.nameLocation.line, + prop.nameLocation.column, + tr("Property names cannot begin with an upper case letter")); + } + + if (enginePrivate->v8engine()->illegalNames().contains(prop.name)) { + COMPILE_EXCEPTION_LOCATION(prop.nameLocation.line, + prop.nameLocation.column, + tr("Illegal property name")); + } + } + + for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) { + const QQmlScript::Object::DynamicSignal &currSig = *s; + + if (methodNames.testAndSet(currSig.name.hash())) { + for (Object::DynamicSignal *s2 = obj->dynamicSignals.first(); s2 != s; + s2 = obj->dynamicSignals.next(s2)) { + if (s2->name == currSig.name) + COMPILE_EXCEPTION(&currSig, tr("Duplicate signal name")); + } + } + + if (currSig.name.at(0).isUpper()) + COMPILE_EXCEPTION(&currSig, tr("Signal names cannot begin with an upper case letter")); + if (enginePrivate->v8engine()->illegalNames().contains(currSig.name)) + COMPILE_EXCEPTION(&currSig, tr("Illegal signal name")); + } + + for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) { + const QQmlScript::Object::DynamicSlot &currSlot = *s; + + if (methodNames.testAndSet(currSlot.name.hash())) { + for (Object::DynamicSignal *s2 = obj->dynamicSignals.first(); s2; + s2 = obj->dynamicSignals.next(s2)) { + if (s2->name == currSlot.name) + COMPILE_EXCEPTION(&currSlot, tr("Duplicate method name")); + } + for (Object::DynamicSlot *s2 = obj->dynamicSlots.first(); s2 != s; + s2 = obj->dynamicSlots.next(s2)) { + if (s2->name == currSlot.name) + COMPILE_EXCEPTION(&currSlot, tr("Duplicate method name")); + } + } + + if (currSlot.name.at(0).isUpper()) + COMPILE_EXCEPTION(&currSlot, tr("Method names cannot begin with an upper case letter")); + if (enginePrivate->v8engine()->illegalNames().contains(currSlot.name)) + COMPILE_EXCEPTION(&currSlot, tr("Illegal method name")); + } + + return true; +} + +bool QQmlCompiler::mergeDynamicMetaProperties(QQmlScript::Object *obj) +{ + for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; + p = obj->dynamicProperties.next(p)) { + + if (!p->defaultValue || p->type == Object::DynamicProperty::Alias) + continue; + + Property *property = 0; + if (p->isDefaultProperty) { + property = obj->getDefaultProperty(); + } else { + property = obj->getProperty(p->name); + if (!property->values.isEmpty()) + COMPILE_EXCEPTION(property, tr("Property value set multiple times")); + } + + if (p->isReadOnly) + property->isReadOnlyDeclaration = true; + + if (property->value) + COMPILE_EXCEPTION(property, tr("Invalid property nesting")); + + property->values.append(p->defaultValue->values); + } + return true; +} + +Q_GLOBAL_STATIC(QAtomicInt, classIndexCounter) + +bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mode) +{ + Q_ASSERT(obj); + Q_ASSERT(obj->metatype); + + if (mode != ForceCreation && + obj->dynamicProperties.isEmpty() && + obj->dynamicSignals.isEmpty() && + obj->dynamicSlots.isEmpty()) + return true; + + bool resolveAlias = (mode == ResolveAliases); + + const Object::DynamicProperty *defaultProperty = 0; + int aliasCount = 0; + int varPropCount = 0; + int totalPropCount = 0; + int firstPropertyVarIndex = 0; + + for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) { + + if (p->type == Object::DynamicProperty::Alias) + aliasCount++; + if (p->type == Object::DynamicProperty::Var) + varPropCount++; + + if (p->isDefaultProperty && + (resolveAlias || p->type != Object::DynamicProperty::Alias)) + defaultProperty = p; + + if (!resolveAlias) { + // No point doing this for both the alias and non alias cases + QQmlPropertyData *d = property(obj, p->name); + if (d && d->isFinal()) + COMPILE_EXCEPTION(p, tr("Cannot override FINAL property")); + } + } + + bool buildData = resolveAlias || aliasCount == 0; + + QByteArray dynamicData; + if (buildData) { + typedef QQmlVMEMetaData VMD; + + dynamicData = QByteArray(sizeof(QQmlVMEMetaData) + + (obj->dynamicProperties.count() - aliasCount) * sizeof(VMD::PropertyData) + + obj->dynamicSlots.count() * sizeof(VMD::MethodData) + + aliasCount * sizeof(VMD::AliasData), 0); + } + + int uniqueClassId = classIndexCounter()->fetchAndAddRelaxed(1); + + QByteArray newClassName = obj->metatype->className(); + newClassName.append("_QML_"); + newClassName.append(QByteArray::number(uniqueClassId)); + + if (compileState->root == obj && !compileState->nested) { + QString path = output->url.path(); + int lastSlash = path.lastIndexOf(QLatin1Char('/')); + if (lastSlash > -1) { + QString nameBase = path.mid(lastSlash + 1, path.length()-lastSlash-5); + if (!nameBase.isEmpty() && nameBase.at(0).isUpper()) + newClassName = nameBase.toUtf8() + "_QMLTYPE_" + QByteArray::number(uniqueClassId); + } + } + + QFastMetaBuilder builder; + QFastMetaBuilder::StringRef classNameRef = builder.init(newClassName.length(), + obj->dynamicProperties.count() - (resolveAlias?0:aliasCount), + obj->dynamicSlots.count(), + obj->dynamicSignals.count() + obj->dynamicProperties.count(), + defaultProperty?1:0); + + struct TypeData { + Object::DynamicProperty::Type dtype; + int metaType; + const char *cppType; + } builtinTypes[] = { + { Object::DynamicProperty::Var, QMetaType::QVariant, "QVariant" }, + { Object::DynamicProperty::Variant, QMetaType::QVariant, "QVariant" }, + { Object::DynamicProperty::Int, QMetaType::Int, "int" }, + { Object::DynamicProperty::Bool, QMetaType::Bool, "bool" }, + { Object::DynamicProperty::Real, QMetaType::Double, "double" }, + { Object::DynamicProperty::String, QMetaType::QString, "QString" }, + { Object::DynamicProperty::Url, QMetaType::QUrl, "QUrl" }, + { Object::DynamicProperty::Color, QMetaType::QColor, "QColor" }, + { Object::DynamicProperty::Time, QMetaType::QTime, "QTime" }, + { Object::DynamicProperty::Date, QMetaType::QDate, "QDate" }, + { Object::DynamicProperty::DateTime, QMetaType::QDateTime, "QDateTime" }, + }; + static const int builtinTypeCount = sizeof(builtinTypes) / sizeof(TypeData); + QFastMetaBuilder::StringRef typeRefs[builtinTypeCount]; + + // Reserve dynamic properties + if (obj->dynamicProperties.count()) { + typedef QQmlVMEMetaData VMD; + + int effectivePropertyIndex = 0; + for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) { + + // Reserve space for name + p->nameRef = builder.newString(p->name.utf8length()); + + int propertyType = 0; + bool readonly = false; + QFastMetaBuilder::StringRef typeRef; + + if (p->type == Object::DynamicProperty::Alias) { + continue; + } else if (p->type < builtinTypeCount) { + Q_ASSERT(builtinTypes[p->type].dtype == p->type); + propertyType = builtinTypes[p->type].metaType; + if (typeRefs[p->type].isEmpty()) + typeRefs[p->type] = builder.newString(strlen(builtinTypes[p->type].cppType)); + typeRef = typeRefs[p->type]; + + } else { + Q_ASSERT(p->type == Object::DynamicProperty::CustomList || + p->type == Object::DynamicProperty::Custom); + + // XXX don't double resolve this in the case of an alias run + + QByteArray customTypeName; + QQmlType *qmltype = 0; + QString url; + if (!unit->imports().resolveType(p->customType.toString(), &qmltype, &url, 0, 0, 0)) + COMPILE_EXCEPTION(p, tr("Invalid property type")); + + if (!qmltype) { + QQmlTypeData *tdata = enginePrivate->typeLoader.get(QUrl(url)); + Q_ASSERT(tdata); + Q_ASSERT(tdata->isComplete()); + + QQmlCompiledData *data = tdata->compiledData(); + customTypeName = data->root->className(); + data->release(); + tdata->release(); + } else { + customTypeName = qmltype->typeName(); + } + + if (p->type == Object::DynamicProperty::Custom) { + customTypeName += '*'; + propertyType = QMetaType::QObjectStar; + } else { + readonly = true; + customTypeName = QByteArray("QQmlListProperty<") + customTypeName + QByteArray(">"); + propertyType = qMetaTypeId >(); + } + + p->resolvedCustomTypeName = pool->NewByteArray(customTypeName); + p->typeRef = builder.newString(customTypeName.length()); + typeRef = p->typeRef; + } + + if (p->type == Object::DynamicProperty::Var) + continue; + + if (p->isReadOnly) + readonly = true; + + if (buildData) { + VMD *vmd = (QQmlVMEMetaData *)dynamicData.data(); + vmd->propertyCount++; + (vmd->propertyData() + effectivePropertyIndex)->propertyType = propertyType; + } + + if (p->type < builtinTypeCount) + builder.setProperty(effectivePropertyIndex, p->nameRef, typeRef, (QMetaType::Type)propertyType, + readonly?QFastMetaBuilder::None:QFastMetaBuilder::Writable, + effectivePropertyIndex); + else + builder.setProperty(effectivePropertyIndex, p->nameRef, typeRef, + readonly?QFastMetaBuilder::None:QFastMetaBuilder::Writable, + effectivePropertyIndex); + + p->changedSignatureRef = builder.newString(p->name.utf8length() + strlen("Changed()")); + builder.setSignal(effectivePropertyIndex, p->changedSignatureRef); + + effectivePropertyIndex++; + } + + if (varPropCount) { + VMD *vmd = (QQmlVMEMetaData *)dynamicData.data(); + if (buildData) + vmd->varPropertyCount = varPropCount; + firstPropertyVarIndex = effectivePropertyIndex; + totalPropCount = varPropCount + effectivePropertyIndex; + for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) { + if (p->type == Object::DynamicProperty::Var) { + QFastMetaBuilder::StringRef typeRef = typeRefs[p->type]; + if (buildData) { + vmd->propertyCount++; + (vmd->propertyData() + effectivePropertyIndex)->propertyType = QMetaType::QVariant; + } + + builder.setProperty(effectivePropertyIndex, p->nameRef, typeRef, + QMetaType::QVariant, + p->isReadOnly?QFastMetaBuilder::None:QFastMetaBuilder::Writable, + effectivePropertyIndex); + + p->changedSignatureRef = builder.newString(p->name.utf8length() + strlen("Changed()")); + builder.setSignal(effectivePropertyIndex, p->changedSignatureRef); + + effectivePropertyIndex++; + } + } + } + + if (aliasCount) { + int aliasIndex = 0; + for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) { + if (p->type == Object::DynamicProperty::Alias) { + if (resolveAlias) { + Q_ASSERT(buildData); + ((QQmlVMEMetaData *)dynamicData.data())->aliasCount++; + COMPILE_CHECK(compileAlias(builder, dynamicData, obj, effectivePropertyIndex, + aliasIndex, *p)); + } + // Even if we aren't resolving the alias, we need a fake signal so that the + // metaobject remains consistent across the resolve and non-resolve alias runs + p->changedSignatureRef = builder.newString(p->name.utf8length() + strlen("Changed()")); + builder.setSignal(effectivePropertyIndex, p->changedSignatureRef); + effectivePropertyIndex++; + aliasIndex++; + } + } + } + } + + // Reserve default property + QFastMetaBuilder::StringRef defPropRef; + if (defaultProperty) { + defPropRef = builder.newString(strlen("DefaultProperty")); + builder.setClassInfo(0, defPropRef, defaultProperty->nameRef); + } + + // Reserve dynamic signals + int signalIndex = 0; + for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) { + + int paramCount = s->parameterNames.count(); + + int signatureSize = s->name.utf8length() + 2 /* paren */; + int namesSize = 0; + if (paramCount) signatureSize += s->parameterTypesLength() + (paramCount - 1) /* commas */; + if (paramCount) namesSize += s->parameterNamesLength() + (paramCount - 1) /* commas */; + + s->signatureRef = builder.newString(signatureSize); + if (namesSize) s->parameterNamesRef = builder.newString(namesSize); + + if (buildData) + ((QQmlVMEMetaData *)dynamicData.data())->signalCount++; + + builder.setSignal(signalIndex + obj->dynamicProperties.count(), s->signatureRef, s->parameterNamesRef); + ++signalIndex; + } + + // Reserve dynamic slots + if (obj->dynamicSlots.count()) { + + // Allocate QVariant string + if (typeRefs[0].isEmpty()) + typeRefs[0] = builder.newString(strlen(builtinTypes[0].cppType)); + + typedef QQmlVMEMetaData VMD; + + int methodIndex = 0; + for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) { + int paramCount = s->parameterNames.count(); + + int signatureSize = s->name.utf8length() + 2 /* paren */; + int namesSize = 0; + if (paramCount) signatureSize += (paramCount * strlen("QVariant") + (paramCount - 1)); + if (paramCount) namesSize += s->parameterNamesLength() + (paramCount - 1 /* commas */); + + s->signatureRef = builder.newString(signatureSize); + if (namesSize) s->parameterNamesRef = builder.newString(namesSize); + + builder.setMethod(methodIndex, s->signatureRef, s->parameterNamesRef, typeRefs[0]); + + if (buildData) { + QString funcScript; + funcScript.reserve(strlen("(function ") + s->name.length() + 1 /* lparen */ + + namesSize + 1 /* rparen */ + s->body.length() + 1 /* rparen */); + funcScript = QLatin1String("(function ") + s->name.toString() + QLatin1Char('('); + for (int jj = 0; jj < paramCount; ++jj) { + if (jj) funcScript.append(QLatin1Char(',')); + funcScript.append(QLatin1String(s->parameterNames.at(jj))); + } + funcScript += QLatin1Char(')') + s->body + QLatin1Char(')'); + + QByteArray utf8 = funcScript.toUtf8(); + VMD::MethodData methodData = { s->parameterNames.count(), 0, + utf8.length(), + s->location.start.line }; + + VMD *vmd = (QQmlVMEMetaData *)dynamicData.data(); + vmd->methodCount++; + + VMD::MethodData &md = *(vmd->methodData() + methodIndex); + md = methodData; + md.bodyOffset = dynamicData.size(); + + dynamicData.append((const char *)utf8.constData(), utf8.length()); + } + + + methodIndex++; + } + } + + // Now allocate used builtin types + for (int ii = 0; ii < builtinTypeCount; ++ii) { + if (!typeRefs[ii].isEmpty()) + typeRefs[ii].load(builtinTypes[ii].cppType); + } + + // Now allocate properties + for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) { + + char *d = p->changedSignatureRef.data(); + p->name.writeUtf8(d); + strcpy(d + p->name.utf8length(), "Changed()"); + + if (p->type == Object::DynamicProperty::Alias && !resolveAlias) + continue; + + p->nameRef.load(p->name); + + if (p->type >= builtinTypeCount) { + Q_ASSERT(p->resolvedCustomTypeName); + p->typeRef.load(*p->resolvedCustomTypeName); + } + } + + // Allocate default property if necessary + if (defaultProperty) + strcpy(defPropRef.data(), "DefaultProperty"); + + // Now allocate signals + for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) { + + char *d = s->signatureRef.data(); + char *d2 = s->parameterNamesRef.isEmpty()?0:s->parameterNamesRef.data(); + s->name.writeUtf8(d); d += s->name.utf8length(); + *d++ = '('; + + for (int jj = 0; jj < s->parameterNames.count(); ++jj) { + if (jj != 0) { *d++ = ','; *d2++ = ','; } + strcpy(d, s->parameterTypes.at(jj).constData()); + d += s->parameterTypes.at(jj).length(); + s->parameterNames.at(jj).writeUtf8(d2); + d2 += s->parameterNames.at(jj).utf8length(); + } + *d++ = ')'; + *d = 0; + if (d2) *d2 = 0; + } + + // Now allocate methods + for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) { + char *d = s->signatureRef.data(); + char *d2 = s->parameterNamesRef.isEmpty()?0:s->parameterNamesRef.data(); + s->name.writeUtf8(d); d += s->name.utf8length(); + *d++ = '('; + for (int jj = 0; jj < s->parameterNames.count(); ++jj) { + if (jj != 0) { *d++ = ','; *d2++ = ','; } + strcpy(d, "QVariant"); + d += strlen("QVariant"); + strcpy(d2, s->parameterNames.at(jj).constData()); + d2 += s->parameterNames.at(jj).length(); + } + *d++ = ')'; + *d = 0; + if (d2) *d2 = 0; + } + + // Now allocate class name + classNameRef.load(newClassName); + + obj->metadata = builder.toData(); + builder.fromData(&obj->extObject, obj->metatype, obj->metadata); + + if (mode == IgnoreAliases && aliasCount) + compileState->aliasingObjects.append(obj); + + obj->synthdata = dynamicData; + + if (obj->synthCache) { + obj->synthCache->release(); + obj->synthCache = 0; + } + + if (obj->type != -1) { + QQmlPropertyCache *superCache = output->types[obj->type].createPropertyCache(engine); + QQmlPropertyCache *cache = + superCache->copyAndAppend(engine, &obj->extObject, + QQmlPropertyData::NoFlags, + QQmlPropertyData::IsVMEFunction, + QQmlPropertyData::IsVMESignal); + + // now we modify the flags appropriately for var properties. + int propertyOffset = obj->extObject.propertyOffset(); + QQmlPropertyData *currPropData = 0; + for (int pvi = firstPropertyVarIndex; pvi < totalPropCount; ++pvi) { + currPropData = cache->property(pvi + propertyOffset); + currPropData->setFlags(currPropData->getFlags() | QQmlPropertyData::IsVMEProperty); + } + + obj->synthCache = cache; + } + + return true; +} + +bool QQmlCompiler::checkValidId(QQmlScript::Value *v, const QString &val) +{ + if (val.isEmpty()) + COMPILE_EXCEPTION(v, tr( "Invalid empty ID")); + + QChar ch = val.at(0); + if (ch.isLetter() && !ch.isLower()) + COMPILE_EXCEPTION(v, tr( "IDs cannot start with an uppercase letter")); + + QChar u(QLatin1Char('_')); + if (!ch.isLetter() && ch != u) + COMPILE_EXCEPTION(v, tr( "IDs must start with a letter or underscore")); + + for (int ii = 1; ii < val.count(); ++ii) { + ch = val.at(ii); + if (!ch.isLetterOrNumber() && ch != u) + COMPILE_EXCEPTION(v, tr( "IDs must contain only letters, numbers, and underscores")); + } + + if (enginePrivate->v8engine()->illegalNames().contains(val)) + COMPILE_EXCEPTION(v, tr( "ID illegally masks global JavaScript property")); + + return true; +} + +#include + +static QStringList astNodeToStringList(QQmlJS::AST::Node *node) +{ + if (node->kind == QQmlJS::AST::Node::Kind_IdentifierExpression) { + QString name = + static_cast(node)->name.toString(); + return QStringList() << name; + } else if (node->kind == QQmlJS::AST::Node::Kind_FieldMemberExpression) { + QQmlJS::AST::FieldMemberExpression *expr = static_cast(node); + + QStringList rv = astNodeToStringList(expr->base); + if (rv.isEmpty()) + return rv; + rv.append(expr->name.toString()); + return rv; + } + return QStringList(); +} + +bool QQmlCompiler::compileAlias(QFastMetaBuilder &builder, + QByteArray &data, + QQmlScript::Object *obj, + int propIndex, int aliasIndex, + Object::DynamicProperty &prop) +{ + if (!prop.defaultValue) + COMPILE_EXCEPTION(obj, tr("No property alias location")); + + if (!prop.defaultValue->values.isOne() || + prop.defaultValue->values.first()->object || + !prop.defaultValue->values.first()->value.isScript()) + COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); + + QQmlJS::AST::Node *node = prop.defaultValue->values.first()->value.asAST(); + if (!node) + COMPILE_EXCEPTION(obj, tr("No property alias location")); // ### Can this happen? + + QStringList alias = astNodeToStringList(node); + + if (alias.count() < 1 || alias.count() > 3) + COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias reference. An alias reference must be specified as , . or ..")); + + QQmlScript::Object *idObject = compileState->ids.value(alias.at(0)); + if (!idObject) + COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias reference. Unable to find id \"%1\"").arg(alias.at(0))); + + QByteArray typeName; + + int propIdx = -1; + int flags = 0; + int type = 0; + bool writable = false; + bool resettable = false; + if (alias.count() == 2 || alias.count() == 3) { + propIdx = indexOfProperty(idObject, alias.at(1)); + + if (-1 == propIdx) { + COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); + } else if (propIdx > 0xFFFF) { + COMPILE_EXCEPTION(prop.defaultValue, tr("Alias property exceeds alias bounds")); + } + + QMetaProperty aliasProperty = idObject->metaObject()->property(propIdx); + if (!aliasProperty.isScriptable()) + COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); + + writable = aliasProperty.isWritable() && !prop.isReadOnly; + resettable = aliasProperty.isResettable() && !prop.isReadOnly; + + if (aliasProperty.type() < QVariant::UserType + || uint(aliasProperty.type()) == QMetaType::QVariant) + type = aliasProperty.type(); + + if (alias.count() == 3) { + QQmlValueType *valueType = enginePrivate->valueTypes[aliasProperty.type()]; + if (!valueType) + COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); + + propIdx |= ((unsigned int)aliasProperty.type()) << 24; + + int valueTypeIndex = valueType->metaObject()->indexOfProperty(alias.at(2).toUtf8().constData()); + if (valueTypeIndex == -1) + COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); + Q_ASSERT(valueTypeIndex <= 0xFF); + + aliasProperty = valueType->metaObject()->property(valueTypeIndex); + propIdx |= (valueTypeIndex << 16); + + // update the property type + type = aliasProperty.type(); + if (type >= (int)QVariant::UserType) + type = 0; + } + + if (aliasProperty.isEnumType()) + typeName = "int"; // Avoid introducing a dependency on the aliased metaobject + else + typeName = aliasProperty.typeName(); + } else { + Q_ASSERT(idObject->type != -1); // How else did it get an id? + + const QQmlCompiledData::TypeReference &ref = output->types.at(idObject->type); + if (ref.type) + typeName = ref.type->typeName(); + else + typeName = ref.component->root->className(); + + typeName += '*'; + } + + if (typeName.endsWith('*')) + flags |= QML_ALIAS_FLAG_PTR; + + QQmlVMEMetaData::AliasData aliasData = { idObject->idIndex, propIdx, flags }; + + typedef QQmlVMEMetaData VMD; + VMD *vmd = (QQmlVMEMetaData *)data.data(); + *(vmd->aliasData() + aliasIndex) = aliasData; + + prop.nameRef = builder.newString(prop.name.utf8length()); + prop.resolvedCustomTypeName = pool->NewByteArray(typeName); + prop.typeRef = builder.newString(typeName.length()); + + int propertyFlags = 0; + if (writable) + propertyFlags |= QFastMetaBuilder::Writable; + if (resettable) + propertyFlags |= QFastMetaBuilder::Resettable; + + builder.setProperty(propIndex, prop.nameRef, prop.typeRef, (QMetaType::Type)type, + (QFastMetaBuilder::PropertyFlag)propertyFlags, + propIndex); + + return true; +} + +bool QQmlCompiler::buildBinding(QQmlScript::Value *value, + QQmlScript::Property *prop, + const BindingContext &ctxt) +{ + Q_ASSERT(prop->index != -1); + Q_ASSERT(prop->parent); + Q_ASSERT(prop->parent->metaObject()); + + if (!prop->core.isWritable() && !prop->core.isQList() && !prop->isReadOnlyDeclaration) + COMPILE_EXCEPTION(prop, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString())); + + JSBindingReference *reference = pool->New(); + reference->expression = value->value; + reference->property = prop; + reference->value = value; + reference->bindingContext = ctxt; + addBindingReference(reference); + + return true; +} + +bool QQmlCompiler::buildLiteralBinding(QQmlScript::Value *v, + QQmlScript::Property *prop, + const QQmlCompilerTypes::BindingContext &) +{ + Q_ASSERT(v->value.isScript()); + + if (!prop->core.isWritable()) + return false; + + AST::Node *binding = v->value.asAST(); + + if (prop->type == QVariant::String) { + if (AST::CallExpression *e = AST::cast(binding)) { + if (AST::IdentifierExpression *i = AST::cast(e->base)) { + if (i->name == qsTrId_string) { + AST::ArgumentList *arg1 = e->arguments?e->arguments:0; + AST::ArgumentList *arg2 = arg1?arg1->next:0; + + if (arg1 && arg1->expression->kind == AST::Node::Kind_StringLiteral && + (!arg2 || arg2->expression->kind == AST::Node::Kind_NumericLiteral) && + (!arg2 || !arg2->next)) { + + QStringRef text; + int n = -1; + + text = AST::cast(arg1->expression)->value; + if (arg2) n = (int)AST::cast(arg2->expression)->value; + + TrBindingReference *reference = pool->New(); + reference->dataType = BindingReference::TrId; + reference->text = text; + reference->n = n; + v->bindingReference = reference; + return true; + } + + } else if (i->name == qsTr_string) { + + AST::ArgumentList *arg1 = e->arguments?e->arguments:0; + AST::ArgumentList *arg2 = arg1?arg1->next:0; + AST::ArgumentList *arg3 = arg2?arg2->next:0; + + if (arg1 && arg1->expression->kind == AST::Node::Kind_StringLiteral && + (!arg2 || arg2->expression->kind == AST::Node::Kind_StringLiteral) && + (!arg3 || arg3->expression->kind == AST::Node::Kind_NumericLiteral) && + (!arg3 || !arg3->next)) { + + QStringRef text; + QStringRef comment; + int n = -1; + + text = AST::cast(arg1->expression)->value; + if (arg2) comment = AST::cast(arg2->expression)->value; + if (arg3) n = (int)AST::cast(arg3->expression)->value; + + TrBindingReference *reference = pool->New(); + reference->dataType = BindingReference::Tr; + reference->text = text; + reference->comment = comment; + reference->n = n; + v->bindingReference = reference; + return true; + } + + } + } + } + + } + + return false; +} + +void QQmlCompiler::genBindingAssignment(QQmlScript::Value *binding, + QQmlScript::Property *prop, + QQmlScript::Object *obj, + QQmlScript::Property *valueTypeProperty) +{ + Q_UNUSED(obj); + Q_ASSERT(binding->bindingReference); + + const BindingReference &ref = *binding->bindingReference; + if (ref.dataType == BindingReference::TrId) { + const TrBindingReference &tr = static_cast(ref); + + Instruction::StoreTrIdString store; + store.propertyIndex = prop->core.coreIndex; + store.text = output->indexForByteArray(tr.text.toUtf8()); + store.n = tr.n; + output->addInstruction(store); + } else if (ref.dataType == BindingReference::Tr) { + const TrBindingReference &tr = static_cast(ref); + + Instruction::StoreTrString store; + store.propertyIndex = prop->core.coreIndex; + store.context = translationContextIndex(); + store.text = output->indexForByteArray(tr.text.toUtf8()); + store.comment = output->indexForByteArray(tr.comment.toUtf8()); + store.n = tr.n; + output->addInstruction(store); + } else if (ref.dataType == BindingReference::V4) { + const JSBindingReference &js = static_cast(ref); + + Instruction::StoreV4Binding store; + store.value = js.compiledIndex; + store.context = js.bindingContext.stack; + store.owner = js.bindingContext.owner; + if (valueTypeProperty) { + store.property = (valueTypeProperty->index & 0xFFFF) | + ((valueTypeProperty->type & 0xFF)) << 16 | + ((prop->index & 0xFF) << 24); + store.isRoot = (compileState->root == valueTypeProperty->parent); + } else { + store.property = prop->index; + store.isRoot = (compileState->root == obj); + } + store.line = binding->location.start.line; + store.column = binding->location.start.column; + output->addInstruction(store); + } else if (ref.dataType == BindingReference::V8) { + const JSBindingReference &js = static_cast(ref); + + Instruction::StoreV8Binding store; + store.value = js.compiledIndex; + store.context = js.bindingContext.stack; + store.owner = js.bindingContext.owner; + if (valueTypeProperty) { + store.isRoot = (compileState->root == valueTypeProperty->parent); + } else { + store.isRoot = (compileState->root == obj); + } + store.line = binding->location.start.line; + store.column = binding->location.start.column; + + Q_ASSERT(js.bindingContext.owner == 0 || + (js.bindingContext.owner != 0 && valueTypeProperty)); + if (js.bindingContext.owner) { + store.property = genValueTypeData(prop, valueTypeProperty); + } else { + store.property = prop->core; + } + + output->addInstruction(store); + } else if (ref.dataType == BindingReference::QtScript) { + const JSBindingReference &js = static_cast(ref); + + QQmlInstruction store; + store.assignBinding.value = output->indexForString(js.rewrittenExpression); + store.assignBinding.context = js.bindingContext.stack; + store.assignBinding.owner = js.bindingContext.owner; + store.assignBinding.line = binding->location.start.line; + store.assignBinding.column = binding->location.start.column; + + if (valueTypeProperty) { + store.assignBinding.isRoot = (compileState->root == valueTypeProperty->parent); + } else { + store.assignBinding.isRoot = (compileState->root == obj); + } + + Q_ASSERT(js.bindingContext.owner == 0 || + (js.bindingContext.owner != 0 && valueTypeProperty)); + if (js.bindingContext.owner) { + store.assignBinding.property = genValueTypeData(prop, valueTypeProperty); + } else { + store.assignBinding.property = prop->core; + } + output->addInstructionHelper( + !prop->isAlias ? QQmlInstruction::StoreBinding + : QQmlInstruction::StoreBindingOnAlias + , store); + } else { + Q_ASSERT(!"Unhandled BindingReference::DataType type"); + } +} + +int QQmlCompiler::genContextCache() +{ + if (compileState->ids.count() == 0) + return -1; + + QQmlIntegerCache *cache = new QQmlIntegerCache(); + cache->reserve(compileState->ids.count()); + for (Object *o = compileState->ids.first(); o; o = compileState->ids.next(o)) + cache->add(o->id, o->idIndex); + + output->contextCaches.append(cache); + return output->contextCaches.count() - 1; +} + +QQmlPropertyData +QQmlCompiler::genValueTypeData(QQmlScript::Property *valueTypeProp, + QQmlScript::Property *prop) +{ + typedef QQmlPropertyPrivate QDPP; + return QDPP::saveValueType(prop->parent->metaObject(), prop->index, + enginePrivate->valueTypes[prop->type]->metaObject(), + valueTypeProp->index, engine); +} + +bool QQmlCompiler::completeComponentBuild() +{ + if (componentStats) + componentStats->componentStat.ids = compileState->ids.count(); + + for (Object *aliasObject = compileState->aliasingObjects.first(); aliasObject; + aliasObject = compileState->aliasingObjects.next(aliasObject)) + COMPILE_CHECK(buildDynamicMeta(aliasObject, ResolveAliases)); + + QV4Compiler::Expression expr(unit->imports()); + expr.component = compileState->root; + expr.ids = &compileState->ids; + expr.importCache = output->importCache; + + QV4Compiler bindingCompiler; + + QList sharedBindings; + + for (JSBindingReference *b = compileState->bindings.first(); b; b = b->nextReference) { + + JSBindingReference &binding = *b; + + // ### We don't currently optimize for bindings on alias's - because + // of the solution to QTBUG-13719 + if (!binding.property->isAlias) { + expr.context = binding.bindingContext.object; + expr.property = binding.property; + expr.expression = binding.expression; + + int index = bindingCompiler.compile(expr, enginePrivate); + if (index != -1) { + binding.dataType = BindingReference::V4; + binding.compiledIndex = index; + if (componentStats) + componentStats->componentStat.optimizedBindings.append(b->value->location); + continue; + } + } + + // Pre-rewrite the expression + QString expression = binding.expression.asScript(); + + QQmlRewrite::RewriteBinding rewriteBinding; + rewriteBinding.setName(QLatin1Char('$')+binding.property->name().toString()); + bool isSharable = false; + binding.rewrittenExpression = rewriteBinding(binding.expression.asAST(), expression, &isSharable); + - if (isSharable && !binding.property->isValueTypeSubProperty && !binding.property->isAlias /* See above re alias */ && ++ if (isSharable && !binding.property->isAlias /* See above re alias */ && + binding.property->type != qMetaTypeId()) { + binding.dataType = BindingReference::V8; + sharedBindings.append(b); ++ ++ if (componentStats) ++ componentStats->componentStat.sharedBindings.append(b->value->location); + } else { + binding.dataType = BindingReference::QtScript; - } + - if (componentStats) - componentStats->componentStat.scriptBindings.append(b->value->location); ++ if (componentStats) ++ componentStats->componentStat.scriptBindings.append(b->value->location); ++ } + } + + if (!sharedBindings.isEmpty()) { + struct Sort { + static bool lt(const JSBindingReference *lhs, const JSBindingReference *rhs) + { + return lhs->value->location.start.line < rhs->value->location.start.line; + } + }; + + qSort(sharedBindings.begin(), sharedBindings.end(), Sort::lt); + + int startLineNumber = sharedBindings.at(0)->value->location.start.line; + int lineNumber = startLineNumber; + + QByteArray functionArray("[", 1); + for (int ii = 0; ii < sharedBindings.count(); ++ii) { + + JSBindingReference *reference = sharedBindings.at(ii); + QQmlScript::Value *value = reference->value; + const QString &expression = reference->rewrittenExpression; + + if (ii != 0) functionArray.append(",", 1); + + while (lineNumber < value->location.start.line) { + lineNumber++; + functionArray.append("\n", 1); + } + + functionArray += expression.toUtf8(); + lineNumber += expression.count(QLatin1Char('\n')); + reference->compiledIndex = ii; + } + functionArray.append("]", 1); + + compileState->v8BindingProgram = functionArray; + compileState->v8BindingProgramLine = startLineNumber; + } + + if (bindingCompiler.isValid()) + compileState->compiledBindingData = bindingCompiler.program(); + + // Check pop()'s matched push()'s + Q_ASSERT(compileState->objectDepth.depth() == 0); + Q_ASSERT(compileState->listDepth.depth() == 0); + + saveComponentState(); + + return true; +} + +void QQmlCompiler::dumpStats() +{ + Q_ASSERT(componentStats); + qWarning().nospace() << "QML Document: " << output->url.toString(); + for (int ii = 0; ii < componentStats->savedComponentStats.count(); ++ii) { + const ComponentStat &stat = componentStats->savedComponentStats.at(ii); + qWarning().nospace() << " Component Line " << stat.lineNumber; + qWarning().nospace() << " Total Objects: " << stat.objects; + qWarning().nospace() << " IDs Used: " << stat.ids; + qWarning().nospace() << " Optimized Bindings: " << stat.optimizedBindings.count(); + + { + QByteArray output; + for (int ii = 0; ii < stat.optimizedBindings.count(); ++ii) { + if (0 == (ii % 10)) { + if (ii) output.append("\n"); + output.append(" "); + } + + output.append("("); + output.append(QByteArray::number(stat.optimizedBindings.at(ii).start.line)); + output.append(":"); + output.append(QByteArray::number(stat.optimizedBindings.at(ii).start.column)); + output.append(") "); + } + if (!output.isEmpty()) + qWarning().nospace() << output.constData(); + } + ++ qWarning().nospace() << " Shared Bindings: " << stat.sharedBindings.count(); ++ { ++ QByteArray output; ++ for (int ii = 0; ii < stat.sharedBindings.count(); ++ii) { ++ if (0 == (ii % 10)) { ++ if (ii) output.append("\n"); ++ output.append(" "); ++ } ++ ++ output.append("("); ++ output.append(QByteArray::number(stat.sharedBindings.at(ii).start.line)); ++ output.append(":"); ++ output.append(QByteArray::number(stat.sharedBindings.at(ii).start.column)); ++ output.append(") "); ++ } ++ if (!output.isEmpty()) ++ qWarning().nospace() << output.constData(); ++ } ++ + qWarning().nospace() << " QScript Bindings: " << stat.scriptBindings.count(); + { + QByteArray output; + for (int ii = 0; ii < stat.scriptBindings.count(); ++ii) { + if (0 == (ii % 10)) { + if (ii) output.append("\n"); + output.append(" "); + } + + output.append("("); + output.append(QByteArray::number(stat.scriptBindings.at(ii).start.line)); + output.append(":"); + output.append(QByteArray::number(stat.scriptBindings.at(ii).start.column)); + output.append(") "); + } + if (!output.isEmpty()) + qWarning().nospace() << output.constData(); + } + } +} + +/*! + Returns true if from can be assigned to a (QObject) property of type + to. +*/ +bool QQmlCompiler::canCoerce(int to, QQmlScript::Object *from) +{ + const QMetaObject *toMo = enginePrivate->rawMetaObjectForType(to); + const QMetaObject *fromMo = from->metaObject(); + + while (fromMo) { + if (QQmlPropertyPrivate::equal(fromMo, toMo)) + return true; + fromMo = fromMo->superClass(); + } + return false; +} + +/*! + Returns the element name, as written in the QML file, for o. +*/ +QString QQmlCompiler::elementName(QQmlScript::Object *o) +{ + Q_ASSERT(o); + if (o->type != -1) { + return output->types.at(o->type).className; + } else { + return QString(); + } +} + +QQmlType *QQmlCompiler::toQmlType(QQmlScript::Object *from) +{ + // ### Optimize + const QMetaObject *mo = from->metatype; + QQmlType *type = 0; + while (!type && mo) { + type = QQmlMetaType::qmlType(mo); + mo = mo->superClass(); + } + return type; +} + +QStringList QQmlCompiler::deferredProperties(QQmlScript::Object *obj) +{ + const QMetaObject *mo = obj->metatype; + + int idx = mo->indexOfClassInfo("DeferredPropertyNames"); + if (idx == -1) + return QStringList(); + + QMetaClassInfo classInfo = mo->classInfo(idx); + QStringList rv = QString::fromUtf8(classInfo.value()).split(QLatin1Char(',')); + return rv; +} + +QQmlPropertyData * +QQmlCompiler::property(QQmlScript::Object *object, int index) +{ + QQmlPropertyCache *cache = 0; + + if (object->synthCache) + cache = object->synthCache; + else if (object->type != -1) + cache = output->types[object->type].createPropertyCache(engine); + else + cache = QQmlEnginePrivate::get(engine)->cache(object->metaObject()); + + return cache->property(index); +} + +QQmlPropertyData * +QQmlCompiler::property(QQmlScript::Object *object, const QHashedStringRef &name, bool *notInRevision) +{ + if (notInRevision) *notInRevision = false; + + QQmlPropertyCache *cache = 0; + + if (object->synthCache) + cache = object->synthCache; + else if (object->type != -1) + cache = output->types[object->type].createPropertyCache(engine); + else + cache = QQmlEnginePrivate::get(engine)->cache(object->metaObject()); + + QQmlPropertyData *d = cache->property(name); + + // Find the first property + while (d && d->isFunction()) + d = cache->overrideData(d); + + if (d && !cache->isAllowedInRevision(d)) { + if (notInRevision) *notInRevision = true; + return 0; + } else { + return d; + } +} + +// This code must match the semantics of QQmlPropertyPrivate::findSignalByName +QQmlPropertyData * +QQmlCompiler::signal(QQmlScript::Object *object, const QHashedStringRef &name, bool *notInRevision) +{ + if (notInRevision) *notInRevision = false; + + QQmlPropertyCache *cache = 0; + + if (object->synthCache) + cache = object->synthCache; + else if (object->type != -1) + cache = output->types[object->type].createPropertyCache(engine); + else + cache = QQmlEnginePrivate::get(engine)->cache(object->metaObject()); + + + QQmlPropertyData *d = cache->property(name); + if (notInRevision) *notInRevision = false; + + while (d && !(d->isFunction())) + d = cache->overrideData(d); + + if (d && !cache->isAllowedInRevision(d)) { + if (notInRevision) *notInRevision = true; + return 0; + } else if (d) { + return d; + } + + if (name.endsWith(Changed_string)) { + QHashedStringRef propName = name.mid(0, name.length() - Changed_string.length()); + + d = property(object, propName, notInRevision); + if (d) + return cache->method(d->notifyIndex); + } + + return 0; +} + +// This code must match the semantics of QQmlPropertyPrivate::findSignalByName +int QQmlCompiler::indexOfSignal(QQmlScript::Object *object, const QString &name, + bool *notInRevision) +{ + QQmlPropertyData *d = signal(object, QStringRef(&name), notInRevision); + return d?d->coreIndex:-1; +} + +int QQmlCompiler::indexOfProperty(QQmlScript::Object *object, const QString &name, + bool *notInRevision) +{ + return indexOfProperty(object, QStringRef(&name), notInRevision); +} + +int QQmlCompiler::indexOfProperty(QQmlScript::Object *object, const QHashedStringRef &name, + bool *notInRevision) +{ + QQmlPropertyData *d = property(object, name, notInRevision); + return d?d->coreIndex:-1; +} + +QT_END_NAMESPACE diff --cc src/qml/qml/qqmlcompiler_p.h index 9b13b7e,0000000..3b6fdf1 mode 100644,000000..100644 --- a/src/qml/qml/qqmlcompiler_p.h +++ b/src/qml/qml/qqmlcompiler_p.h @@@ -1,466 -1,0 +1,467 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLCOMPILER_P_H +#define QQMLCOMPILER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qqml.h" +#include "qqmlerror.h" +#include +#include "qqmlinstruction_p.h" +#include "qqmlscript_p.h" +#include "qqmlengine_p.h" +#include +#include "qqmlpropertycache_p.h" +#include "qqmlintegercache_p.h" +#include "qqmltypenamecache_p.h" +#include "qqmltypeloader_p.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QQmlEngine; +class QQmlComponent; +class QQmlContext; +class QQmlContextData; + +class Q_AUTOTEST_EXPORT QQmlCompiledData : public QQmlRefCount, + public QQmlCleanup +{ +public: + QQmlCompiledData(QQmlEngine *engine); + virtual ~QQmlCompiledData(); + + QQmlEngine *engine; + + QString name; + QUrl url; + QQmlTypeNameCache *importCache; + + struct TypeReference + { + TypeReference() + : type(0), typePropertyCache(0), component(0) {} + + QString className; + QQmlType *type; + QQmlPropertyCache *typePropertyCache; + QQmlCompiledData *component; + + const QMetaObject *metaObject() const; + QQmlPropertyCache *propertyCache() const; + QQmlPropertyCache *createPropertyCache(QQmlEngine *); + }; + QList types; + + struct V8Program { + V8Program(const QByteArray &p, QQmlCompiledData *c) + : program(p), cdata(c) {} + + QByteArray program; + v8::Persistent bindings; + QQmlCompiledData *cdata; + }; + + QList programs; + + const QMetaObject *root; + QAbstractDynamicMetaObject rootData; + QQmlPropertyCache *rootPropertyCache; + QList primitives; + QList datas; + QByteArray bytecode; + QList propertyCaches; + QList contextCaches; + QList scripts; + QList urls; + + struct Instruction { +#define QML_INSTR_DATA_TYPEDEF(I, FMT) typedef QQmlInstructionData I; + FOR_EACH_QML_INSTR(QML_INSTR_DATA_TYPEDEF) +#undef QML_INSTR_DATA_TYPEDEF + private: + Instruction(); + }; + + void dumpInstructions(); + + template + int addInstruction(const QQmlInstructionData &data) + { + QQmlInstruction genericInstr; + QQmlInstructionMeta::setData(genericInstr, data); + return addInstructionHelper(static_cast(Instr), genericInstr); + } + int nextInstructionIndex(); + QQmlInstruction *instruction(int index); + QQmlInstruction::Type instructionType(const QQmlInstruction *instr); + + bool isInitialized() const { return hasEngine(); } + void initialize(QQmlEngine *); + +protected: + virtual void destroy(); // From QQmlRefCount + virtual void clear(); // From QQmlCleanup + +private: + friend class QQmlCompiler; + + int addInstructionHelper(QQmlInstruction::Type type, QQmlInstruction &instr); + void dump(QQmlInstruction *, int idx = -1); + QQmlCompiledData(const QQmlCompiledData &other); + QQmlCompiledData &operator=(const QQmlCompiledData &other); + QByteArray packData; + int pack(const char *, size_t); + + int indexForString(const QString &); + int indexForByteArray(const QByteArray &); + int indexForUrl(const QUrl &); +}; + +namespace QQmlCompilerTypes { + struct BindingContext + { + BindingContext() + : stack(0), owner(0), object(0) {} + BindingContext(QQmlScript::Object *o) + : stack(0), owner(0), object(o) {} + BindingContext incr() const { + BindingContext rv(object); + rv.stack = stack + 1; + return rv; + } + bool isSubContext() const { return stack != 0; } + int stack; + int owner; + QQmlScript::Object *object; + }; + + struct BindingReference + { + enum DataType { QtScript, V4, V8, + Tr, TrId }; + DataType dataType; + }; + + struct JSBindingReference : public QQmlPool::Class, + public BindingReference + { + JSBindingReference() : nextReference(0) {} + + QQmlScript::Variant expression; + QQmlScript::Property *property; + QQmlScript::Value *value; + + int compiledIndex; + + QString rewrittenExpression; + BindingContext bindingContext; + + JSBindingReference *nextReference; + }; + + struct TrBindingReference : public QQmlPool::POD, + public BindingReference + { + QStringRef text; + QStringRef comment; + int n; + }; + + struct IdList : public QFieldList + { + QQmlScript::Object *value(const QString &id) const { + for (QQmlScript::Object *o = first(); o; o = next(o)) { + if (o->id == id) + return o; + } + return 0; + } + }; + + struct DepthStack { + DepthStack() : _depth(0), _maxDepth(0) {} + DepthStack(const DepthStack &o) : _depth(o._depth), _maxDepth(o._maxDepth) {} + DepthStack &operator=(const DepthStack &o) { _depth = o._depth; _maxDepth = o._maxDepth; return *this; } + + int depth() const { return _depth; } + int maxDepth() const { return _maxDepth; } + + void push() { ++_depth; _maxDepth = qMax(_depth, _maxDepth); } + void pop() { --_depth; Q_ASSERT(_depth >= 0); Q_ASSERT(_maxDepth > _depth); } + + void pushPop(int count) { _maxDepth = qMax(_depth + count, _maxDepth); } + private: + int _depth; + int _maxDepth; + }; + + // Contains all the incremental compiler state about a component. As + // a single QML file can have multiple components defined, there may be + // more than one of these for each compile + struct ComponentCompileState : public QQmlPool::Class + { + ComponentCompileState() + : parserStatusCount(0), totalBindingsCount(0), pushedProperties(0), nested(false), + v8BindingProgramLine(-1), root(0) {} + + IdList ids; + int parserStatusCount; + int totalBindingsCount; + int pushedProperties; + bool nested; + + QByteArray compiledBindingData; + QByteArray v8BindingProgram; + int v8BindingProgramLine; + + DepthStack objectDepth; + DepthStack listDepth; + + typedef QQmlCompilerTypes::JSBindingReference B; + typedef QFieldList JSBindingReferenceList; + JSBindingReferenceList bindings; + typedef QQmlScript::Object O; + typedef QFieldList AliasingObjectsList; + AliasingObjectsList aliasingObjects; + QQmlScript::Object *root; + }; +}; + +class QMetaObjectBuilder; +class Q_AUTOTEST_EXPORT QQmlCompiler +{ + Q_DECLARE_TR_FUNCTIONS(QQmlCompiler) +public: + QQmlCompiler(QQmlPool *); + + bool compile(QQmlEngine *, QQmlTypeData *, QQmlCompiledData *); + + bool isError() const; + QList errors() const; + + static bool isAttachedPropertyName(const QString &); + static bool isSignalPropertyName(const QString &); + static bool isAttachedPropertyName(const QHashedStringRef &); + static bool isSignalPropertyName(const QHashedStringRef &); + + int evaluateEnum(const QByteArray& script) const; // for QQmlCustomParser::evaluateEnum + const QMetaObject *resolveType(const QString& name) const; // for QQmlCustomParser::resolveType + int rewriteBinding(const QQmlScript::Variant& value, const QString& name); // for QQmlCustomParser::rewriteBinding + QString rewriteSignalHandler(const QQmlScript::Variant& value, const QString &name); // for QQmlCustomParser::rewriteSignalHandler + +private: + typedef QQmlCompiledData::Instruction Instruction; + + static void reset(QQmlCompiledData *); + + void compileTree(QQmlScript::Object *tree); + + + bool buildObject(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &); + bool buildComponent(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &); + bool buildSubObject(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &); + bool buildSignal(QQmlScript::Property *prop, QQmlScript::Object *obj, + const QQmlCompilerTypes::BindingContext &); + bool buildProperty(QQmlScript::Property *prop, QQmlScript::Object *obj, + const QQmlCompilerTypes::BindingContext &); + bool buildPropertyInNamespace(QQmlImportedNamespace *ns, + QQmlScript::Property *prop, + QQmlScript::Object *obj, + const QQmlCompilerTypes::BindingContext &); + bool buildIdProperty(QQmlScript::Property *prop, QQmlScript::Object *obj); + bool buildAttachedProperty(QQmlScript::Property *prop, + QQmlScript::Object *obj, + const QQmlCompilerTypes::BindingContext &ctxt); + bool buildGroupedProperty(QQmlScript::Property *prop, + QQmlScript::Object *obj, + const QQmlCompilerTypes::BindingContext &ctxt); + bool buildValueTypeProperty(QObject *type, + QQmlScript::Object *obj, + QQmlScript::Object *baseObj, + const QQmlCompilerTypes::BindingContext &ctxt); + bool buildListProperty(QQmlScript::Property *prop, + QQmlScript::Object *obj, + const QQmlCompilerTypes::BindingContext &ctxt); + bool buildScriptStringProperty(QQmlScript::Property *prop, + QQmlScript::Object *obj, + const QQmlCompilerTypes::BindingContext &ctxt); + bool buildPropertyAssignment(QQmlScript::Property *prop, + QQmlScript::Object *obj, + const QQmlCompilerTypes::BindingContext &ctxt); + bool buildPropertyObjectAssignment(QQmlScript::Property *prop, + QQmlScript::Object *obj, + QQmlScript::Value *value, + const QQmlCompilerTypes::BindingContext &ctxt); + bool buildPropertyOnAssignment(QQmlScript::Property *prop, + QQmlScript::Object *obj, + QQmlScript::Object *baseObj, + QQmlScript::Value *value, + const QQmlCompilerTypes::BindingContext &ctxt); + bool buildPropertyLiteralAssignment(QQmlScript::Property *prop, + QQmlScript::Object *obj, + QQmlScript::Value *value, + const QQmlCompilerTypes::BindingContext &ctxt); + bool doesPropertyExist(QQmlScript::Property *prop, QQmlScript::Object *obj); + bool testLiteralAssignment(QQmlScript::Property *prop, + QQmlScript::Value *value); + bool testQualifiedEnumAssignment(QQmlScript::Property *prop, + QQmlScript::Object *obj, + QQmlScript::Value *value, + bool *isAssignment); + enum DynamicMetaMode { IgnoreAliases, ResolveAliases, ForceCreation }; + bool mergeDynamicMetaProperties(QQmlScript::Object *obj); + bool buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mode); + bool checkDynamicMeta(QQmlScript::Object *obj); + bool buildBinding(QQmlScript::Value *, QQmlScript::Property *prop, + const QQmlCompilerTypes::BindingContext &ctxt); + bool buildLiteralBinding(QQmlScript::Value *, QQmlScript::Property *prop, + const QQmlCompilerTypes::BindingContext &ctxt); + bool buildComponentFromRoot(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &); + bool compileAlias(QFastMetaBuilder &, + QByteArray &data, + QQmlScript::Object *obj, + int propIndex, int aliasIndex, + QQmlScript::Object::DynamicProperty &); + bool completeComponentBuild(); + bool checkValidId(QQmlScript::Value *, const QString &); + + + void genObject(QQmlScript::Object *obj); + void genObjectBody(QQmlScript::Object *obj); + void genValueTypeProperty(QQmlScript::Object *obj,QQmlScript::Property *); + void genComponent(QQmlScript::Object *obj); + void genValueProperty(QQmlScript::Property *prop, QQmlScript::Object *obj); + void genListProperty(QQmlScript::Property *prop, QQmlScript::Object *obj); + void genPropertyAssignment(QQmlScript::Property *prop, + QQmlScript::Object *obj, + QQmlScript::Property *valueTypeProperty = 0); + void genLiteralAssignment(QQmlScript::Property *prop, + QQmlScript::Value *value); + void genBindingAssignment(QQmlScript::Value *binding, + QQmlScript::Property *prop, + QQmlScript::Object *obj, + QQmlScript::Property *valueTypeProperty = 0); + int genContextCache(); + + QQmlPropertyData genValueTypeData(QQmlScript::Property *prop, + QQmlScript::Property *valueTypeProp); + + int componentTypeRef(); + int translationContextIndex(); + + static QQmlType *toQmlType(QQmlScript::Object *from); + bool canCoerce(int to, QQmlScript::Object *from); + + QString elementName(QQmlScript::Object *); + + QStringList deferredProperties(QQmlScript::Object *); + + QQmlPropertyData *property(QQmlScript::Object *, int); + QQmlPropertyData *property(QQmlScript::Object *, const QHashedStringRef &, + bool *notInRevision = 0); + QQmlPropertyData *signal(QQmlScript::Object *, const QHashedStringRef &, + bool *notInRevision = 0); + int indexOfProperty(QQmlScript::Object *, const QHashedStringRef &, bool *notInRevision = 0); + int indexOfProperty(QQmlScript::Object *, const QString &, bool *notInRevision = 0); + int indexOfSignal(QQmlScript::Object *, const QString &, bool *notInRevision = 0); + + void addId(const QString &, QQmlScript::Object *); + + void dumpStats(); + + void addBindingReference(QQmlCompilerTypes::JSBindingReference *); + + QQmlCompilerTypes::ComponentCompileState *compileState; + + QQmlPool *pool; + + QQmlCompilerTypes::ComponentCompileState *componentState(QQmlScript::Object *); + void saveComponentState(); + + QList exceptions; + QQmlCompiledData *output; + QQmlEngine *engine; + QQmlEnginePrivate *enginePrivate; + QQmlScript::Object *unitRoot; + QQmlTypeData *unit; + int cachedComponentTypeRef; + int cachedTranslationContextIndex; + + // Compiler component statistics. Only collected if QML_COMPILER_STATS=1 + struct ComponentStat + { + ComponentStat() : ids(0), objects(0) {} + + int lineNumber; + + int ids; + QList scriptBindings; ++ QList sharedBindings; + QList optimizedBindings; + int objects; + }; + struct ComponentStats : public QQmlPool::Class + { + ComponentStat componentStat; + QList savedComponentStats; + }; + ComponentStats *componentStats; +}; + +QT_END_NAMESPACE + +#endif // QQMLCOMPILER_P_H diff --cc src/qml/qml/qqmlcomponent.cpp index e168f06,0000000..5dd8fc8 mode 100644,000000..100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@@ -1,1350 -1,0 +1,1352 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmlcomponent.h" +#include "qqmlcomponent_p.h" +#include "qqmlcomponentattached_p.h" + +#include "qqmlcompiler_p.h" +#include "qqmlcontext_p.h" +#include "qqmlengine_p.h" +#include "qqmlvme_p.h" +#include "qqml.h" +#include "qqmlengine.h" +#include "qqmlbinding_p.h" +#include "qqmlbinding_p_p.h" ++#include "qqmlglobal_p.h" +#include "qqmlscript_p.h" +#include +#include +#include "qqmlincubator.h" +#include "qqmlincubator_p.h" + +#include +#include + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QQmlComponentExtension : public QV8Engine::Deletable +{ +public: + QQmlComponentExtension(QV8Engine *); + virtual ~QQmlComponentExtension(); + + v8::Persistent incubationConstructor; + v8::Persistent initialProperties; + v8::Persistent forceCompletion; +}; +V8_DEFINE_EXTENSION(QQmlComponentExtension, componentExtension); + +/* + Try to do what's necessary for a reasonable display of the type + name, but no more (just enough for the client to do more extensive cleanup). + + Should only be called when debugging is enabled. +*/ +static inline QString buildTypeNameForDebug(const QMetaObject *metaObject) +{ + static const QString qmlMarker(QLatin1String("_QML")); + static const QChar underscore(QLatin1Char('_')); + static const QChar asterisk(QLatin1Char('*')); + QQmlType *type = QQmlMetaType::qmlType(metaObject); + QString typeName = type ? type->qmlTypeName() : QString::fromUtf8(metaObject->className()); + if (!type) { + //### optimize further? + int marker = typeName.indexOf(qmlMarker); + if (marker != -1 && marker < typeName.count() - 1) { + if (typeName[marker + 1] == underscore) { + const QString className = typeName.left(marker) + asterisk; + type = QQmlMetaType::qmlType(QMetaType::type(className.toUtf8())); + if (type) + typeName = type->qmlTypeName(); + } + } + } + return typeName; +} + +/*! + \class QQmlComponent + \since 4.7 + \brief The QQmlComponent class encapsulates a QML component definition. + \mainclass + + Components are reusable, encapsulated QML elements with well-defined interfaces. + They are often defined in \l {qdeclarativedocuments.html}{Component Files}. + + A QQmlComponent instance can be created from a QML file. + For example, if there is a \c main.qml file like this: + + \qml + import QtQuick 2.0 + + Item { + width: 200 + height: 200 + } + \endqml + + The following code loads this QML file as a component, creates an instance of + this component using create(), and then queries the \l Item's \l {Item::}{width} + value: + + \code + QQmlEngine *engine = new QQmlEngine; + QQmlComponent component(engine, QUrl::fromLocalFile("main.qml")); + + QObject *myObject = component.create(); + QQuickItem *item = qobject_cast(myObject); + int width = item->width(); // width = 200 + \endcode + + + \section2 Network Components + + If the URL passed to QQmlComponent is a network resource, or if the QML document references a + network resource, the QQmlComponent has to fetch the network data before it is able to create + objects. In this case, the QQmlComponent will have a \l {QQmlComponent::Loading}{Loading} + \l {QQmlComponent::status()}{status}. An application will have to wait until the component + is \l {QQmlComponent::Ready}{Ready} before calling \l {QQmlComponent::create()}. + + The following example shows how to load a QML file from a network resource. After creating + the QQmlComponent, it tests whether the component is loading. If it is, it connects to the + QQmlComponent::statusChanged() signal and otherwise calls the \c {continueLoading()} method + directly. Note that QQmlComponent::isLoading() may be false for a network component if the + component has been cached and is ready immediately. + + \code + MyApplication::MyApplication() + { + // ... + component = new QQmlComponent(engine, QUrl("http://www.example.com/main.qml")); + if (component->isLoading()) + QObject::connect(component, SIGNAL(statusChanged(QQmlComponent::Status)), + this, SLOT(continueLoading())); + else + continueLoading(); + } + + void MyApplication::continueLoading() + { + if (component->isError()) { + qWarning() << component->errors(); + } else { + QObject *myObject = component->create(); + } + } + \endcode + + \sa {Using QML Bindings in C++ Applications}, {Integrating QML Code with Existing Qt UI Code} +*/ + +/*! + \qmlclass Component QQmlComponent + \ingroup qml-utility-elements + \since 4.7 + \brief The Component element encapsulates a QML component definition. + + Components are reusable, encapsulated QML elements with well-defined interfaces. + + Components are often defined by \l {qdeclarativedocuments.html}{component files} - + that is, \c .qml files. The \e Component element essentially allows QML components + to be defined inline, within a \l {QML Document}{QML document}, rather than as a separate QML file. + This may be useful for reusing a small component within a QML file, or for defining + a component that logically belongs with other QML components within a file. + + For example, here is a component that is used by multiple \l Loader objects. + It contains a single item, a \l Rectangle: + + \snippet doc/src/snippets/qml/component.qml 0 + + Notice that while a \l Rectangle by itself would be automatically + rendered and displayed, this is not the case for the above rectangle + because it is defined inside a \c Component. The component encapsulates the + QML elements within, as if they were defined in a separate QML + file, and is not loaded until requested (in this case, by the + two \l Loader objects). + + Defining a \c Component is similar to defining a \l {QML Document}{QML document}. + A QML document has a single top-level item that defines the behaviors and + properties of that component, and cannot define properties or behaviors outside + of that top-level item. In the same way, a \c Component definition contains a single + top level item (which in the above example is a \l Rectangle) and cannot define any + data outside of this item, with the exception of an \e id (which in the above example + is \e redSquare). + + The \c Component element is commonly used to provide graphical components + for views. For example, the ListView::delegate property requires a \c Component + to specify how each list item is to be displayed. + + \c Component objects can also be created dynamically using + \l{QML:Qt::createComponent()}{Qt.createComponent()}. +*/ + +/*! + \qmlattachedsignal Component::onCompleted() + + Emitted after component "startup" has completed. This can be used to + execute script code at startup, once the full QML environment has been + established. + + The \c {Component::onCompleted} attached property can be applied to + any element. The order of running the \c onCompleted scripts is + undefined. + + \qml + Rectangle { + Component.onCompleted: console.log("Completed Running!") + Rectangle { + Component.onCompleted: console.log("Nested Completed Running!") + } + } + \endqml +*/ + +/*! + \qmlattachedsignal Component::onDestruction() + + Emitted as the component begins destruction. This can be used to undo + work done in the onCompleted signal, or other imperative code in your + application. + + The \c {Component::onDestruction} attached property can be applied to + any element. However, it applies to the destruction of the component as + a whole, and not the destruction of the specific object. The order of + running the \c onDestruction scripts is undefined. + + \qml + Rectangle { + Component.onDestruction: console.log("Destruction Beginning!") + Rectangle { + Component.onDestruction: console.log("Nested Destruction Beginning!") + } + } + \endqml + + \sa QtQml +*/ + +/*! + \enum QQmlComponent::Status + + Specifies the loading status of the QQmlComponent. + + \value Null This QQmlComponent has no data. Call loadUrl() or setData() to add QML content. + \value Ready This QQmlComponent is ready and create() may be called. + \value Loading This QQmlComponent is loading network data. + \value Error An error has occurred. Call errors() to retrieve a list of \{QQmlError}{errors}. +*/ + +void QQmlComponentPrivate::typeDataReady(QQmlTypeData *) +{ + Q_Q(QQmlComponent); + + Q_ASSERT(typeData); + + fromTypeData(typeData); + typeData = 0; + + emit q->statusChanged(q->status()); +} + +void QQmlComponentPrivate::typeDataProgress(QQmlTypeData *, qreal p) +{ + Q_Q(QQmlComponent); + + progress = p; + + emit q->progressChanged(p); +} + +void QQmlComponentPrivate::fromTypeData(QQmlTypeData *data) +{ + url = data->finalUrl(); + QQmlCompiledData *c = data->compiledData(); + + if (!c) { + Q_ASSERT(data->isError()); + state.errors = data->errors(); + } else { + cc = c; + } + + data->release(); +} + +void QQmlComponentPrivate::clear() +{ + if (typeData) { + typeData->unregisterCallback(this); + typeData->release(); + typeData = 0; + } + + if (cc) { + cc->release(); + cc = 0; + } +} + +/*! + \internal +*/ +QQmlComponent::QQmlComponent(QObject *parent) + : QObject(*(new QQmlComponentPrivate), parent) +{ +} + +/*! + Destruct the QQmlComponent. +*/ +QQmlComponent::~QQmlComponent() +{ + Q_D(QQmlComponent); + + if (d->state.completePending) { + qWarning("QQmlComponent: Component destroyed while completion pending"); + d->completeCreate(); + } + + if (d->typeData) { + d->typeData->unregisterCallback(d); + d->typeData->release(); + } + if (d->cc) + d->cc->release(); +} + +/*! + \qmlproperty enumeration Component::status + This property holds the status of component loading. It can be one of: + \list + \o Component.Null - no data is available for the component + \o Component.Ready - the component has been loaded, and can be used to create instances. + \o Component.Loading - the component is currently being loaded + \o Component.Error - an error occurred while loading the component. + Calling errorString() will provide a human-readable description of any errors. + \endlist + */ + +/*! + \property QQmlComponent::status + The component's current \l{QQmlComponent::Status} {status}. + */ +QQmlComponent::Status QQmlComponent::status() const +{ + Q_D(const QQmlComponent); + + if (d->typeData) + return Loading; + else if (!d->state.errors.isEmpty()) + return Error; + else if (d->engine && d->cc) + return Ready; + else + return Null; +} + +/*! + Returns true if status() == QQmlComponent::Null. +*/ +bool QQmlComponent::isNull() const +{ + return status() == Null; +} + +/*! + Returns true if status() == QQmlComponent::Ready. +*/ +bool QQmlComponent::isReady() const +{ + return status() == Ready; +} + +/*! + Returns true if status() == QQmlComponent::Error. +*/ +bool QQmlComponent::isError() const +{ + return status() == Error; +} + +/*! + Returns true if status() == QQmlComponent::Loading. +*/ +bool QQmlComponent::isLoading() const +{ + return status() == Loading; +} + +/*! + \qmlproperty real Component::progress + The progress of loading the component, from 0.0 (nothing loaded) + to 1.0 (finished). +*/ + +/*! + \property QQmlComponent::progress + The progress of loading the component, from 0.0 (nothing loaded) + to 1.0 (finished). +*/ +qreal QQmlComponent::progress() const +{ + Q_D(const QQmlComponent); + return d->progress; +} + +/*! + \fn void QQmlComponent::progressChanged(qreal progress) + + Emitted whenever the component's loading progress changes. \a progress will be the + current progress between 0.0 (nothing loaded) and 1.0 (finished). +*/ + +/*! + \fn void QQmlComponent::statusChanged(QQmlComponent::Status status) + + Emitted whenever the component's status changes. \a status will be the + new status. +*/ + +/*! + Create a QQmlComponent with no data and give it the specified + \a engine and \a parent. Set the data with setData(). +*/ +QQmlComponent::QQmlComponent(QQmlEngine *engine, QObject *parent) + : QObject(*(new QQmlComponentPrivate), parent) +{ + Q_D(QQmlComponent); + d->engine = engine; +} + +/*! + Create a QQmlComponent from the given \a url and give it the + specified \a parent and \a engine. + + Ensure that the URL provided is full and correct, in particular, use + \l QUrl::fromLocalFile() when loading a file from the local filesystem. + + \sa loadUrl() +*/ +QQmlComponent::QQmlComponent(QQmlEngine *engine, const QUrl &url, QObject *parent) +: QObject(*(new QQmlComponentPrivate), parent) +{ + Q_D(QQmlComponent); + d->engine = engine; + loadUrl(url); +} + +/*! + Create a QQmlComponent from the given \a fileName and give it the specified + \a parent and \a engine. + + \sa loadUrl() +*/ +QQmlComponent::QQmlComponent(QQmlEngine *engine, const QString &fileName, + QObject *parent) +: QObject(*(new QQmlComponentPrivate), parent) +{ + Q_D(QQmlComponent); + d->engine = engine; + loadUrl(d->engine->baseUrl().resolved(QUrl::fromLocalFile(fileName))); +} + +/*! + \internal +*/ +QQmlComponent::QQmlComponent(QQmlEngine *engine, QQmlCompiledData *cc, int start, QObject *parent) + : QObject(*(new QQmlComponentPrivate), parent) +{ + Q_D(QQmlComponent); + d->engine = engine; + d->cc = cc; + cc->addref(); + d->start = start; + d->url = cc->url; + d->progress = 1.0; +} + +/*! + Sets the QQmlComponent to use the given QML \a data. If \a url + is provided, it is used to set the component name and to provide + a base path for items resolved by this component. +*/ +void QQmlComponent::setData(const QByteArray &data, const QUrl &url) +{ + Q_D(QQmlComponent); + + d->clear(); + + d->url = url; + + QQmlTypeData *typeData = QQmlEnginePrivate::get(d->engine)->typeLoader.get(data, url); + + if (typeData->isCompleteOrError()) { + d->fromTypeData(typeData); + } else { + d->typeData = typeData; + d->typeData->registerCallback(d); + } + + d->progress = 1.0; + emit statusChanged(status()); + emit progressChanged(d->progress); +} + +/*! +Returns the QQmlContext the component was created in. This is only +valid for components created directly from QML. +*/ +QQmlContext *QQmlComponent::creationContext() const +{ + Q_D(const QQmlComponent); + if(d->creationContext) + return d->creationContext->asQQmlContext(); + + return qmlContext(this); +} + +/*! + Load the QQmlComponent from the provided \a url. + + Ensure that the URL provided is full and correct, in particular, use + \l QUrl::fromLocalFile() when loading a file from the local filesystem. +*/ +void QQmlComponent::loadUrl(const QUrl &url) +{ + Q_D(QQmlComponent); + + d->clear(); + + if ((url.isRelative() && !url.isEmpty()) + || url.scheme() == QLatin1String("file")) // Workaround QTBUG-11929 + d->url = d->engine->baseUrl().resolved(url); + else + d->url = url; + + if (url.isEmpty()) { + QQmlError error; + error.setDescription(tr("Invalid empty URL")); + d->state.errors << error; + return; + } + + QQmlTypeData *data = QQmlEnginePrivate::get(d->engine)->typeLoader.get(d->url); + + if (data->isCompleteOrError()) { + d->fromTypeData(data); + d->progress = 1.0; + } else { + d->typeData = data; + d->typeData->registerCallback(d); + d->progress = data->progress(); + } + + emit statusChanged(status()); + emit progressChanged(d->progress); +} + +/*! + Return the list of errors that occurred during the last compile or create + operation. An empty list is returned if isError() is not set. +*/ +QList QQmlComponent::errors() const +{ + Q_D(const QQmlComponent); + if (isError()) + return d->state.errors; + else + return QList(); +} + +/*! + \qmlmethod string Component::errorString() + + Returns a human-readable description of any errors. + + The string includes the file, location, and description of each error. + If multiple errors are present they are separated by a newline character. + + If no errors are present, an empty string is returned. +*/ + +/*! + \internal + errorString is only meant as a way to get the errors in script +*/ +QString QQmlComponent::errorString() const +{ + Q_D(const QQmlComponent); + QString ret; + if(!isError()) + return ret; + foreach(const QQmlError &e, d->state.errors) { + ret += e.url().toString() + QLatin1Char(':') + + QString::number(e.line()) + QLatin1Char(' ') + + e.description() + QLatin1Char('\n'); + } + return ret; +} + +/*! + \qmlproperty url Component::url + The component URL. This is the URL that was used to construct the component. +*/ + +/*! + \property QQmlComponent::url + The component URL. This is the URL passed to either the constructor, + or the loadUrl() or setData() methods. +*/ +QUrl QQmlComponent::url() const +{ + Q_D(const QQmlComponent); + return d->url; +} + +/*! + \internal +*/ +QQmlComponent::QQmlComponent(QQmlComponentPrivate &dd, QObject *parent) + : QObject(dd, parent) +{ +} + +/*! + Create an object instance from this component. Returns 0 if creation + failed. \a context specifies the context within which to create the object + instance. + + If \a context is 0 (the default), it will create the instance in the + engine' s \l {QQmlEngine::rootContext()}{root context}. +*/ +QObject *QQmlComponent::create(QQmlContext *context) +{ + Q_D(QQmlComponent); + + if (!context) + context = d->engine->rootContext(); + + QObject *rv = beginCreate(context); + completeCreate(); + return rv; +} + +/*! + This method provides more advanced control over component instance creation. + In general, programmers should use QQmlComponent::create() to create a + component. + + Create an object instance from this component. Returns 0 if creation + failed. \a publicContext specifies the context within which to create the object + instance. + + When QQmlComponent constructs an instance, it occurs in three steps: + \list 1 + \i The object hierarchy is created, and constant values are assigned. + \i Property bindings are evaluated for the the first time. + \i If applicable, QQmlParserStatus::componentComplete() is called on objects. + \endlist + QQmlComponent::beginCreate() differs from QQmlComponent::create() in that it + only performs step 1. QQmlComponent::completeCreate() must be called to + complete steps 2 and 3. + + This breaking point is sometimes useful when using attached properties to + communicate information to an instantiated component, as it allows their + initial values to be configured before property bindings take effect. +*/ +QObject *QQmlComponent::beginCreate(QQmlContext *publicContext) +{ + Q_D(QQmlComponent); + + Q_ASSERT(publicContext); + QQmlContextData *context = QQmlContextData::get(publicContext); + + return d->beginCreate(context); +} + +QObject * +QQmlComponentPrivate::beginCreate(QQmlContextData *context) +{ + Q_Q(QQmlComponent); + if (!context) { + qWarning("QQmlComponent: Cannot create a component in a null context"); + return 0; + } + + if (!context->isValid()) { + qWarning("QQmlComponent: Cannot create a component in an invalid context"); + return 0; + } + + if (context->engine != engine) { + qWarning("QQmlComponent: Must create component in context from the same QQmlEngine"); + return 0; + } + + if (state.completePending) { + qWarning("QQmlComponent: Cannot create new component instance before completing the previous"); + return 0; + } + + if (!q->isReady()) { + qWarning("QQmlComponent: Component is not ready"); + return 0; + } + + QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(engine); + - bool isRoot = enginePriv->inProgressCreations == 0; ++ if (enginePriv->inProgressCreations == 0) { ++ // only track root, since further ones might not be properly nested ++ profiler = new QQmlObjectCreatingProfiler(); ++ } ++ + enginePriv->inProgressCreations++; + state.errors.clear(); + state.completePending = true; + - if (isRoot) - QQmlProfilerService::startRange(QQmlProfilerService::Creating); - + enginePriv->referenceScarceResources(); + state.vme.init(context, cc, start, creationContext); + QObject *rv = state.vme.execute(&state.errors); + enginePriv->dereferenceScarceResources(); + + if (rv) { + QQmlData *ddata = QQmlData::get(rv); + Q_ASSERT(ddata); + ddata->indestructible = true; + } + + if (enginePriv->isDebugging && rv) { + if (!context->isInternal) + context->asQQmlContextPrivate()->instances.append(rv); + QQmlEngineDebugService::instance()->objectCreated(engine, rv); - if (isRoot) { - QQmlProfilerService::rangeData(QQmlProfilerService::Creating, - buildTypeNameForDebug(rv->metaObject())); ++ ++ if (profiler && profiler->enabled) { ++ profiler->setTypeName(buildTypeNameForDebug(rv->metaObject())); + QQmlData *data = QQmlData::get(rv); + Q_ASSERT(data); - QQmlProfilerService::rangeLocation(QQmlProfilerService::Creating, - cc->url, data->lineNumber, data->columnNumber); ++ profiler->setLocation(cc->url, data->lineNumber, data->columnNumber); + } + } + + return rv; +} + +void QQmlComponentPrivate::beginDeferred(QQmlEnginePrivate *enginePriv, + QObject *object, ConstructionState *state) +{ + enginePriv->inProgressCreations++; + state->errors.clear(); + state->completePending = true; + + state->vme.initDeferred(object); + state->vme.execute(&state->errors); +} + +void QQmlComponentPrivate::complete(QQmlEnginePrivate *enginePriv, ConstructionState *state) +{ + if (state->completePending) { + state->vme.complete(); + + state->completePending = false; + + enginePriv->inProgressCreations--; + + if (0 == enginePriv->inProgressCreations) { + while (enginePriv->erroredBindings) { + enginePriv->warning(enginePriv->erroredBindings->error); + enginePriv->erroredBindings->removeError(); + } + } + } +} + +/*! + This method provides more advanced control over component instance creation. + In general, programmers should use QQmlComponent::create() to create a + component. + + Complete a component creation begin with QQmlComponent::beginCreate(). +*/ +void QQmlComponent::completeCreate() +{ + Q_D(QQmlComponent); + + d->completeCreate(); +} + +void QQmlComponentPrivate::completeCreate() +{ + if (state.completePending) { + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine); + complete(ep, &state); + - QQmlProfilerService::endRange(QQmlProfilerService::Creating); ++ delete profiler; ++ profiler = 0; + } +} + +QQmlComponentAttached::QQmlComponentAttached(QObject *parent) +: QObject(parent), prev(0), next(0) +{ +} + +QQmlComponentAttached::~QQmlComponentAttached() +{ + if (prev) *prev = next; + if (next) next->prev = prev; + prev = 0; + next = 0; +} + +/*! + \internal +*/ +QQmlComponentAttached *QQmlComponent::qmlAttachedProperties(QObject *obj) +{ + QQmlComponentAttached *a = new QQmlComponentAttached(obj); + + QQmlEngine *engine = qmlEngine(obj); + if (!engine) + return a; + + if (QQmlEnginePrivate::get(engine)->activeVME) { // XXX should only be allowed during begin + QQmlEnginePrivate *p = QQmlEnginePrivate::get(engine); + a->add(&p->activeVME->componentAttached); + } else { + QQmlData *d = QQmlData::get(obj); + Q_ASSERT(d); + Q_ASSERT(d->context); + a->add(&d->context->componentAttached); + } + + return a; +} + +void QQmlComponent::create(QQmlIncubator &i, QQmlContext *context, + QQmlContext *forContext) +{ + Q_D(QQmlComponent); + + if (!context) + context = d->engine->rootContext(); + + QQmlContextData *contextData = QQmlContextData::get(context); + QQmlContextData *forContextData = contextData; + if (forContext) forContextData = QQmlContextData::get(forContext); + + if (!contextData->isValid()) { + qWarning("QQmlComponent: Cannot create a component in an invalid context"); + return; + } + + if (contextData->engine != d->engine) { + qWarning("QQmlComponent: Must create component in context from the same QQmlEngine"); + return; + } + + if (!isReady()) { + qWarning("QQmlComponent: Component is not ready"); + return; + } + + i.clear(); + QQmlIncubatorPrivate *p = i.d; + + QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(d->engine); + + p->component = d->cc; p->component->addref(); + p->vme.init(contextData, d->cc, d->start, d->creationContext); + + enginePriv->incubate(i, forContextData); +} + +class QV8IncubatorResource : public QV8ObjectResource, + public QQmlIncubator +{ +V8_RESOURCE_TYPE(IncubatorType) +public: + QV8IncubatorResource(QV8Engine *engine, IncubationMode = Asynchronous); + + static v8::Handle StatusChangedGetter(v8::Local, + const v8::AccessorInfo& info); + static v8::Handle StatusGetter(v8::Local, + const v8::AccessorInfo& info); + static v8::Handle ObjectGetter(v8::Local, + const v8::AccessorInfo& info); + static v8::Handle ForceCompletionGetter(v8::Local, + const v8::AccessorInfo& info); + static v8::Handle ForceCompletion(const v8::Arguments &args); + + static void StatusChangedSetter(v8::Local, v8::Local value, + const v8::AccessorInfo& info); + + void dispose(); + + v8::Persistent me; + QQmlGuard parent; + v8::Persistent valuemap; + v8::Persistent qmlGlobal; +protected: + virtual void statusChanged(Status); + virtual void setInitialState(QObject *); +}; + +static void QQmlComponent_setQmlParent(QObject *me, QObject *parent) +{ + if (parent) { + me->setParent(parent); + typedef QQmlPrivate::AutoParentFunction APF; + QList functions = QQmlMetaType::parentFunctions(); + + bool needParent = false; + for (int ii = 0; ii < functions.count(); ++ii) { + QQmlPrivate::AutoParentResult res = functions.at(ii)(me, parent); + if (res == QQmlPrivate::Parented) { + needParent = false; + break; + } else if (res == QQmlPrivate::IncompatibleParent) { + needParent = true; + } + } + if (needParent) + qWarning("QQmlComponent: Created graphical object was not " + "placed in the graphics scene."); + } +} + +/*! + \qmlmethod object Component::createObject(Item parent, object properties) + + Creates and returns an object instance of this component that will have + the given \a parent and \a properties. The \a properties argument is optional. + Returns null if object creation fails. + + The object will be created in the same context as the one in which the component + was created. This function will always return null when called on components + which were not created in QML. + + If you wish to create an object without setting a parent, specify \c null for + the \a parent value. Note that if the returned object is to be displayed, you + must provide a valid \a parent value or set the returned object's \l{Item::parent}{parent} + property, or else the object will not be visible. + + If a \a parent is not provided to createObject(), a reference to the returned object must be held so that + it is not destroyed by the garbage collector. This is true regardless of whether \l{Item::parent} is set afterwards, + since setting the Item parent does not change object ownership; only the graphical parent is changed. + + As of QtQuick 1.1, this method accepts an optional \a properties argument that specifies a + map of initial property values for the created object. These values are applied before object + creation is finalized. (This is more efficient than setting property values after object creation, + particularly where large sets of property values are defined, and also allows property bindings + to be set up before the object is created.) + + The \a properties argument is specified as a map of property-value items. For example, the code + below creates an object with initial \c x and \c y values of 100 and 200, respectively: + + \js + var component = Qt.createComponent("Button.qml"); + if (component.status == Component.Ready) + component.createObject(parent, {"x": 100, "y": 100}); + \endjs + + Dynamically created instances can be deleted with the \c destroy() method. + See \l {Dynamic Object Management in QML} for more information. +*/ +void QQmlComponent::createObject(QQmlV8Function *args) +{ + Q_D(QQmlComponent); + Q_ASSERT(d->engine); + Q_ASSERT(args); + + QObject *parent = 0; + v8::Local valuemap; + + if (args->Length() >= 1) + parent = args->engine()->toQObject((*args)[0]); + + if (args->Length() >= 2) { + v8::Local v = (*args)[1]; + if (!v->IsObject() || v->IsArray()) { + qmlInfo(this) << tr("createObject: value is not an object"); + args->returnValue(v8::Null()); + return; + } + valuemap = v8::Local::Cast(v); + } + + QV8Engine *v8engine = args->engine(); + + QQmlContext *ctxt = creationContext(); + if (!ctxt) ctxt = d->engine->rootContext(); + + QObject *rv = beginCreate(ctxt); + + if (!rv) { + args->returnValue(v8::Null()); + return; + } + + QQmlComponent_setQmlParent(rv, parent); + + v8::Handle ov = v8engine->newQObject(rv); + Q_ASSERT(ov->IsObject()); + v8::Handle object = v8::Handle::Cast(ov); + + if (!valuemap.IsEmpty()) { + QQmlComponentExtension *e = componentExtension(v8engine); + // Try catch isn't needed as the function itself is loaded with try/catch + v8::Handle function = e->initialProperties->Run(args->qmlGlobal()); + v8::Handle args[] = { object, valuemap }; + v8::Handle::Cast(function)->Call(v8engine->global(), 2, args); + } + + d->completeCreate(); + + Q_ASSERT(QQmlData::get(rv)); + QQmlData::get(rv)->setImplicitDestructible(); + + if (!rv) + args->returnValue(v8::Null()); + else + args->returnValue(object); +} + +/*! + \qmlmethod object Component::incubateObject(Item parent, object properties, enum mode) + + Creates an incubator for instance of this component. Incubators allow new component + instances to be instantiated asynchronously and not cause freezes in the UI. + + The \a parent argument specifies the parent the created instance will have. Omitting the + parameter or passing null will create anobject with no parent. In this case, a reference + to the created object must be maintained by the application of the object will eventually + be garbage collected. + + The \a properties argument is specified as a map of property-value items which will be + set on the created object during its construction. \a mode may be Qt.Synchronous or + Qt.Asynchronous and controls whether the instance is created synchronously or asynchronously. + The default is asynchronously. In some circumstances, even if Qt.Synchronous is specified, + the incubator may create the object asynchronously. This happens if the component calling + incubateObject() is itself being created asynchronously. + + All three arguments are optional. + + If successful, the method returns an incubator, otherwise null. The incubator has the following + properties: + + \list + \i status The status of the incubator. Valid values are Component.Ready, Component.Loading and + Component.Error. + \i object The created object instance. Will only be available once the incubator is in the + Ready status. + \i onStatusChanged Specifies a callback function to be invoked when the status changes. The + status is passed as a parameter to the callback. + \i forceCompletion() Call to complete incubation synchronously. + \endlist + + The following example demonstrates how to use an incubator: + + \js + var component = Qt.createComponent("Button.qml"); + + var incubator = component.incubateObject(parent, { x: 10, y: 10 }); + if (incubator.status != Component.Ready) { + incubator.onStatusChanged = function(status) { + if (status == Component.Ready) { + print ("Object", incubator.object, "is now ready!"); + } + } + } else { + print ("Object", incubator.object, "is ready immediately!"); + } + \endjs +*/ + +void QQmlComponent::incubateObject(QQmlV8Function *args) +{ + Q_D(QQmlComponent); + Q_ASSERT(d->engine); + Q_UNUSED(d); + Q_ASSERT(args); + + QObject *parent = 0; + v8::Local valuemap; + QQmlIncubator::IncubationMode mode = QQmlIncubator::Asynchronous; + + if (args->Length() >= 1) + parent = args->engine()->toQObject((*args)[0]); + + if (args->Length() >= 2) { + v8::Local v = (*args)[1]; + if (v->IsNull()) { + } else if (!v->IsObject() || v->IsArray()) { + qmlInfo(this) << tr("createObject: value is not an object"); + args->returnValue(v8::Null()); + return; + } else { + valuemap = v8::Local::Cast(v); + } + } + + if (args->Length() >= 3) { + quint32 v = (*args)[2]->Uint32Value(); + if (v == 0) + mode = QQmlIncubator::Asynchronous; + else if (v == 1) + mode = QQmlIncubator::AsynchronousIfNested; + } + + QQmlComponentExtension *e = componentExtension(args->engine()); + + QV8IncubatorResource *r = new QV8IncubatorResource(args->engine(), mode); + v8::Local o = e->incubationConstructor->NewInstance(); + o->SetExternalResource(r); + + if (!valuemap.IsEmpty()) { + r->valuemap = qPersistentNew(valuemap); + r->qmlGlobal = qPersistentNew(args->qmlGlobal()); + } + r->parent = parent; + r->me = qPersistentNew(o); + + create(*r, creationContext()); + + if (r->status() == QQmlIncubator::Null) { + r->dispose(); + args->returnValue(v8::Null()); + } else { + args->returnValue(o); + } +} + +// XXX used by QSGLoader +void QQmlComponentPrivate::initializeObjectWithInitialProperties(v8::Handle qmlGlobal, v8::Handle valuemap, QObject *toCreate) +{ + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine); + QV8Engine *v8engine = ep->v8engine(); + + v8::HandleScope handle_scope; + v8::Context::Scope scope(v8engine->context()); + v8::Handle ov = v8engine->newQObject(toCreate); + Q_ASSERT(ov->IsObject()); + v8::Handle object = v8::Handle::Cast(ov); + + if (!valuemap.IsEmpty()) { + QQmlComponentExtension *e = componentExtension(v8engine); + // Try catch isn't needed as the function itself is loaded with try/catch + v8::Handle function = e->initialProperties->Run(qmlGlobal); + v8::Handle args[] = { object, valuemap }; + v8::Handle::Cast(function)->Call(v8engine->global(), 2, args); + } + + QQmlData *ddata = QQmlData::get(toCreate); + Q_ASSERT(ddata); + ddata->setImplicitDestructible(); +} + + +QQmlComponentExtension::QQmlComponentExtension(QV8Engine *engine) +{ + v8::HandleScope handle_scope; + v8::Context::Scope scope(engine->context()); + + forceCompletion = qPersistentNew(V8FUNCTION(QV8IncubatorResource::ForceCompletion, engine)); + + { + v8::Local ft = v8::FunctionTemplate::New(); + ft->InstanceTemplate()->SetHasExternalResource(true); + ft->InstanceTemplate()->SetInternalFieldCount(1); + ft->InstanceTemplate()->SetAccessor(v8::String::New("onStatusChanged"), + QV8IncubatorResource::StatusChangedGetter, + QV8IncubatorResource::StatusChangedSetter); + ft->InstanceTemplate()->SetAccessor(v8::String::New("status"), + QV8IncubatorResource::StatusGetter); + ft->InstanceTemplate()->SetAccessor(v8::String::New("object"), + QV8IncubatorResource::ObjectGetter); + ft->InstanceTemplate()->SetAccessor(v8::String::New("forceCompletion"), + QV8IncubatorResource::ForceCompletionGetter); + incubationConstructor = qPersistentNew(ft->GetFunction()); + } + + { +#define INITIALPROPERTIES_SOURCE \ + "(function(object, values) {"\ + "try {"\ + "for(var property in values) {" \ + "try {"\ + "var properties = property.split(\".\");"\ + "var o = object;"\ + "for (var ii = 0; ii < properties.length - 1; ++ii) {"\ + "o = o[properties[ii]];"\ + "}"\ + "o[properties[properties.length - 1]] = values[property];"\ + "} catch(e) {}"\ + "}"\ + "} catch(e) {}"\ + "})" + initialProperties = qPersistentNew(engine->qmlModeCompile(QLatin1String(INITIALPROPERTIES_SOURCE))); +#undef INITIALPROPERTIES_SOURCE + } +} + +v8::Handle QV8IncubatorResource::ObjectGetter(v8::Local, + const v8::AccessorInfo& info) +{ + QV8IncubatorResource *r = v8_resource_check(info.This()); + return r->engine->newQObject(r->object()); +} + +v8::Handle QV8IncubatorResource::ForceCompletionGetter(v8::Local, + const v8::AccessorInfo& info) +{ + QV8IncubatorResource *r = v8_resource_check(info.This()); + return componentExtension(r->engine)->forceCompletion; +} + +v8::Handle QV8IncubatorResource::ForceCompletion(const v8::Arguments &args) +{ + QV8IncubatorResource *r = v8_resource_cast(args.This()); + if (!r) + V8THROW_TYPE("Not an incubator object"); + + r->forceCompletion(); + + return v8::Undefined(); +} + +v8::Handle QV8IncubatorResource::StatusGetter(v8::Local, + const v8::AccessorInfo& info) +{ + QV8IncubatorResource *r = v8_resource_check(info.This()); + return v8::Integer::NewFromUnsigned(r->status()); +} + +v8::Handle QV8IncubatorResource::StatusChangedGetter(v8::Local, + const v8::AccessorInfo& info) +{ + return info.This()->GetInternalField(0); +} + +void QV8IncubatorResource::StatusChangedSetter(v8::Local, v8::Local value, + const v8::AccessorInfo& info) +{ + info.This()->SetInternalField(0, value); +} + +QQmlComponentExtension::~QQmlComponentExtension() +{ + qPersistentDispose(incubationConstructor); + qPersistentDispose(initialProperties); + qPersistentDispose(forceCompletion); +} + +QV8IncubatorResource::QV8IncubatorResource(QV8Engine *engine, IncubationMode m) +: QV8ObjectResource(engine), QQmlIncubator(m) +{ +} + +void QV8IncubatorResource::setInitialState(QObject *o) +{ + QQmlComponent_setQmlParent(o, parent); + + if (!valuemap.IsEmpty()) { + QQmlComponentExtension *e = componentExtension(engine); + + v8::HandleScope handle_scope; + v8::Context::Scope scope(engine->context()); + + v8::Handle function = e->initialProperties->Run(qmlGlobal); + v8::Handle args[] = { engine->newQObject(o), valuemap }; + v8::Handle::Cast(function)->Call(engine->global(), 2, args); + + qPersistentDispose(valuemap); + qPersistentDispose(qmlGlobal); + } +} + +void QV8IncubatorResource::dispose() +{ + qPersistentDispose(valuemap); + qPersistentDispose(qmlGlobal); + // No further status changes are forthcoming, so we no long need a self reference + qPersistentDispose(me); +} + +void QV8IncubatorResource::statusChanged(Status s) +{ + if (s == Ready) { + Q_ASSERT(QQmlData::get(object())); + QQmlData::get(object())->setImplicitDestructible(); + } + + if (!me.IsEmpty()) { // Will be false in synchronous mode + v8::HandleScope scope; + v8::Local callback = me->GetInternalField(0); + + if (!callback.IsEmpty() && !callback->IsUndefined()) { + + if (callback->IsFunction()) { + v8::Context::Scope context_scope(engine->context()); + v8::Local f = v8::Local::Cast(callback); + v8::Handle args[] = { v8::Integer::NewFromUnsigned(s) }; + v8::TryCatch tc; + f->Call(me, 1, args); + if (tc.HasCaught()) { + QQmlError error; + QQmlExpressionPrivate::exceptionToError(tc.Message(), error); + QQmlEnginePrivate::warning(QQmlEnginePrivate::get(engine->engine()), + error); + } + } + } + } + + if (s == Ready || s == Error) + dispose(); +} + +QT_END_NAMESPACE diff --cc src/qml/qml/qqmlcomponent_p.h index 731fb6a,0000000..b03dd68 mode 100644,000000..100644 --- a/src/qml/qml/qqmlcomponent_p.h +++ b/src/qml/qml/qqmlcomponent_p.h @@@ -1,129 -1,0 +1,131 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLCOMPONENT_P_H +#define QQMLCOMPONENT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qqmlcomponent.h" + +#include +#include "qqmlengine_p.h" +#include "qqmltypeloader_p.h" +#include +#include "qqmlvme_p.h" +#include "qqmlerror.h" +#include "qqml.h" ++#include "../debugger/qqmlprofilerservice_p.h" + +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QV8Engine; + +class QQmlComponent; +class QQmlEngine; +class QQmlCompiledData; + +class QQmlComponentAttached; +class Q_QML_PRIVATE_EXPORT QQmlComponentPrivate : public QObjectPrivate, public QQmlTypeData::TypeDataCallback +{ + Q_DECLARE_PUBLIC(QQmlComponent) + +public: - QQmlComponentPrivate() : typeData(0), progress(0.), start(-1), cc(0), engine(0), creationContext(0) {} ++ QQmlComponentPrivate() : typeData(0), progress(0.), start(-1), cc(0), engine(0), creationContext(0), profiler(0) {} + + QObject *beginCreate(QQmlContextData *); + void completeCreate(); + void initializeObjectWithInitialProperties(v8::Handle qmlGlobal, v8::Handle valuemap, QObject *toCreate); + + QQmlTypeData *typeData; + virtual void typeDataReady(QQmlTypeData *); + virtual void typeDataProgress(QQmlTypeData *, qreal); + + void fromTypeData(QQmlTypeData *data); + + QUrl url; + qreal progress; + + int start; + QQmlCompiledData *cc; + + struct ConstructionState { + ConstructionState() : completePending(false) {} + + QQmlVME vme; + QList errors; + bool completePending; + }; + ConstructionState state; + + static void beginDeferred(QQmlEnginePrivate *enginePriv, QObject *object, + ConstructionState *state); + static void complete(QQmlEnginePrivate *enginePriv, ConstructionState *state); + + QQmlEngine *engine; + QQmlGuardedContextData creationContext; ++ QQmlObjectCreatingProfiler *profiler; + + void clear(); + + static QQmlComponentPrivate *get(QQmlComponent *c) { + return static_cast(QObjectPrivate::get(c)); + } +}; + +QT_END_NAMESPACE + +#endif // QQMLCOMPONENT_P_H diff --cc src/qml/qml/qqmlengine.cpp index 8cfe635,0000000..ee5a0c9 mode 100644,000000..100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@@ -1,1854 -1,0 +1,1854 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmlengine_p.h" +#include "qqmlengine.h" +#include "qqmlcomponentattached_p.h" + +#include "qqmlcontext_p.h" +#include "qqmlcompiler_p.h" +#include "qqml.h" +#include "qqmlcontext.h" +#include "qqmlexpression.h" +#include "qqmlcomponent.h" +#include "qqmlbinding_p_p.h" +#include "qqmlvme_p.h" +#include +#include "qqmlstringconverters_p.h" +#include "qqmlxmlhttprequest_p.h" +#include "qqmlscriptstring.h" +#include "qqmlglobal_p.h" +#include "qquicklistmodel_p.h" +#include "qquickworkerscript_p.h" +#include "qqmlcomponent_p.h" +#include "qqmlnetworkaccessmanagerfactory.h" +#include "qqmlimageprovider.h" +#include "qqmldirparser_p.h" +#include "qqmlextensioninterface.h" +#include "qqmllist_p.h" +#include "qqmltypenamecache_p.h" +#include "qqmlnotifier_p.h" +#include +#include +#include +#include +#include "qqmlincubator.h" +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#ifdef Q_OS_WIN // for %APPDATA% +#include +#include +#include + +#define CSIDL_APPDATA 0x001a // \Application Data +#endif + +Q_DECLARE_METATYPE(QQmlProperty) + +QT_BEGIN_NAMESPACE + +void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor) +{ + QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor); + QQmlValueTypeFactory::registerBaseTypes(uri, versionMajor, versionMinor); +} + +/*! + \qmlclass QtObject QObject + \ingroup qml-utility-elements + \since 4.7 + \brief The QtObject element is the most basic element in QML. + + The QtObject element is a non-visual element which contains only the + objectName property. + + It can be useful to create a QtObject if you need an extremely + lightweight element to enclose a set of custom properties: + + \snippet doc/src/snippets/qml/qtobject.qml 0 + + It can also be useful for C++ integration, as it is just a plain + QObject. See the QObject documentation for further details. +*/ +/*! + \qmlproperty string QtObject::objectName + This property holds the QObject::objectName for this specific object instance. + + This allows a C++ application to locate an item within a QML component + using the QObject::findChild() method. For example, the following C++ + application locates the child \l Rectangle item and dynamically changes its + \c color value: + + \qml + // MyRect.qml + + import QtQuick 2.0 + + Item { + width: 200; height: 200 + + Rectangle { + anchors.fill: parent + color: "red" + objectName: "myRect" + } + } + \endqml + + \code + // main.cpp + + QQuickView view; + view.setSource(QUrl::fromLocalFile("MyRect.qml")); + view.show(); + + QQuickItem *item = view.rootObject()->findChild("myRect"); + if (item) + item->setProperty("color", QColor(Qt::yellow)); + \endcode +*/ + +bool QQmlEnginePrivate::qml_debugging_enabled = false; + +void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor) +{ + qmlRegisterType(uri,versionMajor,versionMinor,"Component"); + qmlRegisterType(uri,versionMajor,versionMinor,"QtObject"); + qmlRegisterType(uri, versionMajor, versionMinor,"ListElement"); + qmlRegisterCustomType(uri, versionMajor, versionMinor,"ListModel", new QQuickListModelParser); + qmlRegisterType(uri,versionMajor,versionMinor,"WorkerScript"); +} + +void QQmlEnginePrivate::defineModule() +{ + registerBaseTypes("QtQuick", 2, 0); + qmlRegisterType(); + qmlRegisterUncreatableType("QtQuick",2,0,"Application", QQuickApplication::tr("Application is an abstract class")); + qmlRegisterUncreatableType("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()")); +} + +/*! +\qmlclass Qt QQmlEnginePrivate + \ingroup qml-utility-elements +\brief The QML global Qt object provides useful enums and functions from Qt. + +\keyword QmlGlobalQtObject + +\brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files. + +The \c Qt object is a global object with utility functions, properties and enums. + +It is not instantiable; to use it, call the members of the global \c Qt object directly. +For example: + +\qml +import QtQuick 2.0 + +Text { + color: Qt.rgba(1, 0, 0, 1) + text: Qt.md5("hello, world") +} +\endqml + + +\section1 Enums + +The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access +the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton. + + +\section1 Types +The Qt object also contains helper functions for creating objects of specific +data types. This is primarily useful when setting the properties of an item +when the property has one of the following types: + +\list +\o \c color - use \l{Qt::rgba()}{Qt.rgba()}, \l{Qt::hsla()}{Qt.hsla()}, \l{Qt::darker()}{Qt.darker()}, \l{Qt::lighter()}{Qt.lighter()} or \l{Qt::tint()}{Qt.tint()} +\o \c rect - use \l{Qt::rect()}{Qt.rect()} +\o \c point - use \l{Qt::point()}{Qt.point()} +\o \c size - use \l{Qt::size()}{Qt.size()} +\o \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()} +\endlist + +There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information. + +\section1 Date/Time Formatters + +The Qt object contains several functions for formatting QDateTime, QDate and QTime values. + +\list + \o \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)} + \o \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)} + \o \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)} +\endlist + +The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}. + + +\section1 Dynamic Object Creation +The following functions on the global object allow you to dynamically create QML +items from files or strings. See \l{Dynamic Object Management in QML} for an overview +of their use. + +\list + \o \l{Qt::createComponent()}{object Qt.createComponent(url)} + \o \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)} +\endlist +*/ + + +/*! + \qmlproperty object Qt::application + \since QtQuick 1.1 + + The \c application object provides access to global application state + properties shared by many QML components. + + Its properties are: + + \table + \row + \o \c application.active + \o + This read-only property indicates whether the application is the top-most and focused + application, and the user is able to interact with the application. The property + is false when the application is in the background, the device keylock or screen + saver is active, the screen backlight is turned off, or the global system dialog + is being displayed on top of the application. It can be used for stopping and + pausing animations, timers and active processing of data in order to save device + battery power and free device memory and processor load when the application is not + active. + + \row + \o \c application.layoutDirection + \o + This read-only property can be used to query the default layout direction of the + application. On system start-up, the default layout direction depends on the + application's language. The property has a value of \c Qt.RightToLeft in locales + where text and graphic elements are read from right to left, and \c Qt.LeftToRight + where the reading direction flows from left to right. You can bind to this + property to customize your application layouts to support both layout directions. + + Possible values are: + + \list + \o Qt.LeftToRight - Text and graphics elements should be positioned + from left to right. + \o Qt.RightToLeft - Text and graphics elements should be positioned + from right to left. + \endlist + + \row + \o \c application.inputPanel + \o + This read-only property allows access to application's QInputPanel object + and all its properties and slots. See the QInputPanel documentation for + further details. Deprecated in favor of Qt.InputMethod + \endtable + + The following example uses the \c application object to indicate + whether the application is currently active: + + \snippet doc/src/snippets/qml/application.qml document + + \qmlproperty object Qt::inputMethod + \since QtQuick 2.0 + + The \c inputMethod object allows access to application's QInputMethod object + and all its properties and slots. See the QInputMethod documentation for + further details. +*/ + + +/*! +\qmlmethod object Qt::include(string url, jsobject callback) + +Includes another JavaScript file. This method can only be used from within JavaScript files, +and not regular QML files. + +This imports all functions from \a url into the current script's namespace. + +Qt.include() returns an object that describes the status of the operation. The object has +a single property, \c {status}, that is set to one of the following values: + +\table +\header \o Symbol \o Value \o Description +\row \o result.OK \o 0 \o The include completed successfully. +\row \o result.LOADING \o 1 \o Data is being loaded from the network. +\row \o result.NETWORK_ERROR \o 2 \o A network error occurred while fetching the url. +\row \o result.EXCEPTION \o 3 \o A JavaScript exception occurred while executing the included code. +An additional \c exception property will be set in this case. +\endtable + +The \c status property will be updated as the operation progresses. + +If provided, \a callback is invoked when the operation completes. The callback is passed +the same object as is returned from the Qt.include() call. +*/ +// Qt.include() is implemented in qv8include.cpp + + +QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e) +: propertyCapture(0), rootContext(0), isDebugging(false), + outputWarningsToStdErr(true), sharedContext(0), sharedScope(0), + cleanup(0), erroredBindings(0), inProgressCreations(0), + workerScriptEngine(0), activeVME(0), + networkAccessManager(0), networkAccessManagerFactory(0), + scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1), + incubatorCount(0), incubationController(0), mutex(QMutex::Recursive) +{ +} + +QQmlEnginePrivate::~QQmlEnginePrivate() +{ - Q_ASSERT(inProgressCreations == 0); ++ if (inProgressCreations) ++ qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations); + + while (cleanup) { + QQmlCleanup *c = cleanup; + cleanup = c->next; + if (cleanup) cleanup->prev = &cleanup; + c->next = 0; + c->prev = 0; + c->clear(); + } + + doDeleteInEngineThread(); + + if (incubationController) incubationController->d = 0; + incubationController = 0; + + delete rootContext; + rootContext = 0; + + for(QHash::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter) + (*iter)->release(); + for(QHash::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter) + (*iter)->release(); + for(QHash, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter) + (*iter)->release(); + for(QHash::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) { + delete (*iter)->qobjectApi; + delete *iter; + } +} + +void QQmlPrivate::qdeclarativeelement_destructor(QObject *o) +{ + QObjectPrivate *p = QObjectPrivate::get(o); + if (p->declarativeData) { + QQmlData *d = static_cast(p->declarativeData); + if (d->ownContext && d->context) { + d->context->destroy(); + d->context = 0; + } + } +} + +void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o) +{ + static_cast(d)->destroyed(o); +} + +void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p) +{ + static_cast(d)->parentChanged(o, p); +} + +void QQmlData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o) +{ + static_cast(d)->objectNameChanged(o); +} + +void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **) +{ + QQmlData *ddata = QQmlData::get(object, false); + if (!ddata) return; // Probably being deleted + + QQmlNotifierEndpoint *ep = ddata->notify(index); + if (ep) QQmlNotifier::emitNotify(ep); +} + +void QQmlEnginePrivate::init() +{ + Q_Q(QQmlEngine); + + static bool firstTime = true; + if (firstTime) { + qmlRegisterType("QML", 1, 0, "Component"); + + firstTime = false; + } + + qRegisterMetaType("QVariant"); + qRegisterMetaType("QQmlScriptString"); + qRegisterMetaType("QJSValue"); + qRegisterMetaType("QQmlComponent::Status"); + qRegisterMetaType >("QList"); + qRegisterMetaType >("QList"); + qRegisterMetaType("QQmlV8Handle"); + + QQmlData::init(); + + v8engine()->setEngine(q); + + rootContext = new QQmlContext(q,true); + + if (QCoreApplication::instance()->thread() == q->thread() && + QQmlEngineDebugService::isDebuggingEnabled()) { + isDebugging = true; + QQmlEngineDebugService::instance()->addEngine(q); + QV8DebugService::initialize(v8engine()); + QV8ProfilerService::initialize(); + QQmlProfilerService::initialize(); + QDebugMessageService::instance(); + } + + QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation); + offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator()) + + QDir::separator() + QLatin1String("QML") + + QDir::separator() + QLatin1String("OfflineStorage"); +} + +QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine() +{ + Q_Q(QQmlEngine); + if (!workerScriptEngine) + workerScriptEngine = new QQuickWorkerScriptEngine(q); + return workerScriptEngine; +} + +/*! + \class QQmlEngine + \since 4.7 + \brief The QQmlEngine class provides an environment for instantiating QML components. + \mainclass + + Each QML component is instantiated in a QQmlContext. + QQmlContext's are essential for passing data to QML + components. In QML, contexts are arranged hierarchically and this + hierarchy is managed by the QQmlEngine. + + Prior to creating any QML components, an application must have + created a QQmlEngine to gain access to a QML context. The + following example shows how to create a simple Text item. + + \code + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl()); + QQuickItem *item = qobject_cast(component.create()); + + //add item to view, etc + ... + \endcode + + In this case, the Text item will be created in the engine's + \l {QQmlEngine::rootContext()}{root context}. + + \sa QQmlComponent QQmlContext +*/ + +/*! + Create a new QQmlEngine with the given \a parent. +*/ +QQmlEngine::QQmlEngine(QObject *parent) +: QJSEngine(*new QQmlEnginePrivate(this), parent) +{ + Q_D(QQmlEngine); + d->init(); +} + +/*! + Destroys the QQmlEngine. + + Any QQmlContext's created on this engine will be + invalidated, but not destroyed (unless they are parented to the + QQmlEngine object). +*/ +QQmlEngine::~QQmlEngine() +{ + Q_D(QQmlEngine); + if (d->isDebugging) { + QQmlEngineDebugService::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 keys = d->moduleApiInstances.keys(); + QObject *currQObjectApi = 0; + QQmlMetaType::ModuleApiInstance *currInstance = 0; + foreach (const QQmlMetaType::ModuleApi &key, keys) { + currInstance = d->moduleApiInstances.value(key); + currQObjectApi = currInstance->qobjectApi; + if (this->children().contains(currQObjectApi)) { + delete currQObjectApi; + delete currInstance; + d->moduleApiInstances.remove(key); + } + } + + // ensure we clean up QObjects with JS ownership + d->v8engine()->gc(); + + if (d->incubationController) + d->incubationController->d = 0; +} + +/*! \fn void QQmlEngine::quit() + This signal is emitted when the QML loaded by the engine would like to quit. + */ + +/*! \fn void QQmlEngine::warnings(const QList &warnings) + This signal is emitted when \a warnings messages are generated by QML. + */ + +/*! + Clears the engine's internal component cache. + + Normally the QQmlEngine caches components loaded from qml + files. This method clears this cache and forces the component to be + reloaded. + */ +void QQmlEngine::clearComponentCache() +{ + Q_D(QQmlEngine); + d->typeLoader.clearCache(); +} + +/*! + Returns the engine's root context. + + The root context is automatically created by the QQmlEngine. + Data that should be available to all QML component instances + instantiated by the engine should be put in the root context. + + Additional data that should only be available to a subset of + component instances should be added to sub-contexts parented to the + root context. +*/ +QQmlContext *QQmlEngine::rootContext() const +{ + Q_D(const QQmlEngine); + return d->rootContext; +} + +/*! + Sets the \a factory to use for creating QNetworkAccessManager(s). + + QNetworkAccessManager is used for all network access by QML. By + implementing a factory it is possible to create custom + QNetworkAccessManager with specialized caching, proxy and cookie + support. + + The factory must be set before executing the engine. +*/ +void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory) +{ + Q_D(QQmlEngine); + QMutexLocker locker(&d->mutex); + d->networkAccessManagerFactory = factory; +} + +/*! + Returns the current QQmlNetworkAccessManagerFactory. + + \sa setNetworkAccessManagerFactory() +*/ +QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const +{ + Q_D(const QQmlEngine); + return d->networkAccessManagerFactory; +} + +void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index) +{ + if (activeVME) { + activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard(obj), index)); + } else { + void *args[] = { 0 }; + QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args); + } +} + +QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const +{ + QMutexLocker locker(&mutex); + QNetworkAccessManager *nam; + if (networkAccessManagerFactory) { + nam = networkAccessManagerFactory->create(parent); + } else { + nam = new QNetworkAccessManager(parent); + } + + return nam; +} + +QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const +{ + Q_Q(const QQmlEngine); + if (!networkAccessManager) + networkAccessManager = createNetworkAccessManager(const_cast(q)); + return networkAccessManager; +} + +/*! + Returns a common QNetworkAccessManager which can be used by any QML + element instantiated by this engine. + + If a QQmlNetworkAccessManagerFactory has been set and a + QNetworkAccessManager has not yet been created, the + QQmlNetworkAccessManagerFactory will be used to create the + QNetworkAccessManager; otherwise the returned QNetworkAccessManager + will have no proxy or cache set. + + \sa setNetworkAccessManagerFactory() +*/ +QNetworkAccessManager *QQmlEngine::networkAccessManager() const +{ + Q_D(const QQmlEngine); + return d->getNetworkAccessManager(); +} + +/*! + + Sets the \a provider to use for images requested via the \e + image: url scheme, with host \a providerId. The QQmlEngine + takes ownership of \a provider. + + Image providers enable support for pixmap and threaded image + requests. See the QQmlImageProvider documentation for details on + implementing and using image providers. + + All required image providers should be added to the engine before any + QML sources files are loaded. + + \sa removeImageProvider() +*/ +void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProvider *provider) +{ + Q_D(QQmlEngine); + QMutexLocker locker(&d->mutex); + d->imageProviders.insert(providerId.toLower(), QSharedPointer(provider)); +} + +/*! + Returns the QQmlImageProvider set for \a providerId. + + Returns the provider if it was found; otherwise returns 0. +*/ +QQmlImageProvider *QQmlEngine::imageProvider(const QString &providerId) const +{ + Q_D(const QQmlEngine); + QMutexLocker locker(&d->mutex); + return d->imageProviders.value(providerId).data(); +} + +/*! + Removes the QQmlImageProvider for \a providerId. + + \sa addImageProvider() +*/ +void QQmlEngine::removeImageProvider(const QString &providerId) +{ + Q_D(QQmlEngine); + QMutexLocker locker(&d->mutex); + d->imageProviders.take(providerId); +} + +QQmlImageProvider::ImageType QQmlEnginePrivate::getImageProviderType(const QUrl &url) +{ + QMutexLocker locker(&mutex); + QSharedPointer provider = imageProviders.value(url.host()); + locker.unlock(); + if (provider) + return provider->imageType(); + return QQmlImageProvider::Invalid; +} + +QQuickTextureFactory *QQmlEnginePrivate::getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size) +{ + QMutexLocker locker(&mutex); + QSharedPointer 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 QQmlEnginePrivate::getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size) +{ + QMutexLocker locker(&mutex); + QImage image; + QSharedPointer provider = imageProviders.value(url.host()); + locker.unlock(); + if (provider) { + QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1); + image = provider->requestImage(imageId, size, req_size); + } + return image; +} + +QPixmap QQmlEnginePrivate::getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size) +{ + QMutexLocker locker(&mutex); + QPixmap pixmap; + QSharedPointer provider = imageProviders.value(url.host()); + locker.unlock(); + if (provider) { + QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1); + pixmap = provider->requestPixmap(imageId, size, req_size); + } + return pixmap; +} + +/*! + Return the base URL for this engine. The base URL is only used to + resolve components when a relative URL is passed to the + QQmlComponent constructor. + + If a base URL has not been explicitly set, this method returns the + application's current working directory. + + \sa setBaseUrl() +*/ +QUrl QQmlEngine::baseUrl() const +{ + Q_D(const QQmlEngine); + if (d->baseUrl.isEmpty()) { + return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator()); + } else { + return d->baseUrl; + } +} + +/*! + Set the base URL for this engine to \a url. + + \sa baseUrl() +*/ +void QQmlEngine::setBaseUrl(const QUrl &url) +{ + Q_D(QQmlEngine); + d->baseUrl = url; +} + +/*! + Returns true if warning messages will be output to stderr in addition + to being emitted by the warnings() signal, otherwise false. + + The default value is true. +*/ +bool QQmlEngine::outputWarningsToStandardError() const +{ + Q_D(const QQmlEngine); + return d->outputWarningsToStdErr; +} + +/*! + Set whether warning messages will be output to stderr to \a enabled. + + If \a enabled is true, any warning messages generated by QML will be + output to stderr and emitted by the warnings() signal. If \a enabled + is false, on the warnings() signal will be emitted. This allows + applications to handle warning output themselves. + + The default value is true. +*/ +void QQmlEngine::setOutputWarningsToStandardError(bool enabled) +{ + Q_D(QQmlEngine); + d->outputWarningsToStdErr = enabled; +} + +/*! + Attempt to free unused memory. +*/ +void QQmlEngine::collectGarbage() +{ + QV8Engine::gc(); +} + +/*! + Returns the QQmlContext for the \a object, or 0 if no + context has been set. + + When the QQmlEngine instantiates a QObject, the context is + set automatically. + */ +QQmlContext *QQmlEngine::contextForObject(const QObject *object) +{ + if(!object) + return 0; + + QObjectPrivate *priv = QObjectPrivate::get(const_cast(object)); + + QQmlData *data = + static_cast(priv->declarativeData); + + if (!data) + return 0; + else if (data->outerContext) + return data->outerContext->asQQmlContext(); + else + return 0; +} + +/*! + Sets the QQmlContext for the \a object to \a context. + If the \a object already has a context, a warning is + output, but the context is not changed. + + When the QQmlEngine instantiates a QObject, the context is + set automatically. + */ +void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context) +{ + if (!object || !context) + return; + + QQmlData *data = QQmlData::get(object, true); + if (data->context) { + qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext"); + return; + } + + QQmlContextData *contextData = QQmlContextData::get(context); + contextData->addObject(object); +} + +/*! + \enum QQmlEngine::ObjectOwnership + + Ownership controls whether or not QML automatically destroys the + QObject when the object is garbage collected by the JavaScript + engine. The two ownership options are: + + \value CppOwnership The object is owned by C++ code, and will + never be deleted by QML. The JavaScript destroy() method cannot be + used on objects with CppOwnership. This option is similar to + QScriptEngine::QtOwnership. + + \value JavaScriptOwnership The object is owned by JavaScript. + When the object is returned to QML as the return value of a method + call or property access, QML will delete the object if there are no + remaining JavaScript references to it and it has no + QObject::parent(). This option is similar to + QScriptEngine::ScriptOwnership. + + Generally an application doesn't need to set an object's ownership + explicitly. QML uses a heuristic to set the default object + ownership. By default, an object that is created by QML has + JavaScriptOwnership. The exception to this are the root objects + created by calling QQmlComponent::create() or + QQmlComponent::beginCreate() which have CppOwnership by + default. The ownership of these root-level objects is considered to + have been transferred to the C++ caller. + + Objects not-created by QML have CppOwnership by default. The + exception to this is objects returned from a C++ method call. The + ownership of these objects is passed to JavaScript. + + Calling setObjectOwnership() overrides the default ownership + heuristic used by QML. +*/ + +/*! + Sets the \a ownership of \a object. +*/ +void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership) +{ + if (!object) + return; + + QQmlData *ddata = QQmlData::get(object, true); + if (!ddata) + return; + + ddata->indestructible = (ownership == CppOwnership)?true:false; + ddata->explicitIndestructibleSet = true; +} + +/*! + Returns the ownership of \a object. +*/ +QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object) +{ + if (!object) + return CppOwnership; + + QQmlData *ddata = QQmlData::get(object, false); + if (!ddata) + return CppOwnership; + else + return ddata->indestructible?CppOwnership:JavaScriptOwnership; +} + +bool QQmlEngine::event(QEvent *e) +{ + Q_D(QQmlEngine); + if (e->type() == QEvent::User) + d->doDeleteInEngineThread(); + + return QJSEngine::event(e); +} + +void QQmlEnginePrivate::doDeleteInEngineThread() +{ + QFieldList list; + mutex.lock(); + list.copyAndClear(toDeleteInEngineThread); + mutex.unlock(); + + while (Deletable *d = list.takeFirst()) + delete d; +} + +Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object) +{ + QQmlData *data = QQmlData::get(object); + + if (data && data->deferredComponent) { - if (QQmlDebugService::isDebuggingEnabled()) { - QQmlProfilerService::startRange(QQmlProfilerService::Creating); ++ QQmlObjectCreatingProfiler prof; ++ if (prof.enabled) { + QQmlType *type = QQmlMetaType::qmlType(object->metaObject()); - QString typeName = type ? type->qmlTypeName() : QString::fromUtf8(object->metaObject()->className()); - QQmlProfilerService::rangeData(QQmlProfilerService::Creating, typeName); ++ prof.setTypeName(type ? type->qmlTypeName() ++ : QString::fromUtf8(object->metaObject()->className())); + if (data->outerContext) - QQmlProfilerService::rangeLocation(QQmlProfilerService::Creating, data->outerContext->url, data->lineNumber, data->columnNumber); ++ prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber); + } + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine); + + QQmlComponentPrivate::ConstructionState state; + QQmlComponentPrivate::beginDeferred(ep, object, &state); + + data->deferredComponent->release(); + data->deferredComponent = 0; + + QQmlComponentPrivate::complete(ep, &state); - QQmlProfilerService::endRange(QQmlProfilerService::Creating); + } +} + +QQmlContext *qmlContext(const QObject *obj) +{ + return QQmlEngine::contextForObject(obj); +} + +QQmlEngine *qmlEngine(const QObject *obj) +{ + QQmlData *data = QQmlData::get(obj, false); + if (!data || !data->context) + return 0; + return data->context->engine; +} + +QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create) +{ + QQmlData *data = QQmlData::get(object); + if (!data) + return 0; // Attached properties are only on objects created by QML + + QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0; + if (rv || !create) + return rv; + + QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id); + if (!pf) + return 0; + + rv = pf(const_cast(object)); + + if (rv) + data->attachedProperties()->insert(id, rv); + + return rv; +} + +QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object, + const QMetaObject *attachedMetaObject, bool create) +{ + if (*idCache == -1) + *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject); + + if (*idCache == -1 || !object) + return 0; + + return qmlAttachedPropertiesObjectById(*idCache, object, create); +} + +QQmlDebuggingEnabler::QQmlDebuggingEnabler() +{ +#ifndef QQML_NO_DEBUG_PROTOCOL + if (!QQmlEnginePrivate::qml_debugging_enabled) { + qWarning("Qml debugging is enabled. Only use this in a safe environment!"); + } + QQmlEnginePrivate::qml_debugging_enabled = true; +#endif +} + + +class QQmlDataExtended { +public: + QQmlDataExtended(); + ~QQmlDataExtended(); + + QHash attachedProperties; + QQmlNotifier objectNameNotifier; +}; + +QQmlDataExtended::QQmlDataExtended() +{ +} + +QQmlDataExtended::~QQmlDataExtended() +{ +} + +void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint) +{ + if (endpoint->next) + layout(endpoint->next); + + int index = endpoint->sourceSignal; + index = qMin(index, 0xFFFF - 1); + + endpoint->next = notifies[index]; + if (endpoint->next) endpoint->next->prev = &endpoint->next; + endpoint->prev = ¬ifies[index]; + notifies[index] = endpoint; +} + +void QQmlData::NotifyList::layout() +{ + Q_ASSERT(maximumTodoIndex >= notifiesSize); + + if (todo) { + QQmlNotifierEndpoint **old = notifies; + const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*); + notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize); + const int memsetSize = (maximumTodoIndex - notifiesSize + 1) * + sizeof(QQmlNotifierEndpoint*); + memset(notifies + notifiesSize, 0, memsetSize); + + if (notifies != old) { + for (int ii = 0; ii < notifiesSize; ++ii) + if (notifies[ii]) + notifies[ii]->prev = ¬ifies[ii]; + } + + notifiesSize = maximumTodoIndex + 1; + + layout(todo); + } + + maximumTodoIndex = 0; + todo = 0; +} + +void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint) +{ + if (!notifyList) { + notifyList = (NotifyList *)malloc(sizeof(NotifyList)); + notifyList->connectionMask = 0; + notifyList->maximumTodoIndex = 0; + notifyList->notifiesSize = 0; + notifyList->todo = 0; + notifyList->notifies = 0; + } + + Q_ASSERT(!endpoint->isConnected()); + + index = qMin(index, 0xFFFF - 1); + notifyList->connectionMask |= (1ULL << quint64(index % 64)); + + if (index < notifyList->notifiesSize) { + + endpoint->next = notifyList->notifies[index]; + if (endpoint->next) endpoint->next->prev = &endpoint->next; + endpoint->prev = ¬ifyList->notifies[index]; + notifyList->notifies[index] = endpoint; + + } else { + notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index); + + endpoint->next = notifyList->todo; + if (endpoint->next) endpoint->next->prev = &endpoint->next; + endpoint->prev = ¬ifyList->todo; + notifyList->todo = endpoint; + } +} + +QQmlNotifier *QQmlData::objectNameNotifier() const +{ + if (!extendedData) extendedData = new QQmlDataExtended; + return &extendedData->objectNameNotifier; +} + +QHash *QQmlData::attachedProperties() const +{ + if (!extendedData) extendedData = new QQmlDataExtended; + return &extendedData->attachedProperties; +} + +void QQmlData::destroyed(QObject *object) +{ + if (deferredComponent) + deferredComponent->release(); + + if (nextContextObject) + nextContextObject->prevContextObject = prevContextObject; + if (prevContextObject) + *prevContextObject = nextContextObject; + + QQmlAbstractBinding *binding = bindings; + while (binding) { + QQmlAbstractBinding *next = binding->m_nextBinding; + binding->m_prevBinding = 0; + binding->m_nextBinding = 0; + binding->destroy(); + binding = next; + } + + if (bindingBits) + free(bindingBits); + + if (propertyCache) + propertyCache->release(); + + if (ownContext && context) + context->destroy(); + + while (guards) { + QQmlGuard *guard = static_cast *>(guards); + *guard = (QObject *)0; + guard->objectDestroyed(object); + } + + if (notifyList) { + while (notifyList->todo) + notifyList->todo->disconnect(); + for (int ii = 0; ii < notifyList->notifiesSize; ++ii) { + while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii]) + ep->disconnect(); + } + free(notifyList->notifies); + free(notifyList); + } + + if (extendedData) + delete extendedData; + + v8object.Clear(); // The WeakReference handler will clean the actual handle + + if (ownMemory) + delete this; +} + +void QQmlData::parentChanged(QObject *object, QObject *parent) +{ + Q_UNUSED(object); + Q_UNUSED(parent); +} + +void QQmlData::objectNameChanged(QObject *) +{ + if (extendedData) objectNameNotifier()->notify(); +} + +bool QQmlData::hasBindingBit(int bit) const +{ + if (bindingBitsSize > bit) + return bindingBits[bit / 32] & (1 << (bit % 32)); + else + return false; +} + +void QQmlData::clearBindingBit(int bit) +{ + if (bindingBitsSize > bit) + bindingBits[bit / 32] &= ~(1 << (bit % 32)); +} + +void QQmlData::setBindingBit(QObject *obj, int bit) +{ + if (bindingBitsSize <= bit) { + int props = obj->metaObject()->propertyCount(); + Q_ASSERT(bit < props); + + int arraySize = (props + 31) / 32; + int oldArraySize = bindingBitsSize / 32; + + bindingBits = (quint32 *)realloc(bindingBits, + arraySize * sizeof(quint32)); + + memset(bindingBits + oldArraySize, + 0x00, + sizeof(quint32) * (arraySize - oldArraySize)); + + bindingBitsSize = arraySize * 32; + } + + bindingBits[bit / 32] |= (1 << (bit % 32)); +} + +QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QUrl& url) +{ + if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) { + if (url.authority().isEmpty()) + return QLatin1Char(':') + url.path(); + return QString(); + } + return url.toLocalFile(); +} + + +static QString toLocalFile(const QString &url) +{ + if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive)) + return QString(); + + QString file = url.mid(7); + + //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt" + + // magic for drives on windows + if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':')) + file.remove(0, 1); + + return file; +} + +QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QString& url) +{ + if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) { + if (url.length() > 4) + return QLatin1Char(':') + url.mid(4); + return QString(); + } + + return toLocalFile(url); +} + +void QQmlEnginePrivate::sendQuit() +{ + Q_Q(QQmlEngine); + emit q->quit(); + if (q->receivers(SIGNAL(quit())) == 0) { + qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it."); + } +} + +static void dumpwarning(const QQmlError &error) +{ + qWarning().nospace() << qPrintable(error.toString()); +} + +static void dumpwarning(const QList &errors) +{ + for (int ii = 0; ii < errors.count(); ++ii) + dumpwarning(errors.at(ii)); +} + +void QQmlEnginePrivate::warning(const QQmlError &error) +{ + Q_Q(QQmlEngine); + q->warnings(QList() << error); + if (outputWarningsToStdErr) + dumpwarning(error); +} + +void QQmlEnginePrivate::warning(const QList &errors) +{ + Q_Q(QQmlEngine); + q->warnings(errors); + if (outputWarningsToStdErr) + dumpwarning(errors); +} + +void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error) +{ + if (engine) + QQmlEnginePrivate::get(engine)->warning(error); + else + dumpwarning(error); +} + +void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList &error) +{ + if (engine) + QQmlEnginePrivate::get(engine)->warning(error); + else + dumpwarning(error); +} + +void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error) +{ + if (engine) + engine->warning(error); + else + dumpwarning(error); +} + +void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList &error) +{ + if (engine) + engine->warning(error); + else + dumpwarning(error); +} + +/* + 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 QQmlEnginePrivate::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 QQmlEnginePrivate::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. + while (ScarceResourceData *sr = scarceResources.first()) { + sr->data = QVariant(); + scarceResources.remove(sr); + } + } +} + +/*! + Adds \a path as a directory where the engine searches for + installed modules in a URL-based directory structure. + The \a path may be a local filesystem directory or a URL. + + The newly added \a path will be first in the importPathList(). + + \sa setImportPathList(), {QML Modules} +*/ +void QQmlEngine::addImportPath(const QString& path) +{ + Q_D(QQmlEngine); + d->importDatabase.addImportPath(path); +} + +/*! + Returns the list of directories where the engine searches for + 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 QQmlEngine to look + in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components + provided by that module. A \c qmldir file is required for defining the - type version mapping and possibly declarative extensions plugins. ++ type version mapping and possibly QML extensions plugins. + + By default, the list contains the directory of the application executable, + paths specified in the \c QML_IMPORT_PATH environment variable, + and the builtin \c ImportsPath from QLibraryInfo. + + \sa addImportPath() setImportPathList() +*/ +QStringList QQmlEngine::importPathList() const +{ + Q_D(const QQmlEngine); + return d->importDatabase.importPathList(); +} + +/*! + Sets \a paths as the list of directories where the engine searches for + installed modules in a URL-based directory structure. + + By default, the list contains the directory of the application executable, + paths specified in the \c QML_IMPORT_PATH environment variable, + and the builtin \c ImportsPath from QLibraryInfo. + + \sa importPathList() addImportPath() + */ +void QQmlEngine::setImportPathList(const QStringList &paths) +{ + Q_D(QQmlEngine); + d->importDatabase.setImportPathList(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 QQmlEngine::addPluginPath(const QString& path) +{ + Q_D(QQmlEngine); + d->importDatabase.addPluginPath(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 QQmlEngine::pluginPathList() const +{ + Q_D(const QQmlEngine); + return d->importDatabase.pluginPathList(); +} + +/*! + Sets the list of directories where the engine searches for + native plugins for imported modules (referenced in the \c qmldir file) + to \a paths. + + 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 QQmlEngine::setPluginPathList(const QStringList &paths) +{ + Q_D(QQmlEngine); + d->importDatabase.setPluginPathList(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 QQmlExtensionPlugin interface. +*/ +bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList *errors) +{ + Q_D(QQmlEngine); + 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 QQmlExtensionPlugin interface. +*/ +bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString) +{ + Q_D(QQmlEngine); + QList 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; +} + +/*! + \property QQmlEngine::offlineStoragePath + \brief the directory for storing offline user data + + Returns the directory where SQL and other offline + storage is placed. + + QQuickWebView and the SQL databases created with openDatabase() + are stored here. + + The default is QML/OfflineStorage in the platform-standard + user application data directory. + + Note that the path may not currently exist on the filesystem, so + callers wanting to \e create new files at this location should create + it first - see QDir::mkpath(). +*/ +void QQmlEngine::setOfflineStoragePath(const QString& dir) +{ + Q_D(QQmlEngine); + d->offlineStoragePath = dir; +} + +QString QQmlEngine::offlineStoragePath() const +{ + Q_D(const QQmlEngine); + return d->offlineStoragePath; +} + +static void voidptr_destructor(void *v) +{ + void **ptr = (void **)v; + delete ptr; +} + +static void *voidptr_constructor(const void *v) +{ + if (!v) { + return new void*; + } else { + return new void*(*(void **)v); + } +} + +QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo) +{ + Q_Q(QQmlEngine); + + if (!mo->superClass()) { + QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo); + propertyCache.insert(mo, rv); + return rv; + } else { + QQmlPropertyCache *super = cache(mo->superClass()); + QQmlPropertyCache *rv = super->copyAndAppend(q, mo); + propertyCache.insert(mo, rv); + return rv; + } +} + +QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion, + QQmlError &error) +{ + QList types; + + int maxMinorVersion = 0; + + const QMetaObject *metaObject = type->metaObject(); + + while (metaObject) { + QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(), + type->majorVersion(), minorVersion); + if (t) { + maxMinorVersion = qMax(maxMinorVersion, t->minorVersion()); + types << t; + } else { + types << 0; + } + + metaObject = metaObject->superClass(); + } + + if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) { + c->addref(); + typePropertyCache.insert(qMakePair(type, minorVersion), c); + return c; + } + + QQmlPropertyCache *raw = cache(type->metaObject()); + + bool hasCopied = false; + + for (int ii = 0; ii < types.count(); ++ii) { + QQmlType *currentType = types.at(ii); + if (!currentType) + continue; + + int rev = currentType->metaObjectRevision(); + int moIndex = types.count() - 1 - ii; + + if (raw->allowedRevisionCache[moIndex] != rev) { + if (!hasCopied) { + raw = raw->copy(); + hasCopied = true; + } + raw->allowedRevisionCache[moIndex] = rev; + } + } + + // Test revision compatibility - the basic rule is: + // * Anything that is excluded, cannot overload something that is not excluded * + + // Signals override: + // * other signals and methods of the same name. + // * properties named on + // * automatic Changed notify signals + + // Methods override: + // * other methods of the same name + + // Properties override: + // * other elements of the same name + + bool overloadError = false; + QString overloadName; + +#if 0 + for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin(); + !overloadError && iter != raw->stringCache.end(); + ++iter) { + + QQmlPropertyData *d = *iter; + if (raw->isAllowedInRevision(d)) + continue; // Not excluded - no problems + + // check that a regular "name" overload isn't happening + QQmlPropertyData *current = d; + while (!overloadError && current) { + current = d->overrideData(current); + if (current && raw->isAllowedInRevision(current)) + overloadError = true; + } + } +#endif + + if (overloadError) { + if (hasCopied) raw->release(); + + error.setDescription(QLatin1String("Type ") + type->qmlTypeName() + QLatin1String(" ") + QString::number(type->majorVersion()) + QLatin1String(".") + QString::number(minorVersion) + QLatin1String(" contains an illegal property \"") + overloadName + QLatin1String("\". This is an error in the type's implementation.")); + return 0; + } + + if (!hasCopied) raw->addref(); + typePropertyCache.insert(qMakePair(type, minorVersion), raw); + + if (minorVersion != maxMinorVersion) { + raw->addref(); + typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw); + } + + return raw; +} + +QQmlMetaType::ModuleApiInstance * +QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module) +{ + Locker locker(this); + + QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module); + if (!a) { + a = new QQmlMetaType::ModuleApiInstance; + a->scriptCallback = module.script; + a->qobjectCallback = module.qobject; + moduleApiInstances.insert(module, a); + } + + return a; +} + +bool QQmlEnginePrivate::isQObject(int t) +{ + Locker locker(this); + return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t); +} + +QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const +{ + Locker locker(this); + int t = v.userType(); + if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) { + if (ok) *ok = true; + return *(QObject **)(v.constData()); + } else { + return QQmlMetaType::toQObject(v, ok); + } +} + +QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const +{ + Locker locker(this); + if (m_compositeTypes.contains(t)) + return QQmlMetaType::Object; + else if (m_qmlLists.contains(t)) + return QQmlMetaType::List; + else + return QQmlMetaType::typeCategory(t); +} + +bool QQmlEnginePrivate::isList(int t) const +{ + Locker locker(this); + return m_qmlLists.contains(t) || QQmlMetaType::isList(t); +} + +int QQmlEnginePrivate::listType(int t) const +{ + Locker locker(this); + QHash::ConstIterator iter = m_qmlLists.find(t); + if (iter != m_qmlLists.end()) + return *iter; + else + return QQmlMetaType::listType(t); +} + +const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const +{ + Locker locker(this); + QHash::ConstIterator iter = m_compositeTypes.find(t); + if (iter != m_compositeTypes.end()) { + return (*iter)->root; + } else { + QQmlType *type = QQmlMetaType::qmlType(t); + return type?type->baseMetaObject():0; + } +} + +const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const +{ + Locker locker(this); + QHash::ConstIterator iter = m_compositeTypes.find(t); + if (iter != m_compositeTypes.end()) { + return (*iter)->root; + } else { + QQmlType *type = QQmlMetaType::qmlType(t); + return type?type->metaObject():0; + } +} + +void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data) +{ + QByteArray name = data->root->className(); + + QByteArray ptr = name + '*'; + QByteArray lst = "QQmlListProperty<" + name + '>'; + + int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor, + voidptr_constructor); + int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor, + voidptr_constructor); + + data->addref(); + + Locker locker(this); + m_qmlLists.insert(lst_type, ptr_type); + m_compositeTypes.insert(ptr_type, data); +} + +bool QQml_isFileCaseCorrect(const QString &fileName) +{ +#if defined(Q_OS_MAC) || defined(Q_OS_WIN) + QFileInfo info(fileName); + const QString absolute = info.absoluteFilePath(); + +#if defined(Q_OS_MAC) + const QString canonical = info.canonicalFilePath(); +#elif defined(Q_OS_WIN) + wchar_t buffer[1024]; + + DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024); + if (rv == 0 || rv >= 1024) return true; + rv = ::GetLongPathName(buffer, buffer, 1024); + if (rv == 0 || rv >= 1024) return true; + + const QString canonical = QString::fromWCharArray(buffer); +#endif + + const int absoluteLength = absolute.length(); + const int canonicalLength = canonical.length(); + + const int length = qMin(absoluteLength, canonicalLength); + for (int ii = 0; ii < length; ++ii) { + const QChar &a = absolute.at(absoluteLength - 1 - ii); + const QChar &c = canonical.at(canonicalLength - 1 - ii); + + if (a.toLower() != c.toLower()) + return true; + if (a != c) + return false; + } +#else + Q_UNUSED(fileName) +#endif + return true; +} + +/*! + \fn QQmlEngine *qmlEngine(const QObject *object) + \relates QQmlEngine + + Returns the QQmlEngine associated with \a object, if any. This is equivalent to + QQmlEngine::contextForObject(object)->engine(), but more efficient. +*/ + +/*! + \fn QQmlContext *qmlContext(const QObject *object) + \relates QQmlEngine + + Returns the QQmlContext associated with \a object, if any. This is equivalent to + QQmlEngine::contextForObject(object). +*/ + +QT_END_NAMESPACE diff --cc src/qml/qml/qqmlexpression.cpp index 3fbb80c,0000000..ecdbf21 mode 100644,000000..100644 --- a/src/qml/qml/qqmlexpression.cpp +++ b/src/qml/qml/qqmlexpression.cpp @@@ -1,982 -1,0 +1,982 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmlexpression.h" +#include "qqmlexpression_p.h" + +#include "qqmlengine_p.h" +#include "qqmlcontext_p.h" +#include "qqmlrewrite_p.h" +#include "qqmlscriptstring_p.h" +#include "qqmlcompiler_p.h" + +#include + +QT_BEGIN_NAMESPACE + +bool QQmlDelayedError::addError(QQmlEnginePrivate *e) +{ + if (!e) return false; + + if (e->inProgressCreations == 0) return false; // Not in construction + + if (prevError) return true; // Already in error chain + + prevError = &e->erroredBindings; + nextError = e->erroredBindings; + e->erroredBindings = this; + if (nextError) nextError->prevError = &nextError; + + return true; +} + +QQmlJavaScriptExpression::QQmlJavaScriptExpression(VTable *v) +: m_vtable(v) +{ +} + +QQmlJavaScriptExpression::~QQmlJavaScriptExpression() +{ + clearGuards(); +} + - static QQmlJavaScriptExpression::VTable QDeclarativeExpressionPrivate_jsvtable = { ++static QQmlJavaScriptExpression::VTable QQmlExpressionPrivate_jsvtable = { + QQmlExpressionPrivate::expressionIdentifier, + QQmlExpressionPrivate::expressionChanged +}; + +QQmlExpressionPrivate::QQmlExpressionPrivate() - : QQmlJavaScriptExpression(&QDeclarativeExpressionPrivate_jsvtable), ++: QQmlJavaScriptExpression(&QQmlExpressionPrivate_jsvtable), + expressionFunctionValid(true), expressionFunctionRewritten(false), + extractExpressionFromFunction(false), line(-1), dataRef(0) +{ +} + +QQmlExpressionPrivate::~QQmlExpressionPrivate() +{ + qPersistentDispose(v8qmlscope); + qPersistentDispose(v8function); + if (dataRef) dataRef->release(); + dataRef = 0; +} + +void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, + QObject *me) +{ + expression = expr; + + QQmlAbstractExpression::setContext(ctxt); + setScopeObject(me); + expressionFunctionValid = false; + expressionFunctionRewritten = false; +} + +void QQmlExpressionPrivate::init(QQmlContextData *ctxt, v8::Handle func, + QObject *me) +{ + QQmlAbstractExpression::setContext(ctxt); + setScopeObject(me); + + v8function = qPersistentNew(func); + setUseSharedContext(false); + expressionFunctionValid = true; + expressionFunctionRewritten = false; + extractExpressionFromFunction = true; +} + +void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, + bool isRewritten, QObject *me, const QString &srcUrl, + int lineNumber, int columnNumber) +{ + url = srcUrl; + line = lineNumber; + column = columnNumber; + + expression = expr; + + expressionFunctionValid = false; + expressionFunctionRewritten = isRewritten; + + QQmlAbstractExpression::setContext(ctxt); + setScopeObject(me); +} + +void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QByteArray &expr, + bool isRewritten, QObject *me, const QString &srcUrl, + int lineNumber, int columnNumber) +{ + url = srcUrl; + line = lineNumber; + column = columnNumber; + + if (isRewritten) { + expressionFunctionValid = true; + expressionFunctionRewritten = true; + v8function = evalFunction(ctxt, me, expr.constData(), expr.length(), + srcUrl, lineNumber, &v8qmlscope); + setUseSharedContext(false); + + expressionUtf8 = expr; + } else { + expression = QString::fromUtf8(expr); + + expressionFunctionValid = false; + expressionFunctionRewritten = isRewritten; + } + + QQmlAbstractExpression::setContext(ctxt); + setScopeObject(me); +} + +// Callee owns the persistent handle +v8::Persistent +QQmlExpressionPrivate::evalFunction(QQmlContextData *ctxt, QObject *scope, + const char *code, int codeLength, + const QString &filename, int line, + v8::Persistent *qmlscope) +{ + QQmlEngine *engine = ctxt->engine; + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine); + + v8::HandleScope handle_scope; + v8::Context::Scope ctxtscope(ep->v8engine()->context()); + + v8::TryCatch tc; + v8::Local scopeobject = ep->v8engine()->qmlScope(ctxt, scope); + v8::Local script = ep->v8engine()->qmlModeCompile(code, codeLength, filename, line); + if (tc.HasCaught()) { + QQmlError error; + error.setDescription(QLatin1String("Exception occurred during function compilation")); + error.setLine(line); + error.setUrl(QUrl::fromLocalFile(filename)); + v8::Local message = tc.Message(); + if (!message.IsEmpty()) + QQmlExpressionPrivate::exceptionToError(message, error); + ep->warning(error); + return v8::Persistent(); + } + v8::Local result = script->Run(scopeobject); + if (tc.HasCaught()) { + QQmlError error; + error.setDescription(QLatin1String("Exception occurred during function evaluation")); + error.setLine(line); + error.setUrl(QUrl::fromLocalFile(filename)); + v8::Local message = tc.Message(); + if (!message.IsEmpty()) + QQmlExpressionPrivate::exceptionToError(message, error); + ep->warning(error); + return v8::Persistent(); + } + if (qmlscope) *qmlscope = qPersistentNew(scopeobject); + return qPersistentNew(v8::Local::Cast(result)); +} + +// Callee owns the persistent handle +v8::Persistent +QQmlExpressionPrivate::evalFunction(QQmlContextData *ctxt, QObject *scope, + const QString &code, const QString &filename, int line, + v8::Persistent *qmlscope) +{ + QQmlEngine *engine = ctxt->engine; + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine); + + v8::HandleScope handle_scope; + v8::Context::Scope ctxtscope(ep->v8engine()->context()); + + v8::TryCatch tc; + v8::Local scopeobject = ep->v8engine()->qmlScope(ctxt, scope); + v8::Local script = ep->v8engine()->qmlModeCompile(code, filename, line); + if (tc.HasCaught()) { + QQmlError error; + error.setDescription(QLatin1String("Exception occurred during function compilation")); + error.setLine(line); + error.setUrl(QUrl::fromLocalFile(filename)); + v8::Local message = tc.Message(); + if (!message.IsEmpty()) + QQmlExpressionPrivate::exceptionToError(message, error); + ep->warning(error); + return v8::Persistent(); + } + v8::Local result = script->Run(scopeobject); + if (tc.HasCaught()) { + QQmlError error; + error.setDescription(QLatin1String("Exception occurred during function evaluation")); + error.setLine(line); + error.setUrl(QUrl::fromLocalFile(filename)); + v8::Local message = tc.Message(); + if (!message.IsEmpty()) + QQmlExpressionPrivate::exceptionToError(message, error); + ep->warning(error); + return v8::Persistent(); + } + if (qmlscope) *qmlscope = qPersistentNew(scopeobject); + return qPersistentNew(v8::Local::Cast(result)); +} + +QQmlExpression * +QQmlExpressionPrivate::create(QQmlContextData *ctxt, QObject *object, + const QString &expr, bool isRewritten, + const QString &url, int lineNumber, int columnNumber) +{ + return new QQmlExpression(ctxt, object, expr, isRewritten, url, lineNumber, columnNumber, *new QQmlExpressionPrivate); +} + +/*! + \class QQmlExpression + \since 4.7 + \brief The QQmlExpression class evaluates JavaScript in a QML context. + + For example, given a file \c main.qml like this: + + \qml + import QtQuick 2.0 + + Item { + width: 200; height: 200 + } + \endqml + + The following code evaluates a JavaScript expression in the context of the + above QML: + + \code + QQmlEngine *engine = new QQmlEngine; + QQmlComponent component(engine, QUrl::fromLocalFile("main.qml")); + + QObject *myObject = component.create(); + QQmlExpression *expr = new QQmlExpression(engine->rootContext(), myObject, "width * 2"); + int result = expr->evaluate().toInt(); // result = 400 + \endcode +*/ + +/*! + Create an invalid QQmlExpression. + + As the expression will not have an associated QQmlContext, this will be a + null expression object and its value will always be an invalid QVariant. + */ +QQmlExpression::QQmlExpression() +: QObject(*new QQmlExpressionPrivate, 0) +{ +} + +/*! \internal */ +QQmlExpression::QQmlExpression(QQmlContextData *ctxt, + QObject *object, const QString &expr, bool isRewritten, + const QString &url, int lineNumber, int columnNumber, + QQmlExpressionPrivate &dd) +: QObject(dd, 0) +{ + Q_D(QQmlExpression); + d->init(ctxt, expr, isRewritten, object, url, lineNumber, columnNumber); +} + +/*! \internal */ +QQmlExpression::QQmlExpression(QQmlContextData *ctxt, + QObject *object, const QByteArray &expr, + bool isRewritten, + const QString &url, int lineNumber, int columnNumber, + QQmlExpressionPrivate &dd) +: QObject(dd, 0) +{ + Q_D(QQmlExpression); + d->init(ctxt, expr, isRewritten, object, url, lineNumber, columnNumber); +} + +/*! + Create a QQmlExpression object that is a child of \a parent. + + The \script provides the expression to be evaluated, the context to evaluate it in, + and the scope object to evaluate it with. + + This constructor is functionally equivalent to the following, but in most cases + is more efficient. + \code + QQmlExpression expression(script.context(), script.scopeObject(), script.script(), parent); + \endcode + + \sa QQmlScriptString +*/ +QQmlExpression::QQmlExpression(const QQmlScriptString &script, QObject *parent) +: QObject(*new QQmlExpressionPrivate, parent) +{ + Q_D(QQmlExpression); + bool defaultConstruction = false; + + int id = script.d.data()->bindingId; + if (id < 0) { + defaultConstruction = true; + } else { + QQmlContextData *ctxtdata = QQmlContextData::get(script.context()); + + QQmlEnginePrivate *engine = QQmlEnginePrivate::get(script.context()->engine()); + QQmlCompiledData *cdata = 0; + QQmlTypeData *typeData = 0; + if (engine && ctxtdata && !ctxtdata->url.isEmpty()) { + typeData = engine->typeLoader.get(ctxtdata->url); + cdata = typeData->compiledData(); + } + + if (cdata) + d->init(ctxtdata, cdata->primitives.at(id), true, script.scopeObject(), + cdata->name, script.d.data()->lineNumber, script.d.data()->columnNumber); + else + defaultConstruction = true; + + if (cdata) + cdata->release(); + if (typeData) + typeData->release(); + } + + if (defaultConstruction) + d->init(QQmlContextData::get(script.context()), script.script(), script.scopeObject()); +} + +/*! + Create a QQmlExpression object that is a child of \a parent. + + The \a expression JavaScript will be executed in the \a ctxt QQmlContext. + If specified, the \a scope object's properties will also be in scope during + the expression's execution. +*/ +QQmlExpression::QQmlExpression(QQmlContext *ctxt, + QObject *scope, + const QString &expression, + QObject *parent) +: QObject(*new QQmlExpressionPrivate, parent) +{ + Q_D(QQmlExpression); + d->init(QQmlContextData::get(ctxt), expression, scope); +} + +/*! + \internal +*/ +QQmlExpression::QQmlExpression(QQmlContextData *ctxt, QObject *scope, + const QString &expression) +: QObject(*new QQmlExpressionPrivate, 0) +{ + Q_D(QQmlExpression); + d->init(ctxt, expression, scope); +} + +/*! \internal */ +QQmlExpression::QQmlExpression(QQmlContextData *ctxt, QObject *scope, + const QString &expression, QQmlExpressionPrivate &dd) +: QObject(dd, 0) +{ + Q_D(QQmlExpression); + d->init(ctxt, expression, scope); +} + +/*! + \internal + + To avoid exposing v8 in the public API, functionPtr must be a pointer to a v8::Handle. + For example: + v8::Handle function; + new QQmlExpression(ctxt, scope, &function, ...); + */ +QQmlExpression::QQmlExpression(QQmlContextData *ctxt, QObject *scope, void *functionPtr, + QQmlExpressionPrivate &dd) +: QObject(dd, 0) +{ + v8::Handle function = *(v8::Handle *)functionPtr; + + Q_D(QQmlExpression); + d->init(ctxt, function, scope); +} + +/*! + Destroy the QQmlExpression instance. +*/ +QQmlExpression::~QQmlExpression() +{ +} + +/*! + Returns the QQmlEngine this expression is associated with, or 0 if there + is no association or the QQmlEngine has been destroyed. +*/ +QQmlEngine *QQmlExpression::engine() const +{ + Q_D(const QQmlExpression); + return d->context()?d->context()->engine:0; +} + +/*! + Returns the QQmlContext this expression is associated with, or 0 if there + is no association or the QQmlContext has been destroyed. +*/ +QQmlContext *QQmlExpression::context() const +{ + Q_D(const QQmlExpression); + QQmlContextData *data = d->context(); + return data?data->asQQmlContext():0; +} + +/*! + Returns the expression string. +*/ +QString QQmlExpression::expression() const +{ + Q_D(const QQmlExpression); + if (d->extractExpressionFromFunction && context()->engine()) { + QV8Engine *v8engine = QQmlEnginePrivate::getV8Engine(context()->engine()); + v8::HandleScope handle_scope; + v8::Context::Scope scope(v8engine->context()); + + return v8engine->toString(v8::Handle(d->v8function)); + } else if (!d->expressionUtf8.isEmpty()) { + return QString::fromUtf8(d->expressionUtf8); + } else { + return d->expression; + } +} + +/*! + Set the expression to \a expression. +*/ +void QQmlExpression::setExpression(const QString &expression) +{ + Q_D(QQmlExpression); + + d->resetNotifyOnValueChanged(); + d->expression = expression; + d->expressionUtf8.clear(); + d->expressionFunctionValid = false; + d->expressionFunctionRewritten = false; + qPersistentDispose(d->v8function); + qPersistentDispose(d->v8qmlscope); +} + +void QQmlExpressionPrivate::exceptionToError(v8::Handle message, + QQmlError &error) +{ + Q_ASSERT(!message.IsEmpty()); + + v8::Handle name = message->GetScriptResourceName(); + v8::Handle description = message->Get(); + int lineNumber = message->GetLineNumber(); + + v8::Local file = name->IsString()?name->ToString():v8::Local(); + if (file.IsEmpty() || file->Length() == 0) + error.setUrl(QUrl(QLatin1String(""))); + else + error.setUrl(QUrl(QV8Engine::toStringStatic(file))); + + error.setLine(lineNumber); + error.setColumn(-1); + + QString qDescription = QV8Engine::toStringStatic(description); + if (qDescription.startsWith(QLatin1String("Uncaught "))) + qDescription = qDescription.mid(9 /* strlen("Uncaught ") */); + + error.setDescription(qDescription); +} + +void QQmlJavaScriptExpression::setNotifyOnValueChanged(bool v) +{ + activeGuards.setFlagValue(v); + if (!v) clearGuards(); +} + +void QQmlJavaScriptExpression::resetNotifyOnValueChanged() +{ + clearGuards(); +} + +v8::Local +QQmlJavaScriptExpression::evaluate(QQmlContextData *context, + v8::Handle function, bool *isUndefined) +{ + Q_ASSERT(context && context->engine); + + if (function.IsEmpty() || function->IsUndefined()) { + if (isUndefined) *isUndefined = true; + return v8::Local(); + } + + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine); + + Q_ASSERT(notifyOnValueChanged() || activeGuards.isEmpty()); + GuardCapture capture(context->engine, this); + + QQmlEnginePrivate::PropertyCapture *lastPropertyCapture = ep->propertyCapture; + ep->propertyCapture = notifyOnValueChanged()?&capture:0; + + + if (notifyOnValueChanged()) + capture.guards.copyAndClearPrepend(activeGuards); + + QQmlContextData *lastSharedContext = 0; + QObject *lastSharedScope = 0; + + bool sharedContext = useSharedContext(); + + // All code that follows must check with watcher before it accesses data members + // incase we have been deleted. + DeleteWatcher watcher(this); + + if (sharedContext) { + lastSharedContext = ep->sharedContext; + lastSharedScope = ep->sharedScope; + ep->sharedContext = context; + ep->sharedScope = scopeObject(); + } + + v8::Local result; + { + v8::TryCatch try_catch; + v8::Handle This = ep->v8engine()->global(); + if (scopeObject() && requiresThisObject()) { + v8::Handle value = ep->v8engine()->newQObject(scopeObject()); + if (value->IsObject()) This = v8::Handle::Cast(value); + } + + result = function->Call(This, 0, 0); + + if (isUndefined) + *isUndefined = try_catch.HasCaught() || result->IsUndefined(); + + if (watcher.wasDeleted()) { + } else if (try_catch.HasCaught()) { + v8::Context::Scope scope(ep->v8engine()->context()); + v8::Local message = try_catch.Message(); + if (!message.IsEmpty()) { + QQmlExpressionPrivate::exceptionToError(message, delayedError()->error); + } else { + if (hasDelayedError()) delayedError()->error = QQmlError(); + } + } else { + if (hasDelayedError()) delayedError()->error = QQmlError(); + } + } + + if (sharedContext) { + ep->sharedContext = lastSharedContext; + ep->sharedScope = lastSharedScope; + } + + if (capture.errorString) { + for (int ii = 0; ii < capture.errorString->count(); ++ii) + qWarning("%s", qPrintable(capture.errorString->at(ii))); + delete capture.errorString; + capture.errorString = 0; + } + + while (Guard *g = capture.guards.takeFirst()) + g->Delete(); + + ep->propertyCapture = lastPropertyCapture; + + return result; +} + +void QQmlJavaScriptExpression::GuardCapture::captureProperty(QQmlNotifier *n) +{ + if (expression) { + + // Try and find a matching guard + while (!guards.isEmpty() && !guards.first()->isConnected(n)) + guards.takeFirst()->Delete(); + + Guard *g = 0; + if (!guards.isEmpty()) { + g = guards.takeFirst(); + g->cancelNotify(); + Q_ASSERT(g->isConnected(n)); + } else { + g = Guard::New(expression, engine); + g->connect(n); + } + + expression->activeGuards.prepend(g); + } +} + +void QQmlJavaScriptExpression::GuardCapture::captureProperty(QObject *o, int c, int n) +{ + if (expression) { + if (n == -1) { + if (!errorString) { + errorString = new QStringList; + QString preamble = QLatin1String("QQmlExpression: Expression ") + + expression->m_vtable->expressionIdentifier(expression) + + QLatin1String(" depends on non-NOTIFYable properties:"); + errorString->append(preamble); + } + + const QMetaObject *metaObj = o->metaObject(); + QMetaProperty metaProp = metaObj->property(c); + + QString error = QLatin1String(" ") + + QString::fromUtf8(metaObj->className()) + + QLatin1String("::") + + QString::fromUtf8(metaProp.name()); + errorString->append(error); + } else { + + // Try and find a matching guard + while (!guards.isEmpty() && !guards.first()->isConnected(o, n)) + guards.takeFirst()->Delete(); + + Guard *g = 0; + if (!guards.isEmpty()) { + g = guards.takeFirst(); + g->cancelNotify(); + Q_ASSERT(g->isConnected(o, n)); + } else { + g = Guard::New(expression, engine); + g->connect(o, n); + } + + expression->activeGuards.prepend(g); + } + } +} + +void QQmlJavaScriptExpression::clearError() +{ + if (m_vtable.hasValue()) { + m_vtable.value().error = QQmlError(); + m_vtable.value().removeError(); + } +} + +QQmlError QQmlJavaScriptExpression::error() const +{ + if (m_vtable.hasValue()) return m_vtable.constValue()->error; + else return QQmlError(); +} + +QQmlDelayedError *QQmlJavaScriptExpression::delayedError() +{ + return &m_vtable.value(); +} + +void QQmlJavaScriptExpression::clearGuards() +{ + while (Guard *g = activeGuards.takeFirst()) + g->Delete(); +} + +// Must be called with a valid handle scope +v8::Local QQmlExpressionPrivate::v8value(QObject *secondaryScope, bool *isUndefined) +{ + if (!expressionFunctionValid) { + bool ok = true; + + QQmlRewrite::RewriteBinding rewriteBinding; + rewriteBinding.setName(name); + QString code; + if (expressionFunctionRewritten) + code = expression; + else + code = rewriteBinding(expression, &ok); + + if (ok) v8function = evalFunction(context(), scopeObject(), code, url, line, &v8qmlscope); + setUseSharedContext(false); + expressionFunctionValid = true; + } + + + if (secondaryScope) { + v8::Local result; + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine); + QObject *restoreSecondaryScope = 0; + restoreSecondaryScope = ep->v8engine()->contextWrapper()->setSecondaryScope(v8qmlscope, secondaryScope); + result = evaluate(context(), v8function, isUndefined); + ep->v8engine()->contextWrapper()->setSecondaryScope(v8qmlscope, restoreSecondaryScope); + return result; + } else { + return evaluate(context(), v8function, isUndefined); + } +} + +QVariant QQmlExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined) +{ + Q_Q(QQmlExpression); + + if (!context() || !context()->isValid()) { + qWarning("QQmlExpression: Attempted to evaluate an expression in an invalid context"); + return QVariant(); + } + + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(q->engine()); + QVariant rv; + + ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation. + + { + v8::HandleScope handle_scope; + v8::Context::Scope context_scope(ep->v8engine()->context()); + v8::Local result = v8value(secondaryScope, isUndefined); + rv = ep->v8engine()->toVariant(result, qMetaTypeId >()); + } + + ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete. + + return rv; +} + +/*! + Evaulates the expression, returning the result of the evaluation, + or an invalid QVariant if the expression is invalid or has an error. + + \a valueIsUndefined is set to true if the expression resulted in an + undefined value. + + \sa hasError(), error() +*/ +QVariant QQmlExpression::evaluate(bool *valueIsUndefined) +{ + Q_D(QQmlExpression); + return d->value(0, valueIsUndefined); +} + +/*! +Returns true if the valueChanged() signal is emitted when the expression's evaluated +value changes. +*/ +bool QQmlExpression::notifyOnValueChanged() const +{ + Q_D(const QQmlExpression); + return d->notifyOnValueChanged(); +} + +/*! + Sets whether the valueChanged() signal is emitted when the + expression's evaluated value changes. + + If \a notifyOnChange is true, the QQmlExpression will + monitor properties involved in the expression's evaluation, and emit + QQmlExpression::valueChanged() if they have changed. This + allows an application to ensure that any value associated with the + result of the expression remains up to date. + + If \a notifyOnChange is false (default), the QQmlExpression + will not montitor properties involved in the expression's + evaluation, and QQmlExpression::valueChanged() will never be + emitted. This is more efficient if an application wants a "one off" + evaluation of the expression. +*/ +void QQmlExpression::setNotifyOnValueChanged(bool notifyOnChange) +{ + Q_D(QQmlExpression); + d->setNotifyOnValueChanged(notifyOnChange); +} + +/*! + Returns the source file URL for this expression. The source location must + have been previously set by calling setSourceLocation(). +*/ +QString QQmlExpression::sourceFile() const +{ + Q_D(const QQmlExpression); + return d->url; +} + +/*! + Returns the source file line number for this expression. The source location + must have been previously set by calling setSourceLocation(). +*/ +int QQmlExpression::lineNumber() const +{ + Q_D(const QQmlExpression); + return d->line; +} + +/*! + Returns the source file column number for this expression. The source location + must have been previously set by calling setSourceLocation(). +*/ +int QQmlExpression::columnNumber() const +{ + Q_D(const QQmlExpression); + return d->column; +} + +/*! + Set the location of this expression to \a line of \a url. This information + is used by the script engine. +*/ +void QQmlExpression::setSourceLocation(const QString &url, int line, int column) +{ + Q_D(QQmlExpression); + d->url = url; + d->line = line; + d->column = column; +} + +/*! + Returns the expression's scope object, if provided, otherwise 0. + + In addition to data provided by the expression's QQmlContext, the scope + object's properties are also in scope during the expression's evaluation. +*/ +QObject *QQmlExpression::scopeObject() const +{ + Q_D(const QQmlExpression); + return d->scopeObject(); +} + +/*! + Returns true if the last call to evaluate() resulted in an error, + otherwise false. + + \sa error(), clearError() +*/ +bool QQmlExpression::hasError() const +{ + Q_D(const QQmlExpression); + return d->hasError(); +} + +/*! + Clear any expression errors. Calls to hasError() following this will + return false. + + \sa hasError(), error() +*/ +void QQmlExpression::clearError() +{ + Q_D(QQmlExpression); + d->clearError(); +} + +/*! + Return any error from the last call to evaluate(). If there was no error, + this returns an invalid QQmlError instance. + + \sa hasError(), clearError() +*/ + +QQmlError QQmlExpression::error() const +{ + Q_D(const QQmlExpression); + return d->error(); +} + +/*! + \fn void QQmlExpression::valueChanged() + + Emitted each time the expression value changes from the last time it was + evaluated. The expression must have been evaluated at least once (by + calling QQmlExpression::evaluate()) before this signal will be emitted. +*/ + +void QQmlExpressionPrivate::expressionChanged(QQmlJavaScriptExpression *e) +{ + QQmlExpressionPrivate *This = static_cast(e); + This->expressionChanged(); +} + +void QQmlExpressionPrivate::expressionChanged() +{ + Q_Q(QQmlExpression); + emit q->valueChanged(); +} + +QString QQmlExpressionPrivate::expressionIdentifier(QQmlJavaScriptExpression *e) +{ + QQmlExpressionPrivate *This = static_cast(e); + return QLatin1String("\"") + This->expression + QLatin1String("\""); +} + +QQmlAbstractExpression::QQmlAbstractExpression() +: m_prevExpression(0), m_nextExpression(0) +{ +} + +QQmlAbstractExpression::~QQmlAbstractExpression() +{ + if (m_prevExpression) { + *m_prevExpression = m_nextExpression; + if (m_nextExpression) + m_nextExpression->m_prevExpression = m_prevExpression; + } + + if (m_context.isT2()) + m_context.asT2()->_s = 0; +} + +QQmlContextData *QQmlAbstractExpression::context() const +{ + if (m_context.isT1()) return m_context.asT1(); + else return m_context.asT2()->_c; +} + +void QQmlAbstractExpression::setContext(QQmlContextData *context) +{ + if (m_prevExpression) { + *m_prevExpression = m_nextExpression; + if (m_nextExpression) + m_nextExpression->m_prevExpression = m_prevExpression; + m_prevExpression = 0; + m_nextExpression = 0; + } + + if (m_context.isT1()) m_context = context; + else m_context.asT2()->_c = context; + + if (context) { + m_nextExpression = context->expressions; + if (m_nextExpression) + m_nextExpression->m_prevExpression = &m_nextExpression; + m_prevExpression = &context->expressions; + context->expressions = this; + } +} + +void QQmlAbstractExpression::refresh() +{ +} + +bool QQmlAbstractExpression::isValid() const +{ + return context() != 0; +} + +QT_END_NAMESPACE + +#include diff --cc src/qml/qml/qqmlextensioninterface.h index 63ef1ad,0000000..1943194 mode 100644,000000..100644 --- a/src/qml/qml/qqmlextensioninterface.h +++ b/src/qml/qml/qqmlextensioninterface.h @@@ -1,76 -1,0 +1,81 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLEXTENSIONINTERFACE_H +#define QQMLEXTENSIONINTERFACE_H + +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + + +class QQmlEngine; + +class Q_QML_EXPORT QQmlTypesExtensionInterface +{ +public: + virtual ~QQmlTypesExtensionInterface() {} + virtual void registerTypes(const char *uri) = 0; +}; + +class Q_QML_EXPORT QQmlExtensionInterface : public QQmlTypesExtensionInterface +{ +public: + virtual ~QQmlExtensionInterface() {} + virtual void initializeEngine(QQmlEngine *engine, const char *uri) = 0; +}; + ++#define QQmlTypesExtensionInterface_iid "org.qt-project.Qt.QQmlTypesExtensionInterface" ++ +Q_DECLARE_INTERFACE(QQmlTypesExtensionInterface, "org.qt-project.Qt.QQmlTypesExtensionInterface/1.0") - Q_DECLARE_INTERFACE(QQmlExtensionInterface, "org.qt-project.Qt.QQmlExtensionInterface/1.0") ++ ++#define QQmlExtensionInterface_iid "org.qt-project.Qt.QQmlExtensionInterface" ++ ++Q_DECLARE_INTERFACE(QQmlExtensionInterface, QQmlExtensionInterface_iid) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QQMLEXTENSIONINTERFACE_H diff --cc src/qml/qml/qqmlimageprovider.h index d59cfc4,0000000..fe06925 mode 100644,000000..100644 --- a/src/qml/qml/qqmlimageprovider.h +++ b/src/qml/qml/qqmlimageprovider.h @@@ -1,96 -1,0 +1,96 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLIMAGEPROVIDER_H +#define QQMLIMAGEPROVIDER_H + +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + + +class QQmlImageProviderPrivate; +class QSGTexture; +class QQuickCanvas; + +class Q_QML_EXPORT QQuickTextureFactory : public QObject +{ +public: + QQuickTextureFactory(); - ~QQuickTextureFactory(); ++ virtual ~QQuickTextureFactory(); + + virtual QSGTexture *createTexture(QQuickCanvas *canvas) const = 0; + virtual QSize textureSize() const = 0; + virtual int textureByteCount() const = 0; +}; + +class Q_QML_EXPORT QQmlImageProvider +{ +public: + enum ImageType { + Image, + Pixmap, + Texture, + Invalid + }; + + QQmlImageProvider(ImageType type); + virtual ~QQmlImageProvider(); + + ImageType imageType() const; + + virtual QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize); + virtual QPixmap requestPixmap(const QString &id, QSize *size, const QSize& requestedSize); + virtual QQuickTextureFactory *requestTexture(const QString &id, QSize *size, const QSize &requestedSize); + +private: + QQmlImageProviderPrivate *d; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QQMLIMAGEPROVIDER diff --cc src/qml/qml/qqmlincubator.cpp index ee622ba,0000000..834d4bb mode 100644,000000..100644 --- a/src/qml/qml/qqmlincubator.cpp +++ b/src/qml/qml/qqmlincubator.cpp @@@ -1,696 -1,0 +1,697 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmlincubator.h" +#include "qqmlcomponent.h" +#include "qqmlincubator_p.h" + +#include "qqmlcompiler_p.h" +#include "qqmlexpression_p.h" + +// XXX TODO +// - check that the Component.onCompleted behavior is the same as 4.8 in the synchronous and +// async if nested cases +void QQmlEnginePrivate::incubate(QQmlIncubator &i, QQmlContextData *forContext) +{ + QQmlIncubatorPrivate *p = i.d; + + QQmlIncubator::IncubationMode mode = i.incubationMode(); + + if (!incubationController) + mode = QQmlIncubator::Synchronous; + + if (mode == QQmlIncubator::AsynchronousIfNested) { + mode = QQmlIncubator::Synchronous; + + // Need to find the first constructing context and see if it is asynchronous + QQmlIncubatorPrivate *parentIncubator = 0; + QQmlContextData *cctxt = forContext; + while (cctxt) { + if (cctxt->activeVMEData) { + parentIncubator = (QQmlIncubatorPrivate *)cctxt->activeVMEData; + break; + } + cctxt = cctxt->parent; + } + + if (parentIncubator && parentIncubator->isAsynchronous) { + mode = QQmlIncubator::Asynchronous; + p->waitingOnMe = parentIncubator; + parentIncubator->waitingFor.insert(p); + } + } + + p->isAsynchronous = (mode != QQmlIncubator::Synchronous); + + inProgressCreations++; + + if (mode == QQmlIncubator::Synchronous) { + typedef QQmlIncubatorPrivate IP; + QRecursionWatcher watcher(p); + + p->changeStatus(QQmlIncubator::Loading); + + if (!watcher.hasRecursed()) { + QQmlVME::Interrupt i; + p->incubate(i); + } + } else { + incubatorList.insert(p); + incubatorCount++; + + p->vmeGuard.guard(&p->vme); + p->changeStatus(QQmlIncubator::Loading); + + if (incubationController) + incubationController->incubatingObjectCountChanged(incubatorCount); + } +} + +/*! +Sets the engine's incubation \a controller. The engine can only have one active controller +and it does not take ownership of it. + +\sa incubationController() +*/ +void QQmlEngine::setIncubationController(QQmlIncubationController *controller) +{ + Q_D(QQmlEngine); + if (d->incubationController) + d->incubationController->d = 0; + d->incubationController = controller; + if (controller) controller->d = d; +} + +/*! +Returns the currently set incubation controller, or 0 if no controller has been set. + +\sa setIncubationController() +*/ +QQmlIncubationController *QQmlEngine::incubationController() const +{ + Q_D(const QQmlEngine); + return d->incubationController; +} + +QQmlIncubatorPrivate::QQmlIncubatorPrivate(QQmlIncubator *q, + QQmlIncubator::IncubationMode m) +: q(q), status(QQmlIncubator::Null), mode(m), isAsynchronous(false), progress(Execute), + result(0), component(0), vme(this), waitingOnMe(0) +{ +} + +QQmlIncubatorPrivate::~QQmlIncubatorPrivate() +{ +} + +void QQmlIncubatorPrivate::clear() +{ + if (next.isInList()) { + next.remove(); + Q_ASSERT(component); + QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(component->engine); + component->release(); + component = 0; + enginePriv->incubatorCount--; + QQmlIncubationController *controller = enginePriv->incubationController; + if (controller) + controller->incubatingObjectCountChanged(enginePriv->incubatorCount); + } else if (component) { + component->release(); + component = 0; + } + if (!rootContext.isNull()) { + rootContext->activeVMEData = 0; + rootContext = 0; + } + + if (nextWaitingFor.isInList()) { + Q_ASSERT(waitingOnMe); + nextWaitingFor.remove(); + waitingOnMe = 0; + } +} + +/*! +\class QQmlIncubationController +\brief QQmlIncubationController instances drive the progress of QQmlIncubators + +In order to behave asynchronously and not introduce stutters or freezes in an application, +the process of creating objects a QQmlIncubators must be driven only during the +application's idle time. QQmlIncubationController allows the application to control +exactly when, how often and for how long this processing occurs. + +A QQmlIncubationController derived instance should be created and set on a +QQmlEngine by calling the QQmlEngine::setIncubationController() method. +Processing is then controlled by calling the QQmlIncubationController::incubateFor() +or QQmlIncubationController::incubateWhile() methods as dictated by the application's +requirements. + +For example, this is an example of a incubation controller that will incubate for a maximum +of 5 milliseconds out of every 16 milliseconds. + +\code +class PeriodicIncubationController : public QObject, + public QQmlIncubationController +{ +public: + PeriodicIncubationController() { + startTimer(16); + } + +protected: + virtual void timerEvent(QTimerEvent *) { + incubateFor(5); + } +}; +\endcode + +Although the previous example would work, it is not optimal. Real world incubation +controllers should try and maximize the amount of idle time they consume - rather +than a static amount like 5 milliseconds - while not disturbing the application. +*/ + +/*! +Create a new incubation controller. +*/ +QQmlIncubationController::QQmlIncubationController() +: d(0) +{ +} + +/*! \internal */ +QQmlIncubationController::~QQmlIncubationController() +{ + if (d) QQmlEnginePrivate::get(d)->setIncubationController(0); + d = 0; +} + +/*! +Return the QQmlEngine this incubation controller is set on, or 0 if it +has not been set on any engine. +*/ +QQmlEngine *QQmlIncubationController::engine() const +{ + return QQmlEnginePrivate::get(d); +} + +/*! +Return the number of objects currently incubating. +*/ +int QQmlIncubationController::incubatingObjectCount() const +{ + if (d) + return d->incubatorCount; + else + return 0; +} + +/*! +Called when the number of incubating objects changes. \a incubatingObjectCount is the +new number of incubating objects. + +The default implementation does nothing. +*/ +void QQmlIncubationController::incubatingObjectCountChanged(int incubatingObjectCount) +{ + Q_UNUSED(incubatingObjectCount); +} + +void QQmlIncubatorPrivate::incubate(QQmlVME::Interrupt &i) +{ + if (!component) + return; + typedef QQmlIncubatorPrivate IP; + QRecursionWatcher watcher(this); + + QQmlEngine *engine = component->engine; + QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(engine); + + bool guardOk = vmeGuard.isOK(); + vmeGuard.clear(); + + if (!guardOk) { + QQmlError error; + error.setUrl(component->url); + error.setDescription(QQmlComponent::tr("Object destroyed during incubation")); + errors << error; + progress = QQmlIncubatorPrivate::Completed; + + goto finishIncubate; + } + + if (progress == QQmlIncubatorPrivate::Execute) { + enginePriv->referenceScarceResources(); + QObject *tresult = vme.execute(&errors, i); + enginePriv->dereferenceScarceResources(); + + if (watcher.hasRecursed()) + return; + + result = tresult; + if (errors.isEmpty() && result == 0) + goto finishIncubate; + + if (result) { + QQmlData *ddata = QQmlData::get(result); + Q_ASSERT(ddata); + ddata->indestructible = true; + + q->setInitialState(result); + } + + if (watcher.hasRecursed()) + return; + + if (errors.isEmpty()) + progress = QQmlIncubatorPrivate::Completing; + else + progress = QQmlIncubatorPrivate::Completed; + + changeStatus(calculateStatus()); + + if (watcher.hasRecursed()) + return; + + if (i.shouldInterrupt()) + goto finishIncubate; + } + + if (progress == QQmlIncubatorPrivate::Completing) { + do { + if (watcher.hasRecursed()) + return; + + QQmlContextData *ctxt = vme.complete(i); + if (ctxt) { + rootContext = ctxt; + progress = QQmlIncubatorPrivate::Completed; + goto finishIncubate; + } + } while (!i.shouldInterrupt()); + } + +finishIncubate: + if (progress == QQmlIncubatorPrivate::Completed && waitingFor.isEmpty()) { + typedef QQmlIncubatorPrivate IP; + + QQmlIncubatorPrivate *isWaiting = waitingOnMe; + clear(); + + if (isWaiting) { + QRecursionWatcher watcher(isWaiting); + changeStatus(calculateStatus()); + if (!watcher.hasRecursed()) + isWaiting->incubate(i); + } else { + changeStatus(calculateStatus()); + } + + enginePriv->inProgressCreations--; + + if (0 == enginePriv->inProgressCreations) { + while (enginePriv->erroredBindings) { + enginePriv->warning(enginePriv->erroredBindings->error); + enginePriv->erroredBindings->removeError(); + } + } + } else { + vmeGuard.guard(&vme); + } +} + +/*! +Incubate objects for \a msecs, or until there are no more objects to incubate. +*/ +void QQmlIncubationController::incubateFor(int msecs) +{ + if (!d || d->incubatorCount == 0) + return; + + QQmlVME::Interrupt i(msecs * 1000000); + i.reset(); + do { + QQmlIncubatorPrivate *p = (QQmlIncubatorPrivate*)d->incubatorList.first(); + p->incubate(i); + } while (d && d->incubatorCount != 0 && !i.shouldInterrupt()); +} + +/*! +Incubate objects while the bool pointed to by \a flag is true, or until there are no - more objects to incubate. ++more objects to incubate, or up to msecs if msecs is not zero. + +Generally this method is used in conjunction with a thread or a UNIX signal that sets +the bool pointed to by \a flag to false when it wants incubation to be interrupted. +*/ - void QQmlIncubationController::incubateWhile(bool *flag) ++void QQmlIncubationController::incubateWhile(volatile bool *flag, int msecs) +{ + if (!d || d->incubatorCount == 0) + return; + - QQmlVME::Interrupt i(flag); ++ QQmlVME::Interrupt i(flag, msecs * 1000000); ++ i.reset(); + do { + QQmlIncubatorPrivate *p = (QQmlIncubatorPrivate*)d->incubatorList.first(); + p->incubate(i); + } while (d && d->incubatorCount != 0 && !i.shouldInterrupt()); +} + +/*! +\class QQmlIncubator +\brief The QQmlIncubator class allows QML objects to be created asynchronously. + +Creating QML objects - like delegates in a view, or a new page in an application - can take +a noticable amount of time, especially on resource constrained mobile devices. When an +application uses QQmlComponent::create() directly, the QML object instance is created +synchronously which, depending on the complexity of the object, can cause noticable pauses or +stutters in the application. + +The use of QQmlIncubator gives more control over the creation of a QML object, +including allowing it to be created asynchronously using application idle time. The following +example shows a simple use of QQmlIncubator. + +\code +QQmlIncubator incubator; +component->create(incubator); + +while (incubator.isReady()) { + QCoreApplication::processEvents(QEventLoop::AllEvents, 50); +} + +QObject *object = incubator.object(); +\endcode + +Asynchronous incubators are controlled by a QQmlIncubationController that is +set on the QQmlEngine, which lets the engine know when the application is idle and +incubating objects should be processed. If an incubation controller is not set on the +QQmlEngine, QQmlIncubator creates objects synchronously regardless of the +specified IncubationMode. + +QQmlIncubator supports three incubation modes: +\list +\i Synchronous The creation occurs synchronously. That is, once the +QQmlComponent::create() call returns, the incubator will already be in either the +Error or Ready state. A synchronous incubator has no real advantage compared to using +the synchronous creation methods on QQmlComponent directly, but it may simplify an +application's implementation to use the same API for both synchronous and asynchronous +creations. + +\i Asynchronous (default) The creation occurs asynchronously, assuming a +QQmlIncubatorController is set on the QQmlEngine. + +The incubator will remain in the Loading state until either the creation is complete or an error +occurs. The statusChanged() callback can be used to be notified of status changes. + +Applications should use the Asynchronous incubation mode to create objects that are not needed +immediately. For example, the ListView element uses Asynchronous incubation to create objects +that are slightly off screen while the list is being scrolled. If, during asynchronous creation, +the object is needed immediately the QQmlIncubator::forceCompletion() method can be called +to complete the creation process synchronously. + +\i AsynchronousIfNested The creation will occur asynchronously if part of a nested asynchronous +creation, or synchronously if not. + +In most scenarios where a QML element or component wants the appearance of a synchronous +instantiation, it should use this mode. + +This mode is best explained with an example. When the ListView element is first created, it needs +to populate itself with an initial set of delegates to show. If the ListView was 400 pixels high, +and each delegate was 100 pixels high, it would need to create four initial delegate instances. If +the ListView used the Asynchronous incubation mode, the ListView would always be created empty and +then, sometime later, the four initial elements would appear. + +Conversely, if the ListView was to use the Synchronous incubation mode it would behave correctly +but it may introduce stutters into the application. As QML would have to stop and instantiate the +ListView's delegates synchronously, if the ListView was part of a QML component that was being +instantiated asynchronously this would undo much of the benefit of asynchronous instantiation. + +The AsynchronousIfNested mode reconciles this problem. By using AsynchronousIfNested, the ListView +delegates are instantiated asynchronously if the ListView itself is already part of an asynchronous +instantiation, and synchronously otherwise. In the case of a nested asynchronous instantiation, the +outer asynchronous instantiation will not complete until after all the nested instantiations have also +completed. This ensures that by the time the outer asynchronous instantitation completes, inner +elements like ListView have already completed loading their initial delegates. + +It is almost always incorrect to use the Synchronous incubation mode - elements or components that +want the appearance of synchronous instantiation, but without the downsides of introducing freezes +or stutters into the application, should use the AsynchronousIfNested incubation mode. +\endlist +*/ + +/*! +Create a new incubator with the specified \a mode +*/ +QQmlIncubator::QQmlIncubator(IncubationMode mode) +: d(new QQmlIncubatorPrivate(this, mode)) +{ +} + +/*! \internal */ +QQmlIncubator::~QQmlIncubator() +{ + clear(); + + delete d; d = 0; +} + +/*! +\enum QQmlIncubator::IncubationMode + +Specifies the mode the incubator operates in. Regardless of the incubation mode, a +QQmlIncubator will behave synchronously if the QQmlEngine does not have +a QQmlIncubationController set. + +\value Asynchronous The object will be created asynchronously. +\value AsynchronousIfNested If the object is being created in a context that is already part +of an asynchronous creation, this incubator will join that existing incubation and execute +asynchronously. The existing incubation will not become Ready until both it and this +incubation have completed. Otherwise, the incubation will execute synchronously. +\value Synchronous The object will be created synchronously. +*/ + +/*! +\enum QQmlIncubator::Status + +Specifies the status of the QQmlIncubator. + +\value Null Incubation is not in progress. Call QQmlComponent::create() to begin incubating. +\value Ready The object is fully created and can be accessed by calling object(). +\value Loading The object is in the process of being created. +\value Error An error occurred. The errors can be access by calling errors(). +*/ + +/*! +Clears the incubator. Any in-progress incubation is aborted. If the incubator is in the +Ready state, the created object is \b not deleted. +*/ +void QQmlIncubator::clear() +{ + typedef QQmlIncubatorPrivate IP; + QRecursionWatcher watcher(d); + + Status s = status(); + + if (s == Null) + return; + + QQmlEnginePrivate *enginePriv = 0; + if (s == Loading) { + Q_ASSERT(d->component); + enginePriv = QQmlEnginePrivate::get(d->component->engine); + if (d->result) d->result->deleteLater(); + d->result = 0; + } + + d->clear(); + + d->vme.reset(); + d->vmeGuard.clear(); + + Q_ASSERT(d->component == 0); + Q_ASSERT(d->waitingOnMe == 0); + Q_ASSERT(d->waitingFor.isEmpty()); + Q_ASSERT(!d->nextWaitingFor.isInList()); + + d->errors.clear(); + d->progress = QQmlIncubatorPrivate::Execute; + d->result = 0; + + if (s == Loading) { + Q_ASSERT(enginePriv); + + enginePriv->inProgressCreations--; + if (0 == enginePriv->inProgressCreations) { + while (enginePriv->erroredBindings) { + enginePriv->warning(enginePriv->erroredBindings->error); + enginePriv->erroredBindings->removeError(); + } + } + } + + d->changeStatus(Null); +} + +/*! +Force any in-progress incubation to finish synchronously. Once this call +returns, the incubator will not be in the Loading state. +*/ +void QQmlIncubator::forceCompletion() +{ + QQmlVME::Interrupt i; + while (Loading == status()) { + while (Loading == status() && !d->waitingFor.isEmpty()) + static_cast(d->waitingFor.first())->incubate(i); + if (Loading == status()) + d->incubate(i); + } +} + +/*! +Returns true if the incubator's status() is Null. +*/ +bool QQmlIncubator::isNull() const +{ + return status() == Null; +} + +/*! +Returns true if the incubator's status() is Ready. +*/ +bool QQmlIncubator::isReady() const +{ + return status() == Ready; +} + +/*! +Returns true if the incubator's status() is Error. +*/ +bool QQmlIncubator::isError() const +{ + return status() == Error; +} + +/*! +Returns true if the incubator's status() is Loading. +*/ +bool QQmlIncubator::isLoading() const +{ + return status() == Loading; +} + +/*! +Return the list of errors encountered while incubating the object. +*/ +QList QQmlIncubator::errors() const +{ + return d->errors; +} + +/*! +Return the incubation mode passed to the QQmlIncubator constructor. +*/ +QQmlIncubator::IncubationMode QQmlIncubator::incubationMode() const +{ + return d->mode; +} + +/*! +Return the current status of the incubator. +*/ +QQmlIncubator::Status QQmlIncubator::status() const +{ + return d->status; +} + +/*! +Return the incubated object if the status is Ready, otherwise 0. +*/ +QObject *QQmlIncubator::object() const +{ + if (status() != Ready) return 0; + else return d->result; +} + +/*! +Called when the status of the incubator changes. \a status is the new status. + +The default implementation does nothing. +*/ +void QQmlIncubator::statusChanged(Status status) +{ + Q_UNUSED(status); +} + +/*! +Called after the object is first created, but before property bindings are +evaluated and, if applicable, QQmlParserStatus::componentComplete() is +called. This is equivalent to the point between QQmlComponent::beginCreate() +and QQmlComponent::endCreate(), and can be used to assign initial values +to the object's properties. + +The default implementation does nothing. +*/ +void QQmlIncubator::setInitialState(QObject *object) +{ + Q_UNUSED(object); +} + +void QQmlIncubatorPrivate::changeStatus(QQmlIncubator::Status s) +{ + if (s == status) + return; + + status = s; + q->statusChanged(status); +} + +QQmlIncubator::Status QQmlIncubatorPrivate::calculateStatus() const +{ + if (!errors.isEmpty()) + return QQmlIncubator::Error; + else if (result && progress == QQmlIncubatorPrivate::Completed && + waitingFor.isEmpty()) + return QQmlIncubator::Ready; + else if (component) + return QQmlIncubator::Loading; + else + return QQmlIncubator::Null; +} + diff --cc src/qml/qml/qqmlincubator.h index 5d8ae7d,0000000..2fb2aaf mode 100644,000000..100644 --- a/src/qml/qml/qqmlincubator.h +++ b/src/qml/qml/qqmlincubator.h @@@ -1,129 -1,0 +1,130 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLINCUBATOR_H +#define QQMLINCUBATOR_H + ++#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + + +class QQmlEngine; + +class QQmlIncubatorPrivate; +class Q_QML_EXPORT QQmlIncubator +{ + Q_DISABLE_COPY(QQmlIncubator) +public: + enum IncubationMode { + Asynchronous, + AsynchronousIfNested, + Synchronous + }; + enum Status { + Null, + Ready, + Loading, + Error + }; + + QQmlIncubator(IncubationMode = Asynchronous); + virtual ~QQmlIncubator(); + + void clear(); + void forceCompletion(); + + bool isNull() const; + bool isReady() const; + bool isError() const; + bool isLoading() const; + + QList errors() const; + + IncubationMode incubationMode() const; + + Status status() const; + + QObject *object() const; + +protected: + virtual void statusChanged(Status); + virtual void setInitialState(QObject *); + +private: + friend class QQmlComponent; + friend class QQmlEnginePrivate; + friend class QQmlIncubatorPrivate; + QQmlIncubatorPrivate *d; +}; + +class QQmlEnginePrivate; +class Q_QML_EXPORT QQmlIncubationController +{ + Q_DISABLE_COPY(QQmlIncubationController) +public: + QQmlIncubationController(); + virtual ~QQmlIncubationController(); + + QQmlEngine *engine() const; + int incubatingObjectCount() const; + + void incubateFor(int msecs); - void incubateWhile(bool *flag); ++ void incubateWhile(volatile bool *flag, int msecs=0); + +protected: + virtual void incubatingObjectCountChanged(int); + +private: + friend class QQmlEngine; + friend class QQmlEnginePrivate; + friend class QQmlIncubatorPrivate; + QQmlEnginePrivate *d; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QQMLINCUBATOR_H diff --cc src/qml/qml/qqmlinstruction.cpp index 72f04c9,0000000..b37117e mode 100644,000000..100644 --- a/src/qml/qml/qqmlinstruction.cpp +++ b/src/qml/qml/qqmlinstruction.cpp @@@ -1,278 -1,0 +1,278 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmlinstruction_p.h" + +#include "qqmlcompiler_p.h" + +#include + +QT_BEGIN_NAMESPACE + +void QQmlCompiledData::dump(QQmlInstruction *instr, int idx) +{ +#ifdef QT_NO_DEBUG_STREAM + Q_UNUSED(instr) + Q_UNUSED(idx) +#else + switch (instructionType(instr)) { + case QQmlInstruction::Init: + qWarning().nospace() << idx << "\t\t" << "INIT\t\t\t" << instr->init.bindingsSize << "\t" << instr->init.parserStatusSize << "\t" << instr->init.contextCache << "\t" << instr->init.compiledBinding; + break; + case QQmlInstruction::DeferInit: + qWarning().nospace() << idx << "\t\t" << "DEFER_INIT\t\t" << instr->deferInit.bindingsSize << "\t" << instr->deferInit.parserStatusSize; + break; + case QQmlInstruction::Done: + qWarning().nospace() << idx << "\t\t" << "DONE"; + break; + case QQmlInstruction::CreateCppObject: + qWarning().nospace() << idx << "\t\t" << "CREATECPP\t\t\t" << instr->create.type << "\t\t\t" << types.at(instr->create.type).className; + break; + case QQmlInstruction::CreateQMLObject: + qWarning().nospace() << idx << "\t\t" << "CREATEQML\t\t\t" << instr->createQml.type << "\t" << instr->createQml.bindingBits << "\t\t" << types.at(instr->createQml.type).className; + break; + case QQmlInstruction::CompleteQMLObject: + qWarning().nospace() << idx << "\t\t" << "COMPLETEQML"; + break; + case QQmlInstruction::CreateSimpleObject: + qWarning().nospace() << idx << "\t\t" << "CREATE_SIMPLE\t\t" << instr->createSimple.typeSize; + break; + case QQmlInstruction::SetId: + qWarning().nospace() << idx << "\t\t" << "SETID\t\t\t" << instr->setId.value << "\t\t\t" << primitives.at(instr->setId.value); + break; + case QQmlInstruction::SetDefault: + qWarning().nospace() << idx << "\t\t" << "SET_DEFAULT"; + break; + case QQmlInstruction::CreateComponent: + qWarning().nospace() << idx << "\t\t" << "CREATE_COMPONENT\t" << instr->createComponent.count; + break; + case QQmlInstruction::StoreMetaObject: + qWarning().nospace() << idx << "\t\t" << "STORE_META\t\t" << instr->storeMeta.data; + break; + case QQmlInstruction::StoreFloat: + qWarning().nospace() << idx << "\t\t" << "STORE_FLOAT\t\t" << instr->storeFloat.propertyIndex << "\t" << instr->storeFloat.value; + break; + case QQmlInstruction::StoreDouble: + qWarning().nospace() << idx << "\t\t" << "STORE_DOUBLE\t\t" << instr->storeDouble.propertyIndex << "\t" << instr->storeDouble.value; + break; + case QQmlInstruction::StoreDoubleQList: + qWarning().nospace() << idx << "\t\t" << "STORE_DOUBLE_QLIST\t\t" << instr->storeDouble.propertyIndex << "\t" << instr->storeDouble.value; + break; + case QQmlInstruction::StoreInteger: + qWarning().nospace() << idx << "\t\t" << "STORE_INTEGER\t\t" << instr->storeInteger.propertyIndex << "\t" << instr->storeInteger.value; + break; + case QQmlInstruction::StoreIntegerQList: + qWarning().nospace() << idx << "\t\t" << "STORE_INTEGER_QLIST\t\t" << instr->storeInteger.propertyIndex << "\t" << instr->storeInteger.value; + break; + case QQmlInstruction::StoreBool: + qWarning().nospace() << idx << "\t\t" << "STORE_BOOL\t\t" << instr->storeBool.propertyIndex << "\t" << instr->storeBool.value; + break; + case QQmlInstruction::StoreBoolQList: + qWarning().nospace() << idx << "\t\t" << "STORE_BOOL_QLIST\t\t" << instr->storeBool.propertyIndex << "\t" << instr->storeBool.value; + break; + case QQmlInstruction::StoreString: + qWarning().nospace() << idx << "\t\t" << "STORE_STRING\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value); + break; + case QQmlInstruction::StoreStringList: + qWarning().nospace() << idx << "\t\t" << "STORE_STRINGLIST\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value); + break; + case QQmlInstruction::StoreStringQList: + qWarning().nospace() << idx << "\t\t" << "STORE_STRING_QLIST\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value); + break; + case QQmlInstruction::StoreTrString: + qWarning().nospace() << idx << "\t\t" << "STORE_TR_STRING\t" << instr->storeTrString.propertyIndex << "\t" << instr->storeTrString.context << "\t" << instr->storeTrString.text << "\t" << instr->storeTrString.comment << "\t" << instr->storeTrString.n; + break; + case QQmlInstruction::StoreTrIdString: + qWarning().nospace() << idx << "\t\t" << "STORE_TRID_STRING\t" << instr->storeTrIdString.propertyIndex << "\t" << instr->storeTrIdString.text << "\t" << instr->storeTrIdString.n; + break; + case QQmlInstruction::StoreByteArray: + qWarning().nospace() << idx << "\t\t" << "STORE_BYTEARRAY" << instr->storeByteArray.propertyIndex << "\t" << instr->storeByteArray.value << "\t\t" << datas.at(instr->storeByteArray.value); + break; + case QQmlInstruction::StoreUrl: + qWarning().nospace() << idx << "\t\t" << "STORE_URL\t\t" << instr->storeUrl.propertyIndex << "\t" << instr->storeUrl.value << "\t\t" << urls.at(instr->storeUrl.value); + break; + case QQmlInstruction::StoreUrlQList: + qWarning().nospace() << idx << "\t\t" << "STORE_URL_QLIST\t\t" << instr->storeUrl.propertyIndex << "\t" << instr->storeUrl.value << "\t\t" << urls.at(instr->storeUrl.value); + break; + case QQmlInstruction::StoreColor: + qWarning().nospace() << idx << "\t\t" << "STORE_COLOR\t\t" << instr->storeColor.propertyIndex << "\t\t\t" << QString::number(instr->storeColor.value, 16); + break; + case QQmlInstruction::StoreDate: + qWarning().nospace() << idx << "\t\t" << "STORE_DATE\t\t" << instr->storeDate.propertyIndex << "\t" << instr->storeDate.value; + break; + case QQmlInstruction::StoreTime: + qWarning().nospace() << idx << "\t\t" << "STORE_TIME\t\t" << instr->storeTime.propertyIndex; + break; + case QQmlInstruction::StoreDateTime: + qWarning().nospace() << idx << "\t\t" << "STORE_DATETIME\t\t" << instr->storeDateTime.propertyIndex; + break; + case QQmlInstruction::StorePoint: + qWarning().nospace() << idx << "\t\t" << "STORE_POINT\t\t" << instr->storePoint.propertyIndex << "\t" << instr->storePoint.point.xp << "\t" << instr->storePoint.point.yp; + break; + case QQmlInstruction::StorePointF: + qWarning().nospace() << idx << "\t\t" << "STORE_POINTF\t\t" << instr->storePointF.propertyIndex << "\t" << instr->storePointF.point.xp << "\t" << instr->storePointF.point.yp; + break; + case QQmlInstruction::StoreSize: + qWarning().nospace() << idx << "\t\t" << "STORE_SIZE\t\t" << instr->storeSize.propertyIndex << "\t" << instr->storeSize.size.wd << "\t" << instr->storeSize.size.ht; + break; + case QQmlInstruction::StoreSizeF: + qWarning().nospace() << idx << "\t\t" << "STORE_SIZEF\t\t" << instr->storeSizeF.propertyIndex << "\t" << instr->storeSizeF.size.wd << "\t" << instr->storeSizeF.size.ht; + break; + case QQmlInstruction::StoreRect: + qWarning().nospace() << idx << "\t\t" << "STORE_RECT\t\t" << instr->storeRect.propertyIndex << "\t" << instr->storeRect.rect.x1 << "\t" << instr->storeRect.rect.y1 << "\t" << instr->storeRect.rect.x2 << "\t" << instr->storeRect.rect.y2; + break; + case QQmlInstruction::StoreRectF: + qWarning().nospace() << idx << "\t\t" << "STORE_RECTF\t\t" << instr->storeRectF.propertyIndex << "\t" << instr->storeRectF.rect.xp << "\t" << instr->storeRectF.rect.yp << "\t" << instr->storeRectF.rect.w << "\t" << instr->storeRectF.rect.h; + break; + case QQmlInstruction::StoreVector3D: + qWarning().nospace() << idx << "\t\t" << "STORE_VECTOR3D\t\t" << instr->storeVector3D.propertyIndex << "\t" << instr->storeVector3D.vector.xp << "\t" << instr->storeVector3D.vector.yp << "\t" << instr->storeVector3D.vector.zp; + break; + case QQmlInstruction::StoreVector4D: + qWarning().nospace() << idx << "\t\t" << "STORE_VECTOR4D\t\t" << instr->storeVector4D.propertyIndex << "\t" << instr->storeVector4D.vector.xp << "\t" << instr->storeVector4D.vector.yp << "\t" << instr->storeVector4D.vector.zp << "\t" << instr->storeVector4D.vector.wp; + break; + case QQmlInstruction::StoreVariant: + qWarning().nospace() << idx << "\t\t" << "STORE_VARIANT\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value); + break; + case QQmlInstruction::StoreVariantInteger: + qWarning().nospace() << idx << "\t\t" << "STORE_VARIANT_INTEGER\t\t" << instr->storeInteger.propertyIndex << "\t" << instr->storeInteger.value; + break; + case QQmlInstruction::StoreVariantDouble: + qWarning().nospace() << idx << "\t\t" << "STORE_VARIANT_DOUBLE\t\t" << instr->storeDouble.propertyIndex << "\t" << instr->storeDouble.value; + break; + case QQmlInstruction::StoreVariantBool: + qWarning().nospace() << idx << "\t\t" << "STORE_VARIANT_BOOL\t\t" << instr->storeBool.propertyIndex << "\t" << instr->storeBool.value; + break; + case QQmlInstruction::StoreObject: + qWarning().nospace() << idx << "\t\t" << "STORE_OBJECT\t\t" << instr->storeObject.propertyIndex; + break; + case QQmlInstruction::StoreVariantObject: + qWarning().nospace() << idx << "\t\t" << "STORE_VARIANT_OBJECT\t" << instr->storeObject.propertyIndex; + break; + case QQmlInstruction::StoreInterface: + qWarning().nospace() << idx << "\t\t" << "STORE_INTERFACE\t\t" << instr->storeObject.propertyIndex; + break; + case QQmlInstruction::StoreSignal: - qWarning().nospace() << idx << "\t\t" << "STORE_SIGNAL\t\t" << instr->storeSignal.signalIndex << "\t" << instr->storeSignal.value << "\t\t" << primitives.at(instr->storeSignal.value); ++ qWarning().nospace() << idx << "\t\t" << "STORE_SIGNAL\t\t" << instr->storeSignal.signalIndex << "\t" << instr->storeSignal.value; + break; + case QQmlInstruction::StoreImportedScript: + qWarning().nospace() << idx << "\t\t" << "STORE_IMPORTED_SCRIPT\t" << instr->storeScript.value; + break; + case QQmlInstruction::StoreScriptString: + qWarning().nospace() << idx << "\t\t" << "STORE_SCRIPT_STRING\t" << instr->storeScriptString.propertyIndex << "\t" << instr->storeScriptString.value << "\t" << instr->storeScriptString.scope << "\t" << instr->storeScriptString.bindingId; + break; + case QQmlInstruction::AssignSignalObject: - qWarning().nospace() << idx << "\t\t" << "ASSIGN_SIGNAL_OBJECT\t" << instr->assignSignalObject.signal << "\t\t\t" << primitives.at(instr->assignSignalObject.signal); ++ qWarning().nospace() << idx << "\t\t" << "ASSIGN_SIGNAL_OBJECT\t" << instr->assignSignalObject.signal; + break; + case QQmlInstruction::AssignCustomType: + qWarning().nospace() << idx << "\t\t" << "ASSIGN_CUSTOMTYPE\t" << instr->assignCustomType.propertyIndex << "\t" << instr->assignCustomType.primitive << "\t" << instr->assignCustomType.type; + break; + case QQmlInstruction::InitV8Bindings: + qWarning().nospace() << idx << "\t\t" << "INIT_V8_BINDING\t" << instr->initV8Bindings.programIndex << "\t" << instr->initV8Bindings.line; + break; + case QQmlInstruction::StoreBinding: + qWarning().nospace() << idx << "\t\t" << "STORE_BINDING\t" << instr->assignBinding.property.coreIndex << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context; + break; + case QQmlInstruction::StoreBindingOnAlias: + qWarning().nospace() << idx << "\t\t" << "STORE_BINDING_ALIAS\t" << instr->assignBinding.property.coreIndex << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context; + break; + case QQmlInstruction::StoreV4Binding: + qWarning().nospace() << idx << "\t\t" << "STORE_COMPILED_BINDING\t" << instr->assignV4Binding.property << "\t" << instr->assignV4Binding.value << "\t" << instr->assignV4Binding.context; + break; + case QQmlInstruction::StoreV8Binding: + qWarning().nospace() << idx << "\t\t" << "STORE_V8_BINDING\t" << instr->assignBinding.property.coreIndex << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context; + break; + case QQmlInstruction::StoreValueSource: + qWarning().nospace() << idx << "\t\t" << "STORE_VALUE_SOURCE\t" << instr->assignValueSource.property.coreIndex << "\t" << instr->assignValueSource.castValue; + break; + case QQmlInstruction::StoreValueInterceptor: + qWarning().nospace() << idx << "\t\t" << "STORE_VALUE_INTERCEPTOR\t" << instr->assignValueInterceptor.property.coreIndex << "\t" << instr->assignValueInterceptor.castValue; + break; + case QQmlInstruction::BeginObject: + qWarning().nospace() << idx << "\t\t" << "BEGIN\t\t\t" << instr->begin.castValue; + break; + case QQmlInstruction::StoreObjectQList: + qWarning().nospace() << idx << "\t\t" << "STORE_OBJECT_QLIST"; + break; + case QQmlInstruction::AssignObjectList: + qWarning().nospace() << idx << "\t\t" << "ASSIGN_OBJECT_LIST"; + break; + case QQmlInstruction::FetchAttached: + qWarning().nospace() << idx << "\t\t" << "FETCH_ATTACHED\t\t" << instr->fetchAttached.id; + break; + case QQmlInstruction::FetchQList: + qWarning().nospace() << idx << "\t\t" << "FETCH_QLIST\t\t" << instr->fetch.property; + break; + case QQmlInstruction::FetchObject: + qWarning().nospace() << idx << "\t\t" << "FETCH\t\t\t" << instr->fetch.property; + break; + case QQmlInstruction::FetchValueType: + qWarning().nospace() << idx << "\t\t" << "FETCH_VALUE\t\t" << instr->fetchValue.property << "\t" << instr->fetchValue.type << "\t" << instr->fetchValue.bindingSkipList; + break; + case QQmlInstruction::PopFetchedObject: + qWarning().nospace() << idx << "\t\t" << "POP"; + break; + case QQmlInstruction::PopQList: + qWarning().nospace() << idx << "\t\t" << "POP_QLIST"; + break; + case QQmlInstruction::PopValueType: + qWarning().nospace() << idx << "\t\t" << "POP_VALUE\t\t" << instr->fetchValue.property << "\t" << instr->fetchValue.type; + break; + case QQmlInstruction::Defer: + qWarning().nospace() << idx << "\t\t" << "DEFER" << "\t\t\t" << instr->defer.deferCount; + break; + default: + qWarning().nospace() << idx << "\t\t" << "XXX UNKNOWN INSTRUCTION" << "\t" << instructionType(instr); + break; + } +#endif // QT_NO_DEBUG_STREAM +} + +int QQmlInstruction::size(Type type) +{ +#define QML_RETURN_INSTR_SIZE(I, FMT) case I: return QQmlInstructionMeta<(int)I>::Size; + switch (type) { + FOR_EACH_QML_INSTR(QML_RETURN_INSTR_SIZE) + default: return 0; + } +#undef QML_RETURN_INSTR_SIZE +} + +QT_END_NAMESPACE diff --cc src/qml/qml/qqmllocale.cpp index 4dc30f2,0000000..d684378 mode 100644,000000..100644 --- a/src/qml/qml/qqmllocale.cpp +++ b/src/qml/qml/qqmllocale.cpp @@@ -1,1123 -1,0 +1,1126 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmllocale_p.h" +#include "qqmlengine_p.h" +#include +#include +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class QV8LocaleDataResource : public QV8ObjectResource +{ + V8_RESOURCE_TYPE(LocaleDataType) +public: + QV8LocaleDataResource(QV8Engine *e) : QV8ObjectResource(e) {} + QLocale locale; +}; + +#define GET_LOCALE_DATA_RESOURCE(OBJECT) \ +QV8LocaleDataResource *r = v8_resource_cast(OBJECT); \ +if (!r) \ + V8THROW_ERROR("Not a valid Locale object") + +static bool isLocaleObject(v8::Handle val) +{ + if (!val->IsObject()) + return false; + + v8::Handle localeObj = val->ToObject(); + return localeObj->Has(v8::String::New("nativeLanguageName")); //XXX detect locale object properly +} + +//-------------- +// Date extension + +static const char *dateToLocaleStringFunction = + "(function(toLocaleStringFunc) { " + " var orig_toLocaleString;" + " orig_toLocaleString = Date.prototype.toLocaleString;" + " Date.prototype.toLocaleString = (function() {" + " var val = toLocaleStringFunc.apply(this, arguments);" + " if (val == undefined) val = orig_toLocaleString.call(this);" + " return val;" + " })" + "})"; + +static const char *dateToLocaleTimeStringFunction = + "(function(toLocaleTimeStringFunc) { " + " var orig_toLocaleTimeString;" + " orig_toLocaleTimeString = Date.prototype.toLocaleTimeString;" + " Date.prototype.toLocaleTimeString = (function() {" + " var val = toLocaleTimeStringFunc.apply(this, arguments);" + " if (val == undefined) val = orig_toLocaleTimeString.call(this);" + " return val;" + " })" + "})"; + +static const char *dateToLocaleDateStringFunction = + "(function(toLocaleDateStringFunc) { " + " var orig_toLocaleDateString;" + " orig_toLocaleDateString = Date.prototype.toLocaleDateString;" + " Date.prototype.toLocaleDateString = (function() {" + " var val = toLocaleDateStringFunc.apply(this, arguments);" + " if (val == undefined) val = orig_toLocaleDateString.call(this);" + " return val;" + " })" + "})"; + + +static const char *dateFromLocaleStringFunction = + "(function(fromLocaleStringFunc) { " + " Date.fromLocaleString = (function() {" + " return fromLocaleStringFunc.apply(null, arguments);" + " })" + "})"; + +static const char *dateFromLocaleTimeStringFunction = + "(function(fromLocaleTimeStringFunc) { " + " Date.fromLocaleTimeString = (function() {" + " return fromLocaleTimeStringFunc.apply(null, arguments);" + " })" + "})"; + +static const char *dateFromLocaleDateStringFunction = + "(function(fromLocaleDateStringFunc) { " + " Date.fromLocaleDateString = (function() {" + " return fromLocaleDateStringFunc.apply(null, arguments);" + " })" + "})"; + + +static void registerFunction(QV8Engine *engine, const char *script, v8::InvocationCallback func) +{ + v8::Local registerScript = v8::Script::New(v8::String::New(script), 0, 0, v8::Handle(), v8::Script::NativeMode); + v8::Local result = registerScript->Run(); + Q_ASSERT(result->IsFunction()); + v8::Local registerFunc = v8::Local::Cast(result); + v8::Handle args = V8FUNCTION(func, engine); + registerFunc->Call(v8::Local::Cast(registerFunc), 1, &args); +} + +void QQmlDateExtension::registerExtension(QV8Engine *engine) +{ + registerFunction(engine, dateToLocaleStringFunction, toLocaleString); + registerFunction(engine, dateToLocaleTimeStringFunction, toLocaleTimeString); + registerFunction(engine, dateToLocaleDateStringFunction, toLocaleDateString); + registerFunction(engine, dateFromLocaleStringFunction, fromLocaleString); + registerFunction(engine, dateFromLocaleTimeStringFunction, fromLocaleTimeString); + registerFunction(engine, dateFromLocaleDateStringFunction, fromLocaleDateString); +} + +v8::Handle QQmlDateExtension::toLocaleString(const v8::Arguments& args) +{ + if (args.Length() > 2) + return v8::Undefined(); + + if (!args.This()->IsDate()) + return v8::Undefined(); + + QDateTime dt = QV8Engine::qtDateTimeFromJsDate(v8::Handle::Cast(args.This())->NumberValue()); + + if (args.Length() == 0) { + // Use QLocale for standard toLocaleString() function + QLocale locale; + return QJSConverter::toString(locale.toString(dt)); + } + + if (!isLocaleObject(args[0])) + return v8::Undefined(); // Use the default Date toLocaleString() + + GET_LOCALE_DATA_RESOURCE(args[0]->ToObject()); + + QLocale::FormatType enumFormat = QLocale::LongFormat; + QString formattedDt; + if (args.Length() == 2) { + if (args[1]->IsString()) { + QString format = r->engine->toVariant(args[1], -1).toString(); + formattedDt = r->locale.toString(dt, format); + } else if (args[1]->IsNumber()) { + quint32 intFormat = args[1]->ToNumber()->Value(); + QLocale::FormatType format = QLocale::FormatType(intFormat); + formattedDt = r->locale.toString(dt, format); + } else { + V8THROW_ERROR("Locale: Date.toLocaleString(): Invalid datetime format"); + } + } else { + formattedDt = r->locale.toString(dt, enumFormat); + } + + return r->engine->toString(formattedDt); +} + +v8::Handle QQmlDateExtension::toLocaleTimeString(const v8::Arguments& args) +{ + if (args.Length() > 2) + return v8::Undefined(); + + if (!args.This()->IsDate()) + return v8::Undefined(); + + QDateTime dt = QV8Engine::qtDateTimeFromJsDate(v8::Handle::Cast(args.This())->NumberValue()); + QTime time = dt.time(); + + if (args.Length() == 0) { + // Use QLocale for standard toLocaleString() function + QLocale locale; + return QJSConverter::toString(locale.toString(time)); + } + + if (!isLocaleObject(args[0])) + return v8::Undefined(); // Use the default Date toLocaleTimeString() + + GET_LOCALE_DATA_RESOURCE(args[0]->ToObject()); + + QLocale::FormatType enumFormat = QLocale::LongFormat; + QString formattedTime; + if (args.Length() == 2) { + if (args[1]->IsString()) { + QString format = r->engine->toVariant(args[1], -1).toString(); + formattedTime = r->locale.toString(time, format); + } else if (args[1]->IsNumber()) { + quint32 intFormat = args[1]->ToNumber()->Value(); + QLocale::FormatType format = QLocale::FormatType(intFormat); + formattedTime = r->locale.toString(time, format); + } else { + V8THROW_ERROR("Locale: Date.toLocaleTimeString(): Invalid time format"); + } + } else { + formattedTime = r->locale.toString(time, enumFormat); + } + + return r->engine->toString(formattedTime); +} + +v8::Handle QQmlDateExtension::toLocaleDateString(const v8::Arguments& args) +{ + if (args.Length() > 2) + return v8::Undefined(); + + if (!args.This()->IsDate()) + return v8::Undefined(); + + QDateTime dt = QV8Engine::qtDateTimeFromJsDate(v8::Handle::Cast(args.This())->NumberValue()); + QDate date = dt.date(); + + if (args.Length() == 0) { + // Use QLocale for standard toLocaleString() function + QLocale locale; + return QJSConverter::toString(locale.toString(date)); + } + + if (!isLocaleObject(args[0])) + return v8::Undefined(); // Use the default Date toLocaleDateString() + + GET_LOCALE_DATA_RESOURCE(args[0]->ToObject()); + + QLocale::FormatType enumFormat = QLocale::LongFormat; + QString formattedDate; + if (args.Length() == 2) { + if (args[1]->IsString()) { + QString format = r->engine->toVariant(args[1], -1).toString(); + formattedDate = r->locale.toString(date, format); + } else if (args[1]->IsNumber()) { + quint32 intFormat = args[1]->ToNumber()->Value(); + QLocale::FormatType format = QLocale::FormatType(intFormat); + formattedDate = r->locale.toString(date, format); + } else { + V8THROW_ERROR("Locale: Date.loLocaleDateString(): Invalid date format"); + } + } else { + formattedDate = r->locale.toString(date, enumFormat); + } + + return r->engine->toString(formattedDate); +} + +v8::Handle QQmlDateExtension::fromLocaleString(const v8::Arguments& args) +{ + if (args.Length() == 1 && args[0]->IsString()) { + QLocale locale; + QString dateString = QJSConverter::toString(args[0]->ToString()); + QDateTime dt = locale.toDateTime(dateString); + return QJSConverter::toDateTime(dt); + } + + if (args.Length() < 1 || args.Length() > 3 || !isLocaleObject(args[0])) + V8THROW_ERROR("Locale: Date.fromLocaleString(): Invalid arguments"); + + GET_LOCALE_DATA_RESOURCE(args[0]->ToObject()); + + QLocale::FormatType enumFormat = QLocale::LongFormat; + QDateTime dt; + QString dateString = r->engine->toString(args[1]->ToString()); + if (args.Length() == 3) { + if (args[2]->IsString()) { + QString format = r->engine->toString(args[2]->ToString()); + dt = r->locale.toDateTime(dateString, format); + } else if (args[2]->IsNumber()) { + quint32 intFormat = args[2]->ToNumber()->Value(); + QLocale::FormatType format = QLocale::FormatType(intFormat); + dt = r->locale.toDateTime(dateString, format); + } else { + V8THROW_ERROR("Locale: Date.fromLocaleString(): Invalid datetime format"); + } + } else { + dt = r->locale.toDateTime(dateString, enumFormat); + } + + return QJSConverter::toDateTime(dt); +} + +v8::Handle QQmlDateExtension::fromLocaleTimeString(const v8::Arguments& args) +{ + if (args.Length() == 1 && args[0]->IsString()) { + QLocale locale; + QString timeString = QJSConverter::toString(args[0]->ToString()); + QTime time = locale.toTime(timeString); + QDateTime dt = QDateTime::currentDateTime(); + dt.setTime(time); + return QJSConverter::toDateTime(dt); + } + + if (args.Length() < 1 || args.Length() > 3 || !isLocaleObject(args[0])) + V8THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid arguments"); + + GET_LOCALE_DATA_RESOURCE(args[0]->ToObject()); + + QLocale::FormatType enumFormat = QLocale::LongFormat; + QTime tm; + QString dateString = r->engine->toString(args[1]->ToString()); + if (args.Length() == 3) { + if (args[2]->IsString()) { + QString format = r->engine->toString(args[2]->ToString()); + tm = r->locale.toTime(dateString, format); + } else if (args[2]->IsNumber()) { + quint32 intFormat = args[2]->ToNumber()->Value(); + QLocale::FormatType format = QLocale::FormatType(intFormat); + tm = r->locale.toTime(dateString, format); + } else { + V8THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid datetime format"); + } + } else { + tm = r->locale.toTime(dateString, enumFormat); + } + + QDateTime dt = QDateTime::currentDateTime(); + dt.setTime(tm); + + return QJSConverter::toDateTime(dt); +} + +v8::Handle QQmlDateExtension::fromLocaleDateString(const v8::Arguments& args) +{ + if (args.Length() == 1 && args[0]->IsString()) { + QLocale locale; + QString dateString = QJSConverter::toString(args[0]->ToString()); + QDate date = locale.toDate(dateString); + return QJSConverter::toDateTime(QDateTime(date)); + } + + if (args.Length() < 1 || args.Length() > 3 || !isLocaleObject(args[0])) + V8THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid arguments"); + + GET_LOCALE_DATA_RESOURCE(args[0]->ToObject()); + + QLocale::FormatType enumFormat = QLocale::LongFormat; + QDate dt; + QString dateString = r->engine->toString(args[1]->ToString()); + if (args.Length() == 3) { + if (args[2]->IsString()) { + QString format = r->engine->toString(args[2]->ToString()); + dt = r->locale.toDate(dateString, format); + } else if (args[2]->IsNumber()) { + quint32 intFormat = args[2]->ToNumber()->Value(); + QLocale::FormatType format = QLocale::FormatType(intFormat); + dt = r->locale.toDate(dateString, format); + } else { + V8THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid datetime format"); + } + } else { + dt = r->locale.toDate(dateString, enumFormat); + } + + return QJSConverter::toDateTime(QDateTime(dt)); +} + +//----------------- +// Number extension + +static const char *numberToLocaleStringFunction = + "(function(toLocaleStringFunc) { " + " var orig_toLocaleString;" + " orig_toLocaleString = Number.prototype.toLocaleString;" + " Number.prototype.toLocaleString = (function() {" + " var val = toLocaleStringFunc.apply(this, arguments);" + " if (val == undefined) val = orig_toLocaleString.call(this);" + " return val;" + " })" + "})"; + +static const char *numberToLocaleCurrencyStringFunction = + "(function(toLocaleCurrencyStringFunc) { " + " Number.prototype.toLocaleCurrencyString = (function() {" + " return toLocaleCurrencyStringFunc.apply(this, arguments);" + " })" + "})"; + +static const char *numberFromLocaleStringFunction = + "(function(fromLocaleStringFunc) { " + " Number.fromLocaleString = (function() {" + " return fromLocaleStringFunc.apply(null, arguments);" + " })" + "})"; + + +void QQmlNumberExtension::registerExtension(QV8Engine *engine) +{ + registerFunction(engine, numberToLocaleStringFunction, toLocaleString); + registerFunction(engine, numberToLocaleCurrencyStringFunction, toLocaleCurrencyString); + registerFunction(engine, numberFromLocaleStringFunction, fromLocaleString); +} + +v8::Handle QQmlNumberExtension::toLocaleString(const v8::Arguments& args) +{ + if (args.Length() > 3) + V8THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments"); + + double number = args.This()->ToNumber()->Value(); + + if (args.Length() == 0) { + // Use QLocale for standard toLocaleString() function + QLocale locale; + return QJSConverter::toString(locale.toString(number)); + } + + if (!isLocaleObject(args[0])) + return v8::Undefined(); // Use the default Number toLocaleString() + + GET_LOCALE_DATA_RESOURCE(args[0]->ToObject()); + + uint16_t format = 'f'; + if (args.Length() > 1) { + if (!args[1]->IsString()) + V8THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments"); + v8::Local fs = args[1]->ToString(); + if (!fs.IsEmpty() && fs->Length()) + format = fs->GetCharacter(0); + } + int prec = 2; + if (args.Length() > 2) { + if (!args[2]->IsNumber()) + V8THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments"); + prec = args[2]->IntegerValue(); + } + + return r->engine->toString(r->locale.toString(number, (char)format, prec)); +} + +v8::Handle QQmlNumberExtension::toLocaleCurrencyString(const v8::Arguments& args) +{ + if (args.Length() > 2) + V8THROW_ERROR("Locale: Number.toLocaleCurrencyString(): Invalid arguments"); + + double number = args.This()->ToNumber()->Value(); + + if (args.Length() == 0) { + // Use QLocale for standard toLocaleString() function + QLocale locale; + return QJSConverter::toString(locale.toString(number)); + } + + if (!isLocaleObject(args[0])) + V8THROW_ERROR("Locale: Number.toLocaleCurrencyString(): Invalid arguments"); + + GET_LOCALE_DATA_RESOURCE(args[0]->ToObject()); + + QString symbol; + if (args.Length() > 1) { + if (!args[1]->IsString()) + V8THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments"); + symbol = r->engine->toString(args[1]->ToString()); + } + + return r->engine->toString(r->locale.toCurrencyString(number, symbol)); +} + +v8::Handle QQmlNumberExtension::fromLocaleString(const v8::Arguments& args) +{ + if (args.Length() < 1 || args.Length() > 2) + V8THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments"); + + int numberIdx = 0; + QLocale locale; + + if (args.Length() == 2) { + if (!isLocaleObject(args[0])) + V8THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments"); + + GET_LOCALE_DATA_RESOURCE(args[0]->ToObject()); + locale = r->locale; + + numberIdx = 1; + } + + v8::Local ns = args[numberIdx]->ToString(); + if (ns.IsEmpty() || ns->Length() == 0) + return v8::Number::New(Q_QNAN); + + bool ok = false; + double val = locale.toDouble(QJSConverter::toString(ns), &ok); + + if (!ok) + V8THROW_ERROR("Locale: Number.fromLocaleString(): Invalid format") + + return v8::Number::New(val); +} + +//-------------- +// Locale object + +static v8::Handle locale_get_firstDayOfWeek(v8::Local, const v8::AccessorInfo &info) +{ + GET_LOCALE_DATA_RESOURCE(info.This()); - return v8::Integer::New(r->locale.firstDayOfWeek()); ++ int fdow = int(r->locale.firstDayOfWeek()); ++ if (fdow == 7) ++ fdow = 0; // Qt::Sunday = 7, but Sunday is 0 in JS Date ++ return v8::Integer::New(fdow); +} + +static v8::Handle locale_get_measurementSystem(v8::Local, const v8::AccessorInfo &info) +{ + GET_LOCALE_DATA_RESOURCE(info.This()); + return v8::Integer::New(r->locale.measurementSystem()); +} + +static v8::Handle locale_get_textDirection(v8::Local, const v8::AccessorInfo &info) +{ + GET_LOCALE_DATA_RESOURCE(info.This()); + return v8::Integer::New(r->locale.textDirection()); +} + +static v8::Handle locale_get_weekDays(v8::Local, const v8::AccessorInfo &info) +{ + GET_LOCALE_DATA_RESOURCE(info.This()); + + QList days = r->locale.weekdays(); + + v8::Handle result = v8::Array::New(days.size()); + for (int i = 0; i < days.size(); ++i) { + int day = days.at(i); + if (day == 7) // JS Date days in range 0(Sunday) to 6(Saturday) + day = 0; + result->Set(i, v8::Integer::New(day)); + } + + return result; +} + +static v8::Handle locale_get_uiLanguages(v8::Local, const v8::AccessorInfo &info) +{ + GET_LOCALE_DATA_RESOURCE(info.This()); + + QStringList langs = r->locale.uiLanguages(); + v8::Handle result = v8::Array::New(langs.size()); + for (int i = 0; i < langs.size(); ++i) { + result->Set(i, r->engine->toString(langs.at(i))); + } + + return result; +} + +static v8::Handle locale_currencySymbol(const v8::Arguments &args) +{ + GET_LOCALE_DATA_RESOURCE(args.This()); + + if (args.Length() > 1) + V8THROW_ERROR("Locale: currencySymbol(): Invalid arguments"); + + QLocale::CurrencySymbolFormat format = QLocale::CurrencySymbol; + if (args.Length() == 1) { + quint32 intFormat = args[0]->ToNumber()->Value(); + format = QLocale::CurrencySymbolFormat(intFormat); + } + + return r->engine->toString(r->locale.currencySymbol(format)); +} + +#define LOCALE_FORMAT(FUNC) \ +static v8::Handle locale_ ##FUNC (const v8::Arguments &args) { \ + GET_LOCALE_DATA_RESOURCE(args.This());\ + if (args.Length() > 1) \ + V8THROW_ERROR("Locale: " #FUNC "(): Invalid arguments"); \ + QLocale::FormatType format = QLocale::LongFormat;\ + if (args.Length() == 1) { \ + quint32 intFormat = args[0]->Uint32Value(); \ + format = QLocale::FormatType(intFormat); \ + } \ + return r->engine->toString(r->locale. FUNC (format)); \ +} + +LOCALE_FORMAT(dateTimeFormat) +LOCALE_FORMAT(timeFormat) +LOCALE_FORMAT(dateFormat) + +// +1 added to idx because JS is 0-based, whereas QLocale months begin at 1. +#define LOCALE_FORMATTED_MONTHNAME(VARIABLE) \ +static v8::Handle locale_ ## VARIABLE (const v8::Arguments &args) {\ + GET_LOCALE_DATA_RESOURCE(args.This()); \ + if (args.Length() < 1 || args.Length() > 2) \ + V8THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \ + QLocale::FormatType enumFormat = QLocale::LongFormat; \ + int idx = args[0]->IntegerValue() + 1; \ + if (idx < 1 || idx > 12) \ + V8THROW_ERROR("Locale: Invalid month"); \ + QString name; \ + if (args.Length() == 2) { \ + if (args[1]->IsNumber()) { \ + quint32 intFormat = args[1]->IntegerValue(); \ + QLocale::FormatType format = QLocale::FormatType(intFormat); \ + name = r->locale. VARIABLE(idx, format); \ + } else { \ + V8THROW_ERROR("Locale: Invalid datetime format"); \ + } \ + } else { \ + name = r->locale. VARIABLE(idx, enumFormat); \ + } \ + return r->engine->toString(name); \ +} + +// 0 -> 7 as Qt::Sunday is 7, but Sunday is 0 in JS Date +#define LOCALE_FORMATTED_DAYNAME(VARIABLE) \ +static v8::Handle locale_ ## VARIABLE (const v8::Arguments &args) {\ + GET_LOCALE_DATA_RESOURCE(args.This()); \ + if (args.Length() < 1 || args.Length() > 2) \ + V8THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \ + QLocale::FormatType enumFormat = QLocale::LongFormat; \ + int idx = args[0]->IntegerValue(); \ + if (idx < 0 || idx > 7) \ + V8THROW_ERROR("Locale: Invalid day"); \ + if (idx == 0) idx = 7; \ + QString name; \ + if (args.Length() == 2) { \ + if (args[1]->IsNumber()) { \ + quint32 intFormat = args[1]->ToNumber()->Value(); \ + QLocale::FormatType format = QLocale::FormatType(intFormat); \ + name = r->locale. VARIABLE(idx, format); \ + } else { \ + V8THROW_ERROR("Locale: Invalid datetime format"); \ + } \ + } else { \ + name = r->locale. VARIABLE(idx, enumFormat); \ + } \ + return r->engine->toString(name); \ +} + + +#define LOCALE_REGISTER_FORMATTED_NAME_FUNCTION(FT, VARIABLE, ENGINE) \ + FT->PrototypeTemplate()->Set(v8::String::New( #VARIABLE ), V8FUNCTION(locale_ ## VARIABLE, ENGINE)); + +LOCALE_FORMATTED_MONTHNAME(monthName) +LOCALE_FORMATTED_MONTHNAME(standaloneMonthName) +LOCALE_FORMATTED_DAYNAME(dayName) +LOCALE_FORMATTED_DAYNAME(standaloneDayName) + +#define LOCALE_STRING_PROPERTY(VARIABLE) static v8::Handle locale_get_ ## VARIABLE (v8::Local, const v8::AccessorInfo &info) \ +{ \ + GET_LOCALE_DATA_RESOURCE(info.This()); \ + return r->engine->toString(r->locale. VARIABLE());\ +} + +#define LOCALE_REGISTER_STRING_ACCESSOR(FT, VARIABLE) \ + FT ->PrototypeTemplate()->SetAccessor( v8::String::New( #VARIABLE ), locale_get_ ## VARIABLE ) + + +LOCALE_STRING_PROPERTY(name) +LOCALE_STRING_PROPERTY(nativeLanguageName) +LOCALE_STRING_PROPERTY(nativeCountryName) +LOCALE_STRING_PROPERTY(decimalPoint) +LOCALE_STRING_PROPERTY(groupSeparator) +LOCALE_STRING_PROPERTY(percent) +LOCALE_STRING_PROPERTY(zeroDigit) +LOCALE_STRING_PROPERTY(negativeSign) +LOCALE_STRING_PROPERTY(positiveSign) +LOCALE_STRING_PROPERTY(exponential) +LOCALE_STRING_PROPERTY(amText) +LOCALE_STRING_PROPERTY(pmText) + +class QV8LocaleDataDeletable : public QV8Engine::Deletable +{ +public: + QV8LocaleDataDeletable(QV8Engine *engine); + ~QV8LocaleDataDeletable(); + + v8::Persistent constructor; +}; + +QV8LocaleDataDeletable::QV8LocaleDataDeletable(QV8Engine *engine) +{ + v8::HandleScope handle_scope; + v8::Context::Scope scope(engine->context()); + + v8::Local ft = v8::FunctionTemplate::New(); + ft->InstanceTemplate()->SetHasExternalResource(true); + + LOCALE_REGISTER_STRING_ACCESSOR(ft, name); + LOCALE_REGISTER_STRING_ACCESSOR(ft, nativeLanguageName); + LOCALE_REGISTER_STRING_ACCESSOR(ft, nativeCountryName); + LOCALE_REGISTER_STRING_ACCESSOR(ft, decimalPoint); + LOCALE_REGISTER_STRING_ACCESSOR(ft, groupSeparator); + LOCALE_REGISTER_STRING_ACCESSOR(ft, percent); + LOCALE_REGISTER_STRING_ACCESSOR(ft, zeroDigit); + LOCALE_REGISTER_STRING_ACCESSOR(ft, negativeSign); + LOCALE_REGISTER_STRING_ACCESSOR(ft, positiveSign); + LOCALE_REGISTER_STRING_ACCESSOR(ft, exponential); + LOCALE_REGISTER_STRING_ACCESSOR(ft, amText); + LOCALE_REGISTER_STRING_ACCESSOR(ft, pmText); + + ft->PrototypeTemplate()->Set(v8::String::New("currencySymbol"), V8FUNCTION(locale_currencySymbol, engine)); + + ft->PrototypeTemplate()->Set(v8::String::New("dateTimeFormat"), V8FUNCTION(locale_dateTimeFormat, engine)); + ft->PrototypeTemplate()->Set(v8::String::New("dateFormat"), V8FUNCTION(locale_dateFormat, engine)); + ft->PrototypeTemplate()->Set(v8::String::New("timeFormat"), V8FUNCTION(locale_timeFormat, engine)); + + LOCALE_REGISTER_FORMATTED_NAME_FUNCTION(ft, monthName, engine); + LOCALE_REGISTER_FORMATTED_NAME_FUNCTION(ft, standaloneMonthName, engine); + LOCALE_REGISTER_FORMATTED_NAME_FUNCTION(ft, dayName, engine); + LOCALE_REGISTER_FORMATTED_NAME_FUNCTION(ft, standaloneDayName, engine); + + ft->PrototypeTemplate()->SetAccessor(v8::String::New("firstDayOfWeek"), locale_get_firstDayOfWeek); + ft->PrototypeTemplate()->SetAccessor(v8::String::New("weekDays"), locale_get_weekDays); + ft->PrototypeTemplate()->SetAccessor(v8::String::New("measurementSystem"), locale_get_measurementSystem); + ft->PrototypeTemplate()->SetAccessor(v8::String::New("textDirection"), locale_get_textDirection); + ft->PrototypeTemplate()->SetAccessor(v8::String::New("uiLanguages"), locale_get_uiLanguages); + + constructor = qPersistentNew(ft->GetFunction()); +} + +QV8LocaleDataDeletable::~QV8LocaleDataDeletable() +{ + qPersistentDispose(constructor); +} + +V8_DEFINE_EXTENSION(QV8LocaleDataDeletable, localeV8Data); + +/*! + \qmlclass Locale QQmlLocale + \inqmlmodule QtQuick 2 + \brief The Locale object provides locale specific properties and formatted data. + + The Locale object is created via the \l{QML:Qt::locale()}{Qt.locale()} function. It cannot be created + directly. + + The \l{QML:Qt::locale()}{Qt.locale()} function returns a JS Locale object representing the + locale with the specified name, which has the format + "language[_territory][.codeset][@modifier]" or "C". + + Locale supports the concept of a default locale, which is + determined from the system's locale settings at application + startup. If no parameter is passed to Qt.locale() the default + locale object is returned. + + The Locale object provides a number of functions and properties + providing data for the specified locale. + + The Locale object may also be passed to the \l Date and \l Number toLocaleString() + and fromLocaleString() methods in order to convert to/from strings using + the specified locale. + + This example shows the current date formatted for the German locale: + + \code + import QtQuick 2.0 + + Text { + text: "The date is: " + Date().toLocaleString(Qt.locale("de_DE")) + } + \endcode + + The following example displays the specified number + in the correct format for the default locale: + + \code + import QtQuick 2.0 + + Text { + text: "The value is: " + Number(23443.34).toLocaleString(Qt.locale()) + } + \endcode + + QtQuick Locale's data is based on Common Locale Data Repository v1.8.1. + + The double-to-string and string-to-double conversion functions are + covered by the following licenses: + + \legalese + Copyright (c) 1991 by AT&T. + + Permission to use, copy, modify, and distribute this software for any + purpose without fee is hereby granted, provided that this entire notice + is included in all copies of any software which is or includes a copy + or modification of this software and in all copies of the supporting + documentation for such software. + + THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY + REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + + This product includes software developed by the University of + California, Berkeley and its contributors. + + \sa {QtQuick2::Date}{Date} {QtQuick2::Number}{Number} +*/ + +QQmlLocale::QQmlLocale() +{ +} + +QQmlLocale::~QQmlLocale() +{ +} + +v8::Handle QQmlLocale::locale(QV8Engine *v8engine, const QString &locale) +{ + QV8LocaleDataDeletable *d = localeV8Data(v8engine); + v8::Local v8Value = d->constructor->NewInstance(); + QV8LocaleDataResource *r = new QV8LocaleDataResource(v8engine); + if (locale.isEmpty()) + r->locale = QLocale(); + else + r->locale = QLocale(locale); + v8Value->SetExternalResource(r); + + return v8Value; +} + +static const char *localeCompareFunction = + "(function(localeCompareFunc) { " + " var orig_localeCompare;" + " orig_localeCompare = String.prototype.localeCompare;" + " String.prototype.localeCompare = (function() {" + " var val = localeCompareFunc.apply(this, arguments);" + " if (val == undefined) val = orig_localeCompare.call(this);" + " return val;" + " })" + "})"; + +void QQmlLocale::registerStringLocaleCompare(QV8Engine *engine) +{ + registerFunction(engine, localeCompareFunction, localeCompare); +} + +v8::Handle QQmlLocale::localeCompare(const v8::Arguments &args) +{ + if (args.Length() != 1 || (!args[0]->IsString() && !args[0]->IsStringObject())) + return v8::Undefined(); + + if (!args.This()->IsString() && !args.This()->IsStringObject()) + return v8::Undefined(); + + QString thisString = QJSConverter::toString(args.This()->ToString()); + QString thatString = QJSConverter::toString(args[0]->ToString()); + + return v8::Integer::New(QString::localeAwareCompare(thisString, thatString)); +} + +/*! + \enum QtQuick2::Locale::FormatType + + This enumeration describes the types of format that can be used when + converting Date objects to strings. + + \value LongFormat The long version of day and month names; for + example, returning "January" as a month name. + + \value ShortFormat The short version of day and month names; for + example, returning "Jan" as a month name. + + \value NarrowFormat A special version of day and month names for + use when space is limited; for example, returning "J" as a month + name. Note that the narrow format might contain the same text for + different months and days or it can even be an empty string if the + locale doesn't support narrow names, so you should avoid using it + for date formatting. Also, for the system locale this format is + the same as ShortFormat. +*/ + +/*! + \qmlproperty string QtQuick2::Locale::name + + Holds the language and country of this locale as a + string of the form "language_country", where + language is a lowercase, two-letter ISO 639 language code, + and country is an uppercase, two- or three-letter ISO 3166 country code. +*/ + +/*! + \qmlproperty string QtQuick2::Locale::decimalPoint + + Holds the decimal point character of this locale. +*/ + +/*! + \qmlproperty string QtQuick2::Locale::groupSeparator + + Holds the group separator character of this locale. +*/ + +/*! + \qmlproperty string QtQuick2::Locale::percent + + Holds the percent character of this locale. +*/ + + +/*! + \qmlproperty string QtQuick2::Locale::zeroDigit + + Holds Returns the zero digit character of this locale. +*/ + +/*! + \qmlproperty string QtQuick2::Locale::negativeSign + + Holds the negative sign character of this locale. +*/ + +/*! + \qmlproperty string QtQuick2::Locale::positiveSign + + Holds the positive sign character of this locale. +*/ + +/*! + \qmlproperty string QtQuick2::Locale::exponential + + Holds the exponential character of this locale. +*/ + +/*! + \qmlmethod string QtQuick2::Locale::dateTimeFormat(type) + + Returns the date time format used for the current locale. + \a type specifies the FormatType to return. + + \sa {QtQuick2::Date}{Date} +*/ + +/*! + \qmlmethod string QtQuick2::Locale::dateFormat(type) + + Returns the date format used for the current locale. + \a type specifies the FormatType to return. + + \sa {QtQuick2::Date}{Date} +*/ + +/*! + \qmlmethod string QtQuick2::Locale::timeFormat(type) + + Returns the time format used for the current locale. + \a type specifies the FormatType to return. + + \sa {QtQuick2::Date}{Date} +*/ + +/*! + \qmlmethod string QtQuick2::Locale::monthName(month, type) + + Returns the localized name of \a month (0-11), in the optional + \l FortmatType specified by \a type. + + \note the QLocale C++ API expects a range of (1-12), however Locale.monthName() + expects 0-11 as per the JS Date object. + + \sa dayName(), standaloneMonthName() +*/ + +/*! + \qmlmethod string QtQuick2::Locale::standaloneMonthName(month, type) + + Returns the localized name of \a month (0-11) that is used as a + standalone text, in the optional \l FormatType specified by \a type. + + If the locale information doesn't specify the standalone month + name then return value is the same as in monthName(). + + \note the QLocale C++ API expects a range of (1-12), however Locale.standaloneMonthName() + expects 0-11 as per the JS Date object. + + \sa monthName(), standaloneDayName() +*/ + +/*! + \qmlmethod string QtQuick2::Locale::dayName(day, type) + + Returns the localized name of the \a day (where 0 represents + Sunday, 1 represents Monday and so on), in the optional + \l FormatType specified by \a type. + + \sa monthName(), standaloneDayName() +*/ + +/*! + \qmlmethod string QtQuick2::Locale::standaloneDayName(day, type) + + Returns the localized name of the \a day (where 0 represents + Sunday, 1 represents Monday and so on) that is used as a + standalone text, in the \l FormatType specified by \a type. + + If the locale information does not specify the standalone day + name then return value is the same as in dayName(). + + \sa dayName(), standaloneMonthName() +*/ + +/*! + \qmlproperty enumeration QtQuick2::Locale::firstDayOfWeek + + Holds the first day of the week according to the current locale. + + \list + \o Locale.Sunday = 0 + \o Locale.Monday = 1 + \o Locale.Tuesday = 2 + \o Locale.Wednesday = 3 + \o Locale.Thursday = 4 + \o Locale.Friday = 5 + \o Locale.Saturday = 6 + \endlist + + \note that these values match the JS Date API which is different + from the Qt C++ API where Qt::Sunday = 7. +*/ + +/*! + \qmlproperty Array QtQuick2::Locale::weekDays + + Holds an array of days that are considered week days according to the current locale, + where Sunday is 0 and Saturday is 6. + + \sa firstDayOfWeek +*/ + +/*! + \qmlproperty Array QtQuick2::Locale::uiLanguages + + Returns an ordered list of locale names for translation purposes in + preference order. + + The return value represents locale names that the user expects to see the + UI translation in. + + The first item in the list is the most preferred one. +*/ + +/*! + \qmlproperty enumeration QtQuick2::Locale::textDirection + + Holds the text direction of the language: + \list + \o Qt.LeftToRight + \o Qt.RightToLeft + \endlist +*/ + +/*! + \qmlproperty string QtQuick2::Locale::amText + + The localized name of the "AM" suffix for times specified using the conventions of the 12-hour clock. +*/ + +/*! + \qmlproperty string QtQuick2::Locale::pmText + + The localized name of the "PM" suffix for times specified using the conventions of the 12-hour clock. +*/ + +/*! + \qmlmethod string QtQuick2::Locale::currencySymbol(format) + + Returns the currency symbol for the specified \a format: + \list + \o Locale.CurrencyIsoCode a ISO-4217 code of the currency. + \o Locale.CurrencySymbol a currency symbol. + \o Locale.CurrencyDisplayName a user readable name of the currency. + \endlist + \sa Number::toLocaleCurrencyString() +*/ + +/*! + \qmlproperty string QtQuick2::Locale::nativeLanguageName + + Holds a native name of the language for the locale. For example + "Schwiizertüütsch" for Swiss-German locale. + + \sa nativeCountryName +*/ + +/*! + \qmlproperty string QtQuick2::Locale::nativeCountryName + + Holds a native name of the country for the locale. For example + "España" for Spanish/Spain locale. + + \sa nativeLanguageName +*/ + +/*! + \qmlproperty enumeration QtQuick2::Locale::measurementSystem + + This property defines which units are used for measurement. + + \list + \o Locale.MetricSystem This value indicates metric units, such as meters, + centimeters and millimeters. + \o Locale.ImperialSystem This value indicates imperial units, such as inches and + miles. There are several distinct imperial systems in the world; this + value stands for the official United States imperial units. + \endlist +*/ + +QT_END_NAMESPACE diff --cc src/qml/qml/qqmlpropertycache.cpp index 9b132a4,0000000..93c6aa1 mode 100644,000000..100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@@ -1,889 -1,0 +1,891 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmlpropertycache_p.h" + +#include "qqmlengine_p.h" +#include "qqmlbinding_p.h" +#include + +#include +#include + +#include + ++#include // for toupper ++ +Q_DECLARE_METATYPE(QJSValue) +Q_DECLARE_METATYPE(QQmlV8Handle); + +QT_BEGIN_NAMESPACE + +#define Q_INT16_MAX 32767 + +class QQmlPropertyCacheMethodArguments +{ +public: + QQmlPropertyCacheMethodArguments *next; + int arguments[0]; +}; + +// Flags that do *NOT* depend on the property's QMetaProperty::userType() and thus are quick +// to load +static QQmlPropertyData::Flags fastFlagsForProperty(const QMetaProperty &p) +{ + QQmlPropertyData::Flags flags; + + if (p.isConstant()) + flags |= QQmlPropertyData::IsConstant; + if (p.isWritable()) + flags |= QQmlPropertyData::IsWritable; + if (p.isResettable()) + flags |= QQmlPropertyData::IsResettable; + if (p.isFinal()) + flags |= QQmlPropertyData::IsFinal; + if (p.isEnumType()) + flags |= QQmlPropertyData::IsEnumType; + + return flags; +} + +// Flags that do depend on the property's QMetaProperty::userType() and thus are slow to +// load +static QQmlPropertyData::Flags flagsForPropertyType(int propType, QQmlEngine *engine) +{ + Q_ASSERT(propType != -1); + + QQmlPropertyData::Flags flags; + + if (propType == QMetaType::QObjectStar || propType == QMetaType::QWidgetStar) { + flags |= QQmlPropertyData::IsQObjectDerived; + } else if (propType == QMetaType::QVariant) { + flags |= QQmlPropertyData::IsQVariant; + } else if (propType < (int)QVariant::UserType) { + } else if (propType == qMetaTypeId()) { + flags |= QQmlPropertyData::IsQmlBinding; + } else if (propType == qMetaTypeId()) { + flags |= QQmlPropertyData::IsQJSValue; + } else if (propType == qMetaTypeId()) { + flags |= QQmlPropertyData::IsV8Handle; + } else { + QQmlMetaType::TypeCategory cat = + engine ? QQmlEnginePrivate::get(engine)->typeCategory(propType) + : QQmlMetaType::typeCategory(propType); + + if (cat == QQmlMetaType::Object) + flags |= QQmlPropertyData::IsQObjectDerived; + else if (cat == QQmlMetaType::List) + flags |= QQmlPropertyData::IsQList; + } + + return flags; +} + +static int metaObjectSignalCount(const QMetaObject *metaObject) +{ + int signalCount = 0; + for (const QMetaObject *obj = metaObject; obj; obj = obj->superClass()) + signalCount += QMetaObjectPrivate::get(obj)->signalCount; + return signalCount; +} + +QQmlPropertyData::Flags +QQmlPropertyData::flagsForProperty(const QMetaProperty &p, QQmlEngine *engine) +{ + return fastFlagsForProperty(p) | flagsForPropertyType(p.userType(), engine); +} + +void QQmlPropertyData::lazyLoad(const QMetaProperty &p, QQmlEngine *engine) +{ + Q_UNUSED(engine); + + coreIndex = p.propertyIndex(); + notifyIndex = p.notifySignalIndex(); + Q_ASSERT(p.revision() <= Q_INT16_MAX); + revision = p.revision(); + + flags = fastFlagsForProperty(p); + + int type = p.type(); + if (type == QMetaType::QObjectStar || type == QMetaType::QWidgetStar) { + propType = type; + flags |= QQmlPropertyData::IsQObjectDerived; + } else if (type == QMetaType::QVariant) { + propType = type; + flags |= QQmlPropertyData::IsQVariant; + } else if (type == QVariant::UserType || type == -1) { + propTypeName = p.typeName(); + flags |= QQmlPropertyData::NotFullyResolved; + } else { + propType = type; + } +} + +void QQmlPropertyData::load(const QMetaProperty &p, QQmlEngine *engine) +{ + propType = p.userType(); + coreIndex = p.propertyIndex(); + notifyIndex = p.notifySignalIndex(); + flags = fastFlagsForProperty(p) | flagsForPropertyType(propType, engine); + Q_ASSERT(p.revision() <= Q_INT16_MAX); + revision = p.revision(); +} + +void QQmlPropertyData::load(const QMetaMethod &m) +{ + coreIndex = m.methodIndex(); + arguments = 0; + flags |= IsFunction; + if (m.methodType() == QMetaMethod::Signal) + flags |= IsSignal; + propType = QVariant::Invalid; + + const char *returnType = m.typeName(); + if (returnType) + propType = QMetaType::type(returnType); + + const char *signature = m.signature(); + while (*signature != '(') { Q_ASSERT(*signature != 0); ++signature; } + + ++signature; + if (*signature != ')') { + flags |= HasArguments; + if (0 == ::strcmp(signature, "QQmlV8Function*)")) { + flags |= IsV8Function; + } + } + + Q_ASSERT(m.revision() <= Q_INT16_MAX); + revision = m.revision(); +} + +void QQmlPropertyData::lazyLoad(const QMetaMethod &m) +{ + coreIndex = m.methodIndex(); + arguments = 0; + flags |= IsFunction; + if (m.methodType() == QMetaMethod::Signal) + flags |= IsSignal; + propType = QVariant::Invalid; + + const char *returnType = m.typeName(); + if (returnType && *returnType) { + propTypeName = returnType; + flags |= NotFullyResolved; + } + + const char *signature = m.signature(); + while (*signature != '(') { Q_ASSERT(*signature != 0); ++signature; } + + ++signature; + if (*signature != ')') { + flags |= HasArguments; + if (0 == ::strcmp(signature, "QQmlV8Function*)")) { + flags |= IsV8Function; + } + } + + Q_ASSERT(m.revision() <= Q_INT16_MAX); + revision = m.revision(); +} + +/*! +Creates a new empty QQmlPropertyCache. +*/ +QQmlPropertyCache::QQmlPropertyCache(QQmlEngine *e) +: engine(e), parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0), + signalHanderIndexCacheStart(0), metaObject(0), argumentsCache(0) +{ + Q_ASSERT(engine); +} + +/*! +Creates a new QQmlPropertyCache of \a metaObject. +*/ +QQmlPropertyCache::QQmlPropertyCache(QQmlEngine *e, const QMetaObject *metaObject) +: engine(e), parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0), + signalHanderIndexCacheStart(0), metaObject(0), argumentsCache(0) +{ + Q_ASSERT(engine); + Q_ASSERT(metaObject); + + update(engine, metaObject); +} + +QQmlPropertyCache::~QQmlPropertyCache() +{ + clear(); + + QQmlPropertyCacheMethodArguments *args = argumentsCache; + while (args) { + QQmlPropertyCacheMethodArguments *next = args->next; + free(args); + args = next; + } + + // We must clear this prior to releasing the parent incase it is a + // linked hash + stringCache.clear(); + if (parent) parent->release(); + parent = 0; + engine = 0; +} + +void QQmlPropertyCache::destroy() +{ + Q_ASSERT(engine || constructor.IsEmpty()); + if (constructor.IsEmpty()) + delete this; + else + QQmlEnginePrivate::deleteInEngineThread(engine, this); +} + +// This is inherited from QQmlCleanup, so it should only clear the things +// that are tied to the specific QQmlEngine. +void QQmlPropertyCache::clear() +{ + qPersistentDispose(constructor); + engine = 0; +} + +QQmlPropertyCache *QQmlPropertyCache::copy(int reserve) +{ + QQmlPropertyCache *cache = new QQmlPropertyCache(engine); + cache->parent = this; + cache->parent->addref(); + cache->propertyIndexCacheStart = propertyIndexCache.count() + propertyIndexCacheStart; + cache->methodIndexCacheStart = methodIndexCache.count() + methodIndexCacheStart; + cache->signalHanderIndexCacheStart = signalHandlerIndexCache.count() + signalHanderIndexCacheStart; + cache->stringCache.linkAndReserve(stringCache, reserve); + cache->allowedRevisionCache = allowedRevisionCache; + cache->metaObject = metaObject; + + // We specifically do *NOT* copy the constructor + + return cache; +} + +QQmlPropertyCache *QQmlPropertyCache::copy() +{ + return copy(0); +} + +QQmlPropertyCache * +QQmlPropertyCache::copyAndAppend(QQmlEngine *engine, const QMetaObject *metaObject, + QQmlPropertyData::Flag propertyFlags, + QQmlPropertyData::Flag methodFlags, + QQmlPropertyData::Flag signalFlags) +{ + return copyAndAppend(engine, metaObject, -1, propertyFlags, methodFlags, signalFlags); +} + +QQmlPropertyCache * +QQmlPropertyCache::copyAndAppend(QQmlEngine *engine, const QMetaObject *metaObject, + int revision, + QQmlPropertyData::Flag propertyFlags, + QQmlPropertyData::Flag methodFlags, + QQmlPropertyData::Flag signalFlags) +{ + Q_ASSERT(QMetaObjectPrivate::get(metaObject)->revision >= 4); + + // Reserve enough space in the name hash for all the methods (including signals), all the + // signal handlers and all the properties. This assumes no name clashes, but this is the + // common case. + QQmlPropertyCache *rv = copy(QMetaObjectPrivate::get(metaObject)->methodCount + + QMetaObjectPrivate::get(metaObject)->signalCount + + QMetaObjectPrivate::get(metaObject)->propertyCount); + + rv->append(engine, metaObject, revision, propertyFlags, methodFlags, signalFlags); + + return rv; +} + +void QQmlPropertyCache::append(QQmlEngine *engine, const QMetaObject *metaObject, + QQmlPropertyData::Flag propertyFlags, + QQmlPropertyData::Flag methodFlags, + QQmlPropertyData::Flag signalFlags) +{ + append(engine, metaObject, -1, propertyFlags, methodFlags, signalFlags); +} + +void QQmlPropertyCache::append(QQmlEngine *engine, const QMetaObject *metaObject, + int revision, + QQmlPropertyData::Flag propertyFlags, + QQmlPropertyData::Flag methodFlags, + QQmlPropertyData::Flag signalFlags) +{ + Q_UNUSED(revision); + Q_ASSERT(constructor.IsEmpty()); // We should not be appending to an in-use property cache + + this->metaObject = metaObject; + + bool dynamicMetaObject = isDynamicMetaObject(metaObject); + + allowedRevisionCache.append(0); + + int methodCount = metaObject->methodCount(); + Q_ASSERT(QMetaObjectPrivate::get(metaObject)->revision >= 4); + int signalCount = metaObjectSignalCount(metaObject); + int classInfoCount = QMetaObjectPrivate::get(metaObject)->classInfoCount; + + QQmlAccessorProperties::Properties accessorProperties; + + // Special case QObject as we don't want to add a qt_HasQmlAccessors classinfo to it + if (metaObject == &QObject::staticMetaObject) { + accessorProperties = QQmlAccessorProperties::properties(metaObject); + } else if (classInfoCount) { + int classInfoOffset = metaObject->classInfoOffset(); + bool hasFastProperty = false; + for (int ii = 0; ii < classInfoCount; ++ii) { + int idx = ii + classInfoOffset; + + if (0 == qstrcmp(metaObject->classInfo(idx).name(), "qt_HasQmlAccessors")) { + hasFastProperty = true; + break; + } + } + + if (hasFastProperty) { + accessorProperties = QQmlAccessorProperties::properties(metaObject); + if (accessorProperties.count == 0) + qFatal("QQmlPropertyCache: %s has FastProperty class info, but has not " + "installed property accessors", metaObject->className()); + } else { +#ifndef QT_NO_DEBUG + accessorProperties = QQmlAccessorProperties::properties(metaObject); + if (accessorProperties.count != 0) + qFatal("QQmlPropertyCache: %s has fast property accessors, but is missing " + "FastProperty class info", metaObject->className()); +#endif + } + } + + // qMax(defaultMethods, methodOffset) to block the signals and slots of QObject::staticMetaObject + // incl. destroyed signals, objectNameChanged signal, deleteLater slot, _q_reregisterTimers slot. + int methodOffset = qMax(QObject::staticMetaObject.methodCount(), metaObject->methodOffset()); + int signalOffset = signalCount - QMetaObjectPrivate::get(metaObject)->signalCount; + + // update() should have reserved enough space in the vector that this doesn't cause a realloc + // and invalidate the stringCache. + methodIndexCache.resize(methodCount - methodIndexCacheStart); + signalHandlerIndexCache.resize(signalCount - signalHanderIndexCacheStart); + int signalHandlerIndex = signalOffset; + for (int ii = methodOffset; ii < methodCount; ++ii) { + QMetaMethod m = metaObject->method(ii); + if (m.access() == QMetaMethod::Private) + continue; + + // Extract method name + const char *signature = m.signature(); + const char *cptr = signature; + char utf8 = 0; + while (*cptr != '(') { + Q_ASSERT(*cptr != 0); + utf8 |= *cptr & 0x80; + ++cptr; + } + + QQmlPropertyData *data = &methodIndexCache[ii - methodIndexCacheStart]; + QQmlPropertyData *sigdata = 0; + + data->lazyLoad(m); + + if (data->isSignal()) + data->flags |= signalFlags; + else + data->flags |= methodFlags; + + if (!dynamicMetaObject) + data->flags |= QQmlPropertyData::IsDirect; + + Q_ASSERT((allowedRevisionCache.count() - 1) < Q_INT16_MAX); + data->metaObjectOffset = allowedRevisionCache.count() - 1; + + if (data->isSignal()) { + sigdata = &signalHandlerIndexCache[signalHandlerIndex - signalHanderIndexCacheStart]; + *sigdata = *data; + sigdata->flags |= QQmlPropertyData::IsSignalHandler; + } + + QQmlPropertyData *old = 0; + + if (utf8) { + QHashedString methodName(QString::fromUtf8(signature, cptr - signature)); + if (QQmlPropertyData **it = stringCache.value(methodName)) + old = *it; + stringCache.insert(methodName, data); + + if (data->isSignal()) { + QHashedString on(QStringLiteral("on") % methodName.at(0).toUpper() % methodName.midRef(1)); + stringCache.insert(on, sigdata); + ++signalHandlerIndex; + } + } else { + QHashedCStringRef methodName(signature, cptr - signature); + if (QQmlPropertyData **it = stringCache.value(methodName)) + old = *it; + stringCache.insert(methodName, data); + + if (data->isSignal()) { + int length = methodName.length(); + + QVarLengthArray str(length+3); + str[0] = 'o'; + str[1] = 'n'; + str[2] = toupper(signature[0]); + if (length > 1) + memcpy(&str[3], &signature[1], length - 1); + str[length + 2] = '\0'; + + QHashedString on(QString::fromLatin1(str.data())); + stringCache.insert(on, sigdata); + ++signalHandlerIndex; + } + } + + if (old) { + // We only overload methods in the same class, exactly like C++ + if (old->isFunction() && old->coreIndex >= methodOffset) + data->flags |= QQmlPropertyData::IsOverload; + data->overrideIndexIsProperty = !old->isFunction(); + data->overrideIndex = old->coreIndex; + } + } + + int propCount = metaObject->propertyCount(); + int propOffset = metaObject->propertyOffset(); + + // update() should have reserved enough space in the vector that this doesn't cause a realloc + // and invalidate the stringCache. + propertyIndexCache.resize(propCount - propertyIndexCacheStart); + for (int ii = propOffset; ii < propCount; ++ii) { + QMetaProperty p = metaObject->property(ii); + if (!p.isScriptable()) + continue; + + const char *str = p.name(); + char utf8 = 0; + const char *cptr = str; + while (*cptr != 0) { + utf8 |= *cptr & 0x80; + ++cptr; + } + + QQmlPropertyData *data = &propertyIndexCache[ii - propertyIndexCacheStart]; + + data->lazyLoad(p, engine); + data->flags |= propertyFlags; + + if (!dynamicMetaObject) + data->flags |= QQmlPropertyData::IsDirect; + + Q_ASSERT((allowedRevisionCache.count() - 1) < Q_INT16_MAX); + data->metaObjectOffset = allowedRevisionCache.count() - 1; + + QQmlPropertyData *old = 0; + + if (utf8) { + QHashedString propName(QString::fromUtf8(str, cptr - str)); + if (QQmlPropertyData **it = stringCache.value(propName)) + old = *it; + stringCache.insert(propName, data); + } else { + QHashedCStringRef propName(str, cptr - str); + if (QQmlPropertyData **it = stringCache.value(propName)) + old = *it; + stringCache.insert(propName, data); + } + + QQmlAccessorProperties::Property *accessorProperty = accessorProperties.property(str); + + // Fast properties may not be overrides or revisioned + Q_ASSERT(accessorProperty == 0 || (old == 0 && data->revision == 0)); + + if (accessorProperty) { + data->flags |= QQmlPropertyData::HasAccessors; + data->accessors = accessorProperty->accessors; + data->accessorData = accessorProperty->data; + } else if (old) { + data->overrideIndexIsProperty = !old->isFunction(); + data->overrideIndex = old->coreIndex; + } + } +} + +void QQmlPropertyCache::resolve(QQmlPropertyData *data) const +{ + Q_ASSERT(data->notFullyResolved()); + + data->propType = QMetaType::type(data->propTypeName); + + if (!data->isFunction()) + data->flags |= flagsForPropertyType(data->propType, engine); + + data->flags &= ~QQmlPropertyData::NotFullyResolved; +} + +void QQmlPropertyCache::updateRecur(QQmlEngine *engine, const QMetaObject *metaObject) +{ + if (!metaObject) + return; + + updateRecur(engine, metaObject->superClass()); + + append(engine, metaObject); +} + +void QQmlPropertyCache::update(QQmlEngine *engine, const QMetaObject *metaObject) +{ + Q_ASSERT(engine); + Q_ASSERT(metaObject); + Q_ASSERT(stringCache.isEmpty()); + + // Preallocate enough space in the index caches for all the properties/methods/signals that + // are not cached in a parent cache so that the caches never need to be reallocated as this + // would invalidate pointers stored in the stringCache. + int pc = metaObject->propertyCount(); + int mc = metaObject->methodCount(); + int sc = metaObjectSignalCount(metaObject); + propertyIndexCache.reserve(pc - propertyIndexCacheStart); + methodIndexCache.reserve(mc - methodIndexCacheStart); + signalHandlerIndexCache.reserve(sc - signalHanderIndexCacheStart); + + // Reserve enough space in the stringCache for all properties/methods/signals including those + // cached in a parent cache. + stringCache.reserve(pc + mc + sc); + + updateRecur(engine,metaObject); +} + +QQmlPropertyData * +QQmlPropertyCache::property(int index) const +{ + if (index < 0 || index >= (propertyIndexCacheStart + propertyIndexCache.count())) + return 0; + + if (index < propertyIndexCacheStart) + return parent->property(index); + + QQmlPropertyData *rv = const_cast(&propertyIndexCache.at(index - propertyIndexCacheStart)); + if (rv->notFullyResolved()) resolve(rv); + return rv; +} + +QQmlPropertyData * +QQmlPropertyCache::method(int index) const +{ + if (index < 0 || index >= (methodIndexCacheStart + methodIndexCache.count())) + return 0; + + if (index < methodIndexCacheStart) + return parent->method(index); + + QQmlPropertyData *rv = const_cast(&methodIndexCache.at(index - methodIndexCacheStart)); + if (rv->notFullyResolved()) resolve(rv); + return rv; +} + +QQmlPropertyData * +QQmlPropertyCache::property(const QHashedStringRef &str) const +{ + QQmlPropertyData **rv = stringCache.value(str); + if (rv && (*rv)->notFullyResolved()) resolve(*rv); + return rv?*rv:0; +} + +QQmlPropertyData * +QQmlPropertyCache::property(const QHashedCStringRef &str) const +{ + QQmlPropertyData **rv = stringCache.value(str); + if (rv && (*rv)->notFullyResolved()) resolve(*rv); + return rv?*rv:0; +} + +QQmlPropertyData * +QQmlPropertyCache::property(const QString &str) const +{ + QQmlPropertyData **rv = stringCache.value(str); + if (rv && (*rv)->notFullyResolved()) resolve(*rv); + return rv?*rv:0; +} + +QString QQmlPropertyData::name(QObject *object) +{ + if (!object) + return QString(); + + return name(object->metaObject()); +} + +QString QQmlPropertyData::name(const QMetaObject *metaObject) +{ + if (!metaObject || coreIndex == -1) + return QString(); + + if (flags & IsFunction) { + QMetaMethod m = metaObject->method(coreIndex); + + QString name = QString::fromUtf8(m.signature()); + int parenIdx = name.indexOf(QLatin1Char('(')); + if (parenIdx != -1) + name = name.left(parenIdx); + return name; + } else { + QMetaProperty p = metaObject->property(coreIndex); + return QString::fromUtf8(p.name()); + } +} + +QStringList QQmlPropertyCache::propertyNames() const +{ + QStringList keys; + for (StringCache::ConstIterator iter = stringCache.begin(); iter != stringCache.end(); ++iter) + keys.append(iter.key()); + return keys; +} + +static int EnumType(const QMetaObject *meta, const QByteArray &str) +{ + QByteArray scope; + QByteArray name; + int scopeIdx = str.lastIndexOf("::"); + if (scopeIdx != -1) { + scope = str.left(scopeIdx); + name = str.mid(scopeIdx + 2); + } else { + name = str; + } + for (int i = meta->enumeratorCount() - 1; i >= 0; --i) { + QMetaEnum m = meta->enumerator(i); + if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope))) + return QVariant::Int; + } + return QVariant::Invalid; +} + +// Returns an array of the arguments for method \a index. The first entry in the array +// is the number of arguments. +int *QQmlPropertyCache::methodParameterTypes(QObject *object, int index, + QVarLengthArray &dummy, + QByteArray *unknownTypeError) +{ + Q_ASSERT(object && index >= 0); + + QQmlData *ddata = QQmlData::get(object, false); + + if (ddata && ddata->propertyCache) { + typedef QQmlPropertyCacheMethodArguments A; + + QQmlPropertyCache *c = ddata->propertyCache; + Q_ASSERT(index < c->methodIndexCacheStart + c->methodIndexCache.count()); + + while (index < c->methodIndexCacheStart) + c = c->parent; + + QQmlPropertyData *rv = const_cast(&c->methodIndexCache.at(index - c->methodIndexCacheStart)); + + if (rv->arguments) + return static_cast(rv->arguments)->arguments; + + const QMetaObject *metaObject = object->metaObject(); + QMetaMethod m = metaObject->method(index); + QList argTypeNames = m.parameterTypes(); + + A *args = static_cast(malloc(sizeof(A) + (argTypeNames.count() + 1) * sizeof(int))); + args->arguments[0] = argTypeNames.count(); + + for (int ii = 0; ii < argTypeNames.count(); ++ii) { + int type = QMetaType::type(argTypeNames.at(ii)); + if (type == QVariant::Invalid) + type = EnumType(object->metaObject(), argTypeNames.at(ii)); + if (type == QVariant::Invalid) { + if (unknownTypeError) *unknownTypeError = argTypeNames.at(ii); + free(args); + return 0; + } + args->arguments[ii + 1] = type; + } + + rv->arguments = args; + args->next = c->argumentsCache; + c->argumentsCache = args; + return static_cast(rv->arguments)->arguments; + + } else { + QMetaMethod m = object->metaObject()->method(index); + QList argTypeNames = m.parameterTypes(); + dummy.resize(argTypeNames.count() + 1); + dummy[0] = argTypeNames.count(); + + for (int ii = 0; ii < argTypeNames.count(); ++ii) { + int type = QMetaType::type(argTypeNames.at(ii)); + if (type == QVariant::Invalid) + type = EnumType(object->metaObject(), argTypeNames.at(ii)); + if (type == QVariant::Invalid) { + if (unknownTypeError) *unknownTypeError = argTypeNames.at(ii); + return 0; + } + dummy[ii + 1] = type; + } + + return dummy.data(); + } +} + +QQmlPropertyData qQmlPropertyCacheCreate(const QMetaObject *metaObject, + const QString &property) +{ + Q_ASSERT(metaObject); + + QQmlPropertyData rv; + { + const QMetaObject *cmo = metaObject; + const QByteArray propertyName = property.toUtf8(); + while (cmo) { + int idx = cmo->indexOfProperty(propertyName); + if (idx != -1) { + QMetaProperty p = cmo->property(idx); + if (p.isScriptable()) { + rv.load(p); + return rv; + } else { + while (cmo && cmo->propertyOffset() >= idx) + cmo = cmo->superClass(); + } + } else { + cmo = 0; + } + } + } + + int methodCount = metaObject->methodCount(); + int defaultMethods = QObject::staticMetaObject.methodCount(); + for (int ii = methodCount - 1; ii >= defaultMethods; --ii) { + // >=defaultMethods to block the signals and slots of QObject::staticMetaObject + // incl. destroyed signals, objectNameChanged signal, deleteLater slot, _q_reregisterTimers slot. + QMetaMethod m = metaObject->method(ii); + if (m.access() == QMetaMethod::Private) + continue; + QString methodName = QString::fromUtf8(m.signature()); + + int parenIdx = methodName.indexOf(QLatin1Char('(')); + Q_ASSERT(parenIdx != -1); + QStringRef methodNameRef = methodName.leftRef(parenIdx); + + if (methodNameRef == property) { + rv.load(m); + return rv; + } + } + + return rv; +} + +inline const QString &qQmlPropertyCacheToString(const QString &string) +{ + return string; +} + +inline QString qQmlPropertyCacheToString(const QHashedV8String &string) +{ + return QV8Engine::toStringStatic(string.string()); +} + +template +QQmlPropertyData * +qQmlPropertyCacheProperty(QQmlEngine *engine, QObject *obj, + const T &name, QQmlPropertyData &local) +{ + QQmlPropertyCache *cache = 0; + + if (engine) { + QQmlData *ddata = QQmlData::get(obj); + + if (ddata && ddata->propertyCache) { + cache = ddata->propertyCache; + } else if (engine) { + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine); + cache = ep->cache(obj); + if (cache) { + ddata = QQmlData::get(obj, true); + cache->addref(); + ddata->propertyCache = cache; + } + } + } + + QQmlPropertyData *rv = 0; + + if (cache) { + rv = cache->property(name); + } else { + local = qQmlPropertyCacheCreate(obj->metaObject(), + qQmlPropertyCacheToString(name)); + if (local.isValid()) + rv = &local; + } + + return rv; +} + +QQmlPropertyData * +QQmlPropertyCache::property(QQmlEngine *engine, QObject *obj, + const QHashedV8String &name, QQmlPropertyData &local) +{ + return qQmlPropertyCacheProperty(engine, obj, name, local); +} + +QQmlPropertyData * +QQmlPropertyCache::property(QQmlEngine *engine, QObject *obj, + const QString &name, QQmlPropertyData &local) +{ + return qQmlPropertyCacheProperty(engine, obj, name, local); +} + +static inline const QMetaObjectPrivate *priv(const uint* data) +{ return reinterpret_cast(data); } + +bool QQmlPropertyCache::isDynamicMetaObject(const QMetaObject *mo) +{ + return priv(mo->d.data)->revision >= 3 && priv(mo->d.data)->flags & DynamicMetaObject; +} + +QT_END_NAMESPACE diff --cc src/qml/qml/qqmlpropertycache_p.h index 095ee79,0000000..a128cd9 mode 100644,000000..100644 --- a/src/qml/qml/qqmlpropertycache_p.h +++ b/src/qml/qml/qqmlpropertycache_p.h @@@ -1,383 -1,0 +1,384 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLPROPERTYCACHE_P_H +#define QQMLPROPERTYCACHE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include "qqmlcleanup_p.h" +#include "qqmlnotifier_p.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QV8Engine; +class QMetaProperty; +class QV8QObjectWrapper; +class QQmlEngine; +class QQmlPropertyData; +class QQmlAccessors; +class QQmlPropertyCacheMethodArguments; + +// We have this somewhat awful split between RawData and Data so that RawData can be +// used in unions. In normal code, you should always use Data which initializes RawData +// to an invalid state on construction. +class QQmlPropertyRawData +{ +public: + enum Flag { + NoFlags = 0x00000000, + ValueTypeFlagMask = 0x0000FFFF, // Flags in valueTypeFlags must fit in this mask + + // Can apply to all properties, except IsFunction + IsConstant = 0x00000001, // Has CONST flag + IsWritable = 0x00000002, // Has WRITE function + IsResettable = 0x00000004, // Has RESET function + IsAlias = 0x00000008, // Is a QML alias to another property + IsFinal = 0x00000010, // Has FINAL flag + IsDirect = 0x00000020, // Exists on a C++ QMetaObject + HasAccessors = 0x00000040, // Has property accessors + + // These are mutualy exclusive + IsFunction = 0x00000080, // Is an invokable + IsQObjectDerived = 0x00000100, // Property type is a QObject* derived type + IsEnumType = 0x00000200, // Property type is an enum + IsQList = 0x00000400, // Property type is a QML list + IsQmlBinding = 0x00000800, // Property type is a QQmlBinding* + IsQJSValue = 0x00001000, // Property type is a QScriptValue + IsV8Handle = 0x00002000, // Property type is a QQmlV8Handle + IsVMEProperty = 0x00004000, // Property type is a "var" property of VMEMO + IsValueTypeVirtual = 0x00008000, // Property is a value type "virtual" property + IsQVariant = 0x00010000, // Property is a QVariant + + // Apply only to IsFunctions + IsVMEFunction = 0x00020000, // Function was added by QML + HasArguments = 0x00040000, // Function takes arguments + IsSignal = 0x00080000, // Function is a signal + IsVMESignal = 0x00100000, // Signal was added by QML + IsV8Function = 0x00200000, // Function takes QQmlV8Function* args + IsSignalHandler = 0x00400000, // Function is a signal handler + IsOverload = 0x00800000, // Function is an overload of another function + + // Internal QQmlPropertyCache flags + NotFullyResolved = 0x01000000 // True if the type data is to be lazily resolved + }; + Q_DECLARE_FLAGS(Flags, Flag) + + Flags getFlags() const { return Flag(flags); } + void setFlags(Flags f) { flags = f; } + + bool isValid() const { return coreIndex != -1; } + + bool isConstant() const { return flags & IsConstant; } + bool isWritable() const { return flags & IsWritable; } + bool isResettable() const { return flags & IsResettable; } + bool isAlias() const { return flags & IsAlias; } + bool isFinal() const { return flags & IsFinal; } + bool isDirect() const { return flags & IsDirect; } + bool hasAccessors() const { return flags & HasAccessors; } + bool isFunction() const { return flags & IsFunction; } + bool isQObject() const { return flags & IsQObjectDerived; } + bool isEnum() const { return flags & IsEnumType; } + bool isQList() const { return flags & IsQList; } + bool isQmlBinding() const { return flags & IsQmlBinding; } + bool isQJSValue() const { return flags & IsQJSValue; } + bool isV8Handle() const { return flags & IsV8Handle; } + bool isVMEProperty() const { return flags & IsVMEProperty; } + bool isValueTypeVirtual() const { return flags & IsValueTypeVirtual; } + bool isQVariant() const { return flags & IsQVariant; } + bool isVMEFunction() const { return flags & IsVMEFunction; } + bool hasArguments() const { return flags & HasArguments; } + bool isSignal() const { return flags & IsSignal; } + bool isVMESignal() const { return flags & IsVMESignal; } + bool isV8Function() const { return flags & IsV8Function; } + bool isSignalHandler() const { return flags & IsSignalHandler; } + bool isOverload() const { return flags & IsOverload; } + + bool hasOverride() const { return !(flags & IsValueTypeVirtual) && + !(flags & HasAccessors) && + overrideIndex >= 0; } ++ bool hasRevision() const { return !(flags & HasAccessors) && revision != 0; } + + // Returns -1 if not a value type virtual property + inline int getValueTypeCoreIndex() const; + + // Returns the "encoded" index for use with bindings. Encoding is: + // coreIndex | (valueTypeCoreIndex << 24) + inline int encodedIndex() const; + + union { + int propType; // When !NotFullyResolved + const char *propTypeName; // When NotFullyResolved + }; + int coreIndex; + union { + int notifyIndex; // When !IsFunction + void *arguments; // When IsFunction && HasArguments + }; + + union { + struct { // When !HasAccessors + qint16 revision; + qint16 metaObjectOffset; + + union { + struct { // When IsValueTypeVirtual + quint16 valueTypeFlags; // flags of the access property on the value type proxy + // object + quint8 valueTypePropType; // The QVariant::Type of access property on the value + // type proxy object + quint8 valueTypeCoreIndex; // The prop index of the access property on the value + // type proxy object + }; + + struct { // When !IsValueTypeVirtual + uint overrideIndexIsProperty : 1; + signed int overrideIndex : 31; + }; + }; + }; + struct { // When HasAccessors + QQmlAccessors *accessors; + intptr_t accessorData; + }; + }; + +private: + friend class QQmlPropertyData; + friend class QQmlPropertyCache; + quint32 flags; +}; +Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlPropertyRawData::Flags); + +class QQmlPropertyData : public QQmlPropertyRawData +{ +public: + inline QQmlPropertyData(); + inline QQmlPropertyData(const QQmlPropertyRawData &); + + inline bool operator==(const QQmlPropertyRawData &); + + static Flags flagsForProperty(const QMetaProperty &, QQmlEngine *engine = 0); + void load(const QMetaProperty &, QQmlEngine *engine = 0); + void load(const QMetaMethod &); + QString name(QObject *); + QString name(const QMetaObject *); + +private: + friend class QQmlPropertyCache; + void lazyLoad(const QMetaProperty &, QQmlEngine *engine = 0); + void lazyLoad(const QMetaMethod &); + bool notFullyResolved() const { return flags & NotFullyResolved; } +}; + +class Q_QML_EXPORT QQmlPropertyCache : public QQmlRefCount, public QQmlCleanup +{ +public: + QQmlPropertyCache(QQmlEngine *); + QQmlPropertyCache(QQmlEngine *, const QMetaObject *); + virtual ~QQmlPropertyCache(); + + void update(QQmlEngine *, const QMetaObject *); + + QQmlPropertyCache *copy(); + + QQmlPropertyCache *copyAndAppend(QQmlEngine *, const QMetaObject *, + QQmlPropertyData::Flag propertyFlags = QQmlPropertyData::NoFlags, + QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags, + QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags); + QQmlPropertyCache *copyAndAppend(QQmlEngine *, const QMetaObject *, int revision, + QQmlPropertyData::Flag propertyFlags = QQmlPropertyData::NoFlags, + QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags, + QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags); + + void append(QQmlEngine *, const QMetaObject *, + QQmlPropertyData::Flag propertyFlags = QQmlPropertyData::NoFlags, + QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags, + QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags); + void append(QQmlEngine *, const QMetaObject *, int revision, + QQmlPropertyData::Flag propertyFlags = QQmlPropertyData::NoFlags, + QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags, + QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags); + + inline QQmlPropertyData *property(const QHashedV8String &) const; + QQmlPropertyData *property(const QHashedStringRef &) const; + QQmlPropertyData *property(const QHashedCStringRef &) const; + QQmlPropertyData *property(const QString &) const; + QQmlPropertyData *property(int) const; + QQmlPropertyData *method(int) const; + QStringList propertyNames() const; + + inline QQmlPropertyData *overrideData(QQmlPropertyData *) const; + inline bool isAllowedInRevision(QQmlPropertyData *) const; + + inline QQmlEngine *qmlEngine() const; + static QQmlPropertyData *property(QQmlEngine *, QObject *, const QString &, + QQmlPropertyData &); + static QQmlPropertyData *property(QQmlEngine *, QObject *, const QHashedV8String &, + QQmlPropertyData &); + static int *methodParameterTypes(QObject *, int index, QVarLengthArray &dummy, + QByteArray *unknownTypeError); + + static bool isDynamicMetaObject(const QMetaObject *); +protected: + virtual void destroy(); + virtual void clear(); + +private: + friend class QQmlEnginePrivate; + friend class QV8QObjectWrapper; + + inline QQmlPropertyCache *copy(int reserve); + + // Implemented in v8/qv8qobjectwrapper.cpp + v8::Local newQObject(QObject *, QV8Engine *); + + typedef QVector IndexCache; + typedef QStringHash StringCache; + typedef QVector AllowedRevisionCache; + + void resolve(QQmlPropertyData *) const; + void updateRecur(QQmlEngine *, const QMetaObject *); + + QQmlEngine *engine; + + QQmlPropertyCache *parent; + int propertyIndexCacheStart; + int methodIndexCacheStart; + int signalHanderIndexCacheStart; + + IndexCache propertyIndexCache; + IndexCache methodIndexCache; + IndexCache signalHandlerIndexCache; + StringCache stringCache; + AllowedRevisionCache allowedRevisionCache; + v8::Persistent constructor; + + const QMetaObject *metaObject; + QQmlPropertyCacheMethodArguments *argumentsCache; +}; + +QQmlPropertyData::QQmlPropertyData() +{ + propType = 0; + coreIndex = -1; + notifyIndex = -1; + overrideIndexIsProperty = false; + overrideIndex = -1; + revision = 0; + metaObjectOffset = -1; + flags = 0; +} + +QQmlPropertyData::QQmlPropertyData(const QQmlPropertyRawData &d) +{ + *(static_cast(this)) = d; +} + +bool QQmlPropertyData::operator==(const QQmlPropertyRawData &other) +{ + return flags == other.flags && + propType == other.propType && + coreIndex == other.coreIndex && + notifyIndex == other.notifyIndex && + revision == other.revision && + (!isValueTypeVirtual() || + (valueTypeCoreIndex == other.valueTypeCoreIndex && + valueTypePropType == other.valueTypePropType)); +} + +int QQmlPropertyRawData::getValueTypeCoreIndex() const +{ + return isValueTypeVirtual()?valueTypeCoreIndex:-1; +} + +int QQmlPropertyRawData::encodedIndex() const +{ + return isValueTypeVirtual()?(coreIndex | (valueTypeCoreIndex << 24)):coreIndex; +} + +QQmlPropertyData * +QQmlPropertyCache::overrideData(QQmlPropertyData *data) const +{ + if (!data->hasOverride()) + return 0; + + if (data->overrideIndexIsProperty) + return property(data->overrideIndex); + else + return method(data->overrideIndex); +} + +bool QQmlPropertyCache::isAllowedInRevision(QQmlPropertyData *data) const +{ + return (data->hasAccessors() || (data->metaObjectOffset == -1 && data->revision == 0)) || + (allowedRevisionCache[data->metaObjectOffset] >= data->revision); +} + +QQmlEngine *QQmlPropertyCache::qmlEngine() const +{ + return engine; +} + +QQmlPropertyData *QQmlPropertyCache::property(const QHashedV8String &str) const +{ + QQmlPropertyData **rv = stringCache.value(str); + if (rv && (*rv)->notFullyResolved()) resolve(*rv); + return rv?*rv:0; +} + +QT_END_NAMESPACE + +#endif // QQMLPROPERTYCACHE_P_H diff --cc src/qml/qml/qqmlpropertyvalueinterceptor_p.h index f8b8643,0000000..cf449c9 mode 100644,000000..100644 --- a/src/qml/qml/qqmlpropertyvalueinterceptor_p.h +++ b/src/qml/qml/qqmlpropertyvalueinterceptor_p.h @@@ -1,74 -1,0 +1,77 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLPROPERTYVALUEINTERCEPTOR_P_H +#define QQMLPROPERTYVALUEINTERCEPTOR_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +QT_BEGIN_NAMESPACE + +class QQmlProperty; +class Q_QML_EXPORT QQmlPropertyValueInterceptor +{ +public: + QQmlPropertyValueInterceptor(); + virtual ~QQmlPropertyValueInterceptor(); + virtual void setTarget(const QQmlProperty &property) = 0; + virtual void write(const QVariant &value) = 0; +}; - Q_DECLARE_INTERFACE(QQmlPropertyValueInterceptor, "com.trolltech.qml.QQmlPropertyValueInterceptor") ++ ++#define QQmlPropertyValueInterceptor_iid "org.qt-project.Qt.QQmlPropertyValueInterceptor" ++ ++Q_DECLARE_INTERFACE(QQmlPropertyValueInterceptor, QQmlPropertyValueInterceptor_iid) + +QT_END_NAMESPACE + +#endif // QQMLPROPERTYVALUEINTERCEPTOR_P_H diff --cc src/qml/qml/qqmlpropertyvaluesource.h index 910b238,0000000..bbd3c2f mode 100644,000000..100644 --- a/src/qml/qml/qqmlpropertyvaluesource.h +++ b/src/qml/qml/qqmlpropertyvaluesource.h @@@ -1,67 -1,0 +1,70 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLPROPERTYVALUESOURCE_H +#define QQMLPROPERTYVALUESOURCE_H + +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + + +class QQmlProperty; +class Q_QML_EXPORT QQmlPropertyValueSource +{ +public: + QQmlPropertyValueSource(); + virtual ~QQmlPropertyValueSource(); + virtual void setTarget(const QQmlProperty &) = 0; +}; - Q_DECLARE_INTERFACE(QQmlPropertyValueSource, "com.trolltech.qml.QQmlPropertyValueSource") ++ ++#define QQmlPropertyValueSource_iid "org.qt-project.Qt.QQmlPropertyValueSource" ++ ++Q_DECLARE_INTERFACE(QQmlPropertyValueSource, QQmlPropertyValueSource_iid) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QQMLPROPERTYVALUESOURCE_H diff --cc src/qml/qml/qqmlrewrite.cpp index 828f7bf,0000000..72bd239 mode 100644,000000..100644 --- a/src/qml/qml/qqmlrewrite.cpp +++ b/src/qml/qml/qqmlrewrite.cpp @@@ -1,441 -1,0 +1,424 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmlrewrite_p.h" + +#include + +#include + +QT_BEGIN_NAMESPACE + +DEFINE_BOOL_CONFIG_OPTION(rewriteDump, QML_REWRITE_DUMP); + +namespace QQmlRewrite { + ++static void rewriteStringLiteral(AST::StringLiteral *ast, const QString *code, int startPosition, TextWriter *writer) ++{ ++ const unsigned position = ast->firstSourceLocation().begin() - startPosition + 1; ++ const unsigned length = ast->literalToken.length - 2; ++ const QStringRef spell = code->midRef(position, length); ++ const int end = spell.size(); ++ int index = 0; ++ ++ while (index < end) { ++ const QChar ch = spell.at(index++); ++ ++ if (index < end && ch == QLatin1Char('\\')) { ++ int pos = index; ++ ++ // skip a possibly empty sequence of \r characters ++ while (pos < end && spell.at(pos) == QLatin1Char('\r')) ++ ++pos; ++ ++ if (pos < end && spell.at(pos) == QLatin1Char('\n')) { ++ // This is a `\' followed by a newline terminator. ++ // In this case there's nothing to replace. We keep the code ++ // as it is and we resume the searching. ++ index = pos + 1; // refresh the index ++ } ++ } else if (ch == QLatin1Char('\r') || ch == QLatin1Char('\n')) { ++ const QString sep = ch == QLatin1Char('\r') ? QLatin1String("\\r") : QLatin1String("\\n"); ++ const int pos = index - 1; ++ QString s = sep; ++ ++ while (index < end && spell.at(index) == ch) { ++ s += sep; ++ ++index; ++ } ++ ++ writer->replace(position + pos, index - pos, s); ++ } ++ } ++} ++ +bool SharedBindingTester::isSharable(const QString &code) +{ + Engine engine; + Lexer lexer(&engine); + Parser parser(&engine); + lexer.setCode(code, 0); + parser.parseStatement(); + if (!parser.statement()) + return false; + + return isSharable(parser.statement()); +} + +bool SharedBindingTester::isSharable(AST::Node *node) +{ + _sharable = true; + AST::Node::acceptChild(node, this); + return _sharable; +} + +QString RewriteBinding::operator()(const QString &code, bool *ok, bool *sharable) +{ + Engine engine; + Lexer lexer(&engine); + Parser parser(&engine); + lexer.setCode(code, 0); + parser.parseStatement(); + if (!parser.statement()) { + if (ok) *ok = false; + return QString(); + } else { + if (ok) *ok = true; + if (sharable) { + SharedBindingTester tester; + *sharable = tester.isSharable(parser.statement()); + } + } + return rewrite(code, 0, parser.statement()); +} + +QString RewriteBinding::operator()(QQmlJS::AST::Node *node, const QString &code, bool *sharable) +{ + if (!node) + return code; + + if (sharable) { + SharedBindingTester tester; + *sharable = tester.isSharable(node); + } + + QQmlJS::AST::ExpressionNode *expression = node->expressionCast(); + QQmlJS::AST::Statement *statement = node->statementCast(); + if(!expression && !statement) + return code; + + TextWriter w; + _writer = &w; + _position = expression ? expression->firstSourceLocation().begin() : statement->firstSourceLocation().begin(); + _inLoop = 0; + _code = &code; + + accept(node); + + unsigned startOfStatement = 0; + unsigned endOfStatement = (expression ? expression->lastSourceLocation().end() : statement->lastSourceLocation().end()) - _position; + + QString startString = QLatin1String("(function ") + _name + QLatin1String("() { "); + if (expression) + startString += QLatin1String("return "); + _writer->replace(startOfStatement, 0, startString); + _writer->replace(endOfStatement, 0, QLatin1String(" })")); + + if (rewriteDump()) { + qWarning() << "============================================================="; + qWarning() << "Rewrote:"; + qWarning() << qPrintable(code); + } + + QString codeCopy = code; + w.write(&codeCopy); + + if (rewriteDump()) { + qWarning() << "To:"; + qWarning() << qPrintable(codeCopy); + qWarning() << "============================================================="; + } + + return codeCopy; +} + +void RewriteBinding::accept(AST::Node *node) +{ + AST::Node::acceptChild(node, this); +} + +QString RewriteBinding::rewrite(QString code, unsigned position, + AST::Statement *node) +{ + TextWriter w; + _writer = &w; + _position = position; + _inLoop = 0; + _code = &code; + + accept(node); + + unsigned startOfStatement = node->firstSourceLocation().begin() - _position; + unsigned endOfStatement = node->lastSourceLocation().end() - _position; + + _writer->replace(startOfStatement, 0, QLatin1String("(function ") + _name + QLatin1String("() { ")); + _writer->replace(endOfStatement, 0, QLatin1String(" })")); + + if (rewriteDump()) { + qWarning() << "============================================================="; + qWarning() << "Rewrote:"; + qWarning() << qPrintable(code); + } + + w.write(&code); + + if (rewriteDump()) { + qWarning() << "To:"; + qWarning() << qPrintable(code); + qWarning() << "============================================================="; + } + + return code; +} + +bool RewriteBinding::visit(AST::Block *ast) +{ + for (AST::StatementList *it = ast->statements; it; it = it->next) { + if (! it->next) { + // we need to rewrite only the last statement of a block. + accept(it->statement); + } + } + + return false; +} + +bool RewriteBinding::visit(AST::ExpressionStatement *ast) +{ + if (! _inLoop) { + unsigned startOfExpressionStatement = ast->firstSourceLocation().begin() - _position; + _writer->replace(startOfExpressionStatement, 0, QLatin1String("return ")); + } + + return false; +} + +bool RewriteBinding::visit(AST::StringLiteral *ast) +{ - /* When rewriting the code for bindings, we have to remove ILLEGAL JS tokens like newlines. - They're still in multi-line strings, because the QML parser allows them, but we have to - rewrite them to be JS compliant. - - For performance reasons, we don't go for total correctness. \r is only replaced if a - \n was found (since most line endings are \n or \r\n) and QChar::LineSeparator is not - even considered. QTBUG-24064. - - Note that rewriteSignalHandler has a function just like this one, for the same reason. - */ - - unsigned startOfString = ast->firstSourceLocation().begin() + 1 - _position; - unsigned stringLength = ast->firstSourceLocation().length - 2; - - int lastIndex = -1; - bool foundNewLine = false; - QStringRef subStr(_code, startOfString, stringLength); - while (true) { - lastIndex = subStr.indexOf(QLatin1Char('\n'), lastIndex + 1); - if (lastIndex == -1) - break; - foundNewLine = true; - _writer->replace(startOfString+lastIndex, 1, QLatin1String("\\n")); - } - - if (foundNewLine) { - while (true) { - lastIndex = subStr.indexOf(QLatin1Char('\r'), lastIndex + 1); - if (lastIndex == -1) - break; - _writer->replace(startOfString+lastIndex, 1, QLatin1String("\\r")); - } - } - ++ rewriteStringLiteral(ast, _code, _position, _writer); + return false; +} + +bool RewriteBinding::visit(AST::DoWhileStatement *) +{ + ++_inLoop; + return true; +} + +void RewriteBinding::endVisit(AST::DoWhileStatement *) +{ + --_inLoop; +} + +bool RewriteBinding::visit(AST::WhileStatement *) +{ + ++_inLoop; + return true; +} + +void RewriteBinding::endVisit(AST::WhileStatement *) +{ + --_inLoop; +} + +bool RewriteBinding::visit(AST::ForStatement *) +{ + ++_inLoop; + return true; +} + +void RewriteBinding::endVisit(AST::ForStatement *) +{ + --_inLoop; +} + +bool RewriteBinding::visit(AST::LocalForStatement *) +{ + ++_inLoop; + return true; +} + +void RewriteBinding::endVisit(AST::LocalForStatement *) +{ + --_inLoop; +} + +bool RewriteBinding::visit(AST::ForEachStatement *) +{ + ++_inLoop; + return true; +} + +void RewriteBinding::endVisit(AST::ForEachStatement *) +{ + --_inLoop; +} + +bool RewriteBinding::visit(AST::LocalForEachStatement *) +{ + ++_inLoop; + return true; +} + +void RewriteBinding::endVisit(AST::LocalForEachStatement *) +{ + --_inLoop; +} + +bool RewriteBinding::visit(AST::CaseBlock *ast) +{ + // Process the initial sequence of the case clauses. + for (AST::CaseClauses *it = ast->clauses; it; it = it->next) { + // Return the value of the last statement in the block, if this is the last `case clause' + // of the switch statement. + bool returnTheValueOfLastStatement = (it->next == 0) && (ast->defaultClause == 0) && (ast->moreClauses == 0); + + if (AST::CaseClause *clause = it->clause) { + accept(clause->expression); + rewriteCaseStatements(clause->statements, returnTheValueOfLastStatement); + } + } + + // Process the default case clause + if (ast->defaultClause) { + // Return the value of the last statement in the block, if this is the last `case clause' + // of the switch statement. + bool rewriteTheLastStatement = (ast->moreClauses == 0); + + rewriteCaseStatements(ast->defaultClause->statements, rewriteTheLastStatement); + } + + // Process trailing `case clauses' + for (AST::CaseClauses *it = ast->moreClauses; it; it = it->next) { + // Return the value of the last statement in the block, if this is the last `case clause' + // of the switch statement. + bool returnTheValueOfLastStatement = (it->next == 0); + + if (AST::CaseClause *clause = it->clause) { + accept(clause->expression); + rewriteCaseStatements(clause->statements, returnTheValueOfLastStatement); + } + } + + return false; +} + +void RewriteBinding::rewriteCaseStatements(AST::StatementList *statements, bool rewriteTheLastStatement) +{ + for (AST::StatementList *it = statements; it; it = it->next) { + if (it->next && AST::cast(it->next->statement) != 0) { + // The value of the first statement followed by a `break'. + accept(it->statement); + break; + } else if (!it->next) { + if (rewriteTheLastStatement) + accept(it->statement); + else if (AST::Block *block = AST::cast(it->statement)) + rewriteCaseStatements(block->statements, rewriteTheLastStatement); + } + } +} + ++RewriteSignalHandler::RewriteSignalHandler() ++ : _writer(0) ++ , _code(0) ++ , _position(0) ++{ ++} ++ +void RewriteSignalHandler::accept(AST::Node *node) +{ + AST::Node::acceptChild(node, this); +} + +bool RewriteSignalHandler::visit(AST::StringLiteral *ast) +{ - unsigned startOfExpressionStatement = ast->firstSourceLocation().begin() - _position; - _strStarts << startOfExpressionStatement + 1; - _strLens << ast->firstSourceLocation().length - 2; - ++ rewriteStringLiteral(ast, _code, _position, _writer); + return false; +} + - void RewriteSignalHandler::rewriteMultilineStrings(QString &code) - { - QList replaceR, replaceN; - for (int i=0; i < _strStarts.count(); i++) { - QStringRef curSubstr = QStringRef(&code, _strStarts[i], _strLens[i]); - int lastIndex = -1; - while (true) { - lastIndex = curSubstr.indexOf(QLatin1Char('\n'), lastIndex + 1); - if (lastIndex == -1) - break; - replaceN << _strStarts[i]+lastIndex; - } - - if (replaceN.count()) { - while (true) { - lastIndex = curSubstr.indexOf(QLatin1Char('\r'), lastIndex + 1); - if (lastIndex == -1) - break; - replaceR << _strStarts[i]+lastIndex; - } - } - } - for (int ii = replaceN.count() - 1; ii >= 0; ii--) - code.replace(replaceN[ii], 1, QLatin1String("\\n")); - if (replaceR.count()) - for (int ii = replaceR.count() - 1; ii >= 0; ii--) - code.replace(replaceR[ii], 1, QLatin1String("\\r")); - } - +QString RewriteSignalHandler::operator()(QQmlJS::AST::Node *node, const QString &code, const QString &name) +{ + if (rewriteDump()) { + qWarning() << "============================================================="; + qWarning() << "Rewrote:"; + qWarning() << qPrintable(code); + } + + QQmlJS::AST::ExpressionNode *expression = node->expressionCast(); + QQmlJS::AST::Statement *statement = node->statementCast(); + if (!expression && !statement) + return code; + - _strStarts.clear(); - _strLens.clear(); ++ TextWriter w; ++ _writer = &w; ++ _code = &code; ++ + _position = expression ? expression->firstSourceLocation().begin() : statement->firstSourceLocation().begin(); + accept(node); + + QString rewritten = code; - rewriteMultilineStrings(rewritten); ++ w.write(&rewritten); + + rewritten = QStringLiteral("(function ") + name + QStringLiteral("() { ") + rewritten + QStringLiteral(" })"); + + if (rewriteDump()) { + qWarning() << "To:"; + qWarning() << qPrintable(rewritten); + qWarning() << "============================================================="; + } + + return rewritten; +} + +} // namespace QQmlRewrite + +QT_END_NAMESPACE diff --cc src/qml/qml/qqmlrewrite_p.h index e915d79,0000000..1d69839 mode 100644,000000..100644 --- a/src/qml/qml/qqmlrewrite_p.h +++ b/src/qml/qml/qqmlrewrite_p.h @@@ -1,149 -1,0 +1,150 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLREWRITE_P_H +#define QQMLREWRITE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace QQmlRewrite { +using namespace QQmlJS; + +class SharedBindingTester : protected AST::Visitor +{ + bool _sharable; +public: + bool isSharable(const QString &code); + bool isSharable(AST::Node *Node); + + virtual bool visit(AST::FunctionDeclaration *) { _sharable = false; return false; } + virtual bool visit(AST::FunctionExpression *) { _sharable = false; return false; } + virtual bool visit(AST::CallExpression *) { _sharable = false; return false; } +}; + +class RewriteBinding: protected AST::Visitor +{ + unsigned _position; + TextWriter *_writer; + QString _name; + const QString *_code; + +public: + QString operator()(const QString &code, bool *ok = 0, bool *sharable = 0); + QString operator()(QQmlJS::AST::Node *node, const QString &code, bool *sharable = 0); + + //name of the function: used for the debugger + void setName(const QString &name) { _name = name; } + +protected: + using AST::Visitor::visit; + + void accept(AST::Node *node); + QString rewrite(QString code, unsigned position, AST::Statement *node); + void rewriteCaseStatements(AST::StatementList *statements, bool rewriteTheLastStatement); + + virtual bool visit(AST::StringLiteral *ast); + virtual bool visit(AST::Block *ast); + virtual bool visit(AST::ExpressionStatement *ast); + + virtual bool visit(AST::DoWhileStatement *ast); + virtual void endVisit(AST::DoWhileStatement *ast); + + virtual bool visit(AST::WhileStatement *ast); + virtual void endVisit(AST::WhileStatement *ast); + + virtual bool visit(AST::ForStatement *ast); + virtual void endVisit(AST::ForStatement *ast); + + virtual bool visit(AST::LocalForStatement *ast); + virtual void endVisit(AST::LocalForStatement *ast); + + virtual bool visit(AST::ForEachStatement *ast); + virtual void endVisit(AST::ForEachStatement *ast); + + virtual bool visit(AST::LocalForEachStatement *ast); + virtual void endVisit(AST::LocalForEachStatement *ast); + + virtual bool visit(AST::CaseBlock *ast); + +private: + int _inLoop; +}; + +class RewriteSignalHandler: protected AST::Visitor +{ - QList _strStarts; - QList _strLens; ++ TextWriter *_writer; ++ const QString *_code; + int _position; + +public: ++ RewriteSignalHandler(); + QString operator()(QQmlJS::AST::Node *node, const QString &code, const QString &name); + +protected: + void rewriteMultilineStrings(QString &code); + + using AST::Visitor::visit; + void accept(AST::Node *node); + virtual bool visit(AST::StringLiteral *ast); +}; + +} // namespace QQmlRewrite + +QT_END_NAMESPACE + +#endif // QQMLREWRITE_P_H + diff --cc src/qml/qml/qqmltypeloader.cpp index cde2885,0000000..5cbb2f6 mode 100644,000000..100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@@ -1,1928 -1,0 +1,1926 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmltypeloader_p.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined (Q_OS_UNIX) +#include +#include +#endif + +// #define DATABLOB_DEBUG + +#ifdef DATABLOB_DEBUG + +#define ASSERT_MAINTHREAD() do { if(m_thread->isThisThread()) qFatal("QQmlDataLoader: Caller not in main thread"); } while(false) +#define ASSERT_LOADTHREAD() do { if(!m_thread->isThisThread()) qFatal("QQmlDataLoader: Caller not in load thread"); } while(false) +#define ASSERT_CALLBACK() do { if(!m_manager || !m_manager->m_thread->isThisThread()) qFatal("QQmlDataBlob: An API call was made outside a callback"); } while(false) + +#else + +#define ASSERT_MAINTHREAD() +#define ASSERT_LOADTHREAD() +#define ASSERT_CALLBACK() + +#endif + +QT_BEGIN_NAMESPACE + +// This is a lame object that we need to ensure that slots connected to +// QNetworkReply get called in the correct thread (the loader thread). +// As QQmlDataLoader lives in the main thread, and we can't use +// Qt::DirectConnection connections from a QNetworkReply (because then +// sender() wont work), we need to insert this object in the middle. +class QQmlDataLoaderNetworkReplyProxy : public QObject +{ + Q_OBJECT +public: + QQmlDataLoaderNetworkReplyProxy(QQmlDataLoader *l); + +public slots: + void finished(); + void downloadProgress(qint64, qint64); + +private: + QQmlDataLoader *l; +}; + +class QQmlDataLoaderThread : public QQmlThread +{ + typedef QQmlDataLoaderThread This; + +public: + QQmlDataLoaderThread(QQmlDataLoader *loader); + QNetworkAccessManager *networkAccessManager() const; + QQmlDataLoaderNetworkReplyProxy *networkReplyProxy() const; + + void load(QQmlDataBlob *b); + void loadAsync(QQmlDataBlob *b); + void loadWithStaticData(QQmlDataBlob *b, const QByteArray &); + void loadWithStaticDataAsync(QQmlDataBlob *b, const QByteArray &); + void callCompleted(QQmlDataBlob *b); + void callDownloadProgressChanged(QQmlDataBlob *b, qreal p); + void initializeEngine(QQmlExtensionInterface *, const char *); + +protected: + virtual void shutdownThread(); + +private: + void loadThread(QQmlDataBlob *b); + void loadWithStaticDataThread(QQmlDataBlob *b, const QByteArray &); + void callCompletedMain(QQmlDataBlob *b); + void callDownloadProgressChangedMain(QQmlDataBlob *b, qreal p); + void initializeEngineMain(QQmlExtensionInterface *iface, const char *uri); + + QQmlDataLoader *m_loader; + mutable QNetworkAccessManager *m_networkAccessManager; + mutable QQmlDataLoaderNetworkReplyProxy *m_networkReplyProxy; +}; + + +QQmlDataLoaderNetworkReplyProxy::QQmlDataLoaderNetworkReplyProxy(QQmlDataLoader *l) +: l(l) +{ +} + +void QQmlDataLoaderNetworkReplyProxy::finished() +{ + Q_ASSERT(sender()); + Q_ASSERT(qobject_cast(sender())); + QNetworkReply *reply = static_cast(sender()); + l->networkReplyFinished(reply); +} + +void QQmlDataLoaderNetworkReplyProxy::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) +{ + Q_ASSERT(sender()); + Q_ASSERT(qobject_cast(sender())); + QNetworkReply *reply = static_cast(sender()); + l->networkReplyProgress(reply, bytesReceived, bytesTotal); +} + +/* +Returns the set of QML files in path (qmldir, *.qml, *.js). The caller +is responsible for deleting the returned data. +Returns 0 if the directory does not exist. +*/ +#if defined (Q_OS_UNIX) && !defined(Q_OS_DARWIN) +static QStringHash *qmlFilesInDirectory(const QString &path) +{ + QByteArray name(QFile::encodeName(path)); + DIR *dd = opendir(name); + if (!dd) + return 0; + + struct dirent *result; + union { + struct dirent d; + char b[offsetof (struct dirent, d_name) + NAME_MAX + 1]; + } u; + + QStringHash *files = new QStringHash; + while (readdir_r(dd, &u.d, &result) == 0 && result != 0) { + if (!strcmp(u.d.d_name, "qmldir")) { + files->insert(QLatin1String("qmldir"), true); + continue; + } + int len = strlen(u.d.d_name); + if (len < 4) + continue; + if (!strcmp(u.d.d_name+len-4, ".qml") || !strcmp(u.d.d_name+len-3, ".js")) + files->insert(QFile::decodeName(u.d.d_name), true); +#if defined(Q_OS_DARWIN) + else if ((len > 6 && !strcmp(u.d.d_name+len-6, ".dylib")) || !strcmp(u.d.d_name+len-3, ".so") + || (len > 7 && !strcmp(u.d.d_name+len-7, ".bundle"))) + files->insert(QFile::decodeName(u.d.d_name), true); +#else // Unix + else if (!strcmp(u.d.d_name+len-3, ".so") || !strcmp(u.d.d_name+len-3, ".sl")) + files->insert(QFile::decodeName(u.d.d_name), true); +#endif + } + + closedir(dd); + return files; +} +#else +static QStringHash *qmlFilesInDirectory(const QString &path) +{ + QDirIterator dir(path, QDir::Files); + if (!dir.hasNext()) + return 0; + QStringHash *files = new QStringHash; + while (dir.hasNext()) { + dir.next(); + QString fileName = dir.fileName(); + if (fileName == QLatin1String("qmldir") + || fileName.endsWith(QLatin1String(".qml")) + || fileName.endsWith(QLatin1String(".js")) +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) + || fileName.endsWith(QLatin1String(".dll")) +#elif defined(Q_OS_DARWIN) + || fileName.endsWith(QLatin1String(".dylib")) + || fileName.endsWith(QLatin1String(".so")) + || fileName.endsWith(QLatin1String(".bundle")) +#else // Unix + || fileName.endsWith(QLatin1String(".so")) + || fileName.endsWith(QLatin1String(".sl")) +#endif + ) { +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_DARWIN) + fileName = fileName.toLower(); +#endif + files->insert(fileName, true); + } + } + return files; +} +#endif + + +/*! +\class QQmlDataBlob +\brief The QQmlDataBlob encapsulates a data request that can be issued to a QQmlDataLoader. +\internal + +QQmlDataBlob's are loaded by a QQmlDataLoader. The user creates the QQmlDataBlob +and then calls QQmlDataLoader::load() or QQmlDataLoader::loadWithStaticData() to load it. +The QQmlDataLoader invokes callbacks on the QQmlDataBlob as data becomes available. +*/ + +/*! +\enum QQmlDataBlob::Status + +This enum describes the status of the data blob. + +\list +\o Null The blob has not yet been loaded by a QQmlDataLoader +\o Loading The blob is loading network data. The QQmlDataBlob::setData() callback has not yet been +invoked or has not yet returned. +\o WaitingForDependencies The blob is waiting for dependencies to be done before continueing. This status +only occurs after the QQmlDataBlob::setData() callback has been made, and when the blob has outstanding +dependencies. +\o Complete The blob's data has been loaded and all dependencies are done. +\o Error An error has been set on this blob. +\endlist +*/ + +/*! +\enum QQmlDataBlob::Type + +This enum describes the type of the data blob. + +\list +\o QmlFile This is a QQmlTypeData +\o JavaScriptFile This is a QQmlScriptData +\o QmldirFile This is a QQmlQmldirData +\endlist +*/ + +/*! +Create a new QQmlDataBlob for \a url and of the provided \a type. +*/ +QQmlDataBlob::QQmlDataBlob(const QUrl &url, Type type) +: m_type(type), m_url(url), m_finalUrl(url), m_manager(0), m_redirectCount(0), + m_inCallback(false), m_isDone(false) +{ +} + +/*! \internal */ +QQmlDataBlob::~QQmlDataBlob() +{ + Q_ASSERT(m_waitingOnMe.isEmpty()); + + cancelAllWaitingFor(); +} + +/*! +Returns the type provided to the constructor. +*/ +QQmlDataBlob::Type QQmlDataBlob::type() const +{ + return m_type; +} + +/*! +Returns the blob's status. +*/ +QQmlDataBlob::Status QQmlDataBlob::status() const +{ + return m_data.status(); +} + +/*! +Returns true if the status is Null. +*/ +bool QQmlDataBlob::isNull() const +{ + return status() == Null; +} + +/*! +Returns true if the status is Loading. +*/ +bool QQmlDataBlob::isLoading() const +{ + return status() == Loading; +} + +/*! +Returns true if the status is WaitingForDependencies. +*/ +bool QQmlDataBlob::isWaiting() const +{ + return status() == WaitingForDependencies; +} + +/*! +Returns true if the status is Complete. +*/ +bool QQmlDataBlob::isComplete() const +{ + return status() == Complete; +} + +/*! +Returns true if the status is Error. +*/ +bool QQmlDataBlob::isError() const +{ + return status() == Error; +} + +/*! +Returns true if the status is Complete or Error. +*/ +bool QQmlDataBlob::isCompleteOrError() const +{ + Status s = status(); + return s == Error || s == Complete; +} + +/*! +Returns the data download progress from 0 to 1. +*/ +qreal QQmlDataBlob::progress() const +{ + quint8 p = m_data.progress(); + if (p == 0xFF) return 1.; + else return qreal(p) / qreal(0xFF); +} + +/*! +Returns the blob url passed to the constructor. If a network redirect +happens while fetching the data, this url remains the same. + +\sa finalUrl() +*/ +QUrl QQmlDataBlob::url() const +{ + return m_url; +} + +/*! +Returns the final url of the data. Initially this is the same as +url(), but if a network redirect happens while fetching the data, this url +is updated to reflect the new location. + +May only be called from the load thread, or after the blob isCompleteOrError(). +*/ +QUrl QQmlDataBlob::finalUrl() const +{ + Q_ASSERT(isCompleteOrError() || (m_manager && m_manager->m_thread->isThisThread())); + return m_finalUrl; +} + +/*! +Returns the finalUrl() as a string. +*/ +QString QQmlDataBlob::finalUrlString() const +{ + Q_ASSERT(isCompleteOrError() || (m_manager && m_manager->m_thread->isThisThread())); + if (m_finalUrlString.isEmpty()) + m_finalUrlString = m_finalUrl.toString(); + + return m_finalUrlString; +} + +/*! +Return the errors on this blob. + +May only be called from the load thread, or after the blob isCompleteOrError(). +*/ +QList QQmlDataBlob::errors() const +{ + Q_ASSERT(isCompleteOrError() || (m_manager && m_manager->m_thread->isThisThread())); + return m_errors; +} + +/*! +Mark this blob as having \a errors. + +All outstanding dependencies will be cancelled. Requests to add new dependencies +will be ignored. Entry into the Error state is irreversable. + +The setError() method may only be called from within a QQmlDataBlob callback. +*/ +void QQmlDataBlob::setError(const QQmlError &errors) +{ + ASSERT_CALLBACK(); + + QList l; + l << errors; + setError(l); +} + +/*! +\overload +*/ +void QQmlDataBlob::setError(const QList &errors) +{ + ASSERT_CALLBACK(); + + Q_ASSERT(status() != Error); + Q_ASSERT(m_errors.isEmpty()); + + m_errors = errors; // Must be set before the m_data fence + m_data.setStatus(Error); + + cancelAllWaitingFor(); + + if (!m_inCallback) + tryDone(); +} + +/*! +Wait for \a blob to become complete or to error. If \a blob is already +complete or in error, or this blob is already complete, this has no effect. + +The setError() method may only be called from within a QQmlDataBlob callback. +*/ +void QQmlDataBlob::addDependency(QQmlDataBlob *blob) +{ + ASSERT_CALLBACK(); + + Q_ASSERT(status() != Null); + + if (!blob || + blob->status() == Error || blob->status() == Complete || + status() == Error || status() == Complete || m_isDone || + m_waitingFor.contains(blob)) + return; + + blob->addref(); + + m_data.setStatus(WaitingForDependencies); + + m_waitingFor.append(blob); + blob->m_waitingOnMe.append(this); +} + +/*! +\fn void QQmlDataBlob::dataReceived(const QByteArray &data) + +Invoked when data for the blob is received. Implementors should use this callback +to determine a blob's dependencies. Within this callback you may call setError() +or addDependency(). +*/ + +/*! +Invoked once data has either been received or a network error occurred, and all +dependencies are complete. + +You can set an error in this method, but you cannot add new dependencies. Implementors +should use this callback to finalize processing of data. + +The default implementation does nothing. + +XXX Rename processData() or some such to avoid confusion between done() (processing thread) +and completed() (main thread) +*/ +void QQmlDataBlob::done() +{ +} + +/*! +Invoked if there is a network error while fetching this blob. + +The default implementation sets an appropriate QQmlError. +*/ +void QQmlDataBlob::networkError(QNetworkReply::NetworkError networkError) +{ + Q_UNUSED(networkError); + + QQmlError error; + error.setUrl(m_finalUrl); + + const char *errorString = 0; + switch (networkError) { + default: + errorString = "Network error"; + break; + case QNetworkReply::ConnectionRefusedError: + errorString = "Connection refused"; + break; + case QNetworkReply::RemoteHostClosedError: + errorString = "Remote host closed the connection"; + break; + case QNetworkReply::HostNotFoundError: + errorString = "Host not found"; + break; + case QNetworkReply::TimeoutError: + errorString = "Timeout"; + break; + case QNetworkReply::ProxyConnectionRefusedError: + case QNetworkReply::ProxyConnectionClosedError: + case QNetworkReply::ProxyNotFoundError: + case QNetworkReply::ProxyTimeoutError: + case QNetworkReply::ProxyAuthenticationRequiredError: + case QNetworkReply::UnknownProxyError: + errorString = "Proxy error"; + break; + case QNetworkReply::ContentAccessDenied: + errorString = "Access denied"; + break; + case QNetworkReply::ContentNotFoundError: + errorString = "File not found"; + break; + case QNetworkReply::AuthenticationRequiredError: + errorString = "Authentication required"; + break; + }; + + error.setDescription(QLatin1String(errorString)); + + setError(error); +} + +/*! +Called if \a blob, which was previously waited for, has an error. + +The default implementation does nothing. +*/ +void QQmlDataBlob::dependencyError(QQmlDataBlob *blob) +{ + Q_UNUSED(blob); +} + +/*! +Called if \a blob, which was previously waited for, has completed. + +The default implementation does nothing. +*/ +void QQmlDataBlob::dependencyComplete(QQmlDataBlob *blob) +{ + Q_UNUSED(blob); +} + +/*! +Called when all blobs waited for have completed. This occurs regardless of +whether they are in error, or complete state. + +The default implementation does nothing. +*/ +void QQmlDataBlob::allDependenciesDone() +{ +} + +/*! +Called when the download progress of this blob changes. \a progress goes +from 0 to 1. + +This callback is only invoked if an asynchronous load for this blob is +made. An asynchronous load is one in which the Asynchronous mode is +specified explicitly, or one that is implicitly delayed due to a network +operation. + +The default implementation does nothing. +*/ +void QQmlDataBlob::downloadProgressChanged(qreal progress) +{ + Q_UNUSED(progress); +} + +/*! +Invoked on the main thread sometime after done() was called on the load thread. + +You cannot modify the blobs state at all in this callback and cannot depend on the +order or timeliness of these callbacks. Implementors should use this callback to notify +dependencies on the main thread that the blob is done and not a lot else. + +This callback is only invoked if an asynchronous load for this blob is +made. An asynchronous load is one in which the Asynchronous mode is +specified explicitly, or one that is implicitly delayed due to a network +operation. + +The default implementation does nothing. +*/ +void QQmlDataBlob::completed() +{ +} + + +void QQmlDataBlob::tryDone() +{ + if (status() != Loading && m_waitingFor.isEmpty() && !m_isDone) { + m_isDone = true; + addref(); + +#ifdef DATABLOB_DEBUG + qWarning("QQmlDataBlob::done() %s", qPrintable(url().toString())); +#endif + done(); + + if (status() != Error) + m_data.setStatus(Complete); + + notifyAllWaitingOnMe(); + + // Locking is not required here, as anyone expecting callbacks must + // already be protected against the blob being completed (as set above); + if (m_data.isAsync()) { +#ifdef DATABLOB_DEBUG + qWarning("QQmlDataBlob: Dispatching completed"); +#endif + m_manager->m_thread->callCompleted(this); + } + + release(); + } +} + +void QQmlDataBlob::cancelAllWaitingFor() +{ + while (m_waitingFor.count()) { + QQmlDataBlob *blob = m_waitingFor.takeLast(); + + Q_ASSERT(blob->m_waitingOnMe.contains(this)); + + blob->m_waitingOnMe.removeOne(this); + + blob->release(); + } +} + +void QQmlDataBlob::notifyAllWaitingOnMe() +{ + while (m_waitingOnMe.count()) { + QQmlDataBlob *blob = m_waitingOnMe.takeLast(); + + Q_ASSERT(blob->m_waitingFor.contains(this)); + + blob->notifyComplete(this); + } +} + +void QQmlDataBlob::notifyComplete(QQmlDataBlob *blob) +{ + Q_ASSERT(m_waitingFor.contains(blob)); + Q_ASSERT(blob->status() == Error || blob->status() == Complete); + + m_inCallback = true; + + if (blob->status() == Error) { + dependencyError(blob); + } else if (blob->status() == Complete) { + dependencyComplete(blob); + } + + m_waitingFor.removeOne(blob); + blob->release(); + + if (!isError() && m_waitingFor.isEmpty()) + allDependenciesDone(); + + m_inCallback = false; + + tryDone(); +} + +#define TD_STATUS_MASK 0x0000FFFF +#define TD_STATUS_SHIFT 0 +#define TD_PROGRESS_MASK 0x00FF0000 +#define TD_PROGRESS_SHIFT 16 +#define TD_ASYNC_MASK 0x80000000 + +QQmlDataBlob::ThreadData::ThreadData() +: _p(0) +{ +} + +QQmlDataBlob::Status QQmlDataBlob::ThreadData::status() const +{ + return QQmlDataBlob::Status((_p.load() & TD_STATUS_MASK) >> TD_STATUS_SHIFT); +} + +void QQmlDataBlob::ThreadData::setStatus(QQmlDataBlob::Status status) +{ + while (true) { + int d = _p.load(); + int nd = (d & ~TD_STATUS_MASK) | ((status << TD_STATUS_SHIFT) & TD_STATUS_MASK); + if (d == nd || _p.testAndSetOrdered(d, nd)) return; + } +} + +bool QQmlDataBlob::ThreadData::isAsync() const +{ + return _p.load() & TD_ASYNC_MASK; +} + +void QQmlDataBlob::ThreadData::setIsAsync(bool v) +{ + while (true) { + int d = _p.load(); + int nd = (d & ~TD_ASYNC_MASK) | (v?TD_ASYNC_MASK:0); + if (d == nd || _p.testAndSetOrdered(d, nd)) return; + } +} + +quint8 QQmlDataBlob::ThreadData::progress() const +{ + return quint8((_p.load() & TD_PROGRESS_MASK) >> TD_PROGRESS_SHIFT); +} + +void QQmlDataBlob::ThreadData::setProgress(quint8 v) +{ + while (true) { + int d = _p.load(); + int nd = (d & ~TD_PROGRESS_MASK) | ((v << TD_PROGRESS_SHIFT) & TD_PROGRESS_MASK); + if (d == nd || _p.testAndSetOrdered(d, nd)) return; + } +} + +QQmlDataLoaderThread::QQmlDataLoaderThread(QQmlDataLoader *loader) +: m_loader(loader), m_networkAccessManager(0), m_networkReplyProxy(0) +{ +} + +QNetworkAccessManager *QQmlDataLoaderThread::networkAccessManager() const +{ + Q_ASSERT(isThisThread()); + if (!m_networkAccessManager) { + m_networkAccessManager = QQmlEnginePrivate::get(m_loader->engine())->createNetworkAccessManager(0); + m_networkReplyProxy = new QQmlDataLoaderNetworkReplyProxy(m_loader); + } + + return m_networkAccessManager; +} + +QQmlDataLoaderNetworkReplyProxy *QQmlDataLoaderThread::networkReplyProxy() const +{ + Q_ASSERT(isThisThread()); + Q_ASSERT(m_networkReplyProxy); // Must call networkAccessManager() first + return m_networkReplyProxy; +} + +void QQmlDataLoaderThread::load(QQmlDataBlob *b) +{ + b->addref(); + callMethodInThread(&This::loadThread, b); +} + +void QQmlDataLoaderThread::loadAsync(QQmlDataBlob *b) +{ + b->addref(); + postMethodToThread(&This::loadThread, b); +} + +void QQmlDataLoaderThread::loadWithStaticData(QQmlDataBlob *b, const QByteArray &d) +{ + b->addref(); + callMethodInThread(&This::loadWithStaticDataThread, b, d); +} + +void QQmlDataLoaderThread::loadWithStaticDataAsync(QQmlDataBlob *b, const QByteArray &d) +{ + b->addref(); + postMethodToThread(&This::loadWithStaticDataThread, b, d); +} + +void QQmlDataLoaderThread::callCompleted(QQmlDataBlob *b) +{ + b->addref(); + postMethodToMain(&This::callCompletedMain, b); +} + +void QQmlDataLoaderThread::callDownloadProgressChanged(QQmlDataBlob *b, qreal p) +{ + b->addref(); + postMethodToMain(&This::callDownloadProgressChangedMain, b, p); +} + +void QQmlDataLoaderThread::initializeEngine(QQmlExtensionInterface *iface, + const char *uri) +{ + callMethodInMain(&This::initializeEngineMain, iface, uri); +} + +void QQmlDataLoaderThread::shutdownThread() +{ + delete m_networkAccessManager; + m_networkAccessManager = 0; + delete m_networkReplyProxy; + m_networkReplyProxy = 0; +} + +void QQmlDataLoaderThread::loadThread(QQmlDataBlob *b) +{ + m_loader->loadThread(b); + b->release(); +} + +void QQmlDataLoaderThread::loadWithStaticDataThread(QQmlDataBlob *b, const QByteArray &d) +{ + m_loader->loadWithStaticDataThread(b, d); + b->release(); +} + +void QQmlDataLoaderThread::callCompletedMain(QQmlDataBlob *b) +{ +#ifdef DATABLOB_DEBUG + qWarning("QQmlDataLoaderThread: %s completed() callback", qPrintable(b->url().toString())); +#endif + b->completed(); + b->release(); +} + +void QQmlDataLoaderThread::callDownloadProgressChangedMain(QQmlDataBlob *b, qreal p) +{ +#ifdef DATABLOB_DEBUG + qWarning("QQmlDataLoaderThread: %s downloadProgressChanged(%f) callback", + qPrintable(b->url().toString()), p); +#endif + b->downloadProgressChanged(p); + b->release(); +} + +void QQmlDataLoaderThread::initializeEngineMain(QQmlExtensionInterface *iface, + const char *uri) +{ + Q_ASSERT(m_loader->engine()->thread() == QThread::currentThread()); + iface->initializeEngine(m_loader->engine(), uri); +} + +/*! +\class QQmlDataLoader +\brief The QQmlDataLoader class abstracts loading files and their dependencies over the network. +\internal + +The QQmlDataLoader class is provided for the exclusive use of the QQmlTypeLoader class. + +Clients create QQmlDataBlob instances and submit them to the QQmlDataLoader class +through the QQmlDataLoader::load() or QQmlDataLoader::loadWithStaticData() methods. +The loader then fetches the data over the network or from the local file system in an efficient way. +QQmlDataBlob is an abstract class, so should always be specialized. + +Once data is received, the QQmlDataBlob::dataReceived() method is invoked on the blob. The +derived class should use this callback to process the received data. Processing of the data can +result in an error being set (QQmlDataBlob::setError()), or one or more dependencies being +created (QQmlDataBlob::addDependency()). Dependencies are other QQmlDataBlob's that +are required before processing can fully complete. + +To complete processing, the QQmlDataBlob::done() callback is invoked. done() is called when +one of these three preconditions are met. + +\list 1 +\o The QQmlDataBlob has no dependencies. +\o The QQmlDataBlob has an error set. +\o All the QQmlDataBlob's dependencies are themselves "done()". +\endlist + +Thus QQmlDataBlob::done() will always eventually be called, even if the blob has an error set. +*/ + +/*! +Create a new QQmlDataLoader for \a engine. +*/ +QQmlDataLoader::QQmlDataLoader(QQmlEngine *engine) +: m_engine(engine), m_thread(new QQmlDataLoaderThread(this)) +{ +} + +/*! \internal */ +QQmlDataLoader::~QQmlDataLoader() +{ + for (NetworkReplies::Iterator iter = m_networkReplies.begin(); iter != m_networkReplies.end(); ++iter) + (*iter)->release(); + + m_thread->shutdown(); + delete m_thread; +} + +void QQmlDataLoader::lock() +{ + m_thread->lock(); +} + +void QQmlDataLoader::unlock() +{ + m_thread->unlock(); +} + +/*! +Load the provided \a blob from the network or filesystem. + +The loader must be locked. +*/ +void QQmlDataLoader::load(QQmlDataBlob *blob, Mode mode) +{ +#ifdef DATABLOB_DEBUG + qWarning("QQmlDataLoader::load(%s): %s thread", qPrintable(blob->m_url.toString()), + m_thread->isThisThread()?"Compile":"Engine"); +#endif + + Q_ASSERT(blob->status() == QQmlDataBlob::Null); + Q_ASSERT(blob->m_manager == 0); + + blob->m_data.setStatus(QQmlDataBlob::Loading); + blob->m_manager = this; + + if (m_thread->isThisThread()) { + unlock(); + loadThread(blob); + lock(); + } else if (mode == PreferSynchronous) { + unlock(); + m_thread->load(blob); + lock(); + if (!blob->isCompleteOrError()) + blob->m_data.setIsAsync(true); + } else { + Q_ASSERT(mode == Asynchronous); + blob->m_data.setIsAsync(true); + unlock(); + m_thread->loadAsync(blob); + lock(); + } +} + +/*! +Load the provided \a blob with \a data. The blob's URL is not used by the data loader in this case. + +The loader must be locked. +*/ +void QQmlDataLoader::loadWithStaticData(QQmlDataBlob *blob, const QByteArray &data, Mode mode) +{ +#ifdef DATABLOB_DEBUG + qWarning("QQmlDataLoader::loadWithStaticData(%s, data): %s thread", qPrintable(blob->m_url.toString()), + m_thread->isThisThread()?"Compile":"Engine"); +#endif + + Q_ASSERT(blob->status() == QQmlDataBlob::Null); + Q_ASSERT(blob->m_manager == 0); + + blob->m_data.setStatus(QQmlDataBlob::Loading); + blob->m_manager = this; + + if (m_thread->isThisThread()) { + unlock(); + loadWithStaticDataThread(blob, data); + lock(); + } else if (mode == PreferSynchronous) { + unlock(); + m_thread->loadWithStaticData(blob, data); + lock(); + if (!blob->isCompleteOrError()) + blob->m_data.setIsAsync(true); + } else { + Q_ASSERT(mode == Asynchronous); + blob->m_data.setIsAsync(true); + unlock(); + m_thread->loadWithStaticDataAsync(blob, data); + lock(); + } +} + +void QQmlDataLoader::loadWithStaticDataThread(QQmlDataBlob *blob, const QByteArray &data) +{ + ASSERT_LOADTHREAD(); + + setData(blob, data); +} + +void QQmlDataLoader::loadThread(QQmlDataBlob *blob) +{ + ASSERT_LOADTHREAD(); + + if (blob->m_url.isEmpty()) { + QQmlError error; + error.setDescription(QLatin1String("Invalid null URL")); + blob->setError(error); + return; + } + + QString lf = QQmlEnginePrivate::urlToLocalFileOrQrc(blob->m_url); + + if (!lf.isEmpty()) { + if (!QQml_isFileCaseCorrect(lf)) { + QQmlError error; + error.setUrl(blob->m_url); + error.setDescription(QLatin1String("File name case mismatch")); + blob->setError(error); + return; + } + QFile file(lf); + if (file.open(QFile::ReadOnly)) { + QByteArray data = file.readAll(); + + blob->m_data.setProgress(0xFF); + if (blob->m_data.isAsync()) + m_thread->callDownloadProgressChanged(blob, 1.); + + setData(blob, data); + } else { + blob->networkError(QNetworkReply::ContentNotFoundError); + } + + } else { + + QNetworkReply *reply = m_thread->networkAccessManager()->get(QNetworkRequest(blob->m_url)); + QObject *nrp = m_thread->networkReplyProxy(); + QObject::connect(reply, SIGNAL(downloadProgress(qint64,qint64)), + nrp, SLOT(downloadProgress(qint64,qint64))); + QObject::connect(reply, SIGNAL(finished()), + nrp, SLOT(finished())); + m_networkReplies.insert(reply, blob); + + blob->addref(); + } +} + +#define DATALOADER_MAXIMUM_REDIRECT_RECURSION 16 + +void QQmlDataLoader::networkReplyFinished(QNetworkReply *reply) +{ + Q_ASSERT(m_thread->isThisThread()); + + reply->deleteLater(); + + QQmlDataBlob *blob = m_networkReplies.take(reply); + + Q_ASSERT(blob); + + blob->m_redirectCount++; + + if (blob->m_redirectCount < DATALOADER_MAXIMUM_REDIRECT_RECURSION) { + QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); + if (redirect.isValid()) { + QUrl url = reply->url().resolved(redirect.toUrl()); + blob->m_finalUrl = url; + + QNetworkReply *reply = m_thread->networkAccessManager()->get(QNetworkRequest(url)); + QObject *nrp = m_thread->networkReplyProxy(); + QObject::connect(reply, SIGNAL(finished()), nrp, SLOT(finished())); + m_networkReplies.insert(reply, blob); + return; + } + } + + if (reply->error()) { + blob->networkError(reply->error()); + } else { + QByteArray data = reply->readAll(); + setData(blob, data); + } + + blob->release(); +} + +void QQmlDataLoader::networkReplyProgress(QNetworkReply *reply, + qint64 bytesReceived, qint64 bytesTotal) +{ + Q_ASSERT(m_thread->isThisThread()); + + QQmlDataBlob *blob = m_networkReplies.value(reply); + + Q_ASSERT(blob); + + if (bytesTotal != 0) { + quint8 progress = 0xFF * (qreal(bytesReceived) / qreal(bytesTotal)); + blob->m_data.setProgress(progress); + if (blob->m_data.isAsync()) + m_thread->callDownloadProgressChanged(blob, blob->m_data.progress()); + } +} + +/*! +Return the QQmlEngine associated with this loader +*/ +QQmlEngine *QQmlDataLoader::engine() const +{ + return m_engine; +} + +/*! +Call the initializeEngine() method on \a iface. Used by QQmlImportDatabase to ensure it +gets called in the correct thread. +*/ +void QQmlDataLoader::initializeEngine(QQmlExtensionInterface *iface, + const char *uri) +{ + Q_ASSERT(m_thread->isThisThread() || engine()->thread() == QThread::currentThread()); + + if (m_thread->isThisThread()) { + m_thread->initializeEngine(iface, uri); + } else { + Q_ASSERT(engine()->thread() == QThread::currentThread()); + iface->initializeEngine(engine(), uri); + } +} + + +void QQmlDataLoader::setData(QQmlDataBlob *blob, const QByteArray &data) +{ + blob->m_inCallback = true; + + blob->dataReceived(data); + + if (!blob->isError() && !blob->isWaiting()) + blob->allDependenciesDone(); + + if (blob->status() != QQmlDataBlob::Error) + blob->m_data.setStatus(QQmlDataBlob::WaitingForDependencies); + + blob->m_inCallback = false; + + blob->tryDone(); +} + +/*! +Constructs a new type loader that uses the given \a engine. +*/ +QQmlTypeLoader::QQmlTypeLoader(QQmlEngine *engine) +: QQmlDataLoader(engine) +{ +} + +/*! +Destroys the type loader, first clearing the cache of any information about +loaded files. +*/ +QQmlTypeLoader::~QQmlTypeLoader() +{ + clearCache(); +} + +/*! +\enum QQmlTypeLoader::Option + +This enum defines the options that control the way type data is handled. + +\value None The default value, indicating that no other options + are enabled. +\value PreserveParser The parser used to handle the type data is preserved + after the data has been parsed. +*/ + +/*! +Returns a QQmlTypeData for the specified \a url. The QQmlTypeData may be cached. +*/ +QQmlTypeData *QQmlTypeLoader::get(const QUrl &url) +{ + Q_ASSERT(!url.isRelative() && + (QQmlEnginePrivate::urlToLocalFileOrQrc(url).isEmpty() || + !QDir::isRelativePath(QQmlEnginePrivate::urlToLocalFileOrQrc(url)))); + + lock(); + + QQmlTypeData *typeData = m_typeCache.value(url); + + if (!typeData) { + typeData = new QQmlTypeData(url, None, this); + m_typeCache.insert(url, typeData); + QQmlDataLoader::load(typeData); + } + + typeData->addref(); + + unlock(); + + return typeData; +} + +/*! +Returns a QQmlTypeData for the given \a data with the provided base \a url. The +QQmlTypeData will not be cached. + +The specified \a options control how the loader handles type data. +*/ +QQmlTypeData *QQmlTypeLoader::get(const QByteArray &data, const QUrl &url, Options options) +{ + lock(); + + QQmlTypeData *typeData = new QQmlTypeData(url, options, this); + QQmlDataLoader::loadWithStaticData(typeData, data); + + unlock(); + + return typeData; +} + +/*! +Return a QQmlScriptBlob for \a url. The QQmlScriptData may be cached. +*/ +QQmlScriptBlob *QQmlTypeLoader::getScript(const QUrl &url) +{ + Q_ASSERT(!url.isRelative() && + (QQmlEnginePrivate::urlToLocalFileOrQrc(url).isEmpty() || + !QDir::isRelativePath(QQmlEnginePrivate::urlToLocalFileOrQrc(url)))); + + lock(); + + QQmlScriptBlob *scriptBlob = m_scriptCache.value(url); + + if (!scriptBlob) { + scriptBlob = new QQmlScriptBlob(url, this); + m_scriptCache.insert(url, scriptBlob); + QQmlDataLoader::load(scriptBlob); + } + + scriptBlob->addref(); + + unlock(); + + return scriptBlob; +} + +/*! +Returns a QQmlQmldirData for \a url. The QQmlQmldirData may be cached. +*/ +QQmlQmldirData *QQmlTypeLoader::getQmldir(const QUrl &url) +{ + Q_ASSERT(!url.isRelative() && + (QQmlEnginePrivate::urlToLocalFileOrQrc(url).isEmpty() || + !QDir::isRelativePath(QQmlEnginePrivate::urlToLocalFileOrQrc(url)))); + + lock(); + + QQmlQmldirData *qmldirData = m_qmldirCache.value(url); + + if (!qmldirData) { + qmldirData = new QQmlQmldirData(url); + m_qmldirCache.insert(url, qmldirData); + QQmlDataLoader::load(qmldirData); + } + + qmldirData->addref(); + + unlock(); + + return qmldirData; +} + +/*! +Returns the absolute filename of path via a directory cache for files named +"qmldir", "*.qml", "*.js", and plugins. +Returns a empty string if the path does not exist. +*/ +QString QQmlTypeLoader::absoluteFilePath(const QString &path) +{ + if (path.isEmpty()) + return QString(); + if (path.at(0) == QLatin1Char(':')) { + // qrc resource + QFileInfo fileInfo(path); + return fileInfo.isFile() ? fileInfo.absoluteFilePath() : QString(); + } +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_DARWIN) + QString lowPath = path.toLower(); + int lastSlash = lowPath.lastIndexOf(QLatin1Char('/')); + QString dirPath = lowPath.left(lastSlash); +#else + int lastSlash = path.lastIndexOf(QLatin1Char('/')); + QStringRef dirPath(&path, 0, lastSlash); +#endif + + StringSet **fileSet = m_importDirCache.value(QHashedStringRef(dirPath.constData(), dirPath.length())); + if (!fileSet) { +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_DARWIN) + QHashedString dirPathString(dirPath); +#else + QHashedString dirPathString(dirPath.toString()); +#endif + StringSet *files = qmlFilesInDirectory(dirPathString); + m_importDirCache.insert(dirPathString, files); + fileSet = m_importDirCache.value(dirPathString); + } + if (!(*fileSet)) + return QString(); + +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_DARWIN) + QString absoluteFilePath = (*fileSet)->contains(QHashedStringRef(lowPath.constData()+lastSlash+1, lowPath.length()-lastSlash-1)) ? path : QString(); +#else + QString absoluteFilePath = (*fileSet)->contains(QHashedStringRef(path.constData()+lastSlash+1, path.length()-lastSlash-1)) ? path : QString(); +#endif + if (absoluteFilePath.length() > 2 && absoluteFilePath.at(0) != QLatin1Char('/') && absoluteFilePath.at(1) != QLatin1Char(':')) + absoluteFilePath = QFileInfo(absoluteFilePath).absoluteFilePath(); + + return absoluteFilePath; +} + +/*! +Returns true if the path is a directory via a directory cache. Cache is +shared with absoluteFilePath(). +*/ +bool QQmlTypeLoader::directoryExists(const QString &path) +{ + if (path.isEmpty()) + return false; + if (path.at(0) == QLatin1Char(':')) { + // qrc resource + QFileInfo fileInfo(path); + return fileInfo.exists() && fileInfo.isDir(); + } + + int length = path.length(); + if (path.endsWith(QLatin1Char('/'))) + --length; +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_DARWIN) + QString dirPath = path.left(length).toLower(); +#else + QStringRef dirPath(&path, 0, length); +#endif + + StringSet **fileSet = m_importDirCache.value(QHashedStringRef(dirPath.constData(), dirPath.length())); + if (!fileSet) { +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_DARWIN) + QHashedString dirPathString(dirPath); +#else + QHashedString dirPathString(dirPath.toString()); +#endif + StringSet *files = qmlFilesInDirectory(dirPathString); + m_importDirCache.insert(dirPathString, files); + fileSet = m_importDirCache.value(dirPathString); + } + + return (*fileSet); +} + + +/*! +Return a QQmlDirParser for absoluteFilePath. The QQmlDirParser may be cached. +*/ +const QQmlDirParser *QQmlTypeLoader::qmlDirParser(const QString &absoluteFilePath) +{ + QQmlDirParser *qmldirParser; + QQmlDirParser **val = m_importQmlDirCache.value(absoluteFilePath); + if (!val) { + qmldirParser = new QQmlDirParser; + qmldirParser->setFileSource(absoluteFilePath); + qmldirParser->setUrl(QUrl::fromLocalFile(absoluteFilePath)); + qmldirParser->parse(); + m_importQmlDirCache.insert(absoluteFilePath, qmldirParser); + } else { + qmldirParser = *val; + } + + return qmldirParser; +} + + +/*! +Clears cached information about loaded files, including any type data, scripts +and qmldir information. +*/ +void QQmlTypeLoader::clearCache() +{ + for (TypeCache::Iterator iter = m_typeCache.begin(); iter != m_typeCache.end(); ++iter) + (*iter)->release(); + for (ScriptCache::Iterator iter = m_scriptCache.begin(); iter != m_scriptCache.end(); ++iter) + (*iter)->release(); + for (QmldirCache::Iterator iter = m_qmldirCache.begin(); iter != m_qmldirCache.end(); ++iter) + (*iter)->release(); + qDeleteAll(m_importDirCache); + qDeleteAll(m_importQmlDirCache); + + m_typeCache.clear(); + m_scriptCache.clear(); + m_qmldirCache.clear(); + m_importDirCache.clear(); + m_importQmlDirCache.clear(); +} + + +QQmlTypeData::QQmlTypeData(const QUrl &url, QQmlTypeLoader::Options options, + QQmlTypeLoader *manager) +: QQmlDataBlob(url, QmlFile), m_options(options), m_imports(manager), m_typesResolved(false), + m_compiledData(0), m_typeLoader(manager) +{ +} + +QQmlTypeData::~QQmlTypeData() +{ + for (int ii = 0; ii < m_scripts.count(); ++ii) + m_scripts.at(ii).script->release(); + for (int ii = 0; ii < m_qmldirs.count(); ++ii) + m_qmldirs.at(ii)->release(); + for (int ii = 0; ii < m_types.count(); ++ii) + if (m_types.at(ii).typeData) m_types.at(ii).typeData->release(); + if (m_compiledData) + m_compiledData->release(); +} + +QQmlTypeLoader *QQmlTypeData::typeLoader() const +{ + return m_typeLoader; +} + +const QQmlImports &QQmlTypeData::imports() const +{ + return m_imports; +} + +const QQmlScript::Parser &QQmlTypeData::parser() const +{ + return scriptParser; +} + +const QList &QQmlTypeData::resolvedTypes() const +{ + return m_types; +} + +const QList &QQmlTypeData::resolvedScripts() const +{ + return m_scripts; +} + +const QSet &QQmlTypeData::namespaces() const +{ + return m_namespaces; +} + +QQmlCompiledData *QQmlTypeData::compiledData() const +{ + if (m_compiledData) + m_compiledData->addref(); + + return m_compiledData; +} + +void QQmlTypeData::registerCallback(TypeDataCallback *callback) +{ + Q_ASSERT(!m_callbacks.contains(callback)); + m_callbacks.append(callback); +} + +void QQmlTypeData::unregisterCallback(TypeDataCallback *callback) +{ + Q_ASSERT(m_callbacks.contains(callback)); + m_callbacks.removeOne(callback); + Q_ASSERT(!m_callbacks.contains(callback)); +} + +void QQmlTypeData::done() +{ + // Check all script dependencies for errors + for (int ii = 0; !isError() && ii < m_scripts.count(); ++ii) { + const ScriptReference &script = m_scripts.at(ii); + Q_ASSERT(script.script->isCompleteOrError()); + if (script.script->isError()) { + QList errors = script.script->errors(); + QQmlError error; + error.setUrl(finalUrl()); + error.setLine(script.location.line); + error.setColumn(script.location.column); + error.setDescription(QQmlTypeLoader::tr("Script %1 unavailable").arg(script.script->url().toString())); + errors.prepend(error); + setError(errors); + } + } + + // Check all type dependencies for errors + for (int ii = 0; !isError() && ii < m_types.count(); ++ii) { + const TypeReference &type = m_types.at(ii); + Q_ASSERT(!type.typeData || type.typeData->isCompleteOrError()); + if (type.typeData && type.typeData->isError()) { + QString typeName = scriptParser.referencedTypes().at(ii)->name; + + QList errors = type.typeData->errors(); + QQmlError error; + error.setUrl(finalUrl()); + error.setLine(type.location.line); + error.setColumn(type.location.column); + error.setDescription(QQmlTypeLoader::tr("Type %1 unavailable").arg(typeName)); + errors.prepend(error); + setError(errors); + } + } + + // Compile component + if (!isError()) + compile(); + + if (!(m_options & QQmlTypeLoader::PreserveParser)) + scriptParser.clear(); +} + +void QQmlTypeData::completed() +{ + // Notify callbacks + while (!m_callbacks.isEmpty()) { + TypeDataCallback *callback = m_callbacks.takeFirst(); + callback->typeDataReady(this); + } +} + +void QQmlTypeData::dataReceived(const QByteArray &data) +{ + if (!scriptParser.parse(data, finalUrl(), finalUrlString())) { + setError(scriptParser.errors()); + return; + } + + m_imports.setBaseUrl(finalUrl(), finalUrlString()); + + foreach (const QQmlScript::Import &import, scriptParser.imports()) { + if (import.type == QQmlScript::Import::File && import.qualifier.isEmpty()) { + QUrl importUrl = finalUrl().resolved(QUrl(import.uri + QLatin1String("/qmldir"))); + if (QQmlEnginePrivate::urlToLocalFileOrQrc(importUrl).isEmpty()) { + QQmlQmldirData *data = typeLoader()->getQmldir(importUrl); + addDependency(data); + m_qmldirs << data; + } + } else if (import.type == QQmlScript::Import::Script) { + QUrl scriptUrl = finalUrl().resolved(QUrl(import.uri)); + QQmlScriptBlob *blob = typeLoader()->getScript(scriptUrl); + addDependency(blob); + + ScriptReference ref; + ref.location = import.location.start; + ref.qualifier = import.qualifier; + ref.script = blob; + m_scripts << ref; + + } + } + + if (!finalUrl().scheme().isEmpty()) { + QUrl importUrl = finalUrl().resolved(QUrl(QLatin1String("qmldir"))); + if (QQmlEnginePrivate::urlToLocalFileOrQrc(importUrl).isEmpty()) { + QQmlQmldirData *data = typeLoader()->getQmldir(importUrl); + addDependency(data); + m_qmldirs << data; + } + } +} + +void QQmlTypeData::allDependenciesDone() +{ + if (!m_typesResolved) { + resolveTypes(); + m_typesResolved = true; + } +} + +void QQmlTypeData::downloadProgressChanged(qreal p) +{ + for (int ii = 0; ii < m_callbacks.count(); ++ii) { + TypeDataCallback *callback = m_callbacks.at(ii); + callback->typeDataProgress(this, p); + } +} + +void QQmlTypeData::compile() +{ + Q_ASSERT(m_compiledData == 0); - QQmlProfilerService::startRange(QQmlProfilerService::Compiling); + + m_compiledData = new QQmlCompiledData(typeLoader()->engine()); + m_compiledData->url = finalUrl(); + m_compiledData->name = finalUrlString(); - QQmlProfilerService::rangeLocation(QQmlProfilerService::Compiling, QUrl(m_compiledData->name),1,1); - QQmlProfilerService::rangeData(QQmlProfilerService::Compiling, m_compiledData->name); ++ ++ QQmlCompilingProfiler prof(m_compiledData->name); + + QQmlCompiler compiler(&scriptParser._pool); + if (!compiler.compile(typeLoader()->engine(), this, m_compiledData)) { + setError(compiler.errors()); + m_compiledData->release(); + m_compiledData = 0; + } - QQmlProfilerService::endRange(QQmlProfilerService::Compiling); +} + +void QQmlTypeData::resolveTypes() +{ + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(m_typeLoader->engine()); + QQmlImportDatabase *importDatabase = &ep->importDatabase; + + // For local urls, add an implicit import "." as first (most overridden) lookup. + // This will also trigger the loading of the qmldir and the import of any native + // types from available plugins. + QList errors; + if (QQmlQmldirData *qmldir = qmldirForUrl(finalUrl().resolved(QUrl(QLatin1String("./qmldir"))))) { + m_imports.addImport(importDatabase, QLatin1String("."), + QString(), -1, -1, QQmlScript::Import::File, + qmldir->dirComponents(), &errors); + } else { + m_imports.addImport(importDatabase, QLatin1String("."), + QString(), -1, -1, QQmlScript::Import::File, + QQmlDirComponents(), &errors); + } + + // remove any errors which are due to the implicit import which aren't real errors. + // for example, if the implicitly included qmldir file doesn't exist, that is not an error. + QList realErrors; + for (int i = 0; i < errors.size(); ++i) { + if (errors.at(i).description() != QQmlImportDatabase::tr("import \".\" has no qmldir and no namespace") + && errors.at(i).description() != QQmlImportDatabase::tr("\".\": no such directory")) { + realErrors.prepend(errors.at(i)); // this is a real error. + } + } + + // report any real errors which occurred during plugin loading or qmldir parsing. + if (!realErrors.isEmpty()) { + setError(realErrors); + return; + } + + foreach (const QQmlScript::Import &import, scriptParser.imports()) { + QQmlDirComponents qmldircomponentsnetwork; + if (import.type == QQmlScript::Import::Script) + continue; + + if (import.type == QQmlScript::Import::File && import.qualifier.isEmpty()) { + QUrl qmldirUrl = finalUrl().resolved(QUrl(import.uri + QLatin1String("/qmldir"))); + if (QQmlQmldirData *qmldir = qmldirForUrl(qmldirUrl)) + qmldircomponentsnetwork = qmldir->dirComponents(); + } + + int vmaj = -1; + int vmin = -1; + import.extractVersion(&vmaj, &vmin); + + QList errors; + if (!m_imports.addImport(importDatabase, import.uri, import.qualifier, + vmaj, vmin, import.type, qmldircomponentsnetwork, &errors)) { + QQmlError error; + if (errors.size()) { + error = errors.takeFirst(); + } else { + // this should not be possible! + // Description should come from error provided by addImport() function. + error.setDescription(QQmlTypeLoader::tr("Unreported error adding script import to import database")); + } + error.setUrl(m_imports.baseUrl()); + error.setLine(import.location.start.line); + error.setColumn(import.location.start.column); + errors.prepend(error); // put it back on the list after filling out information. + + setError(errors); + return; + } + } + + // Add any imported scripts to our resolved set + foreach (const QQmlImports::ScriptReference &script, m_imports.resolvedScripts()) + { + QQmlScriptBlob *blob = typeLoader()->getScript(script.location); + addDependency(blob); + + ScriptReference ref; + //ref.location = ... + ref.qualifier = script.nameSpace; + if (!script.qualifier.isEmpty()) + { + ref.qualifier.prepend(script.qualifier + QLatin1Char('.')); + + // Add a reference to the enclosing namespace + m_namespaces.insert(script.qualifier); + } + + ref.script = blob; + m_scripts << ref; + } + + foreach (QQmlScript::TypeReference *parserRef, scriptParser.referencedTypes()) { + TypeReference ref; + + QString url; + int majorVersion; + int minorVersion; + QQmlImportedNamespace *typeNamespace = 0; + QList errors; + + if (!m_imports.resolveType(parserRef->name, &ref.type, &url, &majorVersion, &minorVersion, + &typeNamespace, &errors) || typeNamespace) { + // Known to not be a type: + // - known to be a namespace (Namespace {}) + // - type with unknown namespace (UnknownNamespace.SomeType {}) + QQmlError error; + QString userTypeName = parserRef->name; + userTypeName.replace(QLatin1Char('/'),QLatin1Char('.')); + if (typeNamespace) { + error.setDescription(QQmlTypeLoader::tr("Namespace %1 cannot be used as a type").arg(userTypeName)); + } else { + if (errors.size()) { + error = errors.takeFirst(); + } else { + // this should not be possible! + // Description should come from error provided by addImport() function. + error.setDescription(QQmlTypeLoader::tr("Unreported error adding script import to import database")); + } + error.setUrl(m_imports.baseUrl()); + error.setDescription(QQmlTypeLoader::tr("%1 %2").arg(userTypeName).arg(error.description())); + } + + if (!parserRef->refObjects.isEmpty()) { + QQmlScript::Object *obj = parserRef->refObjects.first(); + error.setLine(obj->location.start.line); + error.setColumn(obj->location.start.column); + } + + errors.prepend(error); + setError(errors); + return; + } + + if (ref.type) { + ref.majorVersion = majorVersion; + ref.minorVersion = minorVersion; + } else { + ref.typeData = typeLoader()->get(QUrl(url)); + addDependency(ref.typeData); + } + + if (parserRef->refObjects.count()) + ref.location = parserRef->refObjects.first()->location.start; + + m_types << ref; + } +} + +QQmlQmldirData *QQmlTypeData::qmldirForUrl(const QUrl &url) +{ + for (int ii = 0; ii < m_qmldirs.count(); ++ii) { + if (m_qmldirs.at(ii)->url() == url) + return m_qmldirs.at(ii); + } + return 0; +} + +QQmlScriptData::QQmlScriptData() +: importCache(0), pragmas(QQmlScript::Object::ScriptBlock::None), m_loaded(false) +{ +} + +QQmlScriptData::~QQmlScriptData() +{ +} + +void QQmlScriptData::clear() +{ + if (importCache) { + importCache->release(); + importCache = 0; + } + + for (int ii = 0; ii < scripts.count(); ++ii) + scripts.at(ii)->release(); + scripts.clear(); + + qPersistentDispose(m_program); + qPersistentDispose(m_value); + + // An addref() was made when the QQmlCleanup was added to the engine. + release(); +} + +QQmlScriptBlob::QQmlScriptBlob(const QUrl &url, QQmlTypeLoader *loader) +: QQmlDataBlob(url, JavaScriptFile), m_pragmas(QQmlScript::Object::ScriptBlock::None), + m_imports(loader), m_scriptData(0), m_typeLoader(loader) +{ +} + +QQmlScriptBlob::~QQmlScriptBlob() +{ + if (m_scriptData) { + m_scriptData->release(); + m_scriptData = 0; + } +} + +QQmlScript::Object::ScriptBlock::Pragmas QQmlScriptBlob::pragmas() const +{ + return m_pragmas; +} + +QQmlTypeLoader *QQmlScriptBlob::typeLoader() const +{ + return m_typeLoader; +} + +const QQmlImports &QQmlScriptBlob::imports() const +{ + return m_imports; +} + +QQmlScriptData *QQmlScriptBlob::scriptData() const +{ + return m_scriptData; +} + +void QQmlScriptBlob::dataReceived(const QByteArray &data) +{ + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(m_typeLoader->engine()); + QQmlImportDatabase *importDatabase = &ep->importDatabase; + + m_source = QString::fromUtf8(data); + + QQmlScript::Parser::JavaScriptMetaData metadata = + QQmlScript::Parser::extractMetaData(m_source); + + m_imports.setBaseUrl(finalUrl(), finalUrlString()); + + m_pragmas = metadata.pragmas; + + foreach (const QQmlScript::Import &import, metadata.imports) { + Q_ASSERT(import.type != QQmlScript::Import::File); + + if (import.type == QQmlScript::Import::Script) { + QUrl scriptUrl = finalUrl().resolved(QUrl(import.uri)); + QQmlScriptBlob *blob = typeLoader()->getScript(scriptUrl); + addDependency(blob); + + ScriptReference ref; + ref.location = import.location.start; + ref.qualifier = import.qualifier; + ref.script = blob; + m_scripts << ref; + } else { + Q_ASSERT(import.type == QQmlScript::Import::Library); + int vmaj = -1; + int vmin = -1; + import.extractVersion(&vmaj, &vmin); + + QList errors; + if (!m_imports.addImport(importDatabase, import.uri, import.qualifier, vmaj, vmin, + import.type, QQmlDirComponents(), &errors)) { + QQmlError error = errors.takeFirst(); + // description should be set by addImport(). + error.setUrl(m_imports.baseUrl()); + error.setLine(import.location.start.line); + error.setColumn(import.location.start.column); + errors.prepend(error); + + setError(errors); + return; + } + } + } +} + +void QQmlScriptBlob::done() +{ + // Check all script dependencies for errors + for (int ii = 0; !isError() && ii < m_scripts.count(); ++ii) { + const ScriptReference &script = m_scripts.at(ii); + Q_ASSERT(script.script->isCompleteOrError()); + if (script.script->isError()) { + QList errors = script.script->errors(); + QQmlError error; + error.setUrl(finalUrl()); + error.setLine(script.location.line); + error.setColumn(script.location.column); + error.setDescription(typeLoader()->tr("Script %1 unavailable").arg(script.script->url().toString())); + errors.prepend(error); + setError(errors); + } + } + + if (isError()) + return; + + QQmlEngine *engine = typeLoader()->engine(); + m_scriptData = new QQmlScriptData(); + m_scriptData->url = finalUrl(); + m_scriptData->urlString = finalUrlString(); + m_scriptData->importCache = new QQmlTypeNameCache(); + + for (int ii = 0; !isError() && ii < m_scripts.count(); ++ii) { + const ScriptReference &script = m_scripts.at(ii); + + m_scriptData->scripts.append(script.script); + m_scriptData->importCache->add(script.qualifier, ii); + } + + m_imports.populateCache(m_scriptData->importCache, engine); + + m_scriptData->pragmas = m_pragmas; + m_scriptData->m_programSource = m_source.toUtf8(); + m_source.clear(); +} + +QQmlQmldirData::QQmlQmldirData(const QUrl &url) +: QQmlDataBlob(url, QmldirFile) +{ +} + +const QQmlDirComponents &QQmlQmldirData::dirComponents() const +{ + return m_components; +} + +void QQmlQmldirData::dataReceived(const QByteArray &data) +{ + QQmlDirParser parser; + parser.setSource(QString::fromUtf8(data)); + parser.parse(); + m_components = parser.components(); +} + +QT_END_NAMESPACE + +#include "qqmltypeloader.moc" diff --cc src/qml/qml/qqmlvme_p.h index 8c8d4d0,0000000..844f2cc mode 100644,000000..100644 --- a/src/qml/qml/qqmlvme_p.h +++ b/src/qml/qml/qqmlvme_p.h @@@ -1,240 -1,0 +1,238 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLVME_P_H +#define QQMLVME_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qqmlerror.h" +#include +#include "qqmlinstruction_p.h" +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QObject; +class QJSValue; +class QQmlScriptData; +class QQmlCompiledData; +class QQmlCompiledData; +class QQmlContextData; + +namespace QQmlVMETypes { + struct List + { + List() : type(0) {} + List(int t) : type(t) {} + + int type; + QQmlListProperty qListProperty; + }; +} +Q_DECLARE_TYPEINFO(QQmlVMETypes::List, Q_PRIMITIVE_TYPE | Q_MOVABLE_TYPE); + +class QQmlVME +{ + Q_DECLARE_TR_FUNCTIONS(QQmlVME) +public: + class Interrupt { + public: + inline Interrupt(); - inline Interrupt(bool *runWhile); ++ inline Interrupt(volatile bool *runWhile, int nsecs=0); + inline Interrupt(int nsecs); + + inline void reset(); + inline bool shouldInterrupt() const; + private: + enum Mode { None, Time, Flag }; + Mode mode; - union { - struct { - QElapsedTimer timer; - int nsecs; - }; - bool *runWhile; ++ struct { ++ QElapsedTimer timer; ++ int nsecs; + }; ++ volatile bool *runWhile; + }; + + QQmlVME() : data(0), componentAttached(0) {} + QQmlVME(void *data) : data(data), componentAttached(0) {} + + void *data; + QQmlComponentAttached *componentAttached; + QList finalizeCallbacks; + + void init(QQmlContextData *, QQmlCompiledData *, int start, + QQmlContextData * = 0); + bool initDeferred(QObject *); + void reset(); + + QObject *execute(QList *errors, const Interrupt & = Interrupt()); + QQmlContextData *complete(const Interrupt & = Interrupt()); + +private: + friend class QQmlVMEGuard; + + QObject *run(QList *errors, const Interrupt & +#ifdef QML_THREADED_VME_INTERPRETER + , void ***storeJumpTable = 0 +#endif + ); + v8::Persistent run(QQmlContextData *, QQmlScriptData *); + +#ifdef QML_THREADED_VME_INTERPRETER + static void **instructionJumpTable(); + friend class QQmlCompiledData; +#endif + + QQmlEngine *engine; + QRecursionNode recursion; + +#ifdef QML_ENABLE_TRACE + QQmlCompiledData *rootComponent; +#endif + + QFiniteStack objects; + QFiniteStack lists; + + QFiniteStack bindValues; + QFiniteStack parserStatus; +#ifdef QML_ENABLE_TRACE + QFiniteStack parserStatusData; +#endif + + QQmlGuardedContextData rootContext; + QQmlGuardedContextData creationContext; + + struct State { + enum Flag { Deferred = 0x00000001 }; + + State() : flags(0), context(0), compiledData(0), instructionStream(0) {} + quint32 flags; + QQmlContextData *context; + QQmlCompiledData *compiledData; + const char *instructionStream; + QBitField bindingSkipList; + }; + + QStack states; + + static void blank(QFiniteStack &); + static void blank(QFiniteStack &); +}; + +// Used to check that a QQmlVME that is interrupted mid-execution +// is still valid. Checks all the objects and contexts have not been +// deleted. +class QQmlVMEGuard +{ +public: + QQmlVMEGuard(); + ~QQmlVMEGuard(); + + void guard(QQmlVME *); + void clear(); + + bool isOK() const; + +private: + int m_objectCount; + QQmlGuard *m_objects; + int m_contextCount; + QQmlGuardedContextData *m_contexts; +}; + +QQmlVME::Interrupt::Interrupt() - : mode(None) ++ : mode(None), nsecs(0), runWhile(0) +{ +} + - QQmlVME::Interrupt::Interrupt(bool *runWhile) - : mode(Flag), runWhile(runWhile) ++QQmlVME::Interrupt::Interrupt(volatile bool *runWhile, int nsecs) ++ : mode(Flag), nsecs(nsecs), runWhile(runWhile) +{ +} + +QQmlVME::Interrupt::Interrupt(int nsecs) - : mode(Time), nsecs(nsecs) ++ : mode(Time), nsecs(nsecs), runWhile(0) +{ +} + +void QQmlVME::Interrupt::reset() +{ - if (mode == Time) ++ if (mode == Time || nsecs) + timer.start(); +} + +bool QQmlVME::Interrupt::shouldInterrupt() const +{ + if (mode == None) { + return false; + } else if (mode == Time) { + return timer.nsecsElapsed() > nsecs; + } else if (mode == Flag) { - return !*runWhile; ++ return !*runWhile || (nsecs && timer.nsecsElapsed() > nsecs); + } else { + return false; + } +} + +QT_END_NAMESPACE + +#endif // QQMLVME_P_H diff --cc src/qml/qml/qquickworkerscript.cpp index f91aa28,0000000..529f181 mode 100644,000000..100644 --- a/src/qml/qml/qquickworkerscript.cpp +++ b/src/qml/qml/qquickworkerscript.cpp @@@ -1,730 -1,0 +1,730 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickworkerscript_p.h" +#include "qquicklistmodel_p.h" +#include "qquicklistmodelworkeragent_p.h" +#include "qqmlengine_p.h" +#include "qqmlexpression_p.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qqmlnetworkaccessmanagerfactory.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +class WorkerDataEvent : public QEvent +{ +public: + enum Type { WorkerData = QEvent::User }; + + WorkerDataEvent(int workerId, const QByteArray &data); + virtual ~WorkerDataEvent(); + + int workerId() const; + QByteArray data() const; + +private: + int m_id; + QByteArray m_data; +}; + +class WorkerLoadEvent : public QEvent +{ +public: + enum Type { WorkerLoad = WorkerDataEvent::WorkerData + 1 }; + + WorkerLoadEvent(int workerId, const QUrl &url); + + int workerId() const; + QUrl url() const; + +private: + int m_id; + QUrl m_url; +}; + +class WorkerRemoveEvent : public QEvent +{ +public: + enum Type { WorkerRemove = WorkerLoadEvent::WorkerLoad + 1 }; + + WorkerRemoveEvent(int workerId); + + int workerId() const; + +private: + int m_id; +}; + +class WorkerErrorEvent : public QEvent +{ +public: + enum Type { WorkerError = WorkerRemoveEvent::WorkerRemove + 1 }; + + WorkerErrorEvent(const QQmlError &error); + + QQmlError error() const; + +private: + QQmlError m_error; +}; + +class QQuickWorkerScriptEnginePrivate : public QObject +{ + Q_OBJECT +public: + enum WorkerEventTypes { + WorkerDestroyEvent = QEvent::User + 100 + }; + + QQuickWorkerScriptEnginePrivate(QQmlEngine *eng); + + class WorkerEngine : public QV8Engine + { + public: + WorkerEngine(QQuickWorkerScriptEnginePrivate *parent); + ~WorkerEngine(); + + void init(); + virtual QNetworkAccessManager *networkAccessManager(); + + QQuickWorkerScriptEnginePrivate *p; + + v8::Local sendFunction(int id); + void callOnMessage(v8::Handle object, v8::Handle arg); + private: + v8::Persistent onmessage; + v8::Persistent createsend; + QNetworkAccessManager *accessManager; + }; + + WorkerEngine *workerEngine; + static QQuickWorkerScriptEnginePrivate *get(QV8Engine *e) { + return static_cast(e)->p; + } + + QQmlEngine *qmlengine; + + QMutex m_lock; + QWaitCondition m_wait; + + struct WorkerScript { + WorkerScript(); + ~WorkerScript(); + + int id; + QUrl source; + bool initialized; + QQuickWorkerScript *owner; + v8::Persistent object; + }; + + QHash workers; + v8::Handle getWorker(WorkerScript *); + + int m_nextId; + + static v8::Handle sendMessage(const v8::Arguments &args); + +signals: + void stopThread(); + +protected: + virtual bool event(QEvent *); + +private: + void processMessage(int, const QByteArray &); + void processLoad(int, const QUrl &); + void reportScriptException(WorkerScript *, const QQmlError &error); +}; + +QQuickWorkerScriptEnginePrivate::WorkerEngine::WorkerEngine(QQuickWorkerScriptEnginePrivate *parent) +: QV8Engine(0), p(parent), accessManager(0) +{ +} + +QQuickWorkerScriptEnginePrivate::WorkerEngine::~WorkerEngine() +{ + qPersistentDispose(createsend); + qPersistentDispose(onmessage); + delete accessManager; +} + +void QQuickWorkerScriptEnginePrivate::WorkerEngine::init() +{ - initDeclarativeGlobalObject(); ++ initQmlGlobalObject(); +#define CALL_ONMESSAGE_SCRIPT \ + "(function(object, message) { "\ + "var isfunction = false; "\ + "try { "\ + "isfunction = object.WorkerScript.onMessage instanceof Function; "\ + "} catch (e) {}" \ + "if (isfunction) "\ + "object.WorkerScript.onMessage(message); "\ + "})" + +#define SEND_MESSAGE_CREATE_SCRIPT \ + "(function(method, engine) { "\ + "return (function(id) { "\ + "return (function(message) { "\ + "if (arguments.length) method(engine, id, message); "\ + "}); "\ + "}); "\ + "})" + + v8::HandleScope handle_scope; + v8::Context::Scope scope(context()); + + { + v8::Local onmessagescript = v8::Script::New(v8::String::New(CALL_ONMESSAGE_SCRIPT)); + onmessage = qPersistentNew(v8::Handle::Cast(onmessagescript->Run())); + } + { + v8::Local createsendscript = v8::Script::New(v8::String::New(SEND_MESSAGE_CREATE_SCRIPT)); + v8::Local createsendconstructor = v8::Local::Cast(createsendscript->Run()); + + v8::Handle args[] = { + V8FUNCTION(QQuickWorkerScriptEnginePrivate::sendMessage, this) + }; + v8::Local createsendvalue = createsendconstructor->Call(global(), 1, args); + + createsend = qPersistentNew(v8::Handle::Cast(createsendvalue)); + } +} + +// Requires handle and context scope +v8::Local QQuickWorkerScriptEnginePrivate::WorkerEngine::sendFunction(int id) +{ + v8::Handle args[] = { v8::Integer::New(id) }; + return v8::Local::Cast(createsend->Call(global(), 1, args)); +} + +// Requires handle and context scope +void QQuickWorkerScriptEnginePrivate::WorkerEngine::callOnMessage(v8::Handle object, + v8::Handle arg) +{ + v8::Handle args[] = { object, arg }; + onmessage->Call(global(), 2, args); +} + +QNetworkAccessManager *QQuickWorkerScriptEnginePrivate::WorkerEngine::networkAccessManager() +{ + if (!accessManager) { + if (p->qmlengine && p->qmlengine->networkAccessManagerFactory()) { + accessManager = p->qmlengine->networkAccessManagerFactory()->create(p); + } else { + accessManager = new QNetworkAccessManager(p); + } + } + return accessManager; +} + +QQuickWorkerScriptEnginePrivate::QQuickWorkerScriptEnginePrivate(QQmlEngine *engine) +: workerEngine(0), qmlengine(engine), m_nextId(0) +{ +} + +v8::Handle QQuickWorkerScriptEnginePrivate::sendMessage(const v8::Arguments &args) +{ + WorkerEngine *engine = (WorkerEngine*)V8ENGINE(); + + int id = args[1]->Int32Value(); + + QByteArray data = QV8Worker::serialize(args[2], engine); + + QMutexLocker(&engine->p->m_lock); + WorkerScript *script = engine->p->workers.value(id); + if (!script) + return v8::Undefined(); + + if (script->owner) + QCoreApplication::postEvent(script->owner, new WorkerDataEvent(0, data)); + + return v8::Undefined(); +} + +// Requires handle scope and context scope +v8::Handle QQuickWorkerScriptEnginePrivate::getWorker(WorkerScript *script) +{ + if (!script->initialized) { + script->initialized = true; + + script->object = qPersistentNew(workerEngine->contextWrapper()->urlScope(script->source)); + + workerEngine->contextWrapper()->setReadOnly(script->object, false); + + v8::Local api = v8::Object::New(); + api->Set(v8::String::New("sendMessage"), workerEngine->sendFunction(script->id)); + + script->object->Set(v8::String::New("WorkerScript"), api); + + workerEngine->contextWrapper()->setReadOnly(script->object, true); + } + + return script->object; +} + +bool QQuickWorkerScriptEnginePrivate::event(QEvent *event) +{ + if (event->type() == (QEvent::Type)WorkerDataEvent::WorkerData) { + WorkerDataEvent *workerEvent = static_cast(event); + processMessage(workerEvent->workerId(), workerEvent->data()); + return true; + } else if (event->type() == (QEvent::Type)WorkerLoadEvent::WorkerLoad) { + WorkerLoadEvent *workerEvent = static_cast(event); + processLoad(workerEvent->workerId(), workerEvent->url()); + return true; + } else if (event->type() == (QEvent::Type)WorkerDestroyEvent) { + emit stopThread(); + return true; + } else if (event->type() == (QEvent::Type)WorkerRemoveEvent::WorkerRemove) { + WorkerRemoveEvent *workerEvent = static_cast(event); + workers.remove(workerEvent->workerId()); + return true; + } else { + return QObject::event(event); + } +} + +void QQuickWorkerScriptEnginePrivate::processMessage(int id, const QByteArray &data) +{ + WorkerScript *script = workers.value(id); + if (!script) + return; + + v8::HandleScope handle_scope; + v8::Context::Scope scope(workerEngine->context()); + + v8::Handle value = QV8Worker::deserialize(data, workerEngine); + + v8::TryCatch tc; + workerEngine->callOnMessage(script->object, value); + + if (tc.HasCaught()) { + QQmlError error; + QQmlExpressionPrivate::exceptionToError(tc.Message(), error); + reportScriptException(script, error); + } +} + +void QQuickWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url) +{ + if (url.isRelative()) + return; + + QString fileName = QQmlEnginePrivate::urlToLocalFileOrQrc(url); + + QFile f(fileName); + if (f.open(QIODevice::ReadOnly)) { + QByteArray data = f.readAll(); + QString sourceCode = QString::fromUtf8(data); + QQmlScript::Parser::extractPragmas(sourceCode); + + v8::HandleScope handle_scope; + v8::Context::Scope scope(workerEngine->context()); + + WorkerScript *script = workers.value(id); + if (!script) + return; + script->source = url; + v8::Handle activation = getWorker(script); + if (activation.IsEmpty()) + return; + + // XXX ??? + // workerEngine->baseUrl = url; + + v8::TryCatch tc; + v8::Local program = workerEngine->qmlModeCompile(sourceCode, url.toString()); + + if (!tc.HasCaught()) + program->Run(activation); + + if (tc.HasCaught()) { + QQmlError error; + QQmlExpressionPrivate::exceptionToError(tc.Message(), error); + reportScriptException(script, error); + } + } else { + qWarning().nospace() << "WorkerScript: Cannot find source file " << url.toString(); + } +} + +void QQuickWorkerScriptEnginePrivate::reportScriptException(WorkerScript *script, + const QQmlError &error) +{ + QQuickWorkerScriptEnginePrivate *p = QQuickWorkerScriptEnginePrivate::get(workerEngine); + + QMutexLocker(&p->m_lock); + if (script->owner) + QCoreApplication::postEvent(script->owner, new WorkerErrorEvent(error)); +} + +WorkerDataEvent::WorkerDataEvent(int workerId, const QByteArray &data) +: QEvent((QEvent::Type)WorkerData), m_id(workerId), m_data(data) +{ +} + +WorkerDataEvent::~WorkerDataEvent() +{ +} + +int WorkerDataEvent::workerId() const +{ + return m_id; +} + +QByteArray WorkerDataEvent::data() const +{ + return m_data; +} + +WorkerLoadEvent::WorkerLoadEvent(int workerId, const QUrl &url) +: QEvent((QEvent::Type)WorkerLoad), m_id(workerId), m_url(url) +{ +} + +int WorkerLoadEvent::workerId() const +{ + return m_id; +} + +QUrl WorkerLoadEvent::url() const +{ + return m_url; +} + +WorkerRemoveEvent::WorkerRemoveEvent(int workerId) +: QEvent((QEvent::Type)WorkerRemove), m_id(workerId) +{ +} + +int WorkerRemoveEvent::workerId() const +{ + return m_id; +} + +WorkerErrorEvent::WorkerErrorEvent(const QQmlError &error) +: QEvent((QEvent::Type)WorkerError), m_error(error) +{ +} + +QQmlError WorkerErrorEvent::error() const +{ + return m_error; +} + +QQuickWorkerScriptEngine::QQuickWorkerScriptEngine(QQmlEngine *parent) +: QThread(parent), d(new QQuickWorkerScriptEnginePrivate(parent)) +{ + d->m_lock.lock(); + connect(d, SIGNAL(stopThread()), this, SLOT(quit()), Qt::DirectConnection); + start(QThread::LowestPriority); + d->m_wait.wait(&d->m_lock); + d->moveToThread(this); + d->m_lock.unlock(); +} + +QQuickWorkerScriptEngine::~QQuickWorkerScriptEngine() +{ + d->m_lock.lock(); + QCoreApplication::postEvent(d, new QEvent((QEvent::Type)QQuickWorkerScriptEnginePrivate::WorkerDestroyEvent)); + d->m_lock.unlock(); + + //We have to force to cleanup the main thread's event queue here + //to make sure the main GUI release all pending locks/wait conditions which + //some worker script/agent are waiting for (QQuickListModelWorkerAgent::sync() for example). + QCoreApplication::processEvents(); + wait(); + d->deleteLater(); +} + +QQuickWorkerScriptEnginePrivate::WorkerScript::WorkerScript() +: id(-1), initialized(false), owner(0) +{ +} + +QQuickWorkerScriptEnginePrivate::WorkerScript::~WorkerScript() +{ + qPersistentDispose(object); +} + +int QQuickWorkerScriptEngine::registerWorkerScript(QQuickWorkerScript *owner) +{ + typedef QQuickWorkerScriptEnginePrivate::WorkerScript WorkerScript; + WorkerScript *script = new WorkerScript; + + script->id = d->m_nextId++; + script->owner = owner; + + d->m_lock.lock(); + d->workers.insert(script->id, script); + d->m_lock.unlock(); + + return script->id; +} + +void QQuickWorkerScriptEngine::removeWorkerScript(int id) +{ + QQuickWorkerScriptEnginePrivate::WorkerScript* script = d->workers.value(id); + if (script) { + script->owner = 0; + QCoreApplication::postEvent(d, new WorkerRemoveEvent(id)); + } +} + +void QQuickWorkerScriptEngine::executeUrl(int id, const QUrl &url) +{ + QCoreApplication::postEvent(d, new WorkerLoadEvent(id, url)); +} + +void QQuickWorkerScriptEngine::sendMessage(int id, const QByteArray &data) +{ + QCoreApplication::postEvent(d, new WorkerDataEvent(id, data)); +} + +void QQuickWorkerScriptEngine::run() +{ + d->m_lock.lock(); + + d->workerEngine = new QQuickWorkerScriptEnginePrivate::WorkerEngine(d); + d->workerEngine->init(); + + d->m_wait.wakeAll(); + + d->m_lock.unlock(); + + exec(); + + qDeleteAll(d->workers); + d->workers.clear(); + + delete d->workerEngine; d->workerEngine = 0; +} + + +/*! + \qmlclass WorkerScript QQuickWorkerScript + \ingroup qml-utility-elements + \brief The WorkerScript element enables the use of threads in QML. + + Use WorkerScript to run operations in a new thread. + This is useful for running operations in the background so + that the main GUI thread is not blocked. + + Messages can be passed between the new thread and the parent thread + using \l sendMessage() and the \l {WorkerScript::onMessage}{onMessage()} handler. + + An example: + + \snippet doc/src/snippets/qml/workerscript.qml 0 + + The above worker script specifies a JavaScript file, "script.js", that handles + the operations to be performed in the new thread. Here is \c script.js: + + \quotefile doc/src/snippets/qml/script.js + + When the user clicks anywhere within the rectangle, \c sendMessage() is + called, triggering the \tt WorkerScript.onMessage() handler in + \tt script.js. This in turn sends a reply message that is then received + by the \tt onMessage() handler of \tt myWorker. + + + \section3 Restrictions + + Since the \c WorkerScript.onMessage() function is run in a separate thread, the + JavaScript file is evaluated in a context separate from the main QML engine. This means + that unlike an ordinary JavaScript file that is imported into QML, the \c script.js + in the above example cannot access the properties, methods or other attributes + of the QML item, nor can it access any context properties set on the QML object + through QQmlContext. + + Additionally, there are restrictions on the types of values that can be passed to and + from the worker script. See the sendMessage() documentation for details. + + \sa {declarative/threading/workerscript}{WorkerScript example}, + {declarative/threading/threadedlistmodel}{Threaded ListModel example} +*/ +QQuickWorkerScript::QQuickWorkerScript(QObject *parent) +: QObject(parent), m_engine(0), m_scriptId(-1), m_componentComplete(true) +{ +} + +QQuickWorkerScript::~QQuickWorkerScript() +{ + if (m_scriptId != -1) m_engine->removeWorkerScript(m_scriptId); +} + +/*! + \qmlproperty url WorkerScript::source + + This holds the url of the JavaScript file that implements the + \tt WorkerScript.onMessage() handler for threaded operations. +*/ +QUrl QQuickWorkerScript::source() const +{ + return m_source; +} + +void QQuickWorkerScript::setSource(const QUrl &source) +{ + if (m_source == source) + return; + + m_source = source; + + if (engine()) + m_engine->executeUrl(m_scriptId, m_source); + + emit sourceChanged(); +} + +/*! + \qmlmethod WorkerScript::sendMessage(jsobject message) + + Sends the given \a message to a worker script handler in another + thread. The other worker script handler can receive this message + through the onMessage() handler. + + The \c message object may only contain values of the following + types: + + \list + \o boolean, number, string + \o JavaScript objects and arrays + \o ListModel objects (any other type of QObject* is not allowed) + \endlist + + All objects and arrays are copied to the \c message. With the exception + of ListModel objects, any modifications by the other thread to an object + passed in \c message will not be reflected in the original object. +*/ +void QQuickWorkerScript::sendMessage(QQmlV8Function *args) +{ + if (!engine()) { + qWarning("QQuickWorkerScript: Attempt to send message before WorkerScript establishment"); + return; + } + + v8::Handle argument = v8::Undefined(); + if (args->Length() != 0) + argument = (*args)[0]; + + m_engine->sendMessage(m_scriptId, QV8Worker::serialize(argument, args->engine())); +} + +void QQuickWorkerScript::classBegin() +{ + m_componentComplete = false; +} + +QQuickWorkerScriptEngine *QQuickWorkerScript::engine() +{ + if (m_engine) return m_engine; + if (m_componentComplete) { + QQmlEngine *engine = qmlEngine(this); + if (!engine) { + qWarning("QQuickWorkerScript: engine() called without qmlEngine() set"); + return 0; + } + + m_engine = QQmlEnginePrivate::get(engine)->getWorkerScriptEngine(); + m_scriptId = m_engine->registerWorkerScript(this); + + if (m_source.isValid()) + m_engine->executeUrl(m_scriptId, m_source); + + return m_engine; + } + return 0; +} + +void QQuickWorkerScript::componentComplete() +{ + m_componentComplete = true; + engine(); // Get it started now. +} + +/*! + \qmlsignal WorkerScript::onMessage(jsobject msg) + + This handler is called when a message \a msg is received from a worker + script in another thread through a call to sendMessage(). +*/ + +bool QQuickWorkerScript::event(QEvent *event) +{ + if (event->type() == (QEvent::Type)WorkerDataEvent::WorkerData) { + QQmlEngine *engine = qmlEngine(this); + if (engine) { + WorkerDataEvent *workerEvent = static_cast(event); + QV8Engine *v8engine = QQmlEnginePrivate::get(engine)->v8engine(); + v8::HandleScope handle_scope; + v8::Context::Scope scope(v8engine->context()); + v8::Handle value = QV8Worker::deserialize(workerEvent->data(), v8engine); + emit message(QQmlV8Handle::fromHandle(value)); + } + return true; + } else if (event->type() == (QEvent::Type)WorkerErrorEvent::WorkerError) { + WorkerErrorEvent *workerEvent = static_cast(event); + QQmlEnginePrivate::warning(qmlEngine(this), workerEvent->error()); + return true; + } else { + return QObject::event(event); + } +} + +QT_END_NAMESPACE + +#include + diff --cc src/qml/qml/v4/qv4bindings.cpp index c03292d,0000000..4fd8494 mode 100644,000000..100644 --- a/src/qml/qml/v4/qv4bindings.cpp +++ b/src/qml/qml/v4/qv4bindings.cpp @@@ -1,1538 -1,0 +1,1615 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// #define REGISTER_CLEANUP_DEBUG + +#include "qv4bindings_p.h" +#include "qv4program_p.h" +#include "qv4compiler_p.h" +#include "qv4compiler_p_p.h" + +#include +#include +#include +#include ++#include + +#include +#include +#include +#include // ::fmod + +QT_BEGIN_NAMESPACE + +using namespace QQmlJS; + +namespace { +struct Register { + typedef QQmlRegisterType Type; + + void setUndefined() { dataType = UndefinedType; } + void setNaN() { setqreal(qSNaN()); } + bool isUndefined() const { return dataType == UndefinedType; } + + void setQObject(QObject *o) { qobjectValue = o; dataType = QObjectStarType; } + QObject *getQObject() const { return qobjectValue; } + + void setqreal(qreal v) { qrealValue = v; dataType = QRealType; } + qreal getqreal() const { return qrealValue; } + qreal &getqrealref() { return qrealValue; } + + void setint(int v) { intValue = v; dataType = IntType; } + int getint() const { return intValue; } + int &getintref() { return intValue; } + + void setbool(bool v) { boolValue = v; dataType = BoolType; } + bool getbool() const { return boolValue; } + bool &getboolref() { return boolValue; } + + QVariant *getvariantptr() { return (QVariant *)typeDataPtr(); } + QString *getstringptr() { return (QString *)typeDataPtr(); } + QUrl *geturlptr() { return (QUrl *)typeDataPtr(); } ++ QColor *getcolorptr() { return (QColor *)typeDataPtr(); } + const QVariant *getvariantptr() const { return (QVariant *)typeDataPtr(); } + const QString *getstringptr() const { return (QString *)typeDataPtr(); } + const QUrl *geturlptr() const { return (QUrl *)typeDataPtr(); } ++ const QColor *getcolorptr() const { return (QColor *)typeDataPtr(); } + + void *typeDataPtr() { return (void *)&data; } + void *typeMemory() { return (void *)data; } + const void *typeDataPtr() const { return (void *)&data; } + const void *typeMemory() const { return (void *)data; } + + Type gettype() const { return dataType; } + void settype(Type t) { dataType = t; } + + Type dataType; // Type of data + union { + QObject *qobjectValue; + qreal qrealValue; + int intValue; + bool boolValue; + void *data[sizeof(QVariant)]; + qint64 q_for_alignment_1; + double q_for_alignment_2; + }; + + inline void cleanup(); + inline void cleanupString(); + inline void cleanupUrl(); ++ inline void cleanupColor(); + inline void cleanupVariant(); + + inline void copy(const Register &other); + inline void init(Type type); +#ifdef REGISTER_CLEANUP_DEBUG + Register() { + type = 0; + } + + ~Register() { + if (dataType >= FirstCleanupType) + qWarning("Register leaked of type %d", dataType); + } +#endif +}; + +void Register::cleanup() +{ + if (dataType >= FirstCleanupType) { + if (dataType == QStringType) { + getstringptr()->~QString(); + } else if (dataType == QUrlType) { + geturlptr()->~QUrl(); ++ } else if (dataType == QColorType) { ++ getcolorptr()->~QColor(); + } else if (dataType == QVariantType) { + getvariantptr()->~QVariant(); + } + } + setUndefined(); +} + +void Register::cleanupString() +{ + getstringptr()->~QString(); + setUndefined(); +} + +void Register::cleanupUrl() +{ + geturlptr()->~QUrl(); + setUndefined(); +} + ++void Register::cleanupColor() ++{ ++ getcolorptr()->~QColor(); ++ setUndefined(); ++} ++ +void Register::cleanupVariant() +{ + getvariantptr()->~QVariant(); + setUndefined(); +} + +void Register::copy(const Register &other) +{ + *this = other; + if (other.dataType >= FirstCleanupType) { + if (other.dataType == QStringType) + new (getstringptr()) QString(*other.getstringptr()); + else if (other.dataType == QUrlType) + new (geturlptr()) QUrl(*other.geturlptr()); ++ else if (other.dataType == QColorType) ++ new (getcolorptr()) QColor(*other.getcolorptr()); + else if (other.dataType == QVariantType) + new (getvariantptr()) QVariant(*other.getvariantptr()); + } +} + +void Register::init(Type type) +{ + dataType = type; + if (dataType >= FirstCleanupType) { + if (dataType == QStringType) + new (getstringptr()) QString(); + else if (dataType == QUrlType) + new (geturlptr()) QUrl(); ++ else if (dataType == QColorType) ++ new (getcolorptr()) QColor(); + else if (dataType == QVariantType) + new (getvariantptr()) QVariant(); + } +} + +} // end of anonymous namespace + +QV4Bindings::QV4Bindings(const char *programData, + QQmlContextData *context, + QQmlRefCount *ref) +: subscriptions(0), program(0), dataRef(0), bindings(0) +{ + program = (QV4Program *)programData; + dataRef = ref; + if (dataRef) dataRef->addref(); + + if (program) { + subscriptions = new Subscription[program->subscriptions]; + bindings = new Binding[program->bindings]; + + QQmlAbstractExpression::setContext(context); + } +} + +QV4Bindings::~QV4Bindings() +{ + delete [] bindings; + delete [] subscriptions; subscriptions = 0; + if (dataRef) dataRef->release(); +} + +QQmlAbstractBinding *QV4Bindings::configBinding(int index, QObject *target, + QObject *scope, int property, + int line, int column) +{ + Binding *rv = bindings + index; + + rv->index = index; + rv->property = property; + rv->target = target; + rv->scope = scope; + rv->line = line; + rv->column = column; + rv->parent = this; + + addref(); // This is decremented in Binding::destroy() + + return rv; +} + +void QV4Bindings::Binding::setEnabled(bool e, QQmlPropertyPrivate::WriteFlags flags) +{ + if (enabled != e) { + enabled = e; + + if (e) update(flags); + } +} + +void QV4Bindings::Binding::update(QQmlPropertyPrivate::WriteFlags flags) +{ + parent->run(this, flags); +} + +void QV4Bindings::Binding::destroy() +{ + enabled = false; + removeFromObject(); + clear(); + removeError(); + parent->release(); +} + +int QV4Bindings::Binding::propertyIndex() const +{ - return property; ++ //mask out the type information set for value types ++ return property & 0xFF00FFFF; +} + +QObject *QV4Bindings::Binding::object() const +{ + return target; +} + +void QV4Bindings::Subscription::subscriptionCallback(QQmlNotifierEndpoint *e) +{ + Subscription *s = static_cast(e); + s->bindings->subscriptionNotify(s->method); +} + +void QV4Bindings::subscriptionNotify(int id) +{ + QV4Program::BindingReferenceList *list = program->signalTable(id); + + for (quint32 ii = 0; ii < list->count; ++ii) { + QV4Program::BindingReference *bindingRef = list->bindings + ii; + + Binding *binding = bindings + bindingRef->binding; + + if (binding->executedBlocks & bindingRef->blockMask) { + run(binding, QQmlPropertyPrivate::DontRemoveBinding); + } + } +} + +void QV4Bindings::run(Binding *binding, QQmlPropertyPrivate::WriteFlags flags) +{ + if (!binding->enabled) + return; + + QQmlContextData *context = QQmlAbstractExpression::context(); + if (!context || !context->isValid()) + return; + + QQmlTrace trace("V4 Binding Update"); + trace.addDetail("URL", context->url); + trace.addDetail("Line", binding->line); + trace.addDetail("Column", binding->column); + + QQmlBindingProfiler prof(context->urlString, binding->line, binding->column); + + if (binding->updating) { + QString name; + if (binding->property & 0xFFFF0000) { + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine); + + QQmlValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF]; + Q_ASSERT(vt); + + name = QLatin1String(binding->target->metaObject()->property(binding->property & 0xFFFF).name()); + name.append(QLatin1String(".")); + name.append(QLatin1String(vt->metaObject()->property(binding->property >> 24).name())); + } else { + name = QLatin1String(binding->target->metaObject()->property(binding->property).name()); + } + qmlInfo(binding->target) << tr("Binding loop detected for property \"%1\"").arg(name); + return; + } + + binding->updating = true; + if (binding->property & 0xFFFF0000) { + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine); + + QQmlValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF]; + Q_ASSERT(vt); + vt->read(binding->target, binding->property & 0xFFFF); + + QObject *target = vt; + run(binding->index, binding->executedBlocks, context, binding, binding->scope, target, flags); + + vt->write(binding->target, binding->property & 0xFFFF, flags); + } else { + run(binding->index, binding->executedBlocks, context, binding, binding->scope, binding->target, flags); + } + binding->updating = false; +} + + +void QV4Bindings::unsubscribe(int subIndex) +{ + Subscription *sub = (subscriptions + subIndex); + sub->disconnect(); +} + +void QV4Bindings::subscribeId(QQmlContextData *p, int idIndex, int subIndex) +{ + unsubscribe(subIndex); + + if (p->idValues[idIndex]) { + Subscription *sub = (subscriptions + subIndex); + sub->bindings = this; + sub->method = subIndex; + sub->connect(&p->idValues[idIndex].bindings); + } +} + +void QV4Bindings::subscribe(QObject *o, int notifyIndex, int subIndex) +{ + Subscription *sub = (subscriptions + subIndex); + if (sub->isConnected(o, notifyIndex)) + return; + sub->bindings = this; + sub->method = subIndex; + if (o) + sub->connect(o, notifyIndex); + else + sub->disconnect(); +} + +// Conversion functions - these MUST match the QtScript expression path +inline static qreal toReal(Register *reg, int type, bool *ok = 0) +{ + if (ok) *ok = true; + + if (type == QMetaType::QReal) { + return reg->getqreal(); + } else if (type == qMetaTypeId()) { + return reg->getvariantptr()->toReal(); + } else { + if (ok) *ok = false; + return 0; + } +} + +inline static QString toString(Register *reg, int type, bool *ok = 0) +{ + if (ok) *ok = true; + + if (type == QMetaType::QReal) { + return QString::number(reg->getqreal()); + } else if (type == QMetaType::Int) { + return QString::number(reg->getint()); + } else if (type == qMetaTypeId()) { + return reg->getvariantptr()->toString(); + } else if (type == QMetaType::QString) { + return *reg->getstringptr(); + } else { + if (ok) *ok = false; + return QString(); + } +} + +inline static bool toBool(Register *reg, int type, bool *ok = 0) +{ + if (ok) *ok = true; + + if (type == QMetaType::Bool) { + return reg->getbool(); + } else if (type == qMetaTypeId()) { + return reg->getvariantptr()->toBool(); + } else { + if (ok) *ok = false; + return false; + } +} + +inline static QUrl toUrl(Register *reg, int type, QQmlContextData *context, bool *ok = 0) +{ + if (ok) *ok = true; + + QUrl base; + if (type == qMetaTypeId()) { + QVariant *var = reg->getvariantptr(); + int vt = var->type(); + if (vt == QVariant::Url) { + base = var->toUrl(); + } else if (vt == QVariant::ByteArray) { + // Preserve any valid percent-encoded octets supplied by the source + base.setEncodedUrl(var->toByteArray(), QUrl::TolerantMode); + } else if (vt == QVariant::String) { + base.setEncodedUrl(var->toString().toUtf8(), QUrl::TolerantMode); + } else { + if (ok) *ok = false; + return QUrl(); + } + } else if (type == QMetaType::QString) { + base.setEncodedUrl(reg->getstringptr()->toUtf8(), QUrl::TolerantMode); + } else { + if (ok) *ok = false; + return QUrl(); + } + + if (!base.isEmpty() && base.isRelative()) + return context->url.resolved(base); + else + return base; +} + +static bool testCompareVariants(const QVariant &qtscriptRaw, const QVariant &v4) +{ + QVariant qtscript = qtscriptRaw; + + if (qtscript.userType() == v4.userType()) { + } else if (qtscript.canConvert((QVariant::Type)v4.userType())) { + qtscript.convert((QVariant::Type)v4.userType()); + } else if (qtscript.userType() == QVariant::Invalid && v4.userType() == QMetaType::QObjectStar) { + qtscript = qVariantFromValue(0); + } else { + return false; + } + + int type = qtscript.userType(); + + if (type == QQmlMetaType::QQuickAnchorLineMetaTypeId()) { + return QQmlMetaType::QQuickAnchorLineCompare(qtscript.constData(), v4.constData()); + } else if (type == QMetaType::Double) { + + double la = qvariant_cast(qtscript); + double lr = qvariant_cast(v4); + + return la == lr || (qIsNaN(la) && qIsNaN(lr)); + + } else if (type == QMetaType::Float) { + + float la = qvariant_cast(qtscript); + float lr = qvariant_cast(v4); + + return la == lr || (qIsNaN(la) && qIsNaN(lr)); + + } else { + return qtscript == v4; + } +} + +QByteArray testResultToString(const QVariant &result, bool undefined) +{ + if (undefined) { + return "undefined"; + } else { + QString rv; + QDebug d(&rv); + d << result; + return rv.toUtf8(); + } +} + +static void testBindingResult(const QString &binding, int line, int column, + QQmlContextData *context, QObject *scope, + const Register &result, int resultType) +{ + QQmlExpression expression(context->asQQmlContext(), scope, binding); + bool isUndefined = false; + QVariant value = expression.evaluate(&isUndefined); + + bool iserror = false; + QByteArray qtscriptResult; + QByteArray v4Result; + + if (expression.hasError()) { + iserror = true; + qtscriptResult = "exception"; + } else { + qtscriptResult = testResultToString(value, isUndefined); + } + + if (isUndefined && result.isUndefined()) { + return; + } else if(isUndefined != result.isUndefined()) { + iserror = true; + } + + QVariant v4value; + if (!result.isUndefined()) { + switch (resultType) { + case QMetaType::QString: + v4value = *result.getstringptr(); + break; + case QMetaType::QUrl: + v4value = *result.geturlptr(); + break; + case QMetaType::QObjectStar: + v4value = qVariantFromValue(result.getQObject()); + break; + case QMetaType::Bool: + v4value = result.getbool(); + break; + case QMetaType::Int: + v4value = result.getint(); + break; + case QMetaType::QReal: + v4value = result.getqreal(); + break; + default: + if (resultType == QQmlMetaType::QQuickAnchorLineMetaTypeId()) { + v4value = QVariant(QQmlMetaType::QQuickAnchorLineMetaTypeId(), result.typeDataPtr()); + } else { + iserror = true; + v4Result = "Unknown V4 type"; + } + } + } + if (v4Result.isEmpty()) + v4Result = testResultToString(v4value, result.isUndefined()); + + if (!testCompareVariants(value, v4value)) + iserror = true; + + if (iserror) { + qWarning().nospace() << "QV4: Optimization error @" << context->url.toString().toUtf8().constData() << ":" << line << ":" << column; + + qWarning().nospace() << " Binding: " << binding; + qWarning().nospace() << " QtScript: " << qtscriptResult.constData(); + qWarning().nospace() << " V4: " << v4Result.constData(); + } +} + +static void testBindingException(const QString &binding, int line, int column, + QQmlContextData *context, QObject *scope) +{ + QQmlExpression expression(context->asQQmlContext(), scope, binding); + bool isUndefined = false; + QVariant value = expression.evaluate(&isUndefined); + + if (!expression.hasError()) { + QByteArray qtscriptResult = testResultToString(value, isUndefined); + qWarning().nospace() << "QV4: Optimization error @" << context->url.toString().toUtf8().constData() << ":" << line << ":" << column; + qWarning().nospace() << " Binding: " << binding; + qWarning().nospace() << " QtScript: " << qtscriptResult.constData(); + qWarning().nospace() << " V4: exception"; + } +} + +static void throwException(int id, QQmlDelayedError *error, + QV4Program *program, QQmlContextData *context, + const QString &description = QString()) +{ + error->error.setUrl(context->url); + if (description.isEmpty()) + error->error.setDescription(QLatin1String("TypeError: Result of expression is not an object")); + else + error->error.setDescription(description); + if (id != 0xFF) { + quint64 e = *((quint64 *)(program->data() + program->exceptionDataOffset) + id); + error->error.setLine((e >> 32) & 0xFFFFFFFF); + error->error.setColumn(e & 0xFFFFFFFF); + } else { + error->error.setLine(-1); + error->error.setColumn(-1); + } + if (!context->engine || !error->addError(QQmlEnginePrivate::get(context->engine))) + QQmlEnginePrivate::warning(context->engine, error->error); +} + +const qreal QV4Bindings::D32 = 4294967296.0; + +qint32 QV4Bindings::toInt32(qreal n) +{ + if (qIsNaN(n) || qIsInf(n) || (n == 0)) + return 0; + + double sign = (n < 0) ? -1.0 : 1.0; + qreal abs_n = fabs(n); + + n = ::fmod(sign * ::floor(abs_n), D32); + const double D31 = D32 / 2.0; + + if (sign == -1 && n < -D31) + n += D32; + + else if (sign != -1 && n >= D31) + n -= D32; + + return qint32 (n); +} + +inline quint32 QV4Bindings::toUint32(qreal n) +{ + if (qIsNaN(n) || qIsInf(n) || (n == 0)) + return 0; + + double sign = (n < 0) ? -1.0 : 1.0; + qreal abs_n = fabs(n); + + n = ::fmod(sign * ::floor(abs_n), D32); + + if (n < 0) + n += D32; + + return quint32 (n); +} + +#define THROW_EXCEPTION_STR(id, str) { \ + if (testBinding) testBindingException(*testBindingSource, bindingLine, bindingColumn, context, scope); \ + throwException((id), error, program, context, (str)); \ + goto exceptionExit; \ +} + +#define THROW_EXCEPTION(id) THROW_EXCEPTION_STR(id, QString()) + +#define MARK_REGISTER(reg) cleanupRegisterMask |= (1 << (reg)) +#define MARK_CLEAN_REGISTER(reg) cleanupRegisterMask &= ~(1 << (reg)) + +#define STRING_REGISTER(reg) { \ + registers[(reg)].settype(QStringType); \ + MARK_REGISTER(reg); \ +} + +#define URL_REGISTER(reg) { \ + registers[(reg)].settype(QUrlType); \ + MARK_REGISTER(reg); \ +} + ++#define COLOR_REGISTER(reg) { \ ++ registers[(reg)].settype(QColorType); \ ++ MARK_REGISTER(reg); \ ++} ++ +#define VARIANT_REGISTER(reg) { \ + registers[(reg)].settype(QVariantType); \ + MARK_REGISTER(reg); \ +} + +#ifdef QML_THREADED_INTERPRETER +void **QV4Bindings::getDecodeInstrTable() +{ + static void **decode_instr; + if (!decode_instr) { + QV4Bindings *dummy = new QV4Bindings(0, 0, 0); + quint32 executedBlocks = 0; + dummy->run(0, executedBlocks, 0, 0, 0, 0, + QQmlPropertyPrivate::BypassInterceptor, + &decode_instr); + dummy->release(); + } + return decode_instr; +} +#endif + +void QV4Bindings::run(int instrIndex, quint32 &executedBlocks, + QQmlContextData *context, QQmlDelayedError *error, + QObject *scope, QObject *output, + QQmlPropertyPrivate::WriteFlags storeFlags +#ifdef QML_THREADED_INTERPRETER + ,void ***table +#endif + ) +{ +#ifdef QML_THREADED_INTERPRETER + if (table) { + static void *decode_instr[] = { + FOR_EACH_V4_INSTR(QML_V4_INSTR_ADDR) + }; + + *table = decode_instr; + return; + } +#endif + + + error->removeError(); + + Register registers[32]; + quint32 cleanupRegisterMask = 0; + + executedBlocks = 0; + + const char *code = program->instructions(); + code += instrIndex * QML_V4_INSTR_SIZE(Jump, jump); + const V4Instr *instr = reinterpret_cast(code); + + const char *data = program->data(); + + QString *testBindingSource = 0; + bool testBinding = false; + int bindingLine = 0; + int bindingColumn = 0; + +#ifdef QML_THREADED_INTERPRETER + goto *instr->common.code; +#else + for (;;) { + switch (instr->common.type) { +#endif + + QML_V4_BEGIN_INSTR(Noop, common) + QML_V4_END_INSTR(Noop, common) + + QML_V4_BEGIN_INSTR(BindingId, id) + bindingLine = instr->id.line; + bindingColumn = instr->id.column; + QML_V4_END_INSTR(BindingId, id) + + QML_V4_BEGIN_INSTR(SubscribeId, subscribeop) + subscribeId(context, instr->subscribeop.index, instr->subscribeop.offset); + QML_V4_END_INSTR(SubscribeId, subscribeop) + + QML_V4_BEGIN_INSTR(Subscribe, subscribeop) + { + QObject *o = 0; + const Register &object = registers[instr->subscribeop.reg]; + if (!object.isUndefined()) o = object.getQObject(); + subscribe(o, instr->subscribeop.index, instr->subscribeop.offset); + } + QML_V4_END_INSTR(Subscribe, subscribeop) + + QML_V4_BEGIN_INSTR(FetchAndSubscribe, fetchAndSubscribe) + { + Register ® = registers[instr->fetchAndSubscribe.reg]; + + if (reg.isUndefined()) + THROW_EXCEPTION(instr->fetchAndSubscribe.exceptionId); + + QObject *object = reg.getQObject(); + if (!object) { + reg.setUndefined(); + } else { + int subIdx = instr->fetchAndSubscribe.subscription; + Subscription *sub = 0; + if (subIdx != -1) { + sub = (subscriptions + subIdx); + sub->bindings = this; + sub->method = subIdx; + } + reg.init((Register::Type)instr->fetchAndSubscribe.valueType); + if (instr->fetchAndSubscribe.valueType >= FirstCleanupType) + MARK_REGISTER(instr->fetchAndSubscribe.reg); + QQmlAccessors *accessors = instr->fetchAndSubscribe.property.accessors; + accessors->read(object, instr->fetchAndSubscribe.property.accessorData, + reg.typeDataPtr()); + + if (accessors->notifier) { + QQmlNotifier *notifier = 0; + accessors->notifier(object, instr->fetchAndSubscribe.property.accessorData, ¬ifier); + if (notifier) sub->connect(notifier); + } else if (instr->fetchAndSubscribe.property.notifyIndex != -1) { + sub->connect(object, instr->fetchAndSubscribe.property.notifyIndex); + } + } + } + QML_V4_END_INSTR(FetchAndSubscribe, fetchAndSubscribe) + + QML_V4_BEGIN_INSTR(LoadId, load) + registers[instr->load.reg].setQObject(context->idValues[instr->load.index].data()); + QML_V4_END_INSTR(LoadId, load) + + QML_V4_BEGIN_INSTR(LoadScope, load) + registers[instr->load.reg].setQObject(scope); + QML_V4_END_INSTR(LoadScope, load) + + QML_V4_BEGIN_INSTR(LoadRoot, load) + registers[instr->load.reg].setQObject(context->contextObject); + QML_V4_END_INSTR(LoadRoot, load) + + QML_V4_BEGIN_INSTR(LoadAttached, attached) + { + const Register &input = registers[instr->attached.reg]; + Register &output = registers[instr->attached.output]; + if (input.isUndefined()) + THROW_EXCEPTION(instr->attached.exceptionId); + + QObject *object = registers[instr->attached.reg].getQObject(); + if (!object) { + output.setUndefined(); + } else { + QObject *attached = qmlAttachedPropertiesObjectById(instr->attached.id, input.getQObject(), true); + Q_ASSERT(attached); + output.setQObject(attached); + } + } + QML_V4_END_INSTR(LoadAttached, attached) + + QML_V4_BEGIN_INSTR(UnaryNot, unaryop) + { + registers[instr->unaryop.output].setbool(!registers[instr->unaryop.src].getbool()); + } + QML_V4_END_INSTR(UnaryNot, unaryop) + + QML_V4_BEGIN_INSTR(UnaryMinusReal, unaryop) + { + registers[instr->unaryop.output].setqreal(-registers[instr->unaryop.src].getqreal()); + } + QML_V4_END_INSTR(UnaryMinusReal, unaryop) + + QML_V4_BEGIN_INSTR(UnaryMinusInt, unaryop) + { + registers[instr->unaryop.output].setint(-registers[instr->unaryop.src].getint()); + } + QML_V4_END_INSTR(UnaryMinusInt, unaryop) + + QML_V4_BEGIN_INSTR(UnaryPlusReal, unaryop) + { + registers[instr->unaryop.output].setqreal(+registers[instr->unaryop.src].getqreal()); + } + QML_V4_END_INSTR(UnaryPlusReal, unaryop) + + QML_V4_BEGIN_INSTR(UnaryPlusInt, unaryop) + { + registers[instr->unaryop.output].setint(+registers[instr->unaryop.src].getint()); + } + QML_V4_END_INSTR(UnaryPlusInt, unaryop) + + QML_V4_BEGIN_INSTR(ConvertBoolToInt, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (src.isUndefined()) output.setUndefined(); + else output.setint(src.getbool()); + } + QML_V4_END_INSTR(ConvertBoolToInt, unaryop) + + QML_V4_BEGIN_INSTR(ConvertBoolToReal, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (src.isUndefined()) output.setUndefined(); + else output.setqreal(src.getbool()); + } + QML_V4_END_INSTR(ConvertBoolToReal, unaryop) + + QML_V4_BEGIN_INSTR(ConvertBoolToString, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (src.isUndefined()) { + output.setUndefined(); + } else { + new (output.getstringptr()) QString(QLatin1String(src.getbool() ? "true" : "false")); + STRING_REGISTER(instr->unaryop.output); + } + } + QML_V4_END_INSTR(ConvertBoolToString, unaryop) + + QML_V4_BEGIN_INSTR(ConvertIntToBool, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (src.isUndefined()) output.setUndefined(); + else output.setbool(src.getint()); + } + QML_V4_END_INSTR(ConvertIntToBool, unaryop) + + QML_V4_BEGIN_INSTR(ConvertIntToReal, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (src.isUndefined()) output.setUndefined(); + else output.setqreal(qreal(src.getint())); + } + QML_V4_END_INSTR(ConvertIntToReal, unaryop) + + QML_V4_BEGIN_INSTR(ConvertIntToString, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (src.isUndefined()) { + output.setUndefined(); + } else { + new (output.getstringptr()) QString(QString::number(src.getint())); + STRING_REGISTER(instr->unaryop.output); + } + } + QML_V4_END_INSTR(ConvertIntToString, unaryop) + + QML_V4_BEGIN_INSTR(ConvertRealToBool, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (src.isUndefined()) output.setUndefined(); + else output.setbool(src.getqreal() != 0); + } + QML_V4_END_INSTR(ConvertRealToBool, unaryop) + + QML_V4_BEGIN_INSTR(ConvertRealToInt, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (src.isUndefined()) output.setUndefined(); + else output.setint(toInt32(src.getqreal())); + } + QML_V4_END_INSTR(ConvertRealToInt, unaryop) + + QML_V4_BEGIN_INSTR(ConvertRealToString, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + // ### NaN + if (src.isUndefined()) { + output.setUndefined(); + } else { + new (output.getstringptr()) QString(QString::number(src.getqreal())); + STRING_REGISTER(instr->unaryop.output); + } + } + QML_V4_END_INSTR(ConvertRealToString, unaryop) + + QML_V4_BEGIN_INSTR(ConvertStringToBool, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + // ### NaN + if (src.isUndefined()) { + output.setUndefined(); + } else { + // Delegate the conversion. This is pretty fast and it doesn't require a QScriptEngine. + // Ideally we should just call the methods in the QScript namespace directly. + QJSValue tmp(*src.getstringptr()); + if (instr->unaryop.src == instr->unaryop.output) { + output.cleanupString(); + MARK_CLEAN_REGISTER(instr->unaryop.output); + } + output.setbool(tmp.toBool()); + } + } + QML_V4_END_INSTR(ConvertStringToBool, unaryop) + + QML_V4_BEGIN_INSTR(ConvertStringToInt, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + // ### NaN + if (src.isUndefined()) { + output.setUndefined(); + } else { + // Delegate the conversion. This is pretty fast and it doesn't require a QScriptEngine. + // Ideally we should just call the methods in the QScript namespace directly. + QJSValue tmp(*src.getstringptr()); + if (instr->unaryop.src == instr->unaryop.output) { + output.cleanupString(); + MARK_CLEAN_REGISTER(instr->unaryop.output); + } + output.setint(tmp.toInt()); + } + } + QML_V4_END_INSTR(ConvertStringToInt, unaryop) + + QML_V4_BEGIN_INSTR(ConvertStringToReal, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + // ### NaN + if (src.isUndefined()) { + output.setUndefined(); + } else { + // Delegate the conversion. This is pretty fast and it doesn't require a QScriptEngine. + // Ideally we should just call the methods in the QScript namespace directly. + QJSValue tmp(*src.getstringptr()); + if (instr->unaryop.src == instr->unaryop.output) { + output.cleanupString(); + MARK_CLEAN_REGISTER(instr->unaryop.output); + } + output.setqreal(tmp.toNumber()); + } + } + QML_V4_END_INSTR(ConvertStringToReal, unaryop) + + QML_V4_BEGIN_INSTR(ConvertStringToUrl, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + // ### NaN + if (src.isUndefined()) { + output.setUndefined(); + } else { + const QString tmp(*src.getstringptr()); + if (instr->unaryop.src == instr->unaryop.output) { + output.cleanupString(); + MARK_CLEAN_REGISTER(instr->unaryop.output); + } + QUrl *urlPtr = output.geturlptr(); + new (urlPtr) QUrl(); + urlPtr->setEncodedUrl(tmp.toUtf8(), QUrl::TolerantMode); + + URL_REGISTER(instr->unaryop.output); + } + } + QML_V4_END_INSTR(ConvertStringToUrl, unaryop) + ++ QML_V4_BEGIN_INSTR(ConvertStringToColor, unaryop) ++ { ++ const Register &src = registers[instr->unaryop.src]; ++ Register &output = registers[instr->unaryop.output]; ++ // ### NaN ++ if (src.isUndefined()) { ++ output.setUndefined(); ++ } else { ++ const QString tmp(*src.getstringptr()); ++ if (instr->unaryop.src == instr->unaryop.output) { ++ output.cleanupString(); ++ MARK_CLEAN_REGISTER(instr->unaryop.output); ++ } ++ QColor *colorPtr = output.getcolorptr(); ++ new (colorPtr) QColor(QQmlStringConverters::colorFromString(tmp)); ++ ++ COLOR_REGISTER(instr->unaryop.output); ++ } ++ } ++ QML_V4_END_INSTR(ConvertStringToUrl, unaryop) ++ + QML_V4_BEGIN_INSTR(ConvertUrlToBool, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + // ### NaN + if (src.isUndefined()) { + output.setUndefined(); + } else { + const QUrl tmp(*src.geturlptr()); + if (instr->unaryop.src == instr->unaryop.output) { + output.cleanupUrl(); + MARK_CLEAN_REGISTER(instr->unaryop.output); + } + output.setbool(!tmp.isEmpty()); + } + } + QML_V4_END_INSTR(ConvertUrlToBool, unaryop) + + QML_V4_BEGIN_INSTR(ConvertUrlToString, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + // ### NaN + if (src.isUndefined()) { + output.setUndefined(); + } else { + const QUrl tmp(*src.geturlptr()); + if (instr->unaryop.src == instr->unaryop.output) { + output.cleanupUrl(); + MARK_CLEAN_REGISTER(instr->unaryop.output); + } + new (output.getstringptr()) QString(tmp.toString()); + STRING_REGISTER(instr->unaryop.output); + } + } + QML_V4_END_INSTR(ConvertUrlToString, unaryop) + ++ QML_V4_BEGIN_INSTR(ConvertColorToBool, unaryop) ++ { ++ const Register &src = registers[instr->unaryop.src]; ++ Register &output = registers[instr->unaryop.output]; ++ // ### NaN ++ if (src.isUndefined()) { ++ output.setUndefined(); ++ } else { ++ // for compatibility with color behavior in v8, always true ++ output.setbool(true); ++ } ++ } ++ QML_V4_END_INSTR(ConvertColorToBool, unaryop) ++ ++ QML_V4_BEGIN_INSTR(ConvertColorToString, unaryop) ++ { ++ const Register &src = registers[instr->unaryop.src]; ++ Register &output = registers[instr->unaryop.output]; ++ // ### NaN ++ if (src.isUndefined()) { ++ output.setUndefined(); ++ } else { ++ const QColor tmp(*src.getcolorptr()); ++ if (instr->unaryop.src == instr->unaryop.output) { ++ output.cleanupColor(); ++ MARK_CLEAN_REGISTER(instr->unaryop.output); ++ } ++ // to maintain behaviour with QtQuick 1.0, we just output normal toString() value. ++ new (output.getstringptr()) QString(QVariant(tmp).toString()); ++ STRING_REGISTER(instr->unaryop.output); ++ } ++ } ++ QML_V4_END_INSTR(ConvertColorToString, unaryop) ++ + QML_V4_BEGIN_INSTR(ResolveUrl, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (src.isUndefined()) { + output.setUndefined(); + } else { + const QUrl tmp(*src.geturlptr()); + if (instr->unaryop.src == instr->unaryop.output) { + *output.geturlptr() = context->resolvedUrl(tmp); + } else { + new (output.geturlptr()) QUrl(context->resolvedUrl(tmp)); + URL_REGISTER(instr->unaryop.output); + } + } + } + QML_V4_END_INSTR(ResolveUrl, unaryop) + + QML_V4_BEGIN_INSTR(MathSinReal, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (src.isUndefined()) output.setUndefined(); + else output.setqreal(qSin(src.getqreal())); + } + QML_V4_END_INSTR(MathSinReal, unaryop) + + QML_V4_BEGIN_INSTR(MathCosReal, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (src.isUndefined()) output.setUndefined(); + else output.setqreal(qCos(src.getqreal())); + } + QML_V4_END_INSTR(MathCosReal, unaryop) + + QML_V4_BEGIN_INSTR(MathRoundReal, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (src.isUndefined()) output.setUndefined(); + else output.setint(qRound(src.getqreal())); + } + QML_V4_END_INSTR(MathRoundReal, unaryop) + + QML_V4_BEGIN_INSTR(MathFloorReal, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (src.isUndefined()) output.setUndefined(); + else output.setint(qFloor(src.getqreal())); + } + QML_V4_END_INSTR(MathFloorReal, unaryop) + + QML_V4_BEGIN_INSTR(MathPIReal, unaryop) + { + static const qreal qmlPI = 2.0 * qAsin(1.0); + Register &output = registers[instr->unaryop.output]; + output.setqreal(qmlPI); + } + QML_V4_END_INSTR(MathPIReal, unaryop) + + QML_V4_BEGIN_INSTR(LoadReal, real_value) + registers[instr->real_value.reg].setqreal(instr->real_value.value); + QML_V4_END_INSTR(LoadReal, real_value) + + QML_V4_BEGIN_INSTR(LoadInt, int_value) + registers[instr->int_value.reg].setint(instr->int_value.value); + QML_V4_END_INSTR(LoadInt, int_value) + + QML_V4_BEGIN_INSTR(LoadBool, bool_value) + registers[instr->bool_value.reg].setbool(instr->bool_value.value); + QML_V4_END_INSTR(LoadBool, bool_value) + + QML_V4_BEGIN_INSTR(LoadString, string_value) + { + Register &output = registers[instr->string_value.reg]; + QChar *string = (QChar *)(data + instr->string_value.offset); + new (output.getstringptr()) QString(string, instr->string_value.length); + STRING_REGISTER(instr->string_value.reg); + } + QML_V4_END_INSTR(LoadString, string_value) + + QML_V4_BEGIN_INSTR(EnableV4Test, string_value) + { + testBindingSource = new QString((QChar *)(data + instr->string_value.offset), instr->string_value.length); + testBinding = true; + } + QML_V4_END_INSTR(String, string_value) + + QML_V4_BEGIN_INSTR(BitAndInt, binaryop) + { + registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() & + registers[instr->binaryop.right].getint()); + } + QML_V4_END_INSTR(BitAndInt, binaryop) + + QML_V4_BEGIN_INSTR(BitOrInt, binaryop) + { + registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() | + registers[instr->binaryop.right].getint()); + } + QML_V4_END_INSTR(BitAndInt, binaryop) + + QML_V4_BEGIN_INSTR(BitXorInt, binaryop) + { + registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() ^ + registers[instr->binaryop.right].getint()); + } + QML_V4_END_INSTR(BitXorInt, binaryop) + + QML_V4_BEGIN_INSTR(AddReal, binaryop) + { + registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() + + registers[instr->binaryop.right].getqreal()); + } + QML_V4_END_INSTR(AddReal, binaryop) + + QML_V4_BEGIN_INSTR(AddString, binaryop) + { + QString &string = *registers[instr->binaryop.output].getstringptr(); + if (instr->binaryop.output == instr->binaryop.left) { + string += registers[instr->binaryop.right].getstringptr(); + } else { + string = *registers[instr->binaryop.left].getstringptr() + + *registers[instr->binaryop.right].getstringptr(); + } + } + QML_V4_END_INSTR(AddString, binaryop) + + QML_V4_BEGIN_INSTR(SubReal, binaryop) + { + registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() - + registers[instr->binaryop.right].getqreal()); + } + QML_V4_END_INSTR(SubReal, binaryop) + + QML_V4_BEGIN_INSTR(MulReal, binaryop) + { + registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() * + registers[instr->binaryop.right].getqreal()); + } + QML_V4_END_INSTR(MulReal, binaryop) + + QML_V4_BEGIN_INSTR(DivReal, binaryop) + { + registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() / + registers[instr->binaryop.right].getqreal()); + } + QML_V4_END_INSTR(DivReal, binaryop) + + QML_V4_BEGIN_INSTR(ModReal, binaryop) + { + Register &target = registers[instr->binaryop.output]; + const Register &left = registers[instr->binaryop.left]; + const Register &right = registers[instr->binaryop.right]; + if (QMetaType::QReal == QMetaType::Float) + target.setqreal(::fmodf(left.getqreal(), right.getqreal())); + else + target.setqreal(::fmod(left.getqreal(), right.getqreal())); + } + QML_V4_END_INSTR(ModInt, binaryop) + + QML_V4_BEGIN_INSTR(LShiftInt, binaryop) + { + registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() << + registers[instr->binaryop.right].getint()); + } + QML_V4_END_INSTR(LShiftInt, binaryop) + + QML_V4_BEGIN_INSTR(RShiftInt, binaryop) + { + registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() >> + registers[instr->binaryop.right].getint()); + } + QML_V4_END_INSTR(RShiftInt, binaryop) + + QML_V4_BEGIN_INSTR(URShiftInt, binaryop) + { + registers[instr->binaryop.output].setint((unsigned)registers[instr->binaryop.left].getint() >> + registers[instr->binaryop.right].getint()); + } + QML_V4_END_INSTR(URShiftInt, binaryop) + + QML_V4_BEGIN_INSTR(GtReal, binaryop) + { + registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() > + registers[instr->binaryop.right].getqreal()); + } + QML_V4_END_INSTR(GtReal, binaryop) + + QML_V4_BEGIN_INSTR(LtReal, binaryop) + { + registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() < + registers[instr->binaryop.right].getqreal()); + } + QML_V4_END_INSTR(LtReal, binaryop) + + QML_V4_BEGIN_INSTR(GeReal, binaryop) + { + registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() >= + registers[instr->binaryop.right].getqreal()); + } + QML_V4_END_INSTR(GeReal, binaryop) + + QML_V4_BEGIN_INSTR(LeReal, binaryop) + { + registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() <= + registers[instr->binaryop.right].getqreal()); + } + QML_V4_END_INSTR(LeReal, binaryop) + + QML_V4_BEGIN_INSTR(EqualReal, binaryop) + { + registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() == + registers[instr->binaryop.right].getqreal()); + } + QML_V4_END_INSTR(EqualReal, binaryop) + + QML_V4_BEGIN_INSTR(NotEqualReal, binaryop) + { + registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() != + registers[instr->binaryop.right].getqreal()); + } + QML_V4_END_INSTR(NotEqualReal, binaryop) + + QML_V4_BEGIN_INSTR(StrictEqualReal, binaryop) + { + registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() == + registers[instr->binaryop.right].getqreal()); + } + QML_V4_END_INSTR(StrictEqualReal, binaryop) + + QML_V4_BEGIN_INSTR(StrictNotEqualReal, binaryop) + { + registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() != + registers[instr->binaryop.right].getqreal()); + } + QML_V4_END_INSTR(StrictNotEqualReal, binaryop) + + QML_V4_BEGIN_INSTR(GtString, binaryop) + { + const QString &a = *registers[instr->binaryop.left].getstringptr(); + const QString &b = *registers[instr->binaryop.right].getstringptr(); + bool result = a > b; + if (instr->binaryop.left == instr->binaryop.output) { + registers[instr->binaryop.output].cleanupString(); + MARK_CLEAN_REGISTER(instr->binaryop.output); + } + registers[instr->binaryop.output].setbool(result); + } + QML_V4_END_INSTR(GtString, binaryop) + + QML_V4_BEGIN_INSTR(LtString, binaryop) + { + const QString &a = *registers[instr->binaryop.left].getstringptr(); + const QString &b = *registers[instr->binaryop.right].getstringptr(); + bool result = a < b; + if (instr->binaryop.left == instr->binaryop.output) { + registers[instr->binaryop.output].cleanupString(); + MARK_CLEAN_REGISTER(instr->binaryop.output); + } + registers[instr->binaryop.output].setbool(result); + } + QML_V4_END_INSTR(LtString, binaryop) + + QML_V4_BEGIN_INSTR(GeString, binaryop) + { + const QString &a = *registers[instr->binaryop.left].getstringptr(); + const QString &b = *registers[instr->binaryop.right].getstringptr(); + bool result = a >= b; + if (instr->binaryop.left == instr->binaryop.output) { + registers[instr->binaryop.output].cleanupString(); + MARK_CLEAN_REGISTER(instr->binaryop.output); + } + registers[instr->binaryop.output].setbool(result); + } + QML_V4_END_INSTR(GeString, binaryop) + + QML_V4_BEGIN_INSTR(LeString, binaryop) + { + const QString &a = *registers[instr->binaryop.left].getstringptr(); + const QString &b = *registers[instr->binaryop.right].getstringptr(); + bool result = a <= b; + if (instr->binaryop.left == instr->binaryop.output) { + registers[instr->binaryop.output].cleanupString(); + MARK_CLEAN_REGISTER(instr->binaryop.output); + } + registers[instr->binaryop.output].setbool(result); + } + QML_V4_END_INSTR(LeString, binaryop) + + QML_V4_BEGIN_INSTR(EqualString, binaryop) + { + const QString &a = *registers[instr->binaryop.left].getstringptr(); + const QString &b = *registers[instr->binaryop.right].getstringptr(); + bool result = a == b; + if (instr->binaryop.left == instr->binaryop.output) { + registers[instr->binaryop.output].cleanupString(); + MARK_CLEAN_REGISTER(instr->binaryop.output); + } + registers[instr->binaryop.output].setbool(result); + } + QML_V4_END_INSTR(EqualString, binaryop) + + QML_V4_BEGIN_INSTR(NotEqualString, binaryop) + { + const QString &a = *registers[instr->binaryop.left].getstringptr(); + const QString &b = *registers[instr->binaryop.right].getstringptr(); + bool result = a != b; + if (instr->binaryop.left == instr->binaryop.output) { + registers[instr->binaryop.output].cleanupString(); + MARK_CLEAN_REGISTER(instr->binaryop.output); + } + registers[instr->binaryop.output].setbool(result); + } + QML_V4_END_INSTR(NotEqualString, binaryop) + + QML_V4_BEGIN_INSTR(StrictEqualString, binaryop) + { + const QString &a = *registers[instr->binaryop.left].getstringptr(); + const QString &b = *registers[instr->binaryop.right].getstringptr(); + bool result = a == b; + if (instr->binaryop.left == instr->binaryop.output) { + registers[instr->binaryop.output].cleanupString(); + MARK_CLEAN_REGISTER(instr->binaryop.output); + } + registers[instr->binaryop.output].setbool(result); + } + QML_V4_END_INSTR(StrictEqualString, binaryop) + + QML_V4_BEGIN_INSTR(StrictNotEqualString, binaryop) + { + const QString &a = *registers[instr->binaryop.left].getstringptr(); + const QString &b = *registers[instr->binaryop.right].getstringptr(); + bool result = a != b; + if (instr->binaryop.left == instr->binaryop.output) { + registers[instr->binaryop.output].cleanupString(); + MARK_CLEAN_REGISTER(instr->binaryop.output); + } + registers[instr->binaryop.output].setbool(result); + } + QML_V4_END_INSTR(StrictNotEqualString, binaryop) + + QML_V4_BEGIN_INSTR(NewString, construct) + { + Register &output = registers[instr->construct.reg]; + new (output.getstringptr()) QString; + STRING_REGISTER(instr->construct.reg); + } + QML_V4_END_INSTR(NewString, construct) + + QML_V4_BEGIN_INSTR(NewUrl, construct) + { + Register &output = registers[instr->construct.reg]; + new (output.geturlptr()) QUrl; + URL_REGISTER(instr->construct.reg); + } + QML_V4_END_INSTR(NewUrl, construct) + + QML_V4_BEGIN_INSTR(Fetch, fetch) + { + Register ® = registers[instr->fetch.reg]; + + if (reg.isUndefined()) + THROW_EXCEPTION(instr->fetch.exceptionId); + + QObject *object = reg.getQObject(); + if (!object) { + THROW_EXCEPTION(instr->fetch.exceptionId); + } else { + reg.init((Register::Type)instr->fetch.valueType); + if (instr->fetch.valueType >= FirstCleanupType) + MARK_REGISTER(instr->fetch.reg); + void *argv[] = { reg.typeDataPtr(), 0 }; + QMetaObject::metacall(object, QMetaObject::ReadProperty, instr->fetch.index, argv); + } + } + QML_V4_END_INSTR(Fetch, fetch) + + QML_V4_BEGIN_INSTR(TestV4Store, storetest) + { + Register &data = registers[instr->storetest.reg]; + testBindingResult(*testBindingSource, bindingLine, bindingColumn, context, + scope, data, instr->storetest.regType); + } + QML_V4_END_INSTR(TestV4Store, storetest) + + QML_V4_BEGIN_INSTR(Store, store) + { + Register &data = registers[instr->store.reg]; + + if (data.isUndefined()) + THROW_EXCEPTION_STR(instr->store.exceptionId, QLatin1String("Unable to assign undefined value")); + + int status = -1; + void *argv[] = { data.typeDataPtr(), 0, &status, &storeFlags }; + QMetaObject::metacall(output, QMetaObject::WriteProperty, + instr->store.index, argv); + + goto programExit; + } + QML_V4_END_INSTR(Store, store) + + QML_V4_BEGIN_INSTR(Copy, copy) + registers[instr->copy.reg].copy(registers[instr->copy.src]); + if (registers[instr->copy.reg].gettype() >= FirstCleanupType) + MARK_REGISTER(instr->copy.reg); + QML_V4_END_INSTR(Copy, copy) + + QML_V4_BEGIN_INSTR(Jump, jump) + if (instr->jump.reg == -1 || !registers[instr->jump.reg].getbool()) + code += instr->jump.count; + QML_V4_END_INSTR(Jump, jump) + + QML_V4_BEGIN_INSTR(BranchTrue, branchop) + if (registers[instr->branchop.reg].getbool()) + code += instr->branchop.offset; + QML_V4_END_INSTR(BranchTrue, branchop) + + QML_V4_BEGIN_INSTR(BranchFalse, branchop) + if (! registers[instr->branchop.reg].getbool()) + code += instr->branchop.offset; + QML_V4_END_INSTR(BranchFalse, branchop) + + QML_V4_BEGIN_INSTR(Branch, branchop) + code += instr->branchop.offset; + QML_V4_END_INSTR(Branch, branchop) + + QML_V4_BEGIN_INSTR(Block, blockop) + executedBlocks |= instr->blockop.block; + QML_V4_END_INSTR(Block, blockop) + + // XXX not applicable in v8 + QML_V4_BEGIN_INSTR(InitString, initstring) +// if (!identifiers[instr->initstring.offset].identifier) { +// quint32 len = *(quint32 *)(data + instr->initstring.dataIdx); +// QChar *strdata = (QChar *)(data + instr->initstring.dataIdx + sizeof(quint32)); + +// QString str = QString::fromRawData(strdata, len); + +// // identifiers[instr->initstring.offset] = engine->objectClass->createPersistentIdentifier(str); +// } + QML_V4_END_INSTR(InitString, initstring) + + QML_V4_BEGIN_INSTR(CleanupRegister, cleanup) + registers[instr->cleanup.reg].cleanup(); + QML_V4_END_INSTR(CleanupRegister, cleanup) + +#ifdef QML_THREADED_INTERPRETER + // nothing to do +#else + default: + qFatal("QV4: Unknown instruction %d encountered.", instr->common.type); + break; + } // switch + + } // while +#endif + + Q_ASSERT(!"Unreachable code reached"); + +programExit: +exceptionExit: + delete testBindingSource; + + int reg = 0; + while (cleanupRegisterMask) { + if (cleanupRegisterMask & 0x1) + registers[reg].cleanup(); + + reg++; + cleanupRegisterMask >>= 1; + } +} + +QT_END_NAMESPACE diff --cc src/qml/qml/v4/qv4bindings_p.h index 61d29a6,0000000..1824fa4 mode 100644,000000..100644 --- a/src/qml/qml/v4/qv4bindings_p.h +++ b/src/qml/qml/v4/qv4bindings_p.h @@@ -1,153 -1,0 +1,155 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QV4BINDINGS_P_H +#define QV4BINDINGS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "private/qqmlexpression_p.h" +#include "private/qqmlbinding_p.h" +#include "private/qv4instruction_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +struct QV4Program; +class QV4Bindings : public QQmlAbstractExpression, + public QQmlRefCount +{ + Q_DECLARE_TR_FUNCTIONS(QV4Bindings) +public: + QV4Bindings(const char *program, QQmlContextData *context, + QQmlRefCount *); + virtual ~QV4Bindings(); + + QQmlAbstractBinding *configBinding(int index, QObject *target, + QObject *scope, int property, + int line, int column); + +#ifdef QML_THREADED_INTERPRETER + static void **getDecodeInstrTable(); +#endif + +private: + Q_DISABLE_COPY(QV4Bindings) + + struct Binding : public QQmlAbstractBinding, public QQmlDelayedError { + Binding() : enabled(false), updating(0), property(0), + scope(0), target(0), executedBlocks(0), parent(0) {} + + // Inherited from QQmlAbstractBinding + virtual void setEnabled(bool, QQmlPropertyPrivate::WriteFlags flags); + virtual void update(QQmlPropertyPrivate::WriteFlags flags); + virtual void destroy(); + virtual int propertyIndex() const; + virtual QObject *object() const; + + int index:30; + bool enabled:1; + bool updating:1; ++ // Encoding of property is coreIndex | (propType << 16) | (valueTypeIndex << 24) ++ // propType and valueTypeIndex are only set if the property is a value type property + int property; + QObject *scope; + int line; + int column; + QObject *target; + quint32 executedBlocks; + + QV4Bindings *parent; + }; + + class Subscription : public QQmlNotifierEndpoint + { + public: + Subscription() : bindings(0), method(-1) { callback = &subscriptionCallback; } + static void subscriptionCallback(QQmlNotifierEndpoint *e); + QV4Bindings *bindings; + int method; + }; + friend class Subscription; + + Subscription *subscriptions; + + void subscriptionNotify(int); + void run(Binding *, QQmlPropertyPrivate::WriteFlags flags); + + QV4Program *program; + QQmlRefCount *dataRef; + Binding *bindings; + + void init(); + void run(int instr, quint32 &executedBlocks, QQmlContextData *context, + QQmlDelayedError *error, QObject *scope, QObject *output, + QQmlPropertyPrivate::WriteFlags storeFlags +#ifdef QML_THREADED_INTERPRETER + , void ***decode_instr = 0 +#endif + ); + + + inline void unsubscribe(int subIndex); + inline void subscribeId(QQmlContextData *p, int idIndex, int subIndex); + inline void subscribe(QObject *o, int notifyIndex, int subIndex); + + inline static qint32 toInt32(qreal n); + static const qreal D32; + static quint32 toUint32(qreal n); + +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QV4BINDINGS_P_H + diff --cc src/qml/qml/v4/qv4compiler.cpp index d61fd58,0000000..f8fe3b4 mode 100644,000000..100644 --- a/src/qml/qml/v4/qv4compiler.cpp +++ b/src/qml/qml/v4/qv4compiler.cpp @@@ -1,1399 -1,0 +1,1420 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qv4compiler_p.h" +#include "qv4compiler_p_p.h" +#include "qv4program_p.h" +#include "qv4ir_p.h" +#include "qv4irbuilder_p.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +DEFINE_BOOL_CONFIG_OPTION(bindingsDump, QML_BINDINGS_DUMP) +DEFINE_BOOL_CONFIG_OPTION(qmlDisableOptimizer, QML_DISABLE_OPTIMIZER) +DEFINE_BOOL_CONFIG_OPTION(qmlExperimental, QML_EXPERIMENTAL) +DEFINE_BOOL_CONFIG_OPTION(qmlVerboseCompiler, QML_VERBOSE_COMPILER) +DEFINE_BOOL_CONFIG_OPTION(qmlBindingsTestEnv, QML_BINDINGS_TEST) + +static bool qmlBindingsTest = false; +static bool qmlEnableV4 = true; + +using namespace QQmlJS; +QV4CompilerPrivate::QV4CompilerPrivate() - : _function(0) , _block(0) , _discarded(false) ++ : _function(0) , _block(0) , _discarded(false), registerCount(0) +{ +} + +// +// tracing +// +void QV4CompilerPrivate::trace(int line, int column) +{ + bytecode.clear(); + + this->currentReg = _function->tempCount; ++ this->registerCount = qMax(this->registerCount, this->currentReg); + + foreach (IR::BasicBlock *bb, _function->basicBlocks) { + if (! bb->isTerminated() && (bb->index + 1) < _function->basicBlocks.size()) + bb->JUMP(_function->basicBlocks.at(bb->index + 1)); + } + + QVector blocks; + trace(&blocks); + currentBlockMask = 0x00000001; + + + for (int i = 0; !_discarded && i < blocks.size(); ++i) { + IR::BasicBlock *block = blocks.at(i); + IR::BasicBlock *next = i + 1 < blocks.size() ? blocks.at(i + 1) : 0; + if (IR::Stmt *terminator = block->terminator()) { + if (IR::CJump *cj = terminator->asCJump()) { + if (cj->iffalse != next) { + IR::Jump *jump = _function->pool->New(); + jump->init(cj->iffalse); + block->statements.append(jump); + } + } else if (IR::Jump *j = terminator->asJump()) { + if (j->target == next) { + block->statements.resize(block->statements.size() - 1); + } + } + } + + block->offset = bytecode.size(); + + if (bytecode.isEmpty()) { + if (qmlBindingsTest || bindingsDump()) { + Instr::BindingId id; + id.column = column; + id.line = line; + gen(id); + } + + if (qmlBindingsTest) { + QString str = expression->expression.asScript(); + QByteArray strdata((const char *)str.constData(), str.length() * sizeof(QChar)); + int offset = data.count(); + data += strdata; + + Instr::EnableV4Test test; + test.reg = 0; + test.offset = offset; + test.length = str.length(); + gen(test); + } + } + + bool usic = false; + int patchesCount = patches.count(); + qSwap(usedSubscriptionIdsChanged, usic); + + int blockopIndex = bytecode.size(); + Instr::Block blockop; + blockop.block = currentBlockMask; + gen(blockop); + + foreach (IR::Stmt *s, block->statements) { + if (! _discarded) + s->accept(this); + } + + qSwap(usedSubscriptionIdsChanged, usic); + + if (usic) { + if (currentBlockMask == 0x80000000) { + discard(); + return; + } + currentBlockMask <<= 1; + } else if (! _discarded) { + const int adjust = bytecode.remove(blockopIndex); + // Correct patches + for (int ii = patchesCount; ii < patches.count(); ++ii) + patches[ii].offset -= adjust; + } + } + +#ifdef DEBUG_IR_STRUCTURE + IR::IRDump dump; + for (int i = 0; i < blocks.size(); ++i) { + dump.basicblock(blocks.at(i)); + } +#endif + + + if (! _discarded) { + // back patching + foreach (const Patch &patch, patches) { + V4Instr &instr = bytecode[patch.offset]; + int size = V4Instr::size(instructionType(&instr)); + instr.branchop.offset = patch.block->offset - patch.offset - size; + } + + patches.clear(); + } +} + +void QV4CompilerPrivate::trace(QVector *blocks) +{ + for (int i = 0; i < _function->basicBlocks.size(); ++i) { + IR::BasicBlock *block = _function->basicBlocks.at(i); + + while (! blocks->contains(block)) { + blocks->append(block); + + if (IR::Stmt *terminator = block->terminator()) { + if (IR::CJump *cj = terminator->asCJump()) + block = cj->iffalse; + else if (IR::Jump *j = terminator->asJump()) + block = j->target; + } + } + } +} + +void QV4CompilerPrivate::traceExpression(IR::Expr *e, quint8 r) +{ + if (!e) { + discard(); + } else { + qSwap(currentReg, r); + e->accept(this); + qSwap(currentReg, r); + } +} + +// +// expressions +// +void QV4CompilerPrivate::visitConst(IR::Const *e) +{ + switch (e->type) { + case IR::BoolType: { + Instr::LoadBool i; + i.reg = currentReg; + i.value = e->value; + gen(i); + } break; + + case IR::IntType: { + Instr::LoadInt i; + i.reg = currentReg; + i.value = e->value; + gen(i); + } break; + + case IR::RealType: { + Instr::LoadReal i; + i.reg = currentReg; + i.value = e->value; + gen(i); + } break; + + default: + if (qmlVerboseCompiler()) + qWarning() << Q_FUNC_INFO << "unexpected type"; + discard(); + } +} + +void QV4CompilerPrivate::visitString(IR::String *e) +{ + registerLiteralString(currentReg, e->value); +} + +void QV4CompilerPrivate::visitName(IR::Name *e) +{ + if (e->base) { + // fetch the object and store it in reg. + traceExpression(e->base, currentReg); + } else { + _subscribeName.clear(); + } + + if (e->storage == IR::Name::RootStorage) { + + Instr::LoadRoot instr; + instr.reg = currentReg; + gen(instr); + + if (e->symbol == IR::Name::IdObject) { + // The ID is a reference to the root object + return; + } + + } else if (e->storage == IR::Name::ScopeStorage) { + + Instr::LoadScope instr; + instr.reg = currentReg; + gen(instr); + + _subscribeName << contextName(); + + } else if (e->storage == IR::Name::IdStorage) { + + Instr::LoadId instr; + instr.reg = currentReg; + instr.index = e->idObject->idIndex; + gen(instr); + + _subscribeName << QLatin1String("$$$ID_") + *e->id; + + if (blockNeedsSubscription(_subscribeName)) { + Instr::SubscribeId sub; + sub.reg = currentReg; + sub.offset = subscriptionIndex(_subscribeName); + sub.index = instr.index; + gen(sub); + } + + return; + } else { + // No action needed + } + + switch (e->symbol) { + case IR::Name::Unbound: + case IR::Name::IdObject: + case IR::Name::Slot: + case IR::Name::Object: { + Q_ASSERT(!"Unreachable"); + discard(); + } break; + + case IR::Name::AttachType: { + _subscribeName << *e->id; + + Instr::LoadAttached attached; + attached.output = currentReg; + attached.reg = currentReg; + attached.exceptionId = exceptionId(e->line, e->column); + if (e->declarativeType->attachedPropertiesId() == -1) + discard(); + attached.id = e->declarativeType->attachedPropertiesId(); + gen(attached); + } break; + + case IR::Name::Property: { + _subscribeName << *e->id; + + if (e->property->coreIndex == -1) { + QMetaProperty prop; + e->property->load(prop, QQmlEnginePrivate::get(engine)); + } + + const int propTy = e->property->propType; + QQmlRegisterType regType; + + switch (propTy) { + case QMetaType::QReal: + regType = QRealType; + break; + case QMetaType::Bool: + regType = BoolType; + break; + case QMetaType::Int: + regType = IntType; + break; + case QMetaType::QString: + regType = QStringType; + break; + case QMetaType::QUrl: + regType = QUrlType; + break; ++ case QMetaType::QColor: ++ regType = QColorType; ++ break; + + default: + if (propTy == QQmlMetaType::QQuickAnchorLineMetaTypeId()) { + regType = PODValueType; + } else if (QQmlMetaType::isQObject(propTy)) { + regType = QObjectStarType; + } else { + if (qmlVerboseCompiler()) + qWarning() << "Discard unsupported property type:" << QMetaType::typeName(propTy); + discard(); // Unsupported type + return; + } + + break; + } // switch + + if (e->property->hasAccessors()) { + Instr::FetchAndSubscribe fetch; + fetch.reg = currentReg; + fetch.subscription = subscriptionIndex(_subscribeName); + fetch.exceptionId = exceptionId(e->line, e->column); + fetch.valueType = regType; + fetch.property = *e->property; + gen(fetch); + } else { + if (blockNeedsSubscription(_subscribeName) && e->property->notifyIndex != -1) { + Instr::Subscribe sub; + sub.reg = currentReg; + sub.offset = subscriptionIndex(_subscribeName); + sub.index = e->property->notifyIndex; + gen(sub); + } + + Instr::Fetch fetch; + fetch.reg = currentReg; + fetch.index = e->property->coreIndex; + fetch.exceptionId = exceptionId(e->line, e->column); + fetch.valueType = regType; + gen(fetch); + } + + } break; + } // switch +} + +void QV4CompilerPrivate::visitTemp(IR::Temp *e) +{ + if (currentReg != e->index) { + Instr::Copy i; + i.reg = currentReg; + i.src = e->index; + gen(i); + } +} + +void QV4CompilerPrivate::visitUnop(IR::Unop *e) +{ + quint8 src = currentReg; + + if (IR::Temp *temp = e->expr->asTemp()) { + src = temp->index; + } else { + traceExpression(e->expr, src); + } + + switch (e->op) { + case IR::OpInvalid: + Q_ASSERT(!"unreachable"); + break; + + case IR::OpIfTrue: + convertToBool(e->expr, src); + if (src != currentReg) { + Instr::Copy i; + i.reg = currentReg; + i.src = src; + gen(i); + } + break; + + case IR::OpNot: { + Instr::UnaryNot i; + convertToBool(e->expr, src); + i.output = currentReg; + i.src = src; + gen(i); + } break; + + case IR::OpUMinus: + if (e->expr->type == IR::RealType) { + Instr::UnaryMinusReal i; + i.output = currentReg; + i.src = src; + gen(i); + } else if (e->expr->type == IR::IntType) { + convertToReal(e->expr, currentReg); + Instr::UnaryMinusReal i; + i.output = currentReg; + i.src = src; + gen(i); + } else { + discard(); + } + break; + + case IR::OpUPlus: + if (e->expr->type == IR::RealType) { + Instr::UnaryPlusReal i; + i.output = currentReg; + i.src = src; + gen(i); + } else if (e->expr->type == IR::IntType) { + convertToReal(e->expr, currentReg); + Instr::UnaryPlusReal i; + i.output = currentReg; + i.src = src; + gen(i); + } else { + discard(); + } + break; + + case IR::OpCompl: + // TODO + discard(); + break; + + case IR::OpBitAnd: + case IR::OpBitOr: + case IR::OpBitXor: + case IR::OpAdd: + case IR::OpSub: + case IR::OpMul: + case IR::OpDiv: + case IR::OpMod: + case IR::OpLShift: + case IR::OpRShift: + case IR::OpURShift: + case IR::OpGt: + case IR::OpLt: + case IR::OpGe: + case IR::OpLe: + case IR::OpEqual: + case IR::OpNotEqual: + case IR::OpStrictEqual: + case IR::OpStrictNotEqual: + case IR::OpAnd: + case IR::OpOr: + Q_ASSERT(!"unreachable"); + break; + } // switch +} + +void QV4CompilerPrivate::convertToReal(IR::Expr *expr, int reg) +{ + if (expr->type == IR::RealType) + return; + + switch (expr->type) { + case IR::BoolType: { + Instr::ConvertBoolToReal i; + i.output = i.src = reg; + gen(i); + } break; + + case IR::IntType: { + Instr::ConvertIntToReal i; + i.output = i.src = reg; + gen(i); + } break; + + case IR::RealType: + // nothing to do + return; + + default: + discard(); + break; + } // switch +} + +void QV4CompilerPrivate::convertToInt(IR::Expr *expr, int reg) +{ + if (expr->type == IR::IntType) + return; + + switch (expr->type) { + case IR::BoolType: { + Instr::ConvertBoolToInt i; + i.output = i.src = reg; + gen(i); + } break; + + case IR::IntType: + // nothing to do + return; + + case IR::RealType: { + Instr::ConvertRealToInt i; + i.output = i.src = reg; + gen(i); + } break; + + default: + discard(); + break; + } // switch +} + +void QV4CompilerPrivate::convertToBool(IR::Expr *expr, int reg) +{ + if (expr->type == IR::BoolType) + return; + + switch (expr->type) { + case IR::BoolType: + // nothing to do + break; + + case IR::IntType: { + Instr::ConvertIntToBool i; + i.output = i.src = reg; + gen(i); + } break; + + case IR::RealType: { + Instr::ConvertRealToBool i; + i.output = i.src = reg; + gen(i); + } return; + + case IR::StringType: { + Instr::ConvertStringToBool i; + i.output = i.src = reg; + gen(i); + } return; + ++ case IR::ColorType: { ++ Instr::ConvertColorToBool i; ++ i.output = i.src = reg; ++ gen(i); ++ } return; ++ + default: + discard(); + break; + } // switch +} + +quint8 QV4CompilerPrivate::instructionOpcode(IR::Binop *e) +{ + switch (e->op) { + case IR::OpInvalid: + return V4Instr::Noop; + + case IR::OpIfTrue: + case IR::OpNot: + case IR::OpUMinus: + case IR::OpUPlus: + case IR::OpCompl: + return V4Instr::Noop; + + case IR::OpBitAnd: + return V4Instr::BitAndInt; + + case IR::OpBitOr: + return V4Instr::BitOrInt; + + case IR::OpBitXor: + return V4Instr::BitXorInt; + + case IR::OpAdd: + if (e->type == IR::StringType) + return V4Instr::AddString; + return V4Instr::AddReal; + + case IR::OpSub: + return V4Instr::SubReal; + + case IR::OpMul: + return V4Instr::MulReal; + + case IR::OpDiv: + return V4Instr::DivReal; + + case IR::OpMod: + return V4Instr::ModReal; + + case IR::OpLShift: + return V4Instr::LShiftInt; + + case IR::OpRShift: + return V4Instr::RShiftInt; + + case IR::OpURShift: + return V4Instr::URShiftInt; + + case IR::OpGt: + if (e->left->type == IR::StringType) + return V4Instr::GtString; + return V4Instr::GtReal; + + case IR::OpLt: + if (e->left->type == IR::StringType) + return V4Instr::LtString; + return V4Instr::LtReal; + + case IR::OpGe: + if (e->left->type == IR::StringType) + return V4Instr::GeString; + return V4Instr::GeReal; + + case IR::OpLe: + if (e->left->type == IR::StringType) + return V4Instr::LeString; + return V4Instr::LeReal; + + case IR::OpEqual: + if (e->left->type == IR::StringType) + return V4Instr::EqualString; + return V4Instr::EqualReal; + + case IR::OpNotEqual: + if (e->left->type == IR::StringType) + return V4Instr::NotEqualString; + return V4Instr::NotEqualReal; + + case IR::OpStrictEqual: + if (e->left->type == IR::StringType) + return V4Instr::StrictEqualString; + return V4Instr::StrictEqualReal; + + case IR::OpStrictNotEqual: + if (e->left->type == IR::StringType) + return V4Instr::StrictNotEqualString; + return V4Instr::StrictNotEqualReal; + + case IR::OpAnd: + case IR::OpOr: + return V4Instr::Noop; + + } // switch + + return V4Instr::Noop; +} + +void QV4CompilerPrivate::visitBinop(IR::Binop *e) +{ + int left = currentReg; + int right = currentReg + 1; + + if (e->left->asTemp() && e->type != IR::StringType) // Not sure if the e->type != String test is needed + left = e->left->asTemp()->index; + else + traceExpression(e->left, left); + + if (IR::Temp *t = e->right->asTemp()) + right = t->index; + else + traceExpression(e->right, right); + + if (e->left->type != e->right->type) { + if (qmlVerboseCompiler()) + qWarning().nospace() << "invalid operands to binary operator " << IR::binaryOperator(e->op) + << "(`" << IR::binaryOperator(e->left->type) + << "' and `" + << IR::binaryOperator(e->right->type) + << "'"; + discard(); + return; + } + + switch (e->op) { + case IR::OpInvalid: + discard(); + break; + + // unary + case IR::OpIfTrue: + case IR::OpNot: + case IR::OpUMinus: + case IR::OpUPlus: + case IR::OpCompl: + discard(); + break; + + case IR::OpBitAnd: + case IR::OpBitOr: + case IR::OpBitXor: + case IR::OpLShift: + case IR::OpRShift: + case IR::OpURShift: + convertToInt(e->left, left); + convertToInt(e->right, right); + break; + + case IR::OpAdd: + if (e->type != IR::StringType) { + convertToReal(e->left, left); + convertToReal(e->right, right); + } + break; + + case IR::OpSub: + case IR::OpMul: + case IR::OpDiv: + case IR::OpMod: + convertToReal(e->left, left); + convertToReal(e->right, right); + break; + + case IR::OpGt: + case IR::OpLt: + case IR::OpGe: + case IR::OpLe: + case IR::OpEqual: + case IR::OpNotEqual: + case IR::OpStrictEqual: + case IR::OpStrictNotEqual: + if (e->left->type != IR::StringType) { + convertToReal(e->left, left); + convertToReal(e->right, right); + } + break; + + case IR::OpAnd: + case IR::OpOr: + discard(); // ### unreachable + break; + } // switch + + const quint8 opcode = instructionOpcode(e); + if (opcode != V4Instr::Noop) { + V4Instr instr; + instr.binaryop.output = currentReg; + instr.binaryop.left = left; + instr.binaryop.right = right; + gen(static_cast(opcode), instr); + } +} + +void QV4CompilerPrivate::visitCall(IR::Call *call) +{ + if (IR::Name *name = call->base->asName()) { + IR::Expr *arg = call->onlyArgument(); + if (arg != 0 && arg->type == IR::RealType) { + traceExpression(arg, currentReg); + + switch (name->builtin) { + case IR::NoBuiltinSymbol: + break; + + case IR::MathSinBultinFunction: { + Instr::MathSinReal i; + i.output = i.src = currentReg; + gen(i); + } return; + + case IR::MathCosBultinFunction: { + Instr::MathCosReal i; + i.output = i.src = currentReg; + gen(i); + } return; + + case IR::MathRoundBultinFunction: { + Instr::MathRoundReal i; + i.output = i.src = currentReg; + gen(i); + } return; + + case IR::MathFloorBultinFunction: { + Instr::MathFloorReal i; + i.output = i.src = currentReg; + gen(i); + } return; + + case IR::MathPIBuiltinConstant: + break; + } // switch + } + } + + if (qmlVerboseCompiler()) + qWarning() << "TODO:" << Q_FUNC_INFO << __LINE__; + discard(); +} + + +// +// statements +// +void QV4CompilerPrivate::visitExp(IR::Exp *s) +{ + traceExpression(s->expr, currentReg); +} + +void QV4CompilerPrivate::visitMove(IR::Move *s) +{ + IR::Temp *target = s->target->asTemp(); + Q_ASSERT(target != 0); + + quint8 dest = target->index; + + if (target->type != s->source->type) { + quint8 src = dest; + + if (IR::Temp *t = s->source->asTemp()) + src = t->index; + else + traceExpression(s->source, dest); + + V4Instr::Type opcode = V4Instr::Noop; + IR::Type targetTy = s->target->type; + IR::Type sourceTy = s->source->type; + + if (sourceTy == IR::UrlType) { + switch (targetTy) { + case IR::BoolType: + case IR::StringType: + // nothing to do. V4 will generate optimized + // url-to-xxx conversions. + break; + default: { + // generate a UrlToString conversion and fix + // the type of the source expression. + V4Instr conv; + conv.unaryop.output = V4Instr::ConvertUrlToString; + conv.unaryop.src = src; + gen(opcode, conv); + + sourceTy = IR::StringType; + break; + } + } // switch + } + + if (targetTy == IR::BoolType) { + switch (sourceTy) { + case IR::IntType: opcode = V4Instr::ConvertIntToBool; break; + case IR::RealType: opcode = V4Instr::ConvertRealToBool; break; + case IR::StringType: opcode = V4Instr::ConvertStringToBool; break; + case IR::UrlType: opcode = V4Instr::ConvertUrlToBool; break; ++ case IR::ColorType: opcode = V4Instr::ConvertColorToBool; break; + default: break; + } // switch + } else if (targetTy == IR::IntType) { + switch (sourceTy) { + case IR::BoolType: opcode = V4Instr::ConvertBoolToInt; break; + case IR::RealType: { + if (s->isMoveForReturn) + opcode = V4Instr::MathRoundReal; + else + opcode = V4Instr::ConvertRealToInt; + break; + } + case IR::StringType: opcode = V4Instr::ConvertStringToInt; break; + default: break; + } // switch + } else if (targetTy == IR::RealType) { + switch (sourceTy) { + case IR::BoolType: opcode = V4Instr::ConvertBoolToReal; break; + case IR::IntType: opcode = V4Instr::ConvertIntToReal; break; + case IR::StringType: opcode = V4Instr::ConvertStringToReal; break; + default: break; + } // switch + } else if (targetTy == IR::StringType) { + switch (sourceTy) { + case IR::BoolType: opcode = V4Instr::ConvertBoolToString; break; + case IR::IntType: opcode = V4Instr::ConvertIntToString; break; + case IR::RealType: opcode = V4Instr::ConvertRealToString; break; + case IR::UrlType: opcode = V4Instr::ConvertUrlToString; break; ++ case IR::ColorType: opcode = V4Instr::ConvertColorToString; break; + default: break; + } // switch + } else if (targetTy == IR::UrlType) { + V4Instr convToString; + convToString.unaryop.output = dest; + convToString.unaryop.src = src; + + // try to convert the source expression to a string. + switch (sourceTy) { + case IR::BoolType: gen(V4Instr::ConvertBoolToString, convToString); sourceTy = IR::StringType; break; + case IR::IntType: gen(V4Instr::ConvertIntToString, convToString); sourceTy = IR::StringType; break; + case IR::RealType: gen(V4Instr::ConvertRealToString, convToString); sourceTy = IR::StringType; break; ++ case IR::ColorType: gen(V4Instr::ConvertColorToString, convToString); sourceTy = IR::StringType; break; + default: break; + } // switch + + if (sourceTy == IR::StringType) + opcode = V4Instr::ConvertStringToUrl; ++ } else if (targetTy == IR::ColorType) { ++ switch (sourceTy) { ++ case IR::StringType: opcode = V4Instr::ConvertStringToColor; break; ++ default: break; ++ } // switch + } + if (opcode != V4Instr::Noop) { + V4Instr conv; + conv.unaryop.output = dest; + conv.unaryop.src = src; + gen(opcode, conv); + + if (s->isMoveForReturn && opcode == V4Instr::ConvertStringToUrl) { + V4Instr resolveUrl; + resolveUrl.unaryop.output = dest; + resolveUrl.unaryop.src = dest; + gen(V4Instr::ResolveUrl, resolveUrl); + } + } else { + discard(); + } + } else { + traceExpression(s->source, dest); + } +} + +void QV4CompilerPrivate::visitJump(IR::Jump *s) +{ + patches.append(Patch(s->target, bytecode.size())); + + Instr::Branch i; + i.offset = 0; // ### backpatch + gen(i); +} + +void QV4CompilerPrivate::visitCJump(IR::CJump *s) +{ + traceExpression(s->cond, currentReg); + + patches.append(Patch(s->iftrue, bytecode.size())); + + Instr::BranchTrue i; + i.reg = currentReg; + i.offset = 0; // ### backpatch + gen(i); +} + +void QV4CompilerPrivate::visitRet(IR::Ret *s) +{ + Q_ASSERT(s->expr != 0); + + int storeReg = currentReg; + + if (IR::Temp *temp = s->expr->asTemp()) { + storeReg = temp->index; + } else { + traceExpression(s->expr, storeReg); + } + + if (qmlBindingsTest) { + Instr::TestV4Store test; + test.reg = storeReg; + switch (s->type) { + case IR::StringType: + test.regType = QMetaType::QString; + break; + case IR::UrlType: + test.regType = QMetaType::QUrl; + break; ++ case IR::ColorType: ++ test.regType = QMetaType::QColor; ++ break; + case IR::SGAnchorLineType: + test.regType = QQmlMetaType::QQuickAnchorLineMetaTypeId(); + break; + case IR::ObjectType: + test.regType = QMetaType::QObjectStar; + break; + case IR::BoolType: + test.regType = QMetaType::Bool; + break; + case IR::IntType: + test.regType = QMetaType::Int; + break; + case IR::RealType: + test.regType = QMetaType::QReal; + break; + default: + discard(); + return; + } + gen(test); + } + + Instr::Store store; + store.output = 0; + store.index = expression->property->index; + store.reg = storeReg; + store.exceptionId = exceptionId(s->line, s->column); + gen(store); +} + +void QV4Compiler::dump(const QByteArray &programData) +{ + const QV4Program *program = (const QV4Program *)programData.constData(); + + qWarning() << "Program.bindings:" << program->bindings; + qWarning() << "Program.dataLength:" << program->dataLength; + qWarning() << "Program.subscriptions:" << program->subscriptions; + qWarning() << "Program.indentifiers:" << program->identifiers; + + const int programSize = program->instructionCount; + const char *start = program->instructions(); + const char *end = start + programSize; + Bytecode bc; + bc.dump(start, end); +} + +/*! +Clear the state associated with attempting to compile a specific binding. +This does not clear the global "committed binding" states. +*/ +void QV4CompilerPrivate::resetInstanceState() +{ + data = committed.data; + exceptions = committed.exceptions; + usedSubscriptionIds.clear(); + subscriptionIds = committed.subscriptionIds; + registeredStrings = committed.registeredStrings; + bytecode.clear(); + patches.clear(); + pool.clear(); + currentReg = 0; +} + +/*! +Mark the last compile as successful, and add it to the "committed data" +section. + +Returns the index for the committed binding. +*/ +int QV4CompilerPrivate::commitCompile() +{ + int rv = committed.count(); + committed.offsets << committed.bytecode.count(); + committed.dependencies << usedSubscriptionIds; + committed.bytecode.append(bytecode.constData(), bytecode.size()); + committed.data = data; + committed.exceptions = exceptions; + committed.subscriptionIds = subscriptionIds; + committed.registeredStrings = registeredStrings; + return rv; +} + +bool QV4CompilerPrivate::compile(QQmlJS::AST::Node *node) +{ + resetInstanceState(); + + if (expression->property->type == -1) + return false; + + AST::SourceLocation location; + if (AST::ExpressionNode *astExpression = node->expressionCast()) { + location = astExpression->firstSourceLocation(); + } else if (AST::Statement *astStatement = node->statementCast()) { + if (AST::Block *block = AST::cast(astStatement)) + location = block->lbraceToken; + else if (AST::IfStatement *ifStmt = AST::cast(astStatement)) + location = ifStmt->ifToken; + else + return false; + } else { + return false; + } + + IR::Function thisFunction(&pool), *function = &thisFunction; + + QV4IRBuilder irBuilder(expression, engine); + if (!irBuilder(function, node)) + return false; + + bool discarded = false; + qSwap(_discarded, discarded); + qSwap(_function, function); + trace(location.startLine, location.startColumn); + qSwap(_function, function); + qSwap(_discarded, discarded); + + if (qmlVerboseCompiler()) { + QTextStream qerr(stderr, QIODevice::WriteOnly); + if (discarded) + qerr << "======== TODO ====== " << endl; + else + qerr << "==================== " << endl; + qerr << "\tline: " << location.startLine + << "\tcolumn: " << location.startColumn + << endl; + foreach (IR::BasicBlock *bb, function->basicBlocks) + bb->dump(qerr); + qerr << endl; + } + - if (discarded || subscriptionIds.count() > 0xFFFF || registeredStrings.count() > 0xFFFF) ++ if (discarded || subscriptionIds.count() > 0xFFFF || registeredStrings.count() > 0xFFFF || registerCount > 31) + return false; + + return true; +} + +// Returns a reg +int QV4CompilerPrivate::registerLiteralString(quint8 reg, const QStringRef &str) +{ + // ### string cleanup + + QByteArray strdata((const char *)str.constData(), str.length() * sizeof(QChar)); + int offset = data.count(); + data += strdata; + + Instr::LoadString string; + string.reg = reg; + string.offset = offset; + string.length = str.length(); + gen(string); + + return reg; +} + +// Returns an identifier offset +int QV4CompilerPrivate::registerString(const QString &string) +{ + Q_ASSERT(!string.isEmpty()); + + QPair *iter = registeredStrings.value(string); + + if (!iter) { + quint32 len = string.length(); + QByteArray lendata((const char *)&len, sizeof(quint32)); + QByteArray strdata((const char *)string.constData(), string.length() * sizeof(QChar)); + strdata.prepend(lendata); + int rv = data.count(); + data += strdata; + + iter = ®isteredStrings[string]; + *iter = qMakePair(registeredStrings.count(), rv); + } + + Instr::InitString reg; + reg.offset = iter->first; + reg.dataIdx = iter->second; + gen(reg); + return reg.offset; +} + +/*! +Returns true if the current expression has not already subscribed to \a sub in currentBlockMask. +*/ +bool QV4CompilerPrivate::blockNeedsSubscription(const QStringList &sub) +{ + QString str = sub.join(QLatin1String(".")); + + int *iter = subscriptionIds.value(str); + if (!iter) + return true; + + quint32 *uiter = usedSubscriptionIds.value(*iter); + if (!uiter) + return true; + else + return !(*uiter & currentBlockMask); +} + +int QV4CompilerPrivate::subscriptionIndex(const QStringList &sub) +{ + QString str = sub.join(QLatin1String(".")); + int *iter = subscriptionIds.value(str); + if (!iter) { + int count = subscriptionIds.count(); + iter = &subscriptionIds[str]; + *iter = count; + } + quint32 &u = usedSubscriptionIds[*iter]; + if (!(u & currentBlockMask)) { + u |= currentBlockMask; + usedSubscriptionIdsChanged = true; + } + return *iter; +} + +quint32 QV4CompilerPrivate::subscriptionBlockMask(const QStringList &sub) +{ + QString str = sub.join(QLatin1String(".")); + + int *iter = subscriptionIds.value(str); + Q_ASSERT(iter != 0); + + quint32 *uiter = usedSubscriptionIds.value(*iter); + Q_ASSERT(uiter != 0); + + return *uiter; +} + +quint8 QV4CompilerPrivate::exceptionId(quint32 line, quint32 column) +{ + quint8 rv = 0xFF; + if (exceptions.count() < 0xFF) { + rv = (quint8)exceptions.count(); + quint64 e = line; + e <<= 32; + e |= column; + exceptions.append(e); + } + return rv; +} + +quint8 QV4CompilerPrivate::exceptionId(QQmlJS::AST::ExpressionNode *n) +{ + quint8 rv = 0xFF; + if (n && exceptions.count() < 0xFF) { + QQmlJS::AST::SourceLocation l = n->firstSourceLocation(); + rv = exceptionId(l.startLine, l.startColumn); + } + return rv; +} + +QV4Compiler::QV4Compiler() +: d(new QV4CompilerPrivate) +{ + qmlBindingsTest |= qmlBindingsTestEnv(); +} + +QV4Compiler::~QV4Compiler() +{ + delete d; d = 0; +} + +/* +Returns true if any bindings were compiled. +*/ +bool QV4Compiler::isValid() const +{ + return !d->committed.bytecode.isEmpty(); +} + +/* +-1 on failure, otherwise the binding index to use. +*/ +int QV4Compiler::compile(const Expression &expression, QQmlEnginePrivate *engine) +{ + if (!expression.expression.asAST()) return false; + + if (!qmlExperimental() && expression.property->isValueTypeSubProperty) + return -1; + + if (qmlDisableOptimizer() || !qmlEnableV4) + return -1; + + d->expression = &expression; + d->engine = engine; + + if (d->compile(expression.expression.asAST())) { + return d->commitCompile(); + } else { + return -1; + } +} + +QByteArray QV4CompilerPrivate::buildSignalTable() const +{ + QHash > > table; + + for (int ii = 0; ii < committed.count(); ++ii) { + const QQmlAssociationList &deps = committed.dependencies.at(ii); + for (QQmlAssociationList::const_iterator iter = deps.begin(); iter != deps.end(); ++iter) + table[iter->first].append(qMakePair(ii, iter->second)); + } + + QVector header; + QVector data; + for (int ii = 0; ii < committed.subscriptionIds.count(); ++ii) { + header.append(committed.subscriptionIds.count() + data.count()); + const QList > &bindings = table[ii]; + data.append(bindings.count()); + for (int jj = 0; jj < bindings.count(); ++jj) { + data.append(bindings.at(jj).first); + data.append(bindings.at(jj).second); + } + } + header << data; + + return QByteArray((const char *)header.constData(), header.count() * sizeof(quint32)); +} + +QByteArray QV4CompilerPrivate::buildExceptionData() const +{ + QByteArray rv; + rv.resize(committed.exceptions.count() * sizeof(quint64)); + ::memcpy(rv.data(), committed.exceptions.constData(), rv.size()); + return rv; +} + +/* +Returns the compiled program. +*/ +QByteArray QV4Compiler::program() const +{ + QByteArray programData; + + if (isValid()) { + QV4Program prog; + prog.bindings = d->committed.count(); + + Bytecode bc; + QV4CompilerPrivate::Instr::Jump jump; + jump.reg = -1; + + for (int ii = 0; ii < d->committed.count(); ++ii) { + jump.count = d->committed.count() - ii - 1; + jump.count*= V4InstrMeta::Size; + jump.count+= d->committed.offsets.at(ii); + bc.append(jump); + } + + + QByteArray bytecode; + bytecode.reserve(bc.size() + d->committed.bytecode.size()); + bytecode.append(bc.constData(), bc.size()); + bytecode.append(d->committed.bytecode.constData(), d->committed.bytecode.size()); + + QByteArray data = d->committed.data; + while (data.count() % 4) data.append('\0'); + prog.signalTableOffset = data.count(); + data += d->buildSignalTable(); + while (data.count() % 4) data.append('\0'); + prog.exceptionDataOffset = data.count(); + data += d->buildExceptionData(); + + prog.dataLength = 4 * ((data.size() + 3) / 4); + prog.subscriptions = d->committed.subscriptionIds.count(); + prog.identifiers = d->committed.registeredStrings.count(); + prog.instructionCount = bytecode.count(); + int size = sizeof(QV4Program) + bytecode.count(); + size += prog.dataLength; + + programData.resize(size); + memcpy(programData.data(), &prog, sizeof(QV4Program)); + if (prog.dataLength) + memcpy((char *)((QV4Program *)programData.data())->data(), data.constData(), + data.size()); + memcpy((char *)((QV4Program *)programData.data())->instructions(), bytecode.constData(), + bytecode.count()); + } + + if (bindingsDump()) { + qWarning().nospace() << "Subscription slots:"; + + for (QQmlAssociationList::ConstIterator iter = d->committed.subscriptionIds.begin(); + iter != d->committed.subscriptionIds.end(); + ++iter) { + qWarning().nospace() << " " << iter->first << "\t-> " << iter->second; + } + + QV4Compiler::dump(programData); + } + + return programData; +} + +void QV4Compiler::enableBindingsTest(bool e) +{ + if (e) + qmlBindingsTest = true; + else + qmlBindingsTest = qmlBindingsTestEnv(); +} + +void QV4Compiler::enableV4(bool e) +{ + qmlEnableV4 = e; +} + +QT_END_NAMESPACE diff --cc src/qml/qml/v4/qv4compiler_p_p.h index 4b74a1d,0000000..a9209d9 mode 100644,000000..100644 --- a/src/qml/qml/v4/qv4compiler_p_p.h +++ b/src/qml/qml/v4/qv4compiler_p_p.h @@@ -1,245 -1,0 +1,246 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QV4COMPILER_P_P_H +#define QV4COMPILER_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qv4instruction_p.h" +#include "qv4ir_p.h" +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +template +class QQmlAssociationList +{ +public: + typedef QVarLengthArray, 8> Container; + typedef typename Container::const_iterator const_iterator; + typedef typename Container::const_iterator ConstIterator; + + const_iterator begin() const { return _container.begin(); } + const_iterator end() const { return _container.end(); } + int count() const { return _container.count(); } + void clear() { _container.clear(); } + + _Value *value(const _Key &key) { + for (int i = 0; i < _container.size(); ++i) { + QPair<_Key, _Value> &p = _container[i]; + if (p.first == key) + return &p.second; + } + return 0; + } + + _Value &operator[](const _Key &key) { + for (int i = 0; i < _container.size(); ++i) { + QPair<_Key, _Value> &p = _container[i]; + if (p.first == key) + return p.second; + } + int index = _container.size(); + _container.append(qMakePair(key, _Value())); + return _container[index].second; + } + + void insert(const _Key &key, _Value &value) { + for (int i = 0; i < _container.size(); ++i) { + QPair<_Key, _Value> &p = _container[i]; + if (p.first == key) { + p.second = value; + return; + } + } + _container.append(qMakePair(key, value)); + } + +private: + Container _container; +}; + +class QV4CompilerPrivate: protected QQmlJS::IR::ExprVisitor, + protected QQmlJS::IR::StmtVisitor +{ +public: + QV4CompilerPrivate(); + + void resetInstanceState(); + int commitCompile(); + + const QV4Compiler::Expression *expression; + QQmlEnginePrivate *engine; + + QString contextName() const { return QLatin1String("$$$SCOPE_") + QString::number((quintptr)expression->context, 16); } + + bool compile(QQmlJS::AST::Node *); + + int registerLiteralString(quint8 reg, const QStringRef &); + int registerString(const QString &); + QQmlAssociationList > registeredStrings; + QByteArray data; + + bool blockNeedsSubscription(const QStringList &); + int subscriptionIndex(const QStringList &); + quint32 subscriptionBlockMask(const QStringList &); + + quint8 exceptionId(quint32 line, quint32 column); + quint8 exceptionId(QQmlJS::AST::ExpressionNode *); + QVector exceptions; + + QQmlAssociationList usedSubscriptionIds; + + QQmlAssociationList subscriptionIds; + QQmlJS::Bytecode bytecode; + + // back patching + struct Patch { + QQmlJS::IR::BasicBlock *block; // the basic block + int offset; // the index of the instruction to patch + Patch(QQmlJS::IR::BasicBlock *block = 0, int index = -1) + : block(block), offset(index) {} + }; + QVector patches; + QQmlPool pool; + + // Committed binding data + struct { + QList offsets; + QList > dependencies; + + //QQmlJS::Bytecode bytecode; + QByteArray bytecode; + QByteArray data; + QQmlAssociationList subscriptionIds; + QVector exceptions; + + QQmlAssociationList > registeredStrings; + + int count() const { return offsets.count(); } + } committed; + + QByteArray buildSignalTable() const; + QByteArray buildExceptionData() const; + + void convertToReal(QQmlJS::IR::Expr *expr, int reg); + void convertToInt(QQmlJS::IR::Expr *expr, int reg); + void convertToBool(QQmlJS::IR::Expr *expr, int reg); + quint8 instructionOpcode(QQmlJS::IR::Binop *e); + + struct Instr { +#define QML_V4_INSTR_DATA_TYPEDEF(I, FMT) typedef QQmlJS::V4InstrData I; + FOR_EACH_V4_INSTR(QML_V4_INSTR_DATA_TYPEDEF) +#undef QML_v4_INSTR_DATA_TYPEDEF + private: + Instr(); + }; + +protected: + // + // tracing + // + void trace(int line, int column); + void trace(QVector *blocks); + void traceExpression(QQmlJS::IR::Expr *e, quint8 r); + + template + inline void gen(const QQmlJS::V4InstrData &i) + { bytecode.append(i); } + inline void gen(QQmlJS::V4Instr::Type type, QQmlJS::V4Instr &instr) + { bytecode.append(type, instr); } + + inline QQmlJS::V4Instr::Type instructionType(const QQmlJS::V4Instr *i) const + { return bytecode.instructionType(i); } + + // + // expressions + // + virtual void visitConst(QQmlJS::IR::Const *e); + virtual void visitString(QQmlJS::IR::String *e); + virtual void visitName(QQmlJS::IR::Name *e); + virtual void visitTemp(QQmlJS::IR::Temp *e); + virtual void visitUnop(QQmlJS::IR::Unop *e); + virtual void visitBinop(QQmlJS::IR::Binop *e); + virtual void visitCall(QQmlJS::IR::Call *e); + + // + // statements + // + virtual void visitExp(QQmlJS::IR::Exp *s); + virtual void visitMove(QQmlJS::IR::Move *s); + virtual void visitJump(QQmlJS::IR::Jump *s); + virtual void visitCJump(QQmlJS::IR::CJump *s); + virtual void visitRet(QQmlJS::IR::Ret *s); + +private: + QStringList _subscribeName; + QQmlJS::IR::Function *_function; + QQmlJS::IR::BasicBlock *_block; + void discard() { _discarded = true; } + bool _discarded; + quint8 currentReg; ++ quint8 registerCount; + + bool usedSubscriptionIdsChanged; + quint32 currentBlockMask; +}; + + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QV4COMPILER_P_P_H + diff --cc src/qml/qml/v4/qv4instruction.cpp index 08b2570,0000000..efbd2b2 mode 100644,000000..100644 --- a/src/qml/qml/v4/qv4instruction.cpp +++ b/src/qml/qml/v4/qv4instruction.cpp @@@ -1,412 -1,0 +1,421 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qv4instruction_p.h" +#include "qv4bindings_p.h" + +#include +#include + +// Define this to do a test dump of all the instructions at startup. This is +// helpful to test that each instruction's Instr::dump() case uses the correct +// number of tabs etc and otherwise looks correct. +// #define DEBUG_INSTR_DUMP + +QT_BEGIN_NAMESPACE + +namespace QQmlJS { + +#ifdef DEBUG_INSTR_DUMP +static struct DumpInstrAtStartup { + DumpInstrAtStartup() { + Bytecode bc; +#define DUMP_INSTR_AT_STARTUP(I, FMT) { V4InstrData i; bc.append(i); } + FOR_EACH_V4_INSTR(DUMP_INSTR_AT_STARTUP); +#undef DUMP_INSTR_AT_STARTUP + const char *start = bc.constData(); + const char *end = start + bc.size(); + bc.dump(start, end); + } +} dump_instr_at_startup; +#endif + +int V4Instr::size(Type type) +{ +#define V4_RETURN_INSTR_SIZE(I, FMT) case I: return QML_V4_INSTR_SIZE(I, FMT); + switch (type) { + FOR_EACH_V4_INSTR(V4_RETURN_INSTR_SIZE) + } +#undef V4_RETURN_INSTR_SIZE + return 0; +} + +void Bytecode::dump(const V4Instr *i, int address) const +{ + QByteArray leading; + if (address != -1) { + leading = QByteArray::number(address); + leading.prepend(QByteArray(8 - leading.count(), ' ')); + leading.append("\t"); + } + +#define INSTR_DUMP qWarning().nospace() << leading.constData() + + switch (instructionType(i)) { + case V4Instr::Noop: + INSTR_DUMP << "\t" << "Noop"; + break; + case V4Instr::BindingId: + INSTR_DUMP << i->id.line << ":" << i->id.column << ":"; + break; + case V4Instr::Subscribe: + INSTR_DUMP << "\t" << "Subscribe" << "\t\t" << "Object_Reg(" << i->subscribeop.reg << ") Notify_Signal(" << i->subscribeop.index << ") -> Subscribe_Slot(" << i->subscribeop.offset << ")"; + break; + case V4Instr::SubscribeId: + INSTR_DUMP << "\t" << "SubscribeId" << "\t\t" << "Id_Offset(" << i->subscribeop.index << ") -> Subscribe_Slot(" << i->subscribeop.offset << ")"; + break; + case V4Instr::FetchAndSubscribe: + INSTR_DUMP << "\t" << "FetchAndSubscribe" << "\t" << "Object_Reg(" << i->fetchAndSubscribe.reg << ") Fast_Accessor(" << i->fetchAndSubscribe.property.accessors << ") -> Output_Reg(" << i->fetchAndSubscribe.reg << ") Subscription_Slot(" << i->fetchAndSubscribe.subscription << ")"; + break; + case V4Instr::LoadId: + INSTR_DUMP << "\t" << "LoadId" << "\t\t\t" << "Id_Offset(" << i->load.index << ") -> Output_Reg(" << i->load.reg << ")"; + break; + case V4Instr::LoadScope: + INSTR_DUMP << "\t" << "LoadScope" << "\t\t" << "-> Output_Reg(" << i->load.reg << ")"; + break; + case V4Instr::LoadRoot: + INSTR_DUMP << "\t" << "LoadRoot" << "\t\t" << "-> Output_Reg(" << i->load.reg << ")"; + break; + case V4Instr::LoadAttached: + INSTR_DUMP << "\t" << "LoadAttached" << "\t\t" << "Object_Reg(" << i->attached.reg << ") Attached_Index(" << i->attached.id << ") -> Output_Reg(" << i->attached.output << ")"; + break; + case V4Instr::UnaryNot: + INSTR_DUMP << "\t" << "UnaryNot" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; + case V4Instr::UnaryMinusReal: + INSTR_DUMP << "\t" << "UnaryMinusReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; + case V4Instr::UnaryMinusInt: + INSTR_DUMP << "\t" << "UnaryMinusInt" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; + case V4Instr::UnaryPlusReal: + INSTR_DUMP << "\t" << "UnaryPlusReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; + case V4Instr::UnaryPlusInt: + INSTR_DUMP << "\t" << "UnaryPlusInt" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; + case V4Instr::ConvertBoolToInt: + INSTR_DUMP << "\t" << "ConvertBoolToInt" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; + case V4Instr::ConvertBoolToReal: + INSTR_DUMP << "\t" << "ConvertBoolToReal" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; + case V4Instr::ConvertBoolToString: + INSTR_DUMP << "\t" << "ConvertBoolToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; + case V4Instr::ConvertIntToBool: + INSTR_DUMP << "\t" << "ConvertIntToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; + case V4Instr::ConvertIntToReal: + INSTR_DUMP << "\t" << "ConvertIntToReal" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; + case V4Instr::ConvertIntToString: + INSTR_DUMP << "\t" << "ConvertIntToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; + case V4Instr::ConvertRealToBool: + INSTR_DUMP << "\t" << "ConvertRealToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; + case V4Instr::ConvertRealToInt: + INSTR_DUMP << "\t" << "ConvertRealToInt" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; + case V4Instr::ConvertRealToString: + INSTR_DUMP << "\t" << "ConvertRealToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; + case V4Instr::ConvertStringToBool: + INSTR_DUMP << "\t" << "ConvertStringToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; + case V4Instr::ConvertStringToInt: + INSTR_DUMP << "\t" << "ConvertStringToInt" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; + case V4Instr::ConvertStringToReal: + INSTR_DUMP << "\t" << "ConvertStringToReal" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; + case V4Instr::ConvertStringToUrl: + INSTR_DUMP << "\t" << "ConvertStringToUrl" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; ++ case V4Instr::ConvertStringToColor: ++ INSTR_DUMP << "\t" << "ConvertStringToColor" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; ++ break; + case V4Instr::ConvertUrlToBool: + INSTR_DUMP << "\t" << "ConvertUrlToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; + case V4Instr::ConvertUrlToString: + INSTR_DUMP << "\t" << "ConvertUrlToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; ++ case V4Instr::ConvertColorToBool: ++ INSTR_DUMP << "\t" << "ConvertColorToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; ++ break; ++ case V4Instr::ConvertColorToString: ++ INSTR_DUMP << "\t" << "ConvertColorToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; ++ break; + case V4Instr::ResolveUrl: + INSTR_DUMP << "\t" << "ResolveUrl" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; + case V4Instr::MathSinReal: + INSTR_DUMP << "\t" << "MathSinReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; + case V4Instr::MathCosReal: + INSTR_DUMP << "\t" << "MathCosReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; + case V4Instr::MathRoundReal: + INSTR_DUMP << "\t" << "MathRoundReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; + case V4Instr::MathFloorReal: + INSTR_DUMP << "\t" << "MathFloorReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; + case V4Instr::MathPIReal: + INSTR_DUMP << "\t" << "MathPIReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; + break; + case V4Instr::LoadReal: + INSTR_DUMP << "\t" << "LoadReal" << "\t\t" << "Constant(" << i->real_value.value << ") -> Output_Reg(" << i->real_value.reg << ")"; + break; + case V4Instr::LoadInt: + INSTR_DUMP << "\t" << "LoadInt" << "\t\t\t" << "Constant(" << i->int_value.value << ") -> Output_Reg(" << i->int_value.reg << ")"; + break; + case V4Instr::LoadBool: + INSTR_DUMP << "\t" << "LoadBool" << "\t\t" << "Constant(" << i->bool_value.value << ") -> Output_Reg(" << i->bool_value.reg << ")"; + break; + case V4Instr::LoadString: + INSTR_DUMP << "\t" << "LoadString" << "\t\t" << "String_DataIndex(" << i->string_value.offset << ") String_Length(" << i->string_value.length << ") -> Output_Register(" << i->string_value.reg << ")"; + break; + case V4Instr::EnableV4Test: + INSTR_DUMP << "\t" << "EnableV4Test" << "\t\t" << "String_DataIndex(" << i->string_value.offset << ") String_Length(" << i->string_value.length << ")"; + break; + case V4Instr::TestV4Store: + INSTR_DUMP << "\t" << "TestV4Store" << "\t\t" << "Input_Reg(" << i->storetest.reg << ") Reg_Type(" << i->storetest.regType << ")"; + break; + case V4Instr::BitAndInt: + INSTR_DUMP << "\t" << "BitAndInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::BitOrInt: + INSTR_DUMP << "\t" << "BitOrInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::BitXorInt: + INSTR_DUMP << "\t" << "BitXorInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::AddReal: + INSTR_DUMP << "\t" << "AddReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::AddString: + INSTR_DUMP << "\t" << "AddString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::SubReal: + INSTR_DUMP << "\t" << "SubReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::MulReal: + INSTR_DUMP << "\t" << "MulReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::DivReal: + INSTR_DUMP << "\t" << "DivReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::ModReal: + INSTR_DUMP << "\t" << "ModReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::LShiftInt: + INSTR_DUMP << "\t" << "LShiftInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::RShiftInt: + INSTR_DUMP << "\t" << "RShiftInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::URShiftInt: + INSTR_DUMP << "\t" << "URShiftInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::GtReal: + INSTR_DUMP << "\t" << "GtReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::LtReal: + INSTR_DUMP << "\t" << "LtReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::GeReal: + INSTR_DUMP << "\t" << "GeReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::LeReal: + INSTR_DUMP << "\t" << "LeReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::EqualReal: + INSTR_DUMP << "\t" << "EqualReal" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::NotEqualReal: + INSTR_DUMP << "\t" << "NotEqualReal" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::StrictEqualReal: + INSTR_DUMP << "\t" << "StrictEqualReal" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::StrictNotEqualReal: + INSTR_DUMP << "\t" << "StrictNotEqualReal" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::GtString: + INSTR_DUMP << "\t" << "GtString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::LtString: + INSTR_DUMP << "\t" << "LtString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::GeString: + INSTR_DUMP << "\t" << "GeString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::LeString: + INSTR_DUMP << "\t" << "LeString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::EqualString: + INSTR_DUMP << "\t" << "EqualString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::NotEqualString: + INSTR_DUMP << "\t" << "NotEqualString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::StrictEqualString: + INSTR_DUMP << "\t" << "StrictEqualString" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::StrictNotEqualString: + INSTR_DUMP << "\t" << "StrictNotEqualString" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::NewString: + INSTR_DUMP << "\t" << "NewString" << "\t\t" << "Register(" << i->construct.reg << ")"; + break; + case V4Instr::NewUrl: + INSTR_DUMP << "\t" << "NewUrl" << "\t\t\t" << "Register(" << i->construct.reg << ")"; + break; + case V4Instr::CleanupRegister: + INSTR_DUMP << "\t" << "CleanupRegister" << "\t\t" << "Register(" << i->cleanup.reg << ")"; + break; + case V4Instr::Fetch: + INSTR_DUMP << "\t" << "Fetch" << "\t\t\t" << "Object_Reg(" << i->fetch.reg << ") Property_Index(" << i->fetch.index << ") -> Output_Reg(" << i->fetch.reg << ")"; + break; + case V4Instr::Store: + INSTR_DUMP << "\t" << "Store" << "\t\t\t" << "Input_Reg(" << i->store.reg << ") -> Object_Reg(" << i->store.output << ") Property_Index(" << i->store.index << ")"; + break; + case V4Instr::Copy: + INSTR_DUMP << "\t" << "Copy" << "\t\t\t" << "Input_Reg(" << i->copy.src << ") -> Output_Reg(" << i->copy.reg << ")"; + break; + case V4Instr::Jump: + if (i->jump.reg != -1) { + INSTR_DUMP << "\t" << "Jump" << "\t\t\t" << "Address(" << (address + size() + i->jump.count) << ") [if false == Input_Reg(" << i->jump.reg << ")]"; + } else { + INSTR_DUMP << "\t" << "Jump" << "\t\t\t" << "Address(" << (address + size() + i->jump.count) << ")"; + } + break; + case V4Instr::BranchFalse: + INSTR_DUMP << "\t" << "BranchFalse" << "\t\t" << "Address(" << (address + size() + i->branchop.offset) << ") [if false == Input_Reg(" << i->branchop.reg << ")]"; + break; + case V4Instr::BranchTrue: + INSTR_DUMP << "\t" << "BranchTrue" << "\t\t" << "Address(" << (address + size() + i->branchop.offset) << ") [if true == Input_Reg(" << i->branchop.reg << ")]"; + break; + case V4Instr::Branch: + INSTR_DUMP << "\t" << "Branch" << "\t\t\t" << "Address(" << (address + size() + i->branchop.offset) << ")"; + break; + case V4Instr::InitString: + INSTR_DUMP << "\t" << "InitString" << "\t\t" << "String_DataIndex(" << i->initstring.dataIdx << ") -> String_Slot(" << i->initstring.offset << ")"; + break; + case V4Instr::Block: + INSTR_DUMP << "\t" << "Block" << "\t\t\t" << "Mask(" << QByteArray::number(i->blockop.block, 16).constData() << ")"; + break; + default: + INSTR_DUMP << "\t" << "Unknown"; + break; + } +} + +void Bytecode::dump(const char *start, const char *end) const +{ + const char *code = start; + while (code < end) { + const V4Instr *instr = reinterpret_cast(code); + dump(instr, code - start); + code += V4Instr::size(instructionType(instr)); + } +} + +Bytecode::Bytecode() +{ +#ifdef QML_THREADED_INTERPRETER + decodeInstr = QV4Bindings::getDecodeInstrTable(); +#endif +} + +V4Instr::Type Bytecode::instructionType(const V4Instr *instr) const +{ +#ifdef QML_THREADED_INTERPRETER + void *code = instr->common.code; + +# define CHECK_V4_INSTR_CODE(I, FMT) \ + if (decodeInstr[static_cast(V4Instr::I)] == code) \ + return V4Instr::I; + + FOR_EACH_V4_INSTR(CHECK_V4_INSTR_CODE) + Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid instruction address"); + return static_cast(0); +# undef CHECK_V4_INSTR_CODE +#else + return static_cast(instr->common.type); +#endif + +} + +void Bytecode::append(V4Instr::Type type, V4Instr &instr) +{ +#ifdef QML_THREADED_INTERPRETER + instr.common.code = decodeInstr[static_cast(type)]; +#else + instr.common.type = type; +#endif + d.append(reinterpret_cast(&instr), V4Instr::size(type)); +} + +int Bytecode::remove(int offset) +{ + const V4Instr *instr = reinterpret_cast(d.begin() + offset); + const int instrSize = V4Instr::size(instructionType(instr)); + d.remove(offset, instrSize); + return instrSize; +} + +const V4Instr &Bytecode::operator[](int offset) const +{ + return *(reinterpret_cast(d.begin() + offset)); +} + +V4Instr &Bytecode::operator[](int offset) +{ + return *(reinterpret_cast(d.begin() + offset)); +} + +} + +QT_END_NAMESPACE diff --cc src/qml/qml/v4/qv4instruction_p.h index 8150eed,0000000..964c955 mode 100644,000000..100644 --- a/src/qml/qml/v4/qv4instruction_p.h +++ b/src/qml/qml/v4/qv4instruction_p.h @@@ -1,432 -1,0 +1,435 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QV4INSTRUCTION_P_H +#define QV4INSTRUCTION_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +#define FOR_EACH_V4_INSTR(F) \ + F(Noop, common) \ + F(BindingId, id) \ + F(Subscribe, subscribeop) \ + F(SubscribeId, subscribeop) \ + F(FetchAndSubscribe, fetchAndSubscribe) \ + F(LoadId, load) \ + F(LoadScope, load) \ + F(LoadRoot, load) \ + F(LoadAttached, attached) \ + F(UnaryNot, unaryop) \ + F(UnaryMinusReal, unaryop) \ + F(UnaryMinusInt, unaryop) \ + F(UnaryPlusReal, unaryop) \ + F(UnaryPlusInt, unaryop) \ + F(ConvertBoolToInt, unaryop) \ + F(ConvertBoolToReal, unaryop) \ + F(ConvertBoolToString, unaryop) \ + F(ConvertIntToBool, unaryop) \ + F(ConvertIntToReal, unaryop) \ + F(ConvertIntToString, unaryop) \ + F(ConvertRealToBool, unaryop) \ + F(ConvertRealToInt, unaryop) \ + F(ConvertRealToString, unaryop) \ + F(ConvertStringToBool, unaryop) \ + F(ConvertStringToInt, unaryop) \ + F(ConvertStringToReal, unaryop) \ + F(ConvertStringToUrl, unaryop) \ ++ F(ConvertStringToColor, unaryop) \ + F(ConvertUrlToBool, unaryop) \ + F(ConvertUrlToString, unaryop) \ ++ F(ConvertColorToBool, unaryop) \ ++ F(ConvertColorToString, unaryop) \ + F(ResolveUrl, unaryop) \ + F(MathSinReal, unaryop) \ + F(MathCosReal, unaryop) \ + F(MathRoundReal, unaryop) \ + F(MathFloorReal, unaryop) \ + F(MathPIReal, unaryop) \ + F(LoadReal, real_value) \ + F(LoadInt, int_value) \ + F(LoadBool, bool_value) \ + F(LoadString, string_value) \ + F(EnableV4Test, string_value) \ + F(TestV4Store, storetest) \ + F(BitAndInt, binaryop) \ + F(BitOrInt, binaryop) \ + F(BitXorInt, binaryop) \ + F(AddReal, binaryop) \ + F(AddString, binaryop) \ + F(SubReal, binaryop) \ + F(MulReal, binaryop) \ + F(DivReal, binaryop) \ + F(ModReal, binaryop) \ + F(LShiftInt, binaryop) \ + F(RShiftInt, binaryop) \ + F(URShiftInt, binaryop) \ + F(GtReal, binaryop) \ + F(LtReal, binaryop) \ + F(GeReal, binaryop) \ + F(LeReal, binaryop) \ + F(EqualReal, binaryop) \ + F(NotEqualReal, binaryop) \ + F(StrictEqualReal, binaryop) \ + F(StrictNotEqualReal, binaryop) \ + F(GtString, binaryop) \ + F(LtString, binaryop) \ + F(GeString, binaryop) \ + F(LeString, binaryop) \ + F(EqualString, binaryop) \ + F(NotEqualString, binaryop) \ + F(StrictEqualString, binaryop) \ + F(StrictNotEqualString, binaryop) \ + F(NewString, construct) \ + F(NewUrl, construct) \ + F(CleanupRegister, cleanup) \ + F(Copy, copy) \ + F(Fetch, fetch) \ + F(Store, store) \ + F(Jump, jump) \ + F(BranchTrue, branchop) \ + F(BranchFalse, branchop) \ + F(Branch, branchop) \ + F(Block, blockop) \ + /* Speculative property resolution */ \ + F(InitString, initstring) + +#if defined(Q_CC_GNU) && (!defined(Q_CC_INTEL) || __INTEL_COMPILER >= 1200) +# define QML_THREADED_INTERPRETER +#endif + +#ifdef Q_ALIGNOF +# define QML_V4_INSTR_ALIGN_MASK (Q_ALIGNOF(V4Instr) - 1) +#else +# define QML_V4_INSTR_ALIGN_MASK (sizeof(void *) - 1) +#endif + +#define QML_V4_INSTR_ENUM(I, FMT) I, +#define QML_V4_INSTR_ADDR(I, FMT) &&op_##I, +#define QML_V4_INSTR_SIZE(I, FMT) ((sizeof(V4Instr::instr_##FMT) + QML_V4_INSTR_ALIGN_MASK) & ~QML_V4_INSTR_ALIGN_MASK) + +#ifdef QML_THREADED_INTERPRETER +# define QML_V4_BEGIN_INSTR(I,FMT) op_##I: +# define QML_V4_END_INSTR(I,FMT) code += QML_V4_INSTR_SIZE(I, FMT); instr = (const V4Instr *) code; goto *instr->common.code; +# define QML_V4_INSTR_HEADER void *code; +#else +# define QML_V4_BEGIN_INSTR(I,FMT) case V4Instr::I: +# define QML_V4_END_INSTR(I,FMT) code += QML_V4_INSTR_SIZE(I, FMT); instr = (const V4Instr *) code; break; +# define QML_V4_INSTR_HEADER quint8 type; +#endif + +class QObject; +class QQmlNotifier; + +namespace QQmlJS { + +union V4Instr { + enum Type { + FOR_EACH_V4_INSTR(QML_V4_INSTR_ENUM) + }; + + static int size(Type type); + + struct instr_common { + QML_V4_INSTR_HEADER + }; + + struct instr_id { + QML_V4_INSTR_HEADER + quint16 column; + quint32 line; + }; + + struct instr_init { + QML_V4_INSTR_HEADER + quint16 subscriptions; + quint16 identifiers; + }; + + struct instr_subscribeop { + QML_V4_INSTR_HEADER + qint8 reg; + quint16 offset; + quint32 index; + }; + + struct instr_load { + QML_V4_INSTR_HEADER + qint8 reg; + quint32 index; + }; + + struct instr_attached { + QML_V4_INSTR_HEADER + qint8 output; + qint8 reg; + quint8 exceptionId; + quint32 id; + }; + + struct instr_store { + QML_V4_INSTR_HEADER + qint8 output; + qint8 reg; + quint8 exceptionId; + quint32 index; + }; + + struct instr_storetest { + QML_V4_INSTR_HEADER + qint8 reg; + qint32 regType; + }; + + struct instr_fetchAndSubscribe { + QML_V4_INSTR_HEADER + qint8 reg; + quint8 exceptionId; + quint8 valueType; + quint16 subscription; + QQmlPropertyRawData property; + }; + + struct instr_fetch{ + QML_V4_INSTR_HEADER + qint8 reg; + quint8 exceptionId; + quint8 valueType; + quint32 index; + }; + + struct instr_copy { + QML_V4_INSTR_HEADER + qint8 reg; + qint8 src; + }; + + struct instr_construct { + QML_V4_INSTR_HEADER + qint8 reg; + }; + + struct instr_real_value { + QML_V4_INSTR_HEADER + qint8 reg; + qreal value; // XXX Makes the instruction 12 bytes + }; + + struct instr_int_value { + QML_V4_INSTR_HEADER + qint8 reg; + int value; + }; + + struct instr_bool_value { + QML_V4_INSTR_HEADER + qint8 reg; + bool value; + }; + + struct instr_string_value { + QML_V4_INSTR_HEADER + qint8 reg; + quint16 length; + quint32 offset; + }; + + struct instr_binaryop { + QML_V4_INSTR_HEADER + qint8 output; + qint8 left; + qint8 right; + }; + + struct instr_unaryop { + QML_V4_INSTR_HEADER + qint8 output; + qint8 src; + }; + + struct instr_jump { + QML_V4_INSTR_HEADER + qint8 reg; + quint32 count; + }; + + struct instr_find { + QML_V4_INSTR_HEADER + qint8 reg; + qint8 src; + quint8 exceptionId; + quint16 name; + quint16 subscribeIndex; + }; + + struct instr_cleanup { + QML_V4_INSTR_HEADER + qint8 reg; + }; + + struct instr_initstring { + QML_V4_INSTR_HEADER + quint16 offset; + quint32 dataIdx; + }; + + struct instr_branchop { + QML_V4_INSTR_HEADER + quint8 reg; + qint16 offset; + }; + + struct instr_blockop { + QML_V4_INSTR_HEADER + quint32 block; + }; + + instr_common common; + instr_id id; + instr_init init; + instr_subscribeop subscribeop; + instr_load load; + instr_attached attached; + instr_store store; + instr_storetest storetest; + instr_fetchAndSubscribe fetchAndSubscribe; + instr_fetch fetch; + instr_copy copy; + instr_construct construct; + instr_real_value real_value; + instr_int_value int_value; + instr_bool_value bool_value; + instr_string_value string_value; + instr_binaryop binaryop; + instr_unaryop unaryop; + instr_jump jump; + instr_find find; + instr_cleanup cleanup; + instr_initstring initstring; + instr_branchop branchop; + instr_blockop blockop; +}; + +template +struct V4InstrMeta { +}; + +#define QML_V4_INSTR_META_TEMPLATE(I, FMT) \ + template<> struct V4InstrMeta<(int)V4Instr::I> { \ + enum { Size = QML_V4_INSTR_SIZE(I, FMT) }; \ + typedef V4Instr::instr_##FMT DataType; \ + static const DataType &data(const V4Instr &instr) { return instr.FMT; } \ + static void setData(V4Instr &instr, const DataType &v) { instr.FMT = v; } \ + }; +FOR_EACH_V4_INSTR(QML_V4_INSTR_META_TEMPLATE); +#undef QML_V4_INSTR_META_TEMPLATE + +template +class V4InstrData : public V4InstrMeta::DataType +{ +}; + +class Bytecode +{ + Q_DISABLE_COPY(Bytecode) + +public: + Bytecode(); + + const char *constData() const { return d.constData(); } + int size() const { return d.size(); } + int count() const { return d.count(); } + void clear() { d.clear(); } + bool isEmpty() const { return d.isEmpty(); } + V4Instr::Type instructionType(const V4Instr *instr) const; + + template + void append(const V4InstrData &data) + { + V4Instr genericInstr; + V4InstrMeta::setData(genericInstr, data); + return append(static_cast(Instr), genericInstr); + } + void append(V4Instr::Type type, V4Instr &instr); + + int remove(int index); + + const V4Instr &operator[](int offset) const; + V4Instr &operator[](int offset); + + void dump(const char *start, const char *end) const; + +private: + void dump(const V4Instr *instr, int = -1) const; + + QVarLengthArray d; +#ifdef QML_THREADED_INTERPRETER + void **decodeInstr; +#endif +}; + +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QV4INSTRUCTION_P_H + diff --cc src/qml/qml/v4/qv4ir.cpp index be82214,0000000..3b33898 mode 100644,000000..100644 --- a/src/qml/qml/v4/qv4ir.cpp +++ b/src/qml/qml/v4/qv4ir.cpp @@@ -1,882 -1,0 +1,883 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qv4ir_p.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace QQmlJS { +namespace IR { + +inline const char *typeName(Type t) +{ + switch (t) { + case InvalidType: return "invalid"; + case UndefinedType: return "undefined"; + case NullType: return "null"; + case VoidType: return "void"; + case StringType: return "string"; + case UrlType: return "url"; ++ case ColorType: return "color"; + case SGAnchorLineType: return "SGAnchorLine"; + case AttachType: return "AttachType"; + case ObjectType: return "object"; + case BoolType: return "bool"; + case IntType: return "int"; + case RealType: return "qreal"; + case RealNaNType: return "NaN"; + default: return "invalid"; + } +} + +inline bool isNumberType(IR::Type ty) +{ + return ty >= IR::FirstNumberType; +} + +inline bool isStringType(IR::Type ty) +{ - return ty == IR::StringType || ty == IR::UrlType; ++ return ty == IR::StringType || ty == IR::UrlType || ty == IR::ColorType; +} + +IR::Type maxType(IR::Type left, IR::Type right) +{ + if (isStringType(left) && isStringType(right)) { + // String promotions (url to string) are more specific than + // identity conversions (AKA left == right). That's because + // we want to ensure we convert urls to strings in binary + // expressions. + return IR::StringType; + } else if (left == right) + return left; + else if (isNumberType(left) && isNumberType(right)) + return qMax(left, right); + else if ((isNumberType(left) && isStringType(right)) || + (isNumberType(right) && isStringType(left))) + return IR::StringType; + else + return IR::InvalidType; +} + + +const char *opname(AluOp op) +{ + switch (op) { + case OpInvalid: return "?"; + + case OpIfTrue: return "(bool)"; + case OpNot: return "!"; + case OpUMinus: return "-"; + case OpUPlus: return "+"; + case OpCompl: return "~"; + + case OpBitAnd: return "&"; + case OpBitOr: return "|"; + case OpBitXor: return "^"; + + case OpAdd: return "+"; + case OpSub: return "-"; + case OpMul: return "*"; + case OpDiv: return "/"; + case OpMod: return "%"; + + case OpLShift: return "<<"; + case OpRShift: return ">>"; + case OpURShift: return ">>>"; + + case OpGt: return ">"; + case OpLt: return "<"; + case OpGe: return ">="; + case OpLe: return "<="; + case OpEqual: return "=="; + case OpNotEqual: return "!="; + case OpStrictEqual: return "==="; + case OpStrictNotEqual: return "!=="; + + case OpAnd: return "&&"; + case OpOr: return "||"; + + default: return "?"; + + } // switch +} + +AluOp binaryOperator(int op) +{ + switch (static_cast(op)) { + case QSOperator::Add: return OpAdd; + case QSOperator::And: return OpAnd; + case QSOperator::BitAnd: return OpBitAnd; + case QSOperator::BitOr: return OpBitOr; + case QSOperator::BitXor: return OpBitXor; + case QSOperator::Div: return OpDiv; + case QSOperator::Equal: return OpEqual; + case QSOperator::Ge: return OpGe; + case QSOperator::Gt: return OpGt; + case QSOperator::Le: return OpLe; + case QSOperator::LShift: return OpLShift; + case QSOperator::Lt: return OpLt; + case QSOperator::Mod: return OpMod; + case QSOperator::Mul: return OpMul; + case QSOperator::NotEqual: return OpNotEqual; + case QSOperator::Or: return OpOr; + case QSOperator::RShift: return OpRShift; + case QSOperator::StrictEqual: return OpStrictEqual; + case QSOperator::StrictNotEqual: return OpStrictNotEqual; + case QSOperator::Sub: return OpSub; + case QSOperator::URShift: return OpURShift; + default: return OpInvalid; + } +} + +void Const::dump(QTextStream &out) +{ + out << value; +} + +void String::dump(QTextStream &out) +{ + out << '"' << escape(value) << '"'; +} + +QString String::escape(const QStringRef &s) +{ + QString r; + for (int i = 0; i < s.length(); ++i) { + const QChar ch = s.at(i); + if (ch == QLatin1Char('\n')) + r += QLatin1String("\\n"); + else if (ch == QLatin1Char('\r')) + r += QLatin1String("\\r"); + else if (ch == QLatin1Char('\\')) + r += QLatin1String("\\\\"); + else if (ch == QLatin1Char('"')) + r += QLatin1String("\\\""); + else if (ch == QLatin1Char('\'')) + r += QLatin1String("\\'"); + else + r += ch; + } + return r; +} + +void Name::init(Name *base, Type type, const QString *id, Symbol symbol, quint32 line, quint32 column) +{ + this->type = type; + this->base = base; + this->id = id; + this->symbol = symbol; + this->ptr = 0; + this->property = 0; + this->storage = MemberStorage; + this->builtin = NoBuiltinSymbol; + this->line = line; + this->column = column; + + if (id->length() == 8 && *id == QLatin1String("Math.sin")) { + builtin = MathSinBultinFunction; + } else if (id->length() == 8 && *id == QLatin1String("Math.cos")) { + builtin = MathCosBultinFunction; + } else if (id->length() == 10 && *id == QLatin1String("Math.round")) { + builtin = MathRoundBultinFunction; + } else if (id->length() == 10 && *id == QLatin1String("Math.floor)")) { + builtin = MathFloorBultinFunction; + } else if (id->length() == 7 && *id == QLatin1String("Math.PI")) { + builtin = MathPIBuiltinConstant; + this->type = RealType; + } +} + +void Name::dump(QTextStream &out) +{ + if (base) { + base->dump(out); + out << '.'; + } + + out << *id; +} + +void Temp::dump(QTextStream &out) +{ + out << 't' << index; +} + +void Unop::dump(QTextStream &out) +{ + out << opname(op); + expr->dump(out); +} + +Type Unop::typeForOp(AluOp op, Expr *expr) +{ + switch (op) { + case OpIfTrue: return BoolType; + case OpNot: return BoolType; + + case OpUMinus: + case OpUPlus: + case OpCompl: + return maxType(expr->type, RealType); + + default: + break; + } + + return InvalidType; +} + +void Binop::dump(QTextStream &out) +{ + left->dump(out); + out << ' ' << opname(op) << ' '; + right->dump(out); +} + +Type Binop::typeForOp(AluOp op, Expr *left, Expr *right) +{ + if (! (left && right)) + return InvalidType; + + switch (op) { + case OpInvalid: + return InvalidType; + + // unary operators + case OpIfTrue: + case OpNot: + case OpUMinus: + case OpUPlus: + case OpCompl: + return InvalidType; + + // bit fields + case OpBitAnd: + case OpBitOr: + case OpBitXor: + return IntType; + + case OpAdd: + if (left->type == StringType) + return StringType; + return RealType; + + case OpSub: + case OpMul: + case OpDiv: + case OpMod: + return RealType; + + case OpLShift: + case OpRShift: + case OpURShift: + return IntType; + + case OpAnd: + case OpOr: + return BoolType; + + case OpGt: + case OpLt: + case OpGe: + case OpLe: + case OpEqual: + case OpNotEqual: + case OpStrictEqual: + case OpStrictNotEqual: + return BoolType; + } // switch + + return InvalidType; +} + +void Call::dump(QTextStream &out) +{ + base->dump(out); + out << '('; + for (ExprList *it = args; it; it = it->next) { + if (it != args) + out << ", "; + it->expr->dump(out); + } + out << ')'; +} + +Type Call::typeForFunction(Expr *base) +{ + if (! base) + return InvalidType; + + if (Name *name = base->asName()) { + switch (name->builtin) { + case MathSinBultinFunction: + case MathCosBultinFunction: + return RealType; + + case MathRoundBultinFunction: + case MathFloorBultinFunction: + return IntType; + + case NoBuiltinSymbol: + case MathPIBuiltinConstant: + break; + } + } // switch + + return InvalidType; +} + +void Exp::dump(QTextStream &out, Mode) +{ + out << "(void) "; + expr->dump(out); + out << ';'; +} + +void Move::dump(QTextStream &out, Mode) +{ + target->dump(out); + out << " = "; + if (source->type != target->type) + out << typeName(source->type) << "_to_" << typeName(target->type) << '('; + source->dump(out); + if (source->type != target->type) + out << ')'; + out << ';'; +} + +void Jump::dump(QTextStream &out, Mode mode) +{ + Q_UNUSED(mode); + out << "goto " << 'L' << target << ';'; +} + +void CJump::dump(QTextStream &out, Mode mode) +{ + Q_UNUSED(mode); + out << "if ("; + cond->dump(out); + out << ") goto " << 'L' << iftrue << "; else goto " << 'L' << iffalse << ';'; +} + +void Ret::dump(QTextStream &out, Mode) +{ + out << "return"; + if (expr) { + out << ' '; + expr->dump(out); + } + out << ';'; +} + +Function::~Function() +{ + qDeleteAll(basicBlocks); +} + +QString *Function::newString(const QString &text) +{ + return pool->NewString(text); +} + +BasicBlock *Function::newBasicBlock() +{ + const int index = basicBlocks.size(); + return i(new BasicBlock(this, index)); +} + +void Function::dump(QTextStream &out) +{ + out << "function () {" << endl; + foreach (BasicBlock *bb, basicBlocks) { + bb->dump(out); + } + out << '}' << endl; +} + +Temp *BasicBlock::TEMP(Type type, int index) +{ + Temp *e = function->pool->New(); + e->init(type, index); + return e; +} + +Temp *BasicBlock::TEMP(Type type) +{ + return TEMP(type, function->tempCount++); +} + +Expr *BasicBlock::CONST(double value) +{ + return CONST(IR::RealType, value); +} + +Expr *BasicBlock::CONST(Type type, double value) +{ + Const *e = function->pool->New(); + e->init(type, value); + return e; +} + +Expr *BasicBlock::STRING(const QStringRef &value) +{ + String *e = function->pool->New(); + e->init(value); + return e; +} + +Name *BasicBlock::NAME(const QString &id, quint32 line, quint32 column) +{ + return NAME(0, id, line, column); +} + +Name *BasicBlock::NAME(Name *base, const QString &id, quint32 line, quint32 column) +{ + Name *e = function->pool->New(); + e->init(base, InvalidType, + function->newString(id), + Name::Unbound, line, column); + return e; +} + +Name *BasicBlock::SYMBOL(Type type, const QString &id, const QMetaObject *meta, QQmlPropertyData *property, Name::Storage storage, + quint32 line, quint32 column) +{ + Name *name = SYMBOL(/*base = */ 0, type, id, meta, property, line, column); + name->storage = storage; + return name; +} + +Name *BasicBlock::SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, QQmlPropertyData *property, Name::Storage storage, + quint32 line, quint32 column) +{ + Name *name = function->pool->New(); + name->init(base, type, function->newString(id), + Name::Property, line, column); + name->meta = meta; + name->property = property; + name->storage = storage; + return name; +} + +Name *BasicBlock::SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, QQmlPropertyData *property, + quint32 line, quint32 column) +{ + Name *name = function->pool->New(); + name->init(base, type, function->newString(id), + Name::Property, line, column); + name->meta = meta; + name->property = property; + return name; +} + +Name *BasicBlock::ID_OBJECT(const QString &id, const QQmlScript::Object *object, quint32 line, quint32 column) +{ + Name *name = function->pool->New(); + name->init(/*base = */ 0, IR::ObjectType, + function->newString(id), + Name::IdObject, line, column); + name->idObject = object; + name->property = 0; + name->storage = Name::IdStorage; + return name; +} + +Name *BasicBlock::ATTACH_TYPE(const QString &id, const QQmlType *attachType, Name::Storage storage, + quint32 line, quint32 column) +{ + Name *name = function->pool->New(); + name->init(/*base = */ 0, IR::AttachType, + function->newString(id), + Name::AttachType, line, column); + name->declarativeType = attachType; + name->storage = storage; + return name; +} + + +Expr *BasicBlock::UNOP(AluOp op, Expr *expr) +{ + Unop *e = function->pool->New(); + e->init(op, expr); + return e; +} + +Expr *BasicBlock::BINOP(AluOp op, Expr *left, Expr *right) +{ + if (left && right) { + if (Const *c1 = left->asConst()) { + if (Const *c2 = right->asConst()) { + switch (op) { + case OpAdd: return CONST(c1->value + c2->value); + case OpAnd: return CONST(c1->value ? c2->value : 0); + case OpBitAnd: return CONST(int(c1->value) & int(c2->value)); + case OpBitOr: return CONST(int(c1->value) | int(c2->value)); + case OpBitXor: return CONST(int(c1->value) ^ int(c2->value)); + case OpDiv: return CONST(c1->value / c2->value); + case OpEqual: return CONST(c1->value == c2->value); + case OpGe: return CONST(c1->value >= c2->value); + case OpGt: return CONST(c1->value > c2->value); + case OpLe: return CONST(c1->value <= c2->value); + case OpLShift: return CONST(int(c1->value) << int(c2->value)); + case OpLt: return CONST(c1->value < c2->value); + case OpMod: return CONST(::fmod(c1->value, c2->value)); + case OpMul: return CONST(c1->value * c2->value); + case OpNotEqual: return CONST(c1->value != c2->value); + case OpOr: return CONST(c1->value ? c1->value : c2->value); + case OpRShift: return CONST(int(c1->value) >> int(c2->value)); + case OpStrictEqual: return CONST(c1->value == c2->value); + case OpStrictNotEqual: return CONST(c1->value != c2->value); + case OpSub: return CONST(c1->value - c2->value); + case OpURShift: return CONST(unsigned(c1->value) >> int(c2->value)); + + case OpIfTrue: // unary ops + case OpNot: + case OpUMinus: + case OpUPlus: + case OpCompl: + case OpInvalid: + break; + } + } + } + } + + Binop *e = function->pool->New(); + e->init(op, left, right); + return e; +} + +Expr *BasicBlock::CALL(Expr *base, ExprList *args) +{ + Call *e = function->pool->New(); + e->init(base, args); + return e; +} + +Stmt *BasicBlock::EXP(Expr *expr) +{ + Exp *s = function->pool->New(); + s->init(expr); + statements.append(s); + return s; +} + +Stmt *BasicBlock::MOVE(Expr *target, Expr *source, bool isMoveForReturn) +{ + Move *s = function->pool->New(); + s->init(target, source, isMoveForReturn); + statements.append(s); + return s; +} + +Stmt *BasicBlock::JUMP(BasicBlock *target) +{ + if (isTerminated()) + return 0; + + Jump *s = function->pool->New(); + s->init(target); + statements.append(s); + return s; +} + +Stmt *BasicBlock::CJUMP(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse) +{ + if (isTerminated()) + return 0; + + CJump *s = function->pool->New(); + s->init(cond, iftrue, iffalse); + statements.append(s); + return s; +} + +Stmt *BasicBlock::RET(Expr *expr, Type type, quint32 line, quint32 column) +{ + if (isTerminated()) + return 0; + + Ret *s = function->pool->New(); + s->init(expr, type, line, column); + statements.append(s); + return s; +} + +void BasicBlock::dump(QTextStream &out) +{ + out << 'L' << this << ':' << endl; + foreach (Stmt *s, statements) { + out << '\t'; + s->dump(out); + out << endl; + } +} + +#ifdef DEBUG_IR_STRUCTURE + +static const char *symbolname(Name::Symbol s) +{ + switch (s) { + case Name::Unbound: + return "Unbound"; + case Name::IdObject: + return "IdObject"; + case Name::AttachType: + return "AttachType"; + case Name::Object: + return "Object"; + case Name::Property: + return "Property"; + case Name::Slot: + return "Slot"; + default: + Q_ASSERT(!"Unreachable"); + return "Unknown"; + } +} + +static const char *storagename(Name::Storage s) +{ + switch (s) { + case Name::MemberStorage: + return "MemberStorage"; + case Name::IdStorage: + return "IdStorage"; + case Name::RootStorage: + return "RootStorage"; + case Name::ScopeStorage: + return "ScopeStorage"; + default: + Q_ASSERT(!"Unreachable"); + return "UnknownStorage"; + } +} + +IRDump::IRDump() +: indentSize(0) +{ +} + +void IRDump::inc() +{ + indentSize++; + indentData = QByteArray(indentSize * 4, ' '); +} + +void IRDump::dec() +{ + indentSize--; + indentData = QByteArray(indentSize * 4, ' '); +} + +void IRDump::dec(); + +void IRDump::expression(QQmlJS::IR::Expr *e) +{ + inc(); + + e->accept(this); + + dec(); +} + +void IRDump::basicblock(QQmlJS::IR::BasicBlock *b) +{ + inc(); + + qWarning().nospace() << indent() << "BasicBlock " << b << " {"; + for (int ii = 0; ii < b->statements.count(); ++ii) { + statement(b->statements.at(ii)); + if (ii != (b->statements.count() - 1)) + qWarning(); + } + qWarning().nospace() << indent() << "}"; + + dec(); +} + +void IRDump::statement(QQmlJS::IR::Stmt *s) +{ + inc(); + + s->accept(this); + + dec(); +} + +void IRDump::function(QQmlJS::IR::Function *f) +{ + inc(); + + qWarning().nospace() << indent() << "Function {"; + for (int ii = 0; ii < f->basicBlocks.count(); ++ii) { + basicblock(f->basicBlocks.at(ii)); + } + qWarning().nospace() << indent() << "}"; + + dec(); +} + +const char *IRDump::indent() +{ + return indentData.constData(); +} + +void IRDump::visitConst(QQmlJS::IR::Const *e) +{ + qWarning().nospace() << indent() << "Const:Expr { type: " << typeName(e->type) << ", value: " << e->value << "}"; +} + +void IRDump::visitString(QQmlJS::IR::String *e) +{ + qWarning().nospace() << indent() << "String:Expr { type: " << typeName(e->type) << ", value: " << e->value << "}"; +} + +static void namedumprecur(QQmlJS::IR::Name *e, const char *indent) +{ + if (e->base) namedumprecur(e->base, indent); + qWarning().nospace() << indent << " { type: " << typeName(e->type) << ", symbol: " << symbolname(e->symbol) << ", storage: " << storagename(e->storage) << ", id: " << e->id << "}"; +} + +void IRDump::visitName(QQmlJS::IR::Name *e) +{ + qWarning().nospace() << indent() << "Name:Expr {"; + namedumprecur(e, indent()); + qWarning().nospace() << indent() << "}"; +} + +void IRDump::visitTemp(QQmlJS::IR::Temp *e) +{ + qWarning().nospace() << indent() << "Temp:Expr { type: " << typeName(e->type) << ", index: " << e->index << " }"; +} + +void IRDump::visitUnop(QQmlJS::IR::Unop *e) +{ + qWarning().nospace() << indent() << "Unop:Expr { "; + qWarning().nospace() << indent() << " type: " << typeName(e->type) << ", op: " << opname(e->op); + qWarning().nospace() << indent() << " expr: {"; + expression(e->expr); + qWarning().nospace() << indent() << " }"; + qWarning().nospace() << indent() << "}"; +} + +void IRDump::visitBinop(QQmlJS::IR::Binop *e) +{ + qWarning().nospace() << indent() << "Binop:Expr { "; + qWarning().nospace() << indent() << " type: " << typeName(e->type) << ", op: " << opname(e->op); + qWarning().nospace() << indent() << " left: {"; + inc(); + expression(e->left); + dec(); + qWarning().nospace() << indent() << " },"; + qWarning().nospace() << indent() << " right: {"; + inc(); + expression(e->right); + dec(); + qWarning().nospace() << indent() << " }"; + qWarning().nospace() << indent() << "}"; +} + +void IRDump::visitCall(QQmlJS::IR::Call *e) +{ + Q_UNUSED(e); + qWarning().nospace() << indent() << "Exp::Call { }"; +} + +void IRDump::visitExp(QQmlJS::IR::Exp *s) +{ + qWarning().nospace() << indent() << "Exp:Stmt {"; + expression(s->expr); + qWarning().nospace() << indent() << "}"; +} + +void IRDump::visitMove(QQmlJS::IR::Move *s) +{ + qWarning().nospace() << indent() << "Move:Stmt {"; + qWarning().nospace() << indent() << " isMoveForReturn: " << s->isMoveForReturn; + qWarning().nospace() << indent() << " target: {"; + inc(); + expression(s->target); + dec(); + qWarning().nospace() << indent() << " },"; + qWarning().nospace() << indent() << " source: {"; + inc(); + expression(s->source); + dec(); + qWarning().nospace() << indent() << " }"; + qWarning().nospace() << indent() << "}"; +} + +void IRDump::visitJump(QQmlJS::IR::Jump *s) +{ + qWarning().nospace() << indent() << "Jump:Stmt { BasicBlock(" << s->target << ") }"; +} + +void IRDump::visitCJump(QQmlJS::IR::CJump *s) +{ + qWarning().nospace() << indent() << "CJump:Stmt {"; + qWarning().nospace() << indent() << " cond: {"; + inc(); + expression(s->cond); + dec(); + qWarning().nospace() << indent() << " }"; + qWarning().nospace() << indent() << " iftrue: BasicBlock(" << s->iftrue << ")"; + qWarning().nospace() << indent() << " iffalse: BasicBlock(" << s->iffalse << ")"; + qWarning().nospace() << indent() << "}"; +} + +void IRDump::visitRet(QQmlJS::IR::Ret *s) +{ + qWarning().nospace() << indent() << "Ret:Stmt {"; + qWarning().nospace() << indent() << " type: " << typeName(s->type); + expression(s->expr); + qWarning().nospace() << indent() << "}"; +} +#endif + +} // end of namespace IR +} // end of namespace QQmlJS + +QT_END_NAMESPACE diff --cc src/qml/qml/v4/qv4ir_p.h index 48a08ad,0000000..e80c7e2 mode 100644,000000..100644 --- a/src/qml/qml/v4/qv4ir_p.h +++ b/src/qml/qml/v4/qv4ir_p.h @@@ -1,604 -1,0 +1,605 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QV4IR_P_H +#define QV4IR_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include +#include + +#include +#include + +// #define DEBUG_IR_STRUCTURE + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QTextStream; +class QQmlType; + +namespace QQmlJS { + +namespace IR { + +struct BasicBlock; +struct Function; + +struct Stmt; +struct Expr; + +// expressions +struct Const; +struct String; +struct Name; +struct Temp; +struct Unop; +struct Binop; +struct Call; + +// statements +struct Exp; +struct Move; +struct Jump; +struct CJump; +struct Ret; + +enum AluOp { + OpInvalid = 0, + + OpIfTrue, + OpNot, + OpUMinus, + OpUPlus, + OpCompl, + + OpBitAnd, + OpBitOr, + OpBitXor, + + OpAdd, + OpSub, + OpMul, + OpDiv, + OpMod, + + OpLShift, + OpRShift, + OpURShift, + + OpGt, + OpLt, + OpGe, + OpLe, + OpEqual, + OpNotEqual, + OpStrictEqual, + OpStrictNotEqual, + + OpAnd, + OpOr +}; +AluOp binaryOperator(int op); + +enum Type { + InvalidType, + UndefinedType, + NullType, + VoidType, + StringType, + UrlType, ++ ColorType, + SGAnchorLineType, + AttachType, + ObjectType, + + FirstNumberType, + BoolType = FirstNumberType, + IntType, + RealType, + RealNaNType +}; +Type maxType(IR::Type left, IR::Type right); + +struct ExprVisitor { + virtual ~ExprVisitor() {} + virtual void visitConst(Const *) {} + virtual void visitString(String *) {} + virtual void visitName(Name *) {} + virtual void visitTemp(Temp *) {} + virtual void visitUnop(Unop *) {} + virtual void visitBinop(Binop *) {} + virtual void visitCall(Call *) {} +}; + +struct StmtVisitor { + virtual ~StmtVisitor() {} + virtual void visitExp(Exp *) {} + virtual void visitMove(Move *) {} + virtual void visitJump(Jump *) {} + virtual void visitCJump(CJump *) {} + virtual void visitRet(Ret *) {} +}; + +struct Expr: QQmlPool::POD { + Type type; + + Expr(): type(InvalidType) {} + virtual ~Expr() {} + virtual void accept(ExprVisitor *) = 0; + virtual Const *asConst() { return 0; } + virtual String *asString() { return 0; } + virtual Name *asName() { return 0; } + virtual Temp *asTemp() { return 0; } + virtual Unop *asUnop() { return 0; } + virtual Binop *asBinop() { return 0; } + virtual Call *asCall() { return 0; } + virtual void dump(QTextStream &out) = 0; +}; + +struct ExprList: QQmlPool::POD { + Expr *expr; + ExprList *next; + + void init(Expr *expr, ExprList *next = 0) + { + this->expr = expr; + this->next = next; + } +}; + +struct Const: Expr { + double value; + + void init(Type type, double value) + { + this->type = type; + this->value = value; + } + + virtual void accept(ExprVisitor *v) { v->visitConst(this); } + virtual Const *asConst() { return this; } + + virtual void dump(QTextStream &out); +}; + +struct String: Expr { + QStringRef value; + + void init(const QStringRef &value) + { + this->type = StringType; + this->value = value; + } + + virtual void accept(ExprVisitor *v) { v->visitString(this); } + virtual String *asString() { return this; } + + virtual void dump(QTextStream &out); + static QString escape(const QStringRef &s); +}; + +enum BuiltinSymbol { + NoBuiltinSymbol, + MathSinBultinFunction, + MathCosBultinFunction, + MathRoundBultinFunction, + MathFloorBultinFunction, + + MathPIBuiltinConstant +}; + +struct Name: Expr { + enum Symbol { + Unbound, + IdObject, // This is a load of a id object. Storage will always be IdStorage + AttachType, // This is a load of an attached object + Object, // XXX what is this for? + Property, // This is a load of a regular property + Slot // XXX what is this for? + }; + + enum Storage { + MemberStorage, // This is a property of a previously fetched object + IdStorage, // This is a load of a id object. Symbol will always be IdObject + RootStorage, // This is a property of the root object + ScopeStorage // This is a property of the scope object + }; + + Name *base; + const QString *id; + Symbol symbol; + union { + void *ptr; + const QMetaObject *meta; + const QQmlType *declarativeType; + const QQmlScript::Object *idObject; + }; + QQmlPropertyData *property; + Storage storage; + BuiltinSymbol builtin; + quint32 line; + quint32 column; + + void init(Name *base, Type type, const QString *id, Symbol symbol, quint32 line, quint32 column); + + inline bool is(Symbol s) const { return s == symbol; } + inline bool isNot(Symbol s) const { return s != symbol; } + + virtual void accept(ExprVisitor *v) { v->visitName(this); } + virtual Name *asName() { return this; } + + virtual void dump(QTextStream &out); +}; + +struct Temp: Expr { + int index; + + void init(Type type, int index) + { + this->type = type; + this->index = index; + } + + virtual void accept(ExprVisitor *v) { v->visitTemp(this); } + virtual Temp *asTemp() { return this; } + + virtual void dump(QTextStream &out); +}; + +struct Unop: Expr { + AluOp op; + Expr *expr; + + void init(AluOp op, Expr *expr) + { + this->type = this->typeForOp(op, expr); + this->op = op; + this->expr = expr; + } + + virtual void accept(ExprVisitor *v) { v->visitUnop(this); } + virtual Unop *asUnop() { return this; } + + virtual void dump(QTextStream &out); + +private: + static Type typeForOp(AluOp op, Expr *expr); +}; + +struct Binop: Expr { + AluOp op; + Expr *left; + Expr *right; + + void init(AluOp op, Expr *left, Expr *right) + { + this->type = typeForOp(op, left, right); + this->op = op; + this->left = left; + this->right = right; + } + + virtual void accept(ExprVisitor *v) { v->visitBinop(this); } + virtual Binop *asBinop() { return this; } + + virtual void dump(QTextStream &out); + +private: + static Type typeForOp(AluOp op, Expr *left, Expr *right); +}; + +struct Call: Expr { + Expr *base; + ExprList *args; + + void init(Expr *base, ExprList *args) + { + this->type = typeForFunction(base); + this->base = base; + this->args = args; + } + + Expr *onlyArgument() const { + if (args && ! args->next) + return args->expr; + return 0; + } + + virtual void accept(ExprVisitor *v) { v->visitCall(this); } + virtual Call *asCall() { return this; } + + virtual void dump(QTextStream &out); + +private: + static Type typeForFunction(Expr *base); +}; + +struct Stmt: QQmlPool::POD { + enum Mode { + HIR, + MIR + }; + + virtual ~Stmt() {} + virtual Stmt *asTerminator() { return 0; } + + virtual void accept(StmtVisitor *) = 0; + virtual Exp *asExp() { return 0; } + virtual Move *asMove() { return 0; } + virtual Jump *asJump() { return 0; } + virtual CJump *asCJump() { return 0; } + virtual Ret *asRet() { return 0; } + virtual void dump(QTextStream &out, Mode mode = HIR) = 0; +}; + +struct Exp: Stmt { + Expr *expr; + + void init(Expr *expr) + { + this->expr = expr; + } + + virtual void accept(StmtVisitor *v) { v->visitExp(this); } + virtual Exp *asExp() { return this; } + + virtual void dump(QTextStream &out, Mode); +}; + +struct Move: Stmt { + Expr *target; + Expr *source; + bool isMoveForReturn; + + void init(Expr *target, Expr *source, bool isMoveForReturn) + { + this->target = target; + this->source = source; + this->isMoveForReturn = isMoveForReturn; + } + + virtual void accept(StmtVisitor *v) { v->visitMove(this); } + virtual Move *asMove() { return this; } + + virtual void dump(QTextStream &out, Mode); +}; + +struct Jump: Stmt { + BasicBlock *target; + + void init(BasicBlock *target) + { + this->target = target; + } + + virtual Stmt *asTerminator() { return this; } + + virtual void accept(StmtVisitor *v) { v->visitJump(this); } + virtual Jump *asJump() { return this; } + + virtual void dump(QTextStream &out, Mode mode); +}; + +struct CJump: Stmt { + Expr *cond; + BasicBlock *iftrue; + BasicBlock *iffalse; + + void init(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse) + { + this->cond = cond; + this->iftrue = iftrue; + this->iffalse = iffalse; + } + + virtual Stmt *asTerminator() { return this; } + + virtual void accept(StmtVisitor *v) { v->visitCJump(this); } + virtual CJump *asCJump() { return this; } + + virtual void dump(QTextStream &out, Mode mode); +}; + +struct Ret: Stmt { + Expr *expr; + Type type; + quint32 line; + quint32 column; + + void init(Expr *expr, Type type, quint32 line, quint32 column) + { + this->expr = expr; + this->type = type; + this->line = line; + this->column = column; + } + + virtual Stmt *asTerminator() { return this; } + + virtual void accept(StmtVisitor *v) { v->visitRet(this); } + virtual Ret *asRet() { return this; } + + virtual void dump(QTextStream &out, Mode); +}; + +struct Function { + QQmlPool *pool; + QVarLengthArray basicBlocks; + int tempCount; + + Function(QQmlPool *pool) + : pool(pool), tempCount(0) {} + + ~Function(); + + BasicBlock *newBasicBlock(); + QString *newString(const QString &text); + + inline BasicBlock *i(BasicBlock *block) { basicBlocks.append(block); return block; } + + virtual void dump(QTextStream &out); +}; + +struct BasicBlock { + Function *function; + int index; + int offset; + QVarLengthArray statements; + + BasicBlock(Function *function, int index): function(function), index(index), offset(-1) {} + ~BasicBlock() {} + + template inline Instr i(Instr i) { statements.append(i); return i; } + + inline bool isEmpty() const { + return statements.isEmpty(); + } + + inline Stmt *terminator() const { + if (! statements.isEmpty() && statements.at(statements.size() - 1)->asTerminator() != 0) + return statements.at(statements.size() - 1); + return 0; + } + + inline bool isTerminated() const { + if (terminator() != 0) + return true; + return false; + } + + Temp *TEMP(Type type, int index); + Temp *TEMP(Type type); + + Expr *CONST(double value); + Expr *CONST(Type type, double value); + Expr *STRING(const QStringRef &value); + + Name *NAME(const QString &id, quint32 line, quint32 column); + Name *NAME(Name *base, const QString &id, quint32 line, quint32 column); + Name *SYMBOL(Type type, const QString &id, const QMetaObject *meta, QQmlPropertyData *property, Name::Storage storage, quint32 line, quint32 column); + Name *SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, QQmlPropertyData *property, quint32 line, quint32 column); + Name *SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, QQmlPropertyData *property, Name::Storage storage, quint32 line, quint32 column); + Name *ID_OBJECT(const QString &id, const QQmlScript::Object *object, quint32 line, quint32 column); + Name *ATTACH_TYPE(const QString &id, const QQmlType *attachType, Name::Storage storage, quint32 line, quint32 column); + + Expr *UNOP(AluOp op, Expr *expr); + Expr *BINOP(AluOp op, Expr *left, Expr *right); + Expr *CALL(Expr *base, ExprList *args); + + Stmt *EXP(Expr *expr); + Stmt *MOVE(Expr *target, Expr *source, bool = false); + + Stmt *JUMP(BasicBlock *target); + Stmt *CJUMP(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse); + Stmt *RET(Expr *expr, Type type, quint32 line, quint32 column); + + virtual void dump(QTextStream &out); +}; + +#ifdef DEBUG_IR_STRUCTURE +struct IRDump : public ExprVisitor, + public StmtVisitor +{ +public: + IRDump(); + + void expression(QQmlJS::IR::Expr *); + void basicblock(QQmlJS::IR::BasicBlock *); + void statement(QQmlJS::IR::Stmt *); + void function(QQmlJS::IR::Function *); +protected: + + const char *indent(); + + // + // expressions + // + virtual void visitConst(QQmlJS::IR::Const *e); + virtual void visitString(QQmlJS::IR::String *e); + virtual void visitName(QQmlJS::IR::Name *e); + virtual void visitTemp(QQmlJS::IR::Temp *e); + virtual void visitUnop(QQmlJS::IR::Unop *e); + virtual void visitBinop(QQmlJS::IR::Binop *e); + virtual void visitCall(QQmlJS::IR::Call *e); + + // + // statements + // + virtual void visitExp(QQmlJS::IR::Exp *s); + virtual void visitMove(QQmlJS::IR::Move *s); + virtual void visitJump(QQmlJS::IR::Jump *s); + virtual void visitCJump(QQmlJS::IR::CJump *s); + virtual void visitRet(QQmlJS::IR::Ret *s); + +private: + int indentSize; + QByteArray indentData; + void inc(); + void dec(); +}; +#endif + +} // end of namespace IR + +} // end of namespace QQmlJS + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QV4IR_P_H diff --cc src/qml/qml/v4/qv4irbuilder.cpp index 1956be8,0000000..0efb268 mode 100644,000000..100644 --- a/src/qml/qml/v4/qv4irbuilder.cpp +++ b/src/qml/qml/v4/qv4irbuilder.cpp @@@ -1,1303 -1,0 +1,1306 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qv4irbuilder_p.h" +#include "qv4compiler_p_p.h" + +#include +#include +#include + +DEFINE_BOOL_CONFIG_OPTION(qmlVerboseCompiler, QML_VERBOSE_COMPILER) + +QT_BEGIN_NAMESPACE + +using namespace QQmlJS; + +static IR::Type irTypeFromVariantType(int t, QQmlEnginePrivate *engine, const QMetaObject * /* meta */) +{ + switch (t) { + case QMetaType::Bool: + return IR::BoolType; + + case QMetaType::Int: + return IR::IntType; + + case QMetaType::QReal: + return IR::RealType; + + case QMetaType::QString: + return IR::StringType; + + case QMetaType::QUrl: + return IR::UrlType; + ++ case QMetaType::QColor: ++ return IR::ColorType; ++ + default: + if (t == QQmlMetaType::QQuickAnchorLineMetaTypeId()) { + return IR::SGAnchorLineType; + } else if (engine->metaObjectForType(t)) { + return IR::ObjectType; + } + + return IR::InvalidType; + } +} + +QV4IRBuilder::QV4IRBuilder(const QV4Compiler::Expression *expr, + QQmlEnginePrivate *engine) +: m_expression(expr), m_engine(engine), _function(0), _block(0), _discard(false) +{ +} + +bool QV4IRBuilder::operator()(QQmlJS::IR::Function *function, + QQmlJS::AST::Node *ast) +{ + bool discarded = false; + + IR::BasicBlock *block = function->newBasicBlock(); + + qSwap(_discard, discarded); + qSwap(_function, function); + qSwap(_block, block); + + ExprResult r; + AST::SourceLocation location; + if (AST::ExpressionNode *asExpr = ast->expressionCast()) { + r = expression(asExpr); + location = asExpr->firstSourceLocation(); + } else if (AST::Statement *asStmt = ast->statementCast()) { + r = statement(asStmt); + location = asStmt->firstSourceLocation(); + } + + //_block->MOVE(_block->TEMP(IR::InvalidType), r.code); + if (r.code) { + const QMetaObject *m = 0; + const IR::Type targetType = irTypeFromVariantType(m_expression->property->type, m_engine, m); + if (targetType != r.type()) { + IR::Expr *x = _block->TEMP(targetType); + _block->MOVE(x, r, true); + r.code = x; + } + _block->RET(r.code, targetType, location.startLine, location.startColumn); + } + + qSwap(_block, block); + qSwap(_function, function); + qSwap(_discard, discarded); + + return !discarded; +} + +bool QV4IRBuilder::buildName(QList &name, + AST::Node *node, + QList *nodes) +{ + if (node->kind == AST::Node::Kind_IdentifierExpression) { + name << static_cast(node)->name; + if (nodes) *nodes << static_cast(node); + } else if (node->kind == AST::Node::Kind_FieldMemberExpression) { + AST::FieldMemberExpression *expr = + static_cast(node); + + if (!buildName(name, expr->base, nodes)) + return false; + + name << expr->name; + if (nodes) *nodes << expr; + } else { + return false; + } + + return true; +} + +void QV4IRBuilder::discard() +{ + _discard = true; +} + +QV4IRBuilder::ExprResult +QV4IRBuilder::expression(AST::ExpressionNode *ast) +{ + ExprResult r; + if (ast) { + qSwap(_expr, r); + accept(ast); + qSwap(_expr, r); + + if (r.is(IR::InvalidType)) + discard(); + else { + Q_ASSERT(r.hint == r.format); + } + } + + return r; +} + +void QV4IRBuilder::condition(AST::ExpressionNode *ast, IR::BasicBlock *iftrue, IR::BasicBlock *iffalse) +{ + if (! ast) + return; + ExprResult r(iftrue, iffalse); + qSwap(_expr, r); + accept(ast); + qSwap(_expr, r); + + if (r.format != ExprResult::cx) { + if (! r.code) + discard(); + + Q_ASSERT(r.hint == ExprResult::cx); + Q_ASSERT(r.format == ExprResult::ex); + + if (r.type() != IR::BoolType) { + IR::Temp *t = _block->TEMP(IR::BoolType); + _block->MOVE(t, r); + r = t; + } + + _block->CJUMP(_block->UNOP(IR::OpIfTrue, r), iftrue, iffalse); + } +} + +QV4IRBuilder::ExprResult +QV4IRBuilder::statement(AST::Statement *ast) +{ + ExprResult r; + if (ast) { + qSwap(_expr, r); + accept(ast); + qSwap(_expr, r); + + if (r.is(IR::InvalidType)) + discard(); + else { + Q_ASSERT(r.hint == r.format); + } + } + + return r; +} + +void QV4IRBuilder::sourceElement(AST::SourceElement *ast) +{ + accept(ast); +} + +void QV4IRBuilder::implicitCvt(ExprResult &expr, IR::Type type) +{ + if (expr.type() == type) + return; // nothing to do + + IR::Expr *x = _block->TEMP(type); + _block->MOVE(x, expr.code); + expr.code = x; +} + +// QML +bool QV4IRBuilder::visit(AST::UiProgram *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QV4IRBuilder::visit(AST::UiImportList *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QV4IRBuilder::visit(AST::UiImport *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QV4IRBuilder::visit(AST::UiPublicMember *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QV4IRBuilder::visit(AST::UiSourceElement *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QV4IRBuilder::visit(AST::UiObjectDefinition *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QV4IRBuilder::visit(AST::UiObjectInitializer *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QV4IRBuilder::visit(AST::UiObjectBinding *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QV4IRBuilder::visit(AST::UiScriptBinding *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QV4IRBuilder::visit(AST::UiArrayBinding *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QV4IRBuilder::visit(AST::UiObjectMemberList *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QV4IRBuilder::visit(AST::UiArrayMemberList *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QV4IRBuilder::visit(AST::UiQualifiedId *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + + +// JS +bool QV4IRBuilder::visit(AST::Program *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QV4IRBuilder::visit(AST::SourceElements *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QV4IRBuilder::visit(AST::FunctionSourceElement *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QV4IRBuilder::visit(AST::StatementSourceElement *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +// object literals +bool QV4IRBuilder::visit(AST::PropertyNameAndValueList *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QV4IRBuilder::visit(AST::IdentifierPropertyName *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QV4IRBuilder::visit(AST::StringLiteralPropertyName *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QV4IRBuilder::visit(AST::NumericLiteralPropertyName *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + + +// array literals +bool QV4IRBuilder::visit(AST::ElementList *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QV4IRBuilder::visit(AST::Elision *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + + +// function calls +bool QV4IRBuilder::visit(AST::ArgumentList *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +// expressions +bool QV4IRBuilder::visit(AST::ObjectLiteral *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::ArrayLiteral *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::ThisExpression *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::IdentifierExpression *ast) +{ + const quint32 line = ast->identifierToken.startLine; + const quint32 column = ast->identifierToken.startColumn; + + const QString name = ast->name.toString(); + + if (name.at(0) == QLatin1Char('u') && name.length() == 9 && name == QLatin1String("undefined")) { + _expr.code = _block->CONST(IR::UndefinedType, 0); // ### undefined value + } else if (m_engine->v8engine()->illegalNames().contains(name) ) { + if (qmlVerboseCompiler()) qWarning() << "*** illegal symbol:" << name; + return false; + } else if (const QQmlScript::Object *obj = m_expression->ids->value(name)) { + IR::Name *code = _block->ID_OBJECT(name, obj, line, column); + if (obj == m_expression->component) + code->storage = IR::Name::RootStorage; + _expr.code = code; + } else { + + QQmlTypeNameCache::Result r = m_expression->importCache->query(name); + if (r.isValid()) { + if (r.type) { + _expr.code = _block->ATTACH_TYPE(name, r.type, IR::Name::ScopeStorage, line, column); + } + // We don't support anything else + } else { + bool found = false; + + if (m_expression->context != m_expression->component) { + // RootStorage is more efficient than ScopeStorage, so prefer that if they are the same + QQmlPropertyCache *cache = m_expression->context->synthCache; + const QMetaObject *metaObject = m_expression->context->metaObject(); + if (!cache) cache = m_engine->cache(metaObject); + + QQmlPropertyData *data = cache->property(name); + - if (data && data->revision != 0) { ++ if (data && data->hasRevision()) { + if (qmlVerboseCompiler()) + qWarning() << "*** versioned symbol:" << name; + discard(); + return false; + } + + if (data && !data->isFunction()) { + IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject); + _expr.code = _block->SYMBOL(irType, name, metaObject, data, IR::Name::ScopeStorage, line, column); + found = true; + } + } + + if (!found) { + QQmlPropertyCache *cache = m_expression->component->synthCache; + const QMetaObject *metaObject = m_expression->component->metaObject(); + if (!cache) cache = m_engine->cache(metaObject); + + QQmlPropertyData *data = cache->property(name); + - if (data && data->revision != 0) { ++ if (data && data->hasRevision()) { + if (qmlVerboseCompiler()) + qWarning() << "*** versioned symbol:" << name; + discard(); + return false; + } + + if (data && !data->isFunction()) { + IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject); + _expr.code = _block->SYMBOL(irType, name, metaObject, data, IR::Name::RootStorage, line, column); + found = true; + } + } + + if (!found && qmlVerboseCompiler()) + qWarning() << "*** unknown symbol:" << name; + } + } + + if (_expr.code && _expr.hint == ExprResult::cx) { + _expr.format = ExprResult::cx; + + if (_expr.type() != IR::BoolType) { + IR::Temp *t = _block->TEMP(IR::BoolType); + _block->MOVE(t, _expr); + _expr.code = t; + } + + _block->CJUMP(_expr.code, _expr.iftrue, _expr.iffalse); + _expr.code = 0; + } + + return false; +} + +bool QV4IRBuilder::visit(AST::NullExpression *) +{ + // ### TODO: cx format + _expr.code = _block->CONST(IR::NullType, 0); + return false; +} + +bool QV4IRBuilder::visit(AST::TrueLiteral *) +{ + // ### TODO: cx format + _expr.code = _block->CONST(IR::BoolType, 1); + return false; +} + +bool QV4IRBuilder::visit(AST::FalseLiteral *) +{ + // ### TODO: cx format + _expr.code = _block->CONST(IR::BoolType, 0); + return false; +} + +bool QV4IRBuilder::visit(AST::StringLiteral *ast) +{ + // ### TODO: cx format + _expr.code = _block->STRING(ast->value); + return false; +} + +bool QV4IRBuilder::visit(AST::NumericLiteral *ast) +{ + if (_expr.hint == ExprResult::cx) { + _expr.format = ExprResult::cx; + _block->JUMP(ast->value ? _expr.iftrue : _expr.iffalse); + } else { + _expr.code = _block->CONST(ast->value); + } + return false; +} + +bool QV4IRBuilder::visit(AST::RegExpLiteral *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::NestedExpression *) +{ + return true; // the value of the nested expression +} + +bool QV4IRBuilder::visit(AST::ArrayMemberExpression *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::FieldMemberExpression *ast) +{ + if (IR::Expr *left = expression(ast->base)) { + if (IR::Name *baseName = left->asName()) { + const quint32 line = ast->identifierToken.startLine; + const quint32 column = ast->identifierToken.startColumn; + + QString name = ast->name.toString(); + + switch(baseName->symbol) { + case IR::Name::Unbound: + break; + + case IR::Name::AttachType: + if (name.at(0).isUpper()) { + QByteArray utf8Name = name.toUtf8(); + const char *enumName = utf8Name.constData(); + + const QMetaObject *meta = baseName->declarativeType->metaObject(); + bool found = false; + for (int ii = 0; !found && ii < meta->enumeratorCount(); ++ii) { + QMetaEnum e = meta->enumerator(ii); + for (int jj = 0; !found && jj < e.keyCount(); ++jj) { + if (0 == strcmp(e.key(jj), enumName)) { + found = true; + _expr.code = _block->CONST(IR::IntType, e.value(jj)); + } + } + } + + if (!found && qmlVerboseCompiler()) + qWarning() << "*** unresolved enum:" + << (*baseName->id + QLatin1String(".") + ast->name.toString()); + } else if(const QMetaObject *attachedMeta = baseName->declarativeType->attachedPropertiesType()) { + QQmlPropertyCache *cache = m_engine->cache(attachedMeta); + QQmlPropertyData *data = cache->property(name); + + if (!data || data->isFunction()) + return false; // Don't support methods (or non-existing properties ;) + + if(!data->isFinal()) { + if (qmlVerboseCompiler()) + qWarning() << "*** non-final attached property:" + << (*baseName->id + QLatin1String(".") + ast->name.toString()); + return false; // We don't know enough about this property + } + + IR::Type irType = irTypeFromVariantType(data->propType, m_engine, attachedMeta); + _expr.code = _block->SYMBOL(baseName, irType, name, attachedMeta, data, line, column); + } + break; + + case IR::Name::IdObject: { + const QQmlScript::Object *idObject = baseName->idObject; + QQmlPropertyCache *cache = + idObject->synthCache?idObject->synthCache:m_engine->cache(idObject->metaObject()); + + QQmlPropertyData *data = cache->property(name); + + if (!data || data->isFunction()) + return false; // Don't support methods (or non-existing properties ;) + - if (data->revision != 0) { ++ if (data->hasRevision()) { + if (qmlVerboseCompiler()) + qWarning() << "*** versioned symbol:" << name; + discard(); + return false; + } + + IR::Type irType = irTypeFromVariantType(data->propType, m_engine, idObject->metaObject()); + _expr.code = _block->SYMBOL(baseName, irType, name, + idObject->metaObject(), data, line, column); + } + break; + + case IR::Name::Property: + if (baseName->type == IR::ObjectType && baseName->meta && baseName->property->isFinal()) { + QQmlPropertyCache *cache = m_engine->cache(baseName->meta); + if (!cache) + return false; + + if (QQmlPropertyData *data = cache->property(name)) { + if (!data->isFinal()) { + if (qmlVerboseCompiler()) + qWarning() << "*** non-final property access:" + << (*baseName->id + QLatin1String(".") + ast->name.toString()); + return false; // We don't know enough about this property + } + + IR::Type irType = irTypeFromVariantType(data->propType, m_engine, baseName->meta); + _expr.code = _block->SYMBOL(baseName, irType, name, + baseName->meta, data, line, column); + } + } + break; + + case IR::Name::Object: + case IR::Name::Slot: + break; + } + } + } + + return false; +} + +bool QV4IRBuilder::preVisit(AST::Node *) +{ + return ! _discard; +} + +bool QV4IRBuilder::visit(AST::NewMemberExpression *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::NewExpression *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::CallExpression *ast) +{ + QList names; + QList nameNodes; + + names.reserve(4); + nameNodes.reserve(4); + + if (buildName(names, ast->base, &nameNodes)) { + //ExprResult base = expression(ast->base); + QString id; + for (int i = 0; i < names.size(); ++i) { + if (! i) + id += QLatin1Char('.'); + id += names.at(i); + } + const AST::SourceLocation loc = nameNodes.last()->firstSourceLocation(); + IR::Expr *base = _block->NAME(id, loc.startLine, loc.startColumn); + + IR::ExprList *args = 0, **argsInserter = &args; + for (AST::ArgumentList *it = ast->arguments; it; it = it->next) { + IR::Expr *arg = expression(it->expression); + *argsInserter = _function->pool->New(); + (*argsInserter)->init(arg); + argsInserter = &(*argsInserter)->next; + } + + IR::Temp *r = _block->TEMP(IR::InvalidType); + IR::Expr *call = _block->CALL(base, args); + _block->MOVE(r, call); + r->type = call->type; + _expr.code = r; + } + + return false; +} + +bool QV4IRBuilder::visit(AST::PostIncrementExpression *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::PostDecrementExpression *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::DeleteExpression *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::VoidExpression *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::TypeOfExpression *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::PreIncrementExpression *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::PreDecrementExpression *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::UnaryPlusExpression *ast) +{ + ExprResult expr = expression(ast->expression); + if (expr.isNot(IR::InvalidType)) { + if (expr.code->asConst() != 0) { + _expr = expr; + return false; + } + + IR::Expr *code = _block->UNOP(IR::OpUPlus, expr); + _expr.code = _block->TEMP(code->type); + _block->MOVE(_expr, code); + } + + return false; +} + +bool QV4IRBuilder::visit(AST::UnaryMinusExpression *ast) +{ + ExprResult expr = expression(ast->expression); + if (expr.isNot(IR::InvalidType)) { + if (IR::Const *c = expr.code->asConst()) { + _expr = expr; + _expr.code = _block->CONST(-c->value); + return false; + } + + IR::Expr *code = _block->UNOP(IR::OpUMinus, expr); + _expr.code = _block->TEMP(code->type); + _block->MOVE(_expr, code); + } + + return false; +} + +bool QV4IRBuilder::visit(AST::TildeExpression *ast) +{ + ExprResult expr = expression(ast->expression); + if (expr.isNot(IR::InvalidType)) { + if (IR::Const *c = expr.code->asConst()) { + _expr = expr; + _expr.code = _block->CONST(~int(c->value)); + return false; + } + IR::Expr *code = _block->UNOP(IR::OpCompl, expr); + _expr.code = _block->TEMP(code->type); + _block->MOVE(_expr, code); + } + + return false; +} + +bool QV4IRBuilder::visit(AST::NotExpression *ast) +{ + ExprResult expr = expression(ast->expression); + + if (expr.isNot(IR::InvalidType)) { + if (IR::Const *c = expr.code->asConst()) { + _expr = expr; + _expr.code = _block->CONST(!c->value); + return false; + } + + IR::Expr *code = _block->UNOP(IR::OpNot, expr); + _expr.code = _block->TEMP(code->type); + _block->MOVE(_expr, code); + + } else if (expr.hint == ExprResult::cx) { + expr.format = ExprResult::cx; + _block->CJUMP(_block->UNOP(IR::OpNot, expr), _expr.iftrue, _expr.iffalse); + return false; + } + + return false; +} + +void QV4IRBuilder::binop(AST::BinaryExpression *ast, ExprResult left, ExprResult right) +{ + if (IR::Type t = maxType(left.type(), right.type())) { + implicitCvt(left, t); + implicitCvt(right, t); + + if (_expr.hint == ExprResult::cx) { + _expr.format = ExprResult::cx; + _block->CJUMP(_block->BINOP(IR::binaryOperator(ast->op), left, right), _expr.iftrue, _expr.iffalse); + } else { + IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right); + _expr.code = _block->TEMP(code->type); + _block->MOVE(_expr.code, code); + } + } +} + +bool QV4IRBuilder::visit(AST::BinaryExpression *ast) +{ + switch (ast->op) { + case QSOperator::And: { + if (_expr.hint == ExprResult::cx) { + _expr.format = ExprResult::cx; + + Q_ASSERT(_expr.iffalse != 0); + Q_ASSERT(_expr.iftrue != 0); + + IR::BasicBlock *iftrue = _function->newBasicBlock(); + condition(ast->left, iftrue, _expr.iffalse); + + _block = iftrue; + condition(ast->right, _expr.iftrue, _expr.iffalse); + } else { + IR::BasicBlock *iftrue = _function->newBasicBlock(); + IR::BasicBlock *iffalse = _function->newBasicBlock(); + IR::BasicBlock *endif = _function->newBasicBlock(); + + condition(ast->left, iftrue, iffalse); + + IR::Temp *r = _block->TEMP(IR::InvalidType); + + _block = iffalse; + _block->MOVE(r, _block->CONST(0)); // ### use the right null value + _block->JUMP(endif); + + _block = iftrue; + ExprResult right = expression(ast->right); + _block->MOVE(r, right); + _block->JUMP(endif); + + _block = endif; + + r->type = right.type(); // ### not exactly, it can be IR::BoolType. + _expr.code = r; + } + } break; + + case QSOperator::Or: { + IR::BasicBlock *iftrue = _function->newBasicBlock(); + IR::BasicBlock *endif = _function->newBasicBlock(); + + ExprResult left = expression(ast->left); + IR::Temp *r = _block->TEMP(left.type()); + _block->MOVE(r, left); + + IR::Expr *cond = r; + if (r->type != IR::BoolType) { + cond = _block->TEMP(IR::BoolType); + _block->MOVE(cond, r); + } + + _block->CJUMP(_block->UNOP(IR::OpNot, cond), iftrue, endif); + + _block = iftrue; + ExprResult right = expression(ast->right); + _block->MOVE(r, right); + _block->JUMP(endif); + + if (left.type() != right.type()) + discard(); + + _expr.code = r; + + _block = endif; + } break; + + case QSOperator::Lt: + case QSOperator::Gt: + case QSOperator::Le: + case QSOperator::Ge: { + ExprResult left = expression(ast->left); + ExprResult right = expression(ast->right); + if (left.type() == IR::StringType && right.type() == IR::StringType) { + binop(ast, left, right); + } else if (left.isValid() && right.isValid()) { + implicitCvt(left, IR::RealType); + implicitCvt(right, IR::RealType); + binop(ast, left, right); + } + } break; + + case QSOperator::NotEqual: + case QSOperator::Equal: { + ExprResult left = expression(ast->left); + ExprResult right = expression(ast->right); + if ((left.type() == IR::NullType || left.type() == IR::UndefinedType) && + (right.type() == IR::NullType || right.type() == IR::UndefinedType)) { + const bool isEq = ast->op == QSOperator::Equal; + if (_expr.hint == ExprResult::cx) { + _expr.format = ExprResult::cx; + _block->JUMP(isEq ? _expr.iftrue : _expr.iffalse); + } else { + _expr.code = _block->CONST(IR::BoolType, isEq ? 1 : 0); + } + } else if ((left.type() == IR::StringType && right.type() >= IR::FirstNumberType) || + (left.type() >= IR::FirstNumberType && right.type() == IR::StringType)) { + implicitCvt(left, IR::RealType); + implicitCvt(right, IR::RealType); + binop(ast, left, right); + } else if (left.type() == IR::BoolType || right.type() == IR::BoolType) { + implicitCvt(left, IR::BoolType); + implicitCvt(right, IR::BoolType); + } else if (left.isValid() && right.isValid()) { + binop(ast, left, right); + } + } break; + + case QSOperator::StrictEqual: + case QSOperator::StrictNotEqual: { + ExprResult left = expression(ast->left); + ExprResult right = expression(ast->right); + if (left.type() == right.type()) { + binop(ast, left, right); + } else if (left.type() >= IR::BoolType && right.type() >= IR::BoolType) { + // left and right have numeric type (int or real) + binop(ast, left, right); + } else if (left.isValid() && right.isValid()) { + const bool isEq = ast->op == QSOperator::StrictEqual; + if (_expr.hint == ExprResult::cx) { + _expr.format = ExprResult::cx; + _block->JUMP(isEq ? _expr.iftrue : _expr.iffalse); + } else { + _expr.code = _block->CONST(IR::BoolType, isEq ? 1 : 0); + } + } + } break; + + case QSOperator::BitAnd: + case QSOperator::BitOr: + case QSOperator::BitXor: + case QSOperator::LShift: + case QSOperator::RShift: + case QSOperator::URShift: { + ExprResult left = expression(ast->left); + if (left.is(IR::InvalidType)) + return false; + + ExprResult right = expression(ast->right); + if (right.is(IR::InvalidType)) + return false; + + implicitCvt(left, IR::IntType); + implicitCvt(right, IR::IntType); + + IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right); + _expr.code = _block->TEMP(code->type); + _block->MOVE(_expr.code, code); + + } break; + + case QSOperator::Add: { + ExprResult left = expression(ast->left); + if (left.is(IR::InvalidType)) + return false; + + ExprResult right = expression(ast->right); + if (right.is(IR::InvalidType)) + return false; + + if (left.isPrimitive() && right.isPrimitive()) { + if (left.type() == IR::StringType || right.type() == IR::StringType) { + implicitCvt(left, IR::StringType); + implicitCvt(right, IR::StringType); + } + binop(ast, left, right); + } + } break; + + case QSOperator::Div: + case QSOperator::Mod: + case QSOperator::Mul: + case QSOperator::Sub: { + ExprResult left = expression(ast->left); + if (left.is(IR::InvalidType)) + return false; + + ExprResult right = expression(ast->right); + if (right.is(IR::InvalidType)) + return false; + + IR::Type t = maxType(left.type(), right.type()); + if (t >= IR::FirstNumberType) { + implicitCvt(left, IR::RealType); + implicitCvt(right, IR::RealType); + + IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right); + _expr.code = _block->TEMP(code->type); + _block->MOVE(_expr.code, code); + } + } break; + + case QSOperator::In: + case QSOperator::InstanceOf: + case QSOperator::Assign: + case QSOperator::InplaceAnd: + case QSOperator::InplaceSub: + case QSOperator::InplaceDiv: + case QSOperator::InplaceAdd: + case QSOperator::InplaceLeftShift: + case QSOperator::InplaceMod: + case QSOperator::InplaceMul: + case QSOperator::InplaceOr: + case QSOperator::InplaceRightShift: + case QSOperator::InplaceURightShift: + case QSOperator::InplaceXor: + // yup, we don't do those. + break; + } // switch + + return false; +} + +bool QV4IRBuilder::visit(AST::ConditionalExpression *ast) +{ + IR::BasicBlock *iftrue = _function->newBasicBlock(); + IR::BasicBlock *iffalse = _function->newBasicBlock(); + IR::BasicBlock *endif = _function->newBasicBlock(); + + condition(ast->expression, iftrue, iffalse); + + IR::Temp *r = _block->TEMP(IR::InvalidType); + + qSwap(_block, iftrue); + ExprResult ok = expression(ast->ok); + _block->MOVE(r, ok); + _block->JUMP(endif); + qSwap(_block, iftrue); + + qSwap(_block, iffalse); + ExprResult ko = expression(ast->ko); + _block->MOVE(r, ko); + _block->JUMP(endif); + qSwap(_block, iffalse); + + r->type = maxType(ok.type(), ko.type()); + _expr.code = r; + + _block = endif; + + return false; +} + +bool QV4IRBuilder::visit(AST::Expression *ast) +{ + _block->EXP(expression(ast->left)); + _expr = expression(ast->right); + + return false; +} + + +// statements +bool QV4IRBuilder::visit(AST::Block *ast) +{ + if (ast->statements && ! ast->statements->next) { + // we have one and only one statement + accept(ast->statements->statement); + } + + return false; +} + +bool QV4IRBuilder::visit(AST::StatementList *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::VariableStatement *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::VariableDeclarationList *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::VariableDeclaration *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::EmptyStatement *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::ExpressionStatement *ast) +{ + if (ast->expression) { + // return the value of this expression + return true; + } + + return false; +} + +bool QV4IRBuilder::visit(AST::IfStatement *ast) +{ + if (! ast->ko) { + // This is an if statement without an else branch. + discard(); + } else { + IR::BasicBlock *iftrue = _function->newBasicBlock(); + IR::BasicBlock *iffalse = _function->newBasicBlock(); + IR::BasicBlock *endif = _function->newBasicBlock(); + + condition(ast->expression, iftrue, iffalse); + + IR::Temp *r = _block->TEMP(IR::InvalidType); + + qSwap(_block, iftrue); + ExprResult ok = statement(ast->ok); + _block->MOVE(r, ok); + _block->JUMP(endif); + qSwap(_block, iftrue); + + qSwap(_block, iffalse); + ExprResult ko = statement(ast->ko); + _block->MOVE(r, ko); + _block->JUMP(endif); + qSwap(_block, iffalse); + + r->type = maxType(ok.type(), ko.type()); + _expr.code = r; + + _block = endif; + } + + return false; +} + +bool QV4IRBuilder::visit(AST::DoWhileStatement *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::WhileStatement *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::ForStatement *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::LocalForStatement *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::ForEachStatement *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::LocalForEachStatement *) +{ + discard(); + return false; +} + +bool QV4IRBuilder::visit(AST::ContinueStatement *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::BreakStatement *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::ReturnStatement *ast) +{ + if (ast->expression) { + // return the value of the expression + return true; + } + + return false; +} + +bool QV4IRBuilder::visit(AST::WithStatement *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::SwitchStatement *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::CaseBlock *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::CaseClauses *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::CaseClause *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::DefaultClause *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::LabelledStatement *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::ThrowStatement *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::TryStatement *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::Catch *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::Finally *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::FunctionDeclaration *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::FunctionExpression *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::FormalParameterList *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::FunctionBody *) +{ + return false; +} + +bool QV4IRBuilder::visit(AST::DebuggerStatement *) +{ + return false; +} + +QT_END_NAMESPACE diff --cc src/qml/qml/v4/qv4program_p.h index b6b03e4,0000000..d23cc61 mode 100644,000000..100644 --- a/src/qml/qml/v4/qv4program_p.h +++ b/src/qml/qml/v4/qv4program_p.h @@@ -1,122 -1,0 +1,123 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QV4PROGRAM_P_H +#define QV4PROGRAM_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qv4instruction_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +struct QV4Program { + quint32 bindings; + quint32 dataLength; + quint32 signalTableOffset; + quint32 exceptionDataOffset; + quint16 subscriptions; + quint16 identifiers; + quint16 instructionCount; + + struct BindingReference { + quint32 binding; + quint32 blockMask; + }; + + struct BindingReferenceList { + quint32 count; + BindingReference bindings[]; + }; + + inline const char *data() const; + inline const char *instructions() const; + inline BindingReferenceList *signalTable(int signalIndex) const; +}; + +enum QQmlRegisterType { + UndefinedType, + QObjectStarType, + QRealType, + IntType, + BoolType, + + PODValueType, + + FirstCleanupType, + QStringType = FirstCleanupType, + QUrlType, + QVariantType, ++ QColorType +}; + +const char *QV4Program::data() const +{ + return ((const char *)this) + sizeof(QV4Program); +} + +const char *QV4Program::instructions() const +{ + return (const char *)(data() + dataLength); +} + +QV4Program::BindingReferenceList *QV4Program::signalTable(int signalIndex) const +{ + quint32 *signalTable = (quint32 *)(data() + signalTableOffset); + return (BindingReferenceList *)(signalTable + signalTable[signalIndex]); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QV4PROGRAM_P_H + diff --cc src/qml/qml/v8/qjsconverter_p.h index 29fef3c,0000000..d85f9aa mode 100644,000000..100644 --- a/src/qml/qml/v8/qjsconverter_p.h +++ b/src/qml/qml/v8/qjsconverter_p.h @@@ -1,93 -1,0 +1,111 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** - ** This file is part of the QtScript module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. +** - ** $QT_BEGIN_LICENSE:LGPL-ONLY$ ++** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage - ** This file may be used under the terms of the GNU Lesser - ** General Public License version 2.1 as published by the Free Software - ** Foundation and appearing in the file LICENSE.LGPL included in the - ** packaging of this file. Please review the following information to - ** ensure the GNU Lesser General Public License version 2.1 requirements - ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. - ** - ** If you have questions regarding the use of this file, please contact - ** us via http://www.qt-project.org/. ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** ++** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QJSCONVERTER_P_H +#define QJSCONVERTER_P_H + +#include "qjsvalue_p.h" +#include +#include +#include +#include +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +/* + \internal + \class QJSConverter + QJSValue and QJSEngine helper class. This class's responsibility is to convert values + between JS values and Qt/C++ values. + + This is a nice way to inline these functions in both QJSValue and QJSEngine. +*/ +class QJSConverter { +public: + static inline quint32 toArrayIndex(const QString& string); + + static inline QString toString(v8::Handle jsString); + static inline v8::Local toString(const QString& string); + static inline QString toString(double value); + + enum { + PropertyAttributeMask = v8::ReadOnly | v8::DontDelete | v8::DontEnum, + }; + // return a mask of v8::PropertyAttribute that may also contains QScriptValue::PropertyGetter or QScriptValue::PropertySetter + static inline uint toPropertyAttributes(const QFlags& flags); + + // Converts a JS RegExp to a QRegExp. + // The conversion is not 100% exact since ECMA regexp and QRegExp + // have different semantics/flags, but we try to do our best. + static inline QRegExp toRegExp(v8::Handle jsRegExp); + + // Converts a QRegExp to a JS RegExp. + // The conversion is not 100% exact since ECMA regexp and QRegExp + // have different semantics/flags, but we try to do our best. + static inline v8::Local toRegExp(const QRegExp &re); + + // Converts a QStringList to JS. + // The result is a new Array object with length equal to the length + // of the QStringList, and the elements being the QStringList's + // elements converted to JS Strings. + static inline v8::Local toStringList(const QStringList &lst); + + // Converts a JS Array object to a QStringList. + // The result is a QStringList with length equal to the length + // of the JS Array, and elements being the JS Array's elements + // converted to QStrings. + static inline QStringList toStringList(v8::Handle jsArray); + + // Converts a JS Date to a QDateTime. + static inline QDateTime toDateTime(v8::Handle jsDate); + + // Converts a QDateTime to a JS Date. + static inline v8::Local toDateTime(const QDateTime &dt); +}; + +QT_END_NAMESPACE + +#endif diff --cc src/qml/qml/v8/qjsengine.h index 1521c75,0000000..fa2584b mode 100644,000000..100644 --- a/src/qml/qml/v8/qjsengine.h +++ b/src/qml/qml/v8/qjsengine.h @@@ -1,141 -1,0 +1,159 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** - ** This file is part of the QtScript module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. +** - ** $QT_BEGIN_LICENSE:LGPL-ONLY$ ++** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage - ** This file may be used under the terms of the GNU Lesser - ** General Public License version 2.1 as published by the Free Software - ** Foundation and appearing in the file LICENSE.LGPL included in the - ** packaging of this file. Please review the following information to - ** ensure the GNU Lesser General Public License version 2.1 requirements - ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. - ** - ** If you have questions regarding the use of this file, please contact - ** us via http://www.qt-project.org/. ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** ++** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QJSENGINE_H +#define QJSENGINE_H + +#include + +#include +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + + +class QV8Engine; + +template +inline T qjsvalue_cast(const QJSValue &); + +class QJSEnginePrivate; +class Q_QML_EXPORT QJSEngine + : public QObject +{ + Q_OBJECT +public: +#ifdef QT_DEPRECATED + enum ContextOwnership { + AdoptCurrentContext, + CreateNewContext + }; + QT_DEPRECATED explicit QJSEngine(ContextOwnership ownership); +#endif + + QJSEngine(); + explicit QJSEngine(QObject *parent); + virtual ~QJSEngine(); + + QJSValue globalObject() const; + + QJSValue evaluate(const QString &program, const QString &fileName = QString(), int lineNumber = 1); + + QJSValue newObject(); + QJSValue newArray(uint length = 0); + + QJSValue newQObject(QObject *object); + + template + inline QJSValue toScriptValue(const T &value) + { + return create(qMetaTypeId(), &value); + } + template + inline T fromScriptValue(const QJSValue &value) + { + return qjsvalue_cast(value); + } + + void collectGarbage(); + + QV8Engine *handle() const { return d; } + +#ifdef QT_DEPRECATED + QT_DEPRECATED bool hasUncaughtException() const; + QT_DEPRECATED QJSValue uncaughtException() const; + QT_DEPRECATED void clearExceptions(); +#endif + +Q_SIGNALS: + void signalHandlerException(const QJSValue &exception); + +private: + QJSValue create(int type, const void *ptr); + + static bool convertV2(const QJSValue &value, int type, void *ptr); + + friend inline bool qjsvalue_cast_helper(const QJSValue &, int, void *); + +protected: + QJSEngine(QJSEnginePrivate &dd, QObject *parent = 0); + +private: + QV8Engine *d; + Q_DISABLE_COPY(QJSEngine) + Q_DECLARE_PRIVATE(QJSEngine) + friend class QV8Engine; +}; + +inline bool qjsvalue_cast_helper(const QJSValue &value, int type, void *ptr) +{ + return QJSEngine::convertV2(value, type, ptr); +} + +template +T qjsvalue_cast(const QJSValue &value) +{ + T t; + const int id = qMetaTypeId(); + + if (qjsvalue_cast_helper(value, id, &t)) + return t; + else if (value.isVariant()) + return qvariant_cast(value.toVariant()); + + return T(); +} + +template <> +inline QVariant qjsvalue_cast(const QJSValue &value) +{ + return value.toVariant(); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QJSENGINE_H diff --cc src/qml/qml/v8/qjsengine_p.h index ecd5f7c,0000000..9866aa8 mode 100644,000000..100644 --- a/src/qml/qml/v8/qjsengine_p.h +++ b/src/qml/qml/v8/qjsengine_p.h @@@ -1,57 -1,0 +1,75 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** - ** This file is part of the QtScript module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. +** - ** $QT_BEGIN_LICENSE:LGPL-ONLY$ ++** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage - ** This file may be used under the terms of the GNU Lesser - ** General Public License version 2.1 as published by the Free Software - ** Foundation and appearing in the file LICENSE.LGPL included in the - ** packaging of this file. Please review the following information to - ** ensure the GNU Lesser General Public License version 2.1 requirements - ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. - ** - ** If you have questions regarding the use of this file, please contact - ** us via http://www.qt-project.org/. ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** ++** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QJSENGINE_P_H +#define QJSENGINE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include "qjsengine.h" + + +QT_BEGIN_NAMESPACE + + +class QJSEnginePrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QJSEngine) + +public: + static QJSEnginePrivate* get(QJSEngine*e) { return e->d_func(); } + + QJSEnginePrivate() {} +}; + +QT_END_NAMESPACE + +#endif // QJSENGINE_P_H diff --cc src/qml/qml/v8/qjsvalue.h index 30ea2e7,0000000..209090e mode 100644,000000..100644 --- a/src/qml/qml/v8/qjsvalue.h +++ b/src/qml/qml/v8/qjsvalue.h @@@ -1,143 -1,0 +1,160 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** - ** This file is part of the QtScript module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. +** - ** $QT_BEGIN_LICENSE:LGPL-ONLY$ ++** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage - ** This file may be used under the terms of the GNU Lesser - ** General Public License version 2.1 as published by the Free Software - ** Foundation and appearing in the file LICENSE.LGPL included in the - ** packaging of this file. Please review the following information to - ** ensure the GNU Lesser General Public License version 2.1 requirements - ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** +** - ** If you have questions regarding the use of this file, please contact - ** us via http://www.qt-project.org/. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QJSVALUE_H +#define QJSVALUE_H + +#include - +#include +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + + +class QJSValue; +class QJSEngine; +class QVariant; +class QObject; +struct QMetaObject; +class QDateTime; + +typedef QList QJSValueList; + +class QJSValuePrivate; +struct QScriptValuePrivatePointerDeleter; +template class QScriptPassPointer; + +class Q_QML_EXPORT QJSValue +{ +public: + enum SpecialValue { + NullValue, + UndefinedValue + }; + +public: + QJSValue(SpecialValue value = UndefinedValue); + ~QJSValue(); + QJSValue(const QJSValue &other); + + QJSValue(bool value); + QJSValue(int value); + QJSValue(uint value); + QJSValue(double value); + QJSValue(const QString &value); + QJSValue(const QLatin1String &value); +#ifndef QT_NO_CAST_FROM_ASCII - QT_ASCII_CAST_WARN_CONSTRUCTOR QJSValue(const char *str); ++ QT_ASCII_CAST_WARN QJSValue(const char *str); +#endif + + QJSValue &operator=(const QJSValue &other); + + bool isBool() const; + bool isNumber() const; + bool isNull() const; + bool isString() const; + bool isUndefined() const; + bool isVariant() const; + bool isQObject() const; + bool isObject() const; + bool isDate() const; + bool isRegExp() const; + bool isArray() const; + bool isError() const; + + QString toString() const; + double toNumber() const; + qint32 toInt() const; + quint32 toUInt() const; + bool toBool() const; + QVariant toVariant() const; + QObject *toQObject() const; + QDateTime toDateTime() const; + + bool equals(const QJSValue &other) const; + bool strictlyEquals(const QJSValue &other) const; + + QJSValue prototype() const; + void setPrototype(const QJSValue &prototype); + + QJSValue property(const QString &name) const; + void setProperty(const QString &name, const QJSValue &value); + + bool hasProperty(const QString &name) const; + bool hasOwnProperty(const QString &name) const; + + QJSValue property(quint32 arrayIndex) const; + void setProperty(quint32 arrayIndex, const QJSValue &value); + + bool deleteProperty(const QString &name); + + bool isCallable() const; + QJSValue call(const QJSValueList &args = QJSValueList()); + QJSValue callWithInstance(const QJSValue &instance, const QJSValueList &args = QJSValueList()); + QJSValue callAsConstructor(const QJSValueList &args = QJSValueList()); + +#ifdef QT_DEPRECATED + QT_DEPRECATED QJSEngine *engine() const; +#endif + +private: + // force compile error, prevent QJSValue(bool) to be called + + QJSValue(void *) Q_DECL_EQ_DELETE; + + QJSValue(QJSValuePrivate*); + QJSValue(QScriptPassPointer); + +private: + QExplicitlySharedDataPointer d_ptr; + + Q_DECLARE_PRIVATE(QJSValue) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --cc src/qml/qml/v8/qjsvalue_impl_p.h index cd33859,0000000..fbddcfa mode 100644,000000..100644 --- a/src/qml/qml/v8/qjsvalue_impl_p.h +++ b/src/qml/qml/v8/qjsvalue_impl_p.h @@@ -1,977 -1,0 +1,995 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** - ** This file is part of the QtScript module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. +** - ** $QT_BEGIN_LICENSE:LGPL-ONLY$ ++** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage - ** This file may be used under the terms of the GNU Lesser - ** General Public License version 2.1 as published by the Free Software - ** Foundation and appearing in the file LICENSE.LGPL included in the - ** packaging of this file. Please review the following information to - ** ensure the GNU Lesser General Public License version 2.1 requirements - ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. - ** - ** If you have questions regarding the use of this file, please contact - ** us via http://www.qt-project.org/. ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** ++** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#ifndef QJSVALUE_IMPL_P_H +#define QJSVALUE_IMPL_P_H + +#include "qjsconverter_p.h" +#include "qjsvalue_p.h" +#include "qv8engine_p.h" +#include "qscriptisolate_p.h" + +QT_BEGIN_NAMESPACE + +QJSValuePrivate* QJSValuePrivate::get(const QJSValue& q) { Q_ASSERT(q.d_ptr.data()); return q.d_ptr.data(); } + +QJSValue QJSValuePrivate::get(const QJSValuePrivate* d) +{ + Q_ASSERT(d); + return QJSValue(const_cast(d)); +} + +QJSValue QJSValuePrivate::get(QScriptPassPointer d) +{ + Q_ASSERT(d); + return QJSValue(d); +} + +QJSValue QJSValuePrivate::get(QJSValuePrivate* d) +{ + Q_ASSERT(d); + return QJSValue(d); +} + +QJSValuePrivate::QJSValuePrivate(bool value) + : m_engine(0), m_state(CBool), u(value) +{ +} + +QJSValuePrivate::QJSValuePrivate(int value) + : m_engine(0), m_state(CNumber), u(value) +{ +} + +QJSValuePrivate::QJSValuePrivate(uint value) + : m_engine(0), m_state(CNumber), u(value) +{ +} + +QJSValuePrivate::QJSValuePrivate(double value) + : m_engine(0), m_state(CNumber), u(value) +{ +} + +QJSValuePrivate::QJSValuePrivate(const QString& value) + : m_engine(0), m_state(CString), u(new QString(value)) +{ +} + +QJSValuePrivate::QJSValuePrivate(QJSValue::SpecialValue value) + : m_engine(0), m_state(value == QJSValue::NullValue ? CNull : CUndefined) +{ +} + +QJSValuePrivate::QJSValuePrivate(QV8Engine* engine, bool value) + : m_engine(engine), m_state(JSValue) +{ + Q_ASSERT(engine); + v8::HandleScope handleScope; + m_value = v8::Persistent::New(m_engine->makeJSValue(value)); + m_engine->registerValue(this); +} + +QJSValuePrivate::QJSValuePrivate(QV8Engine* engine, int value) + : m_engine(engine), m_state(JSValue) +{ + Q_ASSERT(engine); + v8::HandleScope handleScope; + m_value = v8::Persistent::New(m_engine->makeJSValue(value)); + m_engine->registerValue(this); +} + +QJSValuePrivate::QJSValuePrivate(QV8Engine* engine, uint value) + : m_engine(engine), m_state(JSValue) +{ + Q_ASSERT(engine); + v8::HandleScope handleScope; + m_value = v8::Persistent::New(m_engine->makeJSValue(value)); + m_engine->registerValue(this); +} + +QJSValuePrivate::QJSValuePrivate(QV8Engine* engine, double value) + : m_engine(engine), m_state(JSValue) +{ + Q_ASSERT(engine); + v8::HandleScope handleScope; + m_value = v8::Persistent::New(m_engine->makeJSValue(value)); + m_engine->registerValue(this); +} + +QJSValuePrivate::QJSValuePrivate(QV8Engine* engine, const QString& value) + : m_engine(engine), m_state(JSValue) +{ + Q_ASSERT(engine); + v8::HandleScope handleScope; + m_value = v8::Persistent::New(m_engine->makeJSValue(value)); + m_engine->registerValue(this); +} + +QJSValuePrivate::QJSValuePrivate(QV8Engine* engine, QJSValue::SpecialValue value) + : m_engine(engine), m_state(JSValue) +{ + Q_ASSERT(engine); + v8::HandleScope handleScope; + m_value = v8::Persistent::New(m_engine->makeJSValue(value)); + m_engine->registerValue(this); +} + +QJSValuePrivate::QJSValuePrivate(QV8Engine *engine, v8::Handle value) + : m_engine(engine), m_state(JSValue), m_value(v8::Persistent::New(value)) +{ + Q_ASSERT(engine); + // It shouldn't happen, v8 shows errors by returning an empty handler. This is important debug + // information and it can't be simply ignored. + Q_ASSERT(!value.IsEmpty()); + m_engine->registerValue(this); +} + +QJSValuePrivate::~QJSValuePrivate() +{ + if (isJSBased()) { + m_engine->unregisterValue(this); + QScriptIsolate api(m_engine); + m_value.Dispose(); + } else if (isStringBased()) { + delete u.m_string; + } +} + +bool QJSValuePrivate::toBool() const +{ + switch (m_state) { + case JSValue: + { + v8::HandleScope scope; + return m_value->ToBoolean()->Value(); + } + case CNumber: + return !(qIsNaN(u.m_number) || !u.m_number); + case CBool: + return u.m_bool; + case CNull: + case CUndefined: + return false; + case CString: + return u.m_string->length(); + } + + Q_ASSERT_X(false, "toBool()", "Not all states are included in the previous switch statement."); + return false; // Avoid compiler warning. +} + +double QJSValuePrivate::toNumber() const +{ + switch (m_state) { + case JSValue: + { + v8::HandleScope scope; + return m_value->ToNumber()->Value(); + } + case CNumber: + return u.m_number; + case CBool: + return u.m_bool ? 1 : 0; + case CNull: + case CUndefined: + return qQNaN(); + case CString: + bool ok; + double result = u.m_string->toDouble(&ok); + if (ok) + return result; + result = u.m_string->toInt(&ok, 0); // Try other bases. + if (ok) + return result; + if (*u.m_string == QLatin1String("Infinity")) + return qInf(); + if (*u.m_string == QLatin1String("-Infinity")) + return -qInf(); + return u.m_string->length() ? qQNaN() : 0; + } + + Q_ASSERT_X(false, "toNumber()", "Not all states are included in the previous switch statement."); + return 0; // Avoid compiler warning. +} + +QString QJSValuePrivate::toString() const +{ + switch (m_state) { + case CBool: + return u.m_bool ? QString::fromLatin1("true") : QString::fromLatin1("false"); + case CString: + return *u.m_string; + case CNumber: + return QJSConverter::toString(u.m_number); + case CNull: + return QString::fromLatin1("null"); + case CUndefined: + return QString::fromLatin1("undefined"); + case JSValue: + Q_ASSERT(!m_value.IsEmpty()); + v8::HandleScope handleScope; + v8::TryCatch tryCatch; + v8::Local result = m_value->ToString(); + if (result.IsEmpty()) { + result = tryCatch.Exception()->ToString(); + m_engine->setException(tryCatch.Exception(), tryCatch.Message()); + } + return QJSConverter::toString(result); + } + + Q_ASSERT_X(false, "toString()", "Not all states are included in the previous switch statement."); + return QString(); // Avoid compiler warning. +} + +QVariant QJSValuePrivate::toVariant() const +{ + switch (m_state) { + case CBool: + return QVariant(u.m_bool); + case CString: + return QVariant(*u.m_string); + case CNumber: + return QVariant(u.m_number); + case CNull: + return QVariant(); + case CUndefined: + return QVariant(); + case JSValue: + break; + } + + Q_ASSERT(m_state == JSValue); + Q_ASSERT(!m_value.IsEmpty()); + Q_ASSERT(m_engine); + + v8::HandleScope handleScope; + return m_engine->variantFromJS(m_value); +} + +inline QDateTime QJSValuePrivate::toDataTime() const +{ + if (!isDate()) + return QDateTime(); + + v8::HandleScope handleScope; + return QJSConverter::toDateTime(v8::Handle::Cast(m_value)); + +} + +QObject* QJSValuePrivate::toQObject() const +{ + if (!isJSBased()) + return 0; + + v8::HandleScope handleScope; + return engine()->qtObjectFromJS(m_value); +} + +double QJSValuePrivate::toInteger() const +{ + double result = toNumber(); + if (qIsNaN(result)) + return 0; + if (qIsInf(result)) + return result; + + // Must use floor explicitly rather than qFloor here. On some + // platforms qFloor will cast the value to a single precision float and use + // floorf() which results in test failures. + return (result > 0) ? floor(result) : -1 * floor(-result); +} + +qint32 QJSValuePrivate::toInt32() const +{ + double result = toInteger(); + // Orginaly it should look like that (result == 0 || qIsInf(result) || qIsNaN(result)), but + // some of these operation are invoked in toInteger subcall. + if (qIsInf(result)) + return 0; + return result; +} + +quint32 QJSValuePrivate::toUInt32() const +{ + double result = toInteger(); + // Orginaly it should look like that (result == 0 || qIsInf(result) || qIsNaN(result)), but + // some of these operation are invoked in toInteger subcall. + if (qIsInf(result)) + return 0; + + // The explicit casts are required to avoid undefined behaviour. For example, casting + // a negative double directly to an unsigned int on ARM NEON FPU results in the value + // being set to zero. Casting to a signed int first ensures well defined behaviour. + return (quint32) (qint32) result; +} + +quint16 QJSValuePrivate::toUInt16() const +{ + return toInt32(); +} + +inline bool QJSValuePrivate::isArray() const +{ + return isJSBased() && m_value->IsArray(); +} + +inline bool QJSValuePrivate::isBool() const +{ + return m_state == CBool || (isJSBased() && m_value->IsBoolean()); +} + +inline bool QJSValuePrivate::isCallable() const +{ + if (isFunction()) + return true; + if (isObject()) { + // Our C++ wrappers register function handlers but not always act as callables. + return v8::Object::Cast(*m_value)->IsCallable(); + } + return false; +} + +inline bool QJSValuePrivate::isError() const +{ + if (!isJSBased()) + return false; + v8::HandleScope handleScope; + return m_value->IsError(); +} + +inline bool QJSValuePrivate::isFunction() const +{ + return isJSBased() && m_value->IsFunction(); +} + +inline bool QJSValuePrivate::isNull() const +{ + return m_state == CNull || (isJSBased() && m_value->IsNull()); +} + +inline bool QJSValuePrivate::isNumber() const +{ + return m_state == CNumber || (isJSBased() && m_value->IsNumber()); +} + +inline bool QJSValuePrivate::isObject() const +{ + return isJSBased() && m_value->IsObject(); +} + +inline bool QJSValuePrivate::isString() const +{ + return m_state == CString || (isJSBased() && m_value->IsString()); +} + +inline bool QJSValuePrivate::isUndefined() const +{ + return m_state == CUndefined || (isJSBased() && m_value->IsUndefined()); +} + +inline bool QJSValuePrivate::isVariant() const +{ + return isJSBased() && m_engine->isVariant(m_value); +} + +bool QJSValuePrivate::isDate() const +{ + return (isJSBased() && m_value->IsDate()); +} + +bool QJSValuePrivate::isRegExp() const +{ + return (isJSBased() && m_value->IsRegExp()); +} + +bool QJSValuePrivate::isQObject() const +{ + return isJSBased() && engine()->isQObject(m_value); +} + +inline bool QJSValuePrivate::equals(QJSValuePrivate* other) +{ + if (!isJSBased() && !other->isJSBased()) { + switch (m_state) { + case CNull: + case CUndefined: + return other->isUndefined() || other->isNull(); + case CNumber: + switch (other->m_state) { + case CBool: + case CString: + return u.m_number == other->toNumber(); + case CNumber: + return u.m_number == other->u.m_number; + default: + return false; + } + case CBool: + switch (other->m_state) { + case CBool: + return u.m_bool == other->u.m_bool; + case CNumber: + return toNumber() == other->u.m_number; + case CString: + return toNumber() == other->toNumber(); + default: + return false; + } + case CString: + switch (other->m_state) { + case CBool: + return toNumber() == other->toNumber(); + case CNumber: + return toNumber() == other->u.m_number; + case CString: + return *u.m_string == *other->u.m_string; + default: + return false; + } + default: + Q_ASSERT_X(false, "QJSValue::equals", "Not all states are included in the previous switch statement."); + } + } + + v8::HandleScope handleScope; + if (isJSBased() && !other->isJSBased()) { + if (!other->assignEngine(engine())) { + qWarning("QJSValue::equals: cannot compare to a value created in a different engine"); + return false; + } + } else if (!isJSBased() && other->isJSBased()) { + if (!assignEngine(other->engine())) { + qWarning("QJSValue::equals: cannot compare to a value created in a different engine"); + return false; + } + } + + Q_ASSERT(this->engine() && other->engine()); + if (this->engine() != other->engine()) { + qWarning("QJSValue::equals: cannot compare to a value created in a different engine"); + return false; + } + return m_value->Equals(other->m_value); +} + +inline bool QJSValuePrivate::strictlyEquals(QJSValuePrivate* other) +{ + if (isJSBased()) { + // We can't compare these two values without binding to the same engine. + if (!other->isJSBased()) { + if (other->assignEngine(engine())) + return m_value->StrictEquals(other->m_value); + return false; + } + if (other->engine() != engine()) { + qWarning("QJSValue::strictlyEquals: cannot compare to a value created in a different engine"); + return false; + } + return m_value->StrictEquals(other->m_value); + } + if (isStringBased()) { + if (other->isStringBased()) + return *u.m_string == *(other->u.m_string); + if (other->isJSBased()) { + assignEngine(other->engine()); + return m_value->StrictEquals(other->m_value); + } + } + if (isNumberBased()) { + if (other->isJSBased()) { + assignEngine(other->engine()); + return m_value->StrictEquals(other->m_value); + } + if (m_state != other->m_state) + return false; + if (m_state == CNumber) + return u.m_number == other->u.m_number; + Q_ASSERT(m_state == CBool); + return u.m_bool == other->u.m_bool; + } + + return (isUndefined() && other->isUndefined()) + || (isNull() && other->isNull()); +} + +inline bool QJSValuePrivate::lessThan(QJSValuePrivate *other) const +{ + if (engine() != other->engine() && engine() && other->engine()) { + qWarning("QJSValue::lessThan: cannot compare to a value created in a different engine"); + return false; + } + + if (isString() && other->isString()) + return toString() < other->toString(); + + if (isObject() || other->isObject()) { + v8::HandleScope handleScope; + QV8Engine *eng = m_engine ? engine() : other->engine(); + // FIXME: lessThan can throw an exception which will be dropped by this code: + Q_ASSERT(eng); + eng->saveException(); + QScriptSharedDataPointer cmp(eng->evaluate(QString::fromLatin1("(function(a,b){return aisFunction()); + v8::Handle args[2]; + cmp->prepareArgumentsForCall(args, QJSValueList() << QJSValuePrivate::get(this) << QJSValuePrivate::get(other)); + QScriptSharedDataPointer resultValue(cmp->call(0, 2, args)); + bool result = resultValue->toBool(); + eng->restoreException(); + return result; + } + + double nthis = toNumber(); + double nother = other->toNumber(); + if (qIsNaN(nthis) || qIsNaN(nother)) { + // Should return undefined in ECMA standard. + return false; + } + return nthis < nother; +} + +inline QScriptPassPointer QJSValuePrivate::prototype() const +{ + if (isObject()) { + v8::HandleScope handleScope; + return new QJSValuePrivate(engine(), v8::Handle::Cast(m_value)->GetPrototype()); + } + return new QJSValuePrivate(); +} + +inline void QJSValuePrivate::setPrototype(QJSValuePrivate* prototype) +{ + if (isObject() && (prototype->isObject() || prototype->isNull())) { + if (engine() != prototype->engine()) { + if (prototype->engine()) { + qWarning("QJSValue::setPrototype() failed: cannot set a prototype created in a different engine"); + return; + } + prototype->assignEngine(engine()); + } + v8::HandleScope handleScope; + if (!v8::Handle::Cast(m_value)->SetPrototype(*prototype)) + qWarning("QJSValue::setPrototype() failed: cyclic prototype value"); + } +} + +inline void QJSValuePrivate::setProperty(const QString& name, QJSValuePrivate* value, uint attribs) +{ + if (!isObject()) + return; + v8::HandleScope handleScope; + setProperty(QJSConverter::toString(name), value, attribs); +} + +inline void QJSValuePrivate::setProperty(v8::Handle name, QJSValuePrivate* value, uint attribs) +{ + if (!isObject()) + return; + + if (!value->isJSBased()) + value->assignEngine(engine()); + + if (engine() != value->engine()) { + qWarning("QJSValue::setProperty(%s) failed: " + "cannot set value created in a different engine", + qPrintable(QJSConverter::toString(name))); + return; + } + + v8::TryCatch tryCatch; +// if (attribs & (QJSValue::PropertyGetter | QJSValue::PropertySetter)) { +// engine()->originalGlobalObject()->defineGetterOrSetter(*this, name, value->m_value, attribs); +// } else { + v8::Object::Cast(*m_value)->Set(name, value->m_value, v8::PropertyAttribute(attribs & QJSConverter::PropertyAttributeMask)); +// } + if (tryCatch.HasCaught()) + engine()->setException(tryCatch.Exception(), tryCatch.Message()); +} + +inline void QJSValuePrivate::setProperty(quint32 index, QJSValuePrivate* value, uint attribs) +{ + // FIXME this method should by integrated with other overloads to use the same code patch. + // for now it is not possible as v8 doesn't allow to set property attributes using index based api. + + if (!isObject()) + return; + + if (attribs) { + // FIXME we dont need to convert index to a string. + //Object::Set(int,value) do not take attributes. + setProperty(QString::number(index), value, attribs); + return; + } + + if (!value->isJSBased()) + value->assignEngine(engine()); + + if (engine() != value->engine()) { + qWarning("QJSValue::setProperty() failed: cannot set value created in a different engine"); + return; + } + + v8::HandleScope handleScope; + v8::TryCatch tryCatch; + v8::Object::Cast(*m_value)->Set(index, value->m_value); + if (tryCatch.HasCaught()) + engine()->setException(tryCatch.Exception(), tryCatch.Message()); +} + +inline QScriptPassPointer QJSValuePrivate::property(const QString& name) const +{ + if (!isObject()) + return new QJSValuePrivate(); + if (!name.length()) + return new QJSValuePrivate(engine()); + + v8::HandleScope handleScope; + return property(QJSConverter::toString(name)); +} + +inline QScriptPassPointer QJSValuePrivate::property(v8::Handle name) const +{ + Q_ASSERT(!name.IsEmpty()); + if (!isObject()) + return new QJSValuePrivate(); + return property<>(name); +} + +inline QScriptPassPointer QJSValuePrivate::property(quint32 index) const +{ + if (!isObject()) + return new QJSValuePrivate(); + return property<>(index); +} + +template +inline QScriptPassPointer QJSValuePrivate::property(T name) const +{ + Q_ASSERT(isObject()); + v8::HandleScope handleScope; + v8::Handle self(v8::Object::Cast(*m_value)); + + v8::TryCatch tryCatch; + v8::Handle result = self->Get(name); + if (tryCatch.HasCaught()) { + result = tryCatch.Exception(); + engine()->setException(result, tryCatch.Message()); + return new QJSValuePrivate(engine(), result); + } + if (result.IsEmpty()) + return new QJSValuePrivate(engine()); + return new QJSValuePrivate(engine(), result); +} + +inline bool QJSValuePrivate::deleteProperty(const QString& name) +{ + if (!isObject()) + return false; + + v8::HandleScope handleScope; + v8::Handle self(v8::Handle::Cast(m_value)); + return self->Delete(QJSConverter::toString(name)); +} + +inline bool QJSValuePrivate::hasProperty(const QString &name) const +{ + if (!isObject()) + return false; + + v8::HandleScope handleScope; + v8::Handle self(v8::Handle::Cast(m_value)); + return self->Has(QJSConverter::toString(name)); +} + +inline bool QJSValuePrivate::hasOwnProperty(const QString &name) const +{ + if (!isObject()) + return false; + + v8::HandleScope handleScope; + v8::Handle self(v8::Handle::Cast(m_value)); + return self->HasOwnProperty(QJSConverter::toString(name)); +} + +inline QJSValuePrivate::PropertyFlags QJSValuePrivate::propertyFlags(const QString& name) const +{ + if (!isObject()) + return QJSValuePrivate::PropertyFlags(0); + + v8::HandleScope handleScope; + return engine()->getPropertyFlags(v8::Handle::Cast(m_value), QJSConverter::toString(name)); +} + +inline QJSValuePrivate::PropertyFlags QJSValuePrivate::propertyFlags(v8::Handle name) const +{ + if (!isObject()) + return QJSValuePrivate::PropertyFlags(0); + + v8::HandleScope handleScope; + return engine()->getPropertyFlags(v8::Handle::Cast(m_value), name); +} + +inline QScriptPassPointer QJSValuePrivate::call(QJSValuePrivate* thisObject, const QJSValueList& args) +{ + if (!isCallable()) + return new QJSValuePrivate(); + + v8::HandleScope handleScope; + + // Convert all arguments and bind to the engine. + int argc = args.size(); + QVarLengthArray, 8> argv(argc); + if (!prepareArgumentsForCall(argv.data(), args)) { + qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine"); + return new QJSValuePrivate(engine()); + } + + return call(thisObject, argc, argv.data()); +} + +QScriptPassPointer QJSValuePrivate::call(QJSValuePrivate* thisObject, int argc, v8::Handle *argv) +{ + QV8Engine *e = engine(); + + v8::Handle recv; + + if (!thisObject || !thisObject->isObject()) { + recv = v8::Handle(v8::Object::Cast(*e->global())); + } else { + if (!thisObject->assignEngine(e)) { + qWarning("QJSValue::call() failed: cannot call function with thisObject created in a different engine"); + return new QJSValuePrivate(engine()); + } + + recv = v8::Handle(v8::Object::Cast(*thisObject->m_value)); + } + + if (argc < 0) { + v8::Local exeption = v8::Exception::TypeError(v8::String::New("Arguments must be an array")); + e->setException(exeption); + return new QJSValuePrivate(e, exeption); + } + + v8::TryCatch tryCatch; + v8::Handle result = v8::Object::Cast(*m_value)->CallAsFunction(recv, argc, argv); + + if (result.IsEmpty()) { + result = tryCatch.Exception(); + // TODO: figure out why v8 doesn't always produce an exception value. + //Q_ASSERT(!result.IsEmpty()); + if (result.IsEmpty()) + result = v8::Exception::Error(v8::String::New("missing exception value")); + e->setException(result, tryCatch.Message()); + } + + return new QJSValuePrivate(e, result); +} + +inline QScriptPassPointer QJSValuePrivate::callAsConstructor(int argc, v8::Handle *argv) +{ + QV8Engine *e = engine(); + + if (argc < 0) { + v8::Local exeption = v8::Exception::TypeError(v8::String::New("Arguments must be an array")); + e->setException(exeption); + return new QJSValuePrivate(e, exeption); + } + + v8::TryCatch tryCatch; + v8::Handle result = v8::Object::Cast(*m_value)->CallAsConstructor(argc, argv); + + if (result.IsEmpty()) { + result = tryCatch.Exception(); + e->setException(result, tryCatch.Message()); + } + + return new QJSValuePrivate(e, result); +} + +inline QScriptPassPointer QJSValuePrivate::callAsConstructor(const QJSValueList& args) +{ + if (!isCallable()) + return new QJSValuePrivate(); + + v8::HandleScope handleScope; + + // Convert all arguments and bind to the engine. + int argc = args.size(); + QVarLengthArray, 8> argv(argc); + if (!prepareArgumentsForCall(argv.data(), args)) { + qWarning("QJSValue::callAsConstructor() failed: cannot construct function with argument created in a different engine"); + return new QJSValuePrivate(engine()); + } + + return callAsConstructor(argc, argv.data()); +} + +/*! \internal + * Make sure this value is associated with a v8 value belonging to this engine. + * If the value belongs to another engine, returns false. + */ +bool QJSValuePrivate::assignEngine(QV8Engine* engine) +{ + Q_ASSERT(engine); + v8::HandleScope handleScope; + switch (m_state) { + case CBool: + m_value = v8::Persistent::New(engine->makeJSValue(u.m_bool)); + break; + case CString: + m_value = v8::Persistent::New(engine->makeJSValue(*u.m_string)); + delete u.m_string; + break; + case CNumber: + m_value = v8::Persistent::New(engine->makeJSValue(u.m_number)); + break; + case CNull: + m_value = v8::Persistent::New(engine->makeJSValue(QJSValue::NullValue)); + break; + case CUndefined: + m_value = v8::Persistent::New(engine->makeJSValue(QJSValue::UndefinedValue)); + break; + default: + if (this->engine() == engine) + return true; + else if (!isJSBased()) + Q_ASSERT_X(!isJSBased(), "assignEngine()", "Not all states are included in the previous switch statement."); + else + qWarning("JSValue can't be rassigned to an another engine."); + return false; + } + m_engine = engine; + m_state = JSValue; + + m_engine->registerValue(this); + return true; +} + +/*! + \internal + Invalidates this value (makes it undefined). + + Does not remove the value from the engine's list of + registered values; that's the responsibility of the caller. +*/ +void QJSValuePrivate::invalidate() +{ + if (isJSBased()) { + m_value.Dispose(); + m_value.Clear(); + } else if (isStringBased()) { + delete u.m_string; + } + m_engine = 0; + m_state = CUndefined; +} + +QV8Engine* QJSValuePrivate::engine() const +{ + return m_engine; +} + +inline QJSValuePrivate::operator v8::Handle() const +{ + Q_ASSERT(isJSBased()); + return m_value; +} + +inline QJSValuePrivate::operator v8::Handle() const +{ + Q_ASSERT(isObject()); + return v8::Handle::Cast(m_value); +} + +/*! + * Return a v8::Handle, assign to the engine if needed. + */ +v8::Handle QJSValuePrivate::asV8Value(QV8Engine* engine) +{ + if (!m_engine) { + if (!assignEngine(engine)) + return v8::Handle(); + } + Q_ASSERT(isJSBased()); + return m_value; +} + +/*! + \internal + Returns true if QSV have an engine associated. +*/ +bool QJSValuePrivate::isJSBased() const +{ +#ifndef QT_NO_DEBUG + // internals check. + if (m_state >= JSValue) + Q_ASSERT(!m_value.IsEmpty()); + else + Q_ASSERT(m_value.IsEmpty()); +#endif + return m_state >= JSValue; +} + +/*! + \internal + Returns true if current value of QSV is placed in m_number. +*/ +bool QJSValuePrivate::isNumberBased() const { return m_state == CNumber || m_state == CBool; } + +/*! + \internal + Returns true if current value of QSV is placed in m_string. +*/ +bool QJSValuePrivate::isStringBased() const { return m_state == CString; } + +/*! + \internal + Converts arguments and bind them to the engine. + \attention argv should be big enough +*/ +inline bool QJSValuePrivate::prepareArgumentsForCall(v8::Handle argv[], const QJSValueList& args) const +{ + QJSValueList::const_iterator i = args.constBegin(); + for (int j = 0; i != args.constEnd(); j++, i++) { + QJSValuePrivate* value = QJSValuePrivate::get(*i); + if ((value->isJSBased() && engine() != value->engine()) + || (!value->isJSBased() && !value->assignEngine(engine()))) + // Different engines are not allowed! + return false; + argv[j] = *value; + } + return true; +} + +QT_END_NAMESPACE + +#endif diff --cc src/qml/qml/v8/qjsvalue_p.h index 3eccba6,0000000..acfe958 mode 100644,000000..100644 --- a/src/qml/qml/v8/qjsvalue_p.h +++ b/src/qml/qml/v8/qjsvalue_p.h @@@ -1,195 -1,0 +1,213 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** - ** This file is part of the QtScript module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. +** - ** $QT_BEGIN_LICENSE:LGPL-ONLY$ ++** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage - ** This file may be used under the terms of the GNU Lesser - ** General Public License version 2.1 as published by the Free Software - ** Foundation and appearing in the file LICENSE.LGPL included in the - ** packaging of this file. Please review the following information to - ** ensure the GNU Lesser General Public License version 2.1 requirements - ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. - ** - ** If you have questions regarding the use of this file, please contact - ** us via http://www.qt-project.org/. ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** ++** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#ifndef QJSVALUE_P_H +#define QJSVALUE_P_H + +#include + +#include +#include +#include +#include +#include + +#include +#include "qscriptshareddata_p.h" +#include "qjsvalue.h" + +QT_BEGIN_NAMESPACE + +class QV8Engine; + +/*! + \internal + \class QJSValuePrivate +*/ +class QJSValuePrivate + : public QSharedData +{ +public: + enum PropertyFlag { + ReadOnly = 0x00000001, + Undeletable = 0x00000002, + SkipInEnumeration = 0x00000004 + }; + Q_DECLARE_FLAGS(PropertyFlags, PropertyFlag) + + inline static QJSValuePrivate* get(const QJSValue& q); + inline static QJSValue get(const QJSValuePrivate* d); + inline static QJSValue get(QJSValuePrivate* d); + inline static QJSValue get(QScriptPassPointer d); + inline ~QJSValuePrivate(); + + inline QJSValuePrivate(bool value); + inline QJSValuePrivate(int value); + inline QJSValuePrivate(uint value); + inline QJSValuePrivate(double value); + inline QJSValuePrivate(const QString& value); + inline QJSValuePrivate(QJSValue::SpecialValue value = QJSValue::UndefinedValue); + + inline QJSValuePrivate(QV8Engine *engine, bool value); + inline QJSValuePrivate(QV8Engine *engine, int value); + inline QJSValuePrivate(QV8Engine *engine, uint value); + inline QJSValuePrivate(QV8Engine *engine, double value); + inline QJSValuePrivate(QV8Engine *engine, const QString& value); + inline QJSValuePrivate(QV8Engine *engine, QJSValue::SpecialValue value = QJSValue::UndefinedValue); + inline QJSValuePrivate(QV8Engine *engine, v8::Handle); + inline void invalidate(); + + inline bool toBool() const; + inline double toNumber() const; + inline QString toString() const; + inline double toInteger() const; + inline qint32 toInt32() const; + inline quint32 toUInt32() const; + inline quint16 toUInt16() const; + inline QDateTime toDataTime() const; + inline QObject *toQObject() const; + inline QVariant toVariant() const; + + inline bool isArray() const; + inline bool isBool() const; + inline bool isCallable() const; + inline bool isError() const; + inline bool isFunction() const; + inline bool isNull() const; + inline bool isNumber() const; + inline bool isObject() const; + inline bool isString() const; + inline bool isUndefined() const; + inline bool isVariant() const; + inline bool isDate() const; + inline bool isRegExp() const; + inline bool isQObject() const; + + inline bool equals(QJSValuePrivate* other); + inline bool strictlyEquals(QJSValuePrivate* other); + inline bool lessThan(QJSValuePrivate *other) const; + + inline QScriptPassPointer prototype() const; + inline void setPrototype(QJSValuePrivate* prototype); + + inline void setProperty(const QString &name, QJSValuePrivate *value, uint attribs = 0); + inline void setProperty(v8::Handle name, QJSValuePrivate *value, uint attribs = 0); + inline void setProperty(quint32 index, QJSValuePrivate* value, uint attribs = 0); + inline QScriptPassPointer property(const QString& name) const; + inline QScriptPassPointer property(v8::Handle name) const; + inline QScriptPassPointer property(quint32 index) const; + template + inline QScriptPassPointer property(T name) const; + inline bool deleteProperty(const QString& name); + inline bool hasProperty(const QString &name) const; + inline bool hasOwnProperty(const QString &name) const; + inline PropertyFlags propertyFlags(const QString& name) const; + inline PropertyFlags propertyFlags(v8::Handle name) const; + + inline QScriptPassPointer call(QJSValuePrivate* thisObject, const QJSValueList& args); + inline QScriptPassPointer call(QJSValuePrivate* thisObject, const QJSValue& arguments); + inline QScriptPassPointer call(QJSValuePrivate* thisObject, int argc, v8::Handle< v8::Value >* argv); + inline QScriptPassPointer callAsConstructor(int argc, v8::Handle *argv); + inline QScriptPassPointer callAsConstructor(const QJSValueList& args); + inline QScriptPassPointer callAsConstructor(const QJSValue& arguments); + + inline bool assignEngine(QV8Engine *engine); + inline QV8Engine *engine() const; + + inline operator v8::Handle() const; + inline operator v8::Handle() const; + inline v8::Handle asV8Value(QV8Engine *engine); +private: + QIntrusiveListNode m_node; + QV8Engine *m_engine; + + // Please, update class documentation when you change the enum. + enum State { + CString = 0x1000, + CNumber, + CBool, + CNull, + CUndefined, + JSValue = 0x2000, // V8 values are equal or higher then this value. + // JSPrimitive, + // JSObject + } m_state; + + union CValue { + bool m_bool; + double m_number; + QString* m_string; + + CValue() : m_number(0) {} + CValue(bool value) : m_bool(value) {} + CValue(int number) : m_number(number) {} + CValue(uint number) : m_number(number) {} + CValue(double number) : m_number(number) {} + CValue(QString* string) : m_string(string) {} + } u; + // v8::Persistent is not a POD, so can't be part of the union. + v8::Persistent m_value; + + Q_DISABLE_COPY(QJSValuePrivate) + inline bool isJSBased() const; + inline bool isNumberBased() const; + inline bool isStringBased() const; + inline bool prepareArgumentsForCall(v8::Handle argv[], const QJSValueList& arguments) const; + + friend class QV8Engine; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QJSValuePrivate::PropertyFlags) + +QT_END_NAMESPACE + +#endif diff --cc src/qml/qml/v8/qjsvalueiterator.h index c47f07d,0000000..3c1b450 mode 100644,000000..100644 --- a/src/qml/qml/v8/qjsvalueiterator.h +++ b/src/qml/qml/v8/qjsvalueiterator.h @@@ -1,63 -1,0 +1,82 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** - ** This file is part of the QtScript module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. +** - ** $QT_BEGIN_LICENSE:LGPL-ONLY$ ++** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage - ** This file may be used under the terms of the GNU Lesser - ** General Public License version 2.1 as published by the Free Software - ** Foundation and appearing in the file LICENSE.LGPL included in the - ** packaging of this file. Please review the following information to - ** ensure the GNU Lesser General Public License version 2.1 requirements - ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** +** - ** If you have questions regarding the use of this file, please contact - ** us via http://www.qt-project.org/. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSCRIPTVALUEITERATOR_H +#define QSCRIPTVALUEITERATOR_H + ++#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + + +class QString; + +class QJSValueIteratorPrivate; +class Q_QML_EXPORT QJSValueIterator +{ +public: + QJSValueIterator(const QJSValue &value); + ~QJSValueIterator(); + + bool hasNext() const; + bool next(); + + QString name() const; + + QJSValue value() const; + QJSValueIterator& operator=(QJSValue &value); + +private: + QScopedPointer d_ptr; + + Q_DECLARE_PRIVATE(QJSValueIterator) + Q_DISABLE_COPY(QJSValueIterator) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QSCRIPTVALUEITERATOR_H diff --cc src/qml/qml/v8/qjsvalueiterator_impl_p.h index 131296e,0000000..2c060b2 mode 100644,000000..100644 --- a/src/qml/qml/v8/qjsvalueiterator_impl_p.h +++ b/src/qml/qml/v8/qjsvalueiterator_impl_p.h @@@ -1,121 -1,0 +1,139 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** - ** $QT_BEGIN_LICENSE:LGPL-ONLY$ ++** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage - ** This file may be used under the terms of the GNU Lesser - ** General Public License version 2.1 as published by the Free Software - ** Foundation and appearing in the file LICENSE.LGPL included in the - ** packaging of this file. Please review the following information to - ** ensure the GNU Lesser General Public License version 2.1 requirements - ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. - ** - ** If you have questions regarding the use of this file, please contact - ** us via http://www.qt-project.org/. ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** ++** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QJSVALUEITERATOR_IMPL_P_H +#define QJSVALUEITERATOR_IMPL_P_H + +#include "qjsvalueiterator_p.h" +#include +#include "qjsconverter_p.h" + +inline QJSValueIteratorPrivate::QJSValueIteratorPrivate(const QJSValuePrivate* value) + : m_object(const_cast(value)) + , m_index(0) + , m_count(0) +{ + Q_ASSERT(value); + QV8Engine *engine = m_object->engine(); + if (!m_object->isObject()) + m_object = 0; + else { + QScriptIsolate api(engine, QScriptIsolate::NotNullEngine); + v8::HandleScope scope; + + v8::Handle tmp = *value; + v8::Handle obj = v8::Handle::Cast(tmp); + v8::Local names; + + // FIXME we need newer V8! + //names = obj->GetOwnPropertyNames(); + names = engine->getOwnPropertyNames(obj); + m_names = v8::Persistent::New(names); + m_count = names->Length(); + + engine->registerValueIterator(this); + } +} + +inline QJSValueIteratorPrivate::~QJSValueIteratorPrivate() +{ + if (isValid()) { + engine()->unregisterValueIterator(this); + m_names.Dispose(); + } +} + +inline void QJSValueIteratorPrivate::invalidate() +{ + m_names.Dispose(); + m_object.reset(); + m_index = 0; + m_count = 0; +} + +inline bool QJSValueIteratorPrivate::hasNext() const +{ + return isValid() ? m_index < m_count : false; +} + +inline bool QJSValueIteratorPrivate::next() +{ + if (hasNext()) { + ++m_index; + return true; + } + return false; +} + +inline QString QJSValueIteratorPrivate::name() const +{ + if (!isValid()) + return QString(); + + v8::HandleScope handleScope; + return QJSConverter::toString(m_names->Get(m_index - 1)->ToString()); +} + +inline QScriptPassPointer QJSValueIteratorPrivate::value() const +{ + if (!isValid()) + return new QJSValuePrivate(); + + v8::HandleScope handleScope; + return m_object->property(m_names->Get(m_index - 1)->ToString()); +} + +inline bool QJSValueIteratorPrivate::isValid() const +{ + bool result = m_object ? !m_object->isUndefined() : false; + // We know that if this object is still valid then it is an object + // if this assumption is not correct then some other logic in this class + // have to be changed too. + Q_ASSERT(!result || m_object->isObject()); + return result; +} + +inline QV8Engine* QJSValueIteratorPrivate::engine() const +{ + return m_object ? m_object->engine() : 0; +} + +#endif // QJSVALUEITERATOR_IMPL_P_H diff --cc src/qml/qml/v8/qjsvalueiterator_p.h index 2a5bcde,0000000..f5f4c44 mode 100644,000000..100644 --- a/src/qml/qml/v8/qjsvalueiterator_p.h +++ b/src/qml/qml/v8/qjsvalueiterator_p.h @@@ -1,68 -1,0 +1,86 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** - ** $QT_BEGIN_LICENSE:LGPL-ONLY$ ++** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage - ** This file may be used under the terms of the GNU Lesser - ** General Public License version 2.1 as published by the Free Software - ** Foundation and appearing in the file LICENSE.LGPL included in the - ** packaging of this file. Please review the following information to - ** ensure the GNU Lesser General Public License version 2.1 requirements - ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** +** - ** If you have questions regarding the use of this file, please contact - ** us via http://www.qt-project.org/. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QJSVALUEITERATOR_P_H +#define QJSVALUEITERATOR_P_H + +#include +#include "qjsvalue_p.h" + +#include + +QT_BEGIN_NAMESPACE + +class QV8Engine; + +class QJSValueIteratorPrivate +{ +public: + inline QJSValueIteratorPrivate(const QJSValuePrivate* value); + inline ~QJSValueIteratorPrivate(); + + inline bool hasNext() const; + inline bool next(); + + inline QString name() const; + + inline QScriptPassPointer value() const; + + inline bool isValid() const; + inline QV8Engine* engine() const; + + inline void invalidate(); +private: + Q_DISABLE_COPY(QJSValueIteratorPrivate) + + QIntrusiveListNode m_node; + QScriptSharedDataPointer m_object; + v8::Persistent m_names; + uint32_t m_index; + uint32_t m_count; + + friend class QV8Engine; +}; + + +QT_END_NAMESPACE + +#endif // QJSVALUEITERATOR_P_H diff --cc src/qml/qml/v8/qqmlbuiltinfunctions.cpp index 5284832,0000000..7d7aaa2 mode 100644,000000..100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@@ -1,1320 -1,0 +1,1321 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmlbuiltinfunctions_p.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace QQmlBuiltinFunctions { + +enum ConsoleLogTypes { + Log, + Warn, + Error +}; + +static void jsContext(v8::Handle *file, int *line, v8::Handle *function) { + v8::Local stackTrace = v8::StackTrace::CurrentStackTrace(1); + if (stackTrace->GetFrameCount()) { + v8::Local frame = stackTrace->GetFrame(0); + *file = frame->GetScriptName(); + *line = frame->GetLineNumber(); + *function = frame->GetFunctionName(); + } +} + +static QString jsStack() { + QStringList stackFrames; + + //The v8 default is currently 10 stack frames. + v8::Handle stackTrace = + v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kOverview); + int stackCount = stackTrace->GetFrameCount(); + + for (int i = 0; i < stackCount; i++) { + v8::Local frame = stackTrace->GetFrame(i); + v8::Handle function(frame->GetFunctionName()); + v8::Handle script(frame->GetScriptName()); + int lineNumber = frame->GetLineNumber(); + int columnNumber = frame->GetColumn(); + + QString stackFrame = + QString::fromLatin1("%1 (%2:%3:%4)").arg(QJSConverter::toString(function), + QJSConverter::toString(script), + QString::number(lineNumber), + QString::number(columnNumber)); + stackFrames.append(stackFrame); + } + return stackFrames.join(QLatin1String("\n")); +} + +v8::Handle console(ConsoleLogTypes logType, const v8::Arguments &args, + bool printStack = false) +{ + v8::HandleScope handleScope; + + QString result; + for (int i = 0; i < args.Length(); ++i) { + if (i != 0) + result.append(QLatin1Char(' ')); + + v8::Local value = args[i]; + //Check for Object Type + if (value->IsObject() && !value->IsFunction() + && !value->IsArray() && !value->IsDate() + && !value->IsRegExp()) { + result.append(QLatin1String("Object")); + } else { + v8::Local jsstr = value->ToString(); + QString tmp = V8ENGINE()->toString(jsstr); + if (value->IsArray()) + result.append(QString::fromLatin1("[%1]").arg(tmp)); + else + result.append(tmp); + } + } + + if (printStack) { + result.append(QLatin1String("\n")); + result.append(jsStack()); + } + + v8::Handle fileHandle; + v8::Handle functionHandle; + int line; + + jsContext(&fileHandle, &line, &functionHandle); + + switch (logType) { + case Log: + QMessageLogger(*v8::String::AsciiValue(fileHandle), line, + *v8::String::AsciiValue(functionHandle)).debug("%s", qPrintable(result)); + break; + case Warn: + QMessageLogger(*v8::String::AsciiValue(fileHandle), line, + *v8::String::AsciiValue(functionHandle)).warning("%s", qPrintable(result)); + break; + case Error: + QMessageLogger(*v8::String::AsciiValue(fileHandle), line, + *v8::String::AsciiValue(functionHandle)).critical("%s", qPrintable(result)); + break; + default: + break; + } + + return v8::Undefined(); +} + +v8::Handle gc(const v8::Arguments &args) +{ + Q_UNUSED(args); + QV8Engine::gc(); + return v8::Undefined(); +} + +v8::Handle consoleError(const v8::Arguments &args) +{ + return console(Error, args); +} + +v8::Handle consoleLog(const v8::Arguments &args) +{ + //console.log + //console.debug + //console.info + //print + return console(Log, args); +} + +v8::Handle consoleProfile(const v8::Arguments &args) +{ + //DeclarativeDebugTrace cannot handle nested profiling + //although v8 can handle several profiling at once, + //we do not allow that. Hence, we pass an empty(default) title + Q_UNUSED(args); + QString title; + + + + v8::Handle file; + v8::Handle function; + int line; + jsContext(&file, &line, &function); + + if (QQmlProfilerService::startProfiling()) { + QV8ProfilerService::instance()->startProfiling(title); + + QMessageLogger(*v8::String::AsciiValue(file), line, + *v8::String::AsciiValue(function)).debug("Profiling started."); + } else { + QMessageLogger(*v8::String::AsciiValue(file), line, + *v8::String::AsciiValue(function)).warning( + "Profiling is already in progress. First, end current profiling session."); + } + + return v8::Undefined(); +} + +v8::Handle consoleProfileEnd(const v8::Arguments &args) +{ + //DeclarativeDebugTrace cannot handle nested profiling + //although v8 can handle several profiling at once, + //we do not allow that. Hence, we pass an empty(default) title + Q_UNUSED(args); + QString title; + + v8::Handle file; + v8::Handle function; + int line; + jsContext(&file, &line, &function); + + if (QQmlProfilerService::stopProfiling()) { + QV8ProfilerService *profiler = QV8ProfilerService::instance(); + profiler->stopProfiling(title); + QQmlProfilerService::sendProfilingData(); + profiler->sendProfilingData(); + + QMessageLogger(*v8::String::AsciiValue(file), line, + *v8::String::AsciiValue(function)).debug("Profiling ended."); + } else { + QMessageLogger(*v8::String::AsciiValue(file), line, + *v8::String::AsciiValue(function)).warning("Profiling was not started."); + } + + return v8::Undefined(); +} + +v8::Handle consoleTime(const v8::Arguments &args) +{ + if (args.Length() != 1) + V8THROW_ERROR("console.time(): Invalid arguments"); + QString name = V8ENGINE()->toString(args[0]); + V8ENGINE()->startTimer(name); + return v8::Undefined(); +} + +v8::Handle consoleTimeEnd(const v8::Arguments &args) +{ + if (args.Length() != 1) + V8THROW_ERROR("console.time(): Invalid arguments"); + QString name = V8ENGINE()->toString(args[0]); + bool wasRunning; + qint64 elapsed = V8ENGINE()->stopTimer(name, &wasRunning); + if (wasRunning) { + qDebug("%s: %llims", qPrintable(name), elapsed); + } + return v8::Undefined(); +} + +v8::Handle consoleCount(const v8::Arguments &args) +{ + // first argument: name to print. Ignore any additional arguments + QString name; + if (args.Length() > 0) + name = V8ENGINE()->toString(args[0]); + + v8::Handle stackTrace = + v8::StackTrace::CurrentStackTrace(1, v8::StackTrace::kOverview); + + if (stackTrace->GetFrameCount()) { + v8::Local frame = stackTrace->GetFrame(0); + + QString scriptName = V8ENGINE()->toString(frame->GetScriptName()); + QString functionName = V8ENGINE()->toString(frame->GetFunctionName()); + int line = frame->GetLineNumber(); + int column = frame->GetColumn(); + + int value = V8ENGINE()->consoleCountHelper(scriptName, line, column); + QString message = name + QLatin1String(": ") + QString::number(value); + + QMessageLogger(qPrintable(scriptName), line, + qPrintable(functionName)).debug("%s", qPrintable(message)); + } + + return v8::Undefined(); +} + +v8::Handle consoleTrace(const v8::Arguments &args) +{ + if (args.Length() != 0) + V8THROW_ERROR("console.trace(): Invalid arguments"); + + QString stack = jsStack(); + + v8::Handle file; + v8::Handle function; + int line; + jsContext(&file, &line, &function); + + QMessageLogger(*v8::String::AsciiValue(file), line, *v8::String::AsciiValue(function)).debug( + "%s", qPrintable(stack)); + return v8::Undefined(); +} + +v8::Handle consoleWarn(const v8::Arguments &args) +{ + return console(Warn, args); +} + +v8::Handle consoleAssert(const v8::Arguments &args) +{ + if (args.Length() == 0) + V8THROW_ERROR("console.assert(): Missing argument"); + + if (!args[0]->ToBoolean()->Value()) { + QString message; + for (int i = 1; i < args.Length(); ++i) { + if (i != 1) + message.append(QLatin1Char(' ')); + + v8::Local value = args[i]; + message.append(V8ENGINE()->toString(value->ToString())); + } + + QString stack = jsStack(); + + v8::Handle file; + v8::Handle function; + int line; + jsContext(&file, &line, &function); + + QMessageLogger(*v8::String::AsciiValue(file), line, *v8::String::AsciiValue(function)).critical( + "%s\n%s", qPrintable(message), qPrintable(stack)); + + } + return v8::Undefined(); +} + +v8::Handle consoleException(const v8::Arguments &args) +{ + if (args.Length() == 0) + V8THROW_ERROR("console.exception(): Missing argument"); + + console(Error, args, true); + + return v8::Undefined(); +} + +v8::Handle stringArg(const v8::Arguments &args) +{ + QString value = V8ENGINE()->toString(args.This()->ToString()); + if (args.Length() != 1) + V8THROW_ERROR("String.arg(): Invalid arguments"); + + v8::Handle arg = args[0]; + if (arg->IsUint32()) + return V8ENGINE()->toString(value.arg(arg->Uint32Value())); + else if (arg->IsInt32()) + return V8ENGINE()->toString(value.arg(arg->Int32Value())); + else if (arg->IsNumber()) + return V8ENGINE()->toString(value.arg(arg->NumberValue())); + else if (arg->IsBoolean()) + return V8ENGINE()->toString(value.arg(arg->BooleanValue())); + + return V8ENGINE()->toString(value.arg(V8ENGINE()->toString(arg))); +} + +/*! +\qmlmethod bool Qt::isQtObject(object) +Returns true if \c object is a valid reference to a Qt or QML object, otherwise false. +*/ +v8::Handle isQtObject(const v8::Arguments &args) +{ + if (args.Length() == 0) + return v8::Boolean::New(false); + + return v8::Boolean::New(0 != V8ENGINE()->toQObject(args[0])); +} + +/*! +\qmlmethod color Qt::rgba(real red, real green, real blue, real alpha) + +Returns a color with the specified \c red, \c green, \c blue and \c alpha components. +All components should be in the range 0-1 inclusive. +*/ +v8::Handle rgba(const v8::Arguments &args) +{ + int argCount = args.Length(); + if (argCount < 3 || argCount > 4) + V8THROW_ERROR("Qt.rgba(): Invalid arguments"); + + double r = args[0]->NumberValue(); + double g = args[1]->NumberValue(); + double b = args[2]->NumberValue(); + double a = (argCount == 4) ? args[3]->NumberValue() : 1; + + if (r < 0.0) r=0.0; + if (r > 1.0) r=1.0; + if (g < 0.0) g=0.0; + if (g > 1.0) g=1.0; + if (b < 0.0) b=0.0; + if (b > 1.0) b=1.0; + if (a < 0.0) a=0.0; + if (a > 1.0) a=1.0; + + return V8ENGINE()->fromVariant(QVariant::fromValue(QColor::fromRgbF(r, g, b, a))); +} + +/*! +\qmlmethod color Qt::hsla(real hue, real saturation, real lightness, real alpha) + +Returns a color with the specified \c hue, \c saturation, \c lightness and \c alpha components. +All components should be in the range 0-1 inclusive. +*/ +v8::Handle hsla(const v8::Arguments &args) +{ + int argCount = args.Length(); + if (argCount < 3 || argCount > 4) + V8THROW_ERROR("Qt.hsla(): Invalid arguments"); + + double h = args[0]->NumberValue(); + double s = args[1]->NumberValue(); + double l = args[2]->NumberValue(); + double a = (argCount == 4) ? args[3]->NumberValue() : 1; + + if (h < 0.0) h=0.0; + if (h > 1.0) h=1.0; + if (s < 0.0) s=0.0; + if (s > 1.0) s=1.0; + if (l < 0.0) l=0.0; + if (l > 1.0) l=1.0; + if (a < 0.0) a=0.0; + if (a > 1.0) a=1.0; + + return V8ENGINE()->fromVariant(QVariant::fromValue(QColor::fromHslF(h, s, l, a))); +} + +/*! +\qmlmethod rect Qt::rect(int x, int y, int width, int height) + +Returns a \c rect with the top-left corner at \c x, \c y and the specified \c width and \c height. + +The returned object has \c x, \c y, \c width and \c height attributes with the given values. +*/ +v8::Handle rect(const v8::Arguments &args) +{ + if (args.Length() != 4) + V8THROW_ERROR("Qt.rect(): Invalid arguments"); + + double x = args[0]->NumberValue(); + double y = args[1]->NumberValue(); + double w = args[2]->NumberValue(); + double h = args[3]->NumberValue(); + + return V8ENGINE()->fromVariant(QVariant::fromValue(QRectF(x, y, w, h))); +} + +/*! +\qmlmethod point Qt::point(int x, int y) +Returns a Point with the specified \c x and \c y coordinates. +*/ +v8::Handle point(const v8::Arguments &args) +{ + if (args.Length() != 2) + V8THROW_ERROR("Qt.point(): Invalid arguments"); + + double x = args[0]->ToNumber()->Value(); + double y = args[1]->ToNumber()->Value(); + + return V8ENGINE()->fromVariant(QVariant::fromValue(QPointF(x, y))); +} + +/*! +\qmlmethod Qt::size(int width, int height) +Returns a Size with the specified \c width and \c height. +*/ +v8::Handle size(const v8::Arguments &args) +{ + if (args.Length() != 2) + V8THROW_ERROR("Qt.size(): Invalid arguments"); + + double w = args[0]->ToNumber()->Value(); + double h = args[1]->ToNumber()->Value(); + + return V8ENGINE()->fromVariant(QVariant::fromValue(QSizeF(w, h))); +} + +/*! +\qmlmethod Qt::vector3d(real x, real y, real z) +Returns a Vector3D with the specified \c x, \c y and \c z. +*/ +v8::Handle vector3d(const v8::Arguments &args) +{ + if (args.Length() != 3) + V8THROW_ERROR("Qt.vector(): Invalid arguments"); + + double x = args[0]->ToNumber()->Value(); + double y = args[1]->ToNumber()->Value(); + double z = args[2]->ToNumber()->Value(); + + return V8ENGINE()->fromVariant(QVariant::fromValue(QVector3D(x, y, z))); +} + +/*! +\qmlmethod Qt::vector4d(real x, real y, real z, real w) +Returns a Vector4D with the specified \c x, \c y, \c z and \c w. +*/ +v8::Handle vector4d(const v8::Arguments &args) +{ + if (args.Length() != 4) + V8THROW_ERROR("Qt.vector4d(): Invalid arguments"); + + double x = args[0]->NumberValue(); + double y = args[1]->NumberValue(); + double z = args[2]->NumberValue(); + double w = args[3]->NumberValue(); + + return V8ENGINE()->fromVariant(QVariant::fromValue(QVector4D(x, y, z, w))); +} + +/*! +\qmlmethod color Qt::lighter(color baseColor, real factor) +Returns a color lighter than \c baseColor by the \c factor provided. + +If the factor is greater than 1.0, this functions returns a lighter color. +Setting factor to 1.5 returns a color that is 50% brighter. If the factor is less than 1.0, +the return color is darker, but we recommend using the Qt.darker() function for this purpose. +If the factor is 0 or negative, the return value is unspecified. + +The function converts the current RGB color to HSV, multiplies the value (V) component +by factor and converts the color back to RGB. + +If \c factor is not supplied, returns a color 50% lighter than \c baseColor (factor 1.5). +*/ +v8::Handle lighter(const v8::Arguments &args) +{ + if (args.Length() != 1 && args.Length() != 2) + V8THROW_ERROR("Qt.lighter(): Invalid arguments"); + + QColor color; + QVariant v = V8ENGINE()->toVariant(args[0], -1); + if (v.userType() == QVariant::Color) { + color = v.value(); + } else if (v.userType() == QVariant::String) { + bool ok = false; + color = QQmlStringConverters::colorFromString(v.toString(), &ok); + if (!ok) { + return v8::Null(); + } + } else { + return v8::Null(); + } + + qreal factor = 1.5; + if (args.Length() == 2) + factor = args[1]->ToNumber()->Value(); + + color = color.lighter(int(qRound(factor*100.))); + return V8ENGINE()->fromVariant(QVariant::fromValue(color)); +} + +/*! +\qmlmethod color Qt::darker(color baseColor, real factor) +Returns a color darker than \c baseColor by the \c factor provided. + +If the factor is greater than 1.0, this function returns a darker color. +Setting factor to 3.0 returns a color that has one-third the brightness. +If the factor is less than 1.0, the return color is lighter, but we recommend using +the Qt.lighter() function for this purpose. If the factor is 0 or negative, the return +value is unspecified. + +The function converts the current RGB color to HSV, divides the value (V) component +by factor and converts the color back to RGB. + +If \c factor is not supplied, returns a color 50% darker than \c baseColor (factor 2.0). +*/ +v8::Handle darker(const v8::Arguments &args) +{ + if (args.Length() != 1 && args.Length() != 2) + V8THROW_ERROR("Qt.darker(): Invalid arguments"); + + QColor color; + QVariant v = V8ENGINE()->toVariant(args[0], -1); + if (v.userType() == QVariant::Color) { + color = v.value(); + } else if (v.userType() == QVariant::String) { + bool ok = false; + color = QQmlStringConverters::colorFromString(v.toString(), &ok); + if (!ok) { + return v8::Null(); + } + } else { + return v8::Null(); + } + + qreal factor = 2.0; + if (args.Length() == 2) + factor = args[1]->ToNumber()->Value(); + + color = color.darker(int(qRound(factor*100.))); + return V8ENGINE()->fromVariant(QVariant::fromValue(color)); +} + +/*! + \qmlmethod color Qt::tint(color baseColor, color tintColor) + This function allows tinting one color with another. + + The tint color should usually be mostly transparent, or you will not be + able to see the underlying color. The below example provides a slight red + tint by having the tint color be pure red which is only 1/16th opaque. + + \qml + Item { + Rectangle { + x: 0; width: 80; height: 80 + color: "lightsteelblue" + } + Rectangle { + x: 100; width: 80; height: 80 + color: Qt.tint("lightsteelblue", "#10FF0000") + } + } + \endqml + \image declarative-rect_tint.png + + Tint is most useful when a subtle change is intended to be conveyed due to some event; you can then use tinting to more effectively tune the visible color. +*/ +v8::Handle tint(const v8::Arguments &args) +{ + if (args.Length() != 2) + V8THROW_ERROR("Qt.tint(): Invalid arguments"); + + // base color + QColor color; + QVariant v = V8ENGINE()->toVariant(args[0], -1); + if (v.userType() == QVariant::Color) { + color = v.value(); + } else if (v.userType() == QVariant::String) { + bool ok = false; + color = QQmlStringConverters::colorFromString(v.toString(), &ok); + if (!ok) { + return v8::Null(); + } + } else { + return v8::Null(); + } + + // tint color + QColor tintColor; + v = V8ENGINE()->toVariant(args[1], -1); + if (v.userType() == QVariant::Color) { + tintColor = v.value(); + } else if (v.userType() == QVariant::String) { + bool ok = false; + tintColor = QQmlStringConverters::colorFromString(v.toString(), &ok); + if (!ok) { + return v8::Null(); + } + } else { + return v8::Null(); + } + + // tint the base color and return the final color + QColor finalColor; + int a = tintColor.alpha(); + if (a == 0xFF) + finalColor = tintColor; + else if (a == 0x00) + finalColor = color; + else { + qreal a = tintColor.alphaF(); + qreal inv_a = 1.0 - a; + + finalColor.setRgbF(tintColor.redF() * a + color.redF() * inv_a, + tintColor.greenF() * a + color.greenF() * inv_a, + tintColor.blueF() * a + color.blueF() * inv_a, + a + inv_a * color.alphaF()); + } + + return V8ENGINE()->fromVariant(QVariant::fromValue(finalColor)); +} + +/*! +\qmlmethod string Qt::formatDate(datetime date, variant format) + +Returns a string representation of \c date, optionally formatted according +to \c format. + +The \a date parameter may be a JavaScript \c Date object, a \l{date}{date} +property, a QDate, or QDateTime value. The \a format parameter may be any of +the possible format values as described for +\l{QML:Qt::formatDateTime()}{Qt.formatDateTime()}. + +If \a format is not specified, \a date is formatted using +\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}. + +\sa Locale +*/ +v8::Handle formatDate(const v8::Arguments &args) +{ + if (args.Length() < 1 || args.Length() > 2) + V8THROW_ERROR("Qt.formatDate(): Invalid arguments"); + + Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate; + QDate date = V8ENGINE()->toVariant(args[0], -1).toDateTime().date(); + QString formattedDate; + if (args.Length() == 2) { + if (args[1]->IsString()) { + QString format = V8ENGINE()->toVariant(args[1], -1).toString(); + formattedDate = date.toString(format); + } else if (args[1]->IsNumber()) { + quint32 intFormat = args[1]->ToNumber()->Value(); + Qt::DateFormat format = Qt::DateFormat(intFormat); + formattedDate = date.toString(format); + } else { + V8THROW_ERROR("Qt.formatDate(): Invalid date format"); + } + } else { + formattedDate = date.toString(enumFormat); + } + + return V8ENGINE()->fromVariant(QVariant::fromValue(formattedDate)); +} + +/*! +\qmlmethod string Qt::formatTime(datetime time, variant format) + +Returns a string representation of \c time, optionally formatted according to +\c format. + +The \a time parameter may be a JavaScript \c Date object, a QTime, or QDateTime +value. The \a format parameter may be any of the possible format values as +described for \l{QML:Qt::formatDateTime()}{Qt.formatDateTime()}. + +If \a format is not specified, \a time is formatted using +\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}. + +\sa Locale +*/ +v8::Handle formatTime(const v8::Arguments &args) +{ + if (args.Length() < 1 || args.Length() > 2) + V8THROW_ERROR("Qt.formatTime(): Invalid arguments"); + + QVariant argVariant = V8ENGINE()->toVariant(args[0], -1); + QTime time; + if (args[0]->IsDate() || (argVariant.type() == QVariant::String)) + time = argVariant.toDateTime().time(); + else // if (argVariant.type() == QVariant::Time), or invalid. + time = argVariant.toTime(); + + Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate; + QString formattedTime; + if (args.Length() == 2) { + if (args[1]->IsString()) { + QString format = V8ENGINE()->toVariant(args[1], -1).toString(); + formattedTime = time.toString(format); + } else if (args[1]->IsNumber()) { + quint32 intFormat = args[1]->ToNumber()->Value(); + Qt::DateFormat format = Qt::DateFormat(intFormat); + formattedTime = time.toString(format); + } else { + V8THROW_ERROR("Qt.formatTime(): Invalid time format"); + } + } else { + formattedTime = time.toString(enumFormat); + } + + return V8ENGINE()->fromVariant(QVariant::fromValue(formattedTime)); +} + +/*! +\qmlmethod string Qt::formatDateTime(datetime dateTime, variant format) + +Returns a string representation of \c datetime, optionally formatted according to +\c format. + +The \a date parameter may be a JavaScript \c Date object, a \l{date}{date} +property, a QDate, QTime, or QDateTime value. + +If \a format is not provided, \a dateTime is formatted using +\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}. Otherwise, +\a format should be either: + +\list +\o One of the Qt::DateFormat enumeration values, such as + \c Qt.DefaultLocaleShortDate or \c Qt.ISODate +\o A string that specifies the format of the returned string, as detailed below. +\endlist + +If \a format specifies a format string, it should use the following expressions +to specify the date: + + \table + \header \i Expression \i Output + \row \i d \i the day as number without a leading zero (1 to 31) + \row \i dd \i the day as number with a leading zero (01 to 31) + \row \i ddd + \i the abbreviated localized day name (e.g. 'Mon' to 'Sun'). + Uses QDate::shortDayName(). + \row \i dddd + \i the long localized day name (e.g. 'Monday' to 'Qt::Sunday'). + Uses QDate::longDayName(). + \row \i M \i the month as number without a leading zero (1-12) + \row \i MM \i the month as number with a leading zero (01-12) + \row \i MMM + \i the abbreviated localized month name (e.g. 'Jan' to 'Dec'). + Uses QDate::shortMonthName(). + \row \i MMMM + \i the long localized month name (e.g. 'January' to 'December'). + Uses QDate::longMonthName(). + \row \i yy \i the year as two digit number (00-99) + \row \i yyyy \i the year as four digit number + \endtable + +In addition the following expressions can be used to specify the time: + + \table + \header \i Expression \i Output + \row \i h + \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display) + \row \i hh + \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display) + \row \i m \i the minute without a leading zero (0 to 59) + \row \i mm \i the minute with a leading zero (00 to 59) + \row \i s \i the second without a leading zero (0 to 59) + \row \i ss \i the second with a leading zero (00 to 59) + \row \i z \i the milliseconds without leading zeroes (0 to 999) + \row \i zzz \i the milliseconds with leading zeroes (000 to 999) + \row \i AP + \i use AM/PM display. \e AP will be replaced by either "AM" or "PM". + \row \i ap + \i use am/pm display. \e ap will be replaced by either "am" or "pm". + \endtable + + All other input characters will be ignored. Any sequence of characters that + are enclosed in single quotes will be treated as text and not be used as an + expression. Two consecutive single quotes ("''") are replaced by a single quote + in the output. + +For example, if the following date/time value was specified: + + \code + // 21 May 2001 14:13:09 + var dateTime = new Date(2001, 5, 21, 14, 13, 09) + \endcode + +This \a dateTime value could be passed to \c Qt.formatDateTime(), +\l {QML:Qt::formatDate()}{Qt.formatDate()} or \l {QML:Qt::formatTime()}{Qt.formatTime()} +with the \a format values below to produce the following results: + + \table + \header \i Format \i Result + \row \i "dd.MM.yyyy" \i 21.05.2001 + \row \i "ddd MMMM d yy" \i Tue May 21 01 + \row \i "hh:mm:ss.zzz" \i 14:13:09.042 + \row \i "h:m:s ap" \i 2:13:9 pm + \endtable + + \sa Locale +*/ +v8::Handle formatDateTime(const v8::Arguments &args) +{ + if (args.Length() < 1 || args.Length() > 2) + V8THROW_ERROR("Qt.formatDateTime(): Invalid arguments"); + + Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate; + QDateTime dt = V8ENGINE()->toVariant(args[0], -1).toDateTime(); + QString formattedDt; + if (args.Length() == 2) { + if (args[1]->IsString()) { + QString format = V8ENGINE()->toVariant(args[1], -1).toString(); + formattedDt = dt.toString(format); + } else if (args[1]->IsNumber()) { + quint32 intFormat = args[1]->ToNumber()->Value(); + Qt::DateFormat format = Qt::DateFormat(intFormat); + formattedDt = dt.toString(format); + } else { + V8THROW_ERROR("Qt.formatDateTime(): Invalid datetime format"); + } + } else { + formattedDt = dt.toString(enumFormat); + } + + return V8ENGINE()->fromVariant(QVariant::fromValue(formattedDt)); +} + +/*! +\qmlmethod bool Qt::openUrlExternally(url target) +Attempts to open the specified \c target url in an external application, based on the user's desktop preferences. Returns true if it succeeds, and false otherwise. +*/ +v8::Handle openUrlExternally(const v8::Arguments &args) +{ + if (args.Length() != 1) + return V8ENGINE()->fromVariant(false); + + bool ret = false; +#ifndef QT_NO_DESKTOPSERVICES + ret = QDesktopServices::openUrl(V8ENGINE()->toVariant(resolvedUrl(args), -1).toUrl()); +#endif + return V8ENGINE()->fromVariant(ret); +} + +/*! + \qmlmethod url Qt::resolvedUrl(url url) + Returns \a url resolved relative to the URL of the caller. +*/ +v8::Handle resolvedUrl(const v8::Arguments &args) +{ + QUrl url = V8ENGINE()->toVariant(args[0], -1).toUrl(); + QQmlEngine *e = V8ENGINE()->engine(); + QQmlEnginePrivate *p = 0; + if (e) p = QQmlEnginePrivate::get(e); + if (p) { + QQmlContextData *ctxt = V8ENGINE()->callingContext(); + if (ctxt) + return V8ENGINE()->toString(ctxt->resolvedUrl(url).toString()); + else + return V8ENGINE()->toString(url.toString()); + } + + return V8ENGINE()->toString(e->baseUrl().resolved(url).toString()); +} + +/*! +\qmlmethod list Qt::fontFamilies() +Returns a list of the font families available to the application. +*/ +v8::Handle fontFamilies(const v8::Arguments &args) +{ + if (args.Length() != 0) + V8THROW_ERROR("Qt.fontFamilies(): Invalid arguments"); + + QFontDatabase database; + return V8ENGINE()->fromVariant(database.families()); +} + +/*! +\qmlmethod string Qt::md5(data) +Returns a hex string of the md5 hash of \c data. +*/ +v8::Handle md5(const v8::Arguments &args) +{ + if (args.Length() != 1) + V8THROW_ERROR("Qt.md5(): Invalid arguments"); + + QByteArray data = V8ENGINE()->toString(args[0]->ToString()).toUtf8(); + QByteArray result = QCryptographicHash::hash(data, QCryptographicHash::Md5); + return V8ENGINE()->toString(QLatin1String(result.toHex())); +} + +/*! +\qmlmethod string Qt::btoa(data) +Binary to ASCII - this function returns a base64 encoding of \c data. +*/ +v8::Handle btoa(const v8::Arguments &args) +{ + if (args.Length() != 1) + V8THROW_ERROR("Qt.btoa(): Invalid arguments"); + + QByteArray data = V8ENGINE()->toString(args[0]->ToString()).toUtf8(); + + return V8ENGINE()->toString(QLatin1String(data.toBase64())); +} + +/*! +\qmlmethod string Qt::atob(data) +ASCII to binary - this function returns a base64 decoding of \c data. +*/ +v8::Handle atob(const v8::Arguments &args) +{ + if (args.Length() != 1) + V8THROW_ERROR("Qt.atob(): Invalid arguments"); + + QByteArray data = V8ENGINE()->toString(args[0]->ToString()).toUtf8(); + + return V8ENGINE()->toString(QLatin1String(QByteArray::fromBase64(data))); +} + +/*! +\qmlmethod Qt::quit() +This function causes the QQmlEngine::quit() signal to be emitted. +Within the \l {QML Viewer}, this causes the launcher application to exit; +to quit a C++ application when this method is called, connect the +QQmlEngine::quit() signal to the QCoreApplication::quit() slot. +*/ +v8::Handle quit(const v8::Arguments &args) +{ + QQmlEnginePrivate::get(V8ENGINE()->engine())->sendQuit(); + return v8::Undefined(); +} + +/*! +\qmlmethod object Qt::createQmlObject(string qml, object parent, string filepath) + +Returns a new object created from the given \a string of QML which will have the specified \a parent, +or \c null if there was an error in creating the object. + +If \a filepath is specified, it will be used for error reporting for the created object. + +Example (where \c parentItem is the id of an existing QML item): + +\snippet doc/src/snippets/qml/createQmlObject.qml 0 + +In the case of an error, a QtScript Error object is thrown. This object has an additional property, +\c qmlErrors, which is an array of the errors encountered. +Each object in this array has the members \c lineNumber, \c columnNumber, \c fileName and \c message. +For example, if the above snippet had misspelled color as 'colro' then the array would contain an object like the following: +{ "lineNumber" : 1, "columnNumber" : 32, "fileName" : "dynamicSnippet1", "message" : "Cannot assign to non-existent property \"colro\""}. + +Note that this function returns immediately, and therefore may not work if +the \a qml string loads new components (that is, external QML files that have not yet been loaded). +If this is the case, consider using \l{QML:Qt::createComponent()}{Qt.createComponent()} instead. + +See \l {Dynamic Object Management in QML} for more information on using this function. +*/ +v8::Handle createQmlObject(const v8::Arguments &args) +{ + if (args.Length() < 2 || args.Length() > 3) + V8THROW_ERROR("Qt.createQmlObject(): Invalid arguments"); + + struct Error { + static v8::Local create(QV8Engine *engine, const QList &errors) { + QString errorstr = QLatin1String("Qt.createQmlObject(): failed to create object: "); + + v8::Local qmlerrors = v8::Array::New(errors.count()); + for (int ii = 0; ii < errors.count(); ++ii) { + const QQmlError &error = errors.at(ii); + errorstr += QLatin1String("\n ") + error.toString(); + v8::Local qmlerror = v8::Object::New(); + qmlerror->Set(v8::String::New("lineNumber"), v8::Integer::New(error.line())); + qmlerror->Set(v8::String::New("columnNumber"), v8::Integer::New(error.column())); + qmlerror->Set(v8::String::New("fileName"), engine->toString(error.url().toString())); + qmlerror->Set(v8::String::New("message"), engine->toString(error.description())); + qmlerrors->Set(ii, qmlerror); + } + + v8::Local error = v8::Exception::Error(engine->toString(errorstr)); + v8::Local errorObject = error->ToObject(); + errorObject->Set(v8::String::New("qmlErrors"), qmlerrors); + return error; + } + }; + + QV8Engine *v8engine = V8ENGINE(); + QQmlEngine *engine = v8engine->engine(); + + QQmlContextData *context = v8engine->callingContext(); + QQmlContext *effectiveContext = 0; + if (context->isPragmaLibraryContext) + effectiveContext = engine->rootContext(); + else + effectiveContext = context->asQQmlContext(); + Q_ASSERT(context && effectiveContext); + + QString qml = v8engine->toString(args[0]->ToString()); + if (qml.isEmpty()) + return v8::Null(); + + QUrl url; + if (args.Length() > 2) + url = QUrl(v8engine->toString(args[2]->ToString())); + else + url = QUrl(QLatin1String("inline")); + + if (url.isValid() && url.isRelative()) + url = context->resolvedUrl(url); + + QObject *parentArg = v8engine->toQObject(args[1]); + if (!parentArg) + V8THROW_ERROR("Qt.createQmlObject(): Missing parent object"); + + QQmlComponent component(engine); + component.setData(qml.toUtf8(), url); + + if (component.isError()) { + v8::ThrowException(Error::create(v8engine, component.errors())); + return v8::Undefined(); + } + + if (!component.isReady()) + V8THROW_ERROR("Qt.createQmlObject(): Component is not ready"); + + QObject *obj = component.beginCreate(effectiveContext); - if (obj) ++ if (obj) { + QQmlData::get(obj, true)->setImplicitDestructible(); ++ ++ obj->setParent(parentArg); ++ ++ QList functions = QQmlMetaType::parentFunctions(); ++ for (int ii = 0; ii < functions.count(); ++ii) { ++ if (QQmlPrivate::Parented == functions.at(ii)(obj, parentArg)) ++ break; ++ } ++ } + component.completeCreate(); + + if (component.isError()) { + v8::ThrowException(Error::create(v8engine, component.errors())); + return v8::Undefined(); + } + + Q_ASSERT(obj); + - obj->setParent(parentArg); - - QList functions = QQmlMetaType::parentFunctions(); - for (int ii = 0; ii < functions.count(); ++ii) { - if (QQmlPrivate::Parented == functions.at(ii)(obj, parentArg)) - break; - } - + return v8engine->newQObject(obj); +} + +/*! +\qmlmethod object Qt::createComponent(url) + +Returns a \l Component object created using the QML file at the specified \a url, +or \c null if an empty string was given. + +The returned component's \l Component::status property indicates whether the +component was successfully created. If the status is \c Component.Error, +see \l Component::errorString() for an error description. + +Call \l {Component::createObject()}{Component.createObject()} on the returned +component to create an object instance of the component. + +For example: + +\snippet doc/src/snippets/qml/createComponent-simple.qml 0 + +See \l {Dynamic Object Management in QML} for more information on using this function. + +To create a QML object from an arbitrary string of QML (instead of a file), +use \l{QML:Qt::createQmlObject()}{Qt.createQmlObject()}. +*/ +v8::Handle createComponent(const v8::Arguments &args) +{ + if (args.Length() != 1) + V8THROW_ERROR("Qt.createComponent(): Invalid arguments"); + + QV8Engine *v8engine = V8ENGINE(); + QQmlEngine *engine = v8engine->engine(); + + QQmlContextData *context = v8engine->callingContext(); + QQmlContextData *effectiveContext = context; + if (context->isPragmaLibraryContext) + effectiveContext = 0; + Q_ASSERT(context); + + QString arg = v8engine->toString(args[0]->ToString()); + if (arg.isEmpty()) + return v8::Null(); + + QUrl url = context->resolvedUrl(QUrl(arg)); + QQmlComponent *c = new QQmlComponent(engine, url, engine); + QQmlComponentPrivate::get(c)->creationContext = effectiveContext; + QQmlData::get(c, true)->setImplicitDestructible(); + return v8engine->newQObject(c); +} + +v8::Handle qsTranslate(const v8::Arguments &args) +{ + if (args.Length() < 2) + V8THROW_ERROR("qsTranslate() requires at least two arguments"); + if (!args[0]->IsString()) + V8THROW_ERROR("qsTranslate(): first argument (context) must be a string"); + if (!args[1]->IsString()) + V8THROW_ERROR("qsTranslate(): second argument (text) must be a string"); + if ((args.Length() > 2) && !args[2]->IsString()) + V8THROW_ERROR("qsTranslate(): third argument (comment) must be a string"); + if ((args.Length() > 3) && !args[3]->IsString()) + V8THROW_ERROR("qsTranslate(): fourth argument (encoding) must be a string"); + + QV8Engine *v8engine = V8ENGINE(); + QString context = v8engine->toString(args[0]); + QString text = v8engine->toString(args[1]); + QString comment; + if (args.Length() > 2) comment = v8engine->toString(args[2]); + + QCoreApplication::Encoding encoding = QCoreApplication::UnicodeUTF8; + if (args.Length() > 3) { + QString encStr = v8engine->toString(args[3]); + if (encStr == QLatin1String("CodecForTr")) { + encoding = QCoreApplication::CodecForTr; + } else if (encStr == QLatin1String("UnicodeUTF8")) { + encoding = QCoreApplication::UnicodeUTF8; + } else { + QString msg = QString::fromLatin1("qsTranslate(): invalid encoding '%0'").arg(encStr); + V8THROW_ERROR((uint16_t *)msg.constData()); + } + } + + int n = -1; + if (args.Length() > 4) + n = args[4]->Int32Value(); + + QString result = QCoreApplication::translate(context.toUtf8().constData(), + text.toUtf8().constData(), + comment.toUtf8().constData(), + encoding, n); + + return v8engine->toString(result); +} + +v8::Handle qsTranslateNoOp(const v8::Arguments &args) +{ + if (args.Length() < 2) + return v8::Undefined(); + return args[1]; +} + +v8::Handle qsTr(const v8::Arguments &args) +{ + if (args.Length() < 1) + V8THROW_ERROR("qsTr() requires at least one argument"); + if (!args[0]->IsString()) + V8THROW_ERROR("qsTr(): first argument (text) must be a string"); + if ((args.Length() > 1) && !args[1]->IsString()) + V8THROW_ERROR("qsTr(): second argument (comment) must be a string"); + if ((args.Length() > 2) && !args[2]->IsNumber()) + V8THROW_ERROR("qsTr(): third argument (n) must be a number"); + + QV8Engine *v8engine = V8ENGINE(); + QQmlContextData *ctxt = v8engine->callingContext(); + + QString path = ctxt->url.toString(); + int lastSlash = path.lastIndexOf(QLatin1Char('/')); + QString context = (lastSlash > -1) ? path.mid(lastSlash + 1, path.length()-lastSlash-5) : QString(); + + QString text = v8engine->toString(args[0]); + QString comment; + if (args.Length() > 1) + comment = v8engine->toString(args[1]); + int n = -1; + if (args.Length() > 2) + n = args[2]->Int32Value(); + + QString result = QCoreApplication::translate(context.toUtf8().constData(), text.toUtf8().constData(), + comment.toUtf8().constData(), QCoreApplication::UnicodeUTF8, n); + + return v8engine->toString(result); +} + +v8::Handle qsTrNoOp(const v8::Arguments &args) +{ + if (args.Length() < 1) + return v8::Undefined(); + return args[0]; +} + +v8::Handle qsTrId(const v8::Arguments &args) +{ + if (args.Length() < 1) + V8THROW_ERROR("qsTrId() requires at least one argument"); + if (!args[0]->IsString()) + V8THROW_TYPE("qsTrId(): first argument (id) must be a string"); + if (args.Length() > 1 && !args[1]->IsNumber()) + V8THROW_TYPE("qsTrId(): second argument (n) must be a number"); + + int n = -1; + if (args.Length() > 1) + n = args[1]->Int32Value(); + + QV8Engine *v8engine = V8ENGINE(); + return v8engine->toString(qtTrId(v8engine->toString(args[0]).toUtf8().constData(), n)); +} + +v8::Handle qsTrIdNoOp(const v8::Arguments &args) +{ + if (args.Length() < 1) + return v8::Undefined(); + return args[0]; +} + + +/*! + \qmlmethod Qt::locale(name) + + Returns a JS object representing the locale with the specified + name, which has the format "language[_territory][.codeset][@modifier]" + or "C", where: + + \list + \o language is a lowercase, two-letter, ISO 639 language code, + \o territory is an uppercase, two-letter, ISO 3166 country code, + \o and codeset and modifier are ignored. + \endlist + + If the string violates the locale format, or language is not a + valid ISO 369 code, the "C" locale is used instead. If country + is not present, or is not a valid ISO 3166 code, the most + appropriate country is chosen for the specified language. + + \sa QtQuick2::Locale +*/ +v8::Handle locale(const v8::Arguments &args) +{ + QString code; + if (args.Length() > 1) + V8THROW_ERROR("locale() requires 0 or 1 argument"); + if (args.Length() == 1 && !args[0]->IsString()) + V8THROW_TYPE("locale(): argument (locale code) must be a string"); + + QV8Engine *v8engine = V8ENGINE(); + if (args.Length() == 1) + code = v8engine->toString(args[0]); + + return QQmlLocale::locale(v8engine, code); +} + +} // namespace QQmlBuiltinFunctions + +QT_END_NAMESPACE diff --cc src/qml/qml/v8/qscript_impl_p.h index fdbf2f0,0000000..d4acc45 mode 100644,000000..100644 --- a/src/qml/qml/v8/qscript_impl_p.h +++ b/src/qml/qml/v8/qscript_impl_p.h @@@ -1,43 -1,0 +1,61 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** - ** This file is part of the QtScript module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. +** - ** $QT_BEGIN_LICENSE:LGPL-ONLY$ ++** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage - ** This file may be used under the terms of the GNU Lesser - ** General Public License version 2.1 as published by the Free Software - ** Foundation and appearing in the file LICENSE.LGPL included in the - ** packaging of this file. Please review the following information to - ** ensure the GNU Lesser General Public License version 2.1 requirements - ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. - ** - ** If you have questions regarding the use of this file, please contact - ** us via http://www.qt-project.org/. ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** ++** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#ifndef QSCRIPT_IMPL_P_H +#define QSCRIPT_IMPL_P_H + +#include "qv8engine_impl_p.h" +#include "qjsvalue_impl_p.h" +#include "qjsvalueiterator_impl_p.h" +#include "qjsconverter_impl_p.h" + +#endif //QSCRIPT_IMPL_P_H diff --cc src/qml/qml/v8/qscriptisolate_p.h index 4afa747,0000000..7784855 mode 100644,000000..100644 --- a/src/qml/qml/v8/qscriptisolate_p.h +++ b/src/qml/qml/v8/qscriptisolate_p.h @@@ -1,71 -1,0 +1,89 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** - ** This file is part of the QtScript module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. +** - ** $QT_BEGIN_LICENSE:LGPL-ONLY$ ++** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage - ** This file may be used under the terms of the GNU Lesser - ** General Public License version 2.1 as published by the Free Software - ** Foundation and appearing in the file LICENSE.LGPL included in the - ** packaging of this file. Please review the following information to - ** ensure the GNU Lesser General Public License version 2.1 requirements - ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. - ** - ** If you have questions regarding the use of this file, please contact - ** us via http://www.qt-project.org/. ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** ++** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef APIPREAMBLE_P_H +#define APIPREAMBLE_P_H + +#include +#include "qv8engine_p.h" + +QT_BEGIN_NAMESPACE + +/** + \internal + Class used to switch to the right isolate. It does the same thing as v8::Isolate::Scope but + it checks for a null engine. + \attention We decided to put context switching "up" which means that it should be as high + as possible on call stack. And it should be switched at most once per public API function call. +*/ +class QScriptIsolate { +public: + // OperationMode was introduced to reduce number of checking for a null engine pointer. If we + // know that given pointer is not null than we should pass NotNullEngine as constructor argument + // that would nicely remove checking on compilation time. + enum OperationMode {Default, NotNullEngine}; + inline QScriptIsolate(const QV8Engine *engine, const OperationMode mode = Default) + : m_engine(engine) + , m_mode(mode) + { + if (m_mode == NotNullEngine || m_engine) { + Q_ASSERT(m_engine); + m_engine->context()->Enter(); + } + } + + inline ~QScriptIsolate() + { + if (m_mode == NotNullEngine || m_engine) { + m_engine->context()->Exit(); + } + } + +private: + Q_DISABLE_COPY(QScriptIsolate); + const QV8Engine *m_engine; + const OperationMode m_mode; +}; + + +QT_END_NAMESPACE + +#endif // APIPREAMBLE_P_H diff --cc src/qml/qml/v8/qscriptoriginalglobalobject_p.h index 12321cc,0000000..e4661c1 mode 100644,000000..100644 --- a/src/qml/qml/v8/qscriptoriginalglobalobject_p.h +++ b/src/qml/qml/v8/qscriptoriginalglobalobject_p.h @@@ -1,159 -1,0 +1,177 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** - ** This file is part of the QtScript module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. +** - ** $QT_BEGIN_LICENSE:LGPL-ONLY$ ++** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage - ** This file may be used under the terms of the GNU Lesser - ** General Public License version 2.1 as published by the Free Software - ** Foundation and appearing in the file LICENSE.LGPL included in the - ** packaging of this file. Please review the following information to - ** ensure the GNU Lesser General Public License version 2.1 requirements - ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. - ** - ** If you have questions regarding the use of this file, please contact - ** us via http://www.qt-project.org/. ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** ++** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSCRIPTORIGINALGLOBALOBJECT_P_H +#define QSCRIPTORIGINALGLOBALOBJECT_P_H + +#include "QtCore/qglobal.h" +#include "qjsvalue_p.h" + +#include + +QT_BEGIN_NAMESPACE + +class QV8Engine; + +/*! + \internal + This class is a workaround for missing V8 API functionality. This class keeps all important + properties of an original (default) global object, so we can use it even if the global object was + changed. + + FIXME this class is a container for workarounds :-) it should be replaced by proper API calls. + + The class have to be created on the QV8Engine creation time (before any change got applied to + global object). + + \attention All methods (apart from constructor) assumes that a context and a scope are prepared correctly. +*/ +class QScriptOriginalGlobalObject +{ +public: + inline QScriptOriginalGlobalObject() {} + inline void init(v8::Handle context); + inline void destroy(); + + inline QJSValuePrivate::PropertyFlags getPropertyFlags(v8::Handle object, v8::Handle property); + inline v8::Local getOwnPropertyDescriptor(v8::Handle object, v8::Handle property) const; + inline bool strictlyEquals(v8::Handle object); +private: + Q_DISABLE_COPY(QScriptOriginalGlobalObject) + + // Copy of constructors and prototypes used in isType functions. + v8::Persistent m_ownPropertyDescriptor; + v8::Persistent m_globalObject; +}; + +void QScriptOriginalGlobalObject::init(v8::Handle context) +{ + // Please notice that engine is not fully initialized at this point. + + v8::Context::Scope contextScope(context); + + v8::HandleScope scope; + + m_globalObject = v8::Persistent::New(context->Global()); + + v8::Local objectConstructor = m_globalObject->Get(v8::String::New("Object"))->ToObject(); + Q_ASSERT(objectConstructor->IsObject()); + { // Initialize m_ownPropertyDescriptor. + v8::Local ownPropertyDescriptor = objectConstructor->Get(v8::String::New("getOwnPropertyDescriptor")); + Q_ASSERT(!ownPropertyDescriptor.IsEmpty()); + m_ownPropertyDescriptor = v8::Persistent::New(v8::Local::Cast(ownPropertyDescriptor)); + } +} + +/*! + \internal + QScriptOriginalGlobalObject lives as long as QV8Engine that keeps it. In ~QSEP + the v8 context is removed, so we need to remove our handlers before. to break this dependency + destroy method should be called before or insight QSEP destructor. +*/ +inline void QScriptOriginalGlobalObject::destroy() +{ + m_ownPropertyDescriptor.Dispose(); + m_globalObject.Dispose(); + // After this line this instance is unusable. +} + +inline QJSValuePrivate::PropertyFlags QScriptOriginalGlobalObject::getPropertyFlags(v8::Handle object, v8::Handle property) +{ + Q_ASSERT(object->IsObject()); + Q_ASSERT(!property.IsEmpty()); + v8::Local descriptor = getOwnPropertyDescriptor(object, property); + if (descriptor.IsEmpty()) { +// // Property isn't owned by this object. +// if (!(mode & QScriptValue::ResolvePrototype)) +// return 0; + v8::Local prototype = object->GetPrototype(); + if (prototype->IsNull()) + return 0; + return getPropertyFlags(v8::Local::Cast(prototype), property); + } + v8::Local writableName = v8::String::New("writable"); + v8::Local configurableName = v8::String::New("configurable"); + v8::Local enumerableName = v8::String::New("enumerable"); +// v8::Local getName = v8::String::New("get"); +// v8::Local setName = v8::String::New("set"); + + unsigned flags = 0; + + if (!descriptor->Get(configurableName)->BooleanValue()) + flags |= QJSValuePrivate::Undeletable; + if (!descriptor->Get(enumerableName)->BooleanValue()) + flags |= QJSValuePrivate::SkipInEnumeration; + + //"writable" is only a property of the descriptor if it is not an accessor + if (descriptor->Has(writableName)) { + if (!descriptor->Get(writableName)->BooleanValue()) + flags |= QJSValuePrivate::ReadOnly; + } else { +// if (descriptor->Get(getName)->IsObject()) +// flags |= QScriptValue::PropertyGetter; +// if (descriptor->Get(setName)->IsObject()) +// flags |= QScriptValue::PropertySetter; + } + + return QJSValuePrivate::PropertyFlag(flags); +} + +inline v8::Local QScriptOriginalGlobalObject::getOwnPropertyDescriptor(v8::Handle object, v8::Handle property) const +{ + Q_ASSERT(object->IsObject()); + Q_ASSERT(!property.IsEmpty()); + // FIXME do we need try catch here? + v8::Handle argv[] = {object, property}; + v8::Local descriptor = m_ownPropertyDescriptor->Call(m_globalObject, /* argc */ 2, argv); + if (descriptor.IsEmpty() || !descriptor->IsObject()) + return v8::Local(); + return v8::Local::Cast(descriptor); +} + +inline bool QScriptOriginalGlobalObject::strictlyEquals(v8::Handle object) +{ + return m_globalObject->GetPrototype()->StrictEquals(object); +} + +QT_END_NAMESPACE + +#endif diff --cc src/qml/qml/v8/qscriptshareddata_p.h index df95b26,0000000..d3491c7 mode 100644,000000..100644 --- a/src/qml/qml/v8/qscriptshareddata_p.h +++ b/src/qml/qml/v8/qscriptshareddata_p.h @@@ -1,151 -1,0 +1,169 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** - ** This file is part of the QtScript module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. +** - ** $QT_BEGIN_LICENSE:LGPL-ONLY$ ++** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage - ** This file may be used under the terms of the GNU Lesser - ** General Public License version 2.1 as published by the Free Software - ** Foundation and appearing in the file LICENSE.LGPL included in the - ** packaging of this file. Please review the following information to - ** ensure the GNU Lesser General Public License version 2.1 requirements - ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. - ** - ** If you have questions regarding the use of this file, please contact - ** us via http://www.qt-project.org/. ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** ++** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#ifndef QSCRIPTSHAREDDATA_P_H +#define QSCRIPTSHAREDDATA_P_H + +#include "qglobal.h" +#include "qshareddata.h" + +QT_BEGIN_NAMESPACE + +/*! + \internal + This class should have the same interface as the QSharedData, but implementation doesn't + need to be thread safe, so atomic ref count was replaced by normal integer value. +*/ +class QScriptSharedData +{ +public: + class ReferenceCounter { + // FIXME shouldn't it be uint or something longer? + mutable int m_ref; + ReferenceCounter(int ref) : m_ref(ref) {} + ~ReferenceCounter() { Q_ASSERT_X(!m_ref, Q_FUNC_INFO, "Memory problem found"); } + public: + bool ref() { return ++m_ref; } + bool deref() { return --m_ref; } + friend class QScriptSharedData; + }; + + ReferenceCounter ref; + inline QScriptSharedData() : ref(0) { } + +private: + Q_DISABLE_COPY(QScriptSharedData) +}; + + +template class QScriptPassPointer; + +// FIXME: that could be reimplemented to not check for a null value. +template +class QScriptSharedDataPointer : public QExplicitlySharedDataPointer +{ +public: + inline QScriptSharedDataPointer() {} + explicit QScriptSharedDataPointer(QScriptPassPointer data) : QExplicitlySharedDataPointer(data.give()) {} + explicit QScriptSharedDataPointer(T *data) : QExplicitlySharedDataPointer(data) {} + + inline QScriptSharedDataPointer &operator=(const QScriptPassPointer &other) + { + this->QExplicitlySharedDataPointer::operator =(other.give()); + return *this; + } + inline QScriptSharedDataPointer &operator=(T *other) + { + this->QExplicitlySharedDataPointer::operator =(other); + return *this; + } +}; + +// FIXME: that could be reimplemented to not check for a null value. +template +class QScriptPassPointer { +public: + QScriptPassPointer(T *data) : m_ptr(data) {} + inline QScriptPassPointer() { m_ptr = 0; } + inline QScriptPassPointer(const QScriptPassPointer &other) : m_ptr(other.give()) {} + inline ~QScriptPassPointer() { Q_ASSERT_X(!m_ptr, Q_FUNC_INFO, "Ownership of the QScriptPassPointer hasn't been taken"); } + + inline T &operator*() const { return *m_ptr; } + inline T *operator->() { return m_ptr; } + inline T *operator->() const { return m_ptr; } + inline T *data() const { return m_ptr; } + inline const T *constData() const { return m_ptr; } + + inline bool operator==(const QScriptPassPointer &other) const { return m_ptr == other.m_ptr; } + inline bool operator!=(const QScriptPassPointer &other) const { return m_ptr != other.m_ptr; } + inline bool operator==(const QScriptSharedDataPointer &other) const { return m_ptr == other.m_ptr; } + inline bool operator!=(const QScriptSharedDataPointer &other) const { return m_ptr != other.m_ptr; } + inline bool operator==(const T *ptr) const { return m_ptr == ptr; } + inline bool operator!=(const T *ptr) const { return m_ptr != ptr; } + + inline operator bool () const { return m_ptr != 0; } + inline bool operator!() const { return !m_ptr; } + + inline QScriptPassPointer & operator=(const QScriptPassPointer &other) + { + if (other.m_ptr != m_ptr) { + if (m_ptr) + delete m_ptr; + m_ptr = other.give(); + } + return *this; + } + + inline QScriptPassPointer &operator=(T *other) + { + if (other != m_ptr) { + if (m_ptr) + delete m_ptr; + m_ptr = other; + } + return *this; + } + + inline T* give() const + { + T* result = m_ptr; + m_ptr = 0; + return result; + } + +private: + mutable T* m_ptr; +}; + +QT_END_NAMESPACE + +#endif // QSCRIPTSHAREDDATA_P_H diff --cc src/qml/qml/v8/qscripttools_p.h index fcea205,0000000..d69e9c8 mode 100644,000000..100644 --- a/src/qml/qml/v8/qscripttools_p.h +++ b/src/qml/qml/v8/qscripttools_p.h @@@ -1,68 -1,0 +1,86 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** - ** This file is part of the QtScript module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. +** - ** $QT_BEGIN_LICENSE:LGPL-ONLY$ ++** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage - ** This file may be used under the terms of the GNU Lesser - ** General Public License version 2.1 as published by the Free Software - ** Foundation and appearing in the file LICENSE.LGPL included in the - ** packaging of this file. Please review the following information to - ** ensure the GNU Lesser General Public License version 2.1 requirements - ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. - ** - ** If you have questions regarding the use of this file, please contact - ** us via http://www.qt-project.org/. ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** ++** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + + +#ifndef QSCRIPTTOOLS_P_H +#define QSCRIPTTOOLS_P_H + +#include + +QT_BEGIN_NAMESPACE + +template +class QScriptIntrusiveList : public QIntrusiveList +{ +public: + inline void insert(N *n); + inline void remove(N *n); +}; + +template +void QScriptIntrusiveList::insert(N *n) +{ + Q_ASSERT_X(!this->contains(n), Q_FUNC_INFO, "Can't insert a value which is in the list already"); + Q_ASSERT_X(!(n->*member).isInList(), Q_FUNC_INFO, "Can't insert a value which is in another list"); + QIntrusiveList::insert(n); +} + +template +void QScriptIntrusiveList::remove(N *n) +{ + Q_ASSERT_X(this->contains(n), Q_FUNC_INFO, "Can't remove a value which is not in the list"); + QIntrusiveList::remove(n); +} + +QT_END_NAMESPACE + +#endif //QSCRIPTTOOLS_P_H diff --cc src/qml/qml/v8/qv8engine.cpp index 4c2cce1,0000000..8e8223f mode 100644,000000..100644 --- a/src/qml/qml/v8/qv8engine.cpp +++ b/src/qml/qml/v8/qv8engine.cpp @@@ -1,1598 -1,0 +1,1600 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qv8engine_p.h" + +#include + +#include "qv8contextwrapper_p.h" +#include "qv8valuetypewrapper_p.h" +#include "qv8sequencewrapper_p.h" +#include "qv8include_p.h" +#include "qjsengine_p.h" +#include "../../../3rdparty/javascriptcore/DateMath.h" + +#include +#include +#include +#include +#include +#include + +#include "qscript_impl_p.h" +#include "qv8domerrors_p.h" +#include "qv8sqlerrors_p.h" + + +Q_DECLARE_METATYPE(QJSValue) +Q_DECLARE_METATYPE(QList) + + +// XXX TODO: Need to check all the global functions will also work in a worker script where the +// QQmlEngine is not available +QT_BEGIN_NAMESPACE + +static bool ObjectComparisonCallback(v8::Local lhs, v8::Local rhs) +{ + if (lhs == rhs) + return true; + ++ if (lhs.IsEmpty() || rhs.IsEmpty()) ++ return false; ++ + QV8ObjectResource *lhsr = static_cast(lhs->GetExternalResource()); + QV8ObjectResource *rhsr = static_cast(rhs->GetExternalResource()); + - Q_ASSERT(lhsr->engine == rhsr->engine); - + if (lhsr && rhsr) { ++ Q_ASSERT(lhsr->engine == rhsr->engine); + QV8ObjectResource::ResourceType lhst = lhsr->resourceType(); + QV8ObjectResource::ResourceType rhst = rhsr->resourceType(); + + switch (lhst) { + case QV8ObjectResource::ValueTypeType: + // a value type might be equal to a variant or another value type + if (rhst == QV8ObjectResource::ValueTypeType) { + return lhsr->engine->valueTypeWrapper()->isEqual(lhsr, lhsr->engine->valueTypeWrapper()->toVariant(rhsr)); + } else if (rhst == QV8ObjectResource::VariantType) { + return lhsr->engine->valueTypeWrapper()->isEqual(lhsr, lhsr->engine->variantWrapper()->toVariant(rhsr)); + } + break; + case QV8ObjectResource::VariantType: + // a variant might be equal to a value type or other variant. + if (rhst == QV8ObjectResource::VariantType) { + return lhsr->engine->variantWrapper()->toVariant(lhsr) == + lhsr->engine->variantWrapper()->toVariant(rhsr); + } else if (rhst == QV8ObjectResource::ValueTypeType) { + return rhsr->engine->valueTypeWrapper()->isEqual(rhsr, rhsr->engine->variantWrapper()->toVariant(lhsr)); + } + break; + case QV8ObjectResource::SequenceType: + // a sequence might be equal to itself. + if (rhst == QV8ObjectResource::SequenceType) { + return lhsr->engine->sequenceWrapper()->isEqual(lhsr, rhsr); + } + break; + default: + break; + } + } + + return false; +} + + +QV8Engine::QV8Engine(QJSEngine* qq, QJSEngine::ContextOwnership ownership) + : q(qq) + , m_engine(0) + , m_ownsV8Context(ownership == QJSEngine::CreateNewContext) + , m_xmlHttpRequestData(0) + , m_listModelData(0) +{ + qMetaTypeId(); + qMetaTypeId >(); + + QByteArray v8args = qgetenv("V8ARGS"); + // change default v8 behaviour to not relocate breakpoints across lines + if (!v8args.contains("breakpoint_relocation")) + v8args.append(" --nobreakpoint_relocation"); + v8::V8::SetFlagsFromString(v8args.constData(), v8args.length()); + + ensurePerThreadIsolate(); + + v8::HandleScope handle_scope; + m_context = (ownership == QJSEngine::CreateNewContext) ? v8::Context::New() : v8::Persistent::New(v8::Context::GetCurrent()); + qPersistentRegister(m_context); + m_originalGlobalObject.init(m_context); + v8::Context::Scope context_scope(m_context); + + v8::V8::SetUserObjectComparisonCallbackFunction(ObjectComparisonCallback); + QV8GCCallback::registerGcPrologueCallback(); + m_strongReferencer = qPersistentNew(v8::Object::New()); + + m_stringWrapper.init(); + m_contextWrapper.init(this); + m_qobjectWrapper.init(this); + m_typeWrapper.init(this); + m_listWrapper.init(this); + m_variantWrapper.init(this); + m_valueTypeWrapper.init(this); + m_sequenceWrapper.init(this); + + { + v8::Handle v = global()->Get(v8::String::New("Object"))->ToObject()->Get(v8::String::New("getOwnPropertyNames")); + m_getOwnPropertyNames = qPersistentNew(v8::Handle::Cast(v)); + } +} + +QV8Engine::~QV8Engine() +{ + Q_ASSERT_X(v8::Isolate::GetCurrent(), "QV8Engine::~QV8Engine()", "called after v8::Isolate has exited"); + for (int ii = 0; ii < m_extensionData.count(); ++ii) + delete m_extensionData[ii]; + m_extensionData.clear(); + + qt_rem_qmlxmlhttprequest(this, m_xmlHttpRequestData); + m_xmlHttpRequestData = 0; + delete m_listModelData; + m_listModelData = 0; + + qPersistentDispose(m_freezeObject); + qPersistentDispose(m_getOwnPropertyNames); + + invalidateAllValues(); + clearExceptions(); + + qPersistentDispose(m_strongReferencer); + + m_sequenceWrapper.destroy(); + m_valueTypeWrapper.destroy(); + m_variantWrapper.destroy(); + m_listWrapper.destroy(); + m_typeWrapper.destroy(); + m_qobjectWrapper.destroy(); + m_contextWrapper.destroy(); + m_stringWrapper.destroy(); + + m_originalGlobalObject.destroy(); + + if (m_ownsV8Context) + qPersistentDispose(m_context); +} + +QString QV8Engine::toStringStatic(v8::Handle jsstr) +{ + return toStringStatic(jsstr->ToString()); +} + +QString QV8Engine::toStringStatic(v8::Handle jsstr) +{ + QString qstr; + qstr.resize(jsstr->Length()); + jsstr->Write((uint16_t*)qstr.data()); + return qstr; +} + +QVariant QV8Engine::toVariant(v8::Handle value, int typeHint) +{ + if (value.IsEmpty()) + return QVariant(); + + if (typeHint == QVariant::Bool) + return QVariant(value->BooleanValue()); + + if (value->IsObject()) { + QV8ObjectResource *r = (QV8ObjectResource *)value->ToObject()->GetExternalResource(); + if (r) { + switch (r->resourceType()) { + case QV8ObjectResource::Context2DStyleType: + case QV8ObjectResource::Context2DPixelArrayType: + case QV8ObjectResource::SignalHandlerType: + case QV8ObjectResource::IncubatorType: + case QV8ObjectResource::VisualDataItemType: + case QV8ObjectResource::ContextType: + case QV8ObjectResource::XMLHttpRequestType: + case QV8ObjectResource::DOMNodeType: + case QV8ObjectResource::SQLDatabaseType: + case QV8ObjectResource::ListModelType: + case QV8ObjectResource::Context2DType: + case QV8ObjectResource::ParticleDataType: + case QV8ObjectResource::LocaleDataType: + return QVariant(); + case QV8ObjectResource::TypeType: + return m_typeWrapper.toVariant(r); + case QV8ObjectResource::QObjectType: + return qVariantFromValue(m_qobjectWrapper.toQObject(r)); + case QV8ObjectResource::ListType: + return m_listWrapper.toVariant(r); + case QV8ObjectResource::VariantType: + return m_variantWrapper.toVariant(r); + case QV8ObjectResource::ValueTypeType: + return m_valueTypeWrapper.toVariant(r); + case QV8ObjectResource::SequenceType: + return m_sequenceWrapper.toVariant(r); + } + } + } + + if (value->IsArray()) { + v8::Handle array = v8::Handle::Cast(value); + if (typeHint == qMetaTypeId >()) { + QList list; + uint32_t length = array->Length(); + for (uint32_t ii = 0; ii < length; ++ii) { + v8::Local arrayItem = array->Get(ii); + if (arrayItem->IsObject()) { + list << toQObject(arrayItem->ToObject()); + } else { + list << 0; + } + } + + return qVariantFromValue >(list); + } + + bool succeeded = false; + QVariant retn = m_sequenceWrapper.toVariant(array, typeHint, &succeeded); + if (succeeded) + return retn; + } + + return toBasicVariant(value); +} + +static v8::Handle arrayFromStringList(QV8Engine *engine, const QStringList &list) +{ + v8::Context::Scope scope(engine->context()); + v8::Local result = v8::Array::New(list.count()); + for (int ii = 0; ii < list.count(); ++ii) + result->Set(ii, engine->toString(list.at(ii))); + return result; +} + +static v8::Handle arrayFromVariantList(QV8Engine *engine, const QVariantList &list) +{ + v8::Context::Scope scope(engine->context()); + v8::Local result = v8::Array::New(list.count()); + for (int ii = 0; ii < list.count(); ++ii) + result->Set(ii, engine->fromVariant(list.at(ii))); + return result; +} + +static v8::Handle objectFromVariantMap(QV8Engine *engine, const QVariantMap &map) +{ + v8::Context::Scope scope(engine->context()); + v8::Local object = v8::Object::New(); + for (QVariantMap::ConstIterator iter = map.begin(); iter != map.end(); ++iter) + object->Set(engine->toString(iter.key()), engine->fromVariant(iter.value())); + return object; +} + +Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax); + +v8::Handle QV8Engine::fromVariant(const QVariant &variant) +{ + int type = variant.userType(); + const void *ptr = variant.constData(); + + if (type < QMetaType::User) { + switch (QMetaType::Type(type)) { + case QMetaType::Void: + return v8::Undefined(); + case QMetaType::Bool: + return v8::Boolean::New(*reinterpret_cast(ptr)); + case QMetaType::Int: + return v8::Integer::New(*reinterpret_cast(ptr)); + case QMetaType::UInt: + return v8::Integer::NewFromUnsigned(*reinterpret_cast(ptr)); + case QMetaType::LongLong: + return v8::Number::New(*reinterpret_cast(ptr)); + case QMetaType::ULongLong: + return v8::Number::New(*reinterpret_cast(ptr)); + case QMetaType::Double: + return v8::Number::New(*reinterpret_cast(ptr)); + case QMetaType::QString: + return m_stringWrapper.toString(*reinterpret_cast(ptr)); + case QMetaType::Float: + return v8::Number::New(*reinterpret_cast(ptr)); + case QMetaType::Short: + return v8::Integer::New(*reinterpret_cast(ptr)); + case QMetaType::UShort: + return v8::Integer::NewFromUnsigned(*reinterpret_cast(ptr)); + case QMetaType::Char: + return v8::Integer::New(*reinterpret_cast(ptr)); + case QMetaType::UChar: + return v8::Integer::NewFromUnsigned(*reinterpret_cast(ptr)); + case QMetaType::QChar: + return v8::Integer::New((*reinterpret_cast(ptr)).unicode()); + case QMetaType::QDateTime: + return v8::Date::New(qtDateTimeToJsDate(*reinterpret_cast(ptr))); + case QMetaType::QDate: + return v8::Date::New(qtDateTimeToJsDate(QDateTime(*reinterpret_cast(ptr)))); + case QMetaType::QTime: + return v8::Date::New(qtDateTimeToJsDate(QDateTime(QDate(1970,1,1), *reinterpret_cast(ptr)))); + case QMetaType::QRegExp: + return QJSConverter::toRegExp(*reinterpret_cast(ptr)); + case QMetaType::QObjectStar: + case QMetaType::QWidgetStar: + return newQObject(*reinterpret_cast(ptr)); + case QMetaType::QStringList: + { + bool succeeded = false; + v8::Handle retn = m_sequenceWrapper.fromVariant(variant, &succeeded); + if (succeeded) + return retn; + return arrayFromStringList(this, *reinterpret_cast(ptr)); + } + case QMetaType::QVariantList: + return arrayFromVariantList(this, *reinterpret_cast(ptr)); + case QMetaType::QVariantMap: + return objectFromVariantMap(this, *reinterpret_cast(ptr)); + + default: + break; + } + + if (m_engine) { + if (QQmlValueType *vt = QQmlEnginePrivate::get(m_engine)->valueTypes[type]) + return m_valueTypeWrapper.newValueType(variant, vt); + } + + } else { + if (type == qMetaTypeId()) { + typedef QQmlListReferencePrivate QDLRP; + QDLRP *p = QDLRP::get((QQmlListReference*)ptr); + if (p->object) { + return m_listWrapper.newList(p->property, p->propertyType); + } else { + return v8::Null(); + } + } else if (type == qMetaTypeId()) { + const QJSValue *value = reinterpret_cast(ptr); + QJSValuePrivate *valuep = QJSValuePrivate::get(*value); + if (valuep->assignEngine(this)) + return v8::Local::New(*valuep); + } else if (type == qMetaTypeId >()) { + // XXX Can this be made more by using Array as a prototype and implementing + // directly against QList? + const QList &list = *(QList*)ptr; + v8::Local array = v8::Array::New(list.count()); + for (int ii = 0; ii < list.count(); ++ii) + array->Set(ii, newQObject(list.at(ii))); + return array; + } + + bool objOk; + QObject *obj = QQmlMetaType::toQObject(variant, &objOk); + if (objOk) + return newQObject(obj); + + bool succeeded = false; + v8::Handle retn = m_sequenceWrapper.fromVariant(variant, &succeeded); + if (succeeded) + return retn; + } + + // XXX TODO: To be compatible, we still need to handle: + // + QObjectList + // + QList + + return m_variantWrapper.newVariant(variant); +} + +// A handle scope and context must be entered +v8::Local QV8Engine::qmlModeCompile(const QString &source, + const QString &fileName, + int lineNumber) +{ + v8::Local v8source = m_stringWrapper.toString(source); + v8::Local v8fileName = m_stringWrapper.toString(fileName); + + v8::ScriptOrigin origin(v8fileName, v8::Integer::New(lineNumber - 1)); + + v8::Local script = v8::Script::Compile(v8source, &origin, 0, v8::Handle(), + v8::Script::QmlMode); + + return script; +} + +// A handle scope and context must be entered. +// source can be either ascii or utf8. +v8::Local QV8Engine::qmlModeCompile(const char *source, int sourceLength, + const QString &fileName, + int lineNumber) +{ + if (sourceLength == -1) + sourceLength = strlen(source); + + v8::Local v8source = v8::String::New(source, sourceLength); + v8::Local v8fileName = m_stringWrapper.toString(fileName); + + v8::ScriptOrigin origin(v8fileName, v8::Integer::New(lineNumber - 1)); + + v8::Local script = v8::Script::Compile(v8source, &origin, 0, v8::Handle(), + v8::Script::QmlMode); + + return script; +} + +QNetworkAccessManager *QV8Engine::networkAccessManager() +{ + return QQmlEnginePrivate::get(m_engine)->getNetworkAccessManager(); +} + +const QStringHash &QV8Engine::illegalNames() const +{ + return m_illegalNames; +} + +// Requires a handle scope +v8::Local QV8Engine::getOwnPropertyNames(v8::Handle o) +{ + // FIXME Newer v8 have API for this function + v8::TryCatch tc; + v8::Handle args[] = { o }; + v8::Local r = m_getOwnPropertyNames->Call(global(), 1, args); + if (tc.HasCaught()) + return v8::Array::New(); + else + return v8::Local::Cast(r); +} + +QQmlContextData *QV8Engine::callingContext() +{ + return m_contextWrapper.callingContext(); +} + +// Converts a JS value to a QVariant. +// Null, Undefined -> QVariant() (invalid) +// Boolean -> QVariant(bool) +// Number -> QVariant(double) +// String -> QVariant(QString) +// Array -> QVariantList(...) +// Date -> QVariant(QDateTime) +// RegExp -> QVariant(QRegExp) +// [Any other object] -> QVariantMap(...) +QVariant QV8Engine::toBasicVariant(v8::Handle value) +{ + if (value->IsNull() || value->IsUndefined()) + return QVariant(); + if (value->IsBoolean()) + return value->ToBoolean()->Value(); + if (value->IsInt32()) + return value->ToInt32()->Value(); + if (value->IsNumber()) + return value->ToNumber()->Value(); + if (value->IsString()) + return m_stringWrapper.toString(value->ToString()); + if (value->IsDate()) + return qtDateTimeFromJsDate(v8::Handle::Cast(value)->NumberValue()); + // NOTE: since we convert QTime to JS Date, round trip will change the variant type (to QDateTime)! + + Q_ASSERT(value->IsObject()); + + if (value->IsRegExp()) { + v8::Context::Scope scope(context()); + return QJSConverter::toRegExp(v8::Handle::Cast(value)); + } + if (value->IsArray()) { + v8::Context::Scope scope(context()); + QVariantList rv; + + v8::Handle array = v8::Handle::Cast(value); + int length = array->Length(); + for (int ii = 0; ii < length; ++ii) + rv << toVariant(array->Get(ii), -1); + return rv; + } + if (!value->IsFunction()) { + v8::Context::Scope scope(context()); + v8::Handle object = value->ToObject(); + return variantMapFromJS(object); + } + + return QVariant(); +} + + + +#include +#include + +struct StaticQtMetaObject : public QObject +{ + static const QMetaObject *get() + { return &static_cast (0)->staticQtMetaObject; } +}; + +void QV8Engine::initializeGlobal(v8::Handle global) +{ + using namespace QQmlBuiltinFunctions; + + v8::Local console = v8::Object::New(); + v8::Local consoleLogFn = V8FUNCTION(consoleLog, this); + + console->Set(v8::String::New("debug"), consoleLogFn); + console->Set(v8::String::New("log"), consoleLogFn); + console->Set(v8::String::New("info"), consoleLogFn); + console->Set(v8::String::New("warn"), V8FUNCTION(consoleWarn, this)); + console->Set(v8::String::New("error"), V8FUNCTION(consoleError, this)); + console->Set(v8::String::New("assert"), V8FUNCTION(consoleAssert, this)); + + console->Set(v8::String::New("count"), V8FUNCTION(consoleCount, this)); + console->Set(v8::String::New("profile"), V8FUNCTION(consoleProfile, this)); + console->Set(v8::String::New("profileEnd"), V8FUNCTION(consoleProfileEnd, this)); + console->Set(v8::String::New("time"), V8FUNCTION(consoleTime, this)); + console->Set(v8::String::New("timeEnd"), V8FUNCTION(consoleTimeEnd, this)); + console->Set(v8::String::New("trace"), V8FUNCTION(consoleTrace, this)); + console->Set(v8::String::New("exception"), V8FUNCTION(consoleException, this)); + + v8::Local qt = v8::Object::New(); + + // Set all the enums from the "Qt" namespace + const QMetaObject *qtMetaObject = StaticQtMetaObject::get(); + for (int ii = 0; ii < qtMetaObject->enumeratorCount(); ++ii) { + QMetaEnum enumerator = qtMetaObject->enumerator(ii); + for (int jj = 0; jj < enumerator.keyCount(); ++jj) { + qt->Set(v8::String::New(enumerator.key(jj)), v8::Integer::New(enumerator.value(jj))); + } + } + qt->Set(v8::String::New("Asynchronous"), v8::Integer::New(0)); + qt->Set(v8::String::New("Synchronous"), v8::Integer::New(1)); + + qt->Set(v8::String::New("include"), V8FUNCTION(QV8Include::include, this)); + qt->Set(v8::String::New("isQtObject"), V8FUNCTION(isQtObject, this)); + qt->Set(v8::String::New("rgba"), V8FUNCTION(rgba, this)); + qt->Set(v8::String::New("hsla"), V8FUNCTION(hsla, this)); + qt->Set(v8::String::New("rect"), V8FUNCTION(rect, this)); + qt->Set(v8::String::New("point"), V8FUNCTION(point, this)); + qt->Set(v8::String::New("size"), V8FUNCTION(size, this)); + qt->Set(v8::String::New("vector3d"), V8FUNCTION(vector3d, this)); + qt->Set(v8::String::New("vector4d"), V8FUNCTION(vector4d, this)); + + qt->Set(v8::String::New("formatDate"), V8FUNCTION(formatDate, this)); + qt->Set(v8::String::New("formatTime"), V8FUNCTION(formatTime, this)); + qt->Set(v8::String::New("formatDateTime"), V8FUNCTION(formatDateTime, this)); + + qt->Set(v8::String::New("openUrlExternally"), V8FUNCTION(openUrlExternally, this)); + qt->Set(v8::String::New("fontFamilies"), V8FUNCTION(fontFamilies, this)); + qt->Set(v8::String::New("md5"), V8FUNCTION(md5, this)); + qt->Set(v8::String::New("btoa"), V8FUNCTION(btoa, this)); + qt->Set(v8::String::New("atob"), V8FUNCTION(atob, this)); + qt->Set(v8::String::New("resolvedUrl"), V8FUNCTION(resolvedUrl, this)); + qt->Set(v8::String::New("locale"), V8FUNCTION(locale, this)); + + if (m_engine) { + qt->Set(v8::String::New("application"), newQObject(new QQuickApplication(m_engine))); + qt->Set(v8::String::New("inputMethod"), newQObject(qGuiApp->inputMethod(), CppOwnership)); + qt->Set(v8::String::New("lighter"), V8FUNCTION(lighter, this)); + qt->Set(v8::String::New("darker"), V8FUNCTION(darker, this)); + qt->Set(v8::String::New("tint"), V8FUNCTION(tint, this)); + qt->Set(v8::String::New("quit"), V8FUNCTION(quit, this)); + qt->Set(v8::String::New("createQmlObject"), V8FUNCTION(createQmlObject, this)); + qt->Set(v8::String::New("createComponent"), V8FUNCTION(createComponent, this)); + } + + global->Set(v8::String::New("qsTranslate"), V8FUNCTION(qsTranslate, this)); + global->Set(v8::String::New("QT_TRANSLATE_NOOP"), V8FUNCTION(qsTranslateNoOp, this)); + global->Set(v8::String::New("qsTr"), V8FUNCTION(qsTr, this)); + global->Set(v8::String::New("QT_TR_NOOP"), V8FUNCTION(qsTrNoOp, this)); + global->Set(v8::String::New("qsTrId"), V8FUNCTION(qsTrId, this)); + global->Set(v8::String::New("QT_TRID_NOOP"), V8FUNCTION(qsTrIdNoOp, this)); + + global->Set(v8::String::New("print"), consoleLogFn); + global->Set(v8::String::New("console"), console); + global->Set(v8::String::New("Qt"), qt); + global->Set(v8::String::New("gc"), V8FUNCTION(QQmlBuiltinFunctions::gc, this)); + + { +#define STRING_ARG "(function(stringArg) { "\ + " String.prototype.arg = (function() {"\ + " return stringArg.apply(this, arguments);"\ + " })"\ + "})" + + v8::Local registerArg = v8::Script::New(v8::String::New(STRING_ARG), 0, 0, v8::Handle(), v8::Script::NativeMode); + v8::Local result = registerArg->Run(); + Q_ASSERT(result->IsFunction()); + v8::Local registerArgFunc = v8::Local::Cast(result); + v8::Handle args = V8FUNCTION(stringArg, this); + registerArgFunc->Call(v8::Local::Cast(registerArgFunc), 1, &args); +#undef STRING_ARG + } + + QQmlLocale::registerStringLocaleCompare(this); + QQmlDateExtension::registerExtension(this); + QQmlNumberExtension::registerExtension(this); + + qt_add_domexceptions(this); + m_xmlHttpRequestData = qt_add_qmlxmlhttprequest(this); + + qt_add_sqlexceptions(this); + + { + v8::Handle args[] = { global }; + v8::Local names = m_getOwnPropertyNames->Call(global, 1, args); + v8::Local namesArray = v8::Local::Cast(names); + for (quint32 ii = 0; ii < namesArray->Length(); ++ii) + m_illegalNames.insert(toString(namesArray->Get(ii)), true); + } + + { +#define FREEZE_SOURCE "(function freeze_recur(obj) { "\ + " if (Qt.isQtObject(obj)) return;"\ + " if (obj != Function.connect && obj != Function.disconnect && "\ + " obj instanceof Object) {"\ + " var properties = Object.getOwnPropertyNames(obj);"\ + " for (var prop in properties) { "\ + " if (prop == \"connect\" || prop == \"disconnect\") {"\ + " Object.freeze(obj[prop]); "\ + " continue;"\ + " }"\ + " freeze_recur(obj[prop]);"\ + " }"\ + " }"\ + " if (obj instanceof Object) {"\ + " Object.freeze(obj);"\ + " }"\ + "})" + + v8::Local freeze = v8::Script::New(v8::String::New(FREEZE_SOURCE)); + v8::Local result = freeze->Run(); + Q_ASSERT(result->IsFunction()); + m_freezeObject = qPersistentNew(v8::Local::Cast(result)); +#undef FREEZE_SOURCE + } +} + +void QV8Engine::freezeObject(v8::Handle value) +{ + v8::Handle args[] = { value }; + m_freezeObject->Call(global(), 1, args); +} + +void QV8Engine::gc() +{ + v8::V8::LowMemoryNotification(); + while (!v8::V8::IdleNotification()) {} +} + +#ifdef QML_GLOBAL_HANDLE_DEBUGGING +#include +static QThreadStorage *> QV8Engine_activeHandles; + +void QV8Engine::registerHandle(void *handle) +{ + if (!handle) { + qWarning("Attempting to register a null handle"); + return; + } + + if (!QV8Engine_activeHandles.hasLocalData()) + QV8Engine_activeHandles.setLocalData(new QSet); + + if (QV8Engine_activeHandles.localData()->contains(handle)) { + qFatal("Handle %p already alive", handle); + } else { + QV8Engine_activeHandles.localData()->insert(handle); + } +} + +void QV8Engine::releaseHandle(void *handle) +{ + if (!handle) + return; + + if (!QV8Engine_activeHandles.hasLocalData()) + QV8Engine_activeHandles.setLocalData(new QSet); + + if (QV8Engine_activeHandles.localData()->contains(handle)) { + QV8Engine_activeHandles.localData()->remove(handle); + } else { + qFatal("Handle %p already dead", handle); + } +} +#endif + +struct QV8EngineRegistrationData +{ + QV8EngineRegistrationData() : extensionCount(0) {} + + QMutex mutex; + int extensionCount; +}; +Q_GLOBAL_STATIC(QV8EngineRegistrationData, registrationData); + +QMutex *QV8Engine::registrationMutex() +{ + return ®istrationData()->mutex; +} + +int QV8Engine::registerExtension() +{ + return registrationData()->extensionCount++; +} + +void QV8Engine::setExtensionData(int index, Deletable *data) +{ + if (m_extensionData.count() <= index) + m_extensionData.resize(index + 1); + + if (m_extensionData.at(index)) + delete m_extensionData.at(index); + + m_extensionData[index] = data; +} + +double QV8Engine::qtDateTimeToJsDate(const QDateTime &dt) +{ + // from QScriptEngine::DateTimeToMs() + if (!dt.isValid()) { + return qSNaN(); + } + QDateTime utc = dt.toUTC(); + QDate date = utc.date(); + QTime time = utc.time(); + QV8DateConverter::JSC::GregorianDateTime tm; + tm.year = date.year() - 1900; + tm.month = date.month() - 1; + tm.monthDay = date.day(); + tm.weekDay = date.dayOfWeek(); + tm.yearDay = date.dayOfYear(); + tm.hour = time.hour(); + tm.minute = time.minute(); + tm.second = time.second(); + return QV8DateConverter::JSC::gregorianDateTimeToMS(tm, time.msec()); +} + +v8::Persistent *QV8Engine::findOwnerAndStrength(QObject *object, bool *shouldBeStrong) +{ + QObject *parent = object->parent(); + if (!parent) { + // if the object has JS ownership, the object's v8object owns the lifetime of the persistent value. + if (QQmlEngine::objectOwnership(object) == QQmlEngine::JavaScriptOwnership) { + *shouldBeStrong = false; + return &(QQmlData::get(object)->v8object); + } + + // no parent, and has CPP ownership - doesn't have an implicit parent. + *shouldBeStrong = true; + return 0; + } + + // if it is owned by CPP, it's root parent may still be owned by JS. + // in that case, the owner of the persistent handle is the root parent's v8object. + while (parent->parent()) + parent = parent->parent(); + + if (QQmlEngine::objectOwnership(parent) == QQmlEngine::JavaScriptOwnership) { + // root parent is owned by JS. It's v8object owns the persistent value in question. + *shouldBeStrong = false; + return &(QQmlData::get(parent)->v8object); + } else { + // root parent has CPP ownership. The persistent value should not be made weak. + *shouldBeStrong = true; + return 0; + } +} + +QDateTime QV8Engine::qtDateTimeFromJsDate(double jsDate) +{ + // from QScriptEngine::MsToDateTime() + if (qIsNaN(jsDate)) + return QDateTime(); + QV8DateConverter::JSC::GregorianDateTime tm; + QV8DateConverter::JSC::msToGregorianDateTime(jsDate, tm); + + // from QScriptEngine::MsFromTime() + int ms = int(::fmod(jsDate, 1000.0)); + if (ms < 0) + ms += int(1000.0); + + QDateTime convertedUTC = QDateTime(QDate(tm.year + 1900, tm.month + 1, tm.monthDay), + QTime(tm.hour, tm.minute, tm.second, ms), Qt::UTC); + return convertedUTC.toLocalTime(); +} + +void QV8Engine::addRelationshipForGC(QObject *object, v8::Persistent handle) +{ + if (handle.IsEmpty()) + return; + + bool handleShouldBeStrong = false; + v8::Persistent *implicitOwner = findOwnerAndStrength(object, &handleShouldBeStrong); + if (handleShouldBeStrong) { + v8::V8::AddImplicitReferences(m_strongReferencer, &handle, 1); + } else if (!implicitOwner->IsEmpty()) { + v8::V8::AddImplicitReferences(*implicitOwner, &handle, 1); + } +} + +void QV8Engine::addRelationshipForGC(QObject *object, QObject *other) +{ + bool handleShouldBeStrong = false; + v8::Persistent *implicitOwner = findOwnerAndStrength(object, &handleShouldBeStrong); + v8::Persistent handle = QQmlData::get(other, true)->v8object; + if (handleShouldBeStrong) { + v8::V8::AddImplicitReferences(m_strongReferencer, &handle, 1); + } else if (!implicitOwner->IsEmpty()) { + v8::V8::AddImplicitReferences(*implicitOwner, &handle, 1); + } +} + +static QThreadStorage perThreadEngineData; + +bool QV8Engine::hasThreadData() +{ + return perThreadEngineData.hasLocalData(); +} + +QV8Engine::ThreadData *QV8Engine::threadData() +{ + Q_ASSERT(perThreadEngineData.hasLocalData()); + return perThreadEngineData.localData(); +} + +void QV8Engine::ensurePerThreadIsolate() +{ + if (!perThreadEngineData.hasLocalData()) + perThreadEngineData.setLocalData(new ThreadData); +} + - void QV8Engine::initDeclarativeGlobalObject() ++void QV8Engine::initQmlGlobalObject() +{ + v8::HandleScope handels; + v8::Context::Scope contextScope(m_context); + initializeGlobal(m_context->Global()); + freezeObject(m_context->Global()); +} + +void QV8Engine::setEngine(QQmlEngine *engine) +{ + m_engine = engine; - initDeclarativeGlobalObject(); ++ initQmlGlobalObject(); +} + +void QV8Engine::setException(v8::Handle value, v8::Handle msg) +{ + m_exception.set(value, msg); +} + +v8::Handle QV8Engine::throwException(v8::Handle value) +{ + setException(value); + v8::ThrowException(value); + return value; +} + +void QV8Engine::clearExceptions() +{ + m_exception.clear(); +} + +v8::Handle QV8Engine::uncaughtException() const +{ + if (!hasUncaughtException()) + return v8::Handle(); + return m_exception; +} + +bool QV8Engine::hasUncaughtException() const +{ + return m_exception; +} + +int QV8Engine::uncaughtExceptionLineNumber() const +{ + return m_exception.lineNumber(); +} + +QStringList QV8Engine::uncaughtExceptionBacktrace() const +{ + return m_exception.backtrace(); +} + +/*! + \internal + Save the current exception on stack so it can be set again later. + \sa QV8Engine::restoreException +*/ +void QV8Engine::saveException() +{ + m_exception.push(); +} + +/*! + \internal + Load a saved exception from stack. Current exception, if exists will be dropped + \sa QV8Engine::saveException +*/ +void QV8Engine::restoreException() +{ + m_exception.pop(); +} + +QV8Engine::Exception::Exception() {} + +QV8Engine::Exception::~Exception() +{ + Q_ASSERT_X(m_stack.isEmpty(), Q_FUNC_INFO, "Some saved exceptions left. Asymetric pop/push found."); + clear(); +} + +void QV8Engine::Exception::set(v8::Handle value, v8::Handle message) +{ + Q_ASSERT_X(!value.IsEmpty(), Q_FUNC_INFO, "Throwing an empty value handle is highly suspected"); + clear(); + m_value = v8::Persistent::New(value); + m_message = v8::Persistent::New(message); +} + +void QV8Engine::Exception::clear() +{ + m_value.Dispose(); + m_value.Clear(); + m_message.Dispose(); + m_message.Clear(); +} + +QV8Engine::Exception::operator bool() const +{ + return !m_value.IsEmpty(); +} + +QV8Engine::Exception::operator v8::Handle() const +{ + Q_ASSERT(*this); + return m_value; +} + +int QV8Engine::Exception::lineNumber() const +{ + if (m_message.IsEmpty()) + return -1; + return m_message->GetLineNumber(); +} + +QStringList QV8Engine::Exception::backtrace() const +{ + if (m_message.IsEmpty()) + return QStringList(); + + QStringList backtrace; + v8::Handle trace = m_message->GetStackTrace(); + if (trace.IsEmpty()) + // FIXME it should not happen (SetCaptureStackTraceForUncaughtExceptions is called). + return QStringList(); + + for (int i = 0; i < trace->GetFrameCount(); ++i) { + v8::Local frame = trace->GetFrame(i); + backtrace.append(QJSConverter::toString(frame->GetFunctionName())); + backtrace.append(QJSConverter::toString(frame->GetFunctionName())); + backtrace.append(QString::fromAscii("()@")); + backtrace.append(QJSConverter::toString(frame->GetScriptName())); + backtrace.append(QString::fromAscii(":")); + backtrace.append(QString::number(frame->GetLineNumber())); + } + return backtrace; +} + +void QV8Engine::Exception::push() +{ + m_stack.push(qMakePair(m_value, m_message)); + m_value.Clear(); + m_message.Clear(); +} + +void QV8Engine::Exception::pop() +{ + Q_ASSERT_X(!m_stack.empty(), Q_FUNC_INFO, "Attempt to load unsaved exception found"); + ValueMessagePair pair = m_stack.pop(); + clear(); + m_value = pair.first; + m_message = pair.second; +} + + +// Converts a QVariantList to JS. +// The result is a new Array object with length equal to the length +// of the QVariantList, and the elements being the QVariantList's +// elements converted to JS, recursively. +v8::Local QV8Engine::variantListToJS(const QVariantList &lst) +{ + v8::Local result = v8::Array::New(lst.size()); + for (int i = 0; i < lst.size(); ++i) + result->Set(i, variantToJS(lst.at(i))); + return result; +} + +// Converts a JS Array object to a QVariantList. +// The result is a QVariantList with length equal to the length +// of the JS Array, and elements being the JS Array's elements +// converted to QVariants, recursively. +QVariantList QV8Engine::variantListFromJS(v8::Handle jsArray) +{ + QVariantList result; + int hash = jsArray->GetIdentityHash(); + if (visitedConversionObjects.contains(hash)) + return result; // Avoid recursion. + v8::HandleScope handleScope; + visitedConversionObjects.insert(hash); + uint32_t length = jsArray->Length(); + for (uint32_t i = 0; i < length; ++i) + result.append(variantFromJS(jsArray->Get(i))); + visitedConversionObjects.remove(hash); + return result; +} + +// Converts a QVariantMap to JS. +// The result is a new Object object with property names being +// the keys of the QVariantMap, and values being the values of +// the QVariantMap converted to JS, recursively. +v8::Local QV8Engine::variantMapToJS(const QVariantMap &vmap) +{ + v8::Local result = v8::Object::New(); + QVariantMap::const_iterator it; + for (it = vmap.constBegin(); it != vmap.constEnd(); ++it) + result->Set(QJSConverter::toString(it.key()), variantToJS(it.value())); + return result; +} + +// Converts a JS Object to a QVariantMap. +// The result is a QVariantMap with keys being the property names +// of the object, and values being the values of the JS object's +// properties converted to QVariants, recursively. +QVariantMap QV8Engine::variantMapFromJS(v8::Handle jsObject) +{ + QVariantMap result; + + v8::HandleScope handleScope; + v8::Handle propertyNames = jsObject->GetPropertyNames(); + uint32_t length = propertyNames->Length(); + if (length == 0) + return result; + + int hash = jsObject->GetIdentityHash(); + if (visitedConversionObjects.contains(hash)) + return result; // Avoid recursion. + + visitedConversionObjects.insert(hash); + // TODO: Only object's own property names. Include non-enumerable properties. + for (uint32_t i = 0; i < length; ++i) { + v8::Handle name = propertyNames->Get(i); + result.insert(QJSConverter::toString(name->ToString()), variantFromJS(jsObject->Get(name))); + } + visitedConversionObjects.remove(hash); + return result; +} + +// Converts the meta-type defined by the given type and data to JS. +// Returns the value if conversion succeeded, an empty handle otherwise. +v8::Handle QV8Engine::metaTypeToJS(int type, const void *data) +{ + Q_ASSERT(data != 0); + v8::Handle result; + + // check if it's one of the types we know + switch (QMetaType::Type(type)) { + case QMetaType::Void: + return v8::Undefined(); + case QMetaType::Bool: + return v8::Boolean::New(*reinterpret_cast(data)); + case QMetaType::Int: + return v8::Int32::New(*reinterpret_cast(data)); + case QMetaType::UInt: + return v8::Uint32::New(*reinterpret_cast(data)); + case QMetaType::LongLong: + return v8::Number::New(double(*reinterpret_cast(data))); + case QMetaType::ULongLong: +#if defined(Q_OS_WIN) && defined(_MSC_FULL_VER) && _MSC_FULL_VER <= 12008804 +#pragma message("** NOTE: You need the Visual Studio Processor Pack to compile support for 64bit unsigned integers.") + return v8::Number::New(double((qlonglong)*reinterpret_cast(data))); +#elif defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) + return v8::Number::New(double((qlonglong)*reinterpret_cast(data))); +#else + return v8::Number::New(double(*reinterpret_cast(data))); +#endif + case QMetaType::Double: + return v8::Number::New(double(*reinterpret_cast(data))); + case QMetaType::QString: + return QJSConverter::toString(*reinterpret_cast(data)); + case QMetaType::Float: + return v8::Number::New(*reinterpret_cast(data)); + case QMetaType::Short: + return v8::Int32::New(*reinterpret_cast(data)); + case QMetaType::UShort: + return v8::Uint32::New(*reinterpret_cast(data)); + case QMetaType::Char: + return v8::Int32::New(*reinterpret_cast(data)); + case QMetaType::UChar: + return v8::Uint32::New(*reinterpret_cast(data)); + case QMetaType::QChar: + return v8::Uint32::New((*reinterpret_cast(data)).unicode()); + case QMetaType::QStringList: + result = QJSConverter::toStringList(*reinterpret_cast(data)); + break; + case QMetaType::QVariantList: + result = variantListToJS(*reinterpret_cast(data)); + break; + case QMetaType::QVariantMap: + result = variantMapToJS(*reinterpret_cast(data)); + break; + case QMetaType::QDateTime: + result = QJSConverter::toDateTime(*reinterpret_cast(data)); + break; + case QMetaType::QDate: + result = QJSConverter::toDateTime(QDateTime(*reinterpret_cast(data))); + break; + case QMetaType::QRegExp: + result = QJSConverter::toRegExp(*reinterpret_cast(data)); + break; + case QMetaType::QObjectStar: + case QMetaType::QWidgetStar: + result = newQObject(*reinterpret_cast(data)); + break; + case QMetaType::QVariant: + result = variantToJS(*reinterpret_cast(data)); + break; + default: + if (type == qMetaTypeId()) { + return QJSValuePrivate::get(*reinterpret_cast(data))->asV8Value(this); + } else { + QByteArray typeName = QMetaType::typeName(type); + if (typeName.endsWith('*') && !*reinterpret_cast(data)) { + return v8::Null(); + } else { + // Fall back to wrapping in a QVariant. + result = newVariant(QVariant(type, data)); + } + } + } + return result; +} + +// Converts a JS value to a meta-type. +// data must point to a place that can store a value of the given type. +// Returns true if conversion succeeded, false otherwise. +bool QV8Engine::metaTypeFromJS(v8::Handle value, int type, void *data) { + // check if it's one of the types we know + switch (QMetaType::Type(type)) { + case QMetaType::Bool: + *reinterpret_cast(data) = value->ToBoolean()->Value(); + return true; + case QMetaType::Int: + *reinterpret_cast(data) = value->ToInt32()->Value(); + return true; + case QMetaType::UInt: + *reinterpret_cast(data) = value->ToUint32()->Value(); + return true; + case QMetaType::LongLong: + *reinterpret_cast(data) = qlonglong(value->ToInteger()->Value()); + return true; + case QMetaType::ULongLong: + *reinterpret_cast(data) = qulonglong(value->ToInteger()->Value()); + return true; + case QMetaType::Double: + *reinterpret_cast(data) = value->ToNumber()->Value(); + return true; + case QMetaType::QString: + if (value->IsUndefined() || value->IsNull()) + *reinterpret_cast(data) = QString(); + else + *reinterpret_cast(data) = QJSConverter::toString(value->ToString()); + return true; + case QMetaType::Float: + *reinterpret_cast(data) = value->ToNumber()->Value(); + return true; + case QMetaType::Short: + *reinterpret_cast(data) = short(value->ToInt32()->Value()); + return true; + case QMetaType::UShort: + *reinterpret_cast(data) = ushort(value->ToInt32()->Value()); // ### QScript::ToUInt16() + return true; + case QMetaType::Char: + *reinterpret_cast(data) = char(value->ToInt32()->Value()); + return true; + case QMetaType::UChar: + *reinterpret_cast(data) = (unsigned char)(value->ToInt32()->Value()); + return true; + case QMetaType::QChar: + if (value->IsString()) { + QString str = QJSConverter::toString(v8::Handle::Cast(value)); + *reinterpret_cast(data) = str.isEmpty() ? QChar() : str.at(0); + } else { + *reinterpret_cast(data) = QChar(ushort(value->ToInt32()->Value())); // ### QScript::ToUInt16() + } + return true; + case QMetaType::QDateTime: + if (value->IsDate()) { + *reinterpret_cast(data) = QJSConverter::toDateTime(v8::Handle::Cast(value)); + return true; + } break; + case QMetaType::QDate: + if (value->IsDate()) { + *reinterpret_cast(data) = QJSConverter::toDateTime(v8::Handle::Cast(value)).date(); + return true; + } break; + case QMetaType::QRegExp: + if (value->IsRegExp()) { + *reinterpret_cast(data) = QJSConverter::toRegExp(v8::Handle::Cast(value)); + return true; + } break; + case QMetaType::QObjectStar: + if (isQObject(value) || value->IsNull()) { + *reinterpret_cast(data) = qtObjectFromJS(value); + return true; + } break; + case QMetaType::QWidgetStar: + if (isQObject(value) || value->IsNull()) { + QObject *qo = qtObjectFromJS(value); + if (!qo || qo->isWidgetType()) { + *reinterpret_cast(data) = reinterpret_cast(qo); + return true; + } + } break; + case QMetaType::QStringList: + if (value->IsArray()) { + *reinterpret_cast(data) = QJSConverter::toStringList(v8::Handle::Cast(value)); + return true; + } break; + case QMetaType::QVariantList: + if (value->IsArray()) { + *reinterpret_cast(data) = variantListFromJS(v8::Handle::Cast(value)); + return true; + } break; + case QMetaType::QVariantMap: + if (value->IsObject()) { + *reinterpret_cast(data) = variantMapFromJS(v8::Handle::Cast(value)); + return true; + } break; + case QMetaType::QVariant: + *reinterpret_cast(data) = variantFromJS(value); + return true; + default: + ; + } + +#if 0 + if (isQtVariant(value)) { + const QVariant &var = variantValue(value); + // ### Enable once constructInPlace() is in qt master. + if (var.userType() == type) { + QMetaType::constructInPlace(type, data, var.constData()); + return true; + } + if (var.canConvert(QVariant::Type(type))) { + QVariant vv = var; + vv.convert(QVariant::Type(type)); + Q_ASSERT(vv.userType() == type); + QMetaType::constructInPlace(type, data, vv.constData()); + return true; + } + + } +#endif + + // Try to use magic; for compatibility with qscriptvalue_cast. + + QByteArray name = QMetaType::typeName(type); + if (convertToNativeQObject(value, name, reinterpret_cast(data))) + return true; + if (isVariant(value) && name.endsWith('*')) { + int valueType = QMetaType::type(name.left(name.size()-1)); + QVariant &var = variantValue(value); + if (valueType == var.userType()) { + // We have T t, T* is requested, so return &t. + *reinterpret_cast(data) = var.data(); + return true; + } else { + // Look in the prototype chain. + v8::Handle proto = value->ToObject()->GetPrototype(); + while (proto->IsObject()) { + bool canCast = false; + if (isVariant(proto)) { + canCast = (type == variantValue(proto).userType()) + || (valueType && (valueType == variantValue(proto).userType())); + } + else if (isQObject(proto)) { + QByteArray className = name.left(name.size()-1); + if (QObject *qobject = qtObjectFromJS(proto)) + canCast = qobject->qt_metacast(className) != 0; + } + if (canCast) { + QByteArray varTypeName = QMetaType::typeName(var.userType()); + if (varTypeName.endsWith('*')) + *reinterpret_cast(data) = *reinterpret_cast(var.data()); + else + *reinterpret_cast(data) = var.data(); + return true; + } + proto = proto->ToObject()->GetPrototype(); + } + } + } else if (value->IsNull() && name.endsWith('*')) { + *reinterpret_cast(data) = 0; + return true; + } else if (type == qMetaTypeId()) { + *reinterpret_cast(data) = QJSValuePrivate::get(new QJSValuePrivate(this, value)); + return true; + } + + return false; +} + +// Converts a QVariant to JS. +v8::Handle QV8Engine::variantToJS(const QVariant &value) +{ + return metaTypeToJS(value.userType(), value.constData()); +} + +// Converts a JS value to a QVariant. +// Null, Undefined -> QVariant() (invalid) +// Boolean -> QVariant(bool) +// Number -> QVariant(double) +// String -> QVariant(QString) +// Array -> QVariantList(...) +// Date -> QVariant(QDateTime) +// RegExp -> QVariant(QRegExp) +// [Any other object] -> QVariantMap(...) +QVariant QV8Engine::variantFromJS(v8::Handle value) +{ + Q_ASSERT(!value.IsEmpty()); + if (value->IsNull() || value->IsUndefined()) + return QVariant(); + if (value->IsBoolean()) + return value->ToBoolean()->Value(); + if (value->IsInt32()) + return value->ToInt32()->Value(); + if (value->IsNumber()) + return value->ToNumber()->Value(); + if (value->IsString()) + return QJSConverter::toString(value->ToString()); + Q_ASSERT(value->IsObject()); + if (value->IsArray()) + return variantListFromJS(v8::Handle::Cast(value)); + if (value->IsDate()) + return QJSConverter::toDateTime(v8::Handle::Cast(value)); + if (value->IsRegExp()) + return QJSConverter::toRegExp(v8::Handle::Cast(value)); + if (isVariant(value)) + return variantValue(value); + if (isQObject(value)) + return qVariantFromValue(qtObjectFromJS(value)); + return variantMapFromJS(value->ToObject()); +} + +bool QV8Engine::convertToNativeQObject(v8::Handle value, + const QByteArray &targetType, + void **result) +{ + if (!targetType.endsWith('*')) + return false; + if (QObject *qobject = qtObjectFromJS(value)) { + int start = targetType.startsWith("const ") ? 6 : 0; + QByteArray className = targetType.mid(start, targetType.size()-start-1); + if (void *instance = qobject->qt_metacast(className)) { + *result = instance; + return true; + } + } + return false; +} + +QObject *QV8Engine::qtObjectFromJS(v8::Handle value) +{ + if (!value->IsObject()) + return 0; + + QV8ObjectResource *r = (QV8ObjectResource *)value->ToObject()->GetExternalResource(); + if (!r) + return 0; + QV8ObjectResource::ResourceType type = r->resourceType(); + if (type == QV8ObjectResource::QObjectType) + return qobjectWrapper()->toQObject(r); + else if (type == QV8ObjectResource::VariantType) { + QVariant variant = variantWrapper()->toVariant(r); + int type = variant.userType(); + if ((type == QMetaType::QObjectStar) || (type == QMetaType::QWidgetStar)) + return *reinterpret_cast(variant.constData()); + } + return 0; +} + + +QVariant &QV8Engine::variantValue(v8::Handle value) +{ + return variantWrapper()->variantValue(value); +} + +// Creates a QVariant wrapper object. +v8::Local QV8Engine::newVariant(const QVariant &value) +{ + return variantWrapper()->newVariant(value); +} + +QScriptPassPointer QV8Engine::evaluate(v8::Handle script, v8::TryCatch& tryCatch) +{ + v8::HandleScope handleScope; + + clearExceptions(); + if (script.IsEmpty()) { + v8::Handle exception = tryCatch.Exception(); + if (exception.IsEmpty()) { + // This is possible on syntax errors like { a:12, b:21 } <- missing "(", ")" around expression. + return new QJSValuePrivate(this); + } + setException(exception, tryCatch.Message()); + return new QJSValuePrivate(this, exception); + } + v8::Handle result; + result = script->Run(); + if (result.IsEmpty()) { + v8::Handle exception = tryCatch.Exception(); + // TODO: figure out why v8 doesn't always produce an exception value + //Q_ASSERT(!exception.IsEmpty()); + if (exception.IsEmpty()) + exception = v8::Exception::Error(v8::String::New("missing exception value")); + setException(exception, tryCatch.Message()); + return new QJSValuePrivate(this, exception); + } + return new QJSValuePrivate(this, result); +} + +QJSValue QV8Engine::scriptValueFromInternal(v8::Handle value) const +{ + if (value.IsEmpty()) + return QJSValuePrivate::get(new QJSValuePrivate(const_cast(this))); + return QJSValuePrivate::get(new QJSValuePrivate(const_cast(this), value)); +} + +QScriptPassPointer QV8Engine::newArray(uint length) +{ + return new QJSValuePrivate(this, v8::Array::New(length)); +} + +void QV8Engine::emitSignalHandlerException() +{ + emit q->signalHandlerException(scriptValueFromInternal(uncaughtException())); +} + +void QV8Engine::startTimer(const QString &timerName) +{ + if (!m_time.isValid()) + m_time.start(); + m_startedTimers[timerName] = m_time.elapsed(); +} + +qint64 QV8Engine::stopTimer(const QString &timerName, bool *wasRunning) +{ + if (!m_startedTimers.contains(timerName)) { + *wasRunning = false; + return 0; + } + *wasRunning = true; + qint64 startedAt = m_startedTimers.take(timerName); + return m_time.elapsed() - startedAt; +} + +int QV8Engine::consoleCountHelper(const QString &file, int line, int column) +{ + const QString key = file + QString::number(line) + QString::number(column); + int number = m_consoleCount.value(key, 0); + number++; + m_consoleCount.insert(key, number); + return number; +} + +void QV8GCCallback::registerGcPrologueCallback() +{ + QV8Engine::ThreadData *td = QV8Engine::threadData(); + if (!td->gcPrologueCallbackRegistered) { + td->gcPrologueCallbackRegistered = true; + v8::V8::AddGCPrologueCallback(QV8GCCallback::garbageCollectorPrologueCallback, v8::kGCTypeMarkSweepCompact); + } +} + +QV8GCCallback::Node::Node(PrologueCallback callback) + : prologueCallback(callback) +{ +} + +QV8GCCallback::Node::~Node() +{ + node.remove(); +} + +/* + Ensure that each persistent handle is strong if it has CPP ownership + and has no implicitly JS owned object owner in its parent chain, and + weak otherwise. + + Any weak handle whose parent object is still alive will have an implicit + reference (between the parent and the handle) added, so that it will + not be collected. + + Note that this callback is registered only for kGCTypeMarkSweepCompact + collection cycles, as it is during collection cycles of that type + in which weak persistent handle callbacks are called when required. + */ +void QV8GCCallback::garbageCollectorPrologueCallback(v8::GCType, v8::GCCallbackFlags) +{ + if (!QV8Engine::hasThreadData()) + return; + + QV8Engine::ThreadData *td = QV8Engine::threadData(); + QV8GCCallback::Node *currNode = td->gcCallbackNodes.first(); + + while (currNode) { + // The client which adds itself to the list is responsible + // for maintaining the correct implicit references in the + // specified callback. + currNode->prologueCallback(currNode); + currNode = td->gcCallbackNodes.next(currNode); + } +} + +void QV8GCCallback::addGcCallbackNode(QV8GCCallback::Node *node) +{ + QV8Engine::ThreadData *td = QV8Engine::threadData(); + td->gcCallbackNodes.insert(node); +} + +QV8Engine::ThreadData::ThreadData() + : gcPrologueCallbackRegistered(false) +{ + if (!v8::Isolate::GetCurrent()) { + isolate = v8::Isolate::New(); + isolate->Enter(); + } else { + isolate = 0; + } +} + +QV8Engine::ThreadData::~ThreadData() +{ + if (isolate) { + isolate->Exit(); + isolate->Dispose(); + isolate = 0; + } +} + +QT_END_NAMESPACE + diff --cc src/qml/qml/v8/qv8engine_impl_p.h index ebb21f8,0000000..7173ae4 mode 100644,000000..100644 --- a/src/qml/qml/v8/qv8engine_impl_p.h +++ b/src/qml/qml/v8/qv8engine_impl_p.h @@@ -1,155 -1,0 +1,173 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** - ** $QT_BEGIN_LICENSE:LGPL-ONLY$ ++** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage - ** This file may be used under the terms of the GNU Lesser - ** General Public License version 2.1 as published by the Free Software - ** Foundation and appearing in the file LICENSE.LGPL included in the - ** packaging of this file. Please review the following information to - ** ensure the GNU Lesser General Public License version 2.1 requirements - ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. - ** - ** If you have questions regarding the use of this file, please contact - ** us via http://www.qt-project.org/. ++** This file may be used under the terms of the GNU Lesser General Public ++** License version 2.1 as published by the Free Software Foundation and ++** appearing in the file LICENSE.LGPL included in the packaging of this ++** file. Please review the following information to ensure the GNU Lesser ++** General Public License version 2.1 requirements will be met: ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU General ++** Public License version 3.0 as published by the Free Software Foundation ++** and appearing in the file LICENSE.GPL included in the packaging of this ++** file. Please review the following information to ensure the GNU General ++** Public License version 3.0 requirements will be met: ++** http://www.gnu.org/copyleft/gpl.html. ++** ++** Other Usage ++** Alternatively, this file may be used in accordance with the terms and ++** conditions contained in a signed written agreement between you and Nokia. ++** ++** ++** ++** ++** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QV8ENGINE_IMPL_P_H +#define QV8ENGINE_IMPL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qv8engine_p.h" +#include "qjsvalue_p.h" +#include "qjsconverter_p.h" +#include "qjsvalueiterator_p.h" + +QT_BEGIN_NAMESPACE + +inline v8::Handle QV8Engine::makeJSValue(bool value) +{ + return value ? v8::True() : v8::False(); +} + +inline v8::Local QV8Engine::makeJSValue(int value) +{ + return v8::Integer::New(value); +} + +inline v8::Local QV8Engine::makeJSValue(uint value) +{ + return v8::Integer::NewFromUnsigned(value); +} + +inline v8::Local QV8Engine::makeJSValue(double value) +{ + return v8::Number::New(value); +} + +inline v8::Handle QV8Engine::makeJSValue(QJSValue::SpecialValue value) { + if (value == QJSValue::NullValue) + return v8::Null(); + return v8::Undefined(); +} + +inline v8::Local QV8Engine::makeJSValue(const QString &value) +{ + return QJSConverter::toString(value); +} + +class QtScriptBagCleaner +{ +public: + template + void operator () (T* value) const + { + value->reinitialize(); + } + void operator () (QJSValueIteratorPrivate *iterator) const + { + iterator->invalidate(); + } +}; + +inline void QV8Engine::registerValue(QJSValuePrivate *data) +{ + m_values.insert(data); +} + +inline void QV8Engine::unregisterValue(QJSValuePrivate *data) +{ + m_values.remove(data); +} + +inline void QV8Engine::invalidateAllValues() +{ + ValueList::iterator it; + for (it = m_values.begin(); it != m_values.end(); it = it.erase()) + (*it)->invalidate(); + Q_ASSERT(m_values.isEmpty()); +} + +inline void QV8Engine::registerValueIterator(QJSValueIteratorPrivate *data) +{ + m_valueIterators.insert(data); +} + +inline void QV8Engine::unregisterValueIterator(QJSValueIteratorPrivate *data) +{ + m_valueIterators.remove(data); +} + +inline void QV8Engine::invalidateAllIterators() +{ + ValueIteratorList::iterator it; + for (it = m_valueIterators.begin(); it != m_valueIterators.end(); it = it.erase()) + (*it)->invalidate(); + Q_ASSERT(m_valueIterators.isEmpty()); +} + +/*! + \internal + \note property can be index (v8::Integer) or a property (v8::String) name, according to ECMA script + property would be converted to a string. +*/ +inline QJSValuePrivate::PropertyFlags QV8Engine::getPropertyFlags(v8::Handle object, v8::Handle property) +{ + QJSValuePrivate::PropertyFlags flags = m_originalGlobalObject.getPropertyFlags(object, property); + return flags; +} + +QScriptPassPointer QV8Engine::evaluate(const QString& program, const QString& fileName, int lineNumber) +{ + v8::TryCatch tryCatch; + v8::ScriptOrigin scriptOrigin(QJSConverter::toString(fileName), v8::Integer::New(lineNumber - 1)); + v8::Handle script; + script = v8::Script::Compile(QJSConverter::toString(program), &scriptOrigin); + if (script.IsEmpty()) { + // TODO: Why don't we get the exception, as with Script::Compile()? + // Q_ASSERT(tryCatch.HasCaught()); + v8::Handle error = v8::Exception::SyntaxError(v8::String::New("")); + setException(error); + return new QJSValuePrivate(this, error); + } + return evaluate(script, tryCatch); +} + +QT_END_NAMESPACE + +#endif // QV8ENGINE_IMPL_P_H diff --cc src/qml/qml/v8/qv8engine_p.h index 22a8d75,0000000..bc57b27 mode 100644,000000..100644 --- a/src/qml/qml/v8/qv8engine_p.h +++ b/src/qml/qml/v8/qv8engine_p.h @@@ -1,631 -1,0 +1,631 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLV8ENGINE_P_H +#define QQMLV8ENGINE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "qjsvalue_p.h" +#include "qjsvalueiterator_p.h" +#include "qscriptoriginalglobalobject_p.h" +#include "qscripttools_p.h" + +#include + +#include "qv8contextwrapper_p.h" +#include "qv8qobjectwrapper_p.h" +#include "qv8stringwrapper_p.h" +#include "qv8typewrapper_p.h" +#include "qv8listwrapper_p.h" +#include "qv8variantwrapper_p.h" +#include "qv8valuetypewrapper_p.h" +#include "qv8sequencewrapper_p.h" + +QT_BEGIN_NAMESPACE + + +// Uncomment the following line to enable global handle debugging. When enabled, all the persistent +// handles allocated using qPersistentNew() (or registered with qPersistentRegsiter()) and disposed +// with qPersistentDispose() are tracked. If you try and do something illegal, like double disposing +// a handle, qFatal() is called. +// #define QML_GLOBAL_HANDLE_DEBUGGING + +#define V8_RESOURCE_TYPE(resourcetype) \ +public: \ + enum { V8ResourceType = QV8ObjectResource:: resourcetype }; \ + virtual QV8ObjectResource::ResourceType resourceType() const { return QV8ObjectResource:: resourcetype; } \ +private: + +#define V8ENGINE() ((QV8Engine *)v8::External::Unwrap(args.Data())) +#define V8FUNCTION(function, engine) v8::FunctionTemplate::New(function, v8::External::Wrap((QV8Engine*)engine))->GetFunction() +#define V8THROW_ERROR(string) { \ + v8::ThrowException(v8::Exception::Error(v8::String::New(string))); \ + return v8::Handle(); \ +} +#define V8THROW_TYPE(string) { \ + v8::ThrowException(v8::Exception::TypeError(v8::String::New(string))); \ + return v8::Handle(); \ +} +#define V8ENGINE_ACCESSOR() ((QV8Engine *)v8::External::Unwrap(info.Data())); +#define V8THROW_ERROR_SETTER(string) { \ + v8::ThrowException(v8::Exception::Error(v8::String::New(string))); \ + return; \ +} + +#define V8_DEFINE_EXTENSION(dataclass, datafunction) \ + static inline dataclass *datafunction(QV8Engine *engine) \ + { \ + static int extensionId = -1; \ + if (extensionId == -1) { \ + QV8Engine::registrationMutex()->lock(); \ + if (extensionId == -1) \ + extensionId = QV8Engine::registerExtension(); \ + QV8Engine::registrationMutex()->unlock(); \ + } \ + dataclass *rv = (dataclass *)engine->extensionData(extensionId); \ + if (!rv) { \ + rv = new dataclass(engine); \ + engine->setExtensionData(extensionId, rv); \ + } \ + return rv; \ + } \ + + +class QV8Engine; +class QV8ObjectResource : public v8::Object::ExternalResource +{ +public: + QV8ObjectResource(QV8Engine *engine) : engine(engine) { Q_ASSERT(engine); } + enum ResourceType { ContextType, QObjectType, TypeType, ListType, VariantType, + ValueTypeType, XMLHttpRequestType, DOMNodeType, SQLDatabaseType, + ListModelType, Context2DType, Context2DStyleType, Context2DPixelArrayType, + ParticleDataType, SignalHandlerType, IncubatorType, VisualDataItemType, + SequenceType, LocaleDataType }; + virtual ResourceType resourceType() const = 0; + + QV8Engine *engine; +}; + +template +inline T *v8_resource_cast(v8::Handle object) { + QV8ObjectResource *resource = static_cast(object->GetExternalResource()); + return (resource && (quint32)resource->resourceType() == (quint32)T::V8ResourceType)?static_cast(resource):0; +} + +template +inline T *v8_resource_check(v8::Handle object) { + T *resource = static_cast(object->GetExternalResource()); + Q_ASSERT(resource && resource->resourceType() == (quint32)T::V8ResourceType); + return resource; +} + +// Used to allow a QObject method take and return raw V8 handles without having to expose +// v8 in the public API. +// Use like this: +// class MyClass : public QObject { +// Q_OBJECT +// ... +// Q_INVOKABLE void myMethod(QQmlV8Function*); +// }; +// The QQmlV8Function - and consequently the arguments and return value - only remains +// valid during the call. If the return value isn't set within myMethod(), the will return +// undefined. +class QV8Engine; +class QQmlV8Function +{ +public: + int Length() const { return _ac; } + v8::Local operator[](int idx) { return (*_a)->Get(idx); } + QQmlContextData *context() { return _c; } + v8::Handle qmlGlobal() { return *_g; } + void returnValue(v8::Handle rv) { *_r = rv; } + QV8Engine *engine() const { return _e; } +private: + friend class QV8QObjectWrapper; + QQmlV8Function(); + QQmlV8Function(const QQmlV8Function &); + QQmlV8Function &operator=(const QQmlV8Function &); + + QQmlV8Function(int length, v8::Handle &args, + v8::Handle &rv, v8::Handle &global, + QQmlContextData *c, QV8Engine *e) + : _ac(length), _a(&args), _r(&rv), _g(&global), _c(c), _e(e) {} + + int _ac; + v8::Handle *_a; + v8::Handle *_r; + v8::Handle *_g; + QQmlContextData *_c; + QV8Engine *_e; +}; + +class QQmlV8Handle +{ +public: + QQmlV8Handle() : d(0) {} + QQmlV8Handle(const QQmlV8Handle &other) : d(other.d) {} + QQmlV8Handle &operator=(const QQmlV8Handle &other) { d = other.d; return *this; } + + static QQmlV8Handle fromHandle(v8::Handle h) { + return QQmlV8Handle(*h); + } + v8::Handle toHandle() const { + return v8::Handle((v8::Value *)d); + } +private: + QQmlV8Handle(void *d) : d(d) {} + void *d; +}; + +class QObject; +class QQmlEngine; +class QQmlValueType; +class QNetworkAccessManager; +class QQmlContextData; + +class Q_AUTOTEST_EXPORT QV8GCCallback +{ +private: + class ThreadData; +public: + static void garbageCollectorPrologueCallback(v8::GCType, v8::GCCallbackFlags); + static void registerGcPrologueCallback(); + + class Q_AUTOTEST_EXPORT Node { + public: + typedef void (*PrologueCallback)(Node *node); + Node(PrologueCallback callback); + ~Node(); + + QIntrusiveListNode node; + PrologueCallback prologueCallback; + }; + + static void addGcCallbackNode(Node *node); +}; + +class Q_QML_EXPORT QV8Engine +{ +public: + static QV8Engine* get(QJSEngine* q) { Q_ASSERT(q); return q->handle(); } + static QJSEngine* get(QV8Engine* d) { Q_ASSERT(d); return d->q; } + + QV8Engine(QJSEngine* qq,QJSEngine::ContextOwnership ownership = QJSEngine::CreateNewContext); + virtual ~QV8Engine(); + + // This enum should be in sync with QQmlEngine::ObjectOwnership + enum ObjectOwnership { CppOwnership, JavaScriptOwnership }; + + struct Deletable { + virtual ~Deletable() {} + }; + + class Exception + { + typedef QPair, v8::Persistent > ValueMessagePair; + + v8::Persistent m_value; + v8::Persistent m_message; + QStack m_stack; + + Q_DISABLE_COPY(Exception) + public: + inline Exception(); + inline ~Exception(); + inline void set(v8::Handle value, v8::Handle message); + inline void clear(); + inline operator bool() const; + inline operator v8::Handle() const; + inline int lineNumber() const; + inline QStringList backtrace() const; + + inline void push(); + inline void pop(); + }; + - void initDeclarativeGlobalObject(); ++ void initQmlGlobalObject(); + void setEngine(QQmlEngine *engine); + QQmlEngine *engine() { return m_engine; } + v8::Local global() { return m_context->Global(); } + v8::Handle context() const { return m_context; } + + inline void registerValue(QJSValuePrivate *data); + inline void unregisterValue(QJSValuePrivate *data); + inline void invalidateAllValues(); + + inline void registerValueIterator(QJSValueIteratorPrivate *data); + inline void unregisterValueIterator(QJSValueIteratorPrivate *data); + inline void invalidateAllIterators(); + + QV8ContextWrapper *contextWrapper() { return &m_contextWrapper; } + QV8QObjectWrapper *qobjectWrapper() { return &m_qobjectWrapper; } + QV8TypeWrapper *typeWrapper() { return &m_typeWrapper; } + QV8ListWrapper *listWrapper() { return &m_listWrapper; } + QV8VariantWrapper *variantWrapper() { return &m_variantWrapper; } + QV8ValueTypeWrapper *valueTypeWrapper() { return &m_valueTypeWrapper; } + QV8SequenceWrapper *sequenceWrapper() { return &m_sequenceWrapper; } + + void *xmlHttpRequestData() { return m_xmlHttpRequestData; } + + Deletable *listModelData() { return m_listModelData; } + void setListModelData(Deletable *d) { if (m_listModelData) delete m_listModelData; m_listModelData = d; } + + QQmlContextData *callingContext(); + + v8::Local getOwnPropertyNames(v8::Handle); + inline QJSValuePrivate::PropertyFlags getPropertyFlags(v8::Handle object, v8::Handle property); + void freezeObject(v8::Handle); + + inline QString toString(v8::Handle string); + inline QString toString(v8::Handle string); + static QString toStringStatic(v8::Handle); + static QString toStringStatic(v8::Handle); + static inline bool startsWithUpper(v8::Handle); + + QVariant toVariant(v8::Handle, int typeHint); + v8::Handle fromVariant(const QVariant &); + inline bool isVariant(v8::Handle); + + // Compile \a source (from \a fileName at \a lineNumber) in QML mode + v8::Local qmlModeCompile(const QString &source, + const QString &fileName = QString(), + int lineNumber = 1); + v8::Local qmlModeCompile(const char *source, int sourceLength = -1, + const QString &fileName = QString(), + int lineNumber = 1); + + // Return the QML global "scope" object for the \a ctxt context and \a scope object. + inline v8::Local qmlScope(QQmlContextData *ctxt, QObject *scope); + + // Return a JS wrapper for the given QObject \a object + inline v8::Handle newQObject(QObject *object); + inline v8::Handle newQObject(QObject *object, const ObjectOwnership ownership); + inline bool isQObject(v8::Handle); + inline QObject *toQObject(v8::Handle); + + // Return a JS string for the given QString \a string + inline v8::Local toString(const QString &string); + + // Create a new value type object + inline v8::Handle newValueType(QObject *, int coreIndex, QQmlValueType *); + inline v8::Handle newValueType(const QVariant &, QQmlValueType *); + + // Create a new sequence type object + inline v8::Handle newSequence(int sequenceType, QObject *, int coreIndex, bool *succeeded); + + // Create a new QVariant object. This doesn't examine the type of the variant, but always returns + // a QVariant wrapper + inline v8::Handle newQVariant(const QVariant &); + + // Return the network access manager for this engine. By default this returns the network + // access manager of the QQmlEngine. It is overridden in the case of a threaded v8 + // instance (like in WorkerScript). + virtual QNetworkAccessManager *networkAccessManager(); + + // Return the list of illegal id names (the names of the properties on the global object) + const QStringHash &illegalNames() const; + + inline void collectGarbage() { gc(); } + static void gc(); + + void clearExceptions(); + void setException(v8::Handle value, v8::Handle message = v8::Handle()); + v8::Handle throwException(v8::Handle value); + bool hasUncaughtException() const; + int uncaughtExceptionLineNumber() const; + QStringList uncaughtExceptionBacktrace() const; + v8::Handle uncaughtException() const; + void saveException(); + void restoreException(); + +#ifdef QML_GLOBAL_HANDLE_DEBUGGING + // Used for handle debugging + static void registerHandle(void *); + static void releaseHandle(void *); +#endif + + static QMutex *registrationMutex(); + static int registerExtension(); + + inline Deletable *extensionData(int) const; + void setExtensionData(int, Deletable *); + + inline v8::Handle makeJSValue(bool value); + inline v8::Local makeJSValue(int value); + inline v8::Local makeJSValue(uint value); + inline v8::Local makeJSValue(double value); + inline v8::Handle makeJSValue(QJSValue::SpecialValue value); + inline v8::Local makeJSValue(const QString &value); + + inline QScriptPassPointer evaluate(const QString &program, const QString &fileName = QString(), int lineNumber = 1); + QScriptPassPointer evaluate(v8::Handle script, v8::TryCatch& tryCatch); + + QScriptPassPointer newArray(uint length); + v8::Local newVariant(const QVariant &variant); + + v8::Local variantListToJS(const QVariantList &lst); + QVariantList variantListFromJS(v8::Handle jsArray); + + v8::Local variantMapToJS(const QVariantMap &vmap); + QVariantMap variantMapFromJS(v8::Handle jsObject); + + v8::Handle variantToJS(const QVariant &value); + QVariant variantFromJS(v8::Handle value); + + v8::Handle metaTypeToJS(int type, const void *data); + bool metaTypeFromJS(v8::Handle value, int type, void *data); + + bool convertToNativeQObject(v8::Handle value, + const QByteArray &targetType, + void **result); + + QVariant &variantValue(v8::Handle value); + + QJSValue scriptValueFromInternal(v8::Handle) const; + + void emitSignalHandlerException(); + + // used for console.time(), console.timeEnd() + void startTimer(const QString &timerName); + qint64 stopTimer(const QString &timerName, bool *wasRunning); + + // used for console.count() + int consoleCountHelper(const QString &file, int line, int column); + + QObject *qtObjectFromJS(v8::Handle value); + QSet visitedConversionObjects; + + static QDateTime qtDateTimeFromJsDate(double jsDate); + + void addRelationshipForGC(QObject *object, v8::Persistent handle); + void addRelationshipForGC(QObject *object, QObject *other); + + struct ThreadData { + ThreadData(); + ~ThreadData(); + v8::Isolate* isolate; + bool gcPrologueCallbackRegistered; + QIntrusiveList gcCallbackNodes; + }; + + static bool hasThreadData(); + static ThreadData* threadData(); + static void ensurePerThreadIsolate(); + + v8::Persistent m_strongReferencer; + +protected: + QJSEngine* q; + QQmlEngine *m_engine; + bool m_ownsV8Context; + v8::Persistent m_context; + QScriptOriginalGlobalObject m_originalGlobalObject; + + QV8StringWrapper m_stringWrapper; + QV8ContextWrapper m_contextWrapper; + QV8QObjectWrapper m_qobjectWrapper; + QV8TypeWrapper m_typeWrapper; + QV8ListWrapper m_listWrapper; + QV8VariantWrapper m_variantWrapper; + QV8ValueTypeWrapper m_valueTypeWrapper; + QV8SequenceWrapper m_sequenceWrapper; + + v8::Persistent m_getOwnPropertyNames; + v8::Persistent m_freezeObject; + + void *m_xmlHttpRequestData; + + QVector m_extensionData; + Deletable *m_listModelData; + + QStringHash m_illegalNames; + + Exception m_exception; + + QElapsedTimer m_time; + QHash m_startedTimers; + + QHash m_consoleCount; + + QVariant toBasicVariant(v8::Handle); + + void initializeGlobal(v8::Handle); + + double qtDateTimeToJsDate(const QDateTime &dt); + +private: + static v8::Persistent *findOwnerAndStrength(QObject *object, bool *shouldBeStrong); + + typedef QScriptIntrusiveList ValueList; + ValueList m_values; + typedef QScriptIntrusiveList ValueIteratorList; + ValueIteratorList m_valueIterators; + + Q_DISABLE_COPY(QV8Engine) +}; + +// Allocate a new Persistent handle. *ALL* persistent handles in QML must be allocated +// using this method. +template +v8::Persistent qPersistentNew(v8::Handle that) +{ + v8::Persistent rv = v8::Persistent::New(that); +#ifdef QML_GLOBAL_HANDLE_DEBUGGING + QV8Engine::registerHandle(*rv); +#endif + return rv; +} + +// Register a Persistent handle that was returned to you by V8 (such as by +// v8::Context::New). This allows us to do handle tracking on these handles too. +template +void qPersistentRegister(v8::Persistent handle) +{ +#ifdef QML_GLOBAL_HANDLE_DEBUGGING + QV8Engine::registerHandle(*handle); +#else + Q_UNUSED(handle); +#endif +} + +// Dispose and clear a persistent handle. *ALL* persistent handles in QML must be +// disposed using this method. +template +void qPersistentDispose(v8::Persistent &that) +{ +#ifdef QML_GLOBAL_HANDLE_DEBUGGING + QV8Engine::releaseHandle(*that); +#endif + that.Dispose(); + that.Clear(); +} + +QString QV8Engine::toString(v8::Handle string) +{ + return m_stringWrapper.toString(string->ToString()); +} + +QString QV8Engine::toString(v8::Handle string) +{ + return m_stringWrapper.toString(string); +} + +bool QV8Engine::isVariant(v8::Handle value) +{ + return m_variantWrapper.isVariant(value); +} + +v8::Local QV8Engine::qmlScope(QQmlContextData *ctxt, QObject *scope) +{ + return m_contextWrapper.qmlScope(ctxt, scope); +} + +bool QV8Engine::isQObject(v8::Handle obj) +{ + return obj->IsObject()?m_qobjectWrapper.isQObject(v8::Handle::Cast(obj)):false; +} + +QObject *QV8Engine::toQObject(v8::Handle obj) +{ + return obj->IsObject()?m_qobjectWrapper.toQObject(v8::Handle::Cast(obj)):0; +} + +v8::Handle QV8Engine::newQObject(QObject *object) +{ + return m_qobjectWrapper.newQObject(object); +} + +v8::Handle QV8Engine::newQObject(QObject *object, const ObjectOwnership ownership) +{ + if (!object) + return v8::Null(); + + v8::Handle result = newQObject(object); + QQmlData *ddata = QQmlData::get(object, true); + if (ownership == JavaScriptOwnership && ddata) { + ddata->indestructible = false; + ddata->explicitIndestructibleSet = true; + } + return result; +} + +v8::Local QV8Engine::toString(const QString &string) +{ + return m_stringWrapper.toString(string); +} + +v8::Handle QV8Engine::newValueType(QObject *object, int property, QQmlValueType *type) +{ + return m_valueTypeWrapper.newValueType(object, property, type); +} + +v8::Handle QV8Engine::newValueType(const QVariant &value, QQmlValueType *type) +{ + return m_valueTypeWrapper.newValueType(value, type); +} + +v8::Handle QV8Engine::newSequence(int sequenceType, QObject *object, int property, bool *succeeded) +{ + return m_sequenceWrapper.newSequence(sequenceType, object, property, succeeded); +} + +// XXX Can this be made more optimal? It is called prior to resolving each and every +// unqualified name in QV8ContextWrapper. +bool QV8Engine::startsWithUpper(v8::Handle string) +{ + uint16_t c = string->GetCharacter(0); + return (c >= 'A' && c <= 'Z') || + (c > 127 && QChar::category(c) == QChar::Letter_Uppercase); +} + +QV8Engine::Deletable *QV8Engine::extensionData(int index) const +{ + if (index < m_extensionData.count()) + return m_extensionData[index]; + else + return 0; +} + +QT_END_NAMESPACE + +#endif // QQMLV8ENGINE_P_H diff --cc src/qml/qml/v8/qv8qobjectwrapper.cpp index b84ae33,0000000..78b2cb7 mode 100644,000000..100644 --- a/src/qml/qml/v8/qv8qobjectwrapper.cpp +++ b/src/qml/qml/v8/qv8qobjectwrapper.cpp @@@ -1,2113 -1,0 +1,2113 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qv8qobjectwrapper_p.h" +#include "qv8contextwrapper_p.h" +#include "qv8engine_p.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +Q_DECLARE_METATYPE(QJSValue); +Q_DECLARE_METATYPE(QQmlV8Handle); + +QT_BEGIN_NAMESPACE + +#if defined(__GNUC__) +# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 +// The code in this file does not violate strict aliasing, but GCC thinks it does +// so turn off the warnings for us to have a clean build +# pragma GCC diagnostic ignored "-Wstrict-aliasing" +# endif +#endif + +#define QOBJECT_TOSTRING_INDEX -2 +#define QOBJECT_DESTROY_INDEX -3 + +// XXX TODO: Need to review all calls to QQmlEngine *engine() to confirm QObjects work +// correctly in a worker thread + +class QV8QObjectResource : public QV8ObjectResource +{ + V8_RESOURCE_TYPE(QObjectType); + +public: + QV8QObjectResource(QV8Engine *engine, QObject *object); + + QQmlGuard object; +}; + +class QV8QObjectInstance : public QQmlGuard +{ +public: + QV8QObjectInstance(QObject *o, QV8QObjectWrapper *w) + : QQmlGuard(o), wrapper(w) + { + } + + ~QV8QObjectInstance() + { + qPersistentDispose(v8object); + } + + virtual void objectDestroyed(QObject *o) + { + if (wrapper) + wrapper->m_taintedObjects.remove(o); + delete this; + } + + v8::Persistent v8object; + QV8QObjectWrapper *wrapper; +}; + +class QV8SignalHandlerResource : public QV8ObjectResource +{ + V8_RESOURCE_TYPE(SignalHandlerType) +public: + QV8SignalHandlerResource(QV8Engine *engine, QObject *object, int index); + + QQmlGuard object; + int index; +}; + +namespace { + +template +class MaxSizeOf5 { + template + struct SMax { + static const size_t Size = sizeof(Z) > sizeof(X) ? sizeof(Z) : sizeof(X); + }; +public: + static const size_t Size = SMax > > >::Size; +}; + +struct CallArgument { + inline CallArgument(); + inline ~CallArgument(); + inline void *dataPtr(); + + inline void initAsType(int type); + inline void fromValue(int type, QV8Engine *, v8::Handle); + inline v8::Handle toValue(QV8Engine *); + +private: + CallArgument(const CallArgument &); + + inline void cleanup(); + + union { + float floatValue; + double doubleValue; + quint32 intValue; + bool boolValue; + QObject *qobjectPtr; + + char allocData[MaxSizeOf5, + QJSValue, + QQmlV8Handle>::Size]; + qint64 q_for_alignment; + }; + + // Pointers to allocData + union { + QString *qstringPtr; + QVariant *qvariantPtr; + QList *qlistPtr; + QJSValue *qjsValuePtr; + QQmlV8Handle *handlePtr; + }; + + int type; +}; +} + +QV8QObjectResource::QV8QObjectResource(QV8Engine *engine, QObject *object) +: QV8ObjectResource(engine), object(object) +{ +} + +QV8SignalHandlerResource::QV8SignalHandlerResource(QV8Engine *engine, QObject *object, int index) +: QV8ObjectResource(engine), object(object), index(index) +{ +} + +static QAtomicInt objectIdCounter(1); + +QV8QObjectWrapper::QV8QObjectWrapper() +: m_engine(0), m_id(objectIdCounter.fetchAndAddOrdered(1)) +{ +} + +QV8QObjectWrapper::~QV8QObjectWrapper() +{ + for (TaintedHash::Iterator iter = m_taintedObjects.begin(); + iter != m_taintedObjects.end(); + ++iter) { + (*iter)->wrapper = 0; + } + m_taintedObjects.clear(); +} + +void QV8QObjectWrapper::destroy() +{ + qDeleteAll(m_connections); + m_connections.clear(); + + qPersistentDispose(m_hiddenObject); + qPersistentDispose(m_destroySymbol); + qPersistentDispose(m_toStringSymbol); + qPersistentDispose(m_signalHandlerConstructor); + qPersistentDispose(m_methodConstructor); + qPersistentDispose(m_constructor); +} + +struct ReadAccessor { + static inline void Indirect(QObject *object, const QQmlPropertyData &property, + void *output, QQmlNotifier **n) + { + Q_ASSERT(n == 0); + Q_UNUSED(n); + + void *args[] = { output, 0 }; + QMetaObject::metacall(object, QMetaObject::ReadProperty, property.coreIndex, args); + } + + static inline void Direct(QObject *object, const QQmlPropertyData &property, + void *output, QQmlNotifier **n) + { + Q_ASSERT(n == 0); + Q_UNUSED(n); + + void *args[] = { output, 0 }; + object->qt_metacall(QMetaObject::ReadProperty, property.coreIndex, args); + } + + static inline void Accessor(QObject *object, const QQmlPropertyData &property, + void *output, QQmlNotifier **n) + { + Q_ASSERT(property.accessors); + + property.accessors->read(object, property.accessorData, output); + if (n) property.accessors->notifier(object, property.accessorData, n); + } +}; + +static inline v8::Handle valueToHandle(QV8Engine *, int v) +{ return v8::Integer::New(v); } +static inline v8::Handle valueToHandle(QV8Engine *, uint v) +{ return v8::Integer::NewFromUnsigned(v); } +static inline v8::Handle valueToHandle(QV8Engine *, bool v) +{ return v8::Boolean::New(v); } +static inline v8::Handle valueToHandle(QV8Engine *e, const QString &v) +{ return e->toString(v); } +static inline v8::Handle valueToHandle(QV8Engine *, float v) +{ return v8::Number::New(v); } +static inline v8::Handle valueToHandle(QV8Engine *, double v) +{ return v8::Number::New(v); } +static inline v8::Handle valueToHandle(QV8Engine *e, QObject *v) +{ return e->newQObject(v); } + +template +static v8::Handle GenericValueGetter(v8::Local, const v8::AccessorInfo &info) +{ + v8::Handle This = info.This(); + QV8QObjectResource *resource = v8_resource_check(This); + + QObject *object = resource->object; + if (!object) return v8::Undefined(); + + QQmlPropertyData *property = + (QQmlPropertyData *)v8::External::Unwrap(info.Data()); + + QQmlEngine *engine = resource->engine->engine(); + QQmlEnginePrivate *ep = engine?QQmlEnginePrivate::get(engine):0; + + T value = T(); + + if (ep && ep->propertyCapture) { + if (ReadFunction == ReadAccessor::Accessor && property->accessors->notifier) { + QQmlNotifier *notifier = 0; + ReadFunction(object, *property, &value, ¬ifier); + if (notifier) ep->captureProperty(notifier); + } else if (!property->isConstant()) { + ep->captureProperty(object, property->coreIndex, property->notifyIndex); + ReadFunction(object, *property, &value, 0); + } else { + ReadFunction(object, *property, &value, 0); + } + } else { + ReadFunction(object, *property, &value, 0); + } + + return valueToHandle(resource->engine, value); +} + +#define FAST_GETTER_FUNCTION(property, cpptype) \ + (property->hasAccessors()?((v8::AccessorGetter)GenericValueGetter):(property->isDirect()?((v8::AccessorGetter)GenericValueGetter):((v8::AccessorGetter)GenericValueGetter))) + +static quint32 toStringHash = -1; +static quint32 destroyHash = -1; + +void QV8QObjectWrapper::init(QV8Engine *engine) +{ + m_engine = engine; + + m_toStringSymbol = qPersistentNew(v8::String::NewSymbol("toString")); + m_destroySymbol = qPersistentNew(v8::String::NewSymbol("destroy")); + m_hiddenObject = qPersistentNew(v8::Object::New()); + + m_toStringString = QHashedV8String(m_toStringSymbol); + m_destroyString = QHashedV8String(m_destroySymbol); + + toStringHash = m_toStringString.hash(); + destroyHash = m_destroyString.hash(); + + { + v8::Local ft = v8::FunctionTemplate::New(); + ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter, Query, 0, Enumerator); + ft->InstanceTemplate()->SetHasExternalResource(true); + m_constructor = qPersistentNew(ft->GetFunction()); + } + { + v8::ScriptOrigin origin(m_hiddenObject); // Hack to allow us to identify these functions +#define CREATE_FUNCTION_SOURCE \ + "(function(method) { "\ + "return (function(object, data, qmlglobal) { "\ + "return (function() { "\ + "return method(object, data, qmlglobal, arguments.length, arguments); "\ + "});"\ + "});"\ + "})" + v8::Local script = v8::Script::New(v8::String::New(CREATE_FUNCTION_SOURCE), &origin, 0, + v8::Handle(), v8::Script::NativeMode); +#undef CREATE_FUNCTION_SOURCE + v8::Local fn = v8::Local::Cast(script->Run()); + v8::Handle invokeFn = v8::FunctionTemplate::New(Invoke)->GetFunction(); + v8::Handle args[] = { invokeFn }; + v8::Local createFn = v8::Local::Cast(fn->Call(engine->global(), 1, args)); + m_methodConstructor = qPersistentNew(createFn); + } + + v8::Local connect = V8FUNCTION(Connect, engine); + v8::Local disconnect = V8FUNCTION(Disconnect, engine); + + { + v8::Local ft = v8::FunctionTemplate::New(); + ft->InstanceTemplate()->SetHasExternalResource(true); + ft->PrototypeTemplate()->Set(v8::String::New("connect"), connect, v8::DontEnum); + ft->PrototypeTemplate()->Set(v8::String::New("disconnect"), disconnect, v8::DontEnum); + m_signalHandlerConstructor = qPersistentNew(ft->GetFunction()); + } + + { + v8::Local prototype = engine->global()->Get(v8::String::New("Function"))->ToObject()->Get(v8::String::New("prototype"))->ToObject(); + prototype->Set(v8::String::New("connect"), connect, v8::DontEnum); + prototype->Set(v8::String::New("disconnect"), disconnect, v8::DontEnum); + } +} + +bool QV8QObjectWrapper::isQObject(v8::Handle obj) +{ + return v8_resource_cast(obj) != 0; +} + +QObject *QV8QObjectWrapper::toQObject(v8::Handle obj) +{ + QV8QObjectResource *r = v8_resource_cast(obj); + return r?r->object:0; +} + +// r *MUST* be a QV8ObjectResource (r->type() == QV8ObjectResource::QObjectType) +QObject *QV8QObjectWrapper::toQObject(QV8ObjectResource *r) +{ + Q_ASSERT(r->resourceType() == QV8ObjectResource::QObjectType); + return static_cast(r)->object; +} + +// Load value properties +template +static v8::Handle LoadProperty(QV8Engine *engine, QObject *object, + const QQmlPropertyData &property, + QQmlNotifier **notifier) +{ + Q_ASSERT(!property.isFunction()); + + if (property.isQObject()) { + QObject *rv = 0; + ReadFunction(object, property, &rv, notifier); + return engine->newQObject(rv); + } else if (property.isQList()) { + return engine->listWrapper()->newList(object, property.coreIndex, property.propType); + } else if (property.propType == QMetaType::QReal) { + qreal v = 0; + ReadFunction(object, property, &v, notifier); + return valueToHandle(engine, v); + } else if (property.propType == QMetaType::Int || property.isEnum()) { + int v = 0; + ReadFunction(object, property, &v, notifier); + return valueToHandle(engine, v); + } else if (property.propType == QMetaType::Bool) { + bool v = false; + ReadFunction(object, property, &v, notifier); + return valueToHandle(engine, v); + } else if (property.propType == QMetaType::QString) { + QString v; + ReadFunction(object, property, &v, notifier); + return valueToHandle(engine, v); + } else if (property.propType == QMetaType::UInt) { + uint v = 0; + ReadFunction(object, property, &v, notifier); + return valueToHandle(engine, v); + } else if (property.propType == QMetaType::Float) { + float v = 0; + ReadFunction(object, property, &v, notifier); + return valueToHandle(engine, v); + } else if (property.propType == QMetaType::Double) { + double v = 0; + ReadFunction(object, property, &v, notifier); + return valueToHandle(engine, v); + } else if (property.isV8Handle()) { + QQmlV8Handle handle; + ReadFunction(object, property, &handle, notifier); + return handle.toHandle(); + } else if (property.isQVariant()) { + QVariant v; + ReadFunction(object, property, &v, notifier); + return engine->fromVariant(v); + } else if (QQmlValueTypeFactory::isValueType((uint)property.propType) + && engine->engine()) { + Q_ASSERT(notifier == 0); + + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine->engine()); + QQmlValueType *valueType = ep->valueTypes[property.propType]; + if (valueType) + return engine->newValueType(object, property.coreIndex, valueType); + } else { + Q_ASSERT(notifier == 0); + + // see if it's a sequence type + bool succeeded = false; + v8::Handle retn = engine->newSequence(property.propType, object, property.coreIndex, + &succeeded); + if (succeeded) + return retn; + } + + if (property.propType == QVariant::Invalid) { + QMetaProperty p = object->metaObject()->property(property.coreIndex); + qWarning("QMetaProperty::read: Unable to handle unregistered datatype '%s' for property " + "'%s::%s'", p.typeName(), object->metaObject()->className(), p.name()); + return v8::Undefined(); + } else { + QVariant v(property.propType, (void *)0); + ReadFunction(object, property, v.data(), notifier); + return engine->fromVariant(v); + } +} + +v8::Handle QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject *object, + v8::Handle *objectHandle, + const QHashedV8String &property, + QV8QObjectWrapper::RevisionMode revisionMode) +{ + // XXX More recent versions of V8 introduced "Callable" objects. It is possible that these + // will be a faster way of creating QObject method objects. + struct MethodClosure { + static v8::Handle create(QV8Engine *engine, QObject *object, + v8::Handle *objectHandle, + int index) { + v8::Handle argv[] = { + objectHandle?*objectHandle:engine->newQObject(object), + v8::Integer::New(index) + }; + return engine->qobjectWrapper()->m_methodConstructor->Call(engine->global(), 2, argv); + } + static v8::Handle createWithGlobal(QV8Engine *engine, QObject *object, + v8::Handle *objectHandle, + int index) { + v8::Handle argv[] = { + objectHandle?*objectHandle:engine->newQObject(object), + v8::Integer::New(index), + v8::Context::GetCallingQmlGlobal() + }; + return engine->qobjectWrapper()->m_methodConstructor->Call(engine->global(), 3, argv); + } + }; + + { + // Comparing the hash first actually makes a measurable difference here, at least on x86 + quint32 hash = property.hash(); + if (hash == toStringHash && engine->qobjectWrapper()->m_toStringString == property) { + return MethodClosure::create(engine, object, objectHandle, QOBJECT_TOSTRING_INDEX); + } else if (hash == destroyHash && engine->qobjectWrapper()->m_destroyString == property) { + return MethodClosure::create(engine, object, objectHandle, QOBJECT_DESTROY_INDEX); + } + } + + QQmlPropertyData local; + QQmlPropertyData *result = 0; + { + QQmlData *ddata = QQmlData::get(object, false); + if (ddata && ddata->propertyCache) + result = ddata->propertyCache->property(property); + else + result = QQmlPropertyCache::property(engine->engine(), object, property, local); + } + + if (!result) + return v8::Handle(); + - if (revisionMode == QV8QObjectWrapper::CheckRevision && result->revision != 0) { ++ if (revisionMode == QV8QObjectWrapper::CheckRevision && result->hasRevision()) { + QQmlData *ddata = QQmlData::get(object); + if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(result)) + return v8::Handle(); + } + + if (result->isFunction()) { + if (result->isVMEFunction()) { + return ((QQmlVMEMetaObject *)(object->metaObject()))->vmeMethod(result->coreIndex); + } else if (result->isV8Function()) { + return MethodClosure::createWithGlobal(engine, object, objectHandle, result->coreIndex); + } else if (result->isSignalHandler()) { + v8::Local handler = engine->qobjectWrapper()->m_signalHandlerConstructor->NewInstance(); + QV8SignalHandlerResource *r = new QV8SignalHandlerResource(engine, object, result->coreIndex); + handler->SetExternalResource(r); + return handler; + } else { + return MethodClosure::create(engine, object, objectHandle, result->coreIndex); + } + } + + QQmlEnginePrivate *ep = + engine->engine()?QQmlEnginePrivate::get(engine->engine()):0; + + if (result->hasAccessors()) { + QQmlNotifier *n = 0; + QQmlNotifier **nptr = 0; + + if (ep && ep->propertyCapture && result->accessors->notifier) + nptr = &n; + + v8::Handle rv = LoadProperty(engine, object, *result, nptr); + + if (result->accessors->notifier) { + if (n) ep->captureProperty(n); + } else { + ep->captureProperty(object, result->coreIndex, result->notifyIndex); + } + + return rv; + } + + if (ep && !result->isConstant()) { + + if (result->coreIndex == 0) + ep->captureProperty(QQmlData::get(object, true)->objectNameNotifier()); + else + ep->captureProperty(object, result->coreIndex, result->notifyIndex); + } + + if (result->isVMEProperty()) { + typedef QQmlVMEMetaObject VMEMO; + VMEMO *vmemo = const_cast(static_cast(object->metaObject())); + return vmemo->vmeProperty(result->coreIndex); + } else if (result->isDirect()) { + return LoadProperty(engine, object, *result, 0); + } else { + return LoadProperty(engine, object, *result, 0); + } +} + +// Setter for writable properties. Shared between the interceptor and fast property accessor +static inline void StoreProperty(QV8Engine *engine, QObject *object, QQmlPropertyData *property, + v8::Handle value) +{ + QQmlBinding *newBinding = 0; + + if (value->IsFunction()) { + QQmlContextData *context = engine->callingContext(); + v8::Handle function = v8::Handle::Cast(value); + + v8::Local trace = + v8::StackTrace::CurrentStackTrace(1, (v8::StackTrace::StackTraceOptions)(v8::StackTrace::kLineNumber | + v8::StackTrace::kScriptName)); + v8::Local frame = trace->GetFrame(0); + int lineNumber = frame->GetLineNumber(); + int columNumber = frame->GetColumn(); + QString url = engine->toString(frame->GetScriptName()); + + newBinding = new QQmlBinding(&function, object, context); + newBinding->setSourceLocation(url, lineNumber, columNumber); + newBinding->setTarget(object, *property, context); + newBinding->setEvaluateFlags(newBinding->evaluateFlags() | + QQmlBinding::RequiresThisObject); + } + + QQmlAbstractBinding *oldBinding = + QQmlPropertyPrivate::setBinding(object, property->coreIndex, -1, newBinding); + if (oldBinding) + oldBinding->destroy(); + +#define PROPERTY_STORE(cpptype, value) \ + cpptype o = value; \ + int status = -1; \ + int flags = 0; \ + void *argv[] = { &o, 0, &status, &flags }; \ + QMetaObject::metacall(object, QMetaObject::WriteProperty, property->coreIndex, argv); + + + if (value->IsNull() && property->isQObject()) { + PROPERTY_STORE(QObject*, 0); + } else if (value->IsUndefined() && property->isResettable()) { + void *a[] = { 0 }; + QMetaObject::metacall(object, QMetaObject::ResetProperty, property->coreIndex, a); + } else if (value->IsUndefined() && property->propType == qMetaTypeId()) { + PROPERTY_STORE(QVariant, QVariant()); + } else if (value->IsUndefined()) { + QString error = QLatin1String("Cannot assign [undefined] to ") + + QLatin1String(QMetaType::typeName(property->propType)); + v8::ThrowException(v8::Exception::Error(engine->toString(error))); + } else if (value->IsFunction()) { + // this is handled by the binding creation above + } else if (property->propType == QMetaType::Int && value->IsNumber()) { + PROPERTY_STORE(int, qRound(value->ToNumber()->Value())); + } else if (property->propType == QMetaType::QReal && value->IsNumber()) { + PROPERTY_STORE(qreal, qreal(value->ToNumber()->Value())); + } else if (property->propType == QMetaType::Float && value->IsNumber()) { + PROPERTY_STORE(float, float(value->ToNumber()->Value())); + } else if (property->propType == QMetaType::Double && value->IsNumber()) { + PROPERTY_STORE(double, double(value->ToNumber()->Value())); + } else if (property->propType == QMetaType::QString && value->IsString()) { + PROPERTY_STORE(QString, engine->toString(value->ToString())); + } else if (property->isVMEProperty()) { + static_cast(const_cast(object->metaObject()))->setVMEProperty(property->coreIndex, value); + } else { + QVariant v; + if (property->isQList()) + v = engine->toVariant(value, qMetaTypeId >()); + else + v = engine->toVariant(value, property->propType); + + QQmlContextData *context = engine->callingContext(); + if (!QQmlPropertyPrivate::write(object, *property, v, context)) { + const char *valueType = 0; + if (v.userType() == QVariant::Invalid) valueType = "null"; + else valueType = QMetaType::typeName(v.userType()); + + QString error = QLatin1String("Cannot assign ") + + QLatin1String(valueType) + + QLatin1String(" to ") + + QLatin1String(QMetaType::typeName(property->propType)); + v8::ThrowException(v8::Exception::Error(engine->toString(error))); + } + } +} + +bool QV8QObjectWrapper::SetProperty(QV8Engine *engine, QObject *object, const QHashedV8String &property, + v8::Handle value, QV8QObjectWrapper::RevisionMode revisionMode) +{ + if (engine->qobjectWrapper()->m_toStringString == property || + engine->qobjectWrapper()->m_destroyString == property) + return true; + + QQmlPropertyData local; + QQmlPropertyData *result = 0; + result = QQmlPropertyCache::property(engine->engine(), object, property, local); + + if (!result) + return false; + - if (revisionMode == QV8QObjectWrapper::CheckRevision && result->revision != 0) { ++ if (revisionMode == QV8QObjectWrapper::CheckRevision && result->hasRevision()) { + QQmlData *ddata = QQmlData::get(object); + if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(result)) + return false; + } + + if (!result->isWritable() && !result->isQList()) { + QString error = QLatin1String("Cannot assign to read-only property \"") + + engine->toString(property.string()) + QLatin1Char('\"'); + v8::ThrowException(v8::Exception::Error(engine->toString(error))); + return true; + } + + StoreProperty(engine, object, result, value); + + return true; +} + +v8::Handle QV8QObjectWrapper::Getter(v8::Local property, + const v8::AccessorInfo &info) +{ + QV8QObjectResource *resource = v8_resource_check(info.This()); + + if (resource->object.isNull()) + return v8::Handle(); + + QObject *object = resource->object; + + QHashedV8String propertystring(property); + + QV8Engine *v8engine = resource->engine; + v8::Handle This = info.This(); + v8::Handle result = GetProperty(v8engine, object, &This, propertystring, + QV8QObjectWrapper::IgnoreRevision); + if (!result.IsEmpty()) + return result; + + if (QV8Engine::startsWithUpper(property)) { + // Check for attached properties + QQmlContextData *context = v8engine->callingContext(); + + if (context && context->imports) { + QQmlTypeNameCache::Result r = context->imports->query(propertystring); + + if (r.isValid()) { + if (r.scriptIndex != -1) { + return v8::Undefined(); + } else if (r.type) { + return v8engine->typeWrapper()->newObject(object, r.type, QV8TypeWrapper::ExcludeEnums); + } else if (r.importNamespace) { + return v8engine->typeWrapper()->newObject(object, context->imports, r.importNamespace, + QV8TypeWrapper::ExcludeEnums); + } + Q_ASSERT(!"Unreachable"); + } + } + } + + return v8::Handle(); +} + +v8::Handle QV8QObjectWrapper::Setter(v8::Local property, + v8::Local value, + const v8::AccessorInfo &info) +{ + QV8QObjectResource *resource = v8_resource_check(info.This()); + + if (resource->object.isNull()) + return value; + + QObject *object = resource->object; + + QHashedV8String propertystring(property); + + QV8Engine *v8engine = resource->engine; + bool result = SetProperty(v8engine, object, propertystring, value, QV8QObjectWrapper::IgnoreRevision); + + if (!result) { + QString error = QLatin1String("Cannot assign to non-existent property \"") + + v8engine->toString(property) + QLatin1Char('\"'); + v8::ThrowException(v8::Exception::Error(v8engine->toString(error))); + return value; + } + + return value; +} + +v8::Handle QV8QObjectWrapper::Query(v8::Local property, + const v8::AccessorInfo &info) +{ + QV8QObjectResource *resource = v8_resource_check(info.This()); + + if (resource->object.isNull()) + return v8::Handle(); + + QV8Engine *engine = resource->engine; + QObject *object = resource->object; + + QHashedV8String propertystring(property); + + QQmlPropertyData local; + QQmlPropertyData *result = 0; + result = QQmlPropertyCache::property(engine->engine(), object, propertystring, local); + + if (!result) + return v8::Handle(); + else if (!result->isWritable() && !result->isQList()) + return v8::Integer::New(v8::ReadOnly | v8::DontDelete); + else + return v8::Integer::New(v8::DontDelete); +} + +v8::Handle QV8QObjectWrapper::Enumerator(const v8::AccessorInfo &info) +{ + QV8QObjectResource *resource = v8_resource_check(info.This()); + + if (resource->object.isNull()) + return v8::Array::New(); + + QObject *object = resource->object; + + QStringList result; + + QQmlEnginePrivate *ep = resource->engine->engine() + ? QQmlEnginePrivate::get(resource->engine->engine()) + : 0; + + QQmlPropertyCache *cache = 0; + QQmlData *ddata = QQmlData::get(object); + if (ddata) + cache = ddata->propertyCache; + + if (!cache) { + cache = ep ? ep->cache(object) : 0; + if (cache) { + if (ddata) { cache->addref(); ddata->propertyCache = cache; } + } else { + // Not cachable - fall back to QMetaObject (eg. dynamic meta object) + const QMetaObject *mo = object->metaObject(); + int pc = mo->propertyCount(); + int po = mo->propertyOffset(); + for (int i=po; iproperty(i).name()); + } + } else { + result = cache->propertyNames(); + } + + v8::Local rv = v8::Array::New(result.count()); + + for (int ii = 0; ii < result.count(); ++ii) + rv->Set(ii, resource->engine->toString(result.at(ii))); + + return rv; +} + +static void FastValueSetter(v8::Local, v8::Local value, + const v8::AccessorInfo& info) +{ + QV8QObjectResource *resource = v8_resource_check(info.This()); + + if (resource->object.isNull()) + return; + + QObject *object = resource->object; + + QQmlPropertyData *property = + (QQmlPropertyData *)v8::External::Unwrap(info.Data()); + + int index = property->coreIndex; + + QQmlData *ddata = QQmlData::get(object, false); + Q_ASSERT(ddata); + Q_ASSERT(ddata->propertyCache); + + QQmlPropertyData *pdata = ddata->propertyCache->property(index); + Q_ASSERT(pdata); + + Q_ASSERT(pdata->isWritable() || pdata->isQList()); + + StoreProperty(resource->engine, object, pdata, value); +} + +static void FastValueSetterReadOnly(v8::Local property, v8::Local, + const v8::AccessorInfo& info) +{ + QV8QObjectResource *resource = v8_resource_check(info.This()); + + if (resource->object.isNull()) + return; + + QV8Engine *v8engine = resource->engine; + + QString error = QLatin1String("Cannot assign to read-only property \"") + + v8engine->toString(property) + QLatin1Char('\"'); + v8::ThrowException(v8::Exception::Error(v8engine->toString(error))); +} + +static void WeakQObjectReferenceCallback(v8::Persistent handle, void *) +{ + Q_ASSERT(handle->IsObject()); + + QV8QObjectResource *resource = v8_resource_check(handle->ToObject()); + + Q_ASSERT(resource); + + QObject *object = resource->object; + if (object) { + QQmlData *ddata = QQmlData::get(object, false); + if (ddata) { + ddata->v8object.Clear(); + if (!object->parent() && !ddata->indestructible) + object->deleteLater(); + } + } + + qPersistentDispose(handle); +} + +static void WeakQObjectInstanceCallback(v8::Persistent handle, void *data) +{ + QV8QObjectInstance *instance = (QV8QObjectInstance *)data; + instance->v8object.Clear(); + qPersistentDispose(handle); +} + +v8::Local QQmlPropertyCache::newQObject(QObject *object, QV8Engine *engine) +{ + Q_ASSERT(object); + Q_ASSERT(this->engine); + + Q_ASSERT(QQmlData::get(object, false)); + Q_ASSERT(QQmlData::get(object, false)->propertyCache == this); + + // Setup constructor + if (constructor.IsEmpty()) { + v8::Local ft; + + QString toString = QLatin1String("toString"); + QString destroy = QLatin1String("destroy"); + + // As we use hash linking, it is possible that iterating over the values can give duplicates. + // To combat this, we must unique'ify our properties. + StringCache uniqueHash; + if (stringCache.isLinked()) + uniqueHash.reserve(stringCache.count()); + + // XXX TODO: Enables fast property accessors. These more than double the property access + // performance, but the cost of setting up this structure hasn't been measured so + // its not guarenteed that this is a win overall. We need to try and measure the cost. + for (StringCache::ConstIterator iter = stringCache.begin(); iter != stringCache.end(); ++iter) { + if (stringCache.isLinked()) { + if (uniqueHash.contains(iter)) + continue; + uniqueHash.insert(iter); + } + + QQmlPropertyData *property = *iter; + if (property->notFullyResolved()) resolve(property); + + if (property->isFunction()) + continue; + + v8::AccessorGetter fastgetter = 0; + v8::AccessorSetter fastsetter = FastValueSetter; + if (!property->isWritable()) + fastsetter = FastValueSetterReadOnly; + + if (property->isQObject()) + fastgetter = FAST_GETTER_FUNCTION(property, QObject*); + else if (property->propType == QMetaType::Int || property->isEnum()) + fastgetter = FAST_GETTER_FUNCTION(property, int); + else if (property->propType == QMetaType::Bool) + fastgetter = FAST_GETTER_FUNCTION(property, bool); + else if (property->propType == QMetaType::QString) + fastgetter = FAST_GETTER_FUNCTION(property, QString); + else if (property->propType == QMetaType::UInt) + fastgetter = FAST_GETTER_FUNCTION(property, uint); + else if (property->propType == QMetaType::Float) + fastgetter = FAST_GETTER_FUNCTION(property, float); + else if (property->propType == QMetaType::Double) + fastgetter = FAST_GETTER_FUNCTION(property, double); + + if (fastgetter) { + QString name = iter.key(); + if (name == toString || name == destroy) + continue; + + if (ft.IsEmpty()) { + ft = v8::FunctionTemplate::New(); + ft->InstanceTemplate()->SetFallbackPropertyHandler(QV8QObjectWrapper::Getter, + QV8QObjectWrapper::Setter, + QV8QObjectWrapper::Query, + 0, + QV8QObjectWrapper::Enumerator); + ft->InstanceTemplate()->SetHasExternalResource(true); + } + + // We wrap the raw QQmlPropertyData pointer here. This is safe as the + // pointer will remain valid at least as long as the lifetime of any QObject's of + // this type and the property accessor checks if the object is 0 (deleted) before + // dereferencing the pointer. + ft->InstanceTemplate()->SetAccessor(engine->toString(name), fastgetter, fastsetter, + v8::External::Wrap(property)); + } + } + + if (ft.IsEmpty()) { + constructor = qPersistentNew(engine->qobjectWrapper()->m_constructor); + } else { + ft->InstanceTemplate()->SetFallbackPropertyHandler(QV8QObjectWrapper::Getter, + QV8QObjectWrapper::Setter, + QV8QObjectWrapper::Query, + 0, + QV8QObjectWrapper::Enumerator); + ft->InstanceTemplate()->SetHasExternalResource(true); + constructor = qPersistentNew(ft->GetFunction()); + } + + QQmlCleanup::addToEngine(this->engine); + } + + v8::Local result = constructor->NewInstance(); + QV8QObjectResource *r = new QV8QObjectResource(engine, object); + result->SetExternalResource(r); + return result; +} + +v8::Local QV8QObjectWrapper::newQObject(QObject *object, QQmlData *ddata, QV8Engine *engine) +{ + v8::Local rv; + + if (!ddata->propertyCache && engine->engine()) { + ddata->propertyCache = QQmlEnginePrivate::get(engine->engine())->cache(object); + if (ddata->propertyCache) ddata->propertyCache->addref(); + } + + if (ddata->propertyCache && ddata->propertyCache->qmlEngine() == engine->engine()) { + rv = ddata->propertyCache->newQObject(object, engine); + } else { + // XXX NewInstance() should be optimized + rv = m_constructor->NewInstance(); + QV8QObjectResource *r = new QV8QObjectResource(engine, object); + rv->SetExternalResource(r); + } + + return rv; +} + +/* +As V8 doesn't support an equality callback, for QObject's we have to return exactly the same +V8 handle for subsequent calls to newQObject for the same QObject. To do this we have a two +pronged strategy: + 1. If there is no current outstanding V8 handle to the QObject, we create one and store a + persistent handle in QQmlData::v8object. We mark the QV8QObjectWrapper that + "owns" this handle by setting the QQmlData::v8objectid to the id of this + QV8QObjectWrapper. + 2. If another QV8QObjectWrapper has create the handle in QQmlData::v8object we create + an entry in the m_taintedObject hash where we store the handle and mark the object as + "tainted" in the QQmlData::hasTaintedV8Object flag. +We have to mark the object as tainted to ensure that we search our m_taintedObject hash even +in the case that the original QV8QObjectWrapper owner of QQmlData::v8object has +released the handle. +*/ +v8::Handle QV8QObjectWrapper::newQObject(QObject *object) +{ + if (!object) + return v8::Null(); + + if (QObjectPrivate::get(object)->wasDeleted) + return v8::Undefined(); + + QQmlData *ddata = QQmlData::get(object, true); + + if (!ddata) + return v8::Undefined(); + + if (ddata->v8objectid == m_id && !ddata->v8object.IsEmpty()) { + // We own the v8object + return v8::Local::New(ddata->v8object); + } else if (ddata->v8object.IsEmpty() && + (ddata->v8objectid == m_id || // We own the QObject + ddata->v8objectid == 0 || // No one owns the QObject + !ddata->hasTaintedV8Object)) { // Someone else has used the QObject, but it isn't tainted + + v8::Local rv = newQObject(object, ddata, m_engine); + ddata->v8object = qPersistentNew(rv); + ddata->v8object.MakeWeak(0, WeakQObjectReferenceCallback); + ddata->v8objectid = m_id; + return rv; + + } else { + // If this object is tainted, we have to check to see if it is in our + // tainted object list + TaintedHash::Iterator iter = + ddata->hasTaintedV8Object?m_taintedObjects.find(object):m_taintedObjects.end(); + bool found = iter != m_taintedObjects.end(); + + // If our tainted handle doesn't exist or has been collected, and there isn't + // a handle in the ddata, we can assume ownership of the ddata->v8object + if ((!found || (*iter)->v8object.IsEmpty()) && ddata->v8object.IsEmpty()) { + v8::Local rv = newQObject(object, ddata, m_engine); + ddata->v8object = qPersistentNew(rv); + ddata->v8object.MakeWeak(0, WeakQObjectReferenceCallback); + ddata->v8objectid = m_id; + + if (found) { + delete (*iter); + m_taintedObjects.erase(iter); + } + + return rv; + } else if (!found) { + QV8QObjectInstance *instance = new QV8QObjectInstance(object, this); + iter = m_taintedObjects.insert(object, instance); + ddata->hasTaintedV8Object = true; + } + + if ((*iter)->v8object.IsEmpty()) { + v8::Local rv = newQObject(object, ddata, m_engine); + (*iter)->v8object = qPersistentNew(rv); + (*iter)->v8object.MakeWeak((*iter), WeakQObjectInstanceCallback); + } + + return v8::Local::New((*iter)->v8object); + } +} + +QPair QV8QObjectWrapper::ExtractQtSignal(QV8Engine *engine, v8::Handle object) +{ + if (object->IsFunction()) + return ExtractQtMethod(engine, v8::Handle::Cast(object)); + + if (QV8SignalHandlerResource *resource = v8_resource_cast(object)) + return qMakePair(resource->object.data(), resource->index); + + return qMakePair((QObject *)0, -1); +} + +QPair QV8QObjectWrapper::ExtractQtMethod(QV8Engine *engine, v8::Handle function) +{ + v8::ScriptOrigin origin = function->GetScriptOrigin(); + if (origin.ResourceName()->StrictEquals(engine->qobjectWrapper()->m_hiddenObject)) { + + // This is one of our special QObject method wrappers + v8::Handle args[] = { engine->qobjectWrapper()->m_hiddenObject }; + v8::Local data = function->Call(engine->global(), 1, args); + + if (data->IsArray()) { + v8::Local array = v8::Local::Cast(data); + return qMakePair(engine->toQObject(array->Get(0)), array->Get(1)->Int32Value()); + } + + // In theory this can't fall through, but I suppose V8 might run out of memory or something + } + + return qMakePair((QObject *)0, -1); +} + +class QV8QObjectConnectionList : public QObject, public QQmlGuard +{ +public: + QV8QObjectConnectionList(QObject *object, QV8Engine *engine); + ~QV8QObjectConnectionList(); + + struct Connection { + Connection() + : needsDestroy(false) {} + Connection(const Connection &other) + : thisObject(other.thisObject), function(other.function), needsDestroy(false) {} + Connection &operator=(const Connection &other) { + thisObject = other.thisObject; + function = other.function; + needsDestroy = other.needsDestroy; + return *this; + } + + v8::Persistent thisObject; + v8::Persistent function; + + void dispose() { + qPersistentDispose(thisObject); + qPersistentDispose(function); + } + + bool needsDestroy; + }; + + struct ConnectionList : public QList { + ConnectionList() : connectionsInUse(0), connectionsNeedClean(false) {} + int connectionsInUse; + bool connectionsNeedClean; + }; + + QV8Engine *engine; + + typedef QHash SlotHash; + SlotHash slotHash; + bool needsDestroy; + int inUse; + + virtual void objectDestroyed(QObject *); + virtual int qt_metacall(QMetaObject::Call, int, void **); +}; + +QV8QObjectConnectionList::QV8QObjectConnectionList(QObject *object, QV8Engine *engine) +: QQmlGuard(object), engine(engine), needsDestroy(false), inUse(0) +{ +} + +QV8QObjectConnectionList::~QV8QObjectConnectionList() +{ + for (SlotHash::Iterator iter = slotHash.begin(); iter != slotHash.end(); ++iter) { + QList &connections = *iter; + for (int ii = 0; ii < connections.count(); ++ii) { + qPersistentDispose(connections[ii].thisObject); + qPersistentDispose(connections[ii].function); + } + } + slotHash.clear(); +} + +void QV8QObjectConnectionList::objectDestroyed(QObject *object) +{ + engine->qobjectWrapper()->m_connections.remove(object); + + if (inUse) + needsDestroy = true; + else + delete this; +} + +int QV8QObjectConnectionList::qt_metacall(QMetaObject::Call method, int index, void **metaArgs) +{ + if (method == QMetaObject::InvokeMetaMethod) { + SlotHash::Iterator iter = slotHash.find(index); + if (iter == slotHash.end()) + return -1; + ConnectionList &connectionList = *iter; + if (connectionList.isEmpty()) + return -1; + + inUse++; + + connectionList.connectionsInUse++; + + QList connections = connectionList; + + QVarLengthArray dummy; + int *argsTypes = QQmlPropertyCache::methodParameterTypes(data(), index, dummy, 0); + + v8::HandleScope handle_scope; + v8::Context::Scope scope(engine->context()); + + int argCount = argsTypes?argsTypes[0]:0; + QVarLengthArray, 9> args(argCount); + + for (int ii = 0; ii < argCount; ++ii) { + int type = argsTypes[ii + 1]; + if (type == qMetaTypeId()) { + args[ii] = engine->fromVariant(*((QVariant *)metaArgs[ii + 1])); + } else { + args[ii] = engine->fromVariant(QVariant(type, metaArgs[ii + 1])); + } + } + + for (int ii = 0; ii < connections.count(); ++ii) { + Connection &connection = connections[ii]; + if (connection.needsDestroy) + continue; + + v8::TryCatch try_catch; + if (connection.thisObject.IsEmpty()) { + connection.function->Call(engine->global(), argCount, args.data()); + } else { + connection.function->Call(connection.thisObject, argCount, args.data()); + } + + if (try_catch.HasCaught()) { + QQmlError error; + error.setDescription(QString(QLatin1String("Unknown exception occurred during evaluation of connected function: %1")).arg(engine->toString(connection.function->GetName()))); + v8::Local message = try_catch.Message(); + if (!message.IsEmpty()) + QQmlExpressionPrivate::exceptionToError(message, error); + QQmlEnginePrivate::get(engine->engine())->warning(error); + } + } + + connectionList.connectionsInUse--; + if (connectionList.connectionsInUse == 0 && connectionList.connectionsNeedClean) { + for (QList::Iterator iter = connectionList.begin(); + iter != connectionList.end(); ) { + if (iter->needsDestroy) { + iter->dispose(); + iter = connectionList.erase(iter); + } else { + ++iter; + } + } + } + + inUse--; + if (inUse == 0 && needsDestroy) + delete this; + } + + return -1; +} + +v8::Handle QV8QObjectWrapper::Connect(const v8::Arguments &args) +{ + if (args.Length() == 0) + V8THROW_ERROR("Function.prototype.connect: no arguments given"); + + QV8Engine *engine = V8ENGINE(); + + QPair signalInfo = ExtractQtSignal(engine, args.This()); + QObject *signalObject = signalInfo.first; + int signalIndex = signalInfo.second; + + if (signalIndex == -1) + V8THROW_ERROR("Function.prototype.connect: this object is not a signal"); + + if (!signalObject) + V8THROW_ERROR("Function.prototype.connect: cannot connect to deleted QObject"); + + if (signalIndex < 0 || signalObject->metaObject()->method(signalIndex).methodType() != QMetaMethod::Signal) + V8THROW_ERROR("Function.prototype.connect: this object is not a signal"); + + v8::Local functionValue; + v8::Local functionThisValue; + + if (args.Length() == 1) { + functionValue = args[0]; + } else { + functionThisValue = args[0]; + functionValue = args[1]; + } + + if (!functionValue->IsFunction()) + V8THROW_ERROR("Function.prototype.connect: target is not a function"); + + if (!functionThisValue.IsEmpty() && !functionThisValue->IsObject()) + V8THROW_ERROR("Function.prototype.connect: target this is not an object"); + + QV8QObjectWrapper *qobjectWrapper = engine->qobjectWrapper(); + QHash &connections = qobjectWrapper->m_connections; + QHash::Iterator iter = connections.find(signalObject); + if (iter == connections.end()) + iter = connections.insert(signalObject, new QV8QObjectConnectionList(signalObject, engine)); + + QV8QObjectConnectionList *connectionList = *iter; + QV8QObjectConnectionList::SlotHash::Iterator slotIter = connectionList->slotHash.find(signalIndex); + if (slotIter == connectionList->slotHash.end()) { + slotIter = connectionList->slotHash.insert(signalIndex, QV8QObjectConnectionList::ConnectionList()); + QMetaObject::connect(signalObject, signalIndex, connectionList, signalIndex); + } + + QV8QObjectConnectionList::Connection connection; + if (!functionThisValue.IsEmpty()) + connection.thisObject = qPersistentNew(functionThisValue->ToObject()); + connection.function = qPersistentNew(v8::Handle::Cast(functionValue)); + + slotIter->append(connection); + + return v8::Undefined(); +} + +v8::Handle QV8QObjectWrapper::Disconnect(const v8::Arguments &args) +{ + if (args.Length() == 0) + V8THROW_ERROR("Function.prototype.disconnect: no arguments given"); + + QV8Engine *engine = V8ENGINE(); + + QPair signalInfo = ExtractQtSignal(engine, args.This()); + QObject *signalObject = signalInfo.first; + int signalIndex = signalInfo.second; + + if (signalIndex == -1) + V8THROW_ERROR("Function.prototype.disconnect: this object is not a signal"); + + if (!signalObject) + V8THROW_ERROR("Function.prototype.disconnect: cannot disconnect from deleted QObject"); + + if (signalIndex < 0 || signalObject->metaObject()->method(signalIndex).methodType() != QMetaMethod::Signal) + V8THROW_ERROR("Function.prototype.disconnect: this object is not a signal"); + + v8::Local functionValue; + v8::Local functionThisValue; + + if (args.Length() == 1) { + functionValue = args[0]; + } else { + functionThisValue = args[0]; + functionValue = args[1]; + } + + if (!functionValue->IsFunction()) + V8THROW_ERROR("Function.prototype.disconnect: target is not a function"); + + if (!functionThisValue.IsEmpty() && !functionThisValue->IsObject()) + V8THROW_ERROR("Function.prototype.disconnect: target this is not an object"); + + QV8QObjectWrapper *qobjectWrapper = engine->qobjectWrapper(); + QHash &connectionsList = qobjectWrapper->m_connections; + QHash::Iterator iter = connectionsList.find(signalObject); + if (iter == connectionsList.end()) + return v8::Undefined(); // Nothing to disconnect from + + QV8QObjectConnectionList *connectionList = *iter; + QV8QObjectConnectionList::SlotHash::Iterator slotIter = connectionList->slotHash.find(signalIndex); + if (slotIter == connectionList->slotHash.end()) + return v8::Undefined(); // Nothing to disconnect from + + QV8QObjectConnectionList::ConnectionList &connections = *slotIter; + + v8::Local function = v8::Local::Cast(functionValue); + QPair functionData = ExtractQtMethod(engine, function); + + if (functionData.second != -1) { + // This is a QObject function wrapper + for (int ii = 0; ii < connections.count(); ++ii) { + QV8QObjectConnectionList::Connection &connection = connections[ii]; + + if (connection.thisObject.IsEmpty() == functionThisValue.IsEmpty() && + (connection.thisObject.IsEmpty() || connection.thisObject->StrictEquals(functionThisValue))) { + + QPair connectedFunctionData = ExtractQtMethod(engine, connection.function); + if (connectedFunctionData == functionData) { + // Match! + if (connections.connectionsInUse) { + connection.needsDestroy = true; + connections.connectionsNeedClean = true; + } else { + connection.dispose(); + connections.removeAt(ii); + } + return v8::Undefined(); + } + } + } + + } else { + // This is a normal JS function + for (int ii = 0; ii < connections.count(); ++ii) { + QV8QObjectConnectionList::Connection &connection = connections[ii]; + if (connection.function->StrictEquals(function) && + connection.thisObject.IsEmpty() == functionThisValue.IsEmpty() && + (connection.thisObject.IsEmpty() || connection.thisObject->StrictEquals(functionThisValue))) { + // Match! + if (connections.connectionsInUse) { + connection.needsDestroy = true; + connections.connectionsNeedClean = true; + } else { + connection.dispose(); + connections.removeAt(ii); + } + return v8::Undefined(); + } + } + } + + return v8::Undefined(); +} + +/*! + \fn v8::Handle QV8QObjectWrapper::getProperty(QObject *object, const QHashedV8String &property, QV8QObjectWrapper::RevisionMode revisionMode) + + Get the \a property of \a object. Returns an empty handle if the property doesn't exist. + + Only searches for real properties of \a object (including methods), not attached properties etc. +*/ + +/* + \fn bool QV8QObjectWrapper::setProperty(QObject *object, const QHashedV8String &property, v8::Handle value, RevisionMode revisionMode) + + Set the \a property of \a object to \a value. + + Returns true if the property was "set" - even if this results in an exception being thrown - + and false if the object has no such property. + + Only searches for real properties of \a object (including methods), not attached properties etc. +*/ + +namespace { +struct CallArgs +{ + CallArgs(int length, v8::Handle *args) : _length(length), _args(args) {} + int Length() const { return _length; } + v8::Local operator[](int idx) { return (*_args)->Get(idx); } + +private: + int _length; + v8::Handle *_args; +}; +} + +static v8::Handle CallMethod(QObject *object, int index, int returnType, int argCount, + int *argTypes, QV8Engine *engine, CallArgs &callArgs) +{ + if (argCount > 0) { + + QVarLengthArray args(argCount + 1); + args[0].initAsType(returnType); + + for (int ii = 0; ii < argCount; ++ii) + args[ii + 1].fromValue(argTypes[ii], engine, callArgs[ii]); + + QVarLengthArray argData(args.count()); + for (int ii = 0; ii < args.count(); ++ii) + argData[ii] = args[ii].dataPtr(); + + QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, argData.data()); + + return args[0].toValue(engine); + + } else if (returnType != 0) { + + CallArgument arg; + arg.initAsType(returnType); + + void *args[] = { arg.dataPtr() }; + + QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, args); + + return arg.toValue(engine); + + } else { + + void *args[] = { 0 }; + QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, args); + return v8::Undefined(); + + } +} + +/*! + Returns the match score for converting \a actual to be of type \a conversionType. A + zero score means "perfect match" whereas a higher score is worse. + + The conversion table is copied out of the QtScript callQtMethod() function. +*/ +static int MatchScore(v8::Handle actual, int conversionType) +{ + if (actual->IsNumber()) { + switch (conversionType) { + case QMetaType::Double: + return 0; + case QMetaType::Float: + return 1; + case QMetaType::LongLong: + case QMetaType::ULongLong: + return 2; + case QMetaType::Long: + case QMetaType::ULong: + return 3; + case QMetaType::Int: + case QMetaType::UInt: + return 4; + case QMetaType::Short: + case QMetaType::UShort: + return 5; + break; + case QMetaType::Char: + case QMetaType::UChar: + return 6; + default: + return 10; + } + } else if (actual->IsString()) { + switch (conversionType) { + case QMetaType::QString: + return 0; + default: + return 10; + } + } else if (actual->IsBoolean()) { + switch (conversionType) { + case QMetaType::Bool: + return 0; + default: + return 10; + } + } else if (actual->IsDate()) { + switch (conversionType) { + case QMetaType::QDateTime: + return 0; + case QMetaType::QDate: + return 1; + case QMetaType::QTime: + return 2; + default: + return 10; + } + } else if (actual->IsRegExp()) { + switch (conversionType) { + case QMetaType::QRegExp: + return 0; + default: + return 10; + } + } else if (actual->IsArray()) { + switch (conversionType) { + case QMetaType::QStringList: + case QMetaType::QVariantList: + return 5; + default: + return 10; + } + } else if (actual->IsNull()) { + switch (conversionType) { + case QMetaType::VoidStar: + case QMetaType::QObjectStar: + return 0; + default: { + const char *typeName = QMetaType::typeName(conversionType); + if (typeName && typeName[strlen(typeName) - 1] == '*') + return 0; + else + return 10; + } + } + } else if (actual->IsObject()) { + v8::Handle obj = v8::Handle::Cast(actual); + + QV8ObjectResource *r = static_cast(obj->GetExternalResource()); + if (r && r->resourceType() == QV8ObjectResource::QObjectType) { + switch (conversionType) { + case QMetaType::QObjectStar: + return 0; + default: + return 10; + } + } else if (r && r->resourceType() == QV8ObjectResource::VariantType) { + if (conversionType == qMetaTypeId()) + return 0; + else if (r->engine->toVariant(actual, -1).userType() == conversionType) + return 0; + else + return 10; + } else { + return 10; + } + + } else { + return 10; + } +} + +static inline int QMetaObject_methods(const QMetaObject *metaObject) +{ + struct Private + { + int revision; + int className; + int classInfoCount, classInfoData; + int methodCount, methodData; + }; + + return reinterpret_cast(metaObject->d.data)->methodCount; +} + +static QByteArray QMetaMethod_name(const QMetaMethod &m) +{ + QByteArray sig = m.signature(); + int paren = sig.indexOf('('); + if (paren == -1) + return sig; + else + return sig.left(paren); +} + +/*! +Returns the next related method, if one, or 0. +*/ +static const QQmlPropertyData * RelatedMethod(QObject *object, + const QQmlPropertyData *current, + QQmlPropertyData &dummy) +{ + QQmlPropertyCache *cache = QQmlData::get(object)->propertyCache; + if (!current->isOverload()) + return 0; + + Q_ASSERT(!current->overrideIndexIsProperty); + + if (cache) { + return cache->method(current->overrideIndex); + } else { + const QMetaObject *mo = object->metaObject(); + int methodOffset = mo->methodCount() - QMetaObject_methods(mo); + + while (methodOffset > current->overrideIndex) { + mo = mo->superClass(); + methodOffset -= QMetaObject_methods(mo); + } + + QMetaMethod method = mo->method(current->overrideIndex); + dummy.load(method); + + // Look for overloaded methods + QByteArray methodName = QMetaMethod_name(method); + for (int ii = current->overrideIndex - 1; ii >= methodOffset; --ii) { + if (methodName == QMetaMethod_name(mo->method(ii))) { + dummy.setFlags(dummy.getFlags() | QQmlPropertyData::IsOverload); + dummy.overrideIndexIsProperty = 0; + dummy.overrideIndex = ii; + return &dummy; + } + } + + return &dummy; + } +} + +static v8::Handle CallPrecise(QObject *object, const QQmlPropertyData &data, + QV8Engine *engine, CallArgs &callArgs) +{ + if (data.hasArguments()) { + + int *args = 0; + QVarLengthArray dummy; + QByteArray unknownTypeError; + + args = QQmlPropertyCache::methodParameterTypes(object, data.coreIndex, dummy, + &unknownTypeError); + + if (!args) { + QString typeName = QString::fromLatin1(unknownTypeError); + QString error = QString::fromLatin1("Unknown method parameter type: %1").arg(typeName); + v8::ThrowException(v8::Exception::Error(engine->toString(error))); + return v8::Handle(); + } + + if (args[0] > callArgs.Length()) { + QString error = QLatin1String("Insufficient arguments"); + v8::ThrowException(v8::Exception::Error(engine->toString(error))); + return v8::Handle(); + } + + return CallMethod(object, data.coreIndex, data.propType, args[0], args + 1, engine, callArgs); + + } else { + + return CallMethod(object, data.coreIndex, data.propType, 0, 0, engine, callArgs); + + } +} + +/*! +Resolve the overloaded method to call. The algorithm works conceptually like this: + 1. Resolve the set of overloads it is *possible* to call. + Impossible overloads include those that have too many parameters or have parameters + of unknown type. + 2. Filter the set of overloads to only contain those with the closest number of + parameters. + For example, if we are called with 3 parameters and there are 2 overloads that + take 2 parameters and one that takes 3, eliminate the 2 parameter overloads. + 3. Find the best remaining overload based on its match score. + If two or more overloads have the same match score, call the last one. The match + score is constructed by adding the matchScore() result for each of the parameters. +*/ +static v8::Handle CallOverloaded(QObject *object, const QQmlPropertyData &data, + QV8Engine *engine, CallArgs &callArgs) +{ + int argumentCount = callArgs.Length(); + + const QQmlPropertyData *best = 0; + int bestParameterScore = INT_MAX; + int bestMatchScore = INT_MAX; + + QQmlPropertyData dummy; + const QQmlPropertyData *attempt = &data; + + do { + QVarLengthArray dummy; + int methodArgumentCount = 0; + int *methodArgTypes = 0; + if (attempt->hasArguments()) { + typedef QQmlPropertyCache PC; + int *args = PC::methodParameterTypes(object, attempt->coreIndex, dummy, 0); + if (!args) // Must be an unknown argument + continue; + + methodArgumentCount = args[0]; + methodArgTypes = args + 1; + } + + if (methodArgumentCount > argumentCount) + continue; // We don't have sufficient arguments to call this method + + int methodParameterScore = argumentCount - methodArgumentCount; + if (methodParameterScore > bestParameterScore) + continue; // We already have a better option + + int methodMatchScore = 0; + for (int ii = 0; ii < methodArgumentCount; ++ii) + methodMatchScore += MatchScore(callArgs[ii], methodArgTypes[ii]); + + if (bestParameterScore > methodParameterScore || bestMatchScore > methodMatchScore) { + best = attempt; + bestParameterScore = methodParameterScore; + bestMatchScore = methodMatchScore; + } + + if (bestParameterScore == 0 && bestMatchScore == 0) + break; // We can't get better than that + + } while((attempt = RelatedMethod(object, attempt, dummy)) != 0); + + if (best) { + return CallPrecise(object, *best, engine, callArgs); + } else { + QString error = QLatin1String("Unable to determine callable overload. Candidates are:"); + const QQmlPropertyData *candidate = &data; + while (candidate) { + error += QLatin1String("\n ") + + QString::fromUtf8(object->metaObject()->method(candidate->coreIndex).signature()); + candidate = RelatedMethod(object, candidate, dummy); + } + + v8::ThrowException(v8::Exception::Error(engine->toString(error))); + return v8::Handle(); + } +} + +static v8::Handle ToString(QV8Engine *engine, QObject *object, int, v8::Handle) +{ + QString result; + if (object) { + QString objectName = object->objectName(); + + result += QString::fromUtf8(object->metaObject()->className()); + result += QLatin1String("(0x"); + result += QString::number((quintptr)object,16); + + if (!objectName.isEmpty()) { + result += QLatin1String(", \""); + result += objectName; + result += QLatin1Char('\"'); + } + + result += QLatin1Char(')'); + } else { + result = QLatin1String("null"); + } + + return engine->toString(result); +} + +static v8::Handle Destroy(QV8Engine *, QObject *object, int argCount, v8::Handle args) +{ + QQmlData *ddata = QQmlData::get(object, false); + if (!ddata || ddata->indestructible) { + const char *error = "Invalid attempt to destroy() an indestructible object"; + v8::ThrowException(v8::Exception::Error(v8::String::New(error))); + return v8::Undefined(); + } + + int delay = 0; + if (argCount > 0) + delay = args->Get(0)->Uint32Value(); + + if (delay > 0) + QTimer::singleShot(delay, object, SLOT(deleteLater())); + else + object->deleteLater(); + + return v8::Undefined(); +} + +v8::Handle QV8QObjectWrapper::Invoke(const v8::Arguments &args) +{ + // object, index, qmlglobal, argCount, args + Q_ASSERT(args.Length() == 5); + Q_ASSERT(args[0]->IsObject()); + + QV8QObjectResource *resource = v8_resource_cast(args[0]->ToObject()); + + if (!resource) + return v8::Undefined(); + + int argCount = args[3]->Int32Value(); + v8::Handle arguments = v8::Handle::Cast(args[4]); + + // Special hack to return info about this closure. + if (argCount == 1 && arguments->Get(0)->StrictEquals(resource->engine->qobjectWrapper()->m_hiddenObject)) { + v8::Local data = v8::Array::New(2); + data->Set(0, args[0]); + data->Set(1, args[1]); + return data; + } + + QObject *object = resource->object; + int index = args[1]->Int32Value(); + + if (!object) + return v8::Undefined(); + + if (index < 0) { + // Builtin functions + if (index == QOBJECT_TOSTRING_INDEX) { + return ToString(resource->engine, object, argCount, arguments); + } else if (index == QOBJECT_DESTROY_INDEX) { + return Destroy(resource->engine, object, argCount, arguments); + } else { + return v8::Undefined(); + } + } + + QQmlPropertyData method; + + if (QQmlData *ddata = static_cast(QObjectPrivate::get(object)->declarativeData)) { + if (ddata->propertyCache) { + QQmlPropertyData *d = ddata->propertyCache->method(index); + if (!d) + return v8::Undefined(); + method = *d; + } + } + + if (method.coreIndex == -1) { + method.load(object->metaObject()->method(index)); + + if (method.coreIndex == -1) + return v8::Undefined(); + } + + if (method.isV8Function()) { + v8::Handle rv; + v8::Handle qmlglobal = args[2]->ToObject(); + + QQmlV8Function func(argCount, arguments, rv, qmlglobal, + resource->engine->contextWrapper()->context(qmlglobal), + resource->engine); + QQmlV8Function *funcptr = &func; + + void *args[] = { 0, &funcptr }; + QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, method.coreIndex, args); + + if (rv.IsEmpty()) return v8::Undefined(); + return rv; + } + + CallArgs callArgs(argCount, &arguments); + if (!method.isOverload()) { + return CallPrecise(object, method, resource->engine, callArgs); + } else { + return CallOverloaded(object, method, resource->engine, callArgs); + } +} + +CallArgument::CallArgument() +: type(QVariant::Invalid) +{ +} + +CallArgument::~CallArgument() +{ + cleanup(); +} + +void CallArgument::cleanup() +{ + if (type == QMetaType::QString) { + qstringPtr->~QString(); + } else if (type == -1 || type == QMetaType::QVariant) { + qvariantPtr->~QVariant(); + } else if (type == qMetaTypeId()) { + qjsValuePtr->~QJSValue(); + } else if (type == qMetaTypeId >()) { + qlistPtr->~QList(); + } +} + +void *CallArgument::dataPtr() +{ + if (type == -1) + return qvariantPtr->data(); + else + return (void *)&allocData; +} + +void CallArgument::initAsType(int callType) +{ + if (type != 0) { cleanup(); type = 0; } + if (callType == 0) return; + + if (callType == qMetaTypeId()) { + qjsValuePtr = new (&allocData) QJSValue(); + type = callType; + } else if (callType == QMetaType::Int || + callType == QMetaType::UInt || + callType == QMetaType::Bool || + callType == QMetaType::Double || + callType == QMetaType::Float) { + type = callType; + } else if (callType == QMetaType::QObjectStar) { + qobjectPtr = 0; + type = callType; + } else if (callType == QMetaType::QString) { + qstringPtr = new (&allocData) QString(); + type = callType; + } else if (callType == QMetaType::QVariant) { + type = callType; + qvariantPtr = new (&allocData) QVariant(); + } else if (callType == qMetaTypeId >()) { + type = callType; + qlistPtr = new (&allocData) QList(); + } else if (callType == qMetaTypeId()) { + type = callType; + handlePtr = new (&allocData) QQmlV8Handle; + } else { + type = -1; + qvariantPtr = new (&allocData) QVariant(callType, (void *)0); + } +} + +void CallArgument::fromValue(int callType, QV8Engine *engine, v8::Handle value) +{ + if (type != 0) { cleanup(); type = 0; } + + if (callType == qMetaTypeId()) { + qjsValuePtr = new (&allocData) QJSValue(QJSValuePrivate::get(new QJSValuePrivate(engine, value))); + type = qMetaTypeId(); + } else if (callType == QMetaType::Int) { + intValue = quint32(value->Int32Value()); + type = callType; + } else if (callType == QMetaType::UInt) { + intValue = quint32(value->Uint32Value()); + type = callType; + } else if (callType == QMetaType::Bool) { + boolValue = value->BooleanValue(); + type = callType; + } else if (callType == QMetaType::Double) { + doubleValue = double(value->NumberValue()); + type = callType; + } else if (callType == QMetaType::Float) { + floatValue = float(value->NumberValue()); + type = callType; + } else if (callType == QMetaType::QString) { + if (value->IsNull() || value->IsUndefined()) + qstringPtr = new (&allocData) QString(); + else + qstringPtr = new (&allocData) QString(engine->toString(value->ToString())); + type = callType; + } else if (callType == QMetaType::QObjectStar) { + qobjectPtr = engine->toQObject(value); + type = callType; + } else if (callType == qMetaTypeId()) { + qvariantPtr = new (&allocData) QVariant(engine->toVariant(value, -1)); + type = callType; + } else if (callType == qMetaTypeId >()) { + qlistPtr = new (&allocData) QList(); + if (value->IsArray()) { + v8::Handle array = v8::Handle::Cast(value); + uint32_t length = array->Length(); + for (uint32_t ii = 0; ii < length; ++ii) + qlistPtr->append(engine->toQObject(array->Get(ii))); + } else { + qlistPtr->append(engine->toQObject(value)); + } + type = callType; + } else if (callType == qMetaTypeId()) { + handlePtr = new (&allocData) QQmlV8Handle(QQmlV8Handle::fromHandle(value)); + type = callType; + } else { + qvariantPtr = new (&allocData) QVariant(); + type = -1; + + QQmlEnginePrivate *ep = engine->engine() ? QQmlEnginePrivate::get(engine->engine()) : 0; + QVariant v = engine->toVariant(value, -1); + + if (v.userType() == callType) { + *qvariantPtr = v; + } else if (v.canConvert((QVariant::Type)callType)) { + *qvariantPtr = v; + qvariantPtr->convert((QVariant::Type)callType); + } else if (const QMetaObject *mo = ep ? ep->rawMetaObjectForType(callType) : 0) { + QObject *obj = ep->toQObject(v); + + if (obj) { + const QMetaObject *objMo = obj->metaObject(); + while (objMo && objMo != mo) objMo = objMo->superClass(); + if (!objMo) obj = 0; + } + + *qvariantPtr = QVariant(callType, &obj); + } else { + *qvariantPtr = QVariant(callType, (void *)0); + } + } +} + +v8::Handle CallArgument::toValue(QV8Engine *engine) +{ + if (type == qMetaTypeId()) { + return QJSValuePrivate::get(*qjsValuePtr)->asV8Value(engine); + } else if (type == QMetaType::Int) { + return v8::Integer::New(int(intValue)); + } else if (type == QMetaType::UInt) { + return v8::Integer::NewFromUnsigned(intValue); + } else if (type == QMetaType::Bool) { + return v8::Boolean::New(boolValue); + } else if (type == QMetaType::Double) { + return v8::Number::New(doubleValue); + } else if (type == QMetaType::Float) { + return v8::Number::New(floatValue); + } else if (type == QMetaType::QString) { + return engine->toString(*qstringPtr); + } else if (type == QMetaType::QObjectStar) { + QObject *object = qobjectPtr; + if (object) + QQmlData::get(object, true)->setImplicitDestructible(); + return engine->newQObject(object); + } else if (type == qMetaTypeId >()) { + // XXX Can this be made more by using Array as a prototype and implementing + // directly against QList? + QList &list = *qlistPtr; + v8::Local array = v8::Array::New(list.count()); + for (int ii = 0; ii < list.count(); ++ii) + array->Set(ii, engine->newQObject(list.at(ii))); + return array; + } else if (type == qMetaTypeId()) { + return handlePtr->toHandle(); + } else if (type == -1 || type == qMetaTypeId()) { + QVariant value = *qvariantPtr; + v8::Handle rv = engine->fromVariant(value); + if (QObject *object = engine->toQObject(rv)) + QQmlData::get(object, true)->setImplicitDestructible(); + return rv; + } else { + return v8::Undefined(); + } +} + +QT_END_NAMESPACE + diff --cc src/quick/items/qquickanimatedsprite.cpp index 0000000,ef79d05..618178f mode 000000,100644..100644 --- a/src/quick/items/qquickanimatedsprite.cpp +++ b/src/quick/items/qquickanimatedsprite.cpp @@@ -1,0 -1,613 +1,613 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + #include "qquickanimatedsprite_p.h" + #include "qquicksprite_p.h" + #include "qquickspriteengine_p.h" + #include + #include + #include + #include + #include + #include + #include -#include ++#include + #include + #include + #include + #include + + QT_BEGIN_NAMESPACE + + static const char vertexShaderCode[] = + "attribute highp vec2 vTex;\n" + "uniform highp vec3 animData;// w,h(premultiplied of anim), interpolation progress\n" + "uniform highp vec4 animPos;//x,y, x,y (two frames for interpolation)\n" + "uniform highp vec2 size;//w,h of element\n" + "\n" + "uniform highp mat4 qt_Matrix;\n" + "\n" + "varying highp vec4 fTexS;\n" + "varying lowp float progress;\n" + "\n" + "\n" + "void main() {\n" + " progress = animData.z;\n" + " //Calculate frame location in texture\n" + " fTexS.xy = animPos.xy + vTex.xy * animData.xy;\n" + " //Next frame is also passed, for interpolation\n" + " fTexS.zw = animPos.zw + vTex.xy * animData.xy;\n" + "\n" + " gl_Position = qt_Matrix * vec4(size.x * vTex.x, size.y * vTex.y, 0, 1);\n" + "}\n"; + + static const char fragmentShaderCode[] = + "uniform sampler2D texture;\n" + "uniform lowp float qt_Opacity;\n" + "\n" + "varying highp vec4 fTexS;\n" + "varying lowp float progress;\n" + "\n" + "void main() {\n" + " gl_FragColor = mix(texture2D(texture, fTexS.xy), texture2D(texture, fTexS.zw), progress) * qt_Opacity;\n" + "}\n"; + + class QQuickAnimatedSpriteMaterial : public QSGMaterial + { + public: + QQuickAnimatedSpriteMaterial(); + ~QQuickAnimatedSpriteMaterial(); + virtual QSGMaterialType *type() const { static QSGMaterialType type; return &type; } + virtual QSGMaterialShader *createShader() const; + virtual int compare(const QSGMaterial *other) const + { + return this - static_cast(other); + } + + QSGTexture *texture; + + float animT; + float animX1; + float animY1; + float animX2; + float animY2; + float animW; + float animH; + float elementWidth; + float elementHeight; + }; + + QQuickAnimatedSpriteMaterial::QQuickAnimatedSpriteMaterial() + : texture(0) + , animT(0.0f) + , animX1(0.0f) + , animY1(0.0f) + , animX2(0.0f) + , animY2(0.0f) + , animW(1.0f) + , animH(1.0f) + , elementWidth(1.0f) + , elementHeight(1.0f) + { + setFlag(Blending, true); + } + + QQuickAnimatedSpriteMaterial::~QQuickAnimatedSpriteMaterial() + { + delete texture; + } + + class AnimatedSpriteMaterialData : public QSGMaterialShader + { + public: + AnimatedSpriteMaterialData(const char * /* vertexFile */ = 0, const char * /* fragmentFile */ = 0) + { + } + + void deactivate() { + QSGMaterialShader::deactivate(); + + for (int i=0; i<8; ++i) { + program()->setAttributeArray(i, GL_FLOAT, chunkOfBytes, 1, 0); + } + } + + virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *) + { + QQuickAnimatedSpriteMaterial *m = static_cast(newEffect); + m->texture->bind(); + + program()->setUniformValue(m_opacity_id, state.opacity()); + program()->setUniformValue(m_animData_id, m->animW, m->animH, m->animT); + program()->setUniformValue(m_animPos_id, m->animX1, m->animY1, m->animX2, m->animY2); + program()->setUniformValue(m_size_id, m->elementWidth, m->elementHeight); + + if (state.isMatrixDirty()) + program()->setUniformValue(m_matrix_id, state.combinedMatrix()); + } + + virtual void initialize() { + m_matrix_id = program()->uniformLocation("qt_Matrix"); + m_opacity_id = program()->uniformLocation("qt_Opacity"); + m_animData_id = program()->uniformLocation("animData"); + m_animPos_id = program()->uniformLocation("animPos"); + m_size_id = program()->uniformLocation("size"); + } + + virtual const char *vertexShader() const { return vertexShaderCode; } + virtual const char *fragmentShader() const { return fragmentShaderCode; } + + virtual char const *const *attributeNames() const { + static const char *attr[] = { + "vTex", + 0 + }; + return attr; + } + + int m_matrix_id; + int m_opacity_id; + int m_animData_id; + int m_animPos_id; + int m_size_id; + + static float chunkOfBytes[1024]; + }; + + float AnimatedSpriteMaterialData::chunkOfBytes[1024]; + + QSGMaterialShader *QQuickAnimatedSpriteMaterial::createShader() const + { + return new AnimatedSpriteMaterialData; + } + + struct AnimatedSpriteVertex { + float tx; + float ty; + }; + + struct AnimatedSpriteVertices { + AnimatedSpriteVertex v1; + AnimatedSpriteVertex v2; + AnimatedSpriteVertex v3; + AnimatedSpriteVertex v4; + }; + + /*! + \qmlclass AnimatedSprite QQuickAnimatedSprite + \inqmlmodule QtQuick 2 + \inherits Item + \brief The AnimatedSprite element draws a sprite animation + */ + + /*! + \qmlproperty bool QtQuick2::AnimatedSprite::running + + Whether the sprite is animating or not. + + Default is true + */ + + /*! + \qmlproperty bool QtQuick2::AnimatedSprite::interpolate + + If true, interpolation will occur between sprite frames to make the + animation appear smoother. + + Default is true. + */ + + /*! + \qmlproperty qreal QtQuick2::AnimatedSprite::frameRate + + Frames per second to show in the animation. Values below 0 are invalid. + + If frameRate is valid then it will be used to calculate the duration of the frames. + If not, and frameDuration is valid , then frameDuration will be used. + */ + + /*! + \qmlproperty int QtQuick2::AnimatedSprite::frameDuration + + Duration of each frame of the animation. Values below 0 are invalid. + + If frameRate is valid then it will be used to calculate the duration of the frames. + If not, and frameDuration is valid, then frameDuration will be used. + */ + + /*! + \qmlproperty int QtQuick2::AnimatedSprite::frameCount + + Number of frames in this AnimatedSprite. + */ + /*! + \qmlproperty int QtQuick2::AnimatedSprite::frameHeight + + Height of a single frame in this AnimatedSprite. + + May be omitted if it is the only sprite in the file. + */ + /*! + \qmlproperty int QtQuick2::AnimatedSprite::frameWidth + + Width of a single frame in this AnimatedSprite. + + May be omitted if it is the only sprite in the file. + */ + /*! + \qmlproperty int QtQuick2::AnimatedSprite::frameX + + The X coordinate in the image file of the first frame of the AnimatedSprite. + + May be omitted if the first frame starts in the upper left corner of the file. + */ + /*! + \qmlproperty int QtQuick2::AnimatedSprite::frameY + + The Y coordinate in the image file of the first frame of the AnimatedSprite. + + May be omitted if the first frame starts in the upper left corner of the file. + */ + /*! + \qmlproperty url QtQuick2::AnimatedSprite::source + + The image source for the animation. + + If frameHeight and frameWidth are not specified, it is assumed to be a single long row of square frames. + Otherwise, it can be multiple contiguous rows or rectangluar frames, when one row runs out the next will be used. + + If frameX and frameY are specified, the row of frames will be taken with that x/y coordinate as the upper left corner. + */ + + /*! + \qmlproperty bool QtQuick2::AnimatedSprite::reverse + + If true, then the animation will be played in reverse. + + Default is false. + */ + + /*! + \qmlproperty bool QtQuick2::AnimatedSprite::frameSync + + If true, then the animation will have no duration. Instead, the animation will advance + one frame each time a frame is rendered to the screen. This syncronizes it with the painting + rate as opposed to elapsed time. + + If frameSync is set to true, it overrides both frameRate and frameDuration. + + Default is false. + */ + + /*! + \qmlproperty int QtQuick2::AnimatedSprite::loops + + After playing the animation this many times, the animation will automatically stop. Negative values are invalid. + + If this is set to AnimatedSprite.Infinite the animation will not stop playing on its own. + + Default is AnimatedSprite.Infinite + */ + + /*! + \qmlproperty bool QtQuick2::AnimatedSprite::paused + + When paused, the current frame can be advanced manually. + + Default is false. + */ + + /*! + \qmlproperty int QtQuick2::AnimatedSprite::currentFrame + + When paused, the current frame can be advanced manually by setting this property or calling advance(). + + */ + + //TODO: Implicitly size element to size of sprite + QQuickAnimatedSprite::QQuickAnimatedSprite(QQuickItem *parent) : + QQuickItem(parent) + , m_node(0) + , m_material(0) + , m_sprite(new QQuickSprite) + , m_spriteEngine(0) + , m_curFrame(0) + , m_pleaseReset(false) + , m_running(true) + , m_paused(false) + , m_interpolate(true) + , m_loops(-1) + , m_curLoop(0) + , m_pauseOffset(0) + { + setFlag(ItemHasContents); + connect(this, SIGNAL(runningChanged(bool)), + this, SLOT(update())); + } + + void QQuickAnimatedSprite::reloadImage() + { + if (!isComponentComplete()) + return; + createEngine();//### It's not as inefficient as it sounds, but it still sucks having to recreate the engine + } + + void QQuickAnimatedSprite::componentComplete() + { + createEngine(); + QQuickItem::componentComplete(); + if (m_running) + start(); + } + + void QQuickAnimatedSprite::start() + { + if (m_running) + return; + m_curLoop = 0; + m_timestamp.start(); + m_running = true; + emit runningChanged(true); + update(); + } + + void QQuickAnimatedSprite::stop() + { + if (!m_running) + return; + m_running = false; + emit runningChanged(false); + } + + void QQuickAnimatedSprite::advance(int frames) + { + if (!frames) + return; + //TODO-C: May not work when running - only when paused + m_curFrame += frames; + while (m_curFrame < 0) + m_curFrame += m_sprite->frames(); + m_curFrame = m_curFrame % m_sprite->frames(); + emit currentFrameChanged(m_curFrame); + } + + void QQuickAnimatedSprite::pause() + { + if (m_paused) + return; + m_pauseOffset = m_timestamp.elapsed(); + m_paused = true; + emit pausedChanged(true); + } + + void QQuickAnimatedSprite::resume() + { + if (!m_paused) + return; + m_pauseOffset = m_pauseOffset - m_timestamp.elapsed(); + m_paused = false; + emit pausedChanged(false); + } + + void QQuickAnimatedSprite::createEngine() + { + if (m_spriteEngine) + delete m_spriteEngine; + QList spriteList; + spriteList << m_sprite; + m_spriteEngine = new QQuickSpriteEngine(QList(spriteList), this); + m_spriteEngine->startAssemblingImage(); + reset(); + } + + static QSGGeometry::Attribute AnimatedSprite_Attributes[] = { + QSGGeometry::Attribute::create(0, 2, GL_FLOAT), // tex + }; + + static QSGGeometry::AttributeSet AnimatedSprite_AttributeSet = + { + 1, // Attribute Count + 2 * sizeof(float), + AnimatedSprite_Attributes + }; + + QSGGeometryNode* QQuickAnimatedSprite::buildNode() + { + if (!m_spriteEngine) { + qmlInfo(this) << "No sprite engine..."; + return 0; - } else if (m_spriteEngine->status() == QDeclarativePixmap::Null) { ++ } else if (m_spriteEngine->status() == QQuickPixmap::Null) { + m_spriteEngine->startAssemblingImage(); + update();//Schedule another update, where we will check again + return 0; - } else if (m_spriteEngine->status() == QDeclarativePixmap::Loading) { ++ } else if (m_spriteEngine->status() == QQuickPixmap::Loading) { + update();//Schedule another update, where we will check again + return 0; + } + + m_material = new QQuickAnimatedSpriteMaterial(); + + QImage image = m_spriteEngine->assembledImage(); + if (image.isNull()) + return 0; + m_sheetSize = QSizeF(image.size()); + m_material->texture = canvas()->createTextureFromImage(image); + m_material->texture->setFiltering(QSGTexture::Linear); + m_spriteEngine->start(0); + m_material->animT = 0; + m_material->animX1 = m_spriteEngine->spriteX() / m_sheetSize.width(); + m_material->animY1 = m_spriteEngine->spriteY() / m_sheetSize.height(); + m_material->animX2 = m_material->animX1; + m_material->animY2 = m_material->animY1; + m_material->animW = m_spriteEngine->spriteWidth() / m_sheetSize.width(); + m_material->animH = m_spriteEngine->spriteHeight() / m_sheetSize.height(); + m_material->elementWidth = width(); + m_material->elementHeight = height(); + + int vCount = 4; + int iCount = 6; + QSGGeometry *g = new QSGGeometry(AnimatedSprite_AttributeSet, vCount, iCount); + g->setDrawingMode(GL_TRIANGLES); + + AnimatedSpriteVertices *p = (AnimatedSpriteVertices *) g->vertexData(); + + p->v1.tx = 0; + p->v1.ty = 0; + + p->v2.tx = 1.0; + p->v2.ty = 0; + + p->v3.tx = 0; + p->v3.ty = 1.0; + + p->v4.tx = 1.0; + p->v4.ty = 1.0; + + quint16 *indices = g->indexDataAsUShort(); + indices[0] = 0; + indices[1] = 1; + indices[2] = 2; + indices[3] = 1; + indices[4] = 3; + indices[5] = 2; + + + m_timestamp.start(); + m_node = new QSGGeometryNode(); + m_node->setGeometry(g); + m_node->setMaterial(m_material); + m_node->setFlag(QSGGeometryNode::OwnsMaterial); + return m_node; + } + + void QQuickAnimatedSprite::reset() + { + m_pleaseReset = true; + } + + QSGNode *QQuickAnimatedSprite::updatePaintNode(QSGNode *, UpdatePaintNodeData *) + { + if (m_pleaseReset) { + delete m_node; + + m_node = 0; + m_material = 0; + m_pleaseReset = false; + } + + prepareNextFrame(); + + if (m_running) { + update(); + if (m_node) + m_node->markDirty(QSGNode::DirtyMaterial); + } + + return m_node; + } + + void QQuickAnimatedSprite::prepareNextFrame() + { + if (m_node == 0) + m_node = buildNode(); + if (m_node == 0) //error creating node + return; + + uint timeInt = m_timestamp.elapsed() + m_pauseOffset; + qreal time = timeInt / 1000.; + m_material->elementHeight = height(); + m_material->elementWidth = width(); + + double frameAt; //double just for modf + qreal progress; + if (!m_paused) { + //Advance State (keeps time for psuedostates) + m_spriteEngine->updateSprites(timeInt); + + //Advance AnimatedSprite + qreal animT = m_spriteEngine->spriteStart()/1000.0; + qreal frameCount = m_spriteEngine->spriteFrames(); + qreal frameDuration = m_spriteEngine->spriteDuration()/frameCount; + if (frameDuration > 0) { + qreal frame = (time - animT)/(frameDuration / 1000.0); + frame = qBound(qreal(0.0), frame, frameCount - qreal(1.0));//Stop at count-1 frames until we have between anim interpolation + progress = modf(frame,&frameAt); + if (m_curFrame > frameAt) //went around + m_curLoop++; + m_curFrame = frameAt; + } else { + m_curFrame++; + if (m_curFrame >= frameCount){ + m_curFrame = 0; + m_curLoop++; + m_spriteEngine->advance(); + } + frameAt = m_curFrame; + progress = 0; + } + if (m_loops > 0 && m_curLoop >= m_loops) { + frameAt = 0; + m_running = false; + } + } else { + frameAt = m_curFrame; + } + if (m_spriteEngine->sprite()->reverse()) + frameAt = (m_spriteEngine->spriteFrames() - 1) - frameAt; + qreal y = m_spriteEngine->spriteY() / m_sheetSize.height(); + qreal w = m_spriteEngine->spriteWidth() / m_sheetSize.width(); + qreal h = m_spriteEngine->spriteHeight() / m_sheetSize.height(); + qreal x1 = m_spriteEngine->spriteX() / m_sheetSize.width(); + x1 += frameAt * w; + qreal x2 = x1; + if (frameAt < (m_spriteEngine->spriteFrames()-1)) + x2 += w; + + m_material->animX1 = x1; + m_material->animY1 = y; + m_material->animX2 = x2; + m_material->animY2 = y; + m_material->animW = w; + m_material->animH = h; + m_material->animT = m_interpolate ? progress : 0.0; + } + + QT_END_NAMESPACE diff --cc src/quick/items/qquickanimatedsprite_p.h index 0000000,062b191..708f94b mode 000000,100644..100644 --- a/src/quick/items/qquickanimatedsprite_p.h +++ b/src/quick/items/qquickanimatedsprite_p.h @@@ -1,0 -1,373 +1,373 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + #ifndef QQUICKANIMATEDSPRITE_P_H + #define QQUICKANIMATEDSPRITE_P_H + + #include + #include + #include + + QT_BEGIN_HEADER + + QT_BEGIN_NAMESPACE + + class QSGContext; + class QQuickSprite; + class QQuickSpriteEngine; + class QSGGeometryNode; + class QQuickAnimatedSpriteMaterial; + class Q_AUTOTEST_EXPORT QQuickAnimatedSprite : public QQuickItem + { + Q_OBJECT + Q_PROPERTY(bool running READ running WRITE setRunning NOTIFY runningChanged) + Q_PROPERTY(bool interpolate READ interpolate WRITE setInterpolate NOTIFY interpolateChanged) + //###try to share similar spriteEngines for less overhead? + //These properties come out of QQuickSprite, since a SimpleSpriteImage is a renderer for a single sprite + Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) + Q_PROPERTY(bool reverse READ reverse WRITE setReverse NOTIFY reverseChanged) + Q_PROPERTY(bool frameSync READ frameSync WRITE setFrameSync NOTIFY frameSyncChanged) + Q_PROPERTY(int frameCount READ frameCount WRITE setFrameCount NOTIFY frameCountChanged) + //If frame height or width is not specified, it is assumed to be a single long row of square frames. + //Otherwise, it can be multiple contiguous rows, when one row runs out the next will be used. + Q_PROPERTY(int frameHeight READ frameHeight WRITE setFrameHeight NOTIFY frameHeightChanged) + Q_PROPERTY(int frameWidth READ frameWidth WRITE setFrameWidth NOTIFY frameWidthChanged) + Q_PROPERTY(int frameX READ frameX WRITE setFrameX NOTIFY frameXChanged) + Q_PROPERTY(int frameY READ frameY WRITE setFrameY NOTIFY frameYChanged) + //Precedence order: frameRate, frameDuration + Q_PROPERTY(qreal frameRate READ frameRate WRITE setFrameRate NOTIFY frameRateChanged RESET resetFrameRate) + Q_PROPERTY(int frameDuration READ frameDuration WRITE setFrameDuration NOTIFY frameDurationChanged RESET resetFrameDuration) + //Extra Simple Sprite Stuff + Q_PROPERTY(int loops READ loops WRITE setLoops NOTIFY loopsChanged) + Q_PROPERTY(bool paused READ paused WRITE setPaused NOTIFY pausedChanged) + Q_PROPERTY(int currentFrame READ currentFrame WRITE setCurrentFrame NOTIFY currentFrameChanged) + + Q_ENUMS(LoopParameters) + public: + explicit QQuickAnimatedSprite(QQuickItem *parent = 0); + enum LoopParameters { + Infinite = -1 + }; + + bool running() const + { + return m_running; + } + + bool interpolate() const + { + return m_interpolate; + } + + QUrl source() const + { + return m_sprite->source(); + } + + bool reverse() const + { + return m_sprite->reverse(); + } + + bool frameSync() const + { + return m_sprite->frameSync(); + } + + int frameCount() const + { + return m_sprite->frames(); + } + + int frameHeight() const + { + return m_sprite->frameHeight(); + } + + int frameWidth() const + { + return m_sprite->frameWidth(); + } + + int frameX() const + { + return m_sprite->frameX(); + } + + int frameY() const + { + return m_sprite->frameY(); + } + + qreal frameRate() const + { + return m_sprite->frameRate(); + } + + int frameDuration() const + { + return m_sprite->frameDuration(); + } + + int loops() const + { + return m_loops; + } + + bool paused() const + { + return m_paused; + } + + int currentFrame() const + { + return m_curFrame; + } + + signals: + + void pausedChanged(bool arg); + void runningChanged(bool arg); + void interpolateChanged(bool arg); + + void sourceChanged(QUrl arg); + + void reverseChanged(bool arg); + + void frameSyncChanged(bool arg); + + void frameCountChanged(int arg); + + void frameHeightChanged(int arg); + + void frameWidthChanged(int arg); + + void frameXChanged(int arg); + + void frameYChanged(int arg); + + void frameRateChanged(qreal arg); + + void frameDurationChanged(int arg); + + void loopsChanged(int arg); + + void currentFrameChanged(int arg); + + public slots: + void start(); + void stop(); + void restart() {stop(); start();} + void advance(int frames=1); + void pause(); + void resume(); + + void setRunning(bool arg) + { + if (m_running != arg) { + if (m_running) + stop(); + else + start(); + } + } + + void setPaused(bool arg) + { + if (m_paused != arg) { + if (m_paused) + resume(); + else + pause(); + } + } + + void setInterpolate(bool arg) + { + if (m_interpolate != arg) { + m_interpolate = arg; + emit interpolateChanged(arg); + } + } + + void setSource(QUrl arg) + { + if (m_sprite->m_source != arg) { + m_sprite->setSource(arg); + emit sourceChanged(arg); + } + } + + void setReverse(bool arg) + { + if (m_sprite->m_reverse != arg) { + m_sprite->setReverse(arg); + emit reverseChanged(arg); + } + } + + void setFrameSync(bool arg) + { + if (m_sprite->m_frameSync != arg) { + m_sprite->setFrameSync(arg); + emit frameSyncChanged(arg); + } + } + + void setFrameCount(int arg) + { + if (m_sprite->m_frames != arg) { + m_sprite->setFrameCount(arg); + emit frameCountChanged(arg); + reloadImage(); + } + } + + void setFrameHeight(int arg) + { + if (m_sprite->m_frameHeight != arg) { + m_sprite->setFrameHeight(arg); + emit frameHeightChanged(arg); + reloadImage(); + } + } + + void setFrameWidth(int arg) + { + if (m_sprite->m_frameWidth != arg) { + m_sprite->setFrameWidth(arg); + emit frameWidthChanged(arg); + reloadImage(); + } + } + + void setFrameX(int arg) + { + if (m_sprite->m_frameX != arg) { + m_sprite->setFrameX(arg); + emit frameXChanged(arg); + reloadImage(); + } + } + + void setFrameY(int arg) + { + if (m_sprite->m_frameY != arg) { + m_sprite->setFrameY(arg); + emit frameYChanged(arg); + reloadImage(); + } + } + + void setFrameRate(qreal arg) + { + if (m_sprite->m_frameRate != arg) { + m_sprite->setFrameRate(arg); + emit frameRateChanged(arg); + } + } + + void setFrameDuration(int arg) + { + if (m_sprite->m_frameDuration != arg) { + m_sprite->setFrameDuration(arg); + emit frameDurationChanged(arg); + } + } + + void resetFrameRate() + { + setFrameRate(-1.0); + } + + void resetFrameDuration() + { + setFrameDuration(-1); + } + + void setLoops(int arg) + { + if (m_loops != arg) { + m_loops = arg; + emit loopsChanged(arg); + } + } + + void setCurrentFrame(int arg) //TODO-C: Probably only works when paused + { + if (m_curFrame != arg) { + m_curFrame = arg; + emit currentFrameChanged(arg); //TODO-C Only emitted on manual advance! + } + } + + + private slots: + void createEngine(); + protected: + void reset(); + void componentComplete(); + QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *); + private: + void prepareNextFrame(); + void reloadImage(); + QSGGeometryNode* buildNode(); + QSGGeometryNode *m_node; + QQuickAnimatedSpriteMaterial *m_material; + QQuickSprite* m_sprite; + QQuickSpriteEngine* m_spriteEngine; + QTime m_timestamp; + int m_curFrame; + bool m_pleaseReset; + bool m_running; + bool m_paused; + bool m_interpolate; + QSizeF m_sheetSize; + int m_loops; + int m_curLoop; + int m_pauseOffset; + }; + + QT_END_NAMESPACE + + QT_END_HEADER + + #endif // QQUICKANIMATEDSPRITE_P_H diff --cc src/quick/items/qquickitem.cpp index 357c72c,7ca683f..77808a6 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@@ -1627,7 -1626,7 +1627,7 @@@ void QQuickItemPrivate::setAccessibleFl \inmodule QtQuick -- All visual items in Qt Declarative inherit from QQuickItem. Although QQuickItem ++ All visual items in Qt Quick inherit from QQuickItem. Although QQuickItem has no visual appearance, it defines all the properties that are common across visual items - such as the x and y position, the width and height, \l {anchor-layout}{anchoring} and key handling. @@@ -1646,7 -1645,7 +1646,7 @@@ \ingroup qml-basic-visual-elements \brief The Item is the most basic of all visual items in QML. -- All visual items in Qt Declarative inherit from Item. Although Item ++ All visual items in Qt Quick inherit from Item. Although Item has no visual appearance, it defines all the properties that are common across visual items - such as the x and y position, the width and height, \l {anchor-layout}{anchoring} and key handling. diff --cc src/quick/items/qquickitemanimation.cpp index 1316a3d,0000000..32f1047 mode 100644,000000..100644 --- a/src/quick/items/qquickitemanimation.cpp +++ b/src/quick/items/qquickitemanimation.cpp @@@ -1,1042 -1,0 +1,1044 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickitemanimation_p.h" +#include "qquickitemanimation_p_p.h" +#include "qquickstateoperations_p.h" + +#include +#include + +#include +#include +#include "private/qsequentialanimationgroupjob_p.h" +#include "private/qparallelanimationgroupjob_p.h" +#include + +QT_BEGIN_NAMESPACE + +/*! + \qmlclass ParentAnimation QQuickParentAnimation + \inqmlmodule QtQuick 2 + \ingroup qml-animation-transition + \since QtQuick 2.0 + \inherits Animation + \brief The ParentAnimation element animates changes in parent values. + + ParentAnimation is used to animate a parent change for an \l Item. + + For example, the following ParentChange changes \c blueRect to become + a child of \c redRect when it is clicked. The inclusion of the + ParentAnimation, which defines a NumberAnimation to be applied during + the transition, ensures the item animates smoothly as it moves to + its new parent: + + \snippet doc/src/snippets/qml/parentanimation.qml 0 + + A ParentAnimation can contain any number of animations. These animations will + be run in parallel; to run them sequentially, define them within a + SequentialAnimation. + + In some cases, such as when reparenting between items with clipping enabled, it is useful + to animate the parent change via another item that does not have clipping + enabled. Such an item can be set using the \l via property. + + For convenience, when a ParentAnimation is used in a \l Transition, it will + animate any ParentChange that has occurred during the state change. + This can be overridden by setting a specific target item using the + \l target property. + + Like any other animation element, a ParentAnimation can be applied in a + number of ways, including transitions, behaviors and property value + sources. The \l {QML Animation and Transitions} documentation shows a + variety of methods for creating animations. + + \sa {QML Animation and Transitions}, {declarative/animation/basics}{Animation basics example} +*/ +QQuickParentAnimation::QQuickParentAnimation(QObject *parent) + : QQuickAnimationGroup(*(new QQuickParentAnimationPrivate), parent) +{ +} + +QQuickParentAnimation::~QQuickParentAnimation() +{ +} + +/*! + \qmlproperty Item QtQuick2::ParentAnimation::target + The item to reparent. + + When used in a transition, if no target is specified, all + ParentChange occurrences are animated by the ParentAnimation. +*/ +QQuickItem *QQuickParentAnimation::target() const +{ + Q_D(const QQuickParentAnimation); + return d->target; +} + +void QQuickParentAnimation::setTargetObject(QQuickItem *target) +{ + Q_D(QQuickParentAnimation); + if (target == d->target) + return; + + d->target = target; + emit targetChanged(); +} + +/*! + \qmlproperty Item QtQuick2::ParentAnimation::newParent + The new parent to animate to. + + If the ParentAnimation is defined within a \l Transition or \l Behavior, + this value defaults to the value defined in the end state of the + \l Transition, or the value of the property change that triggered the + \l Behavior. +*/ +QQuickItem *QQuickParentAnimation::newParent() const +{ + Q_D(const QQuickParentAnimation); + return d->newParent; +} + +void QQuickParentAnimation::setNewParent(QQuickItem *newParent) +{ + Q_D(QQuickParentAnimation); + if (newParent == d->newParent) + return; + + d->newParent = newParent; + emit newParentChanged(); +} + +/*! + \qmlproperty Item QtQuick2::ParentAnimation::via + The item to reparent via. This provides a way to do an unclipped animation + when both the old parent and new parent are clipped. + + \qml + ParentAnimation { + target: myItem + via: topLevelItem + // ... + } + \endqml +*/ +QQuickItem *QQuickParentAnimation::via() const +{ + Q_D(const QQuickParentAnimation); + return d->via; +} + +void QQuickParentAnimation::setVia(QQuickItem *via) +{ + Q_D(QQuickParentAnimation); + if (via == d->via) + return; + + d->via = via; + emit viaChanged(); +} + +//### mirrors same-named function in QQuickItem +QPointF QQuickParentAnimationPrivate::computeTransformOrigin(QQuickItem::TransformOrigin origin, qreal width, qreal height) const +{ + switch (origin) { + default: + case QQuickItem::TopLeft: + return QPointF(0, 0); + case QQuickItem::Top: + return QPointF(width / 2., 0); + case QQuickItem::TopRight: + return QPointF(width, 0); + case QQuickItem::Left: + return QPointF(0, height / 2.); + case QQuickItem::Center: + return QPointF(width / 2., height / 2.); + case QQuickItem::Right: + return QPointF(width, height / 2.); + case QQuickItem::BottomLeft: + return QPointF(0, height); + case QQuickItem::Bottom: + return QPointF(width / 2., height); + case QQuickItem::BottomRight: + return QPointF(width, height); + } +} + +QAbstractAnimationJob* QQuickParentAnimation::transition(QQuickStateActions &actions, + QQmlProperties &modified, + TransitionDirection direction, + QObject *defaultTarget) +{ + Q_D(QQuickParentAnimation); + + struct QQuickParentAnimationData : public QAbstractAnimationAction + { + QQuickParentAnimationData() {} + ~QQuickParentAnimationData() { qDeleteAll(pc); } + + QQuickStateActions actions; + //### reverse should probably apply on a per-action basis + bool reverse; + QList pc; + virtual void doAction() + { + for (int ii = 0; ii < actions.count(); ++ii) { + const QQuickAction &action = actions.at(ii); + if (reverse) + action.event->reverse(); + else + action.event->execute(); + } + } + }; + + QQuickParentAnimationData *data = new QQuickParentAnimationData; + QQuickParentAnimationData *viaData = new QQuickParentAnimationData; + + bool hasExplicit = false; + if (d->target && d->newParent) { + data->reverse = false; + QQuickAction myAction; + QQuickParentChange *pc = new QQuickParentChange; + pc->setObject(d->target); + pc->setParent(d->newParent); + myAction.event = pc; + data->pc << pc; + data->actions << myAction; + hasExplicit = true; + if (d->via) { + viaData->reverse = false; + QQuickAction myVAction; + QQuickParentChange *vpc = new QQuickParentChange; + vpc->setObject(d->target); + vpc->setParent(d->via); + myVAction.event = vpc; + viaData->pc << vpc; + viaData->actions << myVAction; + } + //### once actions have concept of modified, + // loop to match appropriate ParentChanges and mark as modified + } + + if (!hasExplicit) + for (int i = 0; i < actions.size(); ++i) { + QQuickAction &action = actions[i]; + if (action.event && action.event->type() == QQuickActionEvent::ParentChange + && (!d->target || static_cast(action.event)->object() == d->target)) { + + QQuickParentChange *pc = static_cast(action.event); + QQuickAction myAction = action; + data->reverse = action.reverseEvent; + + //### this logic differs from PropertyAnimation + // (probably a result of modified vs. done) + if (d->newParent) { + QQuickParentChange *epc = new QQuickParentChange; + epc->setObject(static_cast(action.event)->object()); + epc->setParent(d->newParent); + myAction.event = epc; + data->pc << epc; + data->actions << myAction; + pc = epc; + } else { + action.actionDone = true; + data->actions << myAction; + } + + if (d->via) { + viaData->reverse = false; + QQuickAction myAction; + QQuickParentChange *vpc = new QQuickParentChange; + vpc->setObject(pc->object()); + vpc->setParent(d->via); + myAction.event = vpc; + viaData->pc << vpc; + viaData->actions << myAction; + QQuickAction dummyAction; + QQuickAction &xAction = pc->xIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction; + QQuickAction &yAction = pc->yIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction; + QQuickAction &sAction = pc->scaleIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction; + QQuickAction &rAction = pc->rotationIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction; + QQuickItem *target = pc->object(); + QQuickItem *targetParent = action.reverseEvent ? pc->originalParent() : pc->parent(); + + //### this mirrors the logic in QQuickParentChange. + bool ok; + const QTransform &transform = targetParent->itemTransform(d->via, &ok); + if (transform.type() >= QTransform::TxShear || !ok) { + qmlInfo(this) << QQuickParentAnimation::tr("Unable to preserve appearance under complex transform"); + ok = false; + } + + qreal scale = 1; + qreal rotation = 0; + bool isRotate = (transform.type() == QTransform::TxRotate) || (transform.m11() < 0); + if (ok && !isRotate) { + if (transform.m11() == transform.m22()) + scale = transform.m11(); + else { + qmlInfo(this) << QQuickParentAnimation::tr("Unable to preserve appearance under non-uniform scale"); + ok = false; + } + } else if (ok && isRotate) { + if (transform.m11() == transform.m22()) + scale = qSqrt(transform.m11()*transform.m11() + transform.m12()*transform.m12()); + else { + qmlInfo(this) << QQuickParentAnimation::tr("Unable to preserve appearance under non-uniform scale"); + ok = false; + } + + if (scale != 0) + rotation = atan2(transform.m12()/scale, transform.m11()/scale) * 180/M_PI; + else { + qmlInfo(this) << QQuickParentAnimation::tr("Unable to preserve appearance under scale of 0"); + ok = false; + } + } + + const QPointF &point = transform.map(QPointF(xAction.toValue.toReal(),yAction.toValue.toReal())); + qreal x = point.x(); + qreal y = point.y(); + if (ok && target->transformOrigin() != QQuickItem::TopLeft) { + qreal w = target->width(); + qreal h = target->height(); + if (pc->widthIsSet() && i < actions.size() - 1) + w = actions[++i].toValue.toReal(); + if (pc->heightIsSet() && i < actions.size() - 1) + h = actions[++i].toValue.toReal(); + const QPointF &transformOrigin + = d->computeTransformOrigin(target->transformOrigin(), w,h); + qreal tempxt = transformOrigin.x(); + qreal tempyt = transformOrigin.y(); + QTransform t; + t.translate(-tempxt, -tempyt); + t.rotate(rotation); + t.scale(scale, scale); + t.translate(tempxt, tempyt); + const QPointF &offset = t.map(QPointF(0,0)); + x += offset.x(); + y += offset.y(); + } + + if (ok) { + //qDebug() << x << y << rotation << scale; + xAction.toValue = x; + yAction.toValue = y; + sAction.toValue = sAction.toValue.toReal() * scale; + rAction.toValue = rAction.toValue.toReal() + rotation; + } + } + } + } + + QSequentialAnimationGroupJob *topLevelGroup = new QSequentialAnimationGroupJob; + QActionAnimation *viaAction = d->via ? new QActionAnimation : 0; + QActionAnimation *targetAction = new QActionAnimation; + //we'll assume the common case by far is to have children, and always create ag + QParallelAnimationGroupJob *ag = new QParallelAnimationGroupJob; + + if (data->actions.count()) { + if (d->via) + viaAction->setAnimAction(viaData); + targetAction->setAnimAction(data); + + //take care of any child animations + bool valid = d->defaultProperty.isValid(); + QAbstractAnimationJob* anim; + for (int ii = 0; ii < d->animations.count(); ++ii) { + if (valid) + d->animations.at(ii)->setDefaultTarget(d->defaultProperty); + anim = d->animations.at(ii)->transition(actions, modified, direction, defaultTarget); + ag->appendAnimation(anim); + } + + //TODO: simplify/clarify logic + bool forwards = direction == QQuickAbstractAnimation::Forward; + if (forwards) { + topLevelGroup->appendAnimation(d->via ? viaAction : targetAction); + topLevelGroup->appendAnimation(ag); + if (d->via) + topLevelGroup->appendAnimation(targetAction); + } else { + if (d->via) + topLevelGroup->appendAnimation(targetAction); + topLevelGroup->appendAnimation(ag); + topLevelGroup->appendAnimation(d->via ? viaAction : targetAction); + } + } else { + delete data; + delete viaData; + } + + return initInstance(topLevelGroup); +} + +/*! + \qmlclass AnchorAnimation QQuickAnchorAnimation + \inqmlmodule QtQuick 2 + \ingroup qml-animation-transition + \inherits Animation + \brief The AnchorAnimation element animates changes in anchor values. + + AnchorAnimation is used to animate an anchor change. + + In the following snippet we animate the addition of a right anchor to a \l Rectangle: + + \snippet doc/src/snippets/qml/anchoranimation.qml 0 + + For convenience, when an AnchorAnimation is used in a \l Transition, it will + animate any AnchorChanges that have occurred during the state change. + This can be overridden by setting a specific target item using the + \l target property. + + Like any other animation element, an AnchorAnimation can be applied in a + number of ways, including transitions, behaviors and property value + sources. The \l {QML Animation and Transitions} documentation shows a + variety of methods for creating animations. + + \sa {QML Animation and Transitions}, AnchorChanges +*/ +QQuickAnchorAnimation::QQuickAnchorAnimation(QObject *parent) +: QQuickAbstractAnimation(*(new QQuickAnchorAnimationPrivate), parent) +{ +} + +QQuickAnchorAnimation::~QQuickAnchorAnimation() +{ +} + +/*! + \qmlproperty list QtQuick2::AnchorAnimation::targets + The items to reanchor. + + If no targets are specified all AnchorChanges will be + animated by the AnchorAnimation. +*/ +QQmlListProperty QQuickAnchorAnimation::targets() +{ + Q_D(QQuickAnchorAnimation); + return QQmlListProperty(this, d->targets); +} + +/*! + \qmlproperty int QtQuick2::AnchorAnimation::duration + This property holds the duration of the animation, in milliseconds. + + The default value is 250. +*/ +int QQuickAnchorAnimation::duration() const +{ + Q_D(const QQuickAnchorAnimation); + return d->duration; +} + +void QQuickAnchorAnimation::setDuration(int duration) +{ + if (duration < 0) { + qmlInfo(this) << tr("Cannot set a duration of < 0"); + return; + } + + Q_D(QQuickAnchorAnimation); + if (d->duration == duration) + return; + d->duration = duration; + emit durationChanged(duration); +} + +/*! + \qmlproperty enumeration QtQuick2::AnchorAnimation::easing.type + \qmlproperty real QtQuick2::AnchorAnimation::easing.amplitude + \qmlproperty real QtQuick2::AnchorAnimation::easing.overshoot + \qmlproperty real QtQuick2::AnchorAnimation::easing.period + \brief the easing curve used for the animation. + + To specify an easing curve you need to specify at least the type. For some curves you can also specify + amplitude, period and/or overshoot. The default easing curve is + Linear. + + \qml + AnchorAnimation { easing.type: Easing.InOutQuad } + \endqml + + See the \l{PropertyAnimation::easing.type} documentation for information + about the different types of easing curves. +*/ +QEasingCurve QQuickAnchorAnimation::easing() const +{ + Q_D(const QQuickAnchorAnimation); + return d->easing; +} + +void QQuickAnchorAnimation::setEasing(const QEasingCurve &e) +{ + Q_D(QQuickAnchorAnimation); + if (d->easing == e) + return; + + d->easing = e; + emit easingChanged(e); +} + +QAbstractAnimationJob* QQuickAnchorAnimation::transition(QQuickStateActions &actions, + QQmlProperties &modified, + TransitionDirection direction, + QObject *defaultTarget) +{ + Q_UNUSED(modified); + Q_UNUSED(defaultTarget); + Q_D(QQuickAnchorAnimation); + QQuickAnimationPropertyUpdater *data = new QQuickAnimationPropertyUpdater; + data->interpolatorType = QMetaType::QReal; + data->interpolator = d->interpolator; + data->reverse = direction == Backward ? true : false; + data->fromSourced = false; + data->fromDefined = false; + + for (int ii = 0; ii < actions.count(); ++ii) { + QQuickAction &action = actions[ii]; + if (action.event && action.event->type() == QQuickActionEvent::AnchorChanges + && (d->targets.isEmpty() || d->targets.contains(static_cast(action.event)->object()))) { + data->actions << static_cast(action.event)->additionalActions(); + } + } + + QQuickBulkValueAnimator *animator = new QQuickBulkValueAnimator; + if (data->actions.count()) { + animator->setAnimValue(data); + animator->setFromSourcedValue(&data->fromSourced); + } else { + delete data; + } + ++ animator->setDuration(d->duration); ++ animator->setEasingCurve(d->easing); + return initInstance(animator); +} + +/*! + \qmlclass PathAnimation QQuickPathAnimation + \inqmlmodule QtQuick 2 + \ingroup qml-animation-transition + \inherits Animation + \since QtQuick 2.0 + \brief The PathAnimation element animates an item along a path. + + When used in a transition, the path can be specified without start + or end points, for example: + \qml + PathAnimation { + path: Path { + //no startX, startY + PathCurve { x: 100; y: 100} + PathCurve {} //last element is empty with no end point specified + } + } + \endqml + + In the above case, the path start will be the item's current position, and the + path end will be the item's target position in the target state. + + \sa {QML Animation and Transitions}, PathInterpolator +*/ +QQuickPathAnimation::QQuickPathAnimation(QObject *parent) +: QQuickAbstractAnimation(*(new QQuickPathAnimationPrivate), parent) +{ +} + +QQuickPathAnimation::~QQuickPathAnimation() +{ + Q_D(QQuickPathAnimation); + QHash::iterator it; + for (it = d->activeAnimations.begin(); it != d->activeAnimations.end(); ++it) { + it.value()->clearTemplate(); + } +} + +/*! + \qmlproperty int QtQuick2::PathAnimation::duration + This property holds the duration of the animation, in milliseconds. + + The default value is 250. +*/ +int QQuickPathAnimation::duration() const +{ + Q_D(const QQuickPathAnimation); + return d->duration; +} + +void QQuickPathAnimation::setDuration(int duration) +{ + if (duration < 0) { + qmlInfo(this) << tr("Cannot set a duration of < 0"); + return; + } + + Q_D(QQuickPathAnimation); + if (d->duration == duration) + return; + d->duration = duration; + emit durationChanged(duration); +} + +/*! + \qmlproperty enumeration QtQuick2::PathAnimation::easing.type + \qmlproperty real QtQuick2::PathAnimation::easing.amplitude + \qmlproperty list QtQuick2::PathAnimation::easing.bezierCurve + \qmlproperty real QtQuick2::PathAnimation::easing.overshoot + \qmlproperty real QtQuick2::PathAnimation::easing.period + \brief the easing curve used for the animation. + + To specify an easing curve you need to specify at least the type. For some curves you can also specify + amplitude, period, overshoot or custom bezierCurve data. The default easing curve is \c Easing.Linear. + + See the \l{PropertyAnimation::easing.type} documentation for information + about the different types of easing curves. +*/ +QEasingCurve QQuickPathAnimation::easing() const +{ + Q_D(const QQuickPathAnimation); + return d->easingCurve; +} + +void QQuickPathAnimation::setEasing(const QEasingCurve &e) +{ + Q_D(QQuickPathAnimation); + if (d->easingCurve == e) + return; + + d->easingCurve = e; + emit easingChanged(e); +} + +/*! + \qmlproperty Path QtQuick2::PathAnimation::path + This property holds the path to animate along. + + For more information on defining a path see the \l Path documentation. +*/ +QQuickPath *QQuickPathAnimation::path() const +{ + Q_D(const QQuickPathAnimation); + return d->path; +} + +void QQuickPathAnimation::setPath(QQuickPath *path) +{ + Q_D(QQuickPathAnimation); + if (d->path == path) + return; + + d->path = path; + emit pathChanged(); +} + +/*! + \qmlproperty Item QtQuick2::PathAnimation::target + This property holds the item to animate. +*/ +QQuickItem *QQuickPathAnimation::target() const +{ + Q_D(const QQuickPathAnimation); + return d->target; +} + +void QQuickPathAnimation::setTargetObject(QQuickItem *target) +{ + Q_D(QQuickPathAnimation); + if (d->target == target) + return; + + d->target = target; + emit targetChanged(); +} + +/*! + \qmlproperty enumeration QtQuick2::PathAnimation::orientation + This property controls the rotation of the item as it animates along the path. + + If a value other than \c Fixed is specified, the PathAnimation will rotate the + item to achieve the specified orientation as it travels along the path. + + \list + \o PathAnimation.Fixed (default) - the PathAnimation will not control + the rotation of the item. + \o PathAnimation.RightFirst - The right side of the item will lead along the path. + \o PathAnimation.LeftFirst - The left side of the item will lead along the path. + \o PathAnimation.BottomFirst - The bottom of the item will lead along the path. + \o PathAnimation.TopFirst - The top of the item will lead along the path. + \endlist +*/ +QQuickPathAnimation::Orientation QQuickPathAnimation::orientation() const +{ + Q_D(const QQuickPathAnimation); + return d->orientation; +} + +void QQuickPathAnimation::setOrientation(Orientation orientation) +{ + Q_D(QQuickPathAnimation); + if (d->orientation == orientation) + return; + + d->orientation = orientation; + emit orientationChanged(d->orientation); +} + +/*! + \qmlproperty point QtQuick2::PathAnimation::anchorPoint + This property holds the anchor point for the item being animated. + + By default, the upper-left corner of the target (its 0,0 point) + will be anchored to (or follow) the path. The anchorPoint property can be used to + specify a different point for anchoring. For example, specifying an anchorPoint of + 5,5 for a 10x10 item means the center of the item will follow the path. +*/ +QPointF QQuickPathAnimation::anchorPoint() const +{ + Q_D(const QQuickPathAnimation); + return d->anchorPoint; +} + +void QQuickPathAnimation::setAnchorPoint(const QPointF &point) +{ + Q_D(QQuickPathAnimation); + if (d->anchorPoint == point) + return; + + d->anchorPoint = point; + emit anchorPointChanged(point); +} + +/*! + \qmlproperty real QtQuick2::PathAnimation::orientationEntryDuration + This property holds the duration (in milliseconds) of the transition in to the orientation. + + If an orientation has been specified for the PathAnimation, and the starting + rotation of the item does not match that given by the orientation, + orientationEntryDuration can be used to smoothly transition from the item's + starting rotation to the rotation given by the path orientation. +*/ +int QQuickPathAnimation::orientationEntryDuration() const +{ + Q_D(const QQuickPathAnimation); + return d->entryDuration; +} + +void QQuickPathAnimation::setOrientationEntryDuration(int duration) +{ + Q_D(QQuickPathAnimation); + if (d->entryDuration == duration) + return; + d->entryDuration = duration; + emit orientationEntryDurationChanged(duration); +} + +/*! + \qmlproperty real QtQuick2::PathAnimation::orientationExitDuration + This property holds the duration (in milliseconds) of the transition out of the orientation. + + If an orientation and endRotation have been specified for the PathAnimation, + orientationExitDuration can be used to smoothly transition from the rotation given + by the path orientation to the specified endRotation. +*/ +int QQuickPathAnimation::orientationExitDuration() const +{ + Q_D(const QQuickPathAnimation); + return d->exitDuration; +} + +void QQuickPathAnimation::setOrientationExitDuration(int duration) +{ + Q_D(QQuickPathAnimation); + if (d->exitDuration == duration) + return; + d->exitDuration = duration; + emit orientationExitDurationChanged(duration); +} + +/*! + \qmlproperty real QtQuick2::PathAnimation::endRotation + This property holds the ending rotation for the target. + + If an orientation has been specified for the PathAnimation, + and the path doesn't end with the item at the desired rotation, + the endRotation property can be used to manually specify an end + rotation. + + This property is typically used with orientationExitDuration, as specifying + an endRotation without an orientationExitDuration may cause a jump to + the final rotation, rather than a smooth transition. +*/ +qreal QQuickPathAnimation::endRotation() const +{ + Q_D(const QQuickPathAnimation); + return d->endRotation.isNull ? qreal(0) : d->endRotation.value; +} + +void QQuickPathAnimation::setEndRotation(qreal rotation) +{ + Q_D(QQuickPathAnimation); + if (!d->endRotation.isNull && d->endRotation == rotation) + return; + + d->endRotation = rotation; + emit endRotationChanged(d->endRotation); +} + +QAbstractAnimationJob* QQuickPathAnimation::transition(QQuickStateActions &actions, + QQmlProperties &modified, + TransitionDirection direction, + QObject *defaultTarget) +{ + Q_D(QQuickPathAnimation); + + QQuickItem *target = d->target ? d->target : qobject_cast(defaultTarget); + + QQuickPathAnimationUpdater prevData; + bool havePrevData = false; + if (d->activeAnimations.contains(target)) { + havePrevData = true; + prevData = *d->activeAnimations[target]->pathUpdater(); + } + + QList keys = d->activeAnimations.keys(); + foreach (QQuickItem *item, keys) { + QQuickPathAnimationAnimator *anim = d->activeAnimations.value(item); + if (anim->state() == QAbstractAnimationJob::Stopped) { + anim->clearTemplate(); + d->activeAnimations.remove(item); + } + } + + QQuickPathAnimationUpdater *data = new QQuickPathAnimationUpdater(); + QQuickPathAnimationAnimator *pa = new QQuickPathAnimationAnimator(d); + + d->activeAnimations[target] = pa; + + data->orientation = d->orientation; + data->anchorPoint = d->anchorPoint; + data->entryInterval = d->duration ? qreal(d->entryDuration) / d->duration : qreal(0); + data->exitInterval = d->duration ? qreal(d->exitDuration) / d->duration : qreal(0); + data->endRotation = d->endRotation; + data->reverse = direction == Backward ? true : false; + data->fromSourced = false; + data->fromDefined = (d->path && d->path->hasStartX() && d->path->hasStartY()) ? true : false; + data->toDefined = d->path ? d->path->hasEnd() : false; + int origModifiedSize = modified.count(); + + for (int i = 0; i < actions.count(); ++i) { + QQuickAction &action = actions[i]; + if (action.event) + continue; + if (action.specifiedObject == target && action.property.name() == QLatin1String("x")) { + data->toX = action.toValue.toReal(); + modified << action.property; + action.fromValue = action.toValue; + } + if (action.specifiedObject == target && action.property.name() == QLatin1String("y")) { + data->toY = action.toValue.toReal(); + modified << action.property; + action.fromValue = action.toValue; + } + } + + if (target && d->path && + (modified.count() > origModifiedSize || data->toDefined)) { + data->target = target; + data->path = d->path; + data->path->invalidateSequentialHistory(); + + if (havePrevData) { + // get the original start angle that was used (so we can exactly reverse). + data->startRotation = prevData.startRotation; + + // treat interruptions specially, otherwise we end up with strange paths + if ((data->reverse || prevData.reverse) && prevData.currentV > 0 && prevData.currentV < 1) { + if (!data->fromDefined && !data->toDefined && !prevData.painterPath.isEmpty()) { + QPointF pathPos = QQuickPath::sequentialPointAt(prevData.painterPath, prevData.pathLength, prevData.attributePoints, prevData.prevBez, prevData.currentV); + if (!prevData.anchorPoint.isNull()) + pathPos -= prevData.anchorPoint; + if (pathPos == data->target->pos()) { //only treat as interruption if we interrupted ourself + data->painterPath = prevData.painterPath; + data->toDefined = data->fromDefined = data->fromSourced = true; + data->prevBez.isValid = false; + data->interruptStart = prevData.currentV; + data->startRotation = prevData.startRotation; + data->pathLength = prevData.pathLength; + data->attributePoints = prevData.attributePoints; + } + } + } + } + pa->setFromSourcedValue(&data->fromSourced); + pa->setAnimValue(data); + } else { + pa->setFromSourcedValue(0); + pa->setAnimValue(0); + delete pa; + delete data; + } + + pa->setDuration(d->duration); + pa->setEasingCurve(d->easingCurve); + return initInstance(pa); +} + +void QQuickPathAnimationUpdater::setValue(qreal v) +{ + if (interruptStart.isValid()) { + if (reverse) + v = 1 - v; + qreal end = reverse ? 0.0 : 1.0; + v = interruptStart + v * (end-interruptStart); + } + currentV = v; + bool atStart = ((reverse && v == 1.0) || (!reverse && v == 0.0)); + if (!fromSourced && (!fromDefined || !toDefined)) { + qreal startX = reverse ? toX + anchorPoint.x() : target->x() + anchorPoint.x(); + qreal startY = reverse ? toY + anchorPoint.y() : target->y() + anchorPoint.y(); + qreal endX = reverse ? target->x() + anchorPoint.x() : toX + anchorPoint.x(); + qreal endY = reverse ? target->y() + anchorPoint.y() : toY + anchorPoint.y(); + + prevBez.isValid = false; + painterPath = path->createPath(QPointF(startX, startY), QPointF(endX, endY), QStringList(), pathLength, attributePoints); + fromSourced = true; + } + + qreal angle; + bool fixed = orientation == QQuickPathAnimation::Fixed; + QPointF currentPos = !painterPath.isEmpty() ? path->sequentialPointAt(painterPath, pathLength, attributePoints, prevBez, v, fixed ? 0 : &angle) : path->sequentialPointAt(v, fixed ? 0 : &angle); + + //adjust position according to anchor point + if (!anchorPoint.isNull()) { + currentPos -= anchorPoint; + if (atStart) { + if (!anchorPoint.isNull() && !fixed) + target->setTransformOriginPoint(anchorPoint); + } + } + + target->setPos(currentPos); + + //adjust angle according to orientation + if (!fixed) { + switch (orientation) { + case QQuickPathAnimation::RightFirst: + angle = -angle; + break; + case QQuickPathAnimation::TopFirst: + angle = -angle + 90; + break; + case QQuickPathAnimation::LeftFirst: + angle = -angle + 180; + break; + case QQuickPathAnimation::BottomFirst: + angle = -angle + 270; + break; + default: + angle = 0; + break; + } + + if (atStart && !reverse) { + startRotation = target->rotation(); + + //shortest distance to correct orientation + qreal diff = angle - startRotation; + while (diff > 180.0) { + startRotation.value += 360.0; + diff -= 360.0; + } + while (diff < -180.0) { + startRotation.value -= 360.0; + diff += 360.0; + } + } + + //smoothly transition to the desired orientation + //TODO: shortest distance calculations + if (startRotation.isValid()) { + if (reverse && v == 0.0) + angle = startRotation; + else if (v < entryInterval) + angle = angle * v / entryInterval + startRotation * (entryInterval - v) / entryInterval; + } + if (endRotation.isValid()) { + qreal exitStart = 1 - entryInterval; + if (!reverse && v == 1.0) + angle = endRotation; + else if (v > exitStart) + angle = endRotation * (v - exitStart) / exitInterval + angle * (exitInterval - (v - exitStart)) / exitInterval; + } + target->setRotation(angle); + } + + /* + NOTE: we don't always reset the transform origin, as it can cause a + visual jump if ending on an angle. This means that in some cases + (anchor point and orientation both specified, and ending at an angle) + the transform origin will always be set after running the path animation. + */ + if ((reverse && v == 0.0) || (!reverse && v == 1.0)) { + if (!anchorPoint.isNull() && !fixed && qFuzzyIsNull(angle)) + target->setTransformOriginPoint(QPointF()); + } +} + +QQuickPathAnimationAnimator::QQuickPathAnimationAnimator(QQuickPathAnimationPrivate *priv) + : animationTemplate(priv) +{ +} + +QQuickPathAnimationAnimator::~QQuickPathAnimationAnimator() +{ + if (animationTemplate && pathUpdater()) { + QHash::iterator it = + animationTemplate->activeAnimations.find(pathUpdater()->target); + if (it != animationTemplate->activeAnimations.end() && it.value() == this) + animationTemplate->activeAnimations.erase(it); + } +} + +QT_END_NAMESPACE diff --cc src/quick/items/qquickitemsmodule.cpp index 64b84d3,f502374..3d23f7b --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@@ -61,8 -61,9 +61,9 @@@ #include "qquickvisualdatamodel_p.h" #include "qquickgridview_p.h" #include "qquickpathview_p.h" + #include "qquickitemviewtransition_p.h" -#include -#include +#include +#include #include "qquickpositioners_p.h" #include "qquickrepeater_p.h" #include "qquickloader_p.h" diff --cc src/quick/items/qquickitemview.cpp index 418b319,5d58cbf..516cf0c --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@@ -1225,111 -593,134 +593,134 @@@ void QQuickItemView::setHighlightMoveDu } } -QDeclarativeTransition *QQuickItemView::populateTransition() const +QQuickTransition *QQuickItemView::populateTransition() const { Q_D(const QQuickItemView); - return d->populateTransition; + return d->transitioner ? d->transitioner->populateTransition : 0; } -void QQuickItemView::setPopulateTransition(QDeclarativeTransition *transition) +void QQuickItemView::setPopulateTransition(QQuickTransition *transition) { Q_D(QQuickItemView); - if (d->populateTransition != transition) { - d->populateTransition = transition; + d->createTransitioner(); + if (d->transitioner->populateTransition != transition) { + d->transitioner->populateTransition = transition; emit populateTransitionChanged(); } } -QDeclarativeTransition *QQuickItemView::addTransition() const +QQuickTransition *QQuickItemView::addTransition() const { Q_D(const QQuickItemView); - return d->addTransition; + return d->transitioner ? d->transitioner->addTransition : 0; } -void QQuickItemView::setAddTransition(QDeclarativeTransition *transition) +void QQuickItemView::setAddTransition(QQuickTransition *transition) { Q_D(QQuickItemView); - if (d->addTransition != transition) { - d->addTransition = transition; + d->createTransitioner(); + if (d->transitioner->addTransition != transition) { + d->transitioner->addTransition = transition; emit addTransitionChanged(); } } -QDeclarativeTransition *QQuickItemView::addDisplacedTransition() const +QQuickTransition *QQuickItemView::addDisplacedTransition() const { Q_D(const QQuickItemView); - return d->addDisplacedTransition; + return d->transitioner ? d->transitioner->addDisplacedTransition : 0; } -void QQuickItemView::setAddDisplacedTransition(QDeclarativeTransition *transition) +void QQuickItemView::setAddDisplacedTransition(QQuickTransition *transition) { Q_D(QQuickItemView); - if (d->addDisplacedTransition != transition) { - d->addDisplacedTransition = transition; + d->createTransitioner(); + if (d->transitioner->addDisplacedTransition != transition) { + d->transitioner->addDisplacedTransition = transition; emit addDisplacedTransitionChanged(); } } -QDeclarativeTransition *QQuickItemView::moveTransition() const +QQuickTransition *QQuickItemView::moveTransition() const { Q_D(const QQuickItemView); - return d->moveTransition; + return d->transitioner ? d->transitioner->moveTransition : 0; } -void QQuickItemView::setMoveTransition(QDeclarativeTransition *transition) +void QQuickItemView::setMoveTransition(QQuickTransition *transition) { Q_D(QQuickItemView); - if (d->moveTransition != transition) { - d->moveTransition = transition; + d->createTransitioner(); + if (d->transitioner->moveTransition != transition) { + d->transitioner->moveTransition = transition; emit moveTransitionChanged(); } } -QDeclarativeTransition *QQuickItemView::moveDisplacedTransition() const +QQuickTransition *QQuickItemView::moveDisplacedTransition() const { Q_D(const QQuickItemView); - return d->moveDisplacedTransition; + return d->transitioner ? d->transitioner->moveDisplacedTransition : 0; } -void QQuickItemView::setMoveDisplacedTransition(QDeclarativeTransition *transition) +void QQuickItemView::setMoveDisplacedTransition(QQuickTransition *transition) { Q_D(QQuickItemView); - if (d->moveDisplacedTransition != transition) { - d->moveDisplacedTransition = transition; + d->createTransitioner(); + if (d->transitioner->moveDisplacedTransition != transition) { + d->transitioner->moveDisplacedTransition = transition; emit moveDisplacedTransitionChanged(); } } -QDeclarativeTransition *QQuickItemView::removeTransition() const +QQuickTransition *QQuickItemView::removeTransition() const { Q_D(const QQuickItemView); - return d->removeTransition; + return d->transitioner ? d->transitioner->removeTransition : 0; } -void QQuickItemView::setRemoveTransition(QDeclarativeTransition *transition) +void QQuickItemView::setRemoveTransition(QQuickTransition *transition) { Q_D(QQuickItemView); - if (d->removeTransition != transition) { - d->removeTransition = transition; + d->createTransitioner(); + if (d->transitioner->removeTransition != transition) { + d->transitioner->removeTransition = transition; emit removeTransitionChanged(); } } -QDeclarativeTransition *QQuickItemView::removeDisplacedTransition() const +QQuickTransition *QQuickItemView::removeDisplacedTransition() const { Q_D(const QQuickItemView); - return d->removeDisplacedTransition; + return d->transitioner ? d->transitioner->removeDisplacedTransition : 0; } -void QQuickItemView::setRemoveDisplacedTransition(QDeclarativeTransition *transition) +void QQuickItemView::setRemoveDisplacedTransition(QQuickTransition *transition) { Q_D(QQuickItemView); - if (d->removeDisplacedTransition != transition) { - d->removeDisplacedTransition = transition; + d->createTransitioner(); + if (d->transitioner->removeDisplacedTransition != transition) { + d->transitioner->removeDisplacedTransition = transition; emit removeDisplacedTransitionChanged(); } } -QDeclarativeTransition *QQuickItemView::displacedTransition() const ++QQuickTransition *QQuickItemView::displacedTransition() const + { + Q_D(const QQuickItemView); + return d->transitioner ? d->transitioner->displacedTransition : 0; + } + -void QQuickItemView::setDisplacedTransition(QDeclarativeTransition *transition) ++void QQuickItemView::setDisplacedTransition(QQuickTransition *transition) + { + Q_D(QQuickItemView); + d->createTransitioner(); + if (d->transitioner->displacedTransition != transition) { + d->transitioner->displacedTransition = transition; + emit displacedTransitionChanged(); + } + } + void QQuickItemViewPrivate::positionViewAtIndex(int index, int mode) { Q_Q(QQuickItemView); @@@ -1464,65 -855,7 +855,7 @@@ void QQuickItemViewPrivate::applyPendin layout(); } - bool QQuickItemViewPrivate::canTransition(FxViewItemTransitionManager::TransitionType type, bool asTarget) const - { - switch (type) { - case FxViewItemTransitionManager::NoTransition: - break; - case FxViewItemTransitionManager::PopulateTransition: - return usePopulateTransition - && populateTransition && populateTransition->enabled(); - case FxViewItemTransitionManager::AddTransition: - if (asTarget) - return addTransition && addTransition->enabled(); - else - return addDisplacedTransition && addDisplacedTransition->enabled(); - case FxViewItemTransitionManager::MoveTransition: - if (asTarget) - return moveTransition && moveTransition->enabled(); - else - return moveDisplacedTransition && moveDisplacedTransition->enabled(); - case FxViewItemTransitionManager::RemoveTransition: - if (asTarget) - return removeTransition && removeTransition->enabled(); - else - return removeDisplacedTransition && removeDisplacedTransition->enabled(); - } - return false; - } - - bool QQuickItemViewPrivate::hasItemTransitions() const - { - return canTransition(FxViewItemTransitionManager::PopulateTransition, true) - || canTransition(FxViewItemTransitionManager::AddTransition, true) - || canTransition(FxViewItemTransitionManager::AddTransition, false) - || canTransition(FxViewItemTransitionManager::MoveTransition, true) - || canTransition(FxViewItemTransitionManager::MoveTransition, false) - || canTransition(FxViewItemTransitionManager::RemoveTransition, true) - || canTransition(FxViewItemTransitionManager::RemoveTransition, false); - } - - void QQuickItemViewPrivate::transitionNextReposition(FxViewItem *item, FxViewItemTransitionManager::TransitionType type, bool isTarget) - { - bool matchedTransition = false; - if (type == FxViewItemTransitionManager::AddTransition) { - // don't run add transitions for added items while populating - matchedTransition = !usePopulateTransition && canTransition(type, isTarget); - } else { - matchedTransition = canTransition(type, isTarget); - } - - if (matchedTransition) { - item->setNextTransition(type, isTarget); - } else { - // the requested transition type is not valid, but the item is scheduled/in another - // transition, so cancel it to allow the item to move directly to the correct pos - if (item->transitionScheduledOrRunning()) - item->stopTransition(); - } - } - -int QQuickItemViewPrivate::findMoveKeyIndex(QDeclarativeChangeSet::MoveKey key, const QVector &changes) const +int QQuickItemViewPrivate::findMoveKeyIndex(QQuickChangeSet::MoveKey key, const QVector &changes) const { for (int i=0; iindex), item); - transitionNextReposition(item, FxViewItemTransitionManager::MoveTransition, true); + if (transitioner) + transitioner->transitionNextReposition(item, QQuickItemViewTransitioner::MoveTransition, true); } else { // track item so it is released later - currentChanges.removedItems.insertMulti(QDeclarativeChangeSet::MoveKey(), item); + currentChanges.removedItems.insertMulti(QQuickChangeSet::MoveKey(), item); } if (!removeResult->changedFirstItem && item == *visibleItems.constBegin()) removeResult->changedFirstItem = true; @@@ -2629,13 -1987,16 +1987,16 @@@ void QQuickItemViewPrivate::prepareVisi } } -void QQuickItemViewPrivate::prepareRemoveTransitions(QHash *removedItems) +void QQuickItemViewPrivate::prepareRemoveTransitions(QHash *removedItems) { - removeTransitionIndexes.clear(); - removeTransitionTargets.clear(); + if (!transitioner) + return; - if (canTransition(FxViewItemTransitionManager::RemoveTransition, true)) { + transitioner->removeTransitionIndexes.clear(); + transitioner->removeTransitionTargets.clear(); + + if (transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, true)) { - for (QHash::Iterator it = removedItems->begin(); + for (QHash::Iterator it = removedItems->begin(); it != removedItems->end(); ) { bool isRemove = it.key().moveId < 0; if (isRemove) { diff --cc src/quick/items/qquickitemview_p.h index 01a6ee2,69a3d4a..f252fb5 --- a/src/quick/items/qquickitemview_p.h +++ b/src/quick/items/qquickitemview_p.h @@@ -48,9 -48,9 +48,9 @@@ QT_BEGIN_HEADE QT_BEGIN_NAMESPACE - QT_MODULE(Qml) -QT_MODULE(Declarative) ++QT_MODULE(Quick) -class QDeclarativeChangeSet; +class QQuickChangeSet; class QQuickItemViewPrivate; @@@ -71,20 -71,21 +71,21 @@@ class Q_AUTOTEST_EXPORT QQuickItemView Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged) Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged) - Q_PROPERTY(QDeclarativeComponent *header READ header WRITE setHeader NOTIFY headerChanged) + Q_PROPERTY(QQmlComponent *header READ header WRITE setHeader NOTIFY headerChanged) Q_PROPERTY(QQuickItem *headerItem READ headerItem NOTIFY headerItemChanged) - Q_PROPERTY(QDeclarativeComponent *footer READ footer WRITE setFooter NOTIFY footerChanged) + Q_PROPERTY(QQmlComponent *footer READ footer WRITE setFooter NOTIFY footerChanged) Q_PROPERTY(QQuickItem *footerItem READ footerItem NOTIFY footerItemChanged) - Q_PROPERTY(QDeclarativeTransition *populate READ populateTransition WRITE setPopulateTransition NOTIFY populateTransitionChanged) - Q_PROPERTY(QDeclarativeTransition *add READ addTransition WRITE setAddTransition NOTIFY addTransitionChanged) - Q_PROPERTY(QDeclarativeTransition *addDisplaced READ addDisplacedTransition WRITE setAddDisplacedTransition NOTIFY addDisplacedTransitionChanged) - Q_PROPERTY(QDeclarativeTransition *move READ moveTransition WRITE setMoveTransition NOTIFY moveTransitionChanged) - Q_PROPERTY(QDeclarativeTransition *moveDisplaced READ moveDisplacedTransition WRITE setMoveDisplacedTransition NOTIFY moveDisplacedTransitionChanged) - Q_PROPERTY(QDeclarativeTransition *remove READ removeTransition WRITE setRemoveTransition NOTIFY removeTransitionChanged) - Q_PROPERTY(QDeclarativeTransition *removeDisplaced READ removeDisplacedTransition WRITE setRemoveDisplacedTransition NOTIFY removeDisplacedTransitionChanged) - Q_PROPERTY(QDeclarativeTransition *displaced READ displacedTransition WRITE setDisplacedTransition NOTIFY displacedTransitionChanged) + Q_PROPERTY(QQuickTransition *populate READ populateTransition WRITE setPopulateTransition NOTIFY populateTransitionChanged) + Q_PROPERTY(QQuickTransition *add READ addTransition WRITE setAddTransition NOTIFY addTransitionChanged) + Q_PROPERTY(QQuickTransition *addDisplaced READ addDisplacedTransition WRITE setAddDisplacedTransition NOTIFY addDisplacedTransitionChanged) + Q_PROPERTY(QQuickTransition *move READ moveTransition WRITE setMoveTransition NOTIFY moveTransitionChanged) + Q_PROPERTY(QQuickTransition *moveDisplaced READ moveDisplacedTransition WRITE setMoveDisplacedTransition NOTIFY moveDisplacedTransitionChanged) + Q_PROPERTY(QQuickTransition *remove READ removeTransition WRITE setRemoveTransition NOTIFY removeTransitionChanged) + Q_PROPERTY(QQuickTransition *removeDisplaced READ removeDisplacedTransition WRITE setRemoveDisplacedTransition NOTIFY removeDisplacedTransitionChanged) ++ Q_PROPERTY(QQuickTransition *displaced READ displacedTransition WRITE setDisplacedTransition NOTIFY displacedTransitionChanged) - Q_PROPERTY(QDeclarativeComponent *highlight READ highlight WRITE setHighlight NOTIFY highlightChanged) + Q_PROPERTY(QQmlComponent *highlight READ highlight WRITE setHighlight NOTIFY highlightChanged) Q_PROPERTY(QQuickItem *highlightItem READ highlightItem NOTIFY highlightItemChanged) Q_PROPERTY(bool highlightFollowsCurrentItem READ highlightFollowsCurrentItem WRITE setHighlightFollowsCurrentItem NOTIFY highlightFollowsCurrentItemChanged) Q_PROPERTY(HighlightRangeMode highlightRangeMode READ highlightRangeMode WRITE setHighlightRangeMode NOTIFY highlightRangeModeChanged) @@@ -122,37 -123,40 +123,40 @@@ public void setLayoutDirection(Qt::LayoutDirection); Qt::LayoutDirection effectiveLayoutDirection() const; - QDeclarativeComponent *footer() const; - void setFooter(QDeclarativeComponent *); + QQmlComponent *footer() const; + void setFooter(QQmlComponent *); QQuickItem *footerItem() const; - QDeclarativeComponent *header() const; - void setHeader(QDeclarativeComponent *); + QQmlComponent *header() const; + void setHeader(QQmlComponent *); QQuickItem *headerItem() const; - QDeclarativeTransition *populateTransition() const; - void setPopulateTransition(QDeclarativeTransition *transition); + QQuickTransition *populateTransition() const; + void setPopulateTransition(QQuickTransition *transition); - QDeclarativeTransition *addTransition() const; - void setAddTransition(QDeclarativeTransition *transition); + QQuickTransition *addTransition() const; + void setAddTransition(QQuickTransition *transition); - QDeclarativeTransition *addDisplacedTransition() const; - void setAddDisplacedTransition(QDeclarativeTransition *transition); + QQuickTransition *addDisplacedTransition() const; + void setAddDisplacedTransition(QQuickTransition *transition); - QDeclarativeTransition *moveTransition() const; - void setMoveTransition(QDeclarativeTransition *transition); + QQuickTransition *moveTransition() const; + void setMoveTransition(QQuickTransition *transition); - QDeclarativeTransition *moveDisplacedTransition() const; - void setMoveDisplacedTransition(QDeclarativeTransition *transition); + QQuickTransition *moveDisplacedTransition() const; + void setMoveDisplacedTransition(QQuickTransition *transition); - QDeclarativeTransition *removeTransition() const; - void setRemoveTransition(QDeclarativeTransition *transition); + QQuickTransition *removeTransition() const; + void setRemoveTransition(QQuickTransition *transition); - QDeclarativeTransition *removeDisplacedTransition() const; - void setRemoveDisplacedTransition(QDeclarativeTransition *transition); + QQuickTransition *removeDisplacedTransition() const; + void setRemoveDisplacedTransition(QQuickTransition *transition); - QDeclarativeTransition *displacedTransition() const; - void setDisplacedTransition(QDeclarativeTransition *transition); ++ QQuickTransition *displacedTransition() const; ++ void setDisplacedTransition(QQuickTransition *transition); + - QDeclarativeComponent *highlight() const; - void setHighlight(QDeclarativeComponent *); + QQmlComponent *highlight() const; + void setHighlight(QQmlComponent *); QQuickItem *highlightItem() const; diff --cc src/quick/items/qquickitemview_p_p.h index a4892e8,57860a4..80dacc0 --- a/src/quick/items/qquickitemview_p_p.h +++ b/src/quick/items/qquickitemview_p_p.h @@@ -46,47 -47,17 +47,17 @@@ #include "qquickflickable_p_p.h" #include "qquickvisualdatamodel_p.h" #include "qquickvisualitemmodel_p.h" - #include -#include +#include QT_BEGIN_HEADER QT_BEGIN_NAMESPACE --QT_MODULE(Declarative) ++QT_MODULE(Quick) - class FxViewItem; - class FxViewItemTransitionManager : public QQuickTransitionManager - { - public: - enum TransitionType { - NoTransition, - PopulateTransition, - AddTransition, - MoveTransition, - RemoveTransition - }; - - FxViewItemTransitionManager(); - ~FxViewItemTransitionManager(); - - bool isActive() const; - void startTransition(FxViewItem *item, FxViewItemTransitionManager::TransitionType type, const QPointF &to, bool isTargetItem); - - bool m_active; - FxViewItem *m_item; - QPointF m_toPos; - FxViewItemTransitionManager::TransitionType m_type; - bool m_isTarget; - - protected: - virtual void finished(); - }; - - - class FxViewItem + class FxViewItem : public QQuickViewItem { public: FxViewItem(QQuickItem *, bool own); @@@ -160,9 -104,10 +104,10 @@@ class QQuickItemViewPrivate : public QQ Q_DECLARE_PUBLIC(QQuickItemView) public: QQuickItemViewPrivate(); + ~QQuickItemViewPrivate(); struct ChangeResult { - QDeclarativeNullableValue visiblePos; + QQmlNullableValue visiblePos; bool changedFirstItem; qreal sizeChangesBeforeVisiblePos; qreal sizeChangesAfterVisiblePos; @@@ -225,10 -170,10 +170,10 @@@ void mirrorChange(); FxViewItem *createItem(int modelIndex, bool asynchronous = false); - virtual void releaseItem(FxViewItem *item); + virtual bool releaseItem(FxViewItem *item); QQuickItem *createHighlightItem(); - QQuickItem *createComponentItem(QDeclarativeComponent *component, bool receiveItemGeometryChanges, bool createDefault = false); + QQuickItem *createComponentItem(QQmlComponent *component, bool receiveItemGeometryChanges, bool createDefault = false); void updateCurrent(int modelIndex); void updateTrackedItem(); @@@ -243,14 -188,13 +188,13 @@@ void repositionFirstItem(FxViewItem *prevVisibleItemsFirst, qreal prevVisibleItemsFirstPos, FxViewItem *prevFirstVisible, ChangeResult *insertionResult, ChangeResult *removalResult); + void createTransitioner(); void prepareVisibleItemTransitions(); - void prepareRemoveTransitions(QHash *removedItems); + void prepareRemoveTransitions(QHash *removedItems); bool prepareNonVisibleItemTransition(FxViewItem *item, const QRectF &viewBounds); + virtual void viewItemTransitionFinished(QQuickViewItem *item); - bool canTransition(FxViewItemTransitionManager::TransitionType type, bool asTarget) const; - bool hasItemTransitions() const; - void transitionNextReposition(FxViewItem *item, FxViewItemTransitionManager::TransitionType type, bool isTarget); - int findMoveKeyIndex(QDeclarativeChangeSet::MoveKey key, const QVector &changes) const; + int findMoveKeyIndex(QQuickChangeSet::MoveKey key, const QVector &changes) const; void checkVisible() const; void showVisibleItems() const; @@@ -281,40 -225,25 +225,25 @@@ FxViewItem *requestedItem; QQuickItemViewChangeSet currentChanges; - // XXX split into struct - QDeclarativeComponent *highlightComponent; + QQmlComponent *highlightComponent; FxViewItem *highlight; int highlightRange; // enum value qreal highlightRangeStart; qreal highlightRangeEnd; int highlightMoveDuration; - QDeclarativeComponent *headerComponent; + QQmlComponent *headerComponent; FxViewItem *header; - QDeclarativeComponent *footerComponent; + QQmlComponent *footerComponent; FxViewItem *footer; - QQuickTransition *populateTransition; - QQuickTransition *addTransition; - QQuickTransition *addDisplacedTransition; - QQuickTransition *moveTransition; - QQuickTransition *moveDisplacedTransition; - QQuickTransition *removeTransition; - QQuickTransition *removeDisplacedTransition; - - QList addTransitionIndexes; - QList moveTransitionIndexes; - QList removeTransitionIndexes; - QList addTransitionTargets; - QList moveTransitionTargets; - QList removeTransitionTargets; - struct MovedItem { FxViewItem *item; - QDeclarativeChangeSet::MoveKey moveKey; - MovedItem(FxViewItem *i, QDeclarativeChangeSet::MoveKey k) + QQuickChangeSet::MoveKey moveKey; + MovedItem(FxViewItem *i, QQuickChangeSet::MoveKey k) : item(i), moveKey(k) {} }; + QQuickItemViewTransitioner *transitioner; QList releasePendingTransition; mutable qreal minExtent; diff --cc src/quick/items/qquickitemviewtransition.cpp index 0000000,3febc9b..54375bf mode 000000,100644..100644 --- a/src/quick/items/qquickitemviewtransition.cpp +++ b/src/quick/items/qquickitemviewtransition.cpp @@@ -1,0 -1,876 +1,876 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + #include "qquickitemviewtransition_p.h" + #include -#include ++#include + + QT_BEGIN_NAMESPACE + + static QList qquickitemviewtransition_emptyIndexes = QList(); + static QList qquickitemviewtransition_emptyTargets = QList(); + + -class QQuickItemViewTransitionJob : public QDeclarativeTransitionManager ++class QQuickItemViewTransitionJob : public QQuickTransitionManager + { + public: + QQuickItemViewTransitionJob(); + ~QQuickItemViewTransitionJob(); + + void startTransition(QQuickViewItem *item, QQuickItemViewTransitioner *transitioner, QQuickItemViewTransitioner::TransitionType type, const QPointF &to, bool isTargetItem); + + QQuickItemViewTransitioner *m_transitioner; + QQuickViewItem *m_item; + QPointF m_toPos; + QQuickItemViewTransitioner::TransitionType m_type; + bool m_isTarget; + + protected: + virtual void finished(); + }; + + + QQuickItemViewTransitionJob::QQuickItemViewTransitionJob() + : m_transitioner(0) + , m_item(0) + , m_type(QQuickItemViewTransitioner::NoTransition) + , m_isTarget(false) + { + } + + QQuickItemViewTransitionJob::~QQuickItemViewTransitionJob() + { + if (m_transitioner) + m_transitioner->runningJobs.remove(this); + } + + void QQuickItemViewTransitionJob::startTransition(QQuickViewItem *item, QQuickItemViewTransitioner *transitioner, QQuickItemViewTransitioner::TransitionType type, const QPointF &to, bool isTargetItem) + { + if (type == QQuickItemViewTransitioner::NoTransition) + return; + if (!item) { + qWarning("startTransition(): invalid item"); + return; + } + if (!transitioner) { + qWarning("startTransition(): invalid transitioner"); + return; + } + - QDeclarativeTransition *trans = transitioner->transitionObject(type, isTargetItem); ++ QQuickTransition *trans = transitioner->transitionObject(type, isTargetItem); + if (!trans) { + qWarning("QQuickItemView: invalid view transition!"); + return; + } + + m_item = item; + m_transitioner = transitioner; + m_toPos = to; + m_type = type; + m_isTarget = isTargetItem; + + QQuickViewTransitionAttached *attached = + static_cast(qmlAttachedPropertiesObject(trans)); + if (attached) { + attached->m_index = item->index; + attached->m_item = item->item; + attached->m_destination = to; + attached->m_targetIndexes = m_transitioner->targetIndexes(type); + attached->m_targetItems = m_transitioner->targetItems(type); + emit attached->indexChanged(); + emit attached->itemChanged(); + emit attached->destinationChanged(); + emit attached->targetIndexesChanged(); + emit attached->targetItemsChanged(); + } + - QDeclarativeStateOperation::ActionList actions; - actions << QDeclarativeAction(item->item, QLatin1String("x"), QVariant(to.x())); - actions << QDeclarativeAction(item->item, QLatin1String("y"), QVariant(to.y())); ++ QQuickStateOperation::ActionList actions; ++ actions << QQuickAction(item->item, QLatin1String("x"), QVariant(to.x())); ++ actions << QQuickAction(item->item, QLatin1String("y"), QVariant(to.y())); + + m_transitioner->runningJobs << this; - QDeclarativeTransitionManager::transition(actions, trans, item->item); ++ QQuickTransitionManager::transition(actions, trans, item->item); + } + + void QQuickItemViewTransitionJob::finished() + { - QDeclarativeTransitionManager::finished(); ++ QQuickTransitionManager::finished(); + + if (m_transitioner) + m_transitioner->finishedTransition(this, m_item); + + m_item = 0; + m_toPos.setX(0); + m_toPos.setY(0); + m_type = QQuickItemViewTransitioner::NoTransition; + m_isTarget = false; + } + + + QQuickItemViewTransitioner::QQuickItemViewTransitioner() + : populateTransition(0) + , addTransition(0), addDisplacedTransition(0) + , moveTransition(0), moveDisplacedTransition(0) + , removeTransition(0), removeDisplacedTransition(0) + , displacedTransition(0) + , changeListener(0) + , usePopulateTransition(false) + { + } + + QQuickItemViewTransitioner::~QQuickItemViewTransitioner() + { + for (QSet::iterator it = runningJobs.begin(); it != runningJobs.end(); ++it) + (*it)->m_transitioner = 0; + } + + bool QQuickItemViewTransitioner::canTransition(QQuickItemViewTransitioner::TransitionType type, bool asTarget) const + { + if (!asTarget + && type != QQuickItemViewTransitioner::NoTransition && type != QQuickItemViewTransitioner::PopulateTransition + && displacedTransition && displacedTransition->enabled()) { + return true; + } + + switch (type) { + case QQuickItemViewTransitioner::NoTransition: + break; + case QQuickItemViewTransitioner::PopulateTransition: + return usePopulateTransition + && populateTransition && populateTransition->enabled(); + case QQuickItemViewTransitioner::AddTransition: + if (asTarget) + return addTransition && addTransition->enabled(); + else + return addDisplacedTransition && addDisplacedTransition->enabled(); + case QQuickItemViewTransitioner::MoveTransition: + if (asTarget) + return moveTransition && moveTransition->enabled(); + else + return moveDisplacedTransition && moveDisplacedTransition->enabled(); + case QQuickItemViewTransitioner::RemoveTransition: + if (asTarget) + return removeTransition && removeTransition->enabled(); + else + return removeDisplacedTransition && removeDisplacedTransition->enabled(); + } + return false; + } + + void QQuickItemViewTransitioner::transitionNextReposition(QQuickViewItem *item, QQuickItemViewTransitioner::TransitionType type, bool isTarget) + { + bool matchedTransition = false; + if (type == QQuickItemViewTransitioner::AddTransition) { + // don't run add transitions for added items while populating + if (usePopulateTransition) + matchedTransition = false; + else + matchedTransition = canTransition(type, isTarget); + } else { + matchedTransition = canTransition(type, isTarget); + } + + if (matchedTransition) { + item->setNextTransition(type, isTarget); + } else { + // the requested transition type is not valid, but the item is scheduled/in another + // transition, so cancel it to allow the item to move directly to the correct pos + if (item->transitionScheduledOrRunning()) + item->stopTransition(); + } + } + -QDeclarativeTransition *QQuickItemViewTransitioner::transitionObject(QQuickItemViewTransitioner::TransitionType type, bool asTarget) ++QQuickTransition *QQuickItemViewTransitioner::transitionObject(QQuickItemViewTransitioner::TransitionType type, bool asTarget) + { + if (type == QQuickItemViewTransitioner::NoTransition) + return 0; + + if (type == PopulateTransition) + asTarget = true; // no separate displaced transition + - QDeclarativeTransition *trans = 0; ++ QQuickTransition *trans = 0; + switch (type) { + case NoTransition: + break; + case PopulateTransition: + trans = populateTransition; + break; + case AddTransition: + trans = asTarget ? addTransition : addDisplacedTransition; + break; + case MoveTransition: + trans = asTarget ? moveTransition : moveDisplacedTransition; + break; + case RemoveTransition: + trans = asTarget ? removeTransition : removeDisplacedTransition; + break; + } + + if (!asTarget && (!trans || !trans->enabled())) + trans = displacedTransition; + if (trans && trans->enabled()) + return trans; + return 0; + } + + const QList &QQuickItemViewTransitioner::targetIndexes(QQuickItemViewTransitioner::TransitionType type) const + { + switch (type) { + case QQuickItemViewTransitioner::NoTransition: + break; + case QQuickItemViewTransitioner::PopulateTransition: + case QQuickItemViewTransitioner::AddTransition: + return addTransitionIndexes; + case QQuickItemViewTransitioner::MoveTransition: + return moveTransitionIndexes; + case QQuickItemViewTransitioner::RemoveTransition: + return removeTransitionIndexes; + } + + return qquickitemviewtransition_emptyIndexes; + } + + const QList &QQuickItemViewTransitioner::targetItems(QQuickItemViewTransitioner::TransitionType type) const + { + switch (type) { + case QQuickItemViewTransitioner::NoTransition: + break; + case QQuickItemViewTransitioner::PopulateTransition: + case QQuickItemViewTransitioner::AddTransition: + return addTransitionTargets; + case QQuickItemViewTransitioner::MoveTransition: + return moveTransitionTargets; + case QQuickItemViewTransitioner::RemoveTransition: + return removeTransitionTargets; + } + + return qquickitemviewtransition_emptyTargets; + } + + void QQuickItemViewTransitioner::finishedTransition(QQuickItemViewTransitionJob *job, QQuickViewItem *item) + { + if (!runningJobs.contains(job)) + return; + runningJobs.remove(job); + if (item) { + item->finishedTransition(); + if (changeListener) + changeListener->viewItemTransitionFinished(item); + } + } + + + QQuickViewItem::QQuickViewItem(QQuickItem *i) + : item(i) + , transition(0) + , nextTransitionType(QQuickItemViewTransitioner::NoTransition) + , index(-1) + , isTransitionTarget(false) + , nextTransitionToSet(false) + { + } + + QQuickViewItem::~QQuickViewItem() + { + delete transition; + } + + qreal QQuickViewItem::itemX() const + { + if (nextTransitionType != QQuickItemViewTransitioner::NoTransition) + return nextTransitionToSet ? nextTransitionTo.x() : item->x(); + else if (transition && transition->isRunning()) + return transition->m_toPos.x(); + else + return item->x(); + } + + qreal QQuickViewItem::itemY() const + { + // If item is transitioning to some pos, return that dest pos. + // If item was redirected to some new pos before the current transition finished, + // return that new pos. + if (nextTransitionType != QQuickItemViewTransitioner::NoTransition) + return nextTransitionToSet ? nextTransitionTo.y() : item->y(); + else if (transition && transition->isRunning()) + return transition->m_toPos.y(); + else + return item->y(); + } + + void QQuickViewItem::moveTo(const QPointF &pos) + { + if (transitionScheduledOrRunning()) { + nextTransitionTo = pos; + nextTransitionToSet = true; + } else { + item->setPos(pos); + } + } + + void QQuickViewItem::setVisible(bool visible) + { + if (!visible && transitionScheduledOrRunning()) + return; + item->setVisible(visible); + } + + bool QQuickViewItem::transitionScheduledOrRunning() const + { + return (transition && transition->isRunning()) + || nextTransitionType != QQuickItemViewTransitioner::NoTransition; + } + + bool QQuickViewItem::transitionRunning() const + { + return (transition && transition->isRunning()); + } + + bool QQuickViewItem::isPendingRemoval() const + { + if (nextTransitionType == QQuickItemViewTransitioner::RemoveTransition) + return isTransitionTarget; + if (transition && transition->isRunning() && transition->m_type == QQuickItemViewTransitioner::RemoveTransition) + return transition->m_isTarget; + return false; + } + + bool QQuickViewItem::prepareTransition(const QRectF &viewBounds) + { + bool doTransition = false; + + // If item is not already moving somewhere, set it to not move anywhere. + // This ensures that removed targets don't transition to the default (0,0) and that + // items set for other transition types only transition if they actually move somewhere. + if (nextTransitionType != QQuickItemViewTransitioner::NoTransition && !nextTransitionToSet) + moveTo(item->pos()); + + // For move transitions (both target and displaced) and displaced transitions of other + // types, only run the transition if the item is actually moving to another position. + + switch (nextTransitionType) { + case QQuickItemViewTransitioner::NoTransition: + { + return false; + } + case QQuickItemViewTransitioner::PopulateTransition: + { + return true; + } + case QQuickItemViewTransitioner::AddTransition: + case QQuickItemViewTransitioner::RemoveTransition: + if (viewBounds.isNull()) { + if (isTransitionTarget) + doTransition = true; + else + doTransition = transitionWillChangePosition(); + } else if (isTransitionTarget) { + // For Add targets, do transition if item is moving into visible area + // For Remove targets, do transition if item is currently in visible area + doTransition = (nextTransitionType == QQuickItemViewTransitioner::AddTransition) + ? viewBounds.intersects(QRectF(nextTransitionTo.x(), nextTransitionTo.y(), item->width(), item->height())) + : viewBounds.intersects(QRectF(item->x(), item->y(), item->width(), item->height())); + if (!doTransition) + item->setPos(nextTransitionTo); + } else { + if (viewBounds.intersects(QRectF(item->x(), item->y(), item->width(), item->height())) + || viewBounds.intersects(QRectF(nextTransitionTo.x(), nextTransitionTo.y(), item->width(), item->height()))) { + doTransition = transitionWillChangePosition(); + } else { + item->setPos(nextTransitionTo); + } + } + break; + case QQuickItemViewTransitioner::MoveTransition: + // do transition if moving from or into visible area + if (transitionWillChangePosition()) { + doTransition = viewBounds.isNull() + || viewBounds.intersects(QRectF(item->x(), item->y(), item->width(), item->height())) + || viewBounds.intersects(QRectF(nextTransitionTo.x(), nextTransitionTo.y(), item->width(), item->height())); + if (!doTransition) + item->setPos(nextTransitionTo); + } + break; + } + + if (!doTransition) + resetTransitionData(); + return doTransition; + } + + void QQuickViewItem::startTransition(QQuickItemViewTransitioner *transitioner) + { + if (nextTransitionType == QQuickItemViewTransitioner::NoTransition) + return; + + if (!transition || transition->m_type != nextTransitionType || transition->m_isTarget != isTransitionTarget) { + delete transition; + transition = new QQuickItemViewTransitionJob; + } + + // if item is not already moving somewhere, set it to not move anywhere + // so that removed items do not move to the default (0,0) + if (!nextTransitionToSet) + moveTo(item->pos()); + + transition->startTransition(this, transitioner, nextTransitionType, nextTransitionTo, isTransitionTarget); + nextTransitionType = QQuickItemViewTransitioner::NoTransition; + } + + void QQuickViewItem::stopTransition() + { + if (transition) { + transition->cancel(); + delete transition; + transition = 0; + } + resetTransitionData(); + finishedTransition(); + } + + void QQuickViewItem::setNextTransition(QQuickItemViewTransitioner::TransitionType type, bool isTargetItem) + { + // Don't reset nextTransitionToSet - once it is set, it cannot be changed + // until the animation finishes since the itemX() and itemY() may be used + // to calculate positions for transitions for other items in the view. + nextTransitionType = type; + isTransitionTarget = isTargetItem; + } + + bool QQuickViewItem::transitionWillChangePosition() const + { + if (transitionRunning() && transition->m_toPos != nextTransitionTo) + return true; + return nextTransitionTo != item->pos(); + } + + void QQuickViewItem::finishedTransition() + { + nextTransitionToSet = false; + nextTransitionTo = QPointF(); + } + + void QQuickViewItem::resetTransitionData() + { + nextTransitionType = QQuickItemViewTransitioner::NoTransition; + isTransitionTarget = false; + nextTransitionTo = QPointF(); + nextTransitionToSet = false; + } + + + QQuickViewTransitionAttached::QQuickViewTransitionAttached(QObject *parent) + : QObject(parent), m_item(0), m_index(-1) + { + } + /*! + \qmlclass ViewTransition QQuickViewTransitionAttached + \inqmlmodule QtQuick 2 + \ingroup qml-view-elements + \brief The ViewTransition attached property provides details on items under transition in a view. + + With ListView and GridView, it is possible to specify transitions that should be applied whenever + the items in the view change as a result of modifications to the view's model. They both have the + following properties that can be set to the appropriate transitions to be run for various + operations: + + \list + \o \c populate - the transition to run when a view is created, or when the model changes + \o \c add - the transition to apply to items that are added to the view + \o \c remove - the transition to apply to items that are removed from the view + \o \c move - the transition to apply to items that are moved within the view (i.e. as a result + of a move operation in the model) + \o \c displaced - the generic transition to be applied to any items that are displaced by an + add, move or remove operation + \o \c addDisplaced, \c removeDisplaced and \c moveDisplaced - the transitions to be applied when + items are displaced by add, move, or remove operations, respectively (these override the + generic displaced transition if specified) + \endlist + + For the \l Row, \l Column, \l Grid and \l Flow positioner elements, which operate with collections of child + items rather than data models, the following properties are used instead: + + \list + \o \c add - the transition to apply to items that are created for the positioner, added to + or reparented to the positioner, or items that have become \l {Item::}{visible} + \o \c move - the transition to apply to items that have moved within the positioner, including + when they are displaced due to the addition or removal of other items, or when items are otherwise + rearranged within the positioner, or when items are repositioned due to the resizing of other + items in the positioner + \endlist + + View transitions have access to a ViewTransition attached property that + provides details of the items that are under transition and the operation that triggered the + transition. Since view transitions are run once per item, these details can be used to customise + each transition for each individual item. + + The ViewTransition attached property provides the following properties specific to the item to + which the transition is applied: + + \list + \o ViewTransition.item - the item that is under transition + \o ViewTransition.index - the index of this item + \o ViewTransition.destination - the (x,y) point to which this item is moving for the relevant view operation + \endlist + + In addition, ViewTransition provides properties specific to the items which are the target + of the operation that triggered the transition: + + \list + \o ViewTransition.targetIndexes - the indexes of the target items + \o ViewTransition.targetItems - the target items themselves + \endlist + + (Note that for the \l Row, \l Column, \l Grid and \l Flow positioner elements, the \c move transition only + provides these two additional details when the transition is triggered by the addition of items + to a positioner.) + + View transitions can be written without referring to any of the attributes listed + above. These attributes merely provide extra details that are useful for customising view + transitions. + + Following is an introduction to view transitions and the ways in which the ViewTransition + attached property can be used to augment view transitions. + + + \section2 View transitions: a simple example + + Here is a basic example of the use of view transitions. The view below specifies transitions for + the \c add and \c displaced properties, which will be run when items are added to the view: + + \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-basic.qml 0 + + When the space key is pressed, adding an item to the model, the new item will fade in and + increase in scale over 400 milliseconds as it is added to the view. Also, any item that is + displaced by the addition of a new item will animate to its new position in the view over + 400 milliseconds, as specified by the \c displaced transition. + + If five items were inserted in succession at index 0, the effect would be this: + + \image viewtransitions-basic.gif + + Notice that the NumberAnimation objects above do not need to specify a \c target to animate + the appropriate item. Also, the NumberAnimation in the \c addTransition does not need to specify + the \c to value to move the item to its correct position in the view. This is because the view + implicitly sets the \c target and \c to values with the correct item and final item position + values if these properties are not explicitly defined. + + At its simplest, a view transition may just animate an item to its new position following a + view operation, just as the \c displaced transition does above, or animate some item properties, + as in the \c add transition above. Additionally, a view transition may make use of the + ViewTransition attached property to customise animation behavior for different items. Following + are some examples of how this can be achieved. + + + \section2 Using the ViewTransition attached property + + As stated, the various ViewTransition properties provide details specific to the individual item + being transitioned as well as the operation that triggered the transition. In the animation above, + five items are inserted in succession at index 0. When the fifth and final insertion takes place, + adding "Item 4" to the view, the \c add transition is run once (for the inserted item) and the + \c displaced transition is run four times (once for each of the four existing items in the view). + + At this point, if we examined the \c displaced transition that was run for the bottom displaced + item ("Item 0"), the ViewTransition property values provided to this transition would be as follows: + + \table + \header + \o Property + \o Value + \o Explanation + \row + \o ViewTransition.item + \o "Item 0" delegate instance + \o The "Item 0" \l Rectangle object itself + \row + \o ViewTransition.index + \o \c int value of 4 + \o The index of "Item 0" within the model following the add operation + \row + \o ViewTransition.destination + \o \l point value of (0, 120) + \o The position that "Item 0" is moving to + \row + \o ViewTransition.targetIndexes + \o \c int array, just contains the integer "0" (zero) + \o The index of "Item 4", the new item added to the view + \row + \o ViewTransition.targetItems + \o object array, just contains the "Item 4" delegate instance + \o The "Item 4" \l Rectangle object - the new item added to the view + \endtable + + The ViewTransition.targetIndexes and ViewTransition.targetItems lists provide the items and + indexes of all delegate instances that are the targets of the relevant operation. For an add + operation, these are all the items that are added into the view; for a remove, these are all + the items removed from the view, and so on. (Note these lists will only contain references to + items that have been created within the view or its cached items; targets that are not within + the visible area of the view or within the item cache will not be accessible.) + + So, while the ViewTransition.item, ViewTransition.index and ViewTransition.destination values + vary for each individual transition that is run, the ViewTransition.targetIndexes and + ViewTransition.targetItems values are the same for every \c add and \c displaced transition + that is triggered by a particular add operation. + + + \section3 Delaying animations based on index + + Since each view transition is run once for each item affected by the transition, the ViewTransition + properties can be used within a transition to define custom behavior for each item's transition. + For example, the ListView in the previous example could use this information to create a ripple-type + effect on the movement of the displaced items. + + This can be achieved by modifying the \c displaced transition so that it delays the animation of + each displaced item based on the difference between its index (provided by ViewTransition.index) + and the first removed index (provided by ViewTransition.targetIndexes): + + \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-delayedbyindex.qml 0 + + Each displaced item delays its animation by an additional 100 milliseconds, producing a subtle + ripple-type effect when items are displaced by the add, like this: + + \image viewtransitions-delayedbyindex.gif + + + \section3 Animating items to intermediate positions + + The ViewTransition.item property gives a reference to the item to which the transition is being + applied. This can be used to access any of the item's attributes, custom \c property values, + and so on. + + Below is a modification of the \c displaced transition from the previous example. It adds a + ParallelAnimation with nested NumberAnimation objects that reference ViewTransition.item to access + each item's \c x and \c y values at the start of their transitions. This allows each item to + animate to an intermediate position relative to its starting point for the transition, before + animating to its final position in the view: + + \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-intermediatemove.qml 0 + + Now, a displaced item will first move to a position of (20, 50) relative to its starting + position, and then to its final, correct position in the view: + + \image viewtransitions-intermediatemove.gif + + Since the final NumberAnimation does not specify a \c to value, the view implicitly sets this + value to the item's final position in the view, and so this last animation will move this item + to the correct place. If the transition requires the final position of the item for some calculation, + this is accessible through ViewTransition.destination. + + Instead of using multiple NumberAnimations, you could use a PathAnimation to animate an item over + a curved path. For example, the \c add transition in the previous example could be augmented with + a PathAnimation as follows: to animate newly added items along a path: + + \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-pathanim.qml 0 + + This animates newly added items along a path. Notice that each path is specified relative to + each item's final destination point, so that items inserted at different indexes start their + paths from different positions: + + \image viewtransitions-pathanim.gif + + + \section2 Handling interrupted animations + + A view transition may be interrupted at any time if a different view transition needs to be + applied while the original transition is in progress. For example, say Item A is inserted at index 0 + and undergoes an "add" transition; then, Item B is inserted at index 0 in quick succession before + Item A's transition has finished. Since Item B is inserted before Item A, it will displace Item + A, causing the view to interrupt Item A's "add" transition mid-way and start a "displaced" + transition on Item A instead. + + For simple animations that simply animate an item's movement to its final destination, this + interruption is unlikely to require additional consideration. However, if a transition changes other + properties, this interruption may cause unwanted side effects. Consider the first example on this + page, repeated below for convenience: + + \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-basic.qml 0 + + If multiple items are added in rapid succession, without waiting for a previous transition + to finish, this is the result: + + \image viewtransitions-interruptedbad.gif + + Each newly added item undergoes an \c add transition, but before the transition can finish, + another item is added, displacing the previously added item. Because of this, the \c add + transition on the previously added item is interrupted and a \c displaced transition is + started on the item instead. Due to the interruption, the \c opacity and \c scale animations + have not completed, thus producing items with opacity and scale that are below 1.0. + + To fix this, the \c displaced transition should additionally ensure the item properties are + set to the end values specified in the \c add transition, effectively resetting these values + whenever an item is displaced. In this case, it means setting the item opacity and scale to 1.0: + + \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-interruptedgood.qml 0 + + Now, when an item's \c add transition is interrupted, its opacity and scale are animated to 1.0 + upon displacement, avoiding the erroneous visual effects from before: + + \image viewtransitions-interruptedgood.gif + + The same principle applies to any combination of view transitions. An added item may be moved + before its add transition finishes, or a moved item may be removed before its moved transition + finishes, and so on; so, the rule of thumb is that every transition should handle the same set of + properties. + + + \section2 Restrictions regarding ScriptAction + + When a view transition is initialized, any property bindings that refer to the ViewTransition + attached property are evaluated in preparation for the transition. Due to the nature of the + internal construction of a view transition, the attributes of the ViewTransition attached + property are only valid for the relevant item when the transition is initialized, and may not be + valid when the transition is actually run. + + Therefore, a ScriptAction within a view transition should not refer to the ViewTransition + attached property, as it may not refer to the expected values at the time that the ScriptAction + is actually invoked. Consider the following example: + + \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-scriptactionbad.qml 0 + + When the space key is pressed, three items are moved from index 5 to index 1. For each moved + item, the \c moveTransition sequence presumably animates the item's color to "yellow", then + animates it to its final position, then changes the item color back to "lightsteelblue" using a + ScriptAction. However, when run, the transition does not produce the intended result: + + \image viewtransitions-scriptactionbad.gif + + Only the last moved item is returned to the "lightsteelblue" color; the others remain yellow. This + is because the ScriptAction is not run until after the transition has already been initialized, by + which time the ViewTransition.item value has changed to refer to a different item; the item that + the script had intended to refer to is not the one held by ViewTransition.item at the time the + ScriptAction is actually invoked. + + In this instance, to avoid this issue, the view could set the property using a PropertyAction + instead: + + \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-scriptactiongood.qml 0 + + When the transition is initialized, the PropertyAction \c target will be set to the respective + ViewTransition.item for the transition and will later run with the correct item target as + expected. + */ + + /*! + \qmlattachedproperty list QtQuick2::ViewTransition::index + + This attached property holds the index of the item that is being + transitioned. + + Note that if the item is being moved, this property holds the index that + the item is moving to, not from. + */ + + /*! + \qmlattachedproperty list QtQuick2::ViewTransition::item + + This attached property holds the the item that is being transitioned. + + \warning This item should not be kept and referred to outside of the transition + as it may become invalid as the view changes. + */ + + /*! + \qmlattachedproperty list QtQuick2::ViewTransition::destination + + This attached property holds the final destination position for the transitioned + item within the view. + + This property value is a \l point with \c x and \c y properties. + */ + + /*! + \qmlattachedproperty list QtQuick2::ViewTransition::targetIndexes + + This attached property holds a list of the indexes of the items in view + that are the target of the relevant operation. + + The targets are the items that are the subject of the operation. For + an add operation, these are the items being added; for a remove, these + are the items being removed; for a move, these are the items being + moved. + + For example, if the transition was triggered by an insert operation + that added two items at index 1 and 2, this targetIndexes list would + have the value [1,2]. + + \note The targetIndexes list only contains the indexes of items that are actually + in view, or will be in the view once the relevant operation completes. + + \sa QtQuick2::ViewTransition::targetIndexes + */ + + /*! + \qmlattachedproperty list QtQuick2::ViewTransition::targetItems + + This attached property holds the list of items in view that are the + target of the relevant operation. + + The targets are the items that are the subject of the operation. For + an add operation, these are the items being added; for a remove, these + are the items being removed; for a move, these are the items being + moved. + + For example, if the transition was triggered by an insert operation + that added two items at index 1 and 2, this targetItems list would + contain these two items. + + \note The targetItems list only contains items that are actually + in view, or will be in the view once the relevant operation completes. + + \warning The objects in this list should not be kept and referred to + outside of the transition as the items may become invalid. The targetItems + are only valid when the Transition is initially created; this also means + they should not be used by ScriptAction objects in the Transition, which are + not evaluated until the transition is run. + + \sa QtQuick2::ViewTransition::targetIndexes + */ -QDeclarativeListProperty QQuickViewTransitionAttached::targetItems() ++QQmlListProperty QQuickViewTransitionAttached::targetItems() + { - return QDeclarativeListProperty(this, m_targetItems); ++ return QQmlListProperty(this, m_targetItems); + } + + QQuickViewTransitionAttached *QQuickViewTransitionAttached::qmlAttachedProperties(QObject *obj) + { + return new QQuickViewTransitionAttached(obj); + } + + QT_END_NAMESPACE diff --cc src/quick/items/qquickitemviewtransition_p.h index 0000000,57ea85b..3fb43d6 mode 000000,100644..100644 --- a/src/quick/items/qquickitemviewtransition_p.h +++ b/src/quick/items/qquickitemviewtransition_p.h @@@ -1,0 -1,209 +1,209 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + #ifndef QQUICKITEMVIEWTRANSITION_P_P_H + #define QQUICKITEMVIEWTRANSITION_P_P_H + -#include ++#include + + QT_BEGIN_HEADER + + QT_BEGIN_NAMESPACE + -QT_MODULE(Declarative) ++QT_MODULE(Quick) + + class QQuickItem; + class QQuickViewItem; + class QQuickItemViewTransitionJob; + + + class QQuickItemViewTransitionChangeListener + { + public: + QQuickItemViewTransitionChangeListener() {} + virtual ~QQuickItemViewTransitionChangeListener() {} + + virtual void viewItemTransitionFinished(QQuickViewItem *item) = 0; + }; + + + class QQuickItemViewTransitioner + { + public: + enum TransitionType { + NoTransition, + PopulateTransition, + AddTransition, + MoveTransition, + RemoveTransition + }; + + QQuickItemViewTransitioner(); + virtual ~QQuickItemViewTransitioner(); + + bool canTransition(QQuickItemViewTransitioner::TransitionType type, bool asTarget) const; + void transitionNextReposition(QQuickViewItem *item, QQuickItemViewTransitioner::TransitionType type, bool isTarget); + - QDeclarativeTransition *transitionObject(QQuickItemViewTransitioner::TransitionType type, bool asTarget); ++ QQuickTransition *transitionObject(QQuickItemViewTransitioner::TransitionType type, bool asTarget); + const QList &targetIndexes(QQuickItemViewTransitioner::TransitionType type) const; + const QList &targetItems(QQuickItemViewTransitioner::TransitionType type) const; + + inline void setPopulateTransitionEnabled(bool b) { usePopulateTransition = b; } + inline void setChangeListener(QQuickItemViewTransitionChangeListener *obj) { changeListener = obj; } + + QSet runningJobs; + + QList addTransitionIndexes; + QList moveTransitionIndexes; + QList removeTransitionIndexes; + QList addTransitionTargets; + QList moveTransitionTargets; + QList removeTransitionTargets; + - QDeclarativeTransition *populateTransition; - QDeclarativeTransition *addTransition; - QDeclarativeTransition *addDisplacedTransition; - QDeclarativeTransition *moveTransition; - QDeclarativeTransition *moveDisplacedTransition; - QDeclarativeTransition *removeTransition; - QDeclarativeTransition *removeDisplacedTransition; - QDeclarativeTransition *displacedTransition; ++ QQuickTransition *populateTransition; ++ QQuickTransition *addTransition; ++ QQuickTransition *addDisplacedTransition; ++ QQuickTransition *moveTransition; ++ QQuickTransition *moveDisplacedTransition; ++ QQuickTransition *removeTransition; ++ QQuickTransition *removeDisplacedTransition; ++ QQuickTransition *displacedTransition; + + private: + friend class QQuickItemViewTransitionJob; + + QQuickItemViewTransitionChangeListener *changeListener; + bool usePopulateTransition; + + void finishedTransition(QQuickItemViewTransitionJob *job, QQuickViewItem *item); + }; + + + /* + An item in a view, that can be transitioned using QQuickViewTransitionJob. + */ + class QQuickViewItem + { + public: + QQuickViewItem(QQuickItem *i); + virtual ~QQuickViewItem(); + + qreal itemX() const; + qreal itemY() const; + + void moveTo(const QPointF &pos); + void setVisible(bool visible); + + bool transitionScheduledOrRunning() const; + bool transitionRunning() const; + bool isPendingRemoval() const; + + bool prepareTransition(const QRectF &viewBounds); + void startTransition(QQuickItemViewTransitioner *transitioner); + void stopTransition(); + + QPointF nextTransitionTo; + QQuickItem *item; + QQuickItemViewTransitionJob *transition; + QQuickItemViewTransitioner::TransitionType nextTransitionType; + int index; + bool isTransitionTarget; + bool nextTransitionToSet; + + private: + friend class QQuickItemViewTransitioner; + friend class QQuickItemViewTransitionJob; + void setNextTransition(QQuickItemViewTransitioner::TransitionType, bool isTargetItem); + bool transitionWillChangePosition() const; + void finishedTransition(); + void resetTransitionData(); + }; + + + class QQuickViewTransitionAttached : public QObject + { + Q_OBJECT + + Q_PROPERTY(int index READ index NOTIFY indexChanged) + Q_PROPERTY(QQuickItem* item READ item NOTIFY itemChanged) + Q_PROPERTY(QPointF destination READ destination NOTIFY destinationChanged) + + Q_PROPERTY(QList targetIndexes READ targetIndexes NOTIFY targetIndexesChanged) - Q_PROPERTY(QDeclarativeListProperty targetItems READ targetItems NOTIFY targetItemsChanged) ++ Q_PROPERTY(QQmlListProperty targetItems READ targetItems NOTIFY targetItemsChanged) + + public: + QQuickViewTransitionAttached(QObject *parent); + + int index() const { return m_index; } + QQuickItem *item() const { return m_item; } + QPointF destination() const { return m_destination; } + + QList targetIndexes() const { return m_targetIndexes; } - QDeclarativeListProperty targetItems(); ++ QQmlListProperty targetItems(); + + static QQuickViewTransitionAttached *qmlAttachedProperties(QObject *); + + signals: + void indexChanged(); + void itemChanged(); + void destinationChanged(); + + void targetIndexesChanged(); + void targetItemsChanged(); + + private: + friend class QQuickItemViewTransitionJob; + QPointF m_destination; + QList m_targetIndexes; + QList m_targetItems; + + QQuickItem *m_item; + int m_index; + }; + + QT_END_NAMESPACE + + QML_DECLARE_TYPE(QQuickViewTransitionAttached) + QML_DECLARE_TYPEINFO(QQuickViewTransitionAttached, QML_HAS_ATTACHED_PROPERTIES) + + QT_END_HEADER + + #endif // QQUICKITEMVIEWTRANSITION_P_P_H diff --cc src/quick/items/qquicklistview.cpp index beb607d,876859e..5e9a685 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@@ -944,18 -955,18 +955,18 @@@ void QQuickListViewPrivate::updateInlin if (listItem->attached->m_prevSection != listItem->attached->m_section && (sectionCriteria->labelPositioning() & QQuickViewSection::InlineLabels || (listItem->index == 0 && sectionCriteria->labelPositioning() & QQuickViewSection::CurrentLabelAtStart))) { - if (!listItem->section) { + if (!listItem->section()) { qreal pos = listItem->position(); - listItem->section = getSectionItem(listItem->attached->m_section); + listItem->setSection(getSectionItem(listItem->attached->m_section)); listItem->setPosition(pos); } else { - QQmlContext *context = QQmlEngine::contextForObject(listItem->section)->parentContext(); - QDeclarativeContext *context = QDeclarativeEngine::contextForObject(listItem->section())->parentContext(); ++ QQmlContext *context = QQmlEngine::contextForObject(listItem->section())->parentContext(); context->setContextProperty(QLatin1String("section"), listItem->attached->m_section); } - } else if (listItem->section) { + } else if (listItem->section()) { qreal pos = listItem->position(); - releaseSectionItem(listItem->section); - listItem->section = 0; + releaseSectionItem(listItem->section()); + listItem->setSection(0); listItem->setPosition(pos); } } diff --cc src/quick/items/qquicklistview_p.h index 239647a,058c50f..ef989ba --- a/src/quick/items/qquicklistview_p.h +++ b/src/quick/items/qquicklistview_p.h @@@ -197,7 -197,8 +197,8 @@@ Q_SIGNALS void viewChanged(); public: - QDeclarativeGuard m_view; + QQmlGuard m_view; + QQuickItem *m_sectionItem; }; diff --cc src/quick/items/qquickpositioners.cpp index 739f74d,6ed35a9..e1d0457 --- a/src/quick/items/qquickpositioners.cpp +++ b/src/quick/items/qquickpositioners.cpp @@@ -137,34 -140,39 +140,39 @@@ void QQuickBasePositioner::setSpacing(q emit spacingChanged(); } -QDeclarativeTransition *QQuickBasePositioner::move() const +QQuickTransition *QQuickBasePositioner::move() const { Q_D(const QQuickBasePositioner); - return d->moveTransition; + return d->transitioner ? d->transitioner->displacedTransition : 0; } -void QQuickBasePositioner::setMove(QDeclarativeTransition *mt) +void QQuickBasePositioner::setMove(QQuickTransition *mt) { Q_D(QQuickBasePositioner); - if (mt == d->moveTransition) + if (!d->transitioner) + d->transitioner = new QQuickItemViewTransitioner; + if (mt == d->transitioner->displacedTransition) return; - d->moveTransition = mt; + + d->transitioner->displacedTransition = mt; emit moveChanged(); } -QDeclarativeTransition *QQuickBasePositioner::add() const +QQuickTransition *QQuickBasePositioner::add() const { Q_D(const QQuickBasePositioner); - return d->addTransition; + return d->transitioner ? d->transitioner->addTransition : 0; } -void QQuickBasePositioner::setAdd(QDeclarativeTransition *add) +void QQuickBasePositioner::setAdd(QQuickTransition *add) { Q_D(QQuickBasePositioner); - if (add == d->addTransition) + if (!d->transitioner) + d->transitioner = new QQuickItemViewTransitioner; + if (add == d->transitioner->addTransition) return; - d->addTransition = add; + d->transitioner->addTransition = add; emit addChanged(); } @@@ -511,15 -557,24 +557,24 @@@ void QQuickPositionerAttached::setIsLas /*! \qmlproperty Transition QtQuick2::Column::move - This property holds the transition to apply to any item that has moved - within the positioner. Positioner transitions will only affect - the position (x, y) of items. + This property holds the transition to run for items that have moved within the + positioner. For a positioner, this applies to: + + \list + \o Child items that move when they are displaced due to the addition, removal or + rearrangement of other items in the positioner + \o Child items that are repositioned due to the resizing of other items in the positioner + \endlist + + The transition can use the \l ViewTransition property to access more details about + the item that is being moved. Note, however, that for this move transition, the + ViewTransition.targetIndexes and ViewTransition.targetItems lists are only set when + this transition is triggered by the addition of other items in the positioner; in other + cases, these lists will be empty. - This transition is applied to items that are displaced as a result of the - addition or removal of other items in the positioner, or when items move due to - a move operation in a related model, or when items resize themselves. + See the \l ViewTransition documentation for more details and examples on using these transitions. - \sa add, {qml/positioners}{Positioners example} - \sa add, ViewTransition, {declarative/positioners}{Positioners example} ++ \sa add, ViewTransition, {qml/positioners}{Positioners example} */ /*! \qmlproperty real QtQuick2::Column::spacing @@@ -635,27 -690,24 +690,24 @@@ void QQuickColumn::reportConflictingAnc /*! \qmlproperty Transition QtQuick2::Row::move - This property holds the transition to apply to any item that has moved - within the positioner. Positioner transitions will only affect - the position (x, y) of items. - - This transition is applied to items that are displaced as a result of the - addition or removal of other items in the positioner, or when items move due to - a move operation in a related model, or when items resize themselves. - - \qml - Row { - id: positioner - move: Transition { - NumberAnimation { - properties: "x" - duration: 1000 - } - } - } - \endqml + This property holds the transition to run for items that have moved within the + positioner. For a positioner, this applies to: + + \list + \o Child items that move when they are displaced due to the addition, removal or + rearrangement of other items in the positioner + \o Child items that are repositioned due to the resizing of other items in the positioner + \endlist - \sa add, {qml/positioners}{Positioners example} + The transition can use the \l ViewTransition property to access more details about + the item that is being moved. Note, however, that for this move transition, the + ViewTransition.targetIndexes and ViewTransition.targetItems lists are only set when + this transition is triggered by the addition of other items in the positioner; in other + cases, these lists will be empty. + + See the \l ViewTransition documentation for more details and examples on using these transitions. + - \sa add, ViewTransition, {declarative/positioners}{Positioners example} ++ \sa add, ViewTransition, {qml/positioners}{Positioners example} */ /*! \qmlproperty real QtQuick2::Row::spacing @@@ -849,26 -902,24 +902,24 @@@ void QQuickRow::reportConflictingAnchor /*! \qmlproperty Transition QtQuick2::Grid::move - This property holds the transition to apply to any item that has moved - within the positioner. Positioner transitions will only affect - the position (x, y) of items. + This property holds the transition to run for items that have moved within the + positioner. For a positioner, this applies to: - This transition is applied to items that are displaced as a result of the - addition or removal of other items in the positioner, or when items move due to - a move operation in a related model, or when items resize themselves. + \list + \o Child items that move when they are displaced due to the addition, removal or + rearrangement of other items in the positioner + \o Child items that are repositioned due to the resizing of other items in the positioner + \endlist - \qml - Grid { - move: Transition { - NumberAnimation { - properties: "x,y" - duration: 1000 - } - } - } - \endqml + The transition can use the \l ViewTransition property to access more details about + the item that is being moved. Note, however, that for this move transition, the + ViewTransition.targetIndexes and ViewTransition.targetItems lists are only set when + this transition is triggered by the addition of other items in the positioner; in other + cases, these lists will be empty. + + See the \l ViewTransition documentation for more details and examples on using these transitions. - \sa add, {qml/positioners}{Positioners example} - \sa add, ViewTransition, {declarative/positioners}{Positioners example} ++ \sa add, ViewTransition, {qml/positioners}{Positioners example} */ /*! \qmlproperty qreal QtQuick2::Grid::spacing @@@ -1264,27 -1315,24 +1315,24 @@@ void QQuickGrid::reportConflictingAncho /*! \qmlproperty Transition QtQuick2::Flow::move - This property holds the transition to apply to any item that has moved - within the positioner. Positioner transitions will only affect - the position (x, y) of items. - - This transition is applied to items that are displaced as a result of the - addition or removal of other items in the positioner, or when items move due to - a move operation in a related model, or when items resize themselves. - - \qml - Flow { - id: positioner - move: Transition { - NumberAnimation { - properties: "x,y" - ease: "easeOutBounce" - } - } - } - \endqml + This property holds the transition to run for items that have moved within the + positioner. For a positioner, this applies to: + + \list + \o Child items that move when they are displaced due to the addition, removal or + rearrangement of other items in the positioner + \o Child items that are repositioned due to the resizing of other items in the positioner + \endlist + + The transition can use the \l ViewTransition property to access more details about + the item that is being moved. Note, however, that for this move transition, the + ViewTransition.targetIndexes and ViewTransition.targetItems lists are only set when + this transition is triggered by the addition of other items in the positioner; in other + cases, these lists will be empty. + + See the \l ViewTransition documentation for more details and examples on using these transitions. - \sa add, {qml/positioners}{Positioners example} - \sa add, ViewTransition, {declarative/positioners}{Positioners example} ++ \sa add, ViewTransition, {qml/positioners}{Positioners example} */ /*! \qmlproperty real QtQuick2::Flow::spacing diff --cc src/quick/items/qquickpositioners_p.h index a2ad572,32dd903..8921bfa --- a/src/quick/items/qquickpositioners_p.h +++ b/src/quick/items/qquickpositioners_p.h @@@ -43,8 -43,9 +43,9 @@@ #define QQUICKPOSITIONERS_P_H #include "qquickimplicitsizeitem_p.h" + #include "qquickitemviewtransition_p.h" -#include +#include #include #include @@@ -92,10 -93,11 +93,11 @@@ class Q_QUICK_PRIVATE_EXPORT QQuickBase Q_OBJECT Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged) - Q_PROPERTY(QDeclarativeTransition *move READ move WRITE setMove NOTIFY moveChanged) - Q_PROPERTY(QDeclarativeTransition *add READ add WRITE setAdd NOTIFY addChanged) + Q_PROPERTY(QQuickTransition *move READ move WRITE setMove NOTIFY moveChanged) + Q_PROPERTY(QQuickTransition *add READ add WRITE setAdd NOTIFY addChanged) public: enum PositionerType { None = 0x0, Horizontal = 0x1, Vertical = 0x2, Both = 0x3 }; + QQuickBasePositioner(PositionerType, QQuickItem *parent); ~QQuickBasePositioner(); diff --cc src/quick/items/qquicksprite.cpp index 817a6b4,2a1bd08..e0535ed --- a/src/quick/items/qquicksprite.cpp +++ b/src/quick/items/qquicksprite.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/items/qquicksprite_p.h index 7c5c20b,dd6560f..85e3ed8 --- a/src/quick/items/qquicksprite_p.h +++ b/src/quick/items/qquicksprite_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage @@@ -45,9 -45,10 +45,10 @@@ #include #include #include -#include -#include +#include +#include #include "qquickspriteengine_p.h" + #include QT_BEGIN_HEADER diff --cc src/quick/items/qquickspriteengine.cpp index 5a78472,c19a5e6..1c35688 --- a/src/quick/items/qquickspriteengine.cpp +++ b/src/quick/items/qquickspriteengine.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/items/qquickspriteengine_p.h index 751b75f,500d526..3763509 --- a/src/quick/items/qquickspriteengine_p.h +++ b/src/quick/items/qquickspriteengine_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/items/qquickspritesequence.cpp index 0000000,a3a8a6e..ce0a246 mode 000000,100644..100644 --- a/src/quick/items/qquickspritesequence.cpp +++ b/src/quick/items/qquickspritesequence.cpp @@@ -1,0 -1,482 +1,482 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + #include "qquickspritesequence_p.h" + #include "qquicksprite_p.h" + #include "qquickspriteengine_p.h" + #include + #include + #include + #include + #include + #include + #include -#include ++#include + #include + #include + #include + #include + + QT_BEGIN_NAMESPACE + + static const char vertexShaderCode[] = + "attribute highp vec2 vTex;\n" + "uniform highp vec3 animData;// w,h(premultiplied of anim), interpolation progress\n" + "uniform highp vec4 animPos;//x,y, x,y (two frames for interpolation)\n" + "uniform highp vec2 size;//w,h of element\n" + "\n" + "uniform highp mat4 qt_Matrix;\n" + "\n" + "varying highp vec4 fTexS;\n" + "varying lowp float progress;\n" + "\n" + "\n" + "void main() {\n" + " progress = animData.z;\n" + " //Calculate frame location in texture\n" + " fTexS.xy = animPos.xy + vTex.xy * animData.xy;\n" + " //Next frame is also passed, for interpolation\n" + " fTexS.zw = animPos.zw + vTex.xy * animData.xy;\n" + "\n" + " gl_Position = qt_Matrix * vec4(size.x * vTex.x, size.y * vTex.y, 0, 1);\n" + "}\n"; + + static const char fragmentShaderCode[] = + "uniform sampler2D texture;\n" + "uniform lowp float qt_Opacity;\n" + "\n" + "varying highp vec4 fTexS;\n" + "varying lowp float progress;\n" + "\n" + "void main() {\n" + " gl_FragColor = mix(texture2D(texture, fTexS.xy), texture2D(texture, fTexS.zw), progress) * qt_Opacity;\n" + "}\n"; + + class QQuickSpriteSequenceMaterial : public QSGMaterial + { + public: + QQuickSpriteSequenceMaterial(); + ~QQuickSpriteSequenceMaterial(); + virtual QSGMaterialType *type() const { static QSGMaterialType type; return &type; } + virtual QSGMaterialShader *createShader() const; + virtual int compare(const QSGMaterial *other) const + { + return this - static_cast(other); + } + + QSGTexture *texture; + + float animT; + float animX1; + float animY1; + float animX2; + float animY2; + float animW; + float animH; + float elementWidth; + float elementHeight; + }; + + QQuickSpriteSequenceMaterial::QQuickSpriteSequenceMaterial() + : animT(0.0f) + , animX1(0.0f) + , animY1(0.0f) + , animX2(0.0f) + , animY2(0.0f) + , animW(1.0f) + , animH(1.0f) + , elementWidth(1.0f) + , elementHeight(1.0f) + { + setFlag(Blending, true); + } + + QQuickSpriteSequenceMaterial::~QQuickSpriteSequenceMaterial() + { + delete texture; + } + + class SpriteSequenceMaterialData : public QSGMaterialShader + { + public: + SpriteSequenceMaterialData(const char * /* vertexFile */ = 0, const char * /* fragmentFile */ = 0) + { + } + + void deactivate() { + QSGMaterialShader::deactivate(); + + for (int i=0; i<8; ++i) { + program()->setAttributeArray(i, GL_FLOAT, chunkOfBytes, 1, 0); + } + } + + virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *) + { + QQuickSpriteSequenceMaterial *m = static_cast(newEffect); + m->texture->bind(); + + program()->setUniformValue(m_opacity_id, state.opacity()); + program()->setUniformValue(m_animData_id, m->animW, m->animH, m->animT); + program()->setUniformValue(m_animPos_id, m->animX1, m->animY1, m->animX2, m->animY2); + program()->setUniformValue(m_size_id, m->elementWidth, m->elementHeight); + + if (state.isMatrixDirty()) + program()->setUniformValue(m_matrix_id, state.combinedMatrix()); + } + + virtual void initialize() { + m_matrix_id = program()->uniformLocation("qt_Matrix"); + m_opacity_id = program()->uniformLocation("qt_Opacity"); + m_animData_id = program()->uniformLocation("animData"); + m_animPos_id = program()->uniformLocation("animPos"); + m_size_id = program()->uniformLocation("size"); + } + + virtual const char *vertexShader() const { return vertexShaderCode; } + virtual const char *fragmentShader() const { return fragmentShaderCode; } + + virtual char const *const *attributeNames() const { + static const char *attr[] = { + "vTex", + 0 + }; + return attr; + } + + int m_matrix_id; + int m_opacity_id; + int m_animData_id; + int m_animPos_id; + int m_size_id; + + static float chunkOfBytes[1024]; + }; + + float SpriteSequenceMaterialData::chunkOfBytes[1024]; + + QSGMaterialShader *QQuickSpriteSequenceMaterial::createShader() const + { + return new SpriteSequenceMaterialData; + } + + struct SpriteVertex { + float tx; + float ty; + }; + + struct SpriteVertices { + SpriteVertex v1; + SpriteVertex v2; + SpriteVertex v3; + SpriteVertex v4; + }; + + /*! + \qmlclass SpriteSequence QQuickSpriteSequence + \inqmlmodule QtQuick 2 + \inherits Item + \brief The SpriteSequence element draws a sprite animation + + */ + /*! + \qmlproperty bool QtQuick2::SpriteSequence::running + + Whether the sprite is animating or not. + + Default is true + */ + /*! + \qmlproperty bool QtQuick2::SpriteSequence::interpolate + + If true, interpolation will occur between sprite frames to make the + animation appear smoother. + + Default is true. + */ + /*! + \qmlproperty string QtQuick2::SpriteSequence::goalSprite + + The name of the Sprite which is currently animating. + */ + /*! + \qmlproperty string QtQuick2::SpriteSequence::goalSprite + + The name of the Sprite which the animation should move to. + + Sprite states have defined durations and transitions between them, setting goalState + will cause it to disregard any path weightings (including 0) and head down the path + which will reach the goalState quickest (fewest animations). It will pass through + intermediate states on that path, and animate them for their duration. + + If it is possible to return to the goalState from the starting point of the goalState + it will continue to do so until goalState is set to "" or an unreachable state. + */ + /*! \qmlmethod void QtQuick2::SpriteSequence::jumpTo(string sprite) + + This function causes the sprite to jump to the specified state immediately, intermediate + states are not played. + */ + /*! + \qmlproperty list QtQuick2::SpriteSequence::sprites + + The sprite or sprites to draw. Sprites will be scaled to the size of this element. + */ + + //TODO: Implicitly size element to size of first sprite? + QQuickSpriteSequence::QQuickSpriteSequence(QQuickItem *parent) : + QQuickItem(parent) + , m_node(0) + , m_material(0) + , m_spriteEngine(0) + , m_curFrame(0) + , m_pleaseReset(false) + , m_running(true) + , m_interpolate(true) + , m_curStateIdx(0) + { + setFlag(ItemHasContents); + connect(this, SIGNAL(runningChanged(bool)), + this, SLOT(update())); + } + + void QQuickSpriteSequence::jumpTo(const QString &sprite) + { + if (!m_spriteEngine) + return; + m_spriteEngine->setGoal(m_spriteEngine->stateIndex(sprite), 0, true); + } + + void QQuickSpriteSequence::setGoalSprite(const QString &sprite) + { + if (m_goalState != sprite){ + m_goalState = sprite; + emit goalSpriteChanged(sprite); + m_spriteEngine->setGoal(m_spriteEngine->stateIndex(sprite)); + } + } + -QDeclarativeListProperty QQuickSpriteSequence::sprites() ++QQmlListProperty QQuickSpriteSequence::sprites() + { - return QDeclarativeListProperty(this, &m_sprites, spriteAppend, spriteCount, spriteAt, spriteClear); ++ return QQmlListProperty(this, &m_sprites, spriteAppend, spriteCount, spriteAt, spriteClear); + } + + void QQuickSpriteSequence::createEngine() + { + //TODO: delay until component complete + if (m_spriteEngine) + delete m_spriteEngine; + if (m_sprites.count()) + m_spriteEngine = new QQuickSpriteEngine(m_sprites, this); + else + m_spriteEngine = 0; + reset(); + } + + static QSGGeometry::Attribute SpriteSequence_Attributes[] = { + QSGGeometry::Attribute::create(0, 2, GL_FLOAT), // tex + }; + + static QSGGeometry::AttributeSet SpriteSequence_AttributeSet = + { + 1, // Attribute Count + 2 * sizeof(float), + SpriteSequence_Attributes + }; + + QSGGeometryNode* QQuickSpriteSequence::buildNode() + { + if (!m_spriteEngine) { + qmlInfo(this) << "No sprite engine..."; + return 0; - } else if (m_spriteEngine->status() == QDeclarativePixmap::Null) { ++ } else if (m_spriteEngine->status() == QQuickPixmap::Null) { + m_spriteEngine->startAssemblingImage(); + update();//Schedule another update, where we will check again + return 0; - } else if (m_spriteEngine->status() == QDeclarativePixmap::Loading) { ++ } else if (m_spriteEngine->status() == QQuickPixmap::Loading) { + update();//Schedule another update, where we will check again + return 0; + } + + m_material = new QQuickSpriteSequenceMaterial(); + + QImage image = m_spriteEngine->assembledImage(); + if (image.isNull()) + return 0; + m_sheetSize = QSizeF(image.size()); + m_material->texture = canvas()->createTextureFromImage(image); + m_material->texture->setFiltering(QSGTexture::Linear); + m_spriteEngine->start(0); + m_material->animT = 0; + m_material->animX1 = m_spriteEngine->spriteX() / m_sheetSize.width(); + m_material->animY1 = m_spriteEngine->spriteY() / m_sheetSize.height(); + m_material->animX2 = m_material->animX1; + m_material->animY2 = m_material->animY1; + m_material->animW = m_spriteEngine->spriteWidth() / m_sheetSize.width(); + m_material->animH = m_spriteEngine->spriteHeight() / m_sheetSize.height(); + m_material->elementWidth = width(); + m_material->elementHeight = height(); + m_curState = m_spriteEngine->state(m_spriteEngine->curState())->name(); + emit currentSpriteChanged(m_curState); + + int vCount = 4; + int iCount = 6; + QSGGeometry *g = new QSGGeometry(SpriteSequence_AttributeSet, vCount, iCount); + g->setDrawingMode(GL_TRIANGLES); + + SpriteVertices *p = (SpriteVertices *) g->vertexData(); + + p->v1.tx = 0; + p->v1.ty = 0; + + p->v2.tx = 1.0; + p->v2.ty = 0; + + p->v3.tx = 0; + p->v3.ty = 1.0; + + p->v4.tx = 1.0; + p->v4.ty = 1.0; + + quint16 *indices = g->indexDataAsUShort(); + indices[0] = 0; + indices[1] = 1; + indices[2] = 2; + indices[3] = 1; + indices[4] = 3; + indices[5] = 2; + + + m_timestamp.start(); + m_node = new QSGGeometryNode(); + m_node->setGeometry(g); + m_node->setMaterial(m_material); + m_node->setFlag(QSGGeometryNode::OwnsMaterial); + return m_node; + } + + void QQuickSpriteSequence::reset() + { + m_pleaseReset = true; + } + + QSGNode *QQuickSpriteSequence::updatePaintNode(QSGNode *, UpdatePaintNodeData *) + { + if (m_pleaseReset) { + delete m_node; + + m_node = 0; + m_material = 0; + m_pleaseReset = false; + } + + prepareNextFrame(); + + if (m_running) { + update(); + if (m_node) + m_node->markDirty(QSGNode::DirtyMaterial); + } + + return m_node; + } + + void QQuickSpriteSequence::prepareNextFrame() + { + if (m_node == 0) + m_node = buildNode(); + if (m_node == 0) //error creating node + return; + + uint timeInt = m_timestamp.elapsed(); + qreal time = timeInt / 1000.; + m_material->elementHeight = height(); + m_material->elementWidth = width(); + + //Advance State + m_spriteEngine->updateSprites(timeInt); + if (m_curStateIdx != m_spriteEngine->curState()) { + m_curStateIdx = m_spriteEngine->curState(); + m_curState = m_spriteEngine->state(m_spriteEngine->curState())->name(); + emit currentSpriteChanged(m_curState); + m_curFrame= -1; + } + + //Advance Sprite + qreal animT = m_spriteEngine->spriteStart()/1000.0; + qreal frameCount = m_spriteEngine->spriteFrames(); + qreal frameDuration = m_spriteEngine->spriteDuration()/frameCount; + double frameAt; + qreal progress; + if (frameDuration > 0) { + qreal frame = (time - animT)/(frameDuration / 1000.0); + frame = qBound(qreal(0.0), frame, frameCount - qreal(1.0));//Stop at count-1 frames until we have between anim interpolation + progress = modf(frame,&frameAt); + } else { + m_curFrame++; + if (m_curFrame >= frameCount){ + m_curFrame = 0; + m_spriteEngine->advance(); + } + frameAt = m_curFrame; + progress = 0; + } + if (m_spriteEngine->sprite()->reverse()) + frameAt = (m_spriteEngine->spriteFrames() - 1) - frameAt; + qreal y = m_spriteEngine->spriteY() / m_sheetSize.height(); + qreal w = m_spriteEngine->spriteWidth() / m_sheetSize.width(); + qreal h = m_spriteEngine->spriteHeight() / m_sheetSize.height(); + qreal x1 = m_spriteEngine->spriteX() / m_sheetSize.width(); + x1 += frameAt * w; + qreal x2 = x1; + if (frameAt < (frameCount-1)) + x2 += w; + + m_material->animX1 = x1; + m_material->animY1 = y; + m_material->animX2 = x2; + m_material->animY2 = y; + m_material->animW = w; + m_material->animH = h; + m_material->animT = m_interpolate ? progress : 0.0; + } + + QT_END_NAMESPACE diff --cc src/quick/items/qquickspritesequence_p.h index 0000000,8a95594..a2f9e41 mode 000000,100644..100644 --- a/src/quick/items/qquickspritesequence_p.h +++ b/src/quick/items/qquickspritesequence_p.h @@@ -1,0 -1,148 +1,148 @@@ + /**************************************************************************** + ** + ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/ + ** -** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + #ifndef QQUICKSPRITESEQUENCE_P_H + #define QQUICKSPRITESEQUENCE_P_H + + #include + #include + + QT_BEGIN_HEADER + + QT_BEGIN_NAMESPACE + + class QSGContext; + class QQuickSprite; + class QQuickSpriteEngine; + class QSGGeometryNode; + class QQuickSpriteSequenceMaterial; + class Q_AUTOTEST_EXPORT QQuickSpriteSequence : public QQuickItem + { + Q_OBJECT + Q_PROPERTY(bool running READ running WRITE setRunning NOTIFY runningChanged) + Q_PROPERTY(bool interpolate READ interpolate WRITE setInterpolate NOTIFY interpolateChanged) + Q_PROPERTY(QString goalSprite READ goalSprite WRITE setGoalSprite NOTIFY goalSpriteChanged) + Q_PROPERTY(QString currentSprite READ currentSprite NOTIFY currentSpriteChanged) + //###try to share similar spriteEngines for less overhead? - Q_PROPERTY(QDeclarativeListProperty sprites READ sprites) ++ Q_PROPERTY(QQmlListProperty sprites READ sprites) + Q_CLASSINFO("DefaultProperty", "sprites") + + public: + explicit QQuickSpriteSequence(QQuickItem *parent = 0); + - QDeclarativeListProperty sprites(); ++ QQmlListProperty sprites(); + + bool running() const + { + return m_running; + } + + bool interpolate() const + { + return m_interpolate; + } + + QString goalSprite() const + { + return m_goalState; + } + + QString currentSprite() const + { + return m_curState; + } + + signals: + + void runningChanged(bool arg); + void interpolateChanged(bool arg); + void goalSpriteChanged(QString arg); + void currentSpriteChanged(QString arg); + + public slots: + + void jumpTo(const QString &sprite); + void setGoalSprite(const QString &sprite); + + void setRunning(bool arg) + { + if (m_running != arg) { + m_running = arg; + emit runningChanged(arg); + } + } + + void setInterpolate(bool arg) + { + if (m_interpolate != arg) { + m_interpolate = arg; + emit interpolateChanged(arg); + } + } + + private slots: + void createEngine(); + protected: + void reset(); + QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *); + private: + void prepareNextFrame(); + QSGGeometryNode* buildNode(); + QSGGeometryNode *m_node; + QQuickSpriteSequenceMaterial *m_material; + QList m_sprites; + QQuickSpriteEngine* m_spriteEngine; + QTime m_timestamp; + int m_curFrame; + bool m_pleaseReset; + bool m_running; + bool m_interpolate; + QString m_goalState; + QString m_curState; + int m_curStateIdx; + QSizeF m_sheetSize; + }; + + QT_END_NAMESPACE + + QT_END_HEADER + + #endif // QQUICKSPRITESEQUENCE_P_H diff --cc src/quick/items/qquicktext.cpp index 7aa4276,6d1cc0d..36b902f --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@@ -299,12 -309,24 +310,24 @@@ void QQuickTextPrivate::updateLayout( if (!richText) { if (textHasChanged) { if (styledText && !text.isEmpty()) { - QQuickStyledText::parse(text, layout, imgTags, q->baseUrl(), qmlContext(q), !maximumLineCountValid); + layout.setFont(font); + // needs temporary bool because formatModifiesFontSize is in a bit-field + bool fontSizeModified = false; - QDeclarativeStyledText::parse(text, layout, imgTags, q->baseUrl(), qmlContext(q), !maximumLineCountValid, &fontSizeModified); ++ QQuickStyledText::parse(text, layout, imgTags, q->baseUrl(), qmlContext(q), !maximumLineCountValid, &fontSizeModified); + formatModifiesFontSize = fontSizeModified; } else { layout.clearAdditionalFormats(); - multilengthEos = text.indexOf(QLatin1Char('\x9c')); - QString tmp = multilengthEos != -1 ? text.mid(0, multilengthEos) : text; - tmp.replace(QLatin1Char('\n'), QChar::LineSeparator); + QString tmp = text; + multilengthEos = tmp.indexOf(QLatin1Char('\x9c')); + if (multilengthEos != -1) { + tmp = tmp.mid(0, multilengthEos); + tmp.replace(QLatin1Char('\n'), QChar::LineSeparator); + } else if (tmp.contains(QLatin1Char('\n'))) { + // Replace always does a detach. Checking for the new line character first + // means iterating over those items again if found but prevents a realloc + // otherwise. + tmp.replace(QLatin1Char('\n'), QChar::LineSeparator); + } layout.setText(tmp); } textHasChanged = false; @@@ -340,9 -362,9 +363,9 @@@ void QQuickText::imageDownloadFinished( // if one of the sizes was not specified at parsing time // we use the implicit size from pixmapcache and re-layout. - if (d->nbActiveDownloads == 0) { + if (d->extra.isAllocated() && d->extra->nbActiveDownloads == 0) { bool needToUpdateLayout = false; - foreach (QDeclarativeStyledTextImgTag *img, d->visibleImgTags) { + foreach (QQuickStyledTextImgTag *img, d->visibleImgTags) { if (!img->size.isValid()) { img->size = img->pix->implicitSize(); needToUpdateLayout = true; @@@ -954,10 -1034,12 +1035,12 @@@ void QQuickTextPrivate::setLineGeometry if (!image->pix) { QUrl url = q->baseUrl().resolved(image->url); - image->pix = new QDeclarativePixmap(qmlEngine(q), url, image->size); + image->pix = new QQuickPixmap(qmlEngine(q), url, image->size); if (image->pix->isLoading()) { image->pix->connectFinished(q, SLOT(imageDownloadFinished())); - nbActiveDownloads++; + if (!extra.isAllocated() || !extra->nbActiveDownloads) + extra.value().nbActiveDownloads = 0; + extra->nbActiveDownloads++; } else if (image->pix->isReady()) { if (!image->size.isValid()) { image->size = image->pix->implicitSize(); diff --cc src/quick/items/qquicktext_p_p.h index 0f8c93a,3be6254..0425c37 --- a/src/quick/items/qquicktext_p_p.h +++ b/src/quick/items/qquicktext_p_p.h @@@ -56,10 -56,11 +56,11 @@@ #include "qquicktext_p.h" #include "qquickimplicitsizeitem_p_p.h" -#include +#include #include #include -#include +#include + #include QT_BEGIN_NAMESPACE @@@ -160,12 -168,16 +168,16 @@@ public bool isLinkActivatedConnected(); QString anchorAt(const QPointF &pos); - static inline QQuickTextPrivate *get(QQuickText *t) { - return t->d_func(); - } + inline qreal lineHeight() const { return extra.isAllocated() ? extra->lineHeight : 1.0; } + inline int maximumLineCount() const { return extra.isAllocated() ? extra->maximumLineCount : INT_MAX; } + inline QQuickText::LineHeightMode lineHeightMode() const { return extra.isAllocated() ? extra->lineHeightMode : QQuickText::ProportionalHeight; } + inline QQuickText::FontSizeMode fontSizeMode() const { return extra.isAllocated() ? extra->fontSizeMode : QQuickText::FixedSize; } + inline int minimumPixelSize() const { return extra.isAllocated() ? extra->minimumPixelSize : 12; } + inline int minimumPointSize() const { return extra.isAllocated() ? extra->minimumPointSize : 12; } + static inline QQuickTextPrivate *get(QQuickText *t) { return t->d_func(); } }; -class QDeclarativePixmap; +class QQuickPixmap; class QQuickTextDocumentWithImageResources : public QTextDocument, public QTextObjectInterface { Q_OBJECT diff --cc src/quick/items/qquicktextedit_p.h index 4dcb7f4,b3fd32a..b28ec9d --- a/src/quick/items/qquicktextedit_p.h +++ b/src/quick/items/qquicktextedit_p.h @@@ -79,8 -79,8 +79,8 @@@ class Q_AUTOTEST_EXPORT QQuickTextEdit Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly NOTIFY readOnlyChanged) Q_PROPERTY(bool cursorVisible READ isCursorVisible WRITE setCursorVisible NOTIFY cursorVisibleChanged) Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged) - Q_PROPERTY(QRect cursorRectangle READ cursorRectangle NOTIFY cursorRectangleChanged) + Q_PROPERTY(QRectF cursorRectangle READ cursorRectangle NOTIFY cursorRectangleChanged) - Q_PROPERTY(QDeclarativeComponent* cursorDelegate READ cursorDelegate WRITE setCursorDelegate NOTIFY cursorDelegateChanged) + Q_PROPERTY(QQmlComponent* cursorDelegate READ cursorDelegate WRITE setCursorDelegate NOTIFY cursorDelegateChanged) Q_PROPERTY(int selectionStart READ selectionStart NOTIFY selectionStartChanged) Q_PROPERTY(int selectionEnd READ selectionEnd NOTIFY selectionEndChanged) Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectionChanged) diff --cc src/quick/items/qquicktextedit_p_p.h index 3004d5b,8ec589d..055b5c7 --- a/src/quick/items/qquicktextedit_p_p.h +++ b/src/quick/items/qquicktextedit_p_p.h @@@ -92,17 -94,42 +94,42 @@@ public void mirrorChange(); qreal getImplicitWidth() const; + QColor color; + QColor selectionColor; + QColor selectedTextColor; + + QSizeF contentSize; + + qreal textMargin; + qreal yoff; + QString text; QUrl baseUrl; - QFont font; QFont sourceFont; - QColor color; - QColor selectionColor; - QColor selectedTextColor; - QString style; - QColor styleColor; + QFont font; + - QDeclarativeComponent* cursorComponent; ++ QQmlComponent* cursorComponent; + QQuickItem* cursor; + QQuickTextDocumentWithImageResources *document; + QQuickTextControl *control; + + int lastSelectionStart; + int lastSelectionEnd; + int lineCount; + + enum UpdateType { + UpdateNone, + UpdateOnlyPreprocess, + UpdatePaintNode + }; + QQuickTextEdit::HAlignment hAlign; QQuickTextEdit::VAlignment vAlign; + QQuickTextEdit::TextFormat format; + QQuickTextEdit::WrapMode wrapMode; + QQuickTextEdit::SelectionMode mouseSelectionMode; + Qt::InputMethodHints inputMethodHints; + UpdateType updateType; bool documentDirty : 1; bool dirty : 1; diff --cc src/quick/items/qquicktextinput_p.h index 8961dbc,ebd3d58..011af65 --- a/src/quick/items/qquicktextinput_p.h +++ b/src/quick/items/qquicktextinput_p.h @@@ -76,8 -76,8 +76,8 @@@ class Q_AUTOTEST_EXPORT QQuickTextInpu Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly NOTIFY readOnlyChanged) Q_PROPERTY(bool cursorVisible READ isCursorVisible WRITE setCursorVisible NOTIFY cursorVisibleChanged) Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged) - Q_PROPERTY(QRect cursorRectangle READ cursorRectangle NOTIFY cursorRectangleChanged) + Q_PROPERTY(QRectF cursorRectangle READ cursorRectangle NOTIFY cursorRectangleChanged) - Q_PROPERTY(QDeclarativeComponent *cursorDelegate READ cursorDelegate WRITE setCursorDelegate NOTIFY cursorDelegateChanged) + Q_PROPERTY(QQmlComponent *cursorDelegate READ cursorDelegate WRITE setCursorDelegate NOTIFY cursorDelegateChanged) Q_PROPERTY(int selectionStart READ selectionStart NOTIFY selectionStartChanged) Q_PROPERTY(int selectionEnd READ selectionEnd NOTIFY selectionEndChanged) Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectedTextChanged) diff --cc src/quick/items/qquicktextinput_p_p.h index 2575694,1921451..9a59b44 --- a/src/quick/items/qquicktextinput_p_p.h +++ b/src/quick/items/qquicktextinput_p_p.h @@@ -174,11 -174,14 +174,14 @@@ public QPointF pressPos; QPointF tripleClickStartPoint; - QDeclarativeGuard cursorComponent; + QQmlGuard cursorComponent; #ifndef QT_NO_VALIDATOR - QDeclarativeGuard m_validator; + QQmlGuard m_validator; #endif + qreal hscroll; + qreal vscroll; + QTextLayout m_textLayout; QString m_text; QString m_inputMask; diff --cc src/quick/items/qquickvisualdatamodel.cpp index 07ad366,3aa6077..70f8897 --- a/src/quick/items/qquickvisualdatamodel.cpp +++ b/src/quick/items/qquickvisualdatamodel.cpp @@@ -450,8 -450,43 +450,43 @@@ QQuickVisualDataModel::ReleaseFlags QQu return stat; } + // Cancel a requested async item + void QQuickVisualDataModel::cancel(int index) + { + Q_D(QQuickVisualDataModel); + if (!d->m_delegate || index < 0 || index >= d->m_compositor.count(d->m_compositorGroup)) { + qWarning() << "VisualDataModel::cancel: index out range" << index << d->m_compositor.count(d->m_compositorGroup); + return; + } + + Compositor::iterator it = d->m_compositor.find(d->m_compositorGroup, index); + QQuickVisualDataModelItem *cacheItem = it->inCache() ? d->m_cache.at(it.cacheIndex) : 0; + if (cacheItem) { + if (cacheItem->incubationTask) { + delete cacheItem->incubationTask->incubatingContext; + cacheItem->incubationTask->incubatingContext = 0; + d->releaseIncubator(cacheItem->incubationTask); + cacheItem->incubationTask = 0; + } + if (cacheItem->object && !cacheItem->isObjectReferenced()) { + d->destroy(cacheItem->object); - if (QDeclarativePackage *package = qobject_cast(cacheItem->object)) ++ if (QQuickPackage *package = qobject_cast(cacheItem->object)) + d->emitDestroyingPackage(package); + else if (QQuickItem *item = qobject_cast(cacheItem->object)) + d->emitDestroyingItem(item); + cacheItem->object = 0; + } + if (!cacheItem->isReferenced()) { + d->m_compositor.clearFlags(Compositor::Cache, it.cacheIndex, 1, Compositor::CacheFlag); + d->m_cache.removeAt(it.cacheIndex); + delete cacheItem; + Q_ASSERT(d->m_cache.count() == d->m_compositor.count(Compositor::Cache)); + } + } + } + void QQuickVisualDataModelPrivate::group_append( - QDeclarativeListProperty *property, QQuickVisualDataGroup *group) + QQmlListProperty *property, QQuickVisualDataGroup *group) { QQuickVisualDataModelPrivate *d = static_cast(property->data); if (d->m_complete) diff --cc src/quick/items/qquickwindowmanager.cpp index 55f11bf,79fd266..5de8ad1 --- a/src/quick/items/qquickwindowmanager.cpp +++ b/src/quick/items/qquickwindowmanager.cpp @@@ -48,10 -48,10 +48,10 @@@ #include #include - #include #include + #include -#include +#include #include #include diff --cc src/quick/items/qquickwindowmodule.cpp index 6faeb96,6faeb96..4c96207 --- a/src/quick/items/qquickwindowmodule.cpp +++ b/src/quick/items/qquickwindowmodule.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/items/qquickwindowmodule_p.h index e0da37d,b02d29e..72fd2b3 --- a/src/quick/items/qquickwindowmodule_p.h +++ b/src/quick/items/qquickwindowmodule_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickage.cpp index 307fb58,307fb58..9f24cba --- a/src/quick/particles/qquickage.cpp +++ b/src/quick/particles/qquickage.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickage_p.h index 60fc0bd,60fc0bd..2ec8faa --- a/src/quick/particles/qquickage_p.h +++ b/src/quick/particles/qquickage_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickangledirection.cpp index 48fc5a8,726b6fa..a3bd45e --- a/src/quick/particles/qquickangledirection.cpp +++ b/src/quick/particles/qquickangledirection.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickangledirection_p.h index 4f86fec,4f86fec..84633cd --- a/src/quick/particles/qquickangledirection_p.h +++ b/src/quick/particles/qquickangledirection_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickcumulativedirection.cpp index 4f4a2cc,0a2ac92..d7c4094 --- a/src/quick/particles/qquickcumulativedirection.cpp +++ b/src/quick/particles/qquickcumulativedirection.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickcumulativedirection_p.h index 3866357,2fbb411..e1675a1 --- a/src/quick/particles/qquickcumulativedirection_p.h +++ b/src/quick/particles/qquickcumulativedirection_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickcustomaffector.cpp index 7c991c7,d890400..acec981 --- a/src/quick/particles/qquickcustomaffector.cpp +++ b/src/quick/particles/qquickcustomaffector.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickcustomaffector_p.h index e831dbc,c38f53c..1266830 --- a/src/quick/particles/qquickcustomaffector_p.h +++ b/src/quick/particles/qquickcustomaffector_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickdirection.cpp index da022fe,da022fe..4127d06 --- a/src/quick/particles/qquickdirection.cpp +++ b/src/quick/particles/qquickdirection.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickdirection_p.h index 22e2278,22e2278..651865a --- a/src/quick/particles/qquickdirection_p.h +++ b/src/quick/particles/qquickdirection_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickellipseextruder.cpp index 3b80810,63ce578..3eb547f --- a/src/quick/particles/qquickellipseextruder.cpp +++ b/src/quick/particles/qquickellipseextruder.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickellipseextruder_p.h index 00b151e,00b151e..c2d0c63 --- a/src/quick/particles/qquickellipseextruder_p.h +++ b/src/quick/particles/qquickellipseextruder_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickfriction.cpp index 57de3d9,57de3d9..d37d109 --- a/src/quick/particles/qquickfriction.cpp +++ b/src/quick/particles/qquickfriction.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickfriction_p.h index b79e57a,b79e57a..3b06710 --- a/src/quick/particles/qquickfriction_p.h +++ b/src/quick/particles/qquickfriction_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickgravity.cpp index 2ab3a29,2ab3a29..cf4f35e --- a/src/quick/particles/qquickgravity.cpp +++ b/src/quick/particles/qquickgravity.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickgravity_p.h index 807b315,807b315..a738fd3 --- a/src/quick/particles/qquickgravity_p.h +++ b/src/quick/particles/qquickgravity_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickgroupgoal.cpp index 926768d,926768d..0d7f15a --- a/src/quick/particles/qquickgroupgoal.cpp +++ b/src/quick/particles/qquickgroupgoal.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickgroupgoal_p.h index 483d45f,483d45f..f553bad --- a/src/quick/particles/qquickgroupgoal_p.h +++ b/src/quick/particles/qquickgroupgoal_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickimageparticle.cpp index bf576b0,562a6c5..7f87dab --- a/src/quick/particles/qquickimageparticle.cpp +++ b/src/quick/particles/qquickimageparticle.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickimageparticle_p.h index 401f460,a0f1595..dca524b --- a/src/quick/particles/qquickimageparticle_p.h +++ b/src/quick/particles/qquickimageparticle_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickitemparticle.cpp index 571ca7f,db9e3d1..91ef06f --- a/src/quick/particles/qquickitemparticle.cpp +++ b/src/quick/particles/qquickitemparticle.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickitemparticle_p.h index d026598,df104a5..c7b8a26 --- a/src/quick/particles/qquickitemparticle_p.h +++ b/src/quick/particles/qquickitemparticle_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquicklineextruder.cpp index c98ce8d,b034c52..f555de3 --- a/src/quick/particles/qquicklineextruder.cpp +++ b/src/quick/particles/qquicklineextruder.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquicklineextruder_p.h index 1f65f8d,1f65f8d..6f2b249 --- a/src/quick/particles/qquicklineextruder_p.h +++ b/src/quick/particles/qquicklineextruder_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickmaskextruder.cpp index 5c27cc7,3ed2eb9..50b7174 --- a/src/quick/particles/qquickmaskextruder.cpp +++ b/src/quick/particles/qquickmaskextruder.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickmaskextruder_p.h index 94b3072,0c9f10b..8b6c3f0 --- a/src/quick/particles/qquickmaskextruder_p.h +++ b/src/quick/particles/qquickmaskextruder_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickparticleaffector.cpp index 6a5a4f3,6a5a4f3..0005af8 --- a/src/quick/particles/qquickparticleaffector.cpp +++ b/src/quick/particles/qquickparticleaffector.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickparticleaffector_p.h index b5126fb,b5126fb..4147488 --- a/src/quick/particles/qquickparticleaffector_p.h +++ b/src/quick/particles/qquickparticleaffector_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickparticleemitter.cpp index 1625f14,88c062b..0f7f381 --- a/src/quick/particles/qquickparticleemitter.cpp +++ b/src/quick/particles/qquickparticleemitter.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickparticleemitter_p.h index bb010a1,684a06b..70adcff --- a/src/quick/particles/qquickparticleemitter_p.h +++ b/src/quick/particles/qquickparticleemitter_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickparticleextruder.cpp index f5605ef,fc985b0..279f7c0 --- a/src/quick/particles/qquickparticleextruder.cpp +++ b/src/quick/particles/qquickparticleextruder.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickparticleextruder_p.h index da59bca,da59bca..e24950e --- a/src/quick/particles/qquickparticleextruder_p.h +++ b/src/quick/particles/qquickparticleextruder_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickparticlegroup.cpp index c4b230f,ae0876f..9a16507 --- a/src/quick/particles/qquickparticlegroup.cpp +++ b/src/quick/particles/qquickparticlegroup.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickparticlegroup_p.h index 774eb8d,f9703e8..8889187 --- a/src/quick/particles/qquickparticlegroup_p.h +++ b/src/quick/particles/qquickparticlegroup_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickparticlepainter.cpp index b9f745e,b9f745e..f46f2f2 --- a/src/quick/particles/qquickparticlepainter.cpp +++ b/src/quick/particles/qquickparticlepainter.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickparticlepainter_p.h index ffa80d7,ffa80d7..ebe76d9 --- a/src/quick/particles/qquickparticlepainter_p.h +++ b/src/quick/particles/qquickparticlepainter_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickparticlesmodule.cpp index f9b45f9,f9b45f9..e83cde3 --- a/src/quick/particles/qquickparticlesmodule.cpp +++ b/src/quick/particles/qquickparticlesmodule.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickparticlesmodule_p.h index 6d16f00,9ef9cd4..b7cf099 --- a/src/quick/particles/qquickparticlesmodule_p.h +++ b/src/quick/particles/qquickparticlesmodule_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickparticlesystem.cpp index 6dc6d21,2a79b8d..4fd6108 --- a/src/quick/particles/qquickparticlesystem.cpp +++ b/src/quick/particles/qquickparticlesystem.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickparticlesystem_p.h index 387219f,68b29b9..f70cc5a --- a/src/quick/particles/qquickparticlesystem_p.h +++ b/src/quick/particles/qquickparticlesystem_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickpointattractor.cpp index 3772e2d,3772e2d..7cb8c32 --- a/src/quick/particles/qquickpointattractor.cpp +++ b/src/quick/particles/qquickpointattractor.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickpointattractor_p.h index 30a666d,30a666d..85b7a9a --- a/src/quick/particles/qquickpointattractor_p.h +++ b/src/quick/particles/qquickpointattractor_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickpointdirection.cpp index 79c3365,6184170..e35eb48 --- a/src/quick/particles/qquickpointdirection.cpp +++ b/src/quick/particles/qquickpointdirection.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickpointdirection_p.h index e660146,e660146..7b18e6d --- a/src/quick/particles/qquickpointdirection_p.h +++ b/src/quick/particles/qquickpointdirection_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickrectangleextruder.cpp index 777d0f6,4127956..ad2207c --- a/src/quick/particles/qquickrectangleextruder.cpp +++ b/src/quick/particles/qquickrectangleextruder.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickrectangleextruder_p.h index 055058c,055058c..1d4f8cc --- a/src/quick/particles/qquickrectangleextruder_p.h +++ b/src/quick/particles/qquickrectangleextruder_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickspritegoal.cpp index 4f9518d,4f9518d..95d913c --- a/src/quick/particles/qquickspritegoal.cpp +++ b/src/quick/particles/qquickspritegoal.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickspritegoal_p.h index 44b022f,1986bc9..2b6b4f2 --- a/src/quick/particles/qquickspritegoal_p.h +++ b/src/quick/particles/qquickspritegoal_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquicktargetdirection.cpp index 3f24a25,3f24a25..695684d --- a/src/quick/particles/qquicktargetdirection.cpp +++ b/src/quick/particles/qquicktargetdirection.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquicktargetdirection_p.h index cc5b65e,cc5b65e..0e0e942 --- a/src/quick/particles/qquicktargetdirection_p.h +++ b/src/quick/particles/qquicktargetdirection_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquicktrailemitter.cpp index e531756,f5bc78c..32f8763 --- a/src/quick/particles/qquicktrailemitter.cpp +++ b/src/quick/particles/qquicktrailemitter.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquicktrailemitter_p.h index f68dd05,bae6464..0b63a44 --- a/src/quick/particles/qquicktrailemitter_p.h +++ b/src/quick/particles/qquicktrailemitter_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickturbulence.cpp index db77e8d,db77e8d..18ecc6a --- a/src/quick/particles/qquickturbulence.cpp +++ b/src/quick/particles/qquickturbulence.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickturbulence_p.h index f453140,cc0dfdc..cd5535c --- a/src/quick/particles/qquickturbulence_p.h +++ b/src/quick/particles/qquickturbulence_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickv8particledata.cpp index 3a387d8,0a3e9f6..8e50e41 --- a/src/quick/particles/qquickv8particledata.cpp +++ b/src/quick/particles/qquickv8particledata.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickv8particledata_p.h index 9b4a443,4afcd89..21ec645 --- a/src/quick/particles/qquickv8particledata_p.h +++ b/src/quick/particles/qquickv8particledata_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickwander.cpp index ec86323,ec86323..3e7cf33 --- a/src/quick/particles/qquickwander.cpp +++ b/src/quick/particles/qquickwander.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/particles/qquickwander_p.h index d71e55d,d71e55d..bb418f7 --- a/src/quick/particles/qquickwander_p.h +++ b/src/quick/particles/qquickwander_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the Declarative module of the Qt Toolkit. ++** This file is part of the QtQuick module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/scenegraph/coreapi/qsgrendernode.cpp index 0697fbe,0697fbe..ee9fd9f --- a/src/quick/scenegraph/coreapi/qsgrendernode.cpp +++ b/src/quick/scenegraph/coreapi/qsgrendernode.cpp @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/scenegraph/coreapi/qsgrendernode_p.h index a2f2be8,a2f2be8..45636cc --- a/src/quick/scenegraph/coreapi/qsgrendernode_p.h +++ b/src/quick/scenegraph/coreapi/qsgrendernode_p.h @@@ -3,7 -3,7 +3,7 @@@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** --** This file is part of the QtDeclarative module of the Qt Toolkit. ++** This file is part of the QtQml module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage diff --cc src/quick/util/qquickanimationcontroller_p.h index 24b0b4e,0000000..2b2b2a8 mode 100644,000000..100644 --- a/src/quick/util/qquickanimationcontroller_p.h +++ b/src/quick/util/qquickanimationcontroller_p.h @@@ -1,94 -1,0 +1,94 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKANIMATIONCONTROLLER_H +#define QQUICKANIMATIONCONTROLLER_H + +#include +#include "qquickanimation_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + - QT_MODULE(Declarative) ++QT_MODULE(Quick) + +class QQuickAnimationControllerPrivate; +class Q_AUTOTEST_EXPORT QQuickAnimationController : public QObject, public QQmlParserStatus +{ + Q_OBJECT + Q_INTERFACES(QQmlParserStatus) + + Q_DECLARE_PRIVATE(QQuickAnimationController) + Q_CLASSINFO("DefaultProperty", "animation") + + Q_PROPERTY(qreal progress READ progress WRITE setProgress NOTIFY progressChanged) + Q_PROPERTY(QQuickAbstractAnimation *animation READ animation WRITE setAnimation NOTIFY animationChanged) + +public: + QQuickAnimationController(QObject *parent=0); + ~QQuickAnimationController(); + + qreal progress() const; + void setProgress(qreal progress); + + QQuickAbstractAnimation *animation() const; + void setAnimation(QQuickAbstractAnimation *animation); + + void classBegin(); + void componentComplete() {} +Q_SIGNALS: + void progressChanged(); + void animationChanged(); +public Q_SLOTS: + void reload(); +private Q_SLOTS: + void componentFinalized(); + void updateProgress(); +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickAnimationController) + +QT_END_HEADER + +#endif // QQUICKANIMATIONCONTROLLER_H diff --cc src/quick/util/qquickpixmapcache.cpp index 85e155f,0000000..aae5306 mode 100644,000000..100644 --- a/src/quick/util/qquickpixmapcache.cpp +++ b/src/quick/util/qquickpixmapcache.cpp @@@ -1,1278 -1,0 +1,1280 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickpixmapcache_p.h" +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IMAGEREQUEST_MAX_REQUEST_COUNT 8 +#define IMAGEREQUEST_MAX_REDIRECT_RECURSION 16 +#define CACHE_EXPIRE_TIME 30 +#define CACHE_REMOVAL_FRACTION 4 + +QT_BEGIN_NAMESPACE + +// The cache limit describes the maximum "junk" in the cache. +static int cache_limit = 2048 * 1024; // 2048 KB cache limit for embedded in qpixmapcache.cpp + +QSGTexture *QQuickDefaultTextureFactory::createTexture(QQuickCanvas *) const +{ + QSGPlainTexture *t = new QSGPlainTexture(); + t->setImage(im); + return t; +} + +class QQuickPixmapReader; +class QQuickPixmapData; +class QQuickPixmapReply : public QObject +{ + Q_OBJECT +public: + enum ReadError { NoError, Loading, Decoding }; + + QQuickPixmapReply(QQuickPixmapData *); + ~QQuickPixmapReply(); + + QQuickPixmapData *data; + QQmlEngine *engineForReader; // always access reader inside readerMutex + QSize requestSize; + QUrl url; + + bool loading; + int redirectCount; + + class Event : public QEvent { + public: + Event(ReadError, const QString &, const QSize &, QQuickTextureFactory *factory, const QImage &image); + + ReadError error; + QString errorString; + QSize implicitSize; + QImage image; + QQuickTextureFactory *textureFactory; + }; + void postReply(ReadError, const QString &, const QSize &, const QImage &image); + void postReply(ReadError, const QString &, const QSize &, QQuickTextureFactory *factory, const QImage &image); + + +Q_SIGNALS: + void finished(); + void downloadProgress(qint64, qint64); + +protected: + bool event(QEvent *event); + +private: + Q_DISABLE_COPY(QQuickPixmapReply) + +public: + static int finishedIndex; + static int downloadProgressIndex; +}; + +class QQuickPixmapReaderThreadObject : public QObject { + Q_OBJECT +public: + QQuickPixmapReaderThreadObject(QQuickPixmapReader *); + void processJobs(); + virtual bool event(QEvent *e); +private slots: + void networkRequestDone(); +private: + QQuickPixmapReader *reader; +}; + +class QQuickPixmapData; +class QQuickPixmapReader : public QThread +{ + Q_OBJECT +public: + QQuickPixmapReader(QQmlEngine *eng); + ~QQuickPixmapReader(); + + QQuickPixmapReply *getImage(QQuickPixmapData *); + void cancel(QQuickPixmapReply *rep); + + static QQuickPixmapReader *instance(QQmlEngine *engine); + static QQuickPixmapReader *existingInstance(QQmlEngine *engine); + +protected: + void run(); + +private: + friend class QQuickPixmapReaderThreadObject; + void processJobs(); + void processJob(QQuickPixmapReply *, const QUrl &, const QSize &); + void networkRequestDone(QNetworkReply *); + + QList jobs; + QList cancelled; + QQmlEngine *engine; + QObject *eventLoopQuitHack; + + QMutex mutex; + QQuickPixmapReaderThreadObject *threadObject; + QWaitCondition waitCondition; + + QNetworkAccessManager *networkAccessManager(); + QNetworkAccessManager *accessManager; + + QHash replies; + + static int replyDownloadProgress; + static int replyFinished; + static int downloadProgress; + static int threadNetworkRequestDone; + static QHash readers; +public: + static QMutex readerMutex; +}; + +class QQuickPixmapData +{ +public: + QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, const QSize &s, const QString &e) + : refCount(1), inCache(false), pixmapStatus(QQuickPixmap::Error), + url(u), errorString(e), requestSize(s), textureFactory(0), reply(0), prevUnreferenced(0), + prevUnreferencedPtr(0), nextUnreferenced(0) + { + declarativePixmaps.insert(pixmap); + } + + QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, const QSize &r) + : refCount(1), inCache(false), pixmapStatus(QQuickPixmap::Loading), + url(u), requestSize(r), textureFactory(0), reply(0), prevUnreferenced(0), prevUnreferencedPtr(0), + nextUnreferenced(0) + { + declarativePixmaps.insert(pixmap); + } + + QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, const QImage &p, const QSize &s, const QSize &r) + : refCount(1), inCache(false), privatePixmap(false), pixmapStatus(QQuickPixmap::Ready), + url(u), image(p), implicitSize(s), requestSize(r), textureFactory(new QQuickDefaultTextureFactory(p)), reply(0), prevUnreferenced(0), + prevUnreferencedPtr(0), nextUnreferenced(0) + { + declarativePixmaps.insert(pixmap); + } + + QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, QQuickTextureFactory *factory, const QImage &p, const QSize &s, const QSize &r) + : refCount(1), inCache(false), privatePixmap(false), pixmapStatus(QQuickPixmap::Ready), + url(u), image(p), implicitSize(s), requestSize(r), textureFactory(factory), reply(0), prevUnreferenced(0), + prevUnreferencedPtr(0), nextUnreferenced(0) + { + declarativePixmaps.insert(pixmap); + } + + QQuickPixmapData(QQuickPixmap *pixmap, const QImage &p) + : refCount(1), inCache(false), privatePixmap(true), pixmapStatus(QQuickPixmap::Ready), + image(p), implicitSize(p.size()), requestSize(p.size()), textureFactory(new QQuickDefaultTextureFactory(p)), reply(0), prevUnreferenced(0), + prevUnreferencedPtr(0), nextUnreferenced(0) + { + declarativePixmaps.insert(pixmap); + } + + ~QQuickPixmapData() + { + while (!declarativePixmaps.isEmpty()) { + QQuickPixmap *referencer = declarativePixmaps.first(); + declarativePixmaps.remove(referencer); + referencer->d = 0; + } + delete textureFactory; + } + + int cost() const; + void addref(); + void release(); + void addToCache(); + void removeFromCache(); + + uint refCount; + + bool inCache:1; + bool privatePixmap:1; + + QQuickPixmap::Status pixmapStatus; + QUrl url; + QString errorString; + QImage image; + QSize implicitSize; + QSize requestSize; + + QQuickTextureFactory *textureFactory; + + QIntrusiveList declarativePixmaps; + QQuickPixmapReply *reply; + + QQuickPixmapData *prevUnreferenced; + QQuickPixmapData**prevUnreferencedPtr; + QQuickPixmapData *nextUnreferenced; +}; + +int QQuickPixmapReply::finishedIndex = -1; +int QQuickPixmapReply::downloadProgressIndex = -1; + +// XXX +QHash QQuickPixmapReader::readers; +QMutex QQuickPixmapReader::readerMutex; + +int QQuickPixmapReader::replyDownloadProgress = -1; +int QQuickPixmapReader::replyFinished = -1; +int QQuickPixmapReader::downloadProgress = -1; +int QQuickPixmapReader::threadNetworkRequestDone = -1; + + +void QQuickPixmapReply::postReply(ReadError error, const QString &errorString, + const QSize &implicitSize, const QImage &image) +{ + loading = false; + QCoreApplication::postEvent(this, new Event(error, errorString, implicitSize, new QQuickDefaultTextureFactory(image), image)); +} + +void QQuickPixmapReply::postReply(ReadError error, const QString &errorString, + const QSize &implicitSize, QQuickTextureFactory *factory, + const QImage &image) +{ + loading = false; + QCoreApplication::postEvent(this, new Event(error, errorString, implicitSize, factory, image)); +} + +QQuickPixmapReply::Event::Event(ReadError e, const QString &s, const QSize &iSize, QQuickTextureFactory *factory, const QImage &i) + : QEvent(QEvent::User), error(e), errorString(s), implicitSize(iSize), image(i), textureFactory(factory) +{ +} + +QNetworkAccessManager *QQuickPixmapReader::networkAccessManager() +{ + if (!accessManager) { + Q_ASSERT(threadObject); + accessManager = QQmlEnginePrivate::get(engine)->createNetworkAccessManager(threadObject); + } + return accessManager; +} + +static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *errorString, QSize *impsize, + const QSize &requestSize) +{ + QImageReader imgio(dev); + + bool force_scale = false; + if (url.path().endsWith(QLatin1String(".svg"),Qt::CaseInsensitive)) { + imgio.setFormat("svg"); // QSvgPlugin::capabilities bug QTBUG-9053 + force_scale = true; + } + + if (requestSize.width() > 0 || requestSize.height() > 0) { + QSize s = imgio.size(); + qreal ratio = 0.0; + if (requestSize.width() && (force_scale || requestSize.width() < s.width())) { + ratio = qreal(requestSize.width())/s.width(); + } + if (requestSize.height() && (force_scale || requestSize.height() < s.height())) { + qreal hr = qreal(requestSize.height())/s.height(); + if (ratio == 0.0 || hr < ratio) + ratio = hr; + } + if (ratio > 0.0) { + s.setHeight(qRound(s.height() * ratio)); + s.setWidth(qRound(s.width() * ratio)); + imgio.setScaledSize(s); + } + } + + if (impsize) + *impsize = imgio.size(); + + if (imgio.read(image)) { + if (impsize && impsize->width() < 0) + *impsize = image->size(); + return true; + } else { + if (errorString) + *errorString = QQuickPixmap::tr("Error decoding: %1: %2").arg(url.toString()) + .arg(imgio.errorString()); + return false; + } +} + +QQuickPixmapReader::QQuickPixmapReader(QQmlEngine *eng) +: QThread(eng), engine(eng), threadObject(0), accessManager(0) +{ + eventLoopQuitHack = new QObject; + eventLoopQuitHack->moveToThread(this); + connect(eventLoopQuitHack, SIGNAL(destroyed(QObject*)), SLOT(quit()), Qt::DirectConnection); + start(QThread::LowestPriority); +} + +QQuickPixmapReader::~QQuickPixmapReader() +{ + readerMutex.lock(); + readers.remove(engine); + readerMutex.unlock(); + + mutex.lock(); + // manually cancel all outstanding jobs. + foreach (QQuickPixmapReply *reply, jobs) { + delete reply; + } + jobs.clear(); + QList activeJobs = replies.values(); + foreach (QQuickPixmapReply *reply, activeJobs) { + if (reply->loading) { + cancelled.append(reply); + reply->data = 0; + } + } + if (threadObject) threadObject->processJobs(); + mutex.unlock(); + + eventLoopQuitHack->deleteLater(); + wait(); +} + +void QQuickPixmapReader::networkRequestDone(QNetworkReply *reply) +{ + QQuickPixmapReply *job = replies.take(reply); + + if (job) { + job->redirectCount++; + if (job->redirectCount < IMAGEREQUEST_MAX_REDIRECT_RECURSION) { + QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); + if (redirect.isValid()) { + QUrl url = reply->url().resolved(redirect.toUrl()); + QNetworkRequest req(url); + req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); + + reply->deleteLater(); + reply = networkAccessManager()->get(req); + + QMetaObject::connect(reply, replyDownloadProgress, job, downloadProgress); + QMetaObject::connect(reply, replyFinished, threadObject, threadNetworkRequestDone); + + replies.insert(reply, job); + return; + } + } + + QImage image; + QQuickPixmapReply::ReadError error = QQuickPixmapReply::NoError; + QString errorString; + QSize readSize; + if (reply->error()) { + error = QQuickPixmapReply::Loading; + errorString = reply->errorString(); + } else { + QByteArray all = reply->readAll(); + QBuffer buff(&all); + buff.open(QIODevice::ReadOnly); + if (!readImage(reply->url(), &buff, &image, &errorString, &readSize, job->requestSize)) + error = QQuickPixmapReply::Decoding; + } + // send completion event to the QQuickPixmapReply + mutex.lock(); + if (!cancelled.contains(job)) { + QQuickTextureFactory *factory = QSGContext::createTextureFactoryFromImage(image); + if (factory) + job->postReply(error, errorString, readSize, factory, image); + else + job->postReply(error, errorString, readSize, image); + } + mutex.unlock(); + } + reply->deleteLater(); + + // kick off event loop again incase we have dropped below max request count + threadObject->processJobs(); +} + +QQuickPixmapReaderThreadObject::QQuickPixmapReaderThreadObject(QQuickPixmapReader *i) +: reader(i) +{ +} + +void QQuickPixmapReaderThreadObject::processJobs() +{ + QCoreApplication::postEvent(this, new QEvent(QEvent::User)); +} + +bool QQuickPixmapReaderThreadObject::event(QEvent *e) +{ + if (e->type() == QEvent::User) { + reader->processJobs(); + return true; + } else { + return QObject::event(e); + } +} + +void QQuickPixmapReaderThreadObject::networkRequestDone() +{ + QNetworkReply *reply = static_cast(sender()); + reader->networkRequestDone(reply); +} + +void QQuickPixmapReader::processJobs() +{ + QMutexLocker locker(&mutex); + + while (true) { + if (cancelled.isEmpty() && (jobs.isEmpty() || replies.count() >= IMAGEREQUEST_MAX_REQUEST_COUNT)) + return; // Nothing else to do + + // Clean cancelled jobs + if (cancelled.count()) { + for (int i = 0; i < cancelled.count(); ++i) { + QQuickPixmapReply *job = cancelled.at(i); + QNetworkReply *reply = replies.key(job, 0); + if (reply && reply->isRunning()) { + // cancel any jobs already started + replies.remove(reply); + reply->close(); + } + // deleteLater, since not owned by this thread + job->deleteLater(); + } + cancelled.clear(); + } + + if (!jobs.isEmpty() && replies.count() < IMAGEREQUEST_MAX_REQUEST_COUNT) { + QQuickPixmapReply *runningJob = jobs.takeLast(); + runningJob->loading = true; + + QUrl url = runningJob->url; + QSize requestSize = runningJob->requestSize; + locker.unlock(); + processJob(runningJob, url, requestSize); + locker.relock(); + } + } +} + +void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &url, + const QSize &requestSize) +{ + // fetch + if (url.scheme() == QLatin1String("image")) { + // Use QmlImageProvider + QSize readSize; + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine); + QQmlImageProvider::ImageType imageType = ep->getImageProviderType(url); + if (imageType == QQmlImageProvider::Invalid) { + QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::Loading; + QString errorStr = QQuickPixmap::tr("Invalid image provider: %1").arg(url.toString()); + QImage image; + mutex.lock(); + if (!cancelled.contains(runningJob)) + runningJob->postReply(errorCode, errorStr, readSize, image); + mutex.unlock(); + } else if (imageType == QQmlImageProvider::Image) { + QImage image = ep->getImageFromProvider(url, &readSize, requestSize); + QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError; + QString errorStr; + if (image.isNull()) { + errorCode = QQuickPixmapReply::Loading; + errorStr = QQuickPixmap::tr("Failed to get image from provider: %1").arg(url.toString()); + } + mutex.lock(); + if (!cancelled.contains(runningJob)) { + QQuickTextureFactory *factory = QSGContext::createTextureFactoryFromImage(image); + if (factory) + runningJob->postReply(errorCode, errorStr, readSize, factory, image); + else + runningJob->postReply(errorCode, errorStr, readSize, image); + } + + mutex.unlock(); + } else { + QQuickTextureFactory *t = ep->getTextureFromProvider(url, &readSize, requestSize); + QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError; + QString errorStr; + if (!t) { + errorCode = QQuickPixmapReply::Loading; + errorStr = QQuickPixmap::tr("Failed to get texture from provider: %1").arg(url.toString()); + } + mutex.lock(); + if (!cancelled.contains(runningJob)) + runningJob->postReply(errorCode, errorStr, readSize, t, QImage()); + mutex.unlock(); + + } + + } else { + QString lf = QQmlEnginePrivate::urlToLocalFileOrQrc(url); + if (!lf.isEmpty()) { + // Image is local - load/decode immediately + QImage image; + QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError; + QString errorStr; + QFile f(lf); + QSize readSize; + if (f.open(QIODevice::ReadOnly)) { + if (!readImage(url, &f, &image, &errorStr, &readSize, requestSize)) + errorCode = QQuickPixmapReply::Loading; + } else { + errorStr = QQuickPixmap::tr("Cannot open: %1").arg(url.toString()); + errorCode = QQuickPixmapReply::Loading; + } + mutex.lock(); + if (!cancelled.contains(runningJob)) { + QQuickTextureFactory *factory = QSGContext::createTextureFactoryFromImage(image); + if (factory) + runningJob->postReply(errorCode, errorStr, readSize, factory, image); + else + runningJob->postReply(errorCode, errorStr, readSize, image); + } + mutex.unlock(); + } else { + // Network resource + QNetworkRequest req(url); + req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); + QNetworkReply *reply = networkAccessManager()->get(req); + + QMetaObject::connect(reply, replyDownloadProgress, runningJob, downloadProgress); + QMetaObject::connect(reply, replyFinished, threadObject, threadNetworkRequestDone); + + replies.insert(reply, runningJob); + } + } +} + +QQuickPixmapReader *QQuickPixmapReader::instance(QQmlEngine *engine) +{ + // XXX NOTE: must be called within readerMutex locking. + QQuickPixmapReader *reader = readers.value(engine); + if (!reader) { + reader = new QQuickPixmapReader(engine); + readers.insert(engine, reader); + } + + return reader; +} + +QQuickPixmapReader *QQuickPixmapReader::existingInstance(QQmlEngine *engine) +{ + // XXX NOTE: must be called within readerMutex locking. + return readers.value(engine, 0); +} + +QQuickPixmapReply *QQuickPixmapReader::getImage(QQuickPixmapData *data) +{ + mutex.lock(); + QQuickPixmapReply *reply = new QQuickPixmapReply(data); + reply->engineForReader = engine; + jobs.append(reply); + // XXX + if (threadObject) threadObject->processJobs(); + mutex.unlock(); + return reply; +} + +void QQuickPixmapReader::cancel(QQuickPixmapReply *reply) +{ + mutex.lock(); + if (reply->loading) { + cancelled.append(reply); + reply->data = 0; + // XXX + if (threadObject) threadObject->processJobs(); + } else { + jobs.removeAll(reply); + delete reply; + } + mutex.unlock(); +} + +void QQuickPixmapReader::run() +{ + if (replyDownloadProgress == -1) { + const QMetaObject *nr = &QNetworkReply::staticMetaObject; + const QMetaObject *pr = &QQuickPixmapReply::staticMetaObject; + const QMetaObject *ir = &QQuickPixmapReaderThreadObject::staticMetaObject; + replyDownloadProgress = nr->indexOfSignal("downloadProgress(qint64,qint64)"); + replyFinished = nr->indexOfSignal("finished()"); + downloadProgress = pr->indexOfSignal("downloadProgress(qint64,qint64)"); + threadNetworkRequestDone = ir->indexOfSlot("networkRequestDone()"); + } + + mutex.lock(); + threadObject = new QQuickPixmapReaderThreadObject(this); + mutex.unlock(); + + processJobs(); + exec(); + + delete threadObject; + threadObject = 0; +} + +class QQuickPixmapKey +{ +public: + const QUrl *url; + const QSize *size; +}; + +inline bool operator==(const QQuickPixmapKey &lhs, const QQuickPixmapKey &rhs) +{ + return *lhs.size == *rhs.size && *lhs.url == *rhs.url; +} + +inline uint qHash(const QQuickPixmapKey &key) +{ + return qHash(*key.url) ^ key.size->width() ^ key.size->height(); +} + +class QSGContext; + +class QQuickPixmapStore : public QObject +{ + Q_OBJECT +public: + QQuickPixmapStore(); + ~QQuickPixmapStore(); + + void unreferencePixmap(QQuickPixmapData *); + void referencePixmap(QQuickPixmapData *); + + void purgeCache(); + +protected: + virtual void timerEvent(QTimerEvent *); + +public: + QHash m_cache; + +private: + void shrinkCache(int remove); + + QQuickPixmapData *m_unreferencedPixmaps; + QQuickPixmapData *m_lastUnreferencedPixmap; + + int m_unreferencedCost; + int m_timerId; + bool m_destroying; +}; +Q_GLOBAL_STATIC(QQuickPixmapStore, pixmapStore); + + +QQuickPixmapStore::QQuickPixmapStore() + : m_unreferencedPixmaps(0), m_lastUnreferencedPixmap(0), m_unreferencedCost(0), m_timerId(-1), m_destroying(false) +{ +} + +QQuickPixmapStore::~QQuickPixmapStore() +{ + m_destroying = true; + + int leakedPixmaps = 0; + QList cachedData = m_cache.values(); + + // Prevent unreferencePixmap() from assuming it needs to kick + // off the cache expiry timer, as we're shrinking the cache + // manually below after releasing all the pixmaps. + m_timerId = -2; + + // unreference all (leaked) pixmaps + foreach (QQuickPixmapData* pixmap, cachedData) { + int currRefCount = pixmap->refCount; + if (currRefCount) { + leakedPixmaps++; + while (currRefCount > 0) { + pixmap->release(); + currRefCount--; + } + } + } + + // free all unreferenced pixmaps + while (m_lastUnreferencedPixmap) { + shrinkCache(20); + } + + if (leakedPixmaps) + qDebug("Number of leaked pixmaps: %i", leakedPixmaps); +} + +void QQuickPixmapStore::unreferencePixmap(QQuickPixmapData *data) +{ + Q_ASSERT(data->prevUnreferenced == 0); + Q_ASSERT(data->prevUnreferencedPtr == 0); + Q_ASSERT(data->nextUnreferenced == 0); + + data->nextUnreferenced = m_unreferencedPixmaps; + data->prevUnreferencedPtr = &m_unreferencedPixmaps; ++ if (!m_destroying) // the texture factories may have been cleaned up already. ++ m_unreferencedCost += data->cost(); + + m_unreferencedPixmaps = data; + if (m_unreferencedPixmaps->nextUnreferenced) { + m_unreferencedPixmaps->nextUnreferenced->prevUnreferenced = m_unreferencedPixmaps; + m_unreferencedPixmaps->nextUnreferenced->prevUnreferencedPtr = &m_unreferencedPixmaps->nextUnreferenced; + } + + if (!m_lastUnreferencedPixmap) + m_lastUnreferencedPixmap = data; + - m_unreferencedCost += data->cost(); - + shrinkCache(-1); // Shrink the cache incase it has become larger than cache_limit + + if (m_timerId == -1 && m_unreferencedPixmaps && !m_destroying) + m_timerId = startTimer(CACHE_EXPIRE_TIME * 1000); +} + +void QQuickPixmapStore::referencePixmap(QQuickPixmapData *data) +{ + Q_ASSERT(data->prevUnreferencedPtr); + + *data->prevUnreferencedPtr = data->nextUnreferenced; + if (data->nextUnreferenced) { + data->nextUnreferenced->prevUnreferencedPtr = data->prevUnreferencedPtr; + data->nextUnreferenced->prevUnreferenced = data->prevUnreferenced; + } + if (m_lastUnreferencedPixmap == data) + m_lastUnreferencedPixmap = data->prevUnreferenced; + + data->nextUnreferenced = 0; + data->prevUnreferencedPtr = 0; + data->prevUnreferenced = 0; + + m_unreferencedCost -= data->cost(); +} + +void QQuickPixmapStore::shrinkCache(int remove) +{ + while ((remove > 0 || m_unreferencedCost > cache_limit) && m_lastUnreferencedPixmap) { + QQuickPixmapData *data = m_lastUnreferencedPixmap; + Q_ASSERT(data->nextUnreferenced == 0); + + *data->prevUnreferencedPtr = 0; + m_lastUnreferencedPixmap = data->prevUnreferenced; + data->prevUnreferencedPtr = 0; + data->prevUnreferenced = 0; + - remove -= data->cost(); - m_unreferencedCost -= data->cost(); ++ if (!m_destroying) { ++ remove -= data->cost(); ++ m_unreferencedCost -= data->cost(); ++ } + data->removeFromCache(); + delete data; + } +} + +void QQuickPixmapStore::timerEvent(QTimerEvent *) +{ + int removalCost = m_unreferencedCost / CACHE_REMOVAL_FRACTION; + + shrinkCache(removalCost); + + if (m_unreferencedPixmaps == 0) { + killTimer(m_timerId); + m_timerId = -1; + } +} + +void QQuickPixmapStore::purgeCache() +{ + shrinkCache(m_unreferencedCost); +} + +void QQuickPixmap::purgeCache() +{ + pixmapStore()->purgeCache(); +} + +QQuickPixmapReply::QQuickPixmapReply(QQuickPixmapData *d) +: data(d), engineForReader(0), requestSize(d->requestSize), url(d->url), loading(false), redirectCount(0) +{ + if (finishedIndex == -1) { + finishedIndex = QQuickPixmapReply::staticMetaObject.indexOfSignal("finished()"); + downloadProgressIndex = QQuickPixmapReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)"); + } +} + +QQuickPixmapReply::~QQuickPixmapReply() +{ +} + +bool QQuickPixmapReply::event(QEvent *event) +{ + if (event->type() == QEvent::User) { + + if (data) { + Event *de = static_cast(event); + data->pixmapStatus = (de->error == NoError) ? QQuickPixmap::Ready : QQuickPixmap::Error; + + if (data->pixmapStatus == QQuickPixmap::Ready) { + if (de->textureFactory) { + data->textureFactory = de->textureFactory; + } + data->image = de->image; + data->implicitSize = de->implicitSize; + } else { + data->errorString = de->errorString; + data->removeFromCache(); // We don't continue to cache error'd pixmaps + } + + data->reply = 0; + emit finished(); + } + + delete this; + return true; + } else { + return QObject::event(event); + } +} + +int QQuickPixmapData::cost() const +{ + if (textureFactory) + return textureFactory->textureByteCount(); + return image.byteCount(); +} + +void QQuickPixmapData::addref() +{ + ++refCount; + if (prevUnreferencedPtr) + pixmapStore()->referencePixmap(this); +} + +void QQuickPixmapData::release() +{ + Q_ASSERT(refCount > 0); + --refCount; + if (refCount == 0) { + if (reply) { + QQuickPixmapReply *cancelReply = reply; + reply->data = 0; + reply = 0; + QQuickPixmapReader::readerMutex.lock(); + QQuickPixmapReader *reader = QQuickPixmapReader::existingInstance(cancelReply->engineForReader); + if (reader) + reader->cancel(cancelReply); + QQuickPixmapReader::readerMutex.unlock(); + } + + if (pixmapStatus == QQuickPixmap::Ready) { + pixmapStore()->unreferencePixmap(this); + } else { + removeFromCache(); + delete this; + } + } +} + +void QQuickPixmapData::addToCache() +{ + if (!inCache) { + QQuickPixmapKey key = { &url, &requestSize }; + pixmapStore()->m_cache.insert(key, this); + inCache = true; + } +} + +void QQuickPixmapData::removeFromCache() +{ + if (inCache) { + QQuickPixmapKey key = { &url, &requestSize }; + pixmapStore()->m_cache.remove(key); + inCache = false; + } +} + +static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, QQmlEngine *engine, const QUrl &url, const QSize &requestSize, bool *ok) +{ + if (url.scheme() == QLatin1String("image")) { + QSize readSize; + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine); + QQmlImageProvider::ImageType imageType = ep->getImageProviderType(url); + + switch (imageType) { + case QQmlImageProvider::Invalid: + return new QQuickPixmapData(declarativePixmap, url, requestSize, + QQuickPixmap::tr("Invalid image provider: %1").arg(url.toString())); + case QQmlImageProvider::Texture: + { + QQuickTextureFactory *texture = ep->getTextureFromProvider(url, &readSize, requestSize); + if (texture) { + *ok = true; + return new QQuickPixmapData(declarativePixmap, url, texture, QImage(), readSize, requestSize); + } + } + + case QQmlImageProvider::Image: + { + QImage image = ep->getImageFromProvider(url, &readSize, requestSize); + if (!image.isNull()) { + *ok = true; + return new QQuickPixmapData(declarativePixmap, url, image, readSize, requestSize); + } + } + case QQmlImageProvider::Pixmap: + { + QPixmap pixmap = ep->getPixmapFromProvider(url, &readSize, requestSize); + if (!pixmap.isNull()) { + *ok = true; + return new QQuickPixmapData(declarativePixmap, url, pixmap.toImage(), readSize, requestSize); + } + } + } + + // provider has bad image type, or provider returned null image + return new QQuickPixmapData(declarativePixmap, url, requestSize, + QQuickPixmap::tr("Failed to get image from provider: %1").arg(url.toString())); + } + + QString localFile = QQmlEnginePrivate::urlToLocalFileOrQrc(url); + if (localFile.isEmpty()) + return 0; + + QFile f(localFile); + QSize readSize; + QString errorString; + + if (f.open(QIODevice::ReadOnly)) { + QImage image; + + if (readImage(url, &f, &image, &errorString, &readSize, requestSize)) { + *ok = true; + return new QQuickPixmapData(declarativePixmap, url, image, readSize, requestSize); + } + errorString = QQuickPixmap::tr("Invalid image data: %1").arg(url.toString()); + + } else { + errorString = QQuickPixmap::tr("Cannot open: %1").arg(url.toString()); + } + return new QQuickPixmapData(declarativePixmap, url, requestSize, errorString); +} + + +struct QQuickPixmapNull { + QUrl url; + QImage image; + QSize size; +}; +Q_GLOBAL_STATIC(QQuickPixmapNull, nullPixmap); + +QQuickPixmap::QQuickPixmap() +: d(0) +{ +} + +QQuickPixmap::QQuickPixmap(QQmlEngine *engine, const QUrl &url) +: d(0) +{ + load(engine, url); +} + +QQuickPixmap::QQuickPixmap(QQmlEngine *engine, const QUrl &url, const QSize &size) +: d(0) +{ + load(engine, url, size); +} + +QQuickPixmap::~QQuickPixmap() +{ + if (d) { + d->declarativePixmaps.remove(this); + d->release(); + d = 0; + } +} + +bool QQuickPixmap::isNull() const +{ + return d == 0; +} + +bool QQuickPixmap::isReady() const +{ + return status() == Ready; +} + +bool QQuickPixmap::isError() const +{ + return status() == Error; +} + +bool QQuickPixmap::isLoading() const +{ + return status() == Loading; +} + +QString QQuickPixmap::error() const +{ + if (d) + return d->errorString; + else + return QString(); +} + +QQuickPixmap::Status QQuickPixmap::status() const +{ + if (d) + return d->pixmapStatus; + else + return Null; +} + +const QUrl &QQuickPixmap::url() const +{ + if (d) + return d->url; + else + return nullPixmap()->url; +} + +const QSize &QQuickPixmap::implicitSize() const +{ + if (d) + return d->implicitSize; + else + return nullPixmap()->size; +} + +const QSize &QQuickPixmap::requestSize() const +{ + if (d) + return d->requestSize; + else + return nullPixmap()->size; +} + +QQuickTextureFactory *QQuickPixmap::textureFactory() const +{ + if (d) + return d->textureFactory; + + return 0; +} + +const QImage &QQuickPixmap::image() const +{ + if (d) + return d->image; + else + return nullPixmap()->image; +} + +void QQuickPixmap::setImage(const QImage &p) +{ + clear(); + + if (!p.isNull()) + d = new QQuickPixmapData(this, p); +} + +int QQuickPixmap::width() const +{ + if (d) + return d->textureFactory ? d->textureFactory->textureSize().width() : d->image.width(); + else + return 0; +} + +int QQuickPixmap::height() const +{ + if (d) + return d->textureFactory ? d->textureFactory->textureSize().height() : d->image.height(); + else + return 0; +} + +QRect QQuickPixmap::rect() const +{ + if (d) + return d->textureFactory ? QRect(QPoint(), d->textureFactory->textureSize()) : d->image.rect(); + else + return QRect(); +} + +void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url) +{ + load(engine, url, QSize(), QQuickPixmap::Cache); +} + +void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, QQuickPixmap::Options options) +{ + load(engine, url, QSize(), options); +} + +void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &size) +{ + load(engine, url, size, QQuickPixmap::Cache); +} + +void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &requestSize, QQuickPixmap::Options options) +{ + if (d) { + d->declarativePixmaps.remove(this); + d->release(); + d = 0; + } + + QQuickPixmapKey key = { &url, &requestSize }; + QQuickPixmapStore *store = pixmapStore(); + + QHash::Iterator iter = store->m_cache.find(key); + + if (iter == store->m_cache.end()) { + if (options & QQuickPixmap::Asynchronous) { + // pixmaps can only be loaded synchronously + if (url.scheme() == QLatin1String("image") + && QQmlEnginePrivate::get(engine)->getImageProviderType(url) == QQmlImageProvider::Pixmap) { + options &= ~QQuickPixmap::Asynchronous; + } + } + + if (!(options & QQuickPixmap::Asynchronous)) { + bool ok = false; + d = createPixmapDataSync(this, engine, url, requestSize, &ok); + if (ok) { + if (options & QQuickPixmap::Cache) + d->addToCache(); + return; + } + if (d) // loadable, but encountered error while loading + return; + } + + if (!engine) + return; + + d = new QQuickPixmapData(this, url, requestSize); + if (options & QQuickPixmap::Cache) + d->addToCache(); + + QQuickPixmapReader::readerMutex.lock(); + d->reply = QQuickPixmapReader::instance(engine)->getImage(d); + QQuickPixmapReader::readerMutex.unlock(); + } else { + d = *iter; + d->addref(); + d->declarativePixmaps.insert(this); + } +} + +void QQuickPixmap::clear() +{ + if (d) { + d->declarativePixmaps.remove(this); + d->release(); + d = 0; + } +} + +void QQuickPixmap::clear(QObject *obj) +{ + if (d) { + if (d->reply) + QObject::disconnect(d->reply, 0, obj, 0); + d->declarativePixmaps.remove(this); + d->release(); + d = 0; + } +} + +bool QQuickPixmap::connectFinished(QObject *object, const char *method) +{ + if (!d || !d->reply) { + qWarning("QQuickPixmap: connectFinished() called when not loading."); + return false; + } + + return QObject::connect(d->reply, SIGNAL(finished()), object, method); +} + +bool QQuickPixmap::connectFinished(QObject *object, int method) +{ + if (!d || !d->reply) { + qWarning("QQuickPixmap: connectFinished() called when not loading."); + return false; + } + + return QMetaObject::connect(d->reply, QQuickPixmapReply::finishedIndex, object, method); +} + +bool QQuickPixmap::connectDownloadProgress(QObject *object, const char *method) +{ + if (!d || !d->reply) { + qWarning("QQuickPixmap: connectDownloadProgress() called when not loading."); + return false; + } + + return QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), object, method); +} + +bool QQuickPixmap::connectDownloadProgress(QObject *object, int method) +{ + if (!d || !d->reply) { + qWarning("QQuickPixmap: connectDownloadProgress() called when not loading."); + return false; + } + + return QMetaObject::connect(d->reply, QQuickPixmapReply::downloadProgressIndex, object, method); +} + +QT_END_NAMESPACE + +#include diff --cc src/quick/util/qquickstyledtext.cpp index 87d4471,0000000..8462166 mode 100644,000000..100644 --- a/src/quick/util/qquickstyledtext.cpp +++ b/src/quick/util/qquickstyledtext.cpp @@@ -1,798 -1,0 +1,815 @@@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include "qquickstyledtext_p.h" +#include + +/* + QQuickStyledText supports few tags: + + - bold + - bold + - italic +
- new line +

- paragraph + - underlined text + +

to
- headers + - anchor +
    ,