├── src
├── .eslintrc
├── engine
│ ├── .eslintrc
│ ├── QMLNumber.js
│ ├── QMLString.js
│ ├── QMLVariant.js
│ ├── QMLBoolean.js
│ ├── QMLInteger.js
│ ├── QMLUrl.js
│ ├── QMLOperationState.js
│ ├── AutoLoader.js
│ ├── jsparser.js
│ ├── QMLList.js
│ ├── getset.js
│ ├── i18n.js
│ ├── keyboard.js
│ └── helpers.js
├── QmlWeb.js
├── modules
│ ├── QmlWeb.Dom
│ │ ├── DomDiv.js
│ │ ├── DomParagraph.js
│ │ └── DomStyle.js
│ ├── QtQuick
│ │ ├── AnimatedImage.js
│ │ ├── FocusScope.js
│ │ ├── XAnimator.js
│ │ ├── YAnimator.js
│ │ ├── ScaleAnimator.js
│ │ ├── OpacityAnimator.js
│ │ ├── RotationAnimator.js
│ │ ├── UniformAnimator.js
│ │ ├── ListElement.js
│ │ ├── RegExpValidator.js
│ │ ├── Translate.js
│ │ ├── PropertyChanges.js
│ │ ├── GradientStop.js
│ │ ├── ShaderEffect.js
│ │ ├── IntValidator.js
│ │ ├── Animator.js
│ │ ├── Column.js
│ │ ├── Behavior.js
│ │ ├── PauseAnimation.js
│ │ ├── Animation.js
│ │ ├── ShaderEffectSource.js
│ │ ├── Positioner.js
│ │ ├── Scale.js
│ │ ├── State.js
│ │ ├── Gradient.js
│ │ ├── Rotation.js
│ │ ├── Row.js
│ │ ├── ListView.js
│ │ ├── Canvas.js
│ │ └── DoubleValidator.js
│ ├── QtQml.Models
│ │ ├── ListElement.js
│ │ └── ListModel.js
│ ├── QtQuick.Particles
│ │ ├── Direction.js
│ │ ├── ParticlePainter.js
│ │ ├── CustomParticle.js
│ │ ├── AngleDirection.js
│ │ ├── ParticleSystem.js
│ │ └── Emitter.js
│ ├── QtQuick.Controls.2
│ │ ├── TabButton.js
│ │ ├── Label.js
│ │ ├── TabBar.js
│ │ ├── Page.js
│ │ ├── ApplicationWindow.js
│ │ ├── SwipeView.js
│ │ ├── Control.js
│ │ ├── AbstractButton.js
│ │ └── Container.js
│ ├── QtWebEngine
│ │ └── WebEngineView.js
│ ├── QtQml
│ │ ├── QValidator.js
│ │ ├── Binding.js
│ │ └── Connections.js
│ ├── QtQuick.Layouts
│ │ ├── DirectionalLayout.js
│ │ ├── Positioner.js
│ │ ├── StackLayout.js
│ │ └── Layout.js
│ ├── QtQuick.Controls
│ │ ├── TextArea.js
│ │ ├── ApplicationWindow.js
│ │ └── Button.js
│ ├── QtNfc
│ │ └── NearField.js
│ ├── QtTest
│ │ └── SignalSpy.js
│ ├── QtMultimedia
│ │ ├── VideoOutput.js
│ │ ├── Camera.js
│ │ └── MediaPlayer.js
│ ├── QtQuick.Window
│ │ └── Window.js
│ ├── QtBluetooth
│ │ └── BluetoothDiscoveryModel.js
│ ├── QtWebKit
│ │ └── WebView.js
│ ├── QtMobility
│ │ └── GeoLocation.js
│ ├── Qt.labs.settings
│ │ └── Settings.js
│ ├── QtGraphicalEffects
│ │ └── FastBlur.js
│ └── QtWebView
│ │ └── WebView.js
└── qtbase
│ ├── JSItemModel.js
│ ├── QPointF.js
│ ├── QSizeF.js
│ ├── QQuaternion.js
│ └── QRectF.js
├── tests
├── QMLEngine
│ ├── qml
│ │ ├── ImportReuse
│ │ │ ├── foo
│ │ │ │ └── bar
│ │ │ │ │ ├── qmldir
│ │ │ │ │ └── ItemS.qml
│ │ │ ├── qmldir
│ │ │ ├── ItemA.qml
│ │ │ └── main.qml
│ │ ├── importTestIncluded.js
│ │ ├── singleton
│ │ │ ├── qmldir
│ │ │ └── Style.qml
│ │ ├── importTestInclude.js
│ │ ├── ScopeComponentIdSomeComponent.qml
│ │ ├── ScopeUpflowWithFoo.qml
│ │ ├── ImportFromDir.qml
│ │ ├── ImportLocalToFile
│ │ │ ├── DirectoryFailSomeComponent.qml
│ │ │ ├── ModuleSucceedSomeComponent.qml
│ │ │ ├── ModuleFailSomeComponent.qml
│ │ │ ├── DirectoryFail.qml
│ │ │ ├── ModuleFail2.qml
│ │ │ ├── ModuleFail1.qml
│ │ │ └── ModuleSucceed.qml
│ │ ├── ItemWithValue.qml
│ │ ├── somelib
│ │ │ ├── qmldir
│ │ │ ├── SimpleButton.qml
│ │ │ └── RectangleColor.qml
│ │ ├── ImportFrom
│ │ │ ├── ImportMe.qml
│ │ │ ├── ParentDir.qml
│ │ │ ├── LocalComponentProperty.qml
│ │ │ └── SiblingDir.qml
│ │ ├── ImportNoQmldir.qml
│ │ ├── ScopeUpflowWithRealFoo.qml
│ │ ├── ItemWithPropertyNamedSignal.qml
│ │ ├── ImportQmldir.qml
│ │ ├── ParseFunctionVar.qml
│ │ ├── ImportQualifiedModule.qml
│ │ ├── ImportQualifiedNoQmldir.qml
│ │ ├── ParseError.qml
│ │ ├── PropertiesNamedSignalValues.qml
│ │ ├── importTestSimple.js
│ │ ├── JavascriptRegexp.qml
│ │ ├── PropertiesDefault.qml
│ │ ├── PropertiesNamedSignal.qml
│ │ ├── ScopeIdOverProperty.qml
│ │ ├── ParseSignal.qml
│ │ ├── ScopeIdOverPropertyImpl.qml
│ │ ├── PropertiesDefaultLabel.qml
│ │ ├── BindingsNoSrc.qml
│ │ ├── ImportQmldirSingleton.qml
│ │ ├── ImportJavascriptInclude.qml
│ │ ├── ScopeOverrideBase.qml
│ │ ├── PropertiesAlias.qml
│ │ ├── PropertiesUndefined.qml
│ │ ├── ScopeRoot.qml
│ │ ├── ScopeComponentId.qml
│ │ ├── ScopeUpflow.qml
│ │ ├── BindingsThis.qml
│ │ ├── ScopeSibling.qml
│ │ ├── ScopeLeaf.qml
│ │ ├── ScopeOverride.qml
│ │ ├── PropertiesAliasToId.qml
│ │ ├── PropertiesChangedExpressionSignal.qml
│ │ ├── BasicCreateObject.qml
│ │ ├── PropertiesAliasToIdSameName.qml
│ │ ├── BasicCreateObjectSomeComponent.qml
│ │ ├── ScopeMid.qml
│ │ ├── PropertiesStringConversion.qml
│ │ ├── BindingsArray.qml
│ │ ├── BindingsUpdate.qml
│ │ ├── BasicSignalParameters.qml
│ │ ├── BasicCompletedOfDynamicObjects.qml
│ │ ├── ImportJavascript.qml
│ │ ├── StateSimple.qml
│ │ ├── BindingsRecursiveInit3.qml
│ │ ├── BindingsRecursiveInit4.qml
│ │ ├── PropertiesBasic.qml
│ │ ├── BindingsRecursiveInit.qml
│ │ ├── BasicCreateQmlObject.qml
│ │ ├── BasicSignalDisconnectOnDelete.qml
│ │ ├── ScopeSafeFromLocals.qml
│ │ ├── PropertiesAliasChanged.qml
│ │ ├── BasicResolvedUrl.qml
│ │ ├── PropertiesAliasChangedBack.qml
│ │ ├── PropertiesChangedSignal.qml
│ │ ├── StateWhen.qml
│ │ ├── BindingsRecursiveInit2.qml
│ │ ├── StateBinding.qml
│ │ ├── ImportJavascriptScope.qml
│ │ ├── PropertiesUrlDir
│ │ │ ├── PropertiesUrlImport.qml
│ │ │ └── PropertiesUrlImportWithExceptions.qml
│ │ ├── ImportLocalComponentAsPropertyInAnotherDir.qml
│ │ ├── JavascriptBasicSyntax.qml
│ │ ├── PropertiesUrl.qml
│ │ ├── ScopeRepeater.qml
│ │ ├── BasicSignalDisconnect.qml
│ │ └── PropertiesUrlExceptionSafe.qml
│ ├── basepath
│ │ ├── B.qml
│ │ ├── test.qml
│ │ ├── import
│ │ │ └── A.qml
│ │ └── test.js
│ ├── javascript.js
│ └── parse.js
├── QtQuick
│ ├── qml
│ │ ├── ItemEmpty.qml
│ │ ├── TextWrapMode.qml
│ │ ├── RectangleColor.qml
│ │ ├── ItemSize.qml
│ │ ├── RectangleTransparent.qml
│ │ ├── RectangleWhite.qml
│ │ ├── ShortcutSequence.qml
│ │ ├── LoaderSourceImmediate.qml
│ │ ├── LoaderDirectory
│ │ │ └── LoaderDirectoryComponent.qml
│ │ ├── PropertyAnimationFailsToLoad.qml
│ │ ├── PropertyAnimationLoads.qml
│ │ ├── TimerSingleshot.qml
│ │ ├── LoaderEmptySource.qml
│ │ ├── LoaderSourceComponentImmediate.qml
│ │ ├── RepeaterNumberModel.qml
│ │ ├── TextImplicitSize.qml
│ │ ├── TimerParentProperty.qml
│ │ ├── LoaderSourceComponentFromComponent.qml
│ │ ├── LoaderComponent.qml
│ │ ├── LoaderSourceDelayed.qml
│ │ ├── RepeaterListModel.qml
│ │ ├── MouseAreaGeneric.qml
│ │ ├── LoaderSourceComponentDelayed.qml
│ │ ├── FontWeights.qml
│ │ ├── RepeaterPropertyRoleNameConflict.qml
│ │ ├── BehaviorBasic.qml
│ │ ├── TimerRunning.qml
│ │ ├── ParallelAnimationRunning.qml
│ │ ├── SequentialAnimationRunning.qml
│ │ ├── ListModel.qml
│ │ ├── SequentialAnimationPaused.qml
│ │ ├── RepeaterCompletedDestruction.qml
│ │ └── RepeaterModelRole.qml
│ ├── Behavior.js
│ ├── Text.js
│ ├── Font.js
│ ├── PropertyAnimation.js
│ ├── Item.js
│ ├── Rectangle.js
│ ├── Shortcut.js
│ ├── Loader.js
│ └── Timer.js
├── Render
│ ├── Async
│ │ ├── bg.png
│ │ ├── Image.png
│ │ ├── ImageFill.png
│ │ ├── BorderImage.png
│ │ ├── ImageMirror.png
│ │ ├── ColorAnimation.png
│ │ ├── NumberAnimation.png
│ │ ├── NumberAnimationAutorun.png
│ │ ├── Image.qml
│ │ ├── ColorAnimation.qml
│ │ ├── NumberAnimationAutorun.qml
│ │ ├── NumberAnimation.qml
│ │ ├── BorderImage.qml
│ │ ├── ImageFill.qml
│ │ └── ImageMirror.qml
│ ├── Simple
│ │ ├── res
│ │ │ ├── PropertyGridComponent.qml
│ │ │ └── LoaderScopeChild.qml
│ │ ├── ElementLoading.qml
│ │ ├── FlowTop.png
│ │ ├── Translate.png
│ │ ├── AnchorChains.png
│ │ ├── AnchorsFill.png
│ │ ├── AnchorsSides.png
│ │ ├── FlowRepeater.png
│ │ ├── LoaderScope.png
│ │ ├── PropertyGrid.png
│ │ ├── TextEditEmpty.png
│ │ ├── ElementLoading.png
│ │ ├── FlowReflowWidth.png
│ │ ├── RectangleBorder.png
│ │ ├── RectangleColor.png
│ │ ├── RectanglesGrid.png
│ │ ├── RepeaterNumber.png
│ │ ├── ScaleRectangle.png
│ │ ├── FlowReflowHeight.png
│ │ ├── PropertyRectangle.png
│ │ ├── RepeaterListModel.png
│ │ ├── ZeroOpacityLayout.png
│ │ ├── AnchorsCenterAndFill.png
│ │ ├── RectangleOnCompleted.png
│ │ ├── ScaleRectangleOrigin.png
│ │ ├── AnchorsCenterAndFill2.png
│ │ ├── FlowImplicitWidthHeight.png
│ │ ├── RectangleBorderChildren.png
│ │ ├── RectangleColor.qml
│ │ ├── RectangleImplicitSize.png
│ │ ├── AnchorUpdateHVGeometryRecursion.png
│ │ ├── RectangleOnCompleted.qml
│ │ ├── TextEditEmpty.qml
│ │ ├── LoaderScope.qml
│ │ ├── FlowRepeater.qml
│ │ ├── FlowTop.qml
│ │ ├── AnchorsFill.qml
│ │ ├── ScaleRectangle.qml
│ │ ├── RepeaterNumber.qml
│ │ ├── PropertyRectangle.qml
│ │ ├── FlowReflowWidth.qml
│ │ ├── Translate.qml
│ │ ├── FlowReflowHeight.qml
│ │ ├── PropertyGrid.qml
│ │ ├── RectanglesGrid.qml
│ │ ├── AnchorsCenterAndFill2.qml
│ │ ├── ScaleRectangleOrigin.qml
│ │ ├── AnchorsCenterAndFill.qml
│ │ ├── ZeroOpacityLayout.qml
│ │ ├── RectangleBorderChildren.qml
│ │ ├── RepeaterListModel.qml
│ │ ├── AnchorsSides.qml
│ │ ├── AnchorChains.qml
│ │ ├── RectangleBorder.qml
│ │ └── RectangleImplicitSize.qml
│ └── Fuzzy
│ │ ├── RectanglesAlpha.png
│ │ ├── RectanglesOpacity.png
│ │ ├── RectanglesOpacity.qml
│ │ └── RectanglesAlpha.qml
├── QtQuick.Controls
│ └── ComboBox
│ │ ├── test.qml
│ │ └── test_populated.qml
├── QtTest
│ ├── qml
│ │ ├── TestCaseEmpty.qml
│ │ ├── TestCaseSimple.qml
│ │ └── TestCaseDatadriven.qml
│ └── TestCase.js
├── Qt.labs.settings
│ ├── qml
│ │ ├── SettingsPlain.qml
│ │ └── SettingsAlias.qml
│ └── Settings.js
├── QmlWeb.Dom
│ ├── qml
│ │ └── DomElementStyle.qml
│ └── DomElementStyle.js
├── QtQuick.Layouts
│ ├── qml
│ │ ├── StackLayout.qml
│ │ ├── GridLayoutTopToBottom.qml
│ │ ├── GridLayoutLeftToRight.qml
│ │ ├── GridLayoutFill.qml
│ │ ├── ColumnLayoutImplicitSize.qml
│ │ └── RowLayoutImplicitSize.qml
│ └── StackLayout.js
├── Auto
│ ├── QtTest
│ │ └── tst_Math.qml
│ ├── Globals
│ │ └── tst_i18n.qml
│ ├── QtWebKit
│ │ └── tst_enums.qml
│ ├── QtQuick
│ │ ├── tst_point.qml
│ │ └── tst_size.qml
│ └── runner.js
├── QtQml
│ ├── qml
│ │ ├── BindingBroken.qml
│ │ ├── BindingOneWay.qml
│ │ ├── BindingUndefined.qml
│ │ ├── ConnectionsConnections.qml
│ │ └── BindingTwoWay.qml
│ ├── Connections.js
│ └── Binding.js
├── phantom.callback.js
├── .eslintrc
├── qmlweb.js
└── failingTests.js
├── misc
└── logo.png
├── .nycrc
├── .babelrc
├── codecov.yml
├── .gitignore
├── .editorconfig
├── examples
├── fullpage.html
├── qml
│ └── main.qml
├── embed.html
└── customelement.html
├── .travis.yml
├── bower.json
├── docs
├── JSItemModel.md
└── Signal.md
├── AUTHORS
├── LICENSE
└── karma.conf.js
/src/.eslintrc:
--------------------------------------------------------------------------------
1 | env:
2 | node: false
3 |
--------------------------------------------------------------------------------
/src/engine/.eslintrc:
--------------------------------------------------------------------------------
1 | rules:
2 | no-new-func: 0
3 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportReuse/foo/bar/qmldir:
--------------------------------------------------------------------------------
1 | ItemS ItemS.qml
2 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/importTestIncluded.js:
--------------------------------------------------------------------------------
1 | var includedTest = 42;
2 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/singleton/qmldir:
--------------------------------------------------------------------------------
1 | singleton Style 1.0 Style.qml
--------------------------------------------------------------------------------
/src/QmlWeb.js:
--------------------------------------------------------------------------------
1 | const QmlWeb = {};
2 |
3 | global.QmlWeb = QmlWeb;
4 |
--------------------------------------------------------------------------------
/misc/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/misc/logo.png
--------------------------------------------------------------------------------
/tests/QtQuick/qml/ItemEmpty.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | }
5 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportReuse/qmldir:
--------------------------------------------------------------------------------
1 | MainUI main.qml
2 | ItemA ItemA.qml
3 |
4 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/importTestInclude.js:
--------------------------------------------------------------------------------
1 | Qt.include("importTestIncluded.js");
2 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportReuse/foo/bar/ItemS.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.3
2 |
3 | Item {
4 | }
5 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ScopeComponentIdSomeComponent.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | }
5 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/TextWrapMode.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Text {
4 | text: "foo"
5 | }
6 |
--------------------------------------------------------------------------------
/tests/QMLEngine/basepath/B.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Controls 1.2
3 |
4 | Item {
5 | }
--------------------------------------------------------------------------------
/tests/Render/Async/bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Async/bg.png
--------------------------------------------------------------------------------
/tests/Render/Simple/res/PropertyGridComponent.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | }
5 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ScopeUpflowWithFoo.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.5
2 |
3 | ScopeUpflowWithRealFoo {
4 | }
5 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/RectangleColor.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | color: 'red'
5 | }
6 |
--------------------------------------------------------------------------------
/tests/Render/Async/Image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Async/Image.png
--------------------------------------------------------------------------------
/.nycrc:
--------------------------------------------------------------------------------
1 | {
2 | "coverageVariable": "__coverage__",
3 | "require": [
4 | "babel-register"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportFromDir.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property int value: 5
5 | }
6 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportLocalToFile/DirectoryFailSomeComponent.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | ImportMe {}
4 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportLocalToFile/ModuleSucceedSomeComponent.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | }
5 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ItemWithValue.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property int value: 1
5 | }
6 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/somelib/qmldir:
--------------------------------------------------------------------------------
1 | ShinyRectangle 1.0 RectangleColor.qml
2 | ShinyButton 1.0 SimpleButton.qml
3 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/ItemSize.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | width: 200
5 | height: 100
6 | }
7 |
--------------------------------------------------------------------------------
/tests/Render/Async/ImageFill.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Async/ImageFill.png
--------------------------------------------------------------------------------
/tests/Render/Simple/ElementLoading.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | RectangleColor {
4 | width: 50
5 | }
6 |
--------------------------------------------------------------------------------
/tests/Render/Simple/FlowTop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/FlowTop.png
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportFrom/ImportMe.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property int value: 67
5 | }
6 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportFrom/ParentDir.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import ".."
3 | ImportFromDir {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportNoQmldir.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import "ImportFrom"
3 |
4 | ImportMe {
5 |
6 | }
7 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ScopeUpflowWithRealFoo.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.5
2 |
3 | Item {
4 | property int foo: 15
5 | }
6 |
--------------------------------------------------------------------------------
/tests/QtQuick.Controls/ComboBox/test.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Controls 1.2
3 |
4 | ComboBox {
5 | }
--------------------------------------------------------------------------------
/tests/Render/Async/BorderImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Async/BorderImage.png
--------------------------------------------------------------------------------
/tests/Render/Async/ImageMirror.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Async/ImageMirror.png
--------------------------------------------------------------------------------
/tests/Render/Simple/Translate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/Translate.png
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015"],
3 | "plugins": ["transform-class-properties"],
4 | "compact" : false
5 | }
6 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ItemWithPropertyNamedSignal.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.5
2 | Item {
3 | property int signal: 10
4 | }
5 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/RectangleTransparent.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | color: 'transparent'
5 | }
6 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/RectangleWhite.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | width: 200
5 | height: 100
6 | }
7 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/ShortcutSequence.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Shortcut {
4 | sequences: ["Ctrl+Alt+P"]
5 | }
6 |
--------------------------------------------------------------------------------
/tests/Render/Async/ColorAnimation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Async/ColorAnimation.png
--------------------------------------------------------------------------------
/tests/Render/Simple/AnchorChains.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/AnchorChains.png
--------------------------------------------------------------------------------
/tests/Render/Simple/AnchorsFill.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/AnchorsFill.png
--------------------------------------------------------------------------------
/tests/Render/Simple/AnchorsSides.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/AnchorsSides.png
--------------------------------------------------------------------------------
/tests/Render/Simple/FlowRepeater.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/FlowRepeater.png
--------------------------------------------------------------------------------
/tests/Render/Simple/LoaderScope.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/LoaderScope.png
--------------------------------------------------------------------------------
/tests/Render/Simple/PropertyGrid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/PropertyGrid.png
--------------------------------------------------------------------------------
/tests/Render/Simple/TextEditEmpty.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/TextEditEmpty.png
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportQmldir.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import "somelib"
3 |
4 | ShinyRectangle {
5 | width: 50
6 | }
7 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ParseFunctionVar.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property var aFunction: function(){}
5 | }
6 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/LoaderSourceImmediate.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Loader {
4 | source: "LoaderComponent.qml"
5 | }
6 |
--------------------------------------------------------------------------------
/tests/QtTest/qml/TestCaseEmpty.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtTest 1.0
3 |
4 | TestCase {
5 | name: "Empty"
6 | }
7 |
--------------------------------------------------------------------------------
/tests/Render/Async/NumberAnimation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Async/NumberAnimation.png
--------------------------------------------------------------------------------
/tests/Render/Fuzzy/RectanglesAlpha.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Fuzzy/RectanglesAlpha.png
--------------------------------------------------------------------------------
/tests/Render/Simple/ElementLoading.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/ElementLoading.png
--------------------------------------------------------------------------------
/tests/Render/Simple/FlowReflowWidth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/FlowReflowWidth.png
--------------------------------------------------------------------------------
/tests/Render/Simple/RectangleBorder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/RectangleBorder.png
--------------------------------------------------------------------------------
/tests/Render/Simple/RectangleColor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/RectangleColor.png
--------------------------------------------------------------------------------
/tests/Render/Simple/RectanglesGrid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/RectanglesGrid.png
--------------------------------------------------------------------------------
/tests/Render/Simple/RepeaterNumber.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/RepeaterNumber.png
--------------------------------------------------------------------------------
/tests/Render/Simple/ScaleRectangle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/ScaleRectangle.png
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportReuse/ItemA.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.2
2 | import "foo/bar"
3 |
4 | Item {
5 | ItemS {
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/tests/Render/Fuzzy/RectanglesOpacity.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Fuzzy/RectanglesOpacity.png
--------------------------------------------------------------------------------
/tests/Render/Simple/FlowReflowHeight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/FlowReflowHeight.png
--------------------------------------------------------------------------------
/tests/Render/Simple/PropertyRectangle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/PropertyRectangle.png
--------------------------------------------------------------------------------
/tests/Render/Simple/RepeaterListModel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/RepeaterListModel.png
--------------------------------------------------------------------------------
/tests/Render/Simple/ZeroOpacityLayout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/ZeroOpacityLayout.png
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportFrom/LocalComponentProperty.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Repeater {
4 | delegate: ImportMe {}
5 | }
6 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportLocalToFile/ModuleFailSomeComponent.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtWebSockets 1.0
3 |
4 | Item {
5 | }
6 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportQualifiedModule.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0 as Quick
2 |
3 | Quick.Item {
4 | property int value: 67
5 | }
6 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportQualifiedNoQmldir.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import "ImportFrom" as ImFr
3 |
4 | ImFr.ImportMe {
5 |
6 | }
7 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ParseError.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.5
2 | Item {
3 | property string correct: ""
4 | properly int error: 11
5 | }
6 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/PropertiesNamedSignalValues.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.5
2 |
3 | ItemWithPropertyNamedSignal {
4 | signal: 20
5 | }
6 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/importTestSimple.js:
--------------------------------------------------------------------------------
1 | function importedTest(x) {
2 | return x + x;
3 | }
4 |
5 | var importedColor = "magenta";
6 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/LoaderDirectory/LoaderDirectoryComponent.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property int value: 43
5 | }
6 |
--------------------------------------------------------------------------------
/tests/Render/Simple/AnchorsCenterAndFill.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/AnchorsCenterAndFill.png
--------------------------------------------------------------------------------
/tests/Render/Simple/RectangleOnCompleted.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/RectangleOnCompleted.png
--------------------------------------------------------------------------------
/tests/Render/Simple/ScaleRectangleOrigin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/ScaleRectangleOrigin.png
--------------------------------------------------------------------------------
/src/modules/QmlWeb.Dom/DomDiv.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QmlWeb_Dom_DomDiv extends QmlWeb_Dom_DomElement {
3 | }
4 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/AnimatedImage.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_AnimatedImage extends QtQuick_Image {
3 | }
4 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/somelib/SimpleButton.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Controls 1.2
3 |
4 | Button {
5 | text: "I'm simple"
6 | }
--------------------------------------------------------------------------------
/tests/Render/Async/NumberAnimationAutorun.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Async/NumberAnimationAutorun.png
--------------------------------------------------------------------------------
/tests/Render/Simple/AnchorsCenterAndFill2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/AnchorsCenterAndFill2.png
--------------------------------------------------------------------------------
/tests/Render/Simple/FlowImplicitWidthHeight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/FlowImplicitWidthHeight.png
--------------------------------------------------------------------------------
/tests/Render/Simple/RectangleBorderChildren.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/RectangleBorderChildren.png
--------------------------------------------------------------------------------
/tests/Render/Simple/RectangleColor.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | color: 'red'
5 | width: 100
6 | height: 100
7 | }
8 |
--------------------------------------------------------------------------------
/tests/Render/Simple/RectangleImplicitSize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/RectangleImplicitSize.png
--------------------------------------------------------------------------------
/src/engine/QMLNumber.js:
--------------------------------------------------------------------------------
1 | function QMLNumber(val) {
2 | return +val;
3 | }
4 | QMLNumber.plainType = true;
5 | QmlWeb.qmlNumber = QMLNumber;
6 |
--------------------------------------------------------------------------------
/src/engine/QMLString.js:
--------------------------------------------------------------------------------
1 | function QMLString(val) {
2 | return `${val}`;
3 | }
4 | QMLString.plainType = true;
5 | QmlWeb.qmlString = QMLString;
6 |
--------------------------------------------------------------------------------
/src/engine/QMLVariant.js:
--------------------------------------------------------------------------------
1 | function QMLVariant(val) {
2 | return val;
3 | }
4 | QMLVariant.plainType = true;
5 | QmlWeb.qmlVariant = QMLVariant;
6 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/FocusScope.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_FocusScope extends QtQuick_Item {
3 | // TODO
4 | }
5 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportFrom/SiblingDir.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import "../somelib"
3 | ShinyButton {
4 | property int value: 55
5 | }
6 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportLocalToFile/DirectoryFail.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import "../ImportFrom"
3 |
4 | DirectoryFailSomeComponent {}
5 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/JavascriptRegexp.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property variant reg: /^[0-9]+\/(first|second){1,2}$/
5 | }
6 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/PropertiesDefault.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.2
2 |
3 | PropertiesDefaultLabel {
4 | Text {
5 | text: "world!"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/PropertiesNamedSignal.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.5
2 | Item {
3 | ItemWithPropertyNamedSignal {
4 | signal: 20
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ScopeIdOverProperty.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | ScopeIdOverPropertyImpl {
4 | Item {
5 | id: foo
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/singleton/Style.qml:
--------------------------------------------------------------------------------
1 | pragma Singleton
2 | import QtQuick 2.0
3 |
4 | QtObject {
5 | property color customColor: "green"
6 | }
--------------------------------------------------------------------------------
/src/engine/QMLBoolean.js:
--------------------------------------------------------------------------------
1 | function QMLBoolean(val) {
2 | return !!val;
3 | }
4 | QMLBoolean.plainType = true;
5 | QmlWeb.qmlBoolean = QMLBoolean;
6 |
--------------------------------------------------------------------------------
/src/engine/QMLInteger.js:
--------------------------------------------------------------------------------
1 | function QMLInteger(val) {
2 | return val | 0;
3 | }
4 | QMLInteger.plainType = true;
5 | QmlWeb.qmlInteger = QMLInteger;
6 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ParseSignal.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | signal simpleSignal;
5 | signal signalWithParams(string someParam)
6 | }
7 |
--------------------------------------------------------------------------------
/src/engine/QMLUrl.js:
--------------------------------------------------------------------------------
1 | function QMLUrl(val) {
2 | return QmlWeb.engine.$resolvePath(`${val}`);
3 | }
4 | QMLUrl.plainType = true;
5 | QmlWeb.qmlUrl = QMLUrl;
6 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportLocalToFile/ModuleFail2.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | ModuleFailSomeComponent {
5 | }
6 | WebSocket {}
7 | }
8 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ScopeIdOverPropertyImpl.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property int foo: 42
5 | property string boo: foo.toString()
6 | }
7 |
--------------------------------------------------------------------------------
/tests/Render/Simple/AnchorUpdateHVGeometryRecursion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qmlweb/qmlweb/HEAD/tests/Render/Simple/AnchorUpdateHVGeometryRecursion.png
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportLocalToFile/ModuleFail1.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | ModuleFailSomeComponent {
5 | WebSocket {}
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/PropertiesDefaultLabel.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.2
2 |
3 | Text {
4 | default property var someText
5 | text: "Hello, " + someText.text
6 | }
7 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/PropertyAnimationFailsToLoad.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.6
2 |
3 | Item {
4 | transform: Rotation {
5 | NumberAnimation {
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/engine/QMLOperationState.js:
--------------------------------------------------------------------------------
1 | const QMLOperationState = {
2 | Idle: 1,
3 | Init: 2,
4 | Running: 3
5 | };
6 |
7 | QmlWeb.QMLOperationState = QMLOperationState;
8 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/PropertyAnimationLoads.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.6
2 |
3 | Item {
4 | transform: Rotation {
5 | NumberAnimation on angle {
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/BindingsNoSrc.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | width: 10
5 | height: (typeof bindSrc === 'undefined') ? width + 2 : bindSrc.length
6 | }
7 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/TimerSingleshot.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.5
2 | Timer {
3 | interval: 50
4 | property int counter: 0
5 | onTriggered: {
6 | yield("done")
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/modules/QtQml.Models/ListElement.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQml_Models_ListElement extends QtQuick_ListElement {
3 | static versions = /^2\./;
4 | }
5 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportQmldirSingleton.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import "singleton"
3 |
4 | Rectangle {
5 | height: 10
6 | width: 20
7 | color: Style.customColor
8 | }
9 |
--------------------------------------------------------------------------------
/tests/QtQuick.Controls/ComboBox/test_populated.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Controls 1.2
3 |
4 | ComboBox {
5 | currentIndex: 1
6 | model: ["a","b","c"]
7 | }
8 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/LoaderEmptySource.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Loader {
4 | source: "LoaderComponent.qml"
5 | Component.onCompleted: {
6 | source = ""
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/XAnimator.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_XAnimator extends QtQuick_Animator {
3 | static versions = /^2\./;
4 |
5 | // TODO
6 | }
7 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/YAnimator.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_YAnimator extends QtQuick_Animator {
3 | static versions = /^2\./;
4 |
5 | // TODO
6 | }
7 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportJavascriptInclude.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import "importTestInclude.js" as Imported
3 |
4 | Item {
5 | property int value: Imported.includedTest
6 | }
7 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ScopeOverrideBase.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property var foo: 42
5 |
6 | function getFooVal() {
7 | return foo;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/ScaleAnimator.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_ScaleAnimator extends QtQuick_Animator {
3 | static versions = /^2\./;
4 |
5 | // TODO
6 | }
7 |
--------------------------------------------------------------------------------
/tests/QMLEngine/basepath/test.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Controls 1.2
3 | import "import"
4 |
5 | Item {
6 | A {
7 | a:1
8 | }
9 | B {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/PropertiesAlias.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property alias childX: child.x
5 |
6 | Item {
7 | id: child
8 | x: 125
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/PropertiesUndefined.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property var theUndefined
5 |
6 | Text {
7 | text: typeof(theUndefined)
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ScopeRoot.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | id: rootItem
5 |
6 | property int value: 1000
7 | ScopeMid {
8 | id: parentItem
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/tests/Render/Simple/RectangleOnCompleted.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | color: 'red'
5 | width: 10
6 | height: 10
7 | Component.onCompleted: color = '#0f0'
8 | }
9 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/OpacityAnimator.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_OpacityAnimator extends QtQuick_Animator {
3 | static versions = /^2\./;
4 |
5 | // TODO
6 | }
7 |
--------------------------------------------------------------------------------
/src/modules/QtQuick.Particles/Direction.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Particles_Direction extends QtQml_QtObject {
3 | static versions = /^2\./;
4 |
5 | // TODO
6 | }
7 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/RotationAnimator.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_RotationAnimator extends QtQuick_Animator {
3 | static versions = /^2\./;
4 |
5 | // TODO
6 | }
7 |
--------------------------------------------------------------------------------
/tests/Qt.labs.settings/qml/SettingsPlain.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import Qt.labs.settings 1.0
3 |
4 | Settings {
5 | category: "QmlWebTestPlain"
6 | property int a: 10
7 | property string b
8 | }
9 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/LoaderSourceComponentImmediate.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Loader {
4 | Component.onCompleted: {
5 | sourceComponent = Qt.createComponent("LoaderComponent.qml");
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ScopeComponentId.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | ScopeComponentIdSomeComponent {
4 | id: some_component
5 |
6 | property int foo: 42
7 | property int bar: some_component.foo
8 | }
9 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ScopeUpflow.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.5
2 |
3 | ScopeUpflowWithFoo {
4 | Item {
5 | id: child
6 | property int thisFoo: typeof foo == "undefined" ? "undefined" : foo
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/RepeaterNumberModel.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property alias repeater: _repeater
5 | Repeater {
6 | id: _repeater
7 | Item {
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/modules/QtQml.Models/ListModel.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQml_Models_ListModel extends QtQuick_ListModel {
3 | static versions = /^2\./;
4 | static defaultProperty = "$items";
5 | }
6 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | coverage:
2 | round: down
3 | range: 50...100
4 |
5 | status:
6 | project:
7 | default:
8 | threshold: 1
9 | changes: off
10 | patch: off
11 |
12 | comment: off
13 |
--------------------------------------------------------------------------------
/tests/Render/Simple/TextEditEmpty.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | width: 24
5 | height: 24
6 |
7 | TextEdit {
8 | x: 2
9 | y: 2
10 | width: 20
11 | height: 20
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/modules/QtQuick.Controls.2/TabButton.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Controls_2_TabButton extends QtQuick_Controls_2_AbstractButton {
3 | static versions = /^2\./;
4 |
5 | // TODO
6 | }
7 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/BindingsThis.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property int intA: 10
5 | property int intB: this.intA * 2
6 | function foo() {
7 | return this.intB + this.intA;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | lib/
3 | coverage/
4 | tmp/
5 | build/
6 | .idea/
7 | *~
8 | *.bak
9 | *.log
10 | .*.swp
11 | .*.swo
12 | *.qmlc
13 | *.kdev4
14 | *kate-swp
15 | .arcconfig
16 | .eslintcache
17 | .project
18 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportLocalToFile/ModuleSucceed.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtWebSockets 1.0
3 |
4 | Item {
5 | ModuleSucceedSomeComponent {
6 | WebSocket {}
7 | }
8 | WebSocket {}
9 | }
10 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/TextImplicitSize.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property alias text_item: _text_item
5 | Rectangle {
6 | Text {
7 | id: _text_item
8 | text: "_ _ _"
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | end_of_line = lf
5 | charset = utf-8
6 | trim_trailing_whitespace = true
7 | indent_style = space
8 | indent_size = 2
9 |
10 | [*.{md,markdown}]
11 | trim_trailing_whitespace = false
12 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ScopeSibling.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.5
2 |
3 | Item {
4 | ItemWithValue {
5 | id: childA
6 | value: 2
7 | }
8 |
9 | ItemWithValue {
10 | id: childB
11 | value: childA.value * 2
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportReuse/main.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import "foo/bar"
3 |
4 | Rectangle {
5 | width: 400
6 | height: 400
7 | color: "#000"
8 |
9 | ItemS {
10 | }
11 |
12 | ItemA {
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/TimerParentProperty.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property int value: 42
5 |
6 | property alias timer: _timer
7 | Timer {
8 | id: _timer
9 | property int value: parent.value
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/tests/QmlWeb.Dom/qml/DomElementStyle.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QmlWeb.Dom 1.0
3 |
4 | DomElement {
5 | property int bindSize: 21
6 | style.textAlign: "center"
7 | style.fontSize: bindSize + "px"
8 | text: "Hello HTML"
9 | }
10 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ScopeLeaf.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property int value: 1
5 | property int rootValue: rootItem.value
6 | property int parentValue: parentItem.value
7 | property int totalValue: (rootValue + parentValue) * value
8 | }
9 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ScopeOverride.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | ScopeOverrideBase {
4 | id: foo
5 | width: 200
6 |
7 | function getFooWidth() {
8 | return foo.width;
9 | }
10 |
11 | Text {
12 | text: getFooWidth()
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/tests/Render/Simple/LoaderScope.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | id: root
5 | width: 30
6 | height: 30
7 | color: 'red'
8 |
9 | Loader {
10 | anchors.fill: parent
11 | source: 'res/LoaderScopeChild.qml'
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/UniformAnimator.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_UniformAnimator extends QtQuick_Animator {
3 | static versions = /^2\./;
4 | static properties = {
5 | uniform: "string"
6 | };
7 |
8 | // TODO
9 | }
10 |
--------------------------------------------------------------------------------
/examples/fullpage.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | QML Fullpage Auto-load Example
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/PropertiesAliasToId.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Controls 1.1
3 |
4 | Item {
5 | property alias childA: child
6 |
7 | Item {
8 | id: child
9 | x: 125
10 | }
11 |
12 | Text {
13 | text: childA.x
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/somelib/RectangleColor.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import "." // import "" is not correct, qmlscene says
3 |
4 | Rectangle {
5 | color: 'green'
6 | width: 100
7 | height: 100
8 | ShinyButton {
9 | x: 10
10 | y: 10
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/ListElement.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_ListElement extends QtQml_QtObject {
3 | $setCustomData(propName, value) {
4 | QmlWeb.createProperty("variant", this, propName, {
5 | initialValue: value
6 | });
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/tests/QMLEngine/basepath/import/A.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Controls 1.2
3 |
4 | Item {
5 | property var a
6 | property var b
7 |
8 | onAChanged: foo1()
9 | onBChanged: foo2()
10 |
11 | function foo1() { b = a+1; }
12 | function foo2() {}
13 | }
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/PropertiesChangedExpressionSignal.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property int counter: 0
5 |
6 | property int value: 0
7 | Component.onCompleted: value++
8 |
9 | property int foo: value > 0 ? 1 : 0
10 | onFooChanged: counter++
11 | }
12 |
--------------------------------------------------------------------------------
/tests/Qt.labs.settings/qml/SettingsAlias.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import Qt.labs.settings 1.0
3 |
4 | Item {
5 | id: root
6 | Settings {
7 | category: "QmlWebTestAlias"
8 | property alias width: root.width
9 | property alias height: root.height
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/modules/QtQuick.Controls.2/Label.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Controls_2_Label extends QtQuick_Text {
3 | static versions = /^2\./;
4 | static properties = {
5 | background: "Item",
6 | palette: "palette"
7 | };
8 |
9 | // TODO
10 | }
11 |
--------------------------------------------------------------------------------
/tests/QtQuick.Layouts/qml/StackLayout.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.15
2 | import QtQuick.Layouts 1.15
3 |
4 | StackLayout {
5 | Rectangle {
6 | implicitHeight: 300
7 | implicitWidth: 200
8 | color: "black"
9 | }
10 |
11 | Rectangle {
12 | color: "red"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/LoaderSourceComponentFromComponent.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Loader {
4 | height: 30
5 | width: 30
6 | sourceComponent: leComponent
7 |
8 | Component {
9 | id: leComponent
10 | Rectangle {
11 | color: "yellow"
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/tests/Render/Async/Image.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Image {
4 | source: 'Image.png'
5 |
6 | onStatusChanged: {
7 | if (typeof window !== 'undefined' &&
8 | status !== Image.Loading) {
9 | window.onTestLoad({ framesDelay: 2 });
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/tests/Render/Simple/FlowRepeater.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Flow {
4 | width: 23
5 | height: 17
6 | Repeater {
7 | model: 11
8 | delegate: Rectangle {
9 | color: index % 3 ? '#ccc' : '#000'
10 | width: 5
11 | height: 5
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/examples/qml/main.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | color: "lightgray"
5 | width: 400
6 | height: 400
7 |
8 | Text {
9 | text: "Hello, world!"
10 | anchors.centerIn: parent
11 | font.pointSize: 24
12 | font.bold: true
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/BasicCreateObject.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.2
2 |
3 | Item {
4 | id: item
5 | property string contextVar: "42";
6 |
7 | Component.onCompleted: {
8 | var c = Qt.createComponent("BasicCreateObjectSomeComponent.qml")
9 | c.createObject(item)
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/PropertiesAliasToIdSameName.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Controls 1.1
3 |
4 | Item {
5 | id: it
6 |
7 | property alias child: child
8 |
9 | Item {
10 | id: child
11 | x: 125
12 | }
13 |
14 | Text {
15 | text: it.child.x
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/modules/QmlWeb.Dom/DomParagraph.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QmlWeb_Dom_DomParagraph extends QmlWeb_Dom_DomElement {
3 | constructor(meta) {
4 | meta.tagName = "p";
5 | if (!meta.style) meta.style = {};
6 | meta.style.margin = 0;
7 | super(meta);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/modules/QtQuick.Particles/ParticlePainter.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Particles_ParticlePainter extends QtQuick_Item {
3 | static versions = /^2\./;
4 | static properties = {
5 | groups: "list",
6 | system: "ParticleSystem"
7 | };
8 |
9 | // TODO
10 | }
11 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/LoaderComponent.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtWebSockets 1.0 as WS
3 | import "LoaderDirectory" as LD
4 | import "LoaderDirectory"
5 |
6 | Item {
7 | property int value: 42
8 |
9 | WS.WebSocket {}
10 | LoaderDirectoryComponent {}
11 | LD.LoaderDirectoryComponent {}
12 | }
13 |
--------------------------------------------------------------------------------
/tests/Render/Simple/FlowTop.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Flow {
4 | width: 23
5 | height: 17
6 | flow: Flow.TopToBottom
7 | Repeater {
8 | model: 11
9 | delegate: Rectangle {
10 | color: index % 4 ? '#ccc' : '#000'
11 | width: 5
12 | height: 5
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/tests/Auto/QtTest/tst_Math.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtTest 1.0
3 |
4 | TestCase {
5 | name: "Math"
6 | width: 30 + 10
7 | height: width - 5
8 |
9 | function test_width() {
10 | compare(width, 40)
11 | }
12 |
13 | function test_height() {
14 | compare(height, 35)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/BasicCreateObjectSomeComponent.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.2
2 | import QtQuick.Controls 1.0
3 |
4 | Rectangle {
5 | color: 'green'
6 | width: 320
7 | height: 32
8 |
9 | property var q: 22
10 |
11 | Text {
12 | color:'gold'
13 | text: 'variable from context = ' + contextVar
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ScopeMid.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | id: parentItem
5 | property int value: 100
6 | property int sum: childA.totalValue + childB.totalValue
7 |
8 | ScopeLeaf {
9 | id: childA
10 | value: 2
11 | }
12 |
13 | ScopeLeaf {
14 | id: childB
15 | value: 4
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/modules/QtQuick.Controls.2/TabBar.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Controls_2_TabBar extends QtQuick_Controls_2_Container {
3 | static versions = /^2\./;
4 | static properties = {
5 | contentHeight: "real",
6 | contentWidth: "real",
7 | position: "enum"
8 | };
9 |
10 | // TODO
11 | }
12 |
--------------------------------------------------------------------------------
/src/modules/QtQuick.Particles/CustomParticle.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef, max-len
2 | class QtQuick_Particles_CustomParticle extends QtQuick_Particles_ParticlePainter {
3 | static versions = /^2\./;
4 | static properties = {
5 | fragmentShader: "string",
6 | vertexShader: "string"
7 | };
8 |
9 | // TODO
10 | }
11 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/PropertiesStringConversion.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property int intA: 10
5 | property string stringA: intA
6 | property string stringB: 11
7 | property string stringBinding: 1 + 1
8 | property string stringFalseVal: 0
9 |
10 | function reassign() {
11 | stringA = 333;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/LoaderSourceDelayed.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Loader {
4 | id: loader
5 |
6 | function start() {
7 | timer.start()
8 | }
9 |
10 | Timer {
11 | id: timer
12 | interval: 10
13 | onTriggered: {
14 | loader.source = "LoaderComponent.qml"
15 | loader.yield()
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/RepeaterListModel.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property alias repeater: _repeater
5 | Repeater {
6 | id: _repeater
7 | model: ListModel {
8 | id: list_model
9 | }
10 | Item {
11 | property var firstRole: role1
12 | property var secondRole: role2
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/modules/QtWebEngine/WebEngineView.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtWebEngine_WebEngineView extends QtWebView_WebView {
3 | static versions = /^5\./;
4 | static properties = {
5 | // TODO
6 | };
7 | static signals = {
8 | // TODO
9 | };
10 |
11 | // TODO: implement more features on top of WebView
12 | }
13 |
--------------------------------------------------------------------------------
/tests/Render/Simple/AnchorsFill.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | color: "white"
5 | width: 16
6 | height: 16
7 | Rectangle {
8 | id: red
9 | color: "red"
10 | anchors.fill: parent
11 | Rectangle {
12 | color: "blue"
13 | anchors.fill: parent
14 | anchors.margins: 3
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/modules/QtQml/QValidator.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQml_QValidator extends QtQml_QtObject {
3 | static enums = {
4 | QValidator: {
5 | Invalid: 0, Intermediate: 1, Acceptable: 2
6 | }
7 | };
8 | static properties = {
9 | locale: "string"
10 | };
11 |
12 | fixup() {} // stub, does nothing
13 | }
14 |
--------------------------------------------------------------------------------
/src/modules/QtQuick.Layouts/DirectionalLayout.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Layouts_DirectionalLayout extends QtQuick_Layouts_Positioner {
3 | constructor(meta) {
4 | super(meta);
5 | this.spacingChanged.connect(this, this.layoutChildren);
6 | this.layoutDirectionChanged.connect(this, this.layoutChildren);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/BindingsArray.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | id: main
5 | property int value: 5
6 | property bool novalue
7 | property variant arr: [1, 2, "hello world", [1, 2, false]]
8 | property variant bindingArray: [1, 2, "hello world", [+1, main.value - 3, novalue]]
9 | property string text: "Value=" + value
10 | }
11 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/BindingsUpdate.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property int intA: 10
5 | property int intB: intA * 2
6 | property string textA: "hello"
7 | property string textB: textA + " world"
8 | property size size: Qt.size(1, 2)
9 | property real sizeWidth: size.width
10 | property real sizeHeight: size.height
11 | }
12 |
--------------------------------------------------------------------------------
/tests/Render/Simple/ScaleRectangle.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | color: 'green'
5 | width: 60; height: 50
6 |
7 | Rectangle {
8 | width: 50; height: 50
9 | color: "#00f"
10 | transform: Scale {
11 | origin.x: 20
12 | origin.y: 15
13 | xScale: 0.5
14 | yScale: 0.8
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/MouseAreaGeneric.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | width: 20
5 | height: 20
6 | property bool pressed: mouse_area.pressed
7 | property Item area: mouse_area
8 | property int clicks: 0
9 | MouseArea {
10 | id: mouse_area
11 | width: 10
12 | height: 10
13 | onClicked: parent.clicks++
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/tests/Render/Simple/RepeaterNumber.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | color: '#fff'
5 | width: 50
6 | height: 25
7 |
8 | Repeater {
9 | model: 10
10 | delegate: Rectangle {
11 | color: 'black'
12 | width: 5
13 | height: 5
14 | x: 5 * index
15 | y: 5 * index % parent.height
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/BasicSignalParameters.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | id: item
5 |
6 | signal someSignal(int a, string b)
7 |
8 | property int propA
9 | property string propB
10 |
11 | onSomeSignal: {
12 | propA = a
13 | propB = b
14 | }
15 |
16 | Component.onCompleted: {
17 | item.someSignal(42, "foo")
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/modules/QtQuick.Controls/TextArea.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Controls_TextArea extends QtQuick_TextEdit {
3 | constructor(meta) {
4 | super(meta);
5 | const textarea = this.impl;
6 | textarea.style.padding = "5px";
7 | textarea.style.borderWidth = "1px";
8 | textarea.style.backgroundColor = "#fff";
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "8"
4 | - "stable"
5 | notifications:
6 | email: false
7 | cache:
8 | directories:
9 | - $HOME/.npm/
10 | - node_modules
11 | before_install:
12 | - npm install -g codecov
13 | matrix:
14 | include:
15 | - node_js: "8"
16 | script: npm run coverage
17 | after_success:
18 | - codecov
19 |
--------------------------------------------------------------------------------
/tests/Render/Simple/PropertyRectangle.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | property real r: 3.4
5 | property int num: Math.round(1.5)
6 | property var arr: [1, 2, 3]
7 | property bool foo: true
8 | property string s: foo ? 'green' : 'red'
9 | color: s
10 | width: height * 2
11 | height: s.length + arr.length * arr[1] + (Math.round(r) - num)
12 | }
13 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/BasicCompletedOfDynamicObjects.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | color: "red"
5 | id: item
6 |
7 | Component.onCompleted: {
8 | Qt.createQmlObject(
9 | "import QtQuick 2.2\nItem { Component.onCompleted: parent.color = 'cyan'; }",
10 | item,
11 | "inlinecode1",
12 | __executionContext
13 | );
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/LoaderSourceComponentDelayed.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Loader {
4 | id: loader
5 |
6 | function start() {
7 | timer.start()
8 | }
9 |
10 | Timer {
11 | id: timer
12 | interval: 10
13 | onTriggered: {
14 | loader.sourceComponent = Qt.createComponent("LoaderComponent.qml")
15 | loader.yield()
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/modules/QtQuick.Particles/AngleDirection.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef, max-len
2 | class QtQuick_Particles_AngleDirection extends QtQuick_Particles_Direction {
3 | static versions = /^2\./;
4 | static properties = {
5 | angle: "real",
6 | angleVariation: "real",
7 | magnitude: "real",
8 | magnitudeVariation: "real"
9 | };
10 |
11 | // TODO
12 | }
13 |
--------------------------------------------------------------------------------
/tests/QtQml/qml/BindingBroken.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.5
2 |
3 | Item {
4 | property int targetValue: 0
5 | property alias sourceValue: sourceItem.value
6 | property bool when: false
7 |
8 | id: root
9 |
10 | Item {
11 | property int value: 0
12 | id: sourceItem
13 | }
14 |
15 | Binding {
16 | target: root; property: "targetValue"; when: root.when
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/RegExpValidator.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_RegExpValidator extends QtQml_QValidator {
3 | static properties = {
4 | regExp: "var"
5 | };
6 |
7 | validate(string) {
8 | if (!this.regExp) return true;
9 | return this.regExp.test(string)
10 | ? this.QValidator.Acceptable
11 | : this.QValidator.Invalid;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/tests/phantom.callback.js:
--------------------------------------------------------------------------------
1 | /* global page */
2 |
3 | module.exports = function(command, options) {
4 | if (options.offset) {
5 | page.clipRect = options.offset;
6 | }
7 |
8 | var system = require("system");
9 | if (options.fileName && system.env.QMLWEB_SAVE_RENDER) {
10 | page.render("tmp/Render/" + options.fileName);
11 | }
12 |
13 | return page.renderBase64("PNG");
14 | };
15 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "qmlweb",
3 | "description": "QML port to Javascript",
4 | "main": "lib/qmlweb.min.js",
5 | "license": "BSD",
6 | "keywords": [
7 | "qml",
8 | "qt"
9 | ],
10 | "homepage": "https://github.com/qmlweb/qmlweb",
11 | "moduleType": [
12 | "globals"
13 | ],
14 | "ignore": [
15 | "**/.*",
16 | "node_modules",
17 | "tests"
18 | ]
19 | }
20 |
--------------------------------------------------------------------------------
/src/modules/QtNfc/NearField.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtNfc_NearField extends QtQml_QtObject {
3 | static properties = {
4 | filter: "list",
5 | messageRecords: "list",
6 | orderMatch: "bool",
7 | polling: "bool"
8 | };
9 | static signals = {
10 | tagFound: [],
11 | tagRemoved: []
12 | };
13 |
14 | // TODO: implementation based on Web NFC API
15 | }
16 |
--------------------------------------------------------------------------------
/src/modules/QtQuick.Controls/ApplicationWindow.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Controls_ApplicationWindow extends QtQuick_Window_Window {
3 | static versions = /^1\./;
4 | static properties = {
5 | //contentItem: "ContentItem", // TODO
6 | menuBar: "MenuBar",
7 | statusBar: "Item",
8 | style: "Component",
9 | toolBar: "Item"
10 | };
11 |
12 | // TODO
13 | }
14 |
--------------------------------------------------------------------------------
/tests/QtQml/qml/BindingOneWay.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.5
2 |
3 | Item {
4 | property int targetValue: 0
5 | property alias sourceValue: sourceItem.value
6 | property bool when: true
7 |
8 | id: root
9 |
10 | Item {
11 | property int value: 0
12 | id: sourceItem
13 | }
14 |
15 | Binding {
16 | target: root; property: "targetValue"; value: sourceItem.value; when: root.when
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/Translate.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Translate extends QtQml_QtObject {
3 | static properties = {
4 | x: "real",
5 | y: "real"
6 | };
7 |
8 | constructor(meta) {
9 | super(meta);
10 |
11 | this.xChanged.connect(this.$parent, this.$parent.$updateTransform);
12 | this.yChanged.connect(this.$parent, this.$parent.$updateTransform);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportJavascript.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import "importTestSimple.js" as Imported
3 |
4 | Rectangle {
5 | height: 10
6 | width: Imported.importedTest(height)
7 | color: Imported.importedColor
8 |
9 | function importedColor() {
10 | return Imported.importedColor;
11 | }
12 |
13 | function setImportedColor(color) {
14 | return Imported.importedColor = color;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/StateSimple.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | Item {
3 | id: root
4 | property int value: 10
5 | states: [
6 | State {
7 | name: "otherState"
8 | PropertyChanges {
9 | target: root
10 | value: 20
11 | }
12 | }
13 | ]
14 | function start() {
15 | yield()
16 | state = "otherState"
17 | yield()
18 | state = ""
19 | yield()
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/tests/QtQml/qml/BindingUndefined.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.5
2 |
3 | Item {
4 | property var targetValue: null
5 | property alias sourceValue: sourceItem.value
6 | property bool when: true
7 |
8 | id: root
9 |
10 | Item {
11 | property var value: null
12 | id: sourceItem
13 | }
14 |
15 | Binding {
16 | target: root; property: "targetValue"; when: root.when; value: sourceItem.value
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/tests/QtQuick.Layouts/qml/GridLayoutTopToBottom.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Layouts 1.0
3 |
4 | GridLayout {
5 | flow: GridLayout.TopToBottom
6 | layoutDirection: Qt.LeftToRight
7 | rows: 3
8 |
9 | Repeater {
10 | model: 11
11 | delegate: Rectangle {
12 | implicitWidth: 100
13 | implicitHeight: 100
14 | color: ["red", "green", "blue"][index % 3]
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/tests/Render/Simple/FlowReflowWidth.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | width: 20
5 | height: 20
6 |
7 | Flow {
8 | width: 18
9 | Repeater {
10 | model: 7
11 | delegate: Rectangle {
12 | color: index % 2 ? '#ccc' : '#000'
13 | width: 5
14 | height: 5
15 | }
16 | }
17 | Component.onCompleted: {
18 | width = 20
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/tests/QtQuick.Layouts/qml/GridLayoutLeftToRight.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Layouts 1.0
3 |
4 | GridLayout {
5 | flow: GridLayout.LeftToRight
6 | layoutDirection: Qt.LeftToRight
7 | columns: 3
8 |
9 | Repeater {
10 | model: 11
11 | delegate: Rectangle {
12 | implicitWidth: 100
13 | implicitHeight: 100
14 | color: ["red", "green", "blue"][index % 3]
15 | }
16 | }
17 | }
18 |
19 |
--------------------------------------------------------------------------------
/tests/Render/Simple/Translate.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | width: 30; height: 24
5 | Rectangle {
6 | width: 10; height: 10
7 | color: '#0f0'
8 | transform: Translate { x: 2; y: 5 }
9 | }
10 | Rectangle {
11 | width: 10; height: 10
12 | anchors.bottom: parent.bottom
13 | anchors.right: parent.right
14 | color: '#00f'
15 | transform: Translate { x: -2; y : -5 }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/tests/Render/Simple/res/LoaderScopeChild.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | Rectangle {
5 | anchors.top: parent.top
6 | anchors.right: parent.right
7 | width: 15
8 | height: 15
9 | color: 'green'
10 | }
11 | Rectangle {
12 | anchors.left: parent.left
13 | anchors.bottom: parent.bottom
14 | width: root.width / 2
15 | height: root.height / 2
16 | color: 'blue'
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/BindingsRecursiveInit3.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.2
2 |
3 | Item {
4 | width: 400
5 | property int intA: 3+3
6 |
7 | onIntAChanged: launch()
8 |
9 | property var log: ""
10 | function launch() {
11 | // perform something expensive and important,
12 | // where intA value really matters
13 | log = log + "Fly to planet N" + intA + "!";
14 | }
15 |
16 | Text {
17 | text: log
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/BindingsRecursiveInit4.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.2
2 |
3 | Item {
4 | width: 400
5 | property int intA: 3
6 |
7 | onIntAChanged: launch()
8 |
9 | property var log: ""
10 | function launch() {
11 | // perform something expensive and important,
12 | // where intA value really matters
13 | log = log + "Fly to planet N" + intA + "!";
14 | }
15 |
16 | Text {
17 | text: log
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/modules/QtQuick.Controls.2/Page.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Controls_2_Page extends QtQuick_Controls_2_Control {
3 | static versions = /^2\./;
4 | static properties = {
5 | contentChildren: "list",
6 | contentData: "list",
7 | contentHeight: "real",
8 | contentWidth: "real",
9 | footer: "Item",
10 | header: "Item",
11 | title: "string"
12 | };
13 |
14 | // TODO
15 | }
16 |
--------------------------------------------------------------------------------
/tests/QtQuick.Layouts/qml/GridLayoutFill.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Layouts 1.0
3 |
4 | GridLayout {
5 | flow: GridLayout.LeftToRight
6 | layoutDirection: Qt.LeftToRight
7 | columns: 3
8 | width: 445
9 |
10 | Repeater {
11 | model: 11
12 | delegate: Rectangle {
13 | implicitWidth: 100
14 | implicitHeight: 100
15 | color: ["red", "green", "blue"][index % 3]
16 | }
17 | }
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/PropertiesBasic.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property int intProperty: 10
5 | property double doubleProperty: 0.5
6 | property string stringProperty: "hello"
7 | property Item itemProperty: Item { }
8 | property var arrayProperty: [1, 2, "bar"]
9 | property int hexProperty: 0xFF
10 | property int octProperty: 077
11 | property double bigNumber: 1e8
12 | property size sizeProperty: Qt.size(5, 6)
13 | }
14 |
--------------------------------------------------------------------------------
/tests/Render/Simple/FlowReflowHeight.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | width: 20
5 | height: 20
6 |
7 | Flow {
8 | flow: Flow.TopToBottom
9 | height: 18
10 | Repeater {
11 | model: 7
12 | delegate: Rectangle {
13 | color: index % 2 ? '#ccc' : '#000'
14 | width: 5
15 | height: 5
16 | }
17 | }
18 | Component.onCompleted: {
19 | height = 20
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/tests/Render/Simple/PropertyGrid.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import "./res"
3 |
4 | Grid {
5 | columns: 4
6 | spacing: 3
7 | Rectangle { color: "red"; width: 5; height: 5 }
8 | PropertyGridComponent { color: 'green'; width: 6; height: 3 }
9 | Rectangle { color: "#00f"; width: 2; height: 6 }
10 | PropertyGridComponent { color: 'cy' + 'an'; width: 1; height: 1 }
11 | Rectangle { color: false ? 'green' : "magenta"; width: 4; height: 4 }
12 | }
13 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/FontWeights.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property var weights: ["Thin", "ExtraLight", "Light", "Normal", "Medium", "DemiBold", "Bold", "ExtraBold", "Black"]
5 | property alias repeater: repeater_
6 | Column {
7 | Repeater {
8 | id: repeater_
9 | model: weights.length
10 | Text {
11 | text: weights[index]
12 | font.weight: eval("Font." + text)
13 | }
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/tests/.eslintrc:
--------------------------------------------------------------------------------
1 | env:
2 | jasmine: true
3 | globals:
4 | loadQmlFile: true
5 | prefixedQmlLoader: true
6 | loadQml: true
7 | setupDivElement: true
8 | customMatchers: true
9 | sendEvent: true
10 | Qt: true
11 | rules:
12 | block-scoped-var: 2
13 | no-var: 0
14 | prefer-arrow-callback: 0
15 | prefer-rest-params: 0
16 | prefer-spread: 0
17 | prefer-template: 0
18 | object-shorthand: 0
19 | no-invalid-this: 0
20 | no-unused-vars: 0
21 |
--------------------------------------------------------------------------------
/src/engine/AutoLoader.js:
--------------------------------------------------------------------------------
1 | window.addEventListener("load", () => {
2 | const metaTags = document.getElementsByTagName("body");
3 | for (let i = 0; i < metaTags.length; ++i) {
4 | const metaTag = metaTags[i];
5 | const source = metaTag.getAttribute("data-qml");
6 | if (source) {
7 | QmlWeb.qmlEngine = new QmlWeb.QMLEngine();
8 | QmlWeb.qmlEngine.loadFile(source);
9 | QmlWeb.qmlEngine.start();
10 | break;
11 | }
12 | }
13 | });
14 |
--------------------------------------------------------------------------------
/src/engine/jsparser.js:
--------------------------------------------------------------------------------
1 | function importJavascriptInContext(contextSetter, $context) {
2 | /* Set the QmlWeb.executionContext so that any internal calls to Qt.include
3 | * will have the proper context */
4 | const oldExecutionContext = QmlWeb.executionContext;
5 | QmlWeb.executionContext = $context;
6 | contextSetter($context);
7 | QmlWeb.executionContext = oldExecutionContext;
8 | }
9 |
10 | QmlWeb.importJavascriptInContext = importJavascriptInContext;
11 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/BindingsRecursiveInit.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.2
2 |
3 | Item {
4 | width: 400
5 | property int intA: 10 / intB
6 | property int intB: 1+1
7 |
8 | onIntAChanged: launch()
9 |
10 | property var log: ""
11 | function launch() {
12 | // perform something expensive and important,
13 | // where intA value really matters
14 | log = log + "Fly to planet N" + intA + "!";
15 | }
16 |
17 | Text {
18 | text: log
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/tests/QtQml/qml/ConnectionsConnections.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | id: root
5 | property int value: 0
6 |
7 | property int test_value: 0
8 |
9 | property alias new_target: _new_target
10 | Item {
11 | id: _new_target
12 | property int value: 0
13 | }
14 |
15 | property alias connections: _connections
16 | Connections {
17 | id: _connections
18 | onValueChanged: {
19 | root.test_value++
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/tests/QtTest/qml/TestCaseSimple.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.7
2 | import QtTest 1.1
3 |
4 | TestCase {
5 | name: "Simple"
6 |
7 | function test_one() {
8 | compare(1 + 2, 2 + 1, "1 + 2 = 2 + 1")
9 | }
10 |
11 | function test_two() {
12 | compare("abc", "ab" + "c", '"abc", "ab" + "c"')
13 | }
14 |
15 | function test_fail() {
16 | compare(0 + 2, 3, "0 + 2 = 3")
17 | }
18 |
19 | function test_skip() {
20 | skip("Let's skip")
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/BasicCreateQmlObject.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.2
2 |
3 | Item {
4 | id: item
5 | property string contextVar: "42";
6 |
7 | Component.onCompleted: {
8 | var q = Qt.createQmlObject(
9 | "import QtQuick 2.2\nimport QtQuick.Controls 1.0\n Rectangle { color: 'green'; width: 320; height: 32; property var q: 22; Text{ color:'gold'; text: 'variable from context = ' + contextVar} }",
10 | item,
11 | "inlinecode1"
12 | );
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/tests/QtQuick.Layouts/qml/ColumnLayoutImplicitSize.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Layouts 1.0
3 |
4 | ColumnLayout {
5 | spacing: 0
6 |
7 | Rectangle {
8 | color: "red"
9 | implicitHeight: 20
10 | implicitWidth: 30
11 | }
12 | Rectangle {
13 | color: "green"
14 | Layout.preferredHeight: 21
15 | implicitWidth: 25
16 | }
17 | Rectangle {
18 | color: "blue"
19 | implicitHeight: 23
20 | implicitWidth: 31
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/tests/QtQuick.Layouts/qml/RowLayoutImplicitSize.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Layouts 1.0
3 |
4 | RowLayout {
5 | spacing: 0
6 |
7 | Rectangle {
8 | color: "red"
9 | implicitHeight: 20
10 | implicitWidth: 30
11 | }
12 | Rectangle {
13 | color: "green"
14 | implicitHeight: 25
15 | Layout.preferredWidth: 21
16 | }
17 | Rectangle {
18 | color: "blue"
19 | implicitHeight: 23
20 | implicitWidth: 31
21 | }
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/tests/QtQuick/Behavior.js:
--------------------------------------------------------------------------------
1 | describe("QtQuick.Behavior", function() {
2 | setupDivElement();
3 | var load = prefixedQmlLoader("QtQuick/qml/Behavior");
4 |
5 | it("Basic", function(done) {
6 | var qml = load("Basic", this.div);
7 | expect(qml.gotX).toBe(false);
8 | expect(qml.gotY).toBe(false);
9 | setTimeout(function() {
10 | expect(qml.gotX).toBe(true);
11 | expect(qml.gotY).toBe(false);
12 | done();
13 | }, 200);
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/RepeaterPropertyRoleNameConflict.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property alias repeater: _repeater
5 | Repeater {
6 | id: _repeater
7 | model: ListModel {
8 | ListElement {
9 | roleName: "foo"
10 | }
11 | }
12 | Item {
13 | property var roleName: "bar"
14 | property var implicitRoleNameReference: roleName
15 | property var explicitRoleNameReference: model.roleName
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/tests/Render/Async/ColorAnimation.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | width: 10
5 | height: 10
6 | Rectangle {
7 | width: 10
8 | height: 10
9 | color: 'black'
10 |
11 | ColorAnimation on color {
12 | from: 'red'; to: 'green'; duration: 50
13 | running: true
14 | }
15 | }
16 |
17 | Timer {
18 | interval: 100
19 | running: typeof window !== 'undefined'
20 | onTriggered: window.onTestLoad()
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/tests/QMLEngine/javascript.js:
--------------------------------------------------------------------------------
1 | describe("QMLEngine.javascript", function() {
2 | setupDivElement();
3 | var load = prefixedQmlLoader("QMLEngine/qml/Javascript");
4 |
5 | it("can be parsed", function() {
6 | load("BasicSyntax", this.div);
7 | });
8 |
9 | it("can parse regexp", function() {
10 | var qml = load("Regexp", this.div);
11 | expect("toto".match(qml.reg)).toBe(null);
12 | expect("4242/firstsecond".match(qml.reg)).not.toBe(null);
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/tests/QtQuick/Text.js:
--------------------------------------------------------------------------------
1 | describe("QtQuick.Text", function() {
2 | setupDivElement();
3 |
4 | var load = prefixedQmlLoader("QtQuick/qml/Text");
5 | it("implicit size", function() {
6 | var qml = load("ImplicitSize", this.div);
7 | expect(qml.text_item.width).toBeGreaterThan(0);
8 | });
9 |
10 | it("default wrap mode", function() {
11 | var qml = load("WrapMode", this.div);
12 | expect(qml.dom.children[0].style.whiteSpace).toBe("pre");
13 | });
14 | });
15 |
16 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/PropertyChanges.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_PropertyChanges extends QtQml_QtObject {
3 | static properties = {
4 | target: "QtObject",
5 | explicit: "bool",
6 | restoreEntryValues: { type: "bool", initialValue: true }
7 | };
8 |
9 | constructor(meta) {
10 | super(meta);
11 |
12 | this.$actions = [];
13 | }
14 | $setCustomData(property, value) {
15 | this.$actions.push({ property, value });
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/BehaviorBasic.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property bool gotX
5 | property bool gotY
6 |
7 | Behavior on x {
8 | NumberAnimation {
9 | duration: 200
10 | }
11 | }
12 | Behavior on y {
13 | enabled: false
14 | NumberAnimation {
15 | duration: 200
16 | }
17 | }
18 | onXChanged: if (x > 0 && x < 1) gotX = true;
19 | onYChanged: if (y > 0 && y < 1) gotY = true;
20 | Component.onCompleted: x = y = 1;
21 | }
22 |
--------------------------------------------------------------------------------
/tests/Render/Simple/RectanglesGrid.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | color: 'white'
5 | width: 20
6 | height: 15
7 | Grid {
8 | columns: 3
9 | spacing: 2
10 | Rectangle { color: 'red'; width: 5; height: 5 }
11 | Rectangle { color: 'green'; width: 6; height: 3 }
12 | Rectangle { color: 'blue'; width: 2; height: 6 }
13 | Rectangle { color: 'cyan'; width: 1; height: 1 }
14 | Rectangle { color: 'black'; width: 4; height: 4 }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/modules/QtQuick.Controls.2/ApplicationWindow.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Controls_2_ApplicationWindow extends QtQuick_Window_Window {
3 | static versions = /^2\./;
4 | static properties = {
5 | font: "font",
6 | activeFocusControl: "Control",
7 | background: "Item",
8 | contentData: "list",
9 | //contentItem: "ContentItem", // TODO
10 | footer: "Item",
11 | header: "Item",
12 | overlay: "Item"
13 | };
14 |
15 | // TODO
16 | }
17 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/BasicSignalDisconnectOnDelete.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.2
2 |
3 | Item {
4 | id: item
5 | property variant child
6 |
7 | function foo() {
8 | console.log("colour changed");
9 | }
10 |
11 | Item {
12 | id: some_child
13 | }
14 |
15 | function create_object() {
16 | return Qt.createQmlObject(
17 | "import QtQuick 2.2\nRectangle { color: 'green'; width: 320; height: 32; }",
18 | some_child,
19 | "inlinecode1"
20 | );
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ScopeSafeFromLocals.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property var a: 'a_init_value'
5 | property var b: 'b_init_value'
6 | property var c: ''
7 | property var d
8 | property var p
9 | property var q
10 |
11 |
12 | function foo() {
13 | a = '333';
14 | var b = '3local';
15 | var c = b;
16 | d = b;
17 | p = q = 17;
18 | }
19 |
20 | Component.onCompleted: foo()
21 |
22 | Text {
23 | text: 'a=' + a + ' b=' + b;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/TimerRunning.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.5
2 | Item {
3 | id: root
4 |
5 | function start() {
6 | success_timer.running = true
7 | fail_timer.start()
8 | }
9 |
10 | Timer {
11 | id: fail_timer
12 | interval: 500
13 | onTriggered: {
14 | root.yield(false)
15 | }
16 | }
17 |
18 | Timer {
19 | id: success_timer
20 | interval: 250
21 | onTriggered: {
22 | fail_timer.stop()
23 | root.yield(true)
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/tests/QtQuick/Font.js:
--------------------------------------------------------------------------------
1 | describe("QtQuick.Font", function() {
2 | setupDivElement();
3 | var load = prefixedQmlLoader("QtQuick/qml/Font");
4 |
5 | it("Weights", function() {
6 | var qml = load("Weights", this.div);
7 | for (var i = 0; i < 9; ++i) {
8 | /* Special case for "Normal", as it just unsets the fontWeight style */
9 | expect(qml.repeater.itemAt(i).dom.children[0].style.fontWeight)
10 | .toBe("" + (i !== 3 ? (i + 1) * 100 : ""));
11 | }
12 | });
13 | });
14 |
--------------------------------------------------------------------------------
/tests/Render/Simple/AnchorsCenterAndFill2.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | color: "green"
5 | width: 30; height: 30
6 |
7 | Rectangle {
8 | anchors.centerIn: parent
9 | color: "blue"
10 | width: 10
11 | height: 10
12 |
13 | Item {
14 | anchors.fill: parent
15 | anchors.margins: 2
16 |
17 | Rectangle {
18 | anchors.centerIn: parent
19 | width: 8
20 | height: 8
21 | color: "red"
22 | }
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/tests/Render/Simple/ScaleRectangleOrigin.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | color: 'green'
5 | width: 60; height: 50
6 |
7 | Rectangle {
8 | width: 50; height: 50
9 | color: "#00f"
10 | transform: Scale {
11 | xScale: 0.5
12 | yScale: 0.8
13 | }
14 | }
15 |
16 | Rectangle {
17 | width: 50; height: 50
18 | color: "red"
19 | transform: Scale {
20 | origin.x: 0
21 | origin.y: 0
22 | xScale: 0.4
23 | yScale: 0.3
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/modules/QtTest/SignalSpy.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtTest_SignalSpy extends QtQuick_Item {
3 | static versions = /^1\./;
4 | static properties = {
5 | count: "int",
6 | signalArguments: "list",
7 | signalName: "string",
8 | target: "var",
9 | valid: "bool"
10 | };
11 |
12 | // TODO
13 |
14 | clear() {
15 | this.count = 0;
16 | this.signalArguments.length = 0;
17 | //this.valid = false;
18 | }
19 |
20 | /*
21 | wait(timeout = 5000) {
22 | }
23 | */
24 | }
25 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/PropertiesAliasChanged.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Controls 1.1
3 |
4 | Item {
5 | property alias childX: child.x
6 |
7 | Item {
8 | id: child
9 | x: 125
10 | }
11 |
12 | property string log: ""
13 | onChildXChanged: log = log + "childX changed to "+childX+"!"
14 |
15 | function go() {
16 | child.x = 44;
17 | }
18 |
19 | Column {
20 | Text {
21 | text: log
22 | }
23 | Button {
24 | text: "go!"
25 | onClicked: go();
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/tests/QMLEngine/basepath/test.js:
--------------------------------------------------------------------------------
1 | describe("QMLEngine.basepath", function() {
2 | setupDivElement();
3 | var webroot = "/base/tests/QMLEngine/basepath/";
4 |
5 | // this checks the case of evalling properties during component init
6 | // when this component is imported from another directory
7 | // followed by loading of component in current directory
8 | it("engine.$basePath is not corrupted after recursive properties eval",
9 | function() {
10 | var qml = loadQmlFile(webroot + "test.qml", this.div);
11 | }
12 | );
13 | });
14 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/BasicResolvedUrl.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property var current: Qt.resolvedUrl('.')
5 | property var inner1: Qt.resolvedUrl('foo/bar')
6 | property var inner2: Qt.resolvedUrl('foo/bar/')
7 | property var inner3: Qt.resolvedUrl('foo//bar/../foo////bar/./../lol/x../..s/../..')
8 | property var outer: Qt.resolvedUrl('../..')
9 | property var full: Qt.resolvedUrl('http://example.com/bar')
10 | property var absolute: Qt.resolvedUrl('/foo/bar')
11 | property var aboutBlank: Qt.resolvedUrl("about:blank")
12 | }
13 |
--------------------------------------------------------------------------------
/tests/Render/Async/NumberAnimationAutorun.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | width: 20
5 | height: 10
6 |
7 | Rectangle {
8 | color: "blue"
9 | width: 10
10 | height: 10
11 |
12 | NumberAnimation on x {
13 | from: 0; to: 10; duration: 50
14 | }
15 |
16 | Component.onCompleted: color = x > 0 ? 'red' : 'green'
17 | }
18 |
19 | Timer {
20 | interval: 100
21 | running: typeof window !== 'undefined'
22 | onTriggered: window.onTestLoad()
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/ParallelAnimationRunning.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | width: 900
5 | height: 300
6 |
7 | Row {
8 | Rectangle { id: rectA }
9 | Rectangle { id: rectB }
10 | Rectangle { id: rectC }
11 | }
12 |
13 | ParallelAnimation {
14 | id:ani
15 | ColorAnimation { target: rectA; property: "color"; to: 'red'; duration: 100 }
16 | ColorAnimation { target: rectB; property: "color"; to: 'green'; duration: 100 }
17 | ColorAnimation { target: rectC; property: "color"; to: 'blue'; duration: 100 }
18 | }
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/src/modules/QtMultimedia/VideoOutput.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtMultimedia_VideoOutput extends QtQuick_Item {
3 | static versions = /^5\./;
4 | static enums = {
5 | VideoOutput: { PreserveAspectFit: 0, PreserveAspectCrop: 1, Stretch: 2 }
6 | };
7 | static properties = {
8 | autoOrientation: "bool",
9 | contentRect: "rect",
10 | fillMode: "enum", // VideoOutput.PreserveAspectFit
11 | filters: "list",
12 | orientation: "int",
13 | source: "variant",
14 | sourceRect: "rect"
15 | };
16 |
17 | // TODO: impl
18 | }
19 |
--------------------------------------------------------------------------------
/tests/Render/Async/NumberAnimation.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | width: 20
5 | height: 10
6 |
7 | Rectangle {
8 | color: "blue"
9 | width: 10
10 | height: 10
11 |
12 | NumberAnimation on x {
13 | from: 0; to: 10; duration: 50
14 | running: true
15 | }
16 |
17 | Component.onCompleted: color = x > 0 ? 'red' : 'green'
18 | }
19 |
20 | Timer {
21 | interval: 100
22 | running: typeof window !== 'undefined'
23 | onTriggered: window.onTestLoad()
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/GradientStop.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_GradientStop extends QtQml_QtObject {
3 | static properties = {
4 | color: { type: "color", initialValue: "black" },
5 | position: { type: "real", initialValue: 0.0 },
6 | };
7 |
8 | constructor(meta) {
9 | super(meta);
10 |
11 | this.$item = this.$parent.$item;
12 | this.colorChanged.connect(this, this.onUpdate);
13 | this.positionChanged.connect(this, this.onUpdate);
14 | }
15 |
16 | onUpdate() {
17 | this.$parent.$onGradientStopChanged();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/PropertiesAliasChangedBack.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Controls 1.1
3 |
4 | Item {
5 | property alias thechild: child
6 | property alias childData: child.somedata
7 |
8 | Rectangle {
9 | id: child
10 | x: somedata[0]
11 | y: somedata[1]
12 | property var somedata: [0,0]
13 |
14 | color: "red"; width: 64; height: 64
15 | }
16 |
17 | function go() {
18 | childData[0] = 100;
19 | childDataChanged();
20 | }
21 |
22 | Column {
23 | Button {
24 | text: "go!"
25 | onClicked: go();
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/SequentialAnimationRunning.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | id: rect
5 | width: 300
6 | height: 300
7 | property Item area: mouse_area
8 | SequentialAnimation {
9 | id:ani
10 | ColorAnimation { target: rect; property: "color"; to: 'red'; duration: 100 }
11 | ColorAnimation { target: rect; property: "color"; duration: 100 }
12 | ColorAnimation { target: rect; property: "color"; to: 'green'; duration: 100 }
13 | }
14 | MouseArea{
15 | id: mouse_area
16 | onClicked: ani.running = !ani.running
17 | anchors.fill: parent;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/tests/QtQuick/PropertyAnimation.js:
--------------------------------------------------------------------------------
1 | describe("QtQuick.PropertyAnimation", function() {
2 | setupDivElement();
3 | var load = prefixedQmlLoader("QtQuick/qml/PropertyAnimation");
4 |
5 | it("Loads", function() {
6 | load("Loads", this.div);
7 | });
8 | xit("FailsToLoad", function() {
9 | var exception = null;
10 | try {
11 | load("FailsToLoad", this.div);
12 | } catch (err) {
13 | exception = err;
14 | }
15 | expect(exception).not.toBe(null);
16 | expect(exception.message).toContain(
17 | "Cannot assign to non-existent default property");
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/PropertiesChangedSignal.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | property int result: 0
5 |
6 | property int value: 1
7 | onValueChanged: result += 2
8 |
9 | width: 40
10 | height: 41
11 |
12 | property string foo: 'foo'
13 | property string bar: 'bar'
14 |
15 | onWidthChanged: result += 4
16 | onHeightChanged: result += 8
17 | onFooChanged: result += 16
18 | onBarChanged: result += 32
19 |
20 | Component.onCompleted: {
21 | result += 1;
22 | width = 41;
23 | height = 41;
24 | foo = 'foo';
25 | bar = '';
26 | bar = 'bar';
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/tests/Render/Fuzzy/RectanglesOpacity.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | // Fuzzy because opacity color rounding could differ between implementations
4 |
5 | Rectangle {
6 | width: 100
7 | height: 100
8 | color: '#fff'
9 | Item {
10 | opacity: 0.5
11 | Rectangle {
12 | color: '#0f0'
13 | width: 50
14 | height: 50
15 | }
16 | Rectangle {
17 | color: '#ff0000'
18 | width: 50;
19 | height: 50
20 | x: 25; y: 25
21 | }
22 | Rectangle {
23 | color: '#00f'
24 | width: 50;
25 | height: 50
26 | x: 70; y: 20
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/engine/QMLList.js:
--------------------------------------------------------------------------------
1 | function QMLList(meta) {
2 | const list = [];
3 | if (meta.object instanceof Array) {
4 | for (const i in meta.object) {
5 | list.push(QmlWeb.construct({
6 | object: meta.object[i],
7 | parent: meta.parent,
8 | context: meta.context
9 | }));
10 | }
11 | } else if (meta.object instanceof QmlWeb.QMLMetaElement) {
12 | list.push(QmlWeb.construct({
13 | object: meta.object,
14 | parent: meta.parent,
15 | context: meta.context
16 | }));
17 | }
18 |
19 | return list;
20 | }
21 | QMLList.plainType = true;
22 | QmlWeb.qmlList = QMLList;
23 |
--------------------------------------------------------------------------------
/tests/QtQml/qml/BindingTwoWay.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.5
2 |
3 | Item {
4 | property alias targetValue: targetItem.value
5 | property alias sourceValue: sourceItem.value
6 | property bool when: true
7 |
8 | id: root
9 |
10 | Item {
11 | property int value: 0
12 | id: sourceItem
13 | }
14 |
15 | Item {
16 | property int value: 0
17 | id: targetItem
18 | }
19 |
20 | Binding {
21 | target: targetItem; property: "value"; value: sourceItem.value; when: root.when
22 | }
23 |
24 | Binding {
25 | target: sourceItem; property: "value"; value: targetItem.value; when: root.when
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/tests/Render/Simple/AnchorsCenterAndFill.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | color: "white"
5 | width: 16
6 | height: 16
7 | Rectangle {
8 | id: red
9 | color: "red"
10 | anchors.centerIn: parent
11 | width: 8
12 | height: 8
13 | Rectangle {
14 | color: "blue"
15 | anchors.horizontalCenter: parent.horizontalCenter
16 | anchors.top: parent.top
17 | anchors.bottom: parent.bottom
18 | width: 4
19 | }
20 | }
21 | Rectangle {
22 | anchors.verticalCenter: parent.verticalCenter
23 | width: parent.width
24 | height: 4
25 | color: "grey"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/tests/Render/Simple/ZeroOpacityLayout.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Row {
4 | width: 30
5 | height: 20
6 | Rectangle {
7 | width: 10
8 | height: parent.height
9 | color: 'red'
10 | opacity: 0
11 | }
12 | Rectangle {
13 | width: 10
14 | height: parent.height
15 | color: 'black'
16 | }
17 | Column {
18 | height: parent.height
19 | width: 10
20 | Rectangle {
21 | height: 10
22 | width: parent.width
23 | color: 'red'
24 | opacity: 0
25 | }
26 | Rectangle {
27 | height: 10
28 | width: parent.width
29 | color: 'black'
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/tests/QtQuick/Item.js:
--------------------------------------------------------------------------------
1 | describe("QtQuick.Item", function() {
2 | setupDivElement();
3 | var load = prefixedQmlLoader("QtQuick/qml/Item");
4 |
5 | it("Empty", function() {
6 | load("Empty", this.div);
7 | var div = this.div.children[0];
8 | expect(div.innerHTML).toBe("");
9 | expect(div.style.backgroundColor).toBe("");
10 | });
11 | it("Size", function() {
12 | load("Size", this.div);
13 | var div = this.div.children[0];
14 | expect(div.offsetWidth).toBe(200);
15 | expect(div.offsetHeight).toBe(100);
16 | expect(div.clientWidth).toBe(200);
17 | expect(div.clientHeight).toBe(100);
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/tests/Render/Fuzzy/RectanglesAlpha.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | // Fuzzy because opacity color rounding could differ between implementations
4 |
5 | Rectangle {
6 | width: 100
7 | height: 100
8 | color: '#fff'
9 | Item {
10 | opacity: 0.9
11 | Rectangle {
12 | color: '#6000ff00'
13 | width: 50
14 | height: 50
15 | opacity: 0.5
16 | }
17 | Rectangle {
18 | color: '#9000ff'
19 | width: 50;
20 | height: 50
21 | x: 25; y: 25
22 | }
23 | Rectangle {
24 | color: Qt.rgba(1, 0.4, 0.4, 0.9)
25 | width: 50;
26 | height: 50
27 | x: 70; y: 20
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/ListModel.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.5
2 |
3 | ListModel {
4 | id: fruitModel
5 |
6 | ListElement {
7 | name: "Apple"
8 | cost: 2.45
9 | attributes: [
10 | ListElement { description: "Core" },
11 | ListElement { description: "Deciduous" }
12 | ]
13 | }
14 | ListElement {
15 | name: "Orange"
16 | cost: 3.25
17 | attributes: [
18 | ListElement { description: "Citrus" }
19 | ]
20 | }
21 | ListElement {
22 | name: "Banana"
23 | cost: 1.95
24 | attributes: [
25 | ListElement { description: "Tropical" },
26 | ListElement { description: "Seedless" }
27 | ]
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/ShaderEffect.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_ShaderEffect extends QtQuick_Item {
3 | static enums = {
4 | ShaderEffect: {
5 | NoCulling: 0, BackFaceCulling: 1, FrontFaceCulling: 2,
6 | Compiled: 0, Uncompiled: 1, Error: 2
7 | }
8 | };
9 | static properties = {
10 | blending: { type: "bool", initialValue: true },
11 | cullMode: "enum", // ShaderEffect.NoCulling
12 | fragmentShader: "string",
13 | log: "string",
14 | mesh: "var",
15 | status: { type: "enum", initialValue: 1 }, // ShaderEffect.Uncompiled
16 | supportsAtlasTextures: "bool",
17 | vertexShader: "string"
18 | };
19 |
20 | // TODO
21 | }
22 |
--------------------------------------------------------------------------------
/src/modules/QtQuick.Controls.2/SwipeView.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Controls_2_SwipeView extends QtQuick_Controls_2_Container {
3 | static versions = /^2\./;
4 | static properties = {
5 | horizontal: "bool",
6 | interactive: "bool",
7 | orientation: "enum",
8 | vertical: "bool"
9 | };
10 |
11 | // TODO
12 |
13 | layoutChildren() {
14 | let pos = 0;
15 | for (let i = 0; i < this.children.length; i++) {
16 | const child = this.children[i];
17 | if (!child.visible) continue;
18 | child.height = this.height;
19 | child.width = this.width;
20 | child.x = pos;
21 | pos += child.width;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/SequentialAnimationPaused.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | id: rect
5 | width: 300
6 | height: 300
7 | property Item area: mouse_area
8 | SequentialAnimation {
9 | id:ani
10 | ColorAnimation { target: rect; property: "color"; to: 'red'; duration: 100 }
11 | ColorAnimation { target: rect; property: "color"; duration: 100 }
12 | ColorAnimation { target: rect; property: "color"; to: 'green'; duration: 100 }
13 | }
14 | MouseArea{
15 | id: mouse_area
16 | onClicked: {
17 | if(ani.running){
18 | ani.paused = !ani.paused
19 | }else{
20 | ani.running = true;
21 | }
22 | }
23 | anchors.fill: parent;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/StateWhen.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | Item {
3 | id: root
4 | property int value: 10
5 | property int stateTrigger: 0
6 |
7 | states: [
8 | State {
9 | name: "state1"
10 | PropertyChanges {
11 | target: root
12 | value: 20
13 | }
14 | when: root.stateTrigger == 1
15 | },
16 | State {
17 | name: "state2"
18 | PropertyChanges {
19 | target: root
20 | value: 30
21 | }
22 | when: root.stateTrigger == 2
23 | }
24 | ]
25 |
26 | function start(){
27 | yield()
28 | stateTrigger = 1
29 | yield()
30 | stateTrigger = 2
31 | yield()
32 | stateTrigger = 3
33 | yield()
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/examples/embed.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | QML Embed Example
5 |
12 |
13 |
14 |
15 |
16 |
17 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/BindingsRecursiveInit2.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.2
2 | import QtQuick.Controls 1.0
3 |
4 | Item {
5 | width: 800
6 | property int intA: 10 / intB + intD
7 | property int intB: intC
8 | property int intC: 1
9 | property int intD: 0
10 |
11 | onIntAChanged: launch()
12 |
13 | property var log: ""
14 | function launch() {
15 | // perform something expensive and important,
16 | // where intA value really matters
17 | log = log + "Fly to planet N" + intA + "!";
18 | }
19 |
20 | function retarget() {
21 | intD = 5;
22 | }
23 |
24 | Text {
25 | text: log
26 | }
27 |
28 | Button {
29 | y: 30
30 | text: "retarget!"
31 | onClicked: retarget()
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/modules/QtQuick.Particles/ParticleSystem.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Particles_ParticleSystem extends QtQuick_Item {
3 | static versions = /^2\./;
4 | static properties = {
5 | empty: "bool",
6 | particleStates: "list",
7 | paused: "bool",
8 | running: { type: "bool", initialValue: true }
9 | };
10 |
11 | // TODO
12 |
13 | pause() {
14 | this.paused = true;
15 | }
16 | reset() {
17 | // TODO
18 | }
19 | restart() {
20 | this.running = false;
21 | this.running = true;
22 | }
23 | resume() {
24 | this.paused = false;
25 | }
26 | start() {
27 | this.running = true;
28 | }
29 | stop() {
30 | this.running = false;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/IntValidator.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_IntValidator extends QtQml_QValidator {
3 | static properties = {
4 | bottom: { type: "int", initialValue: -2147483647 },
5 | top: { type: "int", initialValue: 2147483647 }
6 | };
7 |
8 | validate(string) {
9 | const regExp = /^(-|\+)?\s*[0-9]+$/;
10 |
11 | if (regExp.test(string.trim())) {
12 | const value = parseInt(string, 10);
13 | if (this.bottom <= value && this.top >= value) {
14 | return this.QValidator.Acceptable;
15 | } else if (string.length <= this.top.toString().length) {
16 | return this.QValidator.Intermediate;
17 | }
18 | }
19 | return this.QValidator.Invalid;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/modules/QmlWeb.Dom/DomStyle.js:
--------------------------------------------------------------------------------
1 | const styleProperties = {};
2 | for (const property in document.createElement("div").style) {
3 | styleProperties[property] = "string";
4 | }
5 |
6 | class QmlWeb_Dom_DomStyle extends QmlWeb.QObject {
7 | constructor(meta) {
8 | super(meta);
9 |
10 | this.updated = (new QmlWeb.Signal([], { obj: this })).signal;
11 | QmlWeb.createProperties(this, styleProperties);
12 | for (const propertyName in this.$properties) {
13 | const property = this.$properties[propertyName];
14 | property.changed.connect(this, newVal => {
15 | this.$parent.dom.style[propertyName] = newVal;
16 | this.updated();
17 | });
18 | }
19 | }
20 | }
21 |
22 | QmlWeb.DomStyle = QmlWeb_Dom_DomStyle;
23 |
--------------------------------------------------------------------------------
/tests/Render/Simple/RectangleBorderChildren.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.5
2 |
3 | Rectangle {
4 | width: 75
5 | height: 15
6 | border.width: 5
7 | border.color: 'grey'
8 | color: 'green'
9 |
10 | Rectangle {
11 | width: 10
12 | height: 10
13 | }
14 | Rectangle {
15 | width: 11
16 | height: 10
17 | x: 15
18 | border.color: 'red'
19 | }
20 | Rectangle {
21 | width: 10
22 | height: 12
23 | x: 30
24 | border.width: 2
25 | }
26 | Rectangle {
27 | // no width/heigth is set but border is set
28 | x: 45
29 | color: 'orange'
30 | border.width: 1
31 | }
32 | Rectangle {
33 | x: 60
34 | border.width: 0
35 | border.color: 'red'
36 | width: 10
37 | height: 10
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/Animator.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Animator extends QtQuick_Animation {
3 | static versions = /^2\./;
4 | static properties = {
5 | duration: { type: "int", initialValue: 250 },
6 | from: "real",
7 | target: "Item",
8 | to: "real"
9 | };
10 |
11 | constructor(meta) {
12 | super(meta);
13 |
14 | this.easing = new QmlWeb.QObject(this);
15 | QmlWeb.createProperties(this.easing, {
16 | type: { type: "enum", initialValue: this.Easing.Linear },
17 | amplitude: { type: "real", initialValue: 1 },
18 | overshoot: { type: "real", initialValue: 1.70158 },
19 | period: { type: "real", initialValue: 0.3 },
20 | bezierCurve: "list"
21 | });
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/tests/Render/Simple/RepeaterListModel.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | color: '#ff9'
5 | width: 25
6 | height: 25
7 |
8 | ListModel {
9 | id: list
10 | ListElement { my: 'blue' }
11 | ListElement { my: 'red' }
12 | ListElement { my: 'transparent' }
13 | ListElement { my: '#0f0' }
14 | ListElement { my: '#0ff' }
15 | }
16 |
17 | Repeater {
18 | model: list
19 | Rectangle {
20 | color: my
21 | width: 5
22 | height: 5
23 | x: 5 * index
24 | y: 5 * index
25 | }
26 | }
27 | Repeater {
28 | model: list
29 | delegate: Rectangle {
30 | color: my
31 | width: 5
32 | height: 5
33 | x: 5 * index
34 | y: 20 - 5 * index
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/engine/getset.js:
--------------------------------------------------------------------------------
1 | /* eslint accessor-pairs: 0 */
2 |
3 | function setupGetter(obj, propName, func) {
4 | Object.defineProperty(obj, propName, {
5 | get: func,
6 | configurable: true,
7 | enumerable: true
8 | });
9 | }
10 |
11 | function setupSetter(obj, propName, func) {
12 | Object.defineProperty(obj, propName, {
13 | set: func,
14 | configurable: true,
15 | enumerable: false
16 | });
17 | }
18 |
19 | function setupGetterSetter(obj, propName, getter, setter) {
20 | Object.defineProperty(obj, propName, {
21 | get: getter,
22 | set: setter,
23 | configurable: true,
24 | enumerable: false
25 | });
26 | }
27 |
28 | QmlWeb.setupGetter = setupGetter;
29 | QmlWeb.setupSetter = setupSetter;
30 | QmlWeb.setupGetterSetter = setupGetterSetter;
31 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/StateBinding.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | Item {
3 | id: root
4 | property int stateTrigger: 0
5 | property int variable: 5
6 | property int value: 10 + variable
7 |
8 | states: [
9 | State {
10 | name: "state1"
11 | PropertyChanges {
12 | target: root
13 | value: 20 + variable
14 | }
15 | when: root.stateTrigger == 1
16 | },
17 | State {
18 | name: "state2"
19 | PropertyChanges {
20 | target: root
21 | value: 30 + variable
22 | }
23 | when: root.stateTrigger == 2
24 | }
25 | ]
26 |
27 | function start(){
28 | yield()
29 | stateTrigger = 1
30 | yield()
31 | stateTrigger = 2
32 | yield()
33 | stateTrigger = 3
34 | yield()
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/modules/QtQuick.Controls.2/Control.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Controls_2_Control extends QtQuick_Item {
3 | static versions = /^2\./;
4 | static properties = {
5 | availableHeight: "real",
6 | availableWidth: "real",
7 | background: "Item",
8 | bottomPadding: "real",
9 | contentItem: "Item",
10 | focusPolicy: "enum",
11 | focusReason: "enum",
12 | font: "font",
13 | hoverEnabled: "bool",
14 | hovered: "bool",
15 | leftPadding: "real",
16 | locale: "Locale",
17 | mirrored: "bool",
18 | padding: "real",
19 | palette: "palette",
20 | rightPadding: "real",
21 | spacing: "real",
22 | topPadding: "real",
23 | visualFocus: "bool",
24 | wheelEnabled: "bool"
25 | };
26 |
27 | // TODO
28 | }
29 |
--------------------------------------------------------------------------------
/tests/qmlweb.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const path = require("path");
3 |
4 | function include(file, window) {
5 | const document = window.document;
6 | const exports = global;
7 | // eslint-disable-next-line no-eval
8 | eval(fs.readFileSync(path.join(__dirname, file), "utf-8"));
9 | }
10 |
11 | require("jsdom").env("", (err, window) => {
12 | include("../lib/qmlweb.js", window);
13 | include("../lib/qmlweb.parser.js", window);
14 |
15 | const document = window.document;
16 | const file = process.argv[process.argv.length - 1];
17 | const div = document.createElement("div");
18 | document.body.appendChild(div);
19 | var engine = new QmlWeb.QMLEngine(div, {});
20 | QmlWeb.urlContentCache[file] = fs.readFileSync(file, "utf-8");
21 | engine.loadFile(file);
22 | engine.start();
23 | });
24 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/Column.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Column extends QtQuick_Positioner {
3 | layoutChildren() {
4 | let curPos = this.padding;
5 | let maxWidth = 0;
6 | for (let i = 0; i < this.children.length; i++) {
7 | const child = this.children[i];
8 | if (!child.visible || !child.width || !child.height) {
9 | continue;
10 | }
11 | maxWidth = child.width > maxWidth ? child.width : maxWidth;
12 | child.y = curPos + this.padding;
13 | if (this.padding > 0) child.x = this.padding;
14 | curPos += child.height + this.spacing;
15 | }
16 | this.implicitWidth = maxWidth + this.padding * 2;
17 | this.implicitHeight = curPos - this.spacing + this.padding;
18 | // We want no spacing at the bottom side
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportJavascriptScope.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import "importTestSimple.js" as Imported
3 |
4 | Item {
5 | property alias component: _component
6 | property alias component2: _component2
7 | property alias loader: _loader
8 | property alias repeater: _repeater
9 |
10 | function importedColor() {
11 | return Imported.importedColor;
12 | }
13 | function setImportedColor(color) {
14 | return Imported.importedColor = color;
15 | }
16 |
17 | ImportJavascript {
18 | id: _component
19 | }
20 | ImportJavascript {
21 | id: _component2
22 | }
23 |
24 | Repeater {
25 | id: _repeater
26 | model: 2
27 | ImportJavascript {
28 | }
29 | }
30 |
31 | Loader {
32 | id: _loader
33 | source: "ImportJavascript.qml"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/tests/failingTests.js:
--------------------------------------------------------------------------------
1 | window.failingTests = {
2 | Render: {
3 | Simple: [
4 | "RectangleImplicitSize"
5 | ]
6 | },
7 | QMLEngine: {
8 | basic: [
9 | "SignalDisconnect"
10 | ],
11 | imports: [
12 | "Qmldir singleton"
13 | ],
14 | scope: [
15 | "object id should override same-named property of base object"
16 | ]
17 | },
18 | QtQml: {
19 | Binding: [
20 | "binding undefined var"
21 | ]
22 | },
23 | QtQuick: {
24 | Timer: [
25 | "can roughly set short intervals" // flaky
26 | ],
27 | Repeater: [
28 | "handle delegate property and role name conflict"
29 | ]
30 | },
31 | Initialize: {
32 | QtQuick: [
33 | "Translate",
34 | "Scale",
35 | "Rotation",
36 | "Font"
37 | ]
38 | }
39 | };
40 |
--------------------------------------------------------------------------------
/src/modules/QtQuick.Controls.2/AbstractButton.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Controls_2_AbstractButton extends QtQuick_Controls_2_Control {
3 | static versions = /^2\./;
4 | static properties = {
5 | action: "Action",
6 | autoExclusive: "bool",
7 | checkable: "bool",
8 | checked: "bool",
9 | display: "enum",
10 | // icon is defined manually
11 | down: "bool",
12 | indicator: "Item",
13 | pressed: "bool",
14 | text: "string"
15 | };
16 |
17 | constructor(meta) {
18 | super(meta);
19 |
20 | this.icon = new QmlWeb.QObject(this);
21 | QmlWeb.createProperties(this.icon, {
22 | name: "string",
23 | source: "url",
24 | width: "int",
25 | height: "int",
26 | color: "color"
27 | });
28 |
29 | // TODO
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/tests/Render/Simple/AnchorsSides.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | color: "white"
5 | width: 16
6 | height: 16
7 |
8 | Rectangle {
9 | color: "orange"
10 | width: 8
11 | height: 8
12 | anchors {
13 | left: parent.left
14 | bottom: parent.bottom
15 | }
16 | }
17 | Rectangle {
18 | color: "green"
19 | width: 6
20 | height: 6
21 | anchors {
22 | left: parent.left
23 | top: parent.top
24 | }
25 | }
26 | Rectangle {
27 | color: "cyan"
28 | width: 8
29 | height: 8
30 | anchors {
31 | right: parent.right
32 | top: parent.top
33 | }
34 | }
35 | Rectangle {
36 | color: "red"
37 | width: 6
38 | height: 6
39 | anchors {
40 | right: parent.right
41 | bottom: parent.bottom
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/RepeaterCompletedDestruction.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | id: root
5 |
6 | property int internal_created
7 | property int internal_destroyed
8 |
9 | Repeater {
10 | id: repeater
11 | Item {
12 | Repeater {
13 | model: 1
14 | Rectangle {
15 | Component.onCompleted: {
16 | root.internal_created++
17 | }
18 | Component.onDestruction: {
19 | root.internal_destroyed++
20 | }
21 | }
22 | }
23 | }
24 | }
25 |
26 | Component.onCompleted: {
27 | repeater.model = 1
28 | repeater.model = 0
29 | repeater.model = 2
30 | repeater.model = 0
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/tests/QtQml/Connections.js:
--------------------------------------------------------------------------------
1 | describe("QtQml.Connections", function() {
2 | setupDivElement();
3 | var load = prefixedQmlLoader("QtQml/qml/Connections");
4 |
5 | it("Connections default target is parent", function() {
6 | var qml = load("Connections", this.div);
7 | expect(qml.connections.target).toBe(qml);
8 | qml.value = 1;
9 | expect(qml.test_value).toBe(1);
10 | });
11 |
12 | it("Connections target change", function() {
13 | var qml = load("Connections", this.div);
14 | qml.connections.target = qml.new_target;
15 | qml.new_target.value = 1;
16 | expect(qml.test_value).toBe(1);
17 | });
18 |
19 | it("Connections null target", function() {
20 | var qml = load("Connections", this.div);
21 | qml.connections.target = null;
22 | qml.value = 1;
23 | expect(qml.test_value).toBe(0);
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/Behavior.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Behavior extends QtQml_QtObject {
3 | static properties = {
4 | animation: "Animation",
5 | enabled: { type: "bool", initialValue: true }
6 | };
7 | static defaultProperty = "animation";
8 |
9 | constructor(meta) {
10 | super(meta);
11 | this.$on = meta.object.$on;
12 |
13 | this.animationChanged.connect(this, this.$onAnimationChanged);
14 | this.enabledChanged.connect(this, this.$onEnabledChanged);
15 | }
16 | $onAnimationChanged(newVal) {
17 | newVal.target = this.$parent;
18 | newVal.property = this.$on;
19 | this.$parent.$properties[this.$on].animation = newVal;
20 | }
21 | $onEnabledChanged(newVal) {
22 | this.$parent.$properties[this.$on].animation = newVal
23 | ? this.animation
24 | : null;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/tests/Auto/Globals/tst_i18n.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtTest 1.0
3 |
4 | TestCase {
5 | name: "Internationalization"
6 |
7 | function test_qsTr() {
8 | compare("Foo", qsTr("Foo"))
9 | compare("Foo %n!", qsTr("Foo %n!"))
10 | compare("Foo 10!", qsTr("Foo %n!", "", 10))
11 | compare("Foo 25!", qsTr("Foo %n!", "x", 25))
12 | }
13 | function test_qsTrId() {
14 | compare("Foo", qsTrId("Foo"))
15 | compare("Foo %n!", qsTrId("Foo %n!"))
16 | compare("Foo 10!", qsTrId("Foo %n!", 10))
17 | compare("Foo 25!", qsTrId("Foo %n!", 25))
18 | }
19 | function test_qsTranslate() {
20 | compare("Foo", qsTranslate("Bar", "Foo"))
21 | compare("Foo %n!", qsTranslate("Bar", "Foo %n!"))
22 | compare("Foo 10!", qsTranslate("Bar", "Foo %n!", "", 10))
23 | compare("Foo 25!", qsTranslate("Bar", "Foo %n!", "x", 25))
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/tests/Render/Async/BorderImage.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | BorderImage {
4 | width: 20
5 | height: 20
6 | source: "bg.png"
7 | smooth: false
8 | border { left: 1; top: 3; right: 2; bottom: 3 }
9 | onStatusChanged: {
10 | if (typeof window !== 'undefined' && status !== BorderImage.Loading) {
11 | window.onTestLoad({ framesDelay: 2 });
12 | }
13 | }
14 |
15 | // TODO: this is a hack to work-around PhantomJS not supporting pixelated
16 | // rendering for border-image. Once that would be fixed, thes rectangles
17 | // should be removed and the expected test result should be rebuilt
18 | Rectangle {
19 | x: 0
20 | y: 3
21 | height: 14
22 | width: parent.width
23 | color: "#000"
24 | }
25 | Rectangle {
26 | x: 1
27 | y: 0
28 | height: parent.width
29 | width: 17
30 | color: "#000"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/PauseAnimation.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_PauseAnimation extends QtQuick_Animation {
3 | static properties = {
4 | duration: { type: "int", initialValue: 250 }
5 | };
6 |
7 | constructor(meta) {
8 | super(meta);
9 |
10 | this.$at = 0;
11 |
12 | QmlWeb.engine.$addTicker((...args) => this.$ticker(...args));
13 | this.runningChanged.connect(this, this.$onRunningChanged);
14 | }
15 | $ticker(now, elapsed) {
16 | if (!this.running || this.paused) {
17 | return;
18 | }
19 | this.$at += elapsed / this.duration;
20 | if (this.$at >= 1) {
21 | this.complete();
22 | }
23 | }
24 | $onRunningChanged(newVal) {
25 | if (newVal) {
26 | this.$at = 0;
27 | this.paused = false;
28 | }
29 | }
30 | complete() {
31 | this.running = false;
32 | this.$Signals.finished();
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/tests/Auto/QtWebKit/tst_enums.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtTest 1.0
3 | import QtWebKit 3.0
4 |
5 | TestCase {
6 | WebView { }
7 |
8 | function test_enums_WebView() {
9 | const enums = {
10 | // ErrorDomain
11 | NoErrorDomain: 0, InternalErrorDomain: 1, NetworkErrorDomain: 2,
12 | HttpErrorDomain: 3, DownloadErrorDomain: 4,
13 |
14 | // LoadStatus
15 | LoadStartedStatus: 0, LoadSucceededStatus: 2, LoadFailedStatus: 3,
16 |
17 | // NavigationRequestAction
18 | AcceptRequest: 0, IgnoreRequest: 255,
19 |
20 | // NavigationType
21 | LinkClickedNavigation: 0, FormSubmittedNavigation: 1,
22 | BackForwardNavigation: 2, ReloadNavigation: 3,
23 | FormResubmittedNavigation: 4, OtherNavigation: 5
24 | };
25 |
26 | Object.keys(enums).forEach(function(key) {
27 | compare(WebView[key], enums[key], key);
28 | });
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/PropertiesUrlDir/PropertiesUrlImport.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property url localBindingSimple: "localBindingSimple.png"
5 | property url localBinding: "local" + "Binding.png"
6 | property url localSet
7 | property url remoteBindingSimple
8 | property url remoteBinding
9 | property url remoteSet
10 | Component.onCompleted: {
11 | localSet = "localSet.png"
12 | }
13 | /* These are required as they force some slots to run in this context when
14 | * things are done in PropertiesUrl. This tests that running slots in this
15 | * context doesn't have any unintended consequences. The "return" statements
16 | * are to ensure that slot handling continues after a return. */
17 | onRemoteSetChanged: {
18 | return
19 | }
20 | onRemoteBindingSimpleChanged: {
21 | return
22 | }
23 | onRemoteBindingChanged: {
24 | return
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/modules/QtQuick.Window/Window.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Window_Window extends QtQuick_Item {
3 | static versions = /^2\./;
4 | static properties = {
5 | active: "bool",
6 | activeFocusItem: "Item",
7 | color: { type: "color", initialValue: "#ffffff" },
8 | //contentItem: "Item", // TODO
9 | contentOrientation: "enum",
10 | flags: "int",
11 | maximumHeight: "int",
12 | maximumWidth: "int",
13 | minimumHeight: "int",
14 | minimumWidth: "int",
15 | modality: "enum",
16 | title: "string",
17 | visibility: "enum"
18 | };
19 | static signals = {
20 | closing: [{ type: "CloseEvent", name: "close" }]
21 | };
22 |
23 | constructor(meta) {
24 | super(meta);
25 |
26 | this.colorChanged.connect(this, this.$onColorChanged);
27 | }
28 | $onColorChanged(newVal) {
29 | this.dom.style.backgroundColor = newVal.$css;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/tests/QtTest/qml/TestCaseDatadriven.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtTest 1.0
3 |
4 | Item {
5 | TestCase {
6 | name: "Datadriven"
7 |
8 | function test_one_data() {
9 | return [
10 | { tag: "2 + 2 = 4", a: 2, b: 2, c: 4 },
11 | { tag: "2 + 6 = 8", a: 2, b: 6, c: 8 },
12 | { tag: "2 + 7 = 8", a: 2, b: 7, c: 8 }
13 | ]
14 | }
15 |
16 | function test_one(data) {
17 | compare(data.a + data.b, data.c);
18 | }
19 |
20 | function init_data() {
21 | return [
22 | { tag: "init_data_1", a_skip: false, b_fail: true },
23 | { tag: "init_data_2", a_skip: true, b_skip: false }
24 | ];
25 | }
26 |
27 | function test_a(data) {
28 | if (data.a_skip) {
29 | skip("Skipping");
30 | }
31 | }
32 |
33 | function test_b(data) {
34 | if (data.b_fail) {
35 | fail();
36 | }
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/tests/QtQuick/qml/RepeaterModelRole.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property alias repeater: _repeater
5 | Repeater {
6 | id: _repeater
7 | model: ListModel {
8 | ListElement {
9 | role1: "foo"
10 | role2: 42
11 | }
12 | ListElement {
13 | role1: "bar"
14 | role2: 43
15 | }
16 | }
17 | Item {
18 | id: outer_item
19 | property var firstRole: model.role1
20 | property var secondRole: model.role2
21 | property alias firstRoleInner: inner_item.firstRole
22 | property alias secondRoleInner: inner_item.secondRole
23 | property string role1: "blah"
24 | Component.onCompleted: {
25 | console.log(outer_item.role1, role1, model.role1)
26 | }
27 | Item {
28 | id: inner_item
29 | property var firstRole: model.role1
30 | property var secondRole: model.role2
31 | }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/docs/JSItemModel.md:
--------------------------------------------------------------------------------
1 | # JSItemModel
2 |
3 | JSItemModel is a QAbstractItemModel like class that allows to create models
4 | from javascript, that can later be used from QML.
5 |
6 | ## To implement a model
7 |
8 | * Create a `JSItemModel` object and add `rowCount()` and `data()` functions to
9 | the object,
10 | * use `setRoleNames` to define `roleNames`,
11 | * emit `dataChanged`, `rowsInserted`, `rowsMoved`, `rowsRemoved` and
12 | `modelReset` as your internal data changes.
13 |
14 | ## Example
15 |
16 | ```js
17 | var data = [{ name: 'Ann', age: 23 },
18 | { name: 'John', age: 38 },
19 | { name: 'Gottlieb', age: 67 }];
20 | var myModel = new JSItemModel();
21 |
22 | myModel.data = function(index, role) {
23 | if (index > data.length)
24 | return undefined;
25 | return data[index][role];
26 | }
27 | myModel.rowCount = function() {
28 | return data.length;
29 | }
30 | myModel.setRoleNames(['name', 'age']);
31 | ```
32 |
--------------------------------------------------------------------------------
/examples/customelement.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | QML Custom Element Example
5 |
7 |
8 |
10 |
11 |
12 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/modules/QtBluetooth/BluetoothDiscoveryModel.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtBluetooth_BluetoothDiscoveryModel extends QtQml_QtObject {
3 | static enums = {
4 | BluetoothDiscoveryModel: {
5 | FullServiceDiscovery: 1, MinimalServiceDiscovery: 0, DeviceDiscovery: 2,
6 | NoError: 0, InputOutputError: 1, PoweredOffError: 2,
7 | InvalidBluetoothAdapterError: 4, UnknownError: 3
8 | }
9 | };
10 | static properties = {
11 | discoveryMode: { type: "enum", initialValue: 3 }, // MinimalServiceDiscovery
12 | error: { type: "enum", initialValue: 0 }, // NoError
13 | remoteAddress: "string",
14 | running: "bool",
15 | uuidFilter: "string",
16 | url: "url"
17 | };
18 | static signals = {
19 | deviceDiscovered: [{ type: "string", name: "device" }],
20 | serviceDiscovered: [{ type: "string", name: "device" }]
21 | };
22 |
23 | // TODO: implementation based on navigator.bluetooth
24 | }
25 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/Animation.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Animation extends QtQml_QtObject {
3 | static enums = {
4 | Animation: { Infinite: -1 },
5 | Easing: QmlWeb.Easing
6 | };
7 | static properties = {
8 | alwaysRunToEnd: "bool",
9 | loops: { type: "int", initialValue: 1 },
10 | paused: "bool",
11 | running: "bool"
12 | };
13 |
14 | static signals = {
15 | finished: [],
16 | started: [],
17 | stopped: []
18 | };
19 |
20 | restart() {
21 | this.stop();
22 | this.start();
23 | }
24 | start() {
25 | this.running = true;
26 | this.$Signals.started();
27 | }
28 | stop() {
29 | this.running = false;
30 | this.$Signals.stopped();
31 | }
32 | pause() {
33 | this.paused = true;
34 | }
35 | resume() {
36 | this.paused = false;
37 | }
38 | complete() {
39 | // To be overridden
40 | console.log("Unbound method for", this);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/qtbase/JSItemModel.js:
--------------------------------------------------------------------------------
1 | class JSItemModel {
2 | constructor() {
3 | this.roleNames = [];
4 |
5 | const Signal = QmlWeb.Signal;
6 | this.dataChanged = Signal.signal([
7 | { type: "int", name: "startIndex" },
8 | { type: "int", name: "endIndex" }
9 | ]);
10 | this.rowsInserted = Signal.signal([
11 | { type: "int", name: "startIndex" },
12 | { type: "int", name: "endIndex" }
13 | ]);
14 | this.rowsMoved = Signal.signal([
15 | { type: "int", name: "sourceStartIndex" },
16 | { type: "int", name: "sourceEndIndex" },
17 | { type: "int", name: "destinationIndex" }
18 | ]);
19 | this.rowsRemoved = Signal.signal([
20 | { type: "int", name: "startIndex" },
21 | { type: "int", name: "endIndex" }
22 | ]);
23 | this.modelReset = Signal.signal();
24 | }
25 |
26 | setRoleNames(names) {
27 | this.roleNames = names;
28 | }
29 | }
30 |
31 | QmlWeb.JSItemModel = JSItemModel;
32 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/ShaderEffectSource.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_ShaderEffectSource extends QtQuick_Item {
3 | static enums = {
4 | ShaderEffectSource: {
5 | Alpha: 0x6406, RGB: 0x6407, RGBA: 0x6408,
6 | NoMirroring: 0, MirrorHorizontally: 1, MirrorVertically: 2,
7 | ClampToEdge: 0, RepeatHorizontally: 1, RepeatVertically: 2, Repeat: 3
8 | }
9 | };
10 | static properties = {
11 | format: { type: "enum", initialValue: 0x6408 }, // ShaderEffectSource.RGBA
12 | hideSource: "bool",
13 | live: { type: "bool", initialValue: true },
14 | mipmap: "bool",
15 | recursive: "bool",
16 | sourceItem: "Item",
17 | sourceRect: "rect",
18 | textureMirroring: { type: "enum", initialValue: 2 }, // MirrorVertically
19 | textureSize: "size",
20 | wrapMode: "enum" // ShaderEffectSource.ClampToEdge
21 | };
22 |
23 | // TODO
24 |
25 | scheduleUpdate() {
26 | // TODO
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/qtbase/QPointF.js:
--------------------------------------------------------------------------------
1 | class QPointF extends QmlWeb.QObject {
2 | constructor(...args) {
3 | super();
4 | let data = args;
5 | if (args.length === 0) {
6 | data = [0, 0];
7 | } else if (args.length === 1 && typeof args[0] === "string") {
8 | data = args[0].split(",").map(x => parseFloat(x.trim()));
9 | if (data.length !== 2) throw new Error("point expected");
10 | } else if (args.length === 1 && args[0] instanceof QPointF) {
11 | data = [args[0].x, args[0].y];
12 | } else if (args.length !== 2) {
13 | throw new Error("Invalid arguments");
14 | }
15 | QmlWeb.createProperties(this, {
16 | x: { type: "real", initialValue: data[0] },
17 | y: { type: "real", initialValue: data[1] }
18 | });
19 | }
20 | toString() {
21 | return super.$toString(this.x, this.y);
22 | }
23 |
24 | static nonNullableType = true;
25 | static requireConstructor = true;
26 | }
27 |
28 | QmlWeb.QPointF = QPointF;
29 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ImportLocalComponentAsPropertyInAnotherDir.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | /* The issue that can arise is that LocalComponentProperty ends up with the
3 | * same importContextId as this file, so we import "ImportFrom" qualified, so
4 | * that a plain "ImportMe" in LocalComponentProperty will fail if it ends up
5 | * within this file's context. */
6 | import "ImportFrom" as ImportFrom
7 |
8 | Item {
9 | property int value: local_component_property.count ? local_component_property.itemAt(0).value : 0
10 | ImportFrom.LocalComponentProperty {
11 | id: local_component_property
12 | /* Required to set model here, instead of within Repeater, as it causes the
13 | * Repeater's delegate to get created in this file's context, instead of
14 | * LocalComponentProperty's context. So if the delegate doesn't have an
15 | * importContextId set, it will default to this file's, which is incorrect.
16 | * */
17 | model: 1
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/tests/QtQuick/Rectangle.js:
--------------------------------------------------------------------------------
1 | describe("QtQuick.Rectangle", function() {
2 | setupDivElement();
3 | var load = prefixedQmlLoader("QtQuick/qml/Rectangle");
4 |
5 | it("White", function() {
6 | load("White", this.div);
7 | var div = this.div.children[0];
8 | expect(div.children[0].innerHTML).toBe("");
9 | expect(div.children[0].style.backgroundColor).toBe("rgb(255, 255, 255)");
10 | expect(div.offsetWidth).toBe(200);
11 | expect(div.offsetHeight).toBe(100);
12 | expect(div.clientWidth).toBe(200);
13 | expect(div.clientHeight).toBe(100);
14 | });
15 | it("Color", function() {
16 | load("Color", this.div);
17 | var div = this.div.children[0];
18 | expect(div.children[0].style.backgroundColor).toBe("rgb(255, 0, 0)");
19 | });
20 | it("Transparent", function() {
21 | load("Transparent", this.div);
22 | var div = this.div.children[0];
23 | expect(div.children[0].style.backgroundColor).toBe("transparent");
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/tests/Render/Simple/AnchorChains.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | color: "white"
5 | width: 16
6 | height: 16
7 |
8 | Rectangle {
9 | id: bl
10 | color: "orange"
11 | width: 8
12 | height: 8
13 | anchors {
14 | left: parent.left
15 | bottom: parent.bottom
16 | }
17 | }
18 | Rectangle {
19 | id: tl
20 | color: "green"
21 | anchors {
22 | left: parent.left
23 | top: parent.top
24 | bottom: bl.top
25 | right: tr.left
26 | }
27 | }
28 | Rectangle {
29 | id: tr
30 | color: "cyan"
31 | width: 6
32 | anchors {
33 | right: parent.right
34 | top: parent.top
35 | bottom: br.top
36 | bottomMargin: 2
37 | }
38 | }
39 | Rectangle {
40 | id: br
41 | color: "red"
42 | height: 6
43 | anchors {
44 | right: parent.right
45 | bottom: parent.bottom
46 | left: bl.right
47 | margins: 2
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/qtbase/QSizeF.js:
--------------------------------------------------------------------------------
1 | class QSizeF extends QmlWeb.QObject {
2 | constructor(...args) {
3 | super();
4 | let data = args;
5 | if (args.length === 0) {
6 | data = [-1, -1];
7 | } else if (args.length === 1 && typeof args[0] === "string") {
8 | data = args[0].split("x").map(x => parseFloat(x.trim()));
9 | if (data.length !== 2) throw new Error("size expected");
10 | } else if (args.length === 1 && args[0] instanceof QSizeF) {
11 | data = [args[0].width, args[0].height];
12 | } else if (args.length !== 2) {
13 | throw new Error("Invalid arguments");
14 | }
15 | QmlWeb.createProperties(this, {
16 | width: { type: "real", initialValue: data[0] },
17 | height: { type: "real", initialValue: data[1] }
18 | });
19 | }
20 | toString() {
21 | return super.$toString(this.width, this.height);
22 | }
23 |
24 | static nonNullableType = true;
25 | static requireConstructor = true;
26 | }
27 |
28 | QmlWeb.QSizeF = QSizeF;
29 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/Positioner.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Positioner extends QtQuick_Item {
3 | static properties = {
4 | spacing: "int",
5 | padding: "int"
6 | };
7 |
8 | constructor(meta) {
9 | super(meta);
10 |
11 | this.childrenChanged.connect(this, this.$onChildrenChanged);
12 | this.spacingChanged.connect(this, this.layoutChildren);
13 | this.childrenChanged.connect(this, this.layoutChildren);
14 | this.layoutChildren();
15 | }
16 | $onChildrenChanged() {
17 | const flags = QmlWeb.Signal.UniqueConnection;
18 | for (let i = 0; i < this.children.length; i++) {
19 | const child = this.children[i];
20 | child.widthChanged.connect(this, this.layoutChildren, flags);
21 | child.heightChanged.connect(this, this.layoutChildren, flags);
22 | child.visibleChanged.connect(this, this.layoutChildren, flags);
23 | }
24 | }
25 | layoutChildren() {
26 | // noop, defined in individual positioners
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/AUTHORS:
--------------------------------------------------------------------------------
1 | # Authors ordered by first contribution.
2 |
3 | Lauri Paimen
4 | Anton Kreuzkamp
5 | Jan Gerrit José Marker
6 | Somsubhra Bairi
7 | Сковорода Никита Андреевич
8 | Joshua Kolden
9 | Michael Martin Moro
10 | Sam Segers
11 | Arno Pähler
12 | Henrik Rudstrøm
13 | Edwin Marshall
14 | Pavel Vasev
15 | Igor Andruszkiewicz
16 | Harsh Choudhary
17 | Alexander Potashev
18 | Stephen D'Angelo
19 | Heikki Haveri
20 | Alexander Rössler
21 | Gaubee
22 | Alexey Andreyev
23 | Yauhen Kotau
24 | Wian van Aggelen
25 |
--------------------------------------------------------------------------------
/src/engine/i18n.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-vars */
2 |
3 | function formatString(sourceText, n) {
4 | let text = sourceText;
5 | if (typeof n !== "undefined") {
6 | if (typeof n !== "number") {
7 | throw new Error("(n) must be a number");
8 | }
9 | text = text.replace(/%n/, n.toString(10));
10 | }
11 | return text;
12 | }
13 |
14 | QmlWeb.qsTr = function(sourceText, disambiguation, n) {
15 | return formatString(sourceText, n);
16 | };
17 |
18 | QmlWeb.qsTrId = function(id, n) {
19 | return formatString(id, n);
20 | };
21 |
22 | QmlWeb.qsTranslate = function(context, sourceText, disambiguation, n) {
23 | return formatString(sourceText, n);
24 | };
25 |
26 | // Somewhy these are documented, but not defined in Qt QML 5.10
27 | /*
28 | QmlWeb.qsTrIdNoOp = function(id) {
29 | return id;
30 | };
31 |
32 | QmlWeb.qsTrNoOp = function(sourceText, disambiguation) {
33 | return sourceText;
34 | };
35 |
36 | QmlWeb.qsTranslateNoOp = function(context, sourceText, disambiguation) {
37 | return sourceText;
38 | };
39 | */
40 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/JavascriptBasicSyntax.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | //this is a line comment
5 | /*
6 | this is a block comment
7 | */
8 | function ifstatements(arg) {
9 | const b = 10;
10 | var foo = 0;
11 | if (arg == 0)
12 | foo = 1;
13 | else if (arg == 1)
14 | foo = 2 * 2;
15 | else
16 | foo = 2;
17 | return foo;
18 | }
19 |
20 | function trycatch() {
21 | try {
22 | throw new Error();
23 | } catch(e) {
24 | console.log(e);
25 | } finally {
26 | return 1;
27 | }
28 | }
29 |
30 | function foreach() {
31 | for (var i = 0; i < 5; i++) {
32 | continue;
33 | }
34 | var a = [1, 2, 3];
35 | for (var k in a) {
36 | break;
37 | }
38 | }
39 |
40 | function switchcase(arg) {
41 | var a = 0
42 | switch (arg) {
43 | case 1:
44 | a = 1;
45 | break;
46 | case "32":
47 | a = "hm";
48 | break;
49 | default:
50 | a = undefined;
51 | }
52 | return a;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/docs/Signal.md:
--------------------------------------------------------------------------------
1 | # Signal
2 |
3 | ## new Signal(\[params\[, options\]\])
4 |
5 | * `params` {Array} Parameters of the signal. Defaults to `[]`.
6 | * `options` {Object} Options that allow finetuning of the signal.
7 |
8 | Returns a new Signal object with parameters specified in `params`.
9 |
10 | Each element of the `params` array has to be an object with the two properties:
11 | `type` and `name` specifying the datatype of the parameter and its name.
12 | The type is currently ignored.
13 |
14 | ## signal.execute(...args)
15 |
16 | Executes the signal.
17 |
18 | ## signal.connect(...args)
19 |
20 | ## signal.disconnect(...args)
21 |
22 | ## signal.isConnected(...args)
23 |
24 | ## signal.signal
25 |
26 | Returns a function that runs `signal.execute(...args)` when called and has
27 | `connect`, `disconnect` and `isConnected` properties that call corresponding
28 | methods from the `signal`.
29 |
30 | ## Class Method: Signal.signal(\[params\[, options\]\])
31 |
32 | Constructs a `Signal` instance with the given `params` and `options` and returns
33 | its `.signal` property.
34 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/PropertiesUrl.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import "PropertiesUrlDir"
3 |
4 | Item {
5 | property alias localBindingSimple: properties_url_import.localBindingSimple
6 | property alias localBinding: properties_url_import.localBinding
7 | property alias localSet: properties_url_import.localSet
8 | property alias remoteBindingSimple: properties_url_import.remoteBindingSimple
9 | property alias remoteBinding: properties_url_import.remoteBinding
10 | property alias remoteSet: properties_url_import.remoteSet
11 | property url http: "http://http-url"
12 | property url aboutBlank: "about:blank"
13 | property url absolute: "/absolute-url"
14 | property url unset
15 | property url setToEmptyString: "will-be-empty-string"
16 | Component.onCompleted: {
17 | setToEmptyString = ""
18 | }
19 | PropertiesUrlImport {
20 | id: properties_url_import
21 | remoteBindingSimple: "remoteBindingSimple.png"
22 | remoteBinding: "remote" + "Binding.png"
23 | Component.onCompleted: {
24 | properties_url_import.remoteSet = "remoteSet.png"
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/tests/QtQuick/Shortcut.js:
--------------------------------------------------------------------------------
1 | describe("QtQuick.Shortcut", function() {
2 | setupDivElement();
3 | var load = prefixedQmlLoader("QtQuick/qml/Shortcut");
4 |
5 | // Works in live version. Doesn't work here.
6 | // The modifiers on the shortcut item is set to zero by
7 | // something.
8 | xit("Sequence", function() {
9 | var qml = load("Sequence", this.div);
10 | var called = 0;
11 | var event = {
12 | key: QmlWeb.Qt.Key_P,
13 | modifiers: QmlWeb.Qt.ControlModifer | QmlWeb.Qt.AltModifer
14 | };
15 |
16 | expect(qml.sequences[0].$text).toBe("Ctrl+Alt+P");
17 | expect(qml.sequences[0].$sequences.length).toBe(1);
18 | expect(qml.sequences[0].$sequences[0].key)
19 | .toBe(QmlWeb.Qt.Key_P);
20 | expect(qml.sequences[0].$sequences[0].modifiers)
21 | .toBe(QmlWeb.Qt.ControlModifer | QmlWeb.Qt.AltModifer);
22 | expect(
23 | qml.sequences[0].$match(event)
24 | ).toBe(true);
25 | qml.activated.connect(this, () => {
26 | called++;
27 | });
28 | qml.Keys.pressed(event);
29 | expect(called).toBe(1);
30 | });
31 | });
32 |
33 |
--------------------------------------------------------------------------------
/src/qtbase/QQuaternion.js:
--------------------------------------------------------------------------------
1 | class QQuaternion extends QmlWeb.QObject {
2 | constructor(...args) {
3 | super();
4 | let data = args;
5 | if (args.length === 1 && typeof args[0] === "string") {
6 | data = args[0].split(",").map(x => parseFloat(x.trim()));
7 | if (data.length !== 4) data = [];
8 | } else if (args.length === 1 && args[0] instanceof QQuaternion) {
9 | data = [args[0].scalar, args[0].x, args[0].y, args[0].z];
10 | }
11 | if (data.length === 0) {
12 | data = [1, 0, 0, 0];
13 | } else if (data.length !== 4) {
14 | throw new Error("Invalid arguments");
15 | }
16 | QmlWeb.createProperties(this, {
17 | scalar: { type: "real", initialValue: data[0] },
18 | x: { type: "real", initialValue: data[1] },
19 | y: { type: "real", initialValue: data[2] },
20 | z: { type: "real", initialValue: data[3] }
21 | });
22 | }
23 | toString() {
24 | return super.$toString(this.scalar, this.x, this.y, this.z);
25 | }
26 |
27 | static nonNullableType = true;
28 | static requireConstructor = true;
29 | }
30 |
31 | QmlWeb.QQuaternion = QQuaternion;
32 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/PropertiesUrlDir/PropertiesUrlImportWithExceptions.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | property url localBindingSimple: "localBindingSimple.png"
5 | property url localBinding: "local" + "Binding.png"
6 | property url localSet
7 | property url remoteBindingSimple
8 | property url remoteBinding
9 | property url remoteSet
10 | Component.onCompleted: {
11 | localSet = "localSet.png"
12 | }
13 | /* These are required as they force some slots to run in this context when
14 | * things are done in PropertiesUrlExceptionSafe. This tests that running
15 | * slots that throw an exception in this context doesn't have any unintended
16 | * consequences. */
17 | onLocalSetChanged: {
18 | throw "Some Exception"
19 | }
20 | onLocalBindingSimpleChanged: {
21 | throw "Some Exception"
22 | }
23 | onLocalBindingChanged: {
24 | throw "Some Exception"
25 | }
26 | onRemoteSetChanged: {
27 | throw "Some Exception"
28 | }
29 | onRemoteBindingSimpleChanged: {
30 | throw "Some Exception"
31 | }
32 | onRemoteBindingChanged: {
33 | throw "Some Exception"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/modules/QtWebKit/WebView.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtWebKit_WebView extends QtWebView_WebView {
3 | static versions = /^3\./;
4 | static enums = {
5 | WebView: {
6 | // ErrorDomain
7 | NoErrorDomain: 0, InternalErrorDomain: 1, NetworkErrorDomain: 2,
8 | HttpErrorDomain: 3, DownloadErrorDomain: 4,
9 |
10 | // LoadStatus
11 | LoadStartedStatus: 0, LoadSucceededStatus: 2, LoadFailedStatus: 3,
12 |
13 | // NavigationRequestAction
14 | AcceptRequest: 0, IgnoreRequest: 255,
15 |
16 | // NavigationType
17 | LinkClickedNavigation: 0, FormSubmittedNavigation: 1,
18 | BackForwardNavigation: 2, ReloadNavigation: 3,
19 | FormResubmittedNavigation: 4, OtherNavigation: 5
20 | }
21 | };
22 | static properties = {
23 | icon: "url"
24 | };
25 | static signals = {
26 | navigationRequested: [
27 | { type: "var", name: "request" }
28 | ],
29 | linkHovered: [
30 | { type: "url", name: "hoveredUrl" },
31 | { type: "string", name: "hoveredTitle" }
32 | ]
33 | };
34 |
35 | // TODO: implement more features on top of WebView
36 | }
37 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/ScopeRepeater.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | /* A Flow is used because it will check the width of a new child that is added
4 | * to it (e.g. "new_item" below). This will happen when the Repeater creates a
5 | * new instance of "new_item" and then parents it to the Flow. If this happens
6 | * before the model's "the_width" role has been inserted into the scope of
7 | * "new_item", it will incorrectly resolve to "root.the_width" */
8 | Flow {
9 | id: root
10 |
11 | Timer {
12 | interval: 1
13 | running: true
14 | onTriggered: {
15 | /* This needs to happen in a Timer, so that it is not with a
16 | * $createObject call that sets QmlWeb.engine.operationState =
17 | * QMLOperationState.Init */
18 | list_model.append({"the_width" : 200})
19 | root.yield(repeater.itemAt(0).width)
20 | }
21 | }
22 |
23 | // We shouldn't access this variable
24 | property int the_width: 100
25 |
26 | Repeater {
27 | id: repeater
28 | model: ListModel {
29 | id: list_model
30 | }
31 | Item {
32 | id: new_item
33 | height: 100
34 | width: the_width
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/modules/QtMobility/GeoLocation.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtMobility_GeoLocation extends QtQuick_Item {
3 | static properties = {
4 | accuracy: "double",
5 | altitude: "double",
6 | altitudeAccuracy: "double",
7 | heading: "double",
8 | latitude: "double",
9 | longitude: "double",
10 | speed: "double",
11 | timestamp: "date",
12 | label: "string"
13 | };
14 |
15 | constructor(meta) {
16 | super(meta);
17 |
18 | if (!navigator.geolocation) {
19 | return;
20 | }
21 |
22 | navigator.geolocation.getCurrentPosition(pos => this.$updatePosition(pos));
23 | navigator.geolocation.watchPosition(pos => this.$updatePosition(pos));
24 | }
25 | $updatePosition(position) {
26 | this.accuracy = position.coords.accuracy;
27 | this.altitude = position.coords.altitude;
28 | this.altitudeAccuracy = position.coords.altitudeAccuracy;
29 | this.heading = position.coords.heading;
30 | this.latitude = position.coords.latitude;
31 | this.longitude = position.coords.longitude;
32 | this.speed = position.coords.speed;
33 | this.timestamp = position.timestamp;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/tests/Qt.labs.settings/Settings.js:
--------------------------------------------------------------------------------
1 | describe("Qt.labs.settings.Settings", function() {
2 | setupDivElement();
3 | var load = prefixedQmlLoader("Qt.labs.settings/qml/Settings");
4 |
5 | it("Set plain", function() {
6 | var qml = load("Plain", this.div);
7 | qml.a = 100;
8 | qml.b = "foo";
9 | expect(qml.a).toBe(100);
10 | expect(qml.b).toBe("foo");
11 | qml.a = 20;
12 | qml.b = "bar";
13 | expect(qml.a).toBe(20);
14 | expect(qml.b).toBe("bar");
15 | });
16 |
17 | it("Get plain", function() {
18 | var qml = load("Plain", this.div);
19 | expect(qml.a).toBe(20);
20 | expect(qml.b).toBe("bar");
21 | });
22 |
23 | it("Set alias", function() {
24 | var qml = load("Alias", this.div);
25 | qml.width = 100;
26 | qml.height = 100;
27 | expect(qml.width).toBe(100);
28 | expect(qml.height).toBe(100);
29 | qml.width = 20;
30 | qml.height = 30;
31 | expect(qml.width).toBe(20);
32 | expect(qml.height).toBe(30);
33 | });
34 |
35 | it("Get alias", function() {
36 | var qml = load("Alias", this.div);
37 | expect(qml.width).toBe(20);
38 | expect(qml.height).toBe(30);
39 | });
40 | });
41 |
--------------------------------------------------------------------------------
/src/modules/QtMultimedia/Camera.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtMultimedia_Camera extends QtQml_QtObject {
3 | static versions = /^5\./;
4 | static enums = {
5 | Camera: {
6 | Available: 0, Busy: 2, Unavailable: 1, ResourceMissing: 3,
7 |
8 | UnloadedState: 0, LoadedState: 1, ActiveState: 2
9 | }
10 | };
11 | static properties = {
12 | availability: "enum", // Camera.Available
13 | cameraState: { type: "enum", initialValue: 2 }, // Camera.ActiveState
14 | cameraStatus: "enum", // TODO
15 | captureMode: "enum", // TODO
16 | deviceId: "string",
17 | digitalZoom: { type: "real", initialValue: 1 },
18 | displayName: "string",
19 | errorCode: "enum", // TODO
20 | errorString: "string",
21 | lockStatus: "enum", // TODO
22 | maximumDigitalZoom: "real",
23 | maximumOpticalZoom: "real",
24 | opticalZoom: { type: "real", initialValue: 1 },
25 | orientation: "int",
26 | position: "enum", // TODO
27 | };
28 | static signals = {
29 | error: [
30 | { type: "enum", name: "errorCode" },
31 | { type: "string", name: "errorString" }
32 | ]
33 | };
34 |
35 | // TODO: impl
36 | }
37 |
--------------------------------------------------------------------------------
/src/modules/QtQuick.Particles/Emitter.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Particles_Emitter extends QtQuick_Item {
3 | static versions = /^2\./;
4 | static properties = {
5 | acceleration: "StochasticDirection",
6 | emitRate: { type: "real", initialValue: 10 },
7 | enabled: { type: "bool", initialValue: true },
8 | endSize: { type: "real", initialValue: -1 },
9 | group: "string",
10 | lifeSpan: { type: "int", initialValue: 1000 },
11 | lifeSpanVariation: "int",
12 | maximumEmitted: { type: "int", initialValue: -1 },
13 | shape: "Shape",
14 | size: { type: "real", initialValue: 16 },
15 | sizeVariation: "real",
16 | startTime: "int",
17 | system: "ParticleSystem",
18 | velocity: "StochasticDirection",
19 | velocityFromMovement: "real"
20 | };
21 | static signals = {
22 | emitParticles: [{ type: "Array", name: "particles" }]
23 | };
24 |
25 | // TODO
26 |
27 | burst(/*count, x, y*/) {
28 | // TODO
29 | }
30 | pulse(duration) {
31 | if (this.enabled) return;
32 | this.enabled = true;
33 | setTimeout(() => {
34 | this.enabled = false;
35 | }, duration);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/Scale.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Scale extends QtQml_QtObject {
3 | static properties = {
4 | xScale: { type: "real", initialValue: 1 },
5 | yScale: { type: "real", initialValue: 1 }
6 | };
7 |
8 | constructor(meta) {
9 | super(meta);
10 |
11 | this.origin = new QmlWeb.QObject(this);
12 | QmlWeb.createProperties(this.origin, {
13 | x: "real",
14 | y: "real"
15 | });
16 |
17 | this.xScaleChanged.connect(this.$parent, this.$parent.$updateTransform);
18 | this.yScaleChanged.connect(this.$parent, this.$parent.$updateTransform);
19 | this.origin.xChanged.connect(this, this.$updateOrigin);
20 | this.origin.yChanged.connect(this, this.$updateOrigin);
21 |
22 | /* QML default origin is top-left, while CSS default origin is centre, so
23 | * $updateOrigin must be called to set the initial transformOrigin. */
24 | this.$updateOrigin();
25 | }
26 | $updateOrigin() {
27 | const style = this.$parent.dom.style;
28 | style.transformOrigin = `${this.origin.x}px ${this.origin.y}px`;
29 | style.webkitTransformOrigin = `${this.origin.x}px ${this.origin.y}px`;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/State.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_State extends QtQml_QtObject {
3 | static properties = {
4 | name: "string",
5 | changes: "list",
6 | extend: "string",
7 | when: "bool"
8 | };
9 | static defaultProperty = "changes";
10 |
11 | constructor(meta) {
12 | super(meta);
13 |
14 | this.$item = this.$parent;
15 |
16 | this.whenChanged.connect(this, this.$onWhenChanged);
17 | }
18 | $getAllChanges() {
19 | if (this.extend) {
20 | /* ECMAScript 2015. TODO: polyfill Array?
21 | const base = this.$item.states.find(state => state.name === this.extend);
22 | */
23 | const states = this.$item.states;
24 | const base = states.filter(state => state.name === this.extend)[0];
25 | if (base) {
26 | return base.$getAllChanges().concat(this.changes);
27 | }
28 | console.error("Can't find the state to extend!");
29 | }
30 | return this.changes;
31 | }
32 | $onWhenChanged(newVal) {
33 | if (newVal) {
34 | this.$item.state = this.name;
35 | } else if (this.$item.state === this.name) {
36 | this.$item.state = "";
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/tests/QMLEngine/parse.js:
--------------------------------------------------------------------------------
1 | describe("QMLEngine.parse", function() {
2 | setupDivElement();
3 | var load = prefixedQmlLoader("QMLEngine/qml/Parse");
4 |
5 | it("should throw error with line number and code extract", function() {
6 | var exception = null;
7 | try {
8 | load("Error", this.div);
9 | } catch (e) {
10 | exception = e;
11 | }
12 | expect(exception).not.toBe(null);
13 | expect(exception.message).toContain("properly int error:");
14 | expect(exception.message).toContain("Unexpected token name");
15 | expect(exception.message).toContain("line: 4");
16 | expect(exception.line).toBe(4);
17 | });
18 |
19 | it("can parse a function assigned to a var property", function() {
20 | var qml = load("FunctionVar", this.div);
21 | expect(typeof qml.aFunction).toBe("function");
22 | });
23 |
24 | it("can define signals from a QML component", function() {
25 | var qml = load("Signal", this.div);
26 | expect(qml.simpleSignal).not.toBe(undefined);
27 | expect(qml.signalWithParams).not.toBe(undefined);
28 | expect(typeof qml.simpleSignal.connect).toBe("function");
29 | expect(typeof qml.signalWithParams.connect).toBe("function");
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/Gradient.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Gradient extends QtQml_QtObject {
3 | static enums = {
4 | Orientation: {
5 | Vertical: 0, Horizontal: 1
6 | }
7 | };
8 | static properties = {
9 | orientation: { type: "enum", initialValue: 0 }, // Gradient.Orientation
10 | stops: "list"
11 | };
12 | static defaultProperty = "stops";
13 |
14 | constructor(meta) {
15 | super(meta);
16 |
17 | this.$item = this.$parent;
18 |
19 | this.orientationChanged.connect(this, this.$onGradientStopChanged);
20 | this.stopsChanged.connect(this, this.$onGradientStopChanged);
21 | }
22 | $onGradientStopChanged() {
23 | const style = this.$parent.impl.style;
24 | let linearGradient = "";
25 | for (let i = 0; i < this.stops.length; i++) {
26 | const stop = this.stops[i];
27 | linearGradient += `,${stop.color} ${stop.position * 100}%`;
28 | }
29 | if (this.stops.length > 0) {
30 | style.backgroundColor = "transparent";
31 |
32 | const direction = this.orientation === this.Orientation.Vertical
33 | ? "to bottom" : "to right";
34 | style.backgroundImage = `linear-gradient(${direction}${linearGradient})`;
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/modules/QtQml/Binding.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQml_Binding extends QtQml_QtObject {
3 | static properties = {
4 | target: { type: "QtObject", initialValue: null },
5 | property: { type: "string", initialValue: "" },
6 | value: { type: "var", initialValue: undefined },
7 | when: { type: "bool", initialValue: true }
8 | };
9 |
10 | constructor(meta) {
11 | super(meta);
12 |
13 | this.$property = undefined;
14 |
15 | this.valueChanged.connect(this, this.$onValueChanged);
16 | this.targetChanged.connect(this, this.$updateBinding);
17 | this.propertyChanged.connect(this, this.$updateBinding);
18 | this.whenChanged.connect(this, this.$updateBinding);
19 | }
20 |
21 | $updateBinding() {
22 | if (!this.when || !this.target
23 | || !this.target.hasOwnProperty(this.property)
24 | || this.value === undefined) {
25 | this.$property = undefined;
26 | return;
27 | }
28 | this.$property = this.target.$properties[this.property];
29 | this.$onValueChanged(this.value); // trigger value update
30 | }
31 |
32 | $onValueChanged(value) {
33 | if (value !== undefined && this.$property) {
34 | this.$property.set(value);
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/BasicSignalDisconnect.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | id: mainitem
5 |
6 | signal sig1();
7 |
8 | property string log: ""
9 | Text {
10 | text: log
11 | }
12 |
13 | Item {
14 | id: item1
15 | function foo() {
16 | console.log("Item 1 got signal");
17 | mainitem.log = mainitem.log + "1";
18 | mainitem.sig1.disconnect( item1, item1.foo );
19 | }
20 | }
21 |
22 | Item {
23 | id: item2
24 | function foo() {
25 | console.log("Item 2 got signal");
26 | mainitem.log = mainitem.log + "2";
27 | }
28 | }
29 |
30 | Component.onCompleted: {
31 | mainitem.sig1.connect( item1, item1.foo );
32 | mainitem.sig1.connect( item2, item2.foo );
33 | mainitem.log = mainitem.log + "i";
34 | sig1();
35 | mainitem.log = mainitem.log + "i";
36 | sig1();
37 | }
38 |
39 | /* Expected behaviour (works well in qmlscene.exe Qt 5.3):
40 | sig1 => (item1.foo + disconnect item1.foo) + item2.foo
41 | sig1 => item2.foo
42 | e.g. log = "i12i2"
43 |
44 | Current qmlweb behaviour:
45 | sig1 => (item1.foo + disconnect item1.foo) + missing call to item2.foo
46 | sig1 => item2.foo
47 | e.g. log = "i1i2"
48 | */
49 | }
50 |
--------------------------------------------------------------------------------
/src/modules/QtQuick.Controls.2/Container.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Controls_2_Container extends QtQuick_Controls_2_Control {
3 | static versions = /^2\./;
4 | static properties = {
5 | contentChildren: "list",
6 | contentData: "list",
7 | contentModel: "model",
8 | count: "int",
9 | currentIndex: "int",
10 | currentItem: "Item"
11 | };
12 |
13 | constructor(meta) {
14 | super(meta);
15 |
16 | this.widthChanged.connect(this, this.layoutChildren);
17 | this.heightChanged.connect(this, this.layoutChildren);
18 | this.childrenChanged.connect(this, this.layoutChildren);
19 | this.childrenChanged.connect(this, this.$onChildrenChanged);
20 | this.layoutChildren();
21 | }
22 | $onChildrenChanged() {
23 | const flags = QmlWeb.Signal.UniqueConnection;
24 | for (let i = 0; i < this.children.length; i++) {
25 | const child = this.children[i];
26 | child.widthChanged.connect(this, this.layoutChildren, flags);
27 | child.heightChanged.connect(this, this.layoutChildren, flags);
28 | child.visibleChanged.connect(this, this.layoutChildren, flags);
29 | }
30 | }
31 | layoutChildren() {
32 | // noop, defined in individual positioners
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/qtbase/QRectF.js:
--------------------------------------------------------------------------------
1 | class QRectF extends QmlWeb.QObject {
2 | constructor(...args) {
3 | super();
4 | let data = args;
5 | if (args.length === 0) {
6 | data = [0, 0, 0, 0];
7 | } else if (args.length === 1 && typeof args[0] === "string") {
8 | const mask = /^\s*[-\d.]+\s*,\s*[-\d.]+\s*,\s*[-\d.]+\s*x\s*[-\d.]+\s*$/;
9 | if (!args[0].match(mask)) throw new Error("rect expected");
10 | data = args[0].replace("x", ",").split(",")
11 | .map(x => parseFloat(x.trim()));
12 | } else if (args.length === 1 && args[0] instanceof QRectF) {
13 | data = [args[0].x, args[0].y, args[0].z, args[0].width];
14 | } else if (args.length !== 4) {
15 | throw new Error("Invalid arguments");
16 | }
17 | QmlWeb.createProperties(this, {
18 | x: { type: "real", initialValue: data[0] },
19 | y: { type: "real", initialValue: data[1] },
20 | width: { type: "real", initialValue: data[2] },
21 | height: { type: "real", initialValue: data[3] }
22 | });
23 | }
24 | toString() {
25 | return super.$toString(this.x, this.y, this.width, this.height);
26 | }
27 |
28 | static nonNullableType = true;
29 | static requireConstructor = true;
30 | }
31 |
32 | QmlWeb.QRectF = QRectF;
33 |
--------------------------------------------------------------------------------
/tests/Render/Simple/RectangleBorder.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.5
2 |
3 | Rectangle {
4 | width: 75
5 | height: 21
6 | color: 'green'
7 |
8 | Rectangle {
9 | width: 5
10 | height: 10
11 | }
12 | Rectangle {
13 | width: 11
14 | height: 10
15 | x: 15
16 | border.color: "#27c1cf"
17 | }
18 | Rectangle {
19 | width: 10
20 | height: 10
21 | x: 30
22 | border.width: 2
23 | }
24 | Rectangle {
25 | x: 45
26 | color: 'orange'
27 | border.width: 1
28 | }
29 | Rectangle {
30 | x: 60
31 | border.width: 0
32 | border.color: 'red'
33 | width: 10
34 | height: 10
35 | }
36 | Rectangle {
37 | x: 0
38 | y: 11
39 | border.width: 20
40 | border.color: 'red'
41 | width: 10
42 | height: 10
43 | }
44 | Rectangle {
45 | x: 15
46 | y: 11
47 | border.width: -20
48 | border.color: 'pink'
49 | width: 10
50 | height: 10
51 | }
52 | Rectangle {
53 | x: 30
54 | y: 11
55 | border.width: 3
56 | border.color: 'red'
57 | width: -10
58 | height: 10
59 | }
60 | Rectangle {
61 | x: 45
62 | y: 11
63 | color: 'red'
64 | border.width: 3
65 | border.color: 'transparent'
66 | width: 10
67 | height: 10
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/modules/QtQuick.Controls/Button.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Controls_Button extends QtQuick_Item {
3 | static properties = {
4 | text: "string",
5 | enabled: { type: "bool", initialValue: true }
6 | };
7 | static signals = {
8 | clicked: []
9 | };
10 |
11 | constructor(meta) {
12 | super(meta);
13 |
14 | this.Component.completed.connect(this, this.Component$onCompleted);
15 | this.textChanged.connect(this, this.$onTextChanged);
16 | this.enabledChanged.connect(this, this.$onEnabledChanged);
17 |
18 | const button = this.impl = document.createElement("button");
19 | button.style.pointerEvents = "auto";
20 | this.dom.appendChild(button);
21 |
22 | button.onclick = () => {
23 | this.clicked();
24 | };
25 | }
26 | Component$onCompleted() {
27 | this.implicitWidth = this.impl.offsetWidth;
28 | this.implicitHeight = this.impl.offsetHeight;
29 | }
30 | $onTextChanged(newVal) {
31 | this.impl.textContent = newVal;
32 | //TODO: Replace those statically sized borders
33 | this.implicitWidth = this.impl.offsetWidth;
34 | this.implicitHeight = this.impl.offsetHeight;
35 | }
36 | $onEnabledChanged(newVal) {
37 | this.impl.disabled = !newVal;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/tests/Auto/QtQuick/tst_point.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtTest 1.0
3 |
4 | TestCase {
5 | name: "point"
6 | property point def
7 | property point arg: "1,2.5"
8 | property point tmp
9 |
10 | function compareS(a, b) {
11 | return compare(a + "", b + "")
12 | }
13 |
14 | function test_construction() {
15 | compareS(def, "QPointF(0, 0)");
16 | compareS(arg, "QPointF(1, 2.5)");
17 | tmp = "-1, 20";
18 | compareS(tmp, "QPointF(-1, 20)");
19 | compareS(Qt.point(1, 2.5), "QPointF(1, 2.5)");
20 | }
21 |
22 | function test_get() {
23 | compare(def.x, 0);
24 | compare(def.y, 0);
25 | compare(arg.x, 1);
26 | compare(arg.y, 2.5);
27 | tmp = "-5, 40.31";
28 | compare(tmp.x, -5);
29 | compare(tmp.y, 40.31);
30 | }
31 |
32 | function test_set() {
33 | tmp = "60, -3";
34 | compareS(tmp, "QPointF(60, -3)");
35 | tmp.x = 100.5;
36 | compareS(tmp, "QPointF(100.5, -3)");
37 | tmp.y = -0.125;
38 | compareS(tmp, "QPointF(100.5, -0.125)");
39 | compare(tmp.x, 100.5);
40 | compare(tmp.y, -0.125);
41 | }
42 |
43 | function test_immut() {
44 | tmp = arg;
45 | tmp.x = 10.5;
46 | tmp.y = -20.25;
47 | compareS(tmp, "QPointF(10.5, -20.25)");
48 | compareS(arg, "QPointF(1, 2.5)");
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/tests/Render/Async/ImageFill.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.7
2 |
3 | Rectangle {
4 | width: 40
5 | height: 40
6 | color: '#fff'
7 | property int loaded: 0
8 |
9 | Image {
10 | x: 0
11 | y: 0
12 | height: 20
13 | width: 20
14 | source: "bg.png"
15 | fillMode: Image.Stretch
16 | smooth: false
17 | onStatusChanged: if (status !== Image.Loading) parent.loaded++
18 | }
19 | Image {
20 | x: 0
21 | y: 20
22 | height: 20
23 | width: 20
24 | source: "bg.png"
25 | fillMode: Image.Tile
26 | smooth: false
27 | onStatusChanged: if (status !== Image.Loading) parent.loaded++
28 | }
29 | Image {
30 | x: 20
31 | y: 0
32 | height: 20
33 | width: 20
34 | source: "bg.png"
35 | fillMode: Image.PreserveAspectCrop
36 | smooth: false
37 | onStatusChanged: if (status !== Image.Loading) parent.loaded++
38 | }
39 | Image {
40 | x: 20
41 | y: 20
42 | height: 20
43 | width: 20
44 | source: "bg.png"
45 | fillMode: Image.PreserveAspectFit
46 | smooth: false
47 | onStatusChanged: if (status !== Image.Loading) parent.loaded++
48 | }
49 |
50 | onLoadedChanged: {
51 | if (typeof window !== 'undefined' && loaded === 4) {
52 | window.onTestLoad({ framesDelay: 2 });
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/tests/QtQuick/Loader.js:
--------------------------------------------------------------------------------
1 | describe("QtQuick.Loader", function() {
2 | setupDivElement();
3 | const load = prefixedQmlLoader("QtQuick/qml/Loader");
4 |
5 | it("SourceImmediate", function() {
6 | const qml = load("SourceImmediate", this.div);
7 | expect(qml.item.value).toBe(42);
8 | });
9 | it("SourceComponentImmediate", function() {
10 | const qml = load("SourceComponentImmediate", this.div);
11 | expect(qml.item.value).toBe(42);
12 | });
13 | it("SourceDelayed", function(done) {
14 | const qml = load("SourceDelayed", this.div);
15 | qml.yield = function() {
16 | expect(qml.item.value).toBe(42);
17 | done();
18 | };
19 | qml.start();
20 | });
21 | it("SourceComponentDelayed", function(done) {
22 | const qml = load("SourceComponentDelayed", this.div);
23 | qml.yield = function() {
24 | expect(qml.item.value).toBe(42);
25 | done();
26 | };
27 | qml.start();
28 | });
29 | it("set source to an empty string", function() {
30 | const qml = load("EmptySource", this.div);
31 | expect(qml.sourceComponent).toBe(null);
32 | });
33 | it("SourceComponentFromComponent", function() {
34 | const qml = load("SourceComponentFromComponent", this.div);
35 | expect(qml.item.color.toString()).toBe("#ffff00");
36 | });
37 | });
38 |
--------------------------------------------------------------------------------
/tests/Render/Simple/RectangleImplicitSize.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Rectangle {
4 | width: 90
5 | height: 10
6 | color: 'yellow'
7 |
8 | Rectangle {
9 | width: 0
10 | height: 10
11 | color: 'pink'
12 | }
13 | Rectangle {
14 | width: 10
15 | height: 0
16 | color: 'brown'
17 | }
18 | Rectangle {
19 | width: 0
20 | height: 0
21 | x: 10
22 | color: 'blue'
23 | }
24 | Rectangle {
25 | implicitWidth: 10
26 | implicitHeight: 10
27 | x: 20
28 | color: 'red'
29 | }
30 | Rectangle {
31 | width: 5
32 | height: 10
33 | implicitWidth: 10
34 | implicitHeight: 5
35 | x: 30
36 | color: 'pink'
37 | }
38 | Rectangle {
39 | width: 0
40 | height: 0
41 | implicitWidth: 10
42 | implicitHeight: 10
43 | x: 40
44 | color: 'orange'
45 | }
46 | Rectangle {
47 | implicitWidth: -5
48 | implicitHeight: 10
49 | x: 50
50 | color: "#00ffee"
51 | }
52 | Rectangle {
53 | width: 10
54 | implicitHeight: 10
55 | x: 60
56 | color: 'gray'
57 | }
58 | Rectangle {
59 | height: 10
60 | implicitWidth: 10
61 | x: 70
62 | color: 'green'
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/Rotation.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Rotation extends QtQml_QtObject {
3 | static properties = {
4 | angle: "real"
5 | };
6 |
7 | constructor(meta) {
8 | super(meta);
9 |
10 | this.axis = new QmlWeb.QObject(this);
11 | QmlWeb.createProperties(this.axis, {
12 | x: "real",
13 | y: "real",
14 | z: { type: "real", initialValue: 1 }
15 | });
16 |
17 | this.origin = new QmlWeb.QObject(this);
18 | QmlWeb.createProperties(this.origin, {
19 | x: "real",
20 | y: "real"
21 | });
22 |
23 | this.angleChanged.connect(this.$parent, this.$parent.$updateTransform);
24 | this.axis.xChanged.connect(this.$parent, this.$parent.$updateTransform);
25 | this.axis.yChanged.connect(this.$parent, this.$parent.$updateTransform);
26 | this.axis.zChanged.connect(this.$parent, this.$parent.$updateTransform);
27 | this.origin.xChanged.connect(this, this.$updateOrigin);
28 | this.origin.yChanged.connect(this, this.$updateOrigin);
29 | this.$parent.$updateTransform();
30 | }
31 | $updateOrigin() {
32 | const style = this.$parent.dom.style;
33 | style.transformOrigin = `${this.origin.x}px ${this.origin.y}px`;
34 | style.webkitTransformOrigin = `${this.origin.x}px ${this.origin.y}px`;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/Row.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Row extends QtQuick_Positioner {
3 | static properties = {
4 | layoutDirection: "enum"
5 | };
6 |
7 | constructor(meta) {
8 | super(meta);
9 |
10 | this.layoutDirectionChanged.connect(this, this.layoutChildren);
11 | this.layoutChildren();
12 | }
13 | layoutChildren() {
14 | let curPos = this.padding;
15 | let maxHeight = 0;
16 | // When layoutDirection is RightToLeft we need oposite order
17 | let i = this.layoutDirection === 1 ? this.children.length - 1 : 0;
18 | const endPoint = this.layoutDirection === 1 ? -1 : this.children.length;
19 | const step = this.layoutDirection === 1 ? -1 : 1;
20 | for (; i !== endPoint; i += step) {
21 | const child = this.children[i];
22 | if (!(child.visible && child.width && child.height)) {
23 | continue;
24 | }
25 | maxHeight = child.height > maxHeight ? child.height : maxHeight;
26 |
27 | child.x = curPos;
28 | if (this.padding > 0) child.y = this.padding;
29 |
30 | curPos += child.width + this.spacing;
31 | }
32 | this.implicitHeight = maxHeight + this.padding * 2;
33 | // We want no spacing at the right side
34 | this.implicitWidth = curPos - this.spacing + this.padding;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/ListView.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_ListView extends QtQuick_Repeater {
3 | static properties = {
4 | orientation: "enum",
5 | spacing: "real"
6 | };
7 |
8 | constructor(meta) {
9 | super(meta);
10 | this.modelChanged.connect(this, this.$styleChanged);
11 | this.delegateChanged.connect(this, this.$styleChanged);
12 | this.orientationChanged.connect(this, this.$styleChanged);
13 | this.spacingChanged.connect(this, this.$styleChanged);
14 | this._childrenInserted.connect(this, this.$applyStyleOnItem);
15 | }
16 | container() {
17 | return this;
18 | }
19 | $applyStyleOnItem($item) {
20 | const Qt = QmlWeb.Qt;
21 | $item.dom.style.position = "initial";
22 | if (this.orientation === Qt.Horizontal) {
23 | $item.dom.style.display = "inline-block";
24 | if ($item !== this.$items[0]) {
25 | $item.dom.style["margin-left"] = `${this.spacing}px`;
26 | }
27 | } else {
28 | $item.dom.style.display = "block";
29 | if ($item !== this.$items[0]) {
30 | $item.dom.style["margin-top"] = `${this.spacing}px`;
31 | }
32 | }
33 | }
34 | $styleChanged() {
35 | for (let i = 0; i < this.$items.length; ++i) {
36 | this.$applyStyleOnItem(this.$items[i]);
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/tests/QtQuick/Timer.js:
--------------------------------------------------------------------------------
1 | describe("QtQuick.Timer", function() {
2 | setupDivElement();
3 | beforeEach(function() {
4 | jasmine.addMatchers(customMatchers);
5 | });
6 |
7 | var load = prefixedQmlLoader("QtQuick/qml/Timer");
8 | it("can roughly set short intervals", function(done) {
9 | var qml = load("Singleshot", this.div);
10 | qml.interval = 50;
11 | var now = new Date();
12 | qml.yield = function(arg) {
13 | var t = new Date() - now;
14 | expect(t).toBeRoughly(50, 1);
15 | done();
16 | };
17 | qml.start();
18 | });
19 |
20 | it("can roughly set short intervals", function(done) {
21 | var qml = load("Singleshot", this.div);
22 | qml.interval = 500;
23 | var now = new Date();
24 | qml.yield = function(arg) {
25 | var t = new Date() - now;
26 | expect(t).toBeRoughly(500, 0.1);
27 | done();
28 | };
29 | qml.start();
30 | });
31 |
32 | it("can set Timer.running = true to start", function(done) {
33 | var qml = load("Running", this.div);
34 | qml.yield = function(succeed) {
35 | expect(succeed).toBe(true);
36 | done();
37 | };
38 | qml.start();
39 | });
40 |
41 | it("Timer parent property", function() {
42 | var qml = load("ParentProperty", this.div);
43 | expect(qml.timer.value).toBe(42);
44 | });
45 | });
46 |
--------------------------------------------------------------------------------
/tests/Auto/QtQuick/tst_size.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtTest 1.0
3 |
4 | TestCase {
5 | name: "size"
6 | property size def
7 | property size arg: "1x2.5"
8 | property size tmp
9 |
10 | function compareS(a, b) {
11 | return compare(a + "", b + "")
12 | }
13 |
14 | function test_construction() {
15 | compareS(def, "QSizeF(-1, -1)");
16 | compareS(arg, "QSizeF(1, 2.5)");
17 | tmp = "100.5 x 20";
18 | compareS(tmp, "QSizeF(100.5, 20)");
19 | compareS(Qt.size(1, 2.5), "QSizeF(1, 2.5)");
20 | }
21 |
22 | function test_get() {
23 | compare(def.width, -1);
24 | compare(def.height, -1);
25 | compare(arg.width, 1);
26 | compare(arg.height, 2.5);
27 | tmp = "-5 x 40.31";
28 | compare(tmp.width, -5);
29 | compare(tmp.height, 40.31);
30 | }
31 |
32 | function test_set() {
33 | tmp = "60 x -3";
34 | compareS(tmp, "QSizeF(60, -3)");
35 | tmp.width = 100.5;
36 | compareS(tmp, "QSizeF(100.5, -3)");
37 | tmp.height = -0.125;
38 | compareS(tmp, "QSizeF(100.5, -0.125)");
39 | compare(tmp.width, 100.5);
40 | compare(tmp.height, -0.125);
41 | }
42 |
43 | function test_immut() {
44 | tmp = arg;
45 | tmp.width = 100.5;
46 | tmp.height = -0.125;
47 | compareS(tmp, "QSizeF(100.5, -0.125)");
48 | compareS(arg, "QSizeF(1, 2.5)");
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/engine/keyboard.js:
--------------------------------------------------------------------------------
1 | QmlWeb.keyCodeToQt = e => {
2 | const Qt = QmlWeb.Qt;
3 | e.keypad = e.keyCode >= 96 && e.keyCode <= 111;
4 | if (e.keyCode === Qt.Key_Tab && e.shiftKey) {
5 | return Qt.Key_Backtab;
6 | }
7 | if (e.keyCode >= 97 && e.keyCode <= 122) {
8 | return e.keyCode - (97 - Qt.Key_A);
9 | }
10 | return e.keyCode;
11 | };
12 |
13 | QmlWeb.eventToKeyboard = e => ({
14 | accepted: false,
15 | count: 1,
16 | isAutoRepeat: false,
17 | key: QmlWeb.keyCodeToQt(e),
18 | modifiers: e.ctrlKey * QmlWeb.Qt.ControlModifier
19 | | e.altKey * QmlWeb.Qt.AltModifier
20 | | e.shiftKey * QmlWeb.Qt.ShiftModifier
21 | | e.metaKey * QmlWeb.Qt.MetaModifier
22 | | e.keypad * QmlWeb.Qt.KeypadModifier,
23 | text: e.key || String.fromCharCode(e.charCode || e.keyCode)
24 | });
25 |
26 | QmlWeb.keyboardSignals = {};
27 | [
28 | "asterisk", "back", "backtab", "call", "cancel", "delete", "escape", "flip",
29 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "hangup", "menu", "no", "return", "select",
30 | "space", "tab", "volumeDown", "volumeUp", "yes", "up", "right", "down", "left"
31 | ].forEach(key => {
32 | const name = key.toString();
33 | const qtName = `Key_${name[0].toUpperCase()}${name.slice(1)}`;
34 | const prefix = typeof key === "number" ? "digit" : "";
35 | QmlWeb.keyboardSignals[QmlWeb.Qt[qtName]] = `${prefix}${name}Pressed`;
36 | });
37 |
--------------------------------------------------------------------------------
/tests/Render/Async/ImageMirror.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.7
2 |
3 | Rectangle {
4 | width: 16
5 | height: 10
6 | color: '#fff'
7 | property int loaded: 0
8 |
9 | Image {
10 | x: 0
11 | y: 0
12 | height: 10
13 | width: 4
14 | source: "bg.png"
15 | smooth: false
16 | onStatusChanged: if (status !== Image.Loading) parent.loaded++
17 | }
18 | Image {
19 | x: 4
20 | y: 0
21 | height: 10
22 | width: 4
23 | source: "bg.png"
24 | fillMode: Image.Stretch
25 | smooth: false
26 | mirror: true
27 | onStatusChanged: if (status !== Image.Loading) parent.loaded++
28 | }
29 | Image {
30 | id: image3
31 | x: 8
32 | y: 0
33 | height: 10
34 | width: 4
35 | source: "bg.png"
36 | fillMode: Image.Tile
37 | smooth: false
38 | onStatusChanged: if (status !== Image.Loading) parent.loaded++
39 | }
40 | Image {
41 | id: image4
42 | x: 12
43 | y: 0
44 | height: 10
45 | width: 4
46 | source: "bg.png"
47 | fillMode: Image.Tile
48 | smooth: false
49 | onStatusChanged: if (status !== Image.Loading) parent.loaded++
50 | }
51 |
52 | onLoadedChanged: {
53 | image3.mirror = true;
54 | image4.mirror = true;
55 | image4.mirror = false;
56 | if (typeof window !== 'undefined' && loaded === 4) {
57 | window.onTestLoad({ framesDelay: 2 });
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/tests/QtQuick.Layouts/StackLayout.js:
--------------------------------------------------------------------------------
1 | describe("QtQuick.Layouts.StackLayout", function() {
2 | setupDivElement();
3 | var load = prefixedQmlLoader("QtQuick.Layouts/qml/");
4 |
5 | it("sets implicit sizes", function() {
6 | var qml = load("StackLayout", this.div);
7 |
8 | expect(qml.implicitHeight).toBe(300);
9 | expect(qml.implicitWidth).toBe(200);
10 | });
11 |
12 | it("respects fillWidth and fillHeight policy", function() {
13 | var qml = load("StackLayout", this.div);
14 |
15 | qml.width = 800;
16 | qml.height = 600;
17 | qml.layoutChildren();
18 | expect(qml.children[0].width).toBe(800);
19 | expect(qml.children[0].height).toBe(600);
20 | qml.children[0].$Layout.fillWidth = false;
21 | expect(qml.children[0].width).toBe(200);
22 | qml.children[0].$Layout.fillHeight = false;
23 | expect(qml.children[0].height).toBe(300);
24 | });
25 |
26 | it("only displays the current item", function() {
27 | var qml = load("StackLayout", this.div);
28 |
29 | expect(qml.children[0].visible).toBe(true);
30 | expect(qml.children[1].visible).toBe(false);
31 | qml.currentIndex = 1;
32 | expect(qml.children[1].visible).toBe(true);
33 | expect(qml.children[0].visible).toBe(false);
34 | qml.currentIndex = 2;
35 | expect(qml.children[1].visible).toBe(false);
36 | expect(qml.children[0].visible).toBe(false);
37 | });
38 | });
39 |
--------------------------------------------------------------------------------
/src/modules/QtQml/Connections.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQml_Connections extends QtQml_QtObject {
3 | static properties = {
4 | target: "QtObject",
5 | ignoreUnknownSignals: "bool"
6 | };
7 |
8 | constructor(meta) {
9 | super(meta);
10 | this.target = this.$parent;
11 | this.$connections = {};
12 |
13 | this.$old_target = this.target;
14 | this.targetChanged.connect(this, this.$onTargetChanged);
15 | this.Component.completed.connect(this, this.Component$onCompleted);
16 | }
17 | $onTargetChanged() {
18 | this.$reconnectTarget();
19 | }
20 | Component$onCompleted() {
21 | this.$reconnectTarget();
22 | }
23 | $reconnectTarget() {
24 | const old_target = this.$old_target;
25 | for (const i in this.$connections) {
26 | const c = this.$connections[i];
27 | if (c._currentConnection && old_target && old_target[i] &&
28 | typeof old_target[i].disconnect === "function") {
29 | old_target[i].disconnect(c._currentConnection);
30 | }
31 | if (this.target) {
32 | c._currentConnection = QmlWeb.connectSignal(this.target, i, c.value,
33 | c.objectScope, c.componentScope);
34 | }
35 | }
36 | this.$old_target = this.target;
37 | }
38 | $setCustomSlot(propName, value, objectScope, componentScope) {
39 | this.$connections[propName] = { value, objectScope, componentScope };
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/engine/helpers.js:
--------------------------------------------------------------------------------
1 | class QmlWebHelpers {
2 | static arrayFindIndex(array, callback) {
3 | // Note: does not support thisArg, we don't need that
4 | if (!Array.prototype.findIndex) {
5 | for (const key in array) {
6 | if (callback(array[key], key, array)) {
7 | return key;
8 | }
9 | }
10 | return -1;
11 | }
12 | return Array.prototype.findIndex.call(array, callback);
13 | }
14 | static mergeObjects(...args) {
15 | const merged = {};
16 | for (const i in args) {
17 | const arg = args[i];
18 | if (!arg) {
19 | continue;
20 | }
21 | for (const key in arg) {
22 | merged[key] = arg[key];
23 | }
24 | }
25 | return merged;
26 | }
27 | static reduceUri(uri) {
28 | let reducedUri = uri;
29 | let match;
30 | // eslint-disable-next-line no-cond-assign
31 | while (match = reducedUri.match(/\/?\.\//)) {
32 | const part1 = reducedUri.slice(0, match.index);
33 | const part2 = reducedUri.slice(match.index + match[0].length);
34 | reducedUri = `${part1}/${part2}`;
35 | }
36 | // eslint-disable-next-line no-cond-assign
37 | while (match = reducedUri.match(/([^/]+)(\/\.\.)\/?/)) {
38 | const part1 = reducedUri.slice(0, match.index);
39 | const part2 = reducedUri.slice(match.index + match[0].length);
40 | reducedUri = `${part1}/${part2}`;
41 | }
42 | return reducedUri;
43 | }
44 | }
45 |
46 | QmlWeb.helpers = QmlWebHelpers;
47 |
--------------------------------------------------------------------------------
/src/modules/Qt.labs.settings/Settings.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class Qt_labs_settings_Settings extends QtQuick_Item {
3 | static properties = {
4 | category: "string"
5 | };
6 |
7 | constructor(meta) {
8 | super(meta);
9 |
10 | if (typeof window.localStorage === "undefined") {
11 | return;
12 | }
13 |
14 | this.Component.completed.connect(this, this.Component$onCompleted);
15 | }
16 | Component$onCompleted() {
17 | this.$loadProperties();
18 | this.$initializeProperties();
19 | }
20 | $getKey(attrName) {
21 | return `${this.category}/${attrName}`;
22 | }
23 | $loadProperties() {
24 | this.$attributes.forEach(attrName => {
25 | if (!this.$properties[attrName]) return;
26 |
27 | const key = this.$getKey(attrName);
28 | this[attrName] = localStorage.getItem(key);
29 | });
30 | }
31 | $initializeProperties() {
32 | this.$attributes.forEach(attrName => {
33 | if (!this.$properties[attrName]) return;
34 |
35 | let emitter = this;
36 | let signalName = `${attrName}Changed`;
37 |
38 | if (this.$properties[attrName].type === "alias") {
39 | emitter = this.$context[this.$properties[attrName].val.objectName];
40 | signalName = `${this.$properties[attrName].val.propertyName}Changed`;
41 | }
42 |
43 | emitter[signalName].connect(this, () => {
44 | localStorage.setItem(this.$getKey(attrName), this[attrName]);
45 | });
46 | });
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/tests/Auto/runner.js:
--------------------------------------------------------------------------------
1 | // For Qt QML, run with `qmltestrunner -input tests/Auto/`
2 |
3 | (function() {
4 | var regex = new RegExp("^/base/tests/Auto/.*/tst_[^/]+\\.qml$");
5 | var tests = Object.keys(window.__karma__.files)
6 | .filter(function(path) {
7 | return regex.test(path);
8 | })
9 | .map(function(path) {
10 | return {
11 | qml: path,
12 | group: path.replace("/base/tests/Auto/", "").replace(/\/[^/]+$/, "")
13 | .replace(/\//g, "."),
14 | name: path.replace(/^.*\//, "").replace(".qml", "")
15 | };
16 | })
17 | .reduce(function(data, entry) {
18 | if (!data.hasOwnProperty(entry.group)) {
19 | data[entry.group] = [];
20 | }
21 |
22 | data[entry.group].push(entry);
23 | return data;
24 | }, {});
25 |
26 | Object.keys(tests).forEach(function(group) {
27 | describe("Auto." + group, function() {
28 | setupDivElement();
29 | tests[group].forEach(function(test) {
30 | it(test.name, function() {
31 | loadQmlFile(test.qml, this.div);
32 | var t = QmlWeb.engine.tests;
33 | if (t.errors.length > 0) {
34 | throw new Error(t.errors.join("\n") + "\n");
35 | }
36 | expect(t.total).toBe(1);
37 | expect(t.completed).toBe(1);
38 | expect(t.stats.pass + t.stats.skip).toBeGreaterThan(0);
39 | expect(t.stats.fail).toBe(0);
40 | });
41 | });
42 | });
43 | });
44 | }());
45 |
--------------------------------------------------------------------------------
/tests/QmlWeb.Dom/DomElementStyle.js:
--------------------------------------------------------------------------------
1 | describe("QmlWeb.Dom.DomElement", function() {
2 | setupDivElement();
3 | var load = prefixedQmlLoader("QmlWeb.Dom/qml/DomElement");
4 |
5 | it("initalizes style", function() {
6 | var qml = load("Style", this.div);
7 | expect(qml.dom.style.textAlign).toBe("center");
8 | });
9 |
10 | it("updates style", function() {
11 | var qml = load("Style", this.div);
12 | qml.style.textAlign = "right";
13 | expect(qml.dom.style.textAlign).toBe("right");
14 | });
15 |
16 | it("supports style bindings", function() {
17 | var qml = load("Style", this.div);
18 | expect(qml.dom.style.fontSize).toBe("21px");
19 | qml.bindSize = 14;
20 | expect(qml.style.fontSize).toBe("14px");
21 | expect(qml.dom.style.fontSize).toBe("14px");
22 | });
23 |
24 | it("updates sizes", function() {
25 | var qml = load("Style", this.div);
26 | qml.style.width = "150px";
27 | qml.style.height = "40px";
28 | expect(qml.dom.style.width).toBe("150px");
29 | expect(qml.dom.getBoundingClientRect().width).toBe(150);
30 | expect(qml.width).toBe(150);
31 | expect(qml.dom.getBoundingClientRect().height).toBe(40);
32 | expect(qml.height).toBe(40);
33 | });
34 |
35 | it("updates implicit sizes", function() {
36 | var qml = load("Style", this.div);
37 | var spy = jasmine.createSpy();
38 | qml.implicitWidthChanged.connect(spy);
39 | qml.text = "Hello world!";
40 | expect(spy).toHaveBeenCalled();
41 | });
42 | });
43 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | QmlWeb is licensed under the MIT license, as follows:
2 |
3 | """
4 | MIT License
5 |
6 | Copyright (c) 2011, 2012 Lauri Paimen
7 | Copyright (c) 2013 Anton Kreuzkamp
8 | Copyright (c) 2015 Pavel Vasev - initial and working
9 | import implementation.
10 | Copyright (c) 2016-2018 QmlWeb contributors
11 |
12 | Permission is hereby granted, free of charge, to any person obtaining a copy of
13 | this software and associated documentation files (the "Software"), to deal in
14 | the Software without restriction, including without limitation the rights to
15 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
16 | the Software, and to permit persons to whom the Software is furnished to do so,
17 | subject to the following conditions:
18 |
19 | The above copyright notice and this permission notice shall be included in all
20 | copies or substantial portions of the Software.
21 |
22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
24 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
25 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
26 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 | """
29 |
--------------------------------------------------------------------------------
/src/modules/QtQuick.Layouts/Positioner.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Layouts_Positioner extends QtQuick_Layouts_AbstractLayout {
3 | layoutChildren() {
4 | if (this.children.length > 0) {
5 | const layout = this.$bareLayout();
6 |
7 | this.implicitWidth = this.$isUsingImplicitWidth
8 | ? layout.contentWidth : layout.maxWidth;
9 | this.implicitHeight = this.$isUsingImplicitHeight
10 | ? layout.contentHeight : layout.maxHeight;
11 | this.$fillLayoutCells(layout);
12 | this.$applyDirection(layout);
13 | this.$applyLayout(layout);
14 | } else {
15 | this.implicitWidth = this.implicitHeight = 0;
16 | }
17 | }
18 |
19 | $plugChildrenSignals(children, action) {
20 | super.$plugChildrenSignals(children, action, ["visible"]);
21 | }
22 |
23 | $createLayoutDescriptor() {
24 | return {
25 | cells: [],
26 | maxWidth: this.$isUsingImplicitWidth ? 0 : this.width,
27 | maxHeight: this.$isUsingImplicitHeight ? 0 : this.height,
28 | contentWidth: 0,
29 | contentHeight: 0,
30 | fillColumnCount: 0,
31 | fillRowCount: 0
32 | };
33 | }
34 |
35 | $applyDirection() {
36 | }
37 |
38 | $applyLayout(layout) {
39 | for (let i = 0; i < layout.cells.length; ++i) {
40 | const cell = layout.cells[i];
41 |
42 | cell.item.x = cell.x;
43 | cell.item.y = cell.y;
44 | cell.item.width = cell.width;
45 | cell.item.height = cell.height;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/modules/QtQuick.Layouts/StackLayout.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Layouts_StackLayout extends QtQuick_Layouts_AbstractLayout {
3 | static versions = /^1\./;
4 | static properties = {
5 | count: "int",
6 | currentIndex: "int"
7 | };
8 |
9 | constructor(meta) {
10 | super(meta);
11 | window.bite = this;
12 | this.childrenChanged.connect(this, this.$updateCount);
13 | this.currentIndexChanged.connect(this, this.layoutChildren);
14 | }
15 |
16 | $updateCount() {
17 | this.count = this.children.length;
18 | }
19 |
20 | layoutChildren() {
21 | if (this.currentIndex < this.children.length) {
22 | const currentItem = this.children[this.currentIndex];
23 |
24 | this.$updateSize(currentItem, "Width");
25 | this.$updateSize(currentItem, "Height");
26 | }
27 | this.children.forEach(this.$updateChildVisibility.bind(this));
28 | }
29 |
30 | $updateSize(child, direction) {
31 | const propertyName = direction[0].toLowerCase() + direction.slice(1);
32 |
33 | if (this[`$isUsingImplicit${direction}`]) {
34 | this[`implicit${direction}`] = this.$inferCellSize(child, direction);
35 | } else if (child.$Layout[`fill${direction}`] !== false) {
36 | child[propertyName] = this[propertyName];
37 | } else {
38 | child[propertyName] = child[`implicit${direction}`];
39 | }
40 | }
41 |
42 | $updateChildVisibility(child) {
43 | child.visible = this.currentIndex === this.children.indexOf(child);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/modules/QtGraphicalEffects/FastBlur.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtGraphicalEffects_FastBlur extends QtQuick_Item {
3 | static properties = {
4 | radius: "real",
5 | source: { type: "var", initialValue: null }
6 | };
7 |
8 | constructor(meta) {
9 | super(meta);
10 |
11 | this.$previousSource = null;
12 | this.$filterObject = undefined;
13 |
14 | this.radiusChanged.connect(this, this.$onRadiusChanged);
15 | this.sourceChanged.connect(this, this.$onSourceChanged);
16 | }
17 | $onRadiusChanged() {
18 | this.$updateEffect(this.source);
19 | }
20 | $onSourceChanged() {
21 | this.$updateEffect(this.source);
22 | }
23 | $updateFilterObject() {
24 | this.$filterObject = {
25 | transformType: "filter",
26 | operation: "blur",
27 | parameters: `${this.radius}px`
28 | };
29 | }
30 | $updateEffect(source) {
31 | console.log("updating effect");
32 | if (this.$previousSource) {
33 | const index = this.$previousSource.transform.indexOf(this.$filterObject);
34 | this.$previousSource.transform.splice(index, 1);
35 | this.$previousSource.$updateTransform();
36 | }
37 | if (source && source.transform) {
38 | this.$updateFilterObject();
39 | console.log("updating effect:", this.$filterObject, source);
40 | source.transform.push(this.$filterObject);
41 | source.$updateTransform();
42 | this.$previousSource = source;
43 | } else {
44 | this.$previousSource = null;
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/modules/QtMultimedia/MediaPlayer.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtMultimedia_MediaPlayer extends QtQml_QtObject {
3 | static versions = /^5\./;
4 | static enums = {
5 | MediaPlayer: {
6 | Available: 0, Busy: 2, Unavailable: 1, ResourceMissing: 3,
7 |
8 | NoError: 0, ResourceError: 1, FormatError: 2, NetworkError: 4,
9 | AccessDenied: 8, ServiceMissing: 16,
10 |
11 | StoppedState: 0, PlayingState: 1, PausedState: 2,
12 |
13 | NoMedia: 0, Loading: 1, Loaded: 2, Buffering: 4, Stalled: 8,
14 | EndOfMedia: 16, InvalidMedia: 32, UnknownStatus: 64
15 | }
16 | };
17 | static properties = {
18 | audioRole: "enum", // TODO
19 | autoLoad: { type: "bool", initialValue: true },
20 | autoPlay: "bool",
21 | availability: "enum", // MediaPlayer.Available
22 | bufferProgress: "real",
23 | duration: "int",
24 | error: "enum", // MediaPlayer.NoError
25 | errorString: "string",
26 | hasAudio: "bool",
27 | hasVideo: "bool",
28 | loops: "int",
29 | muted: "bool",
30 | playbackRate: { type: "real", initialValue: 1 },
31 | playbackState: "enum", // MediaPlayer.StoppedState
32 | position: "int",
33 | seekable: "bool",
34 | source: "url",
35 | status: "enum", // MediaPlayer.NoMedia
36 | volume: "real"
37 | };
38 | static signals = {
39 | error: [
40 | { type: "enum", name: "error" },
41 | { type: "string", name: "errorString" }
42 | ],
43 | paused: [],
44 | playing: [],
45 | stopped: []
46 | };
47 |
48 | // TODO: impl
49 | }
50 |
--------------------------------------------------------------------------------
/tests/QMLEngine/qml/PropertiesUrlExceptionSafe.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import "PropertiesUrlDir"
3 |
4 | Item {
5 | property alias localBindingSimple: properties_url_import.localBindingSimple
6 | property alias localBinding: properties_url_import.localBinding
7 | property alias localSet: properties_url_import.localSet
8 | property alias remoteBindingSimple: properties_url_import.remoteBindingSimple
9 | property alias remoteBinding: properties_url_import.remoteBinding
10 | property alias remoteSet: properties_url_import.remoteSet
11 | PropertiesUrlImportWithExceptions {
12 | id: properties_url_import
13 | remoteBindingSimple: "remoteBindingSimple.png"
14 | remoteBinding: "remote" + "Binding.png"
15 | Component.onCompleted: {
16 | properties_url_import.remoteSet = "remoteSet.png"
17 | }
18 | /* These are required as they force some slots to run in this context when
19 | * things are done in PropertiesUrlExceptionSafe. This tests that running
20 | * slots that throw an exception in this context doesn't have any unintended
21 | * consequences. */
22 | onLocalSetChanged: {
23 | throw "Some Exception"
24 | }
25 | onLocalBindingSimpleChanged: {
26 | throw "Some Exception"
27 | }
28 | onLocalBindingChanged: {
29 | throw "Some Exception"
30 | }
31 | onRemoteSetChanged: {
32 | throw "Some Exception"
33 | }
34 | onRemoteBindingSimpleChanged: {
35 | throw "Some Exception"
36 | }
37 | onRemoteBindingChanged: {
38 | throw "Some Exception"
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/modules/QtQuick.Layouts/Layout.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_Layouts_Layout extends QtQml_QtObject {
3 | static versions = /^1\./;
4 |
5 | constructor(meta) {
6 | super(meta);
7 | throw new Error("Do not create objects of type Layout");
8 | }
9 | static getAttachedObject() {
10 | if (!this.$Layout) {
11 | this.$Layout = new QmlWeb.QObject(this);
12 | QmlWeb.createProperties(this.$Layout, {
13 | alignment: { type: "enum", initialValue: null },
14 | bottomMargin: { type: "real", initialValue: null },
15 | column: { type: "int", initialValue: null },
16 | columnSpan: { type: "int", initialValue: 1 },
17 | fillHeight: { type: "bool", initialValue: null },
18 | fillWidth: { type: "bool", initialValue: null },
19 | leftMargin: { type: "real", initialValue: null },
20 | margins: "real",
21 | maximumHeight: { type: "real", initialValue: null },
22 | maximumWidth: { type: "real", initialValue: null },
23 | minimumHeight: { type: "real", initialValue: null },
24 | minimumWidth: { type: "real", initialValue: null },
25 | preferredHeight: { type: "real", initialValue: null },
26 | preferredWidth: { type: "real", initialValue: null },
27 | rightMargin: { type: "real", initialValue: null },
28 | row: { type: "int", initialValue: null },
29 | rowSpan: { type: "int", initialValue: 1 },
30 | topMargin: { type: "real", initialValue: null }
31 | });
32 | }
33 | return this.$Layout;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/Canvas.js:
--------------------------------------------------------------------------------
1 | // TODO
2 | // Currently only a skeleton implementation
3 |
4 | // eslint-disable-next-line no-undef
5 | class QtQuick_Canvas extends QtQuick_Item {
6 | static properties = {
7 | available: { type: "bool", initialValue: true },
8 | canvasSize: { type: "var", initialValue: [0, 0] },
9 | canvasWindow: { type: "var", initialValue: [0, 0, 0, 0] },
10 | context: { type: "var", initialValue: {} },
11 | contextType: { type: "string", initialValue: "contextType" },
12 | renderStrategy: "enum",
13 | renderTarget: "enum",
14 | tileSize: { type: "var", initialValue: [0, 0] }
15 | };
16 | static signals = {
17 | imageLoaded: [],
18 | paint: [{ type: "var", name: "region" }],
19 | painted: []
20 | };
21 |
22 | cancelRequestAnimationFrame(/*handle*/) {
23 | return false;
24 | }
25 | getContext(/*context_id, ...args*/) {
26 | return {};
27 | }
28 | isImageError(/*image*/) {
29 | return true;
30 | }
31 | isImageLoaded(/*image*/) {
32 | return false;
33 | }
34 | isImageLoading(/*image*/) {
35 | return false;
36 | }
37 | loadImage(image) {
38 | //loadImageAsync(image);
39 | if (this.isImageLoaded(image)) {
40 | this.imageLoaded();
41 | }
42 | }
43 | markDirty(area) {
44 | // if dirty
45 | this.paint(area);
46 | }
47 | requestAnimationFrame(/*callback*/) {
48 | return 0;
49 | }
50 | requestPaint() {
51 | }
52 | save(/*file_name*/) {
53 | return false;
54 | }
55 | toDataURL(/*mime_type*/) {
56 | return "";
57 | }
58 | unloadImage(/*image*/) {
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/modules/QtWebView/WebView.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtWebView_WebView extends QtQuick_Item {
3 | static versions = /^1\./;
4 | static properties = {
5 | canGoBack: "bool", // TODO
6 | canGoForward: "bool", // TODO
7 | loadProgress: "int",
8 | loading: "bool",
9 | title: "string",
10 | url: "url"
11 | };
12 | static signals = {
13 | /* // TODO
14 | loadingChanged: [
15 | { type: "WebViewLoadRequest", name: "loadRequest" }
16 | ]
17 | */
18 | };
19 |
20 | constructor(meta) {
21 | super(meta);
22 |
23 | this.urlChanged.connect(this, this.$onUrlChanged);
24 |
25 | const iframe = this.impl = document.createElement("iframe");
26 | iframe.style.display = "block";
27 | iframe.style.position = "absolute";
28 | iframe.style.width = "100%";
29 | iframe.style.height = "100%";
30 | iframe.style.borderWidth = "0";
31 | iframe.style.pointerEvents = "auto";
32 | this.dom.appendChild(iframe);
33 |
34 | iframe.onload = () => {
35 | try {
36 | this.title = iframe.contentDocument.title;
37 | } catch (e) {
38 | console.log(`CSP prevents us from reading title for ${this.url}`);
39 | this.title = "";
40 | }
41 | this.loadProgress = 100;
42 | this.loading = false;
43 | };
44 | iframe.onerror = () => {
45 | this.title = "";
46 | this.loadProgress = 0;
47 | this.loading = false;
48 | };
49 | }
50 | $onUrlChanged(newVal) {
51 | this.loadProgress = 0;
52 | this.loading = true;
53 | this.impl.src = newVal;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | process.env.CHROMIUM_BIN = require("puppeteer").executablePath();
2 |
3 | require("./tests/chromium.callback.js");
4 |
5 | module.exports = function(config) {
6 | config.set({
7 | basePath: "",
8 | frameworks: ["jasmine"],
9 | files: [
10 | config.coverageEnabled ? "tmp/qmlweb.covered.js" : "lib/qmlweb.js",
11 | { pattern: "lib/*.js", included: false },
12 | { pattern: "lib/*.js.map", included: false },
13 | { pattern: "tmp/qmlweb.*.js", included: false },
14 | { pattern: "tmp/*.js.map", included: false },
15 | "tests/common.js",
16 | "tests/failingTests.js",
17 | "tests/*/*.js",
18 | "tests/*/**/test*.js",
19 | { pattern: "tests/*/**/qmldir", included: false },
20 | { pattern: "tests/*/**/qml/*.js", included: false },
21 | { pattern: "tests/*/**/*.qml", included: false },
22 | { pattern: "tests/*/**/*.png", included: false }
23 | ],
24 | browsers: ["ChromiumHeadlessCustom"],
25 | reporters: ["spec", "coverage"],
26 | coverageReporter: {
27 | type: "lcov",
28 | dir: "coverage/"
29 | },
30 | browserDisconnectTolerance: 5, // required for phantomjs in windows
31 | browserNoActivityTimeout: 100000, // required for phantomjs in windows
32 | customLaunchers: {
33 | ChromiumHeadlessCustom: {
34 | base: process.env.NOT_HEADLESS ? "Chromium" : "ChromiumHeadless",
35 | flags: [
36 | "--no-sandbox", // FIXME
37 | "--force-device-scale-factor=1",
38 | "--remote-debugging-port=9222"
39 | ]
40 | }
41 | }
42 | });
43 | };
44 |
--------------------------------------------------------------------------------
/tests/QtQml/Binding.js:
--------------------------------------------------------------------------------
1 | describe("QtQml.Binding", function() {
2 | setupDivElement();
3 |
4 | var load = prefixedQmlLoader("QtQml/qml/Binding");
5 | it("one way binding", function() {
6 | var qml = load("OneWay", this.div);
7 | qml.sourceValue = 50;
8 | expect(qml.targetValue).toBe(50);
9 | });
10 |
11 | it("one way binding - when", function() {
12 | var qml = load("OneWay", this.div);
13 | qml.when = false;
14 | qml.sourceValue = 50;
15 | expect(qml.targetValue).toBe(0);
16 |
17 | qml.when = true;
18 | expect(qml.targetValue).toBe(50);
19 | });
20 |
21 | it("two way binding", function() {
22 | var qml = load("TwoWay", this.div);
23 | qml.sourceValue = 50;
24 | expect(qml.targetValue).toBe(50);
25 | qml.targetValue = 23;
26 | expect(qml.sourceValue).toBe(23);
27 | });
28 |
29 | it("two way binding - when", function() {
30 | var qml = load("TwoWay", this.div);
31 | qml.when = false;
32 | qml.sourceValue = 50;
33 | expect(qml.targetValue).toBe(0);
34 | qml.targetValue = 10;
35 | qml.when = true;
36 | expect(qml.targetValue).toBe(50); // note: the first binding applies first
37 | qml.targetValue = 10;
38 | expect(qml.sourceValue).toBe(10);
39 | });
40 |
41 | it("broken binding", function() {
42 | var qml = load("Broken", this.div);
43 | expect(qml.targetValue).toBe(0);
44 | qml.when = true;
45 | expect(qml.targetValue).toBe(0); // should not override anything
46 | });
47 |
48 | it("binding undefined var", function() {
49 | var qml = load("Undefined", this.div);
50 | qml.sourceValue = undefined;
51 | expect(qml.targetValue).toBe(undefined);
52 | });
53 | });
54 |
--------------------------------------------------------------------------------
/tests/QtTest/TestCase.js:
--------------------------------------------------------------------------------
1 | describe("QtTest", function() {
2 | setupDivElement();
3 | var load = prefixedQmlLoader("QtTest/qml/TestCase");
4 |
5 | it("Empty", function() {
6 | load("Empty", this.div);
7 | var tests = QmlWeb.engine.tests;
8 | expect(tests.total).toBe(1);
9 | expect(tests.completed).toBe(1);
10 | expect(tests.stats.pass).toBe(2);
11 | expect(tests.stats.fail).toBe(0);
12 | expect(tests.stats.skip).toBe(0);
13 | });
14 |
15 | it("Simple", function() {
16 | load("Simple", this.div);
17 | var tests = QmlWeb.engine.tests;
18 | expect(tests.total).toBe(1);
19 | expect(tests.completed).toBe(1);
20 | expect(tests.stats.pass).toBe(4);
21 | expect(tests.stats.fail).toBe(1);
22 | expect(tests.stats.skip).toBe(1);
23 | });
24 |
25 | it("Datadriven", function() {
26 | load("Datadriven", this.div);
27 | var tests = QmlWeb.engine.tests;
28 | expect(tests.total).toBe(1);
29 | expect(tests.completed).toBe(1);
30 | expect(tests.stats.pass).toBe(6);
31 | expect(tests.stats.fail).toBe(2);
32 | expect(tests.stats.skip).toBe(1);
33 | });
34 |
35 | it("API", function() {
36 | var qml = load("Empty", this.div);
37 | expect(function() {
38 | qml.compare(4, 2 + 2, "Compare");
39 | }).not.toThrow();
40 | expect(function() {
41 | qml.compare(5, 2 + 2, "Compare");
42 | }).toThrowError("Compare");
43 | expect(function() {
44 | qml.warn("Warning");
45 | }).not.toThrow();
46 | expect(function() {
47 | qml.verify(true, "True");
48 | }).not.toThrow();
49 | expect(function() {
50 | qml.verify(false, "False");
51 | }).toThrowError();
52 | });
53 | });
54 |
55 |
--------------------------------------------------------------------------------
/src/modules/QtQuick/DoubleValidator.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | class QtQuick_DoubleValidator extends QtQml_QValidator {
3 | static enums = {
4 | DoubleValidator: { StandardNotation: 1, ScientificNotation: 2 }
5 | };
6 | static properties = {
7 | bottom: { type: "real", initialValue: -Infinity },
8 | top: { type: "real", initialValue: Infinity },
9 | decimals: { type: "int", initialValue: 1000 },
10 | // DoubleValidator.ScientificNotation
11 | notation: { type: "enum", initialValue: 2 }
12 | };
13 |
14 | constructor(meta) {
15 | super(meta);
16 | this.$standardRegExp = /^(-|\+)?\s*[0-9]+(\.[0-9]+)?$/;
17 | this.$scientificRegExp = /^(-|\+)?\s*[0-9]+(\.[0-9]+)?(E(-|\+)?[0-9]+)?$/;
18 | }
19 | getRegExpForNotation(notation) {
20 | switch (notation) {
21 | case this.DoubleValidator.ScientificNotation:
22 | return this.$scientificRegExp;
23 | case this.DoubleValidator.StandardNotation:
24 | return this.$standardRegExp;
25 | }
26 | return null;
27 | }
28 | $getDecimalsForNumber(number) {
29 | if (Math.round(number) === number) {
30 | return 0;
31 | }
32 | const str = `${number}`;
33 | return /\d*$/.exec(str)[0].length;
34 | }
35 | validate(string) {
36 | const regExp = this.getRegExpForNotation(this.notation);
37 | if (!regExp.test(string.trim())) {
38 | return false;
39 | }
40 | const value = parseFloat(string);
41 | const acceptable = this.bottom <= value && this.top >= value &&
42 | this.$getDecimalsForNumber(value) <= this.decimals;
43 | return acceptable
44 | ? this.QValidator.Acceptable
45 | : this.QValidator.Invalid;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------