aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--examples/qml/qml.pro12
-rw-r--r--examples/quick/customitems/painteditem/doc/images/declarative-textballoons_example.png (renamed from examples/quick/painteditem/textballoons/doc/images/declarative-textballoons_example.png)bin29663 -> 29663 bytes
-rw-r--r--examples/quick/customitems/painteditem/doc/src/textballoons.qdoc (renamed from examples/quick/painteditem/textballoons/doc/src/textballoons.qdoc)2
-rw-r--r--examples/quick/demos/stocqt/content/StockChart.qml29
-rw-r--r--examples/quick/demos/stocqt/content/StockInfo.qml9
-rw-r--r--examples/quick/demos/stocqt/content/StockListModel.qml174
-rw-r--r--examples/quick/demos/stocqt/content/StockListView.qml20
-rw-r--r--examples/quick/demos/stocqt/content/StockModel.qml8
-rw-r--r--examples/quick/demos/stocqt/stocqt.qml11
-rw-r--r--examples/quick/layouts/doc/src/qtquicklayouts-examples.qdoc42
-rw-r--r--examples/quick/layouts/layouts.pro14
-rw-r--r--examples/quick/layouts/layouts.qml145
-rw-r--r--examples/quick/layouts/layouts.qmlproject16
-rw-r--r--examples/quick/layouts/layouts.qrc5
-rw-r--r--examples/quick/layouts/main.cpp62
-rw-r--r--examples/quick/quick.pro1
-rw-r--r--examples/quick/rendercontrol/window_singlethreaded.cpp5
-rw-r--r--src/imports/imports.pro1
-rw-r--r--src/imports/layouts/layouts.pro22
-rw-r--r--src/imports/layouts/plugin.cpp73
-rw-r--r--src/imports/layouts/plugins.qmltypes102
-rw-r--r--src/imports/layouts/qmldir5
-rw-r--r--src/imports/layouts/qquickgridlayoutengine.cpp61
-rw-r--r--src/imports/layouts/qquickgridlayoutengine_p.h164
-rw-r--r--src/imports/layouts/qquicklayout.cpp1081
-rw-r--r--src/imports/layouts/qquicklayout_p.h326
-rw-r--r--src/imports/layouts/qquicklayoutstyleinfo.cpp80
-rw-r--r--src/imports/layouts/qquicklayoutstyleinfo_p.h60
-rw-r--r--src/imports/layouts/qquicklinearlayout.cpp908
-rw-r--r--src/imports/layouts/qquicklinearlayout_p.h250
-rw-r--r--src/imports/layouts/qquickstacklayout.cpp339
-rw-r--r--src/imports/layouts/qquickstacklayout_p.h108
-rw-r--r--src/particles/particles.pro6
-rw-r--r--src/particles/qquickparticleemitter.cpp2
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro7
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro8
-rw-r--r--src/plugins/qmltooling/qmldbg_local/qmldbg_local.pro8
-rw-r--r--src/plugins/qmltooling/qmldbg_native/qmldbg_native.pro8
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qmldbg_profiler.pro7
-rw-r--r--src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro8
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro8
-rw-r--r--src/plugins/qmltooling/qmltooling.pro44
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp10
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp36
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h1
-rw-r--r--src/qml/compiler/qv4codegen.cpp10
-rw-r--r--src/qml/compiler/qv4isel_p.cpp2
-rw-r--r--src/qml/compiler/qv4jsir.cpp2
-rw-r--r--src/qml/compiler/qv4ssa.cpp12
-rw-r--r--src/qml/debugger/qqmldebugconnector.cpp2
-rw-r--r--src/qml/doc/src/qmlfunctions.qdoc37
-rw-r--r--src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc4
-rw-r--r--src/qml/jit/qv4regalloc.cpp2
-rw-r--r--src/qml/jsruntime/qv4engine.cpp12
-rw-r--r--src/qml/jsruntime/qv4include.cpp38
-rw-r--r--src/qml/jsruntime/qv4include_p.h11
-rw-r--r--src/qml/jsruntime/qv4mathobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp21
-rw-r--r--src/qml/qml.pro17
-rw-r--r--src/qml/qml/qqmlcomponent.cpp7
-rw-r--r--src/qml/qml/qqmlengine.cpp45
-rw-r--r--src/qml/qml/qqmlengine.h5
-rw-r--r--src/qml/qml/qqmlengine_p.h7
-rw-r--r--src/qml/qml/qqmlfile.cpp27
-rw-r--r--src/qml/qml/qqmlfile.h2
-rw-r--r--src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp4
-rw-r--r--src/qml/qml/qqmlnetworkaccessmanagerfactory.h3
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp2
-rw-r--r--src/qml/qml/qqmlscriptstring.cpp16
-rw-r--r--src/qml/qml/qqmltypeloader.cpp32
-rw-r--r--src/qml/qml/qqmltypeloader_p.h10
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp74
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp4
-rw-r--r--src/qml/qml/qqmlxmlhttprequest_p.h4
-rw-r--r--src/qml/qml/v8/qv8engine.cpp6
-rw-r--r--src/qml/qml/v8/qv8engine_p.h2
-rw-r--r--src/qml/types/qqmlbind.cpp4
-rw-r--r--src/qml/types/qquickworkerscript.cpp18
-rw-r--r--src/qmldevtools/qmldevtools.pro4
-rw-r--r--src/qmltest/qmltest.pro4
-rw-r--r--src/qmltest/quicktest.cpp2
-rw-r--r--src/quick/designer/qquickdesignersupportitems.cpp10
-rw-r--r--src/quick/doc/images/columnlayout.pngbin0 -> 348 bytes
-rw-r--r--src/quick/doc/images/gridlayout.pngbin0 -> 2530 bytes
-rw-r--r--src/quick/doc/images/qtquicklayouts-example-layouts.pngbin0 -> 24795 bytes
-rw-r--r--src/quick/doc/images/rowlayout-minimum.pngbin0 -> 5481 bytes
-rw-r--r--src/quick/doc/images/rowlayout.pngbin0 -> 2627 bytes
-rw-r--r--src/quick/doc/qtquick.qdocconf2
-rw-r--r--src/quick/doc/snippets/qml/windowconstraints.qml76
-rw-r--r--src/quick/doc/src/concepts/layouts/qtquicklayouts-index.qdoc54
-rw-r--r--src/quick/doc/src/concepts/layouts/qtquicklayouts-overview.qdoc176
-rw-r--r--src/quick/doc/src/concepts/layouts/qtquicklayouts.qdoc46
-rw-r--r--src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc2
-rw-r--r--src/quick/doc/src/qtquick.qdoc1
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp92
-rw-r--r--src/quick/items/context2d/qquickcontext2dtexture.cpp5
-rw-r--r--src/quick/items/qquickanimatedimage.cpp11
-rw-r--r--src/quick/items/qquickanimatedimage_p_p.h11
-rw-r--r--src/quick/items/qquickanimatedsprite.cpp1
-rw-r--r--src/quick/items/qquickborderimage.cpp10
-rw-r--r--src/quick/items/qquickborderimage_p.h2
-rw-r--r--src/quick/items/qquickborderimage_p_p.h19
-rw-r--r--src/quick/items/qquickflickable.cpp37
-rw-r--r--src/quick/items/qquickflickable_p.h1
-rw-r--r--src/quick/items/qquickflickable_p_p.h1
-rw-r--r--src/quick/items/qquickgridview.cpp82
-rw-r--r--src/quick/items/qquickimagebase.cpp2
-rw-r--r--src/quick/items/qquickitem.cpp40
-rw-r--r--src/quick/items/qquickitem.h3
-rw-r--r--src/quick/items/qquickitemview.cpp6
-rw-r--r--src/quick/items/qquicklistview.cpp2
-rw-r--r--src/quick/items/qquicktext.cpp19
-rw-r--r--src/quick/items/qquicktextcontrol.cpp30
-rw-r--r--src/quick/items/qquicktextcontrol_p.h3
-rw-r--r--src/quick/items/qquicktextedit.cpp27
-rw-r--r--src/quick/items/qquicktextedit_p.h5
-rw-r--r--src/quick/items/qquicktextinput.cpp56
-rw-r--r--src/quick/items/qquicktextinput_p.h5
-rw-r--r--src/quick/items/qquicktextinput_p_p.h2
-rw-r--r--src/quick/items/qquicktextnodeengine.cpp11
-rw-r--r--src/quick/items/qquickwindow.cpp67
-rw-r--r--src/quick/items/qquickwindow.h1
-rw-r--r--src/quick/items/qquickwindow_p.h8
-rw-r--r--src/quick/items/qquickwindowattached.cpp27
-rw-r--r--src/quick/items/qquickwindowattached_p.h5
-rw-r--r--src/quick/quick.pro13
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp4
-rw-r--r--src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp6
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp4
-rw-r--r--src/quick/scenegraph/qsgrenderloop.cpp6
-rw-r--r--src/quick/scenegraph/util/qsgatlastexture.cpp6
-rw-r--r--src/quick/scenegraph/util/qsgtexture.cpp6
-rw-r--r--src/quick/util/qquickanimator.cpp19
-rw-r--r--src/quick/util/qquickanimator_p_p.h2
-rw-r--r--src/quick/util/qquickapplication.cpp5
-rw-r--r--src/quick/util/qquickapplication_p.h3
-rw-r--r--src/quick/util/qquickfontloader.cpp37
-rw-r--r--src/quick/util/qquickpixmapcache.cpp45
-rw-r--r--src/quick/util/qquickstate_p.h2
-rw-r--r--src/quickwidgets/quickwidgets.pro6
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp26
-rw-r--r--tests/auto/qml/qqmlbinding/data/disabledReadonly.qml14
-rw-r--r--tests/auto/qml/qqmlbinding/data/disabledUnknown.qml12
-rw-r--r--tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp28
-rw-r--r--tests/auto/qml/qqmllanguage/data/arraybuffer_method_arg.qml11
-rw-r--r--tests/auto/qml/qqmllanguage/data/arraybuffer_method_overload.qml7
-rw-r--r--tests/auto/qml/qqmllanguage/data/arraybuffer_method_return.qml15
-rw-r--r--tests/auto/qml/qqmllanguage/data/arraybuffer_property_get.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/arraybuffer_property_set.qml11
-rw-r--r--tests/auto/qml/qqmllanguage/data/arraybuffer_signal_arg.qml14
-rw-r--r--tests/auto/qml/qqmllanguage/data/lowercaseEnumCompileTime.1.errors.txt1
-rw-r--r--tests/auto/qml/qqmllanguage/data/lowercaseEnumCompileTime.1.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/data/lowercaseEnumCompileTime.2.errors.txt1
-rw-r--r--tests/auto/qml/qqmllanguage/data/lowercaseEnumCompileTime.2.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/data/lowercaseEnumRuntime.1.qml10
-rw-r--r--tests/auto/qml/qqmllanguage/data/lowercaseEnumRuntime.2.qml10
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.cpp12
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.h60
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp67
-rw-r--r--tests/auto/quick/examples/tst_examples.cpp20
-rw-r--r--tests/auto/quick/qquickanimators/data/positionerWithAnimator.qml63
-rw-r--r--tests/auto/quick/qquickanimators/tst_qquickanimators.cpp25
-rw-r--r--tests/auto/quick/qquickapplication/tst_qquickapplication.cpp16
-rw-r--r--tests/auto/quick/qquickgridview/data/qtbug48870.qml30
-rw-r--r--tests/auto/quick/qquickgridview/tst_qquickgridview.cpp38
-rw-r--r--tests/auto/quick/qquickitem/data/childAtRectangle.qml70
-rw-r--r--tests/auto/quick/qquickitem/tst_qquickitem.cpp42
-rw-r--r--tests/auto/quick/qquickitem2/data/qtbug_50516_2_1.qml13
-rw-r--r--tests/auto/quick/qquickitem2/data/qtbug_50516_2_2.qml12
-rw-r--r--tests/auto/quick/qquickitem2/data/qtbug_50516_2_3.qml16
-rw-r--r--tests/auto/quick/qquickitem2/data/qtbug_50516_2_4.qml15
-rw-r--r--tests/auto/quick/qquickitem2/data/qtbug_50516_2_5.qml16
-rw-r--r--tests/auto/quick/qquickitem2/data/qtbug_50516_2_6.qml17
-rw-r--r--tests/auto/quick/qquickitem2/tst_qquickitem.cpp68
-rw-r--r--tests/auto/quick/qquicklayouts/data/tst_gridlayout.qml1036
-rw-r--r--tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml921
-rw-r--r--tests/auto/quick/qquicklayouts/qquicklayouts.pro13
-rw-r--r--tests/auto/quick/qquicklayouts/tst_qquicklayouts.cpp29
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp92
-rw-r--r--tests/auto/quick/qquicktextedit/BLACKLIST4
-rw-r--r--tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp69
-rw-r--r--tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp43
-rw-r--r--tests/auto/quick/qquickwindow/data/windowattached.qml2
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp8
-rw-r--r--tests/auto/quick/quick.pro1
-rw-r--r--tests/auto/quick/shared/viewtestutil.cpp80
-rw-r--r--tests/auto/quick/shared/viewtestutil.h22
-rw-r--r--tests/manual/scenegraph_lancelot/data/text/textedit_multiline_selected_linebreaks_and_linewraps.qml22
-rw-r--r--tools/qmlimportscanner/main.cpp16
-rw-r--r--tools/qmlplugindump/main.cpp42
-rw-r--r--tools/qmlplugindump/qmlplugindump.pro6
-rw-r--r--tools/qmlplugindump/qmltypereader.cpp63
-rw-r--r--tools/qmlplugindump/qmltypereader.h42
194 files changed, 8523 insertions, 631 deletions
diff --git a/.qmake.conf b/.qmake.conf
index 3bc6c0a02b..0957f58c52 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -2,4 +2,4 @@ load(qt_build_config)
CONFIG += qt_example_installs
CONFIG += warning_clean
-MODULE_VERSION = 5.7.0
+MODULE_VERSION = 5.8.0
diff --git a/examples/qml/qml.pro b/examples/qml/qml.pro
index d5f9fa8a9e..3cb601f542 100644
--- a/examples/qml/qml.pro
+++ b/examples/qml/qml.pro
@@ -1,9 +1,13 @@
TEMPLATE = subdirs
-qtHaveModule(quick): SUBDIRS += \
- networkaccessmanagerfactory \
- qmlextensionplugins \
- xmlhttprequest
+qtHaveModule(quick) {
+ SUBDIRS += \
+ qmlextensionplugins \
+ xmlhttprequest
+
+ !no_network: SUBDIRS += \
+ networkaccessmanagerfactory
+}
SUBDIRS += \
referenceexamples \
diff --git a/examples/quick/painteditem/textballoons/doc/images/declarative-textballoons_example.png b/examples/quick/customitems/painteditem/doc/images/declarative-textballoons_example.png
index d572de597c..d572de597c 100644
--- a/examples/quick/painteditem/textballoons/doc/images/declarative-textballoons_example.png
+++ b/examples/quick/customitems/painteditem/doc/images/declarative-textballoons_example.png
Binary files differ
diff --git a/examples/quick/painteditem/textballoons/doc/src/textballoons.qdoc b/examples/quick/customitems/painteditem/doc/src/textballoons.qdoc
index da1658c7c6..3dc361e4a9 100644
--- a/examples/quick/painteditem/textballoons/doc/src/textballoons.qdoc
+++ b/examples/quick/customitems/painteditem/doc/src/textballoons.qdoc
@@ -24,8 +24,6 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-
-
/*!
\title Scene Graph - Painted Item
\brief Shows how to implement QPainter-based custom scenegraph items.
diff --git a/examples/quick/demos/stocqt/content/StockChart.qml b/examples/quick/demos/stocqt/content/StockChart.qml
index 147f513456..cd8b9f3db9 100644
--- a/examples/quick/demos/stocqt/content/StockChart.qml
+++ b/examples/quick/demos/stocqt/content/StockChart.qml
@@ -321,11 +321,27 @@ Rectangle {
ctx.restore();
}
- onPaint: {
- if (!stockModel.ready) {
- return;
- }
+ function drawError(ctx, msg)
+ {
+ ctx.save();
+ ctx.strokeStyle = "#888888";
+ ctx.font = "24px Open Sans"
+ ctx.textAlign = "center"
+ ctx.shadowOffsetX = 4;
+ ctx.shadowOffsetY = 4;
+ ctx.shadowBlur = 1.5;
+ ctx.shadowColor = "#aaaaaa";
+ ctx.beginPath();
+ ctx.fillText(msg, (canvas.width - tickMargin) / 2,
+ (canvas.height - yGridOffset - yGridStep) / 2);
+
+ ctx.closePath();
+ ctx.stroke();
+ ctx.restore();
+ }
+
+ onPaint: {
numPoints = stockModel.indexOf(chart.startDate);
if (chart.gridSize == 0)
@@ -337,6 +353,11 @@ Rectangle {
drawBackground(ctx);
+ if (!stockModel.ready) {
+ drawError(ctx, "No data available.");
+ return;
+ }
+
var highestPrice = 0;
var highestVolume = 0;
var lowestPrice = -1;
diff --git a/examples/quick/demos/stocqt/content/StockInfo.qml b/examples/quick/demos/stocqt/content/StockInfo.qml
index 3c5ee196f2..88f540fa09 100644
--- a/examples/quick/demos/stocqt/content/StockInfo.qml
+++ b/examples/quick/demos/stocqt/content/StockInfo.qml
@@ -73,7 +73,7 @@ Rectangle {
font.family: Settings.fontFamily
font.pointSize: 28
font.weight: Font.DemiBold
- text: parseFloat(Math.round(root.stock.stockPrice * 100) / 100).toFixed(2);
+ text: parseFloat(root.stock.stockPrice).toFixed(2);
}
}
@@ -99,7 +99,7 @@ Rectangle {
color: root.stock.stockPriceChanged < 0 ? "#d40000" : "#328930"
font.family: Settings.fontFamily
font.pointSize: 18
- text: parseFloat(Math.round(root.stock.stockPriceChanged * 100) / 100).toFixed(2);
+ text: parseFloat(root.stock.stockPriceChanged).toFixed(2);
}
Text {
@@ -110,9 +110,8 @@ Rectangle {
font.pointSize: 18
font.weight: Font.DemiBold
text: "(" +
- Math.abs(Math.round(
- root.stock.stockPriceChanged /
- (root.stock.stockPrice - root.stock.stockPriceChanged) * 100)) / 100 +
+ parseFloat(root.stock.stockPriceChanged /
+ (root.stock.stockPrice - root.stock.stockPriceChanged) * 100.0).toFixed(2) +
"%)"
}
}
diff --git a/examples/quick/demos/stocqt/content/StockListModel.qml b/examples/quick/demos/stocqt/content/StockListModel.qml
index b083b7bacc..be00e7bb1c 100644
--- a/examples/quick/demos/stocqt/content/StockListModel.qml
+++ b/examples/quick/demos/stocqt/content/StockListModel.qml
@@ -42,105 +42,105 @@ import QtQuick 2.0
ListModel {
id: stocks
- // Data from : http://en.wikipedia.org/wiki/NASDAQ-100
- ListElement {name: "Apple Inc."; stockId: "AAPL"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ // Uncomment to test invalid entries
+ // ListElement {name: "The Qt Company"; stockId: "TQTC"; value: "999.0"; change: "0.0"; changePercentage: "0.0"}
+
+ // Data from http://www.nasdaq.com/quotes/nasdaq-100-stocks.aspx
+ ListElement {name: "Activision Blizzard Inc."; stockId: "ATVI"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
ListElement {name: "Adobe Systems Inc."; stockId: "ADBE"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Analog Devices, Inc."; stockId: "ADI"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Automatic Data Processing, Inc."; stockId: "ADP"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Autodesk, Inc."; stockId: "ADSK"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Akamai Technologies, Inc."; stockId: "AKAM"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Altera Corp."; stockId: "ALTR"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Alexion Pharmaceuticals, Inc."; stockId: "ALXN"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Applied Materials, Inc."; stockId: "AMAT"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Amgen Inc."; stockId: "AMGN"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Akamai Technologies Inc."; stockId: "AKAM"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Alexion Pharmaceuticals Inc."; stockId: "ALXN"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Alphabet Inc."; stockId: "GOOG"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Alphabet Inc."; stockId: "GOOGL"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
ListElement {name: "Amazon.com Inc."; stockId: "AMZN"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Activision Blizzard, Inc."; stockId: "ATVI"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Avago Technologies Limited"; stockId: "AVGO"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "American Airlines Group Inc."; stockId: "AAL"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Amgen Inc."; stockId: "AMGN"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Analog Devices Inc."; stockId: "ADI"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Apple Inc."; stockId: "AAPL"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Applied Materials Inc."; stockId: "AMAT"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Autodesk Inc."; stockId: "ADSK"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Automatic Data Processing Inc."; stockId: "ADP"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Baidu Inc."; stockId: "BIDU"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
ListElement {name: "Bed Bath & Beyond Inc."; stockId: "BBBY"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Baidu, Inc."; stockId: "BIDU"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Biogen Idec Inc."; stockId: "BIIB"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Broadcom Corp."; stockId: "BRCM"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "CA Technologies"; stockId: "CA"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Celgene Corporation"; stockId: "CELG"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Cerner Corporation"; stockId: "CERN"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Biogen Inc."; stockId: "BIIB"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "BioMarin Pharmaceutical Inc."; stockId: "BMRN"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Broadcom Limited"; stockId: "AVGO"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "CA Inc."; stockId: "CA"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Celgene Corp."; stockId: "CELG"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Cerner Corp."; stockId: "CERN"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Charter Communications Inc."; stockId: "CHTR"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
ListElement {name: "Check Point Software Technologies Ltd."; stockId: "CHKP"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "CH Robinson Worldwide Inc."; stockId: "CHRW"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Charter Communications, Inc."; stockId: "CHTR"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Comcast Corporation"; stockId: "CMCSA"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Costco Wholesale Corporation"; stockId: "COST"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Cisco Systems, Inc."; stockId: "CSCO"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Catamaran Corporation"; stockId: "CTRX"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Cognizant Technology Solutions Corporation"; stockId: "CTSH"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Citrix Systems, Inc."; stockId: "CTXS"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Discovery Communications, Inc."; stockId: "DISCA"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Dish Network Corp."; stockId: "DISH"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Dollar Tree, Inc."; stockId: "DLTR"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "DIRECTV"; stockId: "DTV"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Cisco Systems Inc."; stockId: "CSCO"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Citrix Systems Inc."; stockId: "CTXS"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Cognizant Technology Solutions Corp."; stockId: "CTSH"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Comcast Corp."; stockId: "CMCSA"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Costco Wholesale Corp."; stockId: "COST"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Ctrip.com International Ltd."; stockId: "CTRP"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Discovery Communications Inc."; stockId: "DISCA"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Discovery Communications Inc."; stockId: "DISCK"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "DISH Network Corp."; stockId: "DISH"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Dollar Tree Inc."; stockId: "DLTR"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
ListElement {name: "eBay Inc."; stockId: "EBAY"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Equinix, Inc."; stockId: "EQIX"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Express Scripts Holding Company"; stockId: "ESRX"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Expeditors International of Washington Inc."; stockId: "EXPD"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Expedia Inc."; stockId: "EXPE"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Fastenal Company"; stockId: "FAST"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Facebook, Inc."; stockId: "FB"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "F5 Networks, Inc."; stockId: "FFIV"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Fiserv, Inc."; stockId: "FISV"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Twenty-First Century Fox, Inc."; stockId: "FOXA"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Gilead Sciences Inc."; stockId: "GILD"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Keurig Green Mountain, Inc."; stockId: "GMCR"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Google Inc."; stockId: "GOOG"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Google Inc."; stockId: "GOOGL"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Garmin Ltd."; stockId: "GRMN"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Henry Schein, Inc."; stockId: "HSIC"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Illumina Inc."; stockId: "ILMN"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Intel Corporation"; stockId: "INTC"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Electronic Arts Inc."; stockId: "EA"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Endo International Plc"; stockId: "ENDP"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Intel Corp."; stockId: "INTC"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
ListElement {name: "Intuit Inc."; stockId: "INTU"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Intuitive Surgical, Inc."; stockId: "ISRG"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "KLA-Tencor Corporation"; stockId: "KLAC"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Kraft Foods Group, Inc."; stockId: "KRFT"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Liberty Global plc"; stockId: "LBTYA"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Liberty Interactive Corporation"; stockId: "LINTA"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Linear Technology Corporation"; stockId: "LLTC"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Liberty Media Corporation"; stockId: "LMCA"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Marriott International, Inc."; stockId: "MAR"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Mattel, Inc"; stockId: "MAT"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Mondelez International, Inc."; stockId: "MDLZ"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Monster Beverage Corporation"; stockId: "MNST"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Microsoft Corporation"; stockId: "MSFT"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Intuitive Surgical Inc."; stockId: "ISRG"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "JD.com Inc."; stockId: "JD"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "KLA-Tencor Corp."; stockId: "KLAC"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Lam Research Corp."; stockId: "LRCX"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Liberty Global Plc"; stockId: "LBTYA"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Liberty Global Plc"; stockId: "LBTYK"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Liberty Interactive Corp."; stockId: "LVNTA"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Liberty Interactive Corp."; stockId: "QVCA"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Liberty Media Corp."; stockId: "LMCA"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Liberty Media Corp."; stockId: "LMCK"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Linear Technology Corp."; stockId: "LLTC"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Marriott International"; stockId: "MAR"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Mattel Inc."; stockId: "MAT"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Maxim Integrated Products Inc."; stockId: "MXIM"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
ListElement {name: "Micron Technology Inc."; stockId: "MU"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Maxim Integrated Products, Inc."; stockId: "MXIM"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Mylan, Inc."; stockId: "MYL"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Netflix, Inc."; stockId: "NFLX"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "NetApp, Inc."; stockId: "NTAP"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "NVIDIA Corporation"; stockId: "NVDA"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "NXP Semiconductors NV"; stockId: "NXPI"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Microsoft Corp."; stockId: "MSFT"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Mondelez International Inc."; stockId: "MDLZ"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Monster Beverage Corp."; stockId: "MNST"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Mylan N.V."; stockId: "MYL"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "NetApp Inc."; stockId: "NTAP"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Netflix Inc."; stockId: "NFLX"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Norwegian Cruise Line Holdings Ltd."; stockId: "NCLH"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "NVIDIA Corp."; stockId: "NVDA"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "NXP Semiconductors N.V."; stockId: "NXPI"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
ListElement {name: "O'Reilly Automotive Inc."; stockId: "ORLY"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Paychex, Inc."; stockId: "PAYX"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
ListElement {name: "PACCAR Inc."; stockId: "PCAR"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "The Priceline Group Inc."; stockId: "PCLN"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "QUALCOMM Incorporated"; stockId: "QCOM"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Regeneron Pharmaceuticals, Inc."; stockId: "REGN"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Paychex Inc."; stockId: "PAYX"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "PayPal Holdings Inc."; stockId: "PYPL"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "QUALCOMM Inc."; stockId: "QCOM"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Regeneron Pharmaceuticals Inc."; stockId: "REGN"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
ListElement {name: "Ross Stores Inc."; stockId: "ROST"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "SanDisk Corp."; stockId: "SNDK"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
ListElement {name: "SBA Communications Corp."; stockId: "SBAC"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Starbucks Corporation"; stockId: "SBUX"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Sigma-Aldrich Corporation"; stockId: "SIAL"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Seagate Technology PLC"; stockId: "STX"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
ListElement {name: "Sirius XM Holdings Inc."; stockId: "SIRI"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "SanDisk Corp."; stockId: "SNDK"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Staples, Inc."; stockId: "SPLS"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Stericycle, Inc."; stockId: "SRCL"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Seagate Technology Public Limited Company"; stockId: "STX"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Symantec Corporation"; stockId: "SYMC"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "TripAdvisor Inc."; stockId: "TRIP"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Tractor Supply Company"; stockId: "TSCO"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Tesla Motors, Inc."; stockId: "TSLA"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Skyworks Solutions Inc."; stockId: "SWKS"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Starbucks Corp."; stockId: "SBUX"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Stericycle Inc."; stockId: "SRCL"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Symantec Corp."; stockId: "SYMC"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "T-Mobile US Inc."; stockId: "TMUS"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Tesla Motors Inc."; stockId: "TSLA"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
ListElement {name: "Texas Instruments Inc."; stockId: "TXN"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Viacom, Inc."; stockId: "VIAB"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "VimpelCom Ltd."; stockId: "VIP"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Vodafone Group Public Limited Company"; stockId: "VOD"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Verisk Analytics, Inc."; stockId: "VRSK"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Vertex Pharmaceuticals Incorporated"; stockId: "VRTX"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Western Digital Corporation"; stockId: "WDC"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Whole Foods Market, Inc."; stockId: "WFM"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Wynn Resorts Ltd."; stockId: "WYNN"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "The Kraft Heinz Company"; stockId: "KHC"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "The Priceline Group Inc."; stockId: "PCLN"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Tractor Supply Company"; stockId: "TSCO"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "TripAdvisor Inc."; stockId: "TRIP"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Twenty-First Century Fox Inc."; stockId: "FOX"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Twenty-First Century Fox Inc."; stockId: "FOXA"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Ulta Salon Cosmetics & Fragrance Inc."; stockId: "ULTA"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Verisk Analytics Inc."; stockId: "VRSK"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Vertex Pharmaceuticals Inc."; stockId: "VRTX"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Viacom Inc."; stockId: "VIAB"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Vodafone Group Plc"; stockId: "VOD"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Walgreens Boots Alliance Inc."; stockId: "WBA"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Western Digital Corp."; stockId: "WDC"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Whole Foods Market Inc."; stockId: "WFM"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
ListElement {name: "Xilinx Inc."; stockId: "XLNX"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
+ ListElement {name: "Yahoo! Inc."; stockId: "YHOO"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
}
diff --git a/examples/quick/demos/stocqt/content/StockListView.qml b/examples/quick/demos/stocqt/content/StockListView.qml
index d1f735fde3..59f36b42cc 100644
--- a/examples/quick/demos/stocqt/content/StockListView.qml
+++ b/examples/quick/demos/stocqt/content/StockListView.qml
@@ -62,6 +62,7 @@ Rectangle {
focus: true
snapMode: ListView.SnapToItem
model: StockListModel{}
+ currentIndex: -1 // Don't pre-select any item
function requestUrl(stockId) {
var endDate = new Date(""); //today
@@ -95,7 +96,7 @@ Rectangle {
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.LOADING || xhr.readyState === XMLHttpRequest.DONE) {
var records = xhr.responseText.split('\n');
- if (records.length > 0) {
+ if (records.length > 0 && xhr.status == 200) {
var r = records[1].split(',');
var today = parseFloat(r[4]);
model.setProperty(index, "value", today.toFixed(2));
@@ -113,6 +114,9 @@ Rectangle {
model.setProperty(index, "changePercentage", "+" + changePercentage.toFixed(2) + "%");
else
model.setProperty(index, "changePercentage", changePercentage.toFixed(2) + "%");
+ } else {
+ var unknown = "n/a";
+ model.set(index, {"value": unknown, "change": unknown, "changePercentage": unknown});
}
}
}
@@ -120,9 +124,10 @@ Rectangle {
}
onCurrentIndexChanged: {
- mainRect.listViewActive = 0;
- root.currentStockId = model.get(currentIndex).stockId;
- root.currentStockName = model.get(currentIndex).name;
+ if (currentItem) {
+ root.currentStockId = model.get(currentIndex).stockId;
+ root.currentStockName = model.get(currentIndex).name;
+ }
}
delegate: Rectangle {
@@ -132,7 +137,10 @@ Rectangle {
MouseArea {
anchors.fill: parent;
onClicked: {
- view.currentIndex = index;
+ if (view.currentIndex == index)
+ mainRect.currentIndex = 1;
+ else
+ view.currentIndex = index;
}
}
@@ -243,7 +251,7 @@ Rectangle {
}
highlight: Rectangle {
- width: parent.width
+ width: view.width
color: "#eeeeee"
}
}
diff --git a/examples/quick/demos/stocqt/content/StockModel.qml b/examples/quick/demos/stocqt/content/StockModel.qml
index c1484d318e..035d9454d0 100644
--- a/examples/quick/demos/stocqt/content/StockModel.qml
+++ b/examples/quick/demos/stocqt/content/StockModel.qml
@@ -52,6 +52,9 @@ ListModel {
signal dataReady
function indexOf(date) {
+ if (model.count == 0)
+ return -1;
+
var newest = new Date(model.get(0).date);
var oldest = new Date(model.get(model.count - 1).date);
if (newest <= date)
@@ -148,8 +151,11 @@ ListModel {
model.ready = true;
model.stockPrice = model.get(0).adjusted;
model.stockPriceChanged = model.count > 1 ? (Math.round((model.stockPrice - model.get(1).close) * 100) / 100) : 0;
- model.dataReady(); //emit signal
+ } else {
+ model.stockPrice = 0;
+ model.stockPriceChanged = 0;
}
+ model.dataReady(); // emit signal - model.ready indicates whether the data is valid
}
}
}
diff --git a/examples/quick/demos/stocqt/stocqt.qml b/examples/quick/demos/stocqt/stocqt.qml
index 512d6e1073..6b1da1713a 100644
--- a/examples/quick/demos/stocqt/stocqt.qml
+++ b/examples/quick/demos/stocqt/stocqt.qml
@@ -47,7 +47,7 @@ Rectangle {
width: 1000
height: 700
- property int listViewActive: 0
+ property alias currentIndex: root.currentIndex
Rectangle {
id: banner
@@ -66,7 +66,7 @@ Rectangle {
MouseArea {
anchors.fill: parent
- onClicked: listViewActive = 1;
+ onClicked: root.currentIndex = 0;
}
}
@@ -108,11 +108,6 @@ Rectangle {
focus: false
orientation: ListView.Horizontal
boundsBehavior: Flickable.StopAtBounds
- currentIndex: listViewActive == 0 ? 1 : 0
- onCurrentIndexChanged: {
- if (currentIndex == 1)
- listViewActive = 0;
- }
StockModel {
id: stock
@@ -120,7 +115,7 @@ Rectangle {
stockName: listView.currentStockName
onStockIdChanged: stock.updateStock();
onDataReady: {
- root.positionViewAtIndex(1, ListView.SnapPosition)
+ root.currentIndex = 1
stockView.update()
}
}
diff --git a/examples/quick/layouts/doc/src/qtquicklayouts-examples.qdoc b/examples/quick/layouts/doc/src/qtquicklayouts-examples.qdoc
new file mode 100644
index 0000000000..23e36c0469
--- /dev/null
+++ b/examples/quick/layouts/doc/src/qtquicklayouts-examples.qdoc
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+/*!
+ \title Qt Quick Layouts - Basic Example
+ \example layouts
+ \brief Demonstrates how to use layout types to arrange a UI
+ \image qtquicklayouts-example-layouts.png
+ \ingroup qtquickexamples
+
+ This example shows how to easily arrange UI components into
+ \l{Qt Quick Layouts}{layouts} with \l{GridLayout}, \l{RowLayout}, and
+ \l{ColumnLayout}.
+
+ \include examples-run.qdocinc
+*/
+
+
+
diff --git a/examples/quick/layouts/layouts.pro b/examples/quick/layouts/layouts.pro
new file mode 100644
index 0000000000..4d676ef49b
--- /dev/null
+++ b/examples/quick/layouts/layouts.pro
@@ -0,0 +1,14 @@
+TEMPLATE = app
+
+QT += qml quick
+
+SOURCES += main.cpp
+
+RESOURCES += \
+ layouts.qrc
+EXAMPLE_FILES = \
+ layouts.qml
+
+target.path = $$[QT_INSTALL_EXAMPLES]/quick/layouts
+INSTALLS += target
+
diff --git a/examples/quick/layouts/layouts.qml b/examples/quick/layouts/layouts.qml
new file mode 100644
index 0000000000..48299f36aa
--- /dev/null
+++ b/examples/quick/layouts/layouts.qml
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtQuick.Controls 1.2
+import QtQuick.Layouts 1.3
+
+ApplicationWindow {
+ visible: true
+ title: "Basic layouts"
+ property int margin: 11
+ width: mainLayout.implicitWidth + 2 * margin
+ height: mainLayout.implicitHeight + 2 * margin
+ minimumWidth: mainLayout.Layout.minimumWidth + 2 * margin
+ minimumHeight: mainLayout.Layout.minimumHeight + 2 * margin
+
+ ColumnLayout {
+ id: mainLayout
+ anchors.fill: parent
+ anchors.margins: margin
+ GroupBox {
+ id: rowBox
+ title: "Row layout"
+ Layout.fillWidth: true
+
+ RowLayout {
+ id: rowLayout
+ anchors.fill: parent
+ TextField {
+ placeholderText: "This wants to grow horizontally"
+ Layout.fillWidth: true
+ }
+ Button {
+ text: "Button"
+ }
+ }
+ }
+
+ GroupBox {
+ id: gridBox
+ title: "Grid layout"
+ Layout.fillWidth: true
+
+ GridLayout {
+ id: gridLayout
+ rows: 3
+ flow: GridLayout.TopToBottom
+ anchors.fill: parent
+
+ Label { text: "Line 1" }
+ Label { text: "Line 2" }
+ Label { text: "Line 3" }
+
+ TextField { }
+ TextField { }
+ TextField { }
+
+ TextArea {
+ text: "This widget spans over three rows in the GridLayout.\n"
+ + "All items in the GridLayout are implicitly positioned from top to bottom."
+ Layout.rowSpan: 3
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ }
+ }
+ }
+ TextArea {
+ id: t3
+ text: "This fills the whole cell"
+ Layout.minimumHeight: 30
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ }
+ GroupBox {
+ id: stackBox
+ title: "Stack layout"
+ implicitWidth: 200
+ implicitHeight: 60
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ StackLayout {
+ id: stackLayout
+ anchors.fill: parent
+
+ function advance() { currentIndex = (currentIndex + 1) % count }
+
+ Repeater {
+ id: stackRepeater
+ model: 5
+ Rectangle {
+ color: Qt.hsla((0.5 + index)/stackRepeater.count, 0.3, 0.7, 1)
+ Button { anchors.centerIn: parent; text: "Page " + (index + 1); onClicked: { stackLayout.advance() } }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/examples/quick/layouts/layouts.qmlproject b/examples/quick/layouts/layouts.qmlproject
new file mode 100644
index 0000000000..e5a8bf02ca
--- /dev/null
+++ b/examples/quick/layouts/layouts.qmlproject
@@ -0,0 +1,16 @@
+import QmlProject 1.1
+
+Project {
+ mainFile: "main.qml"
+
+ /* Include .qml, .js, and image files from current directory and subdirectories */
+ QmlFiles {
+ directory: "."
+ }
+ JavaScriptFiles {
+ directory: "."
+ }
+ ImageFiles {
+ directory: "."
+ }
+}
diff --git a/examples/quick/layouts/layouts.qrc b/examples/quick/layouts/layouts.qrc
new file mode 100644
index 0000000000..1e01c43fe1
--- /dev/null
+++ b/examples/quick/layouts/layouts.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/layouts">
+ <file>layouts.qml</file>
+</qresource>
+</RCC>
diff --git a/examples/quick/layouts/main.cpp b/examples/quick/layouts/main.cpp
new file mode 100644
index 0000000000..ef3e27a799
--- /dev/null
+++ b/examples/quick/layouts/main.cpp
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+
+int main(int argc, char* argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ QQmlApplicationEngine engine;
+ engine.load(QUrl(QStringLiteral("qrc:///layouts/layouts.qml")));
+
+ return app.exec();
+}
diff --git a/examples/quick/quick.pro b/examples/quick/quick.pro
index c5ef46173c..e66e24882e 100644
--- a/examples/quick/quick.pro
+++ b/examples/quick/quick.pro
@@ -6,6 +6,7 @@ SUBDIRS = quick-accessibility \
canvas \
imageelements \
keyinteraction \
+ layouts \
localstorage \
models \
views \
diff --git a/examples/quick/rendercontrol/window_singlethreaded.cpp b/examples/quick/rendercontrol/window_singlethreaded.cpp
index e43093e241..45f2635ca4 100644
--- a/examples/quick/rendercontrol/window_singlethreaded.cpp
+++ b/examples/quick/rendercontrol/window_singlethreaded.cpp
@@ -265,9 +265,10 @@ void WindowSingleThreaded::startQuick(const QString &filename)
void WindowSingleThreaded::exposeEvent(QExposeEvent *)
{
if (isExposed()) {
- m_cubeRenderer->render(this, m_context, m_quickReady ? m_fbo->texture() : 0);
- if (!m_quickInitialized)
+ if (!m_quickInitialized) {
+ m_cubeRenderer->render(this, m_context, m_quickReady ? m_fbo->texture() : 0);
startQuick(QStringLiteral("qrc:/rendercontrol/demo.qml"));
+ }
}
}
diff --git a/src/imports/imports.pro b/src/imports/imports.pro
index f7002f9ed5..ff7b6e75af 100644
--- a/src/imports/imports.pro
+++ b/src/imports/imports.pro
@@ -10,6 +10,7 @@ SUBDIRS += \
qtHaveModule(quick) {
SUBDIRS += \
+ layouts \
qtquick2 \
particles \
window \
diff --git a/src/imports/layouts/layouts.pro b/src/imports/layouts/layouts.pro
new file mode 100644
index 0000000000..26574150de
--- /dev/null
+++ b/src/imports/layouts/layouts.pro
@@ -0,0 +1,22 @@
+CXX_MODULE = qml
+TARGET = qquicklayoutsplugin
+TARGETPATH = QtQuick/Layouts
+IMPORT_VERSION = 1.2
+
+QT *= qml-private quick-private gui-private core-private
+
+SOURCES += plugin.cpp \
+ qquicklayout.cpp \
+ qquicklinearlayout.cpp \
+ qquickstacklayout.cpp \
+ qquickgridlayoutengine.cpp \
+ qquicklayoutstyleinfo.cpp
+
+HEADERS += \
+ qquicklayout_p.h \
+ qquicklinearlayout_p.h \
+ qquickstacklayout_p.h \
+ qquickgridlayoutengine_p.h \
+ qquicklayoutstyleinfo_p.h
+
+load(qml_plugin)
diff --git a/src/imports/layouts/plugin.cpp b/src/imports/layouts/plugin.cpp
new file mode 100644
index 0000000000..4552b7219b
--- /dev/null
+++ b/src/imports/layouts/plugin.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Layouts module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtQml/qqmlextensionplugin.h>
+
+#include "qquicklinearlayout_p.h"
+#include "qquickstacklayout_p.h"
+
+QT_BEGIN_NAMESPACE
+
+//![class decl]
+class QtQuickLayoutsPlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
+public:
+ virtual void registerTypes(const char *uri)
+ {
+ Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQuick.Layouts"));
+ Q_UNUSED(uri);
+
+ qmlRegisterType<QQuickRowLayout>(uri, 1, 0, "RowLayout");
+ qmlRegisterType<QQuickColumnLayout>(uri, 1, 0, "ColumnLayout");
+ qmlRegisterType<QQuickGridLayout>(uri, 1, 0, "GridLayout");
+ qmlRegisterType<QQuickStackLayout>(uri, 1, 3, "StackLayout");
+ qmlRegisterUncreatableType<QQuickLayout>(uri, 1, 0, "Layout",
+ QStringLiteral("Do not create objects of type Layout"));
+ qmlRegisterUncreatableType<QQuickLayout>(uri, 1, 2, "Layout",
+ QStringLiteral("Do not create objects of type Layout"));
+ qmlRegisterRevision<QQuickGridLayoutBase, 1>(uri, 1, 1);
+ }
+};
+//![class decl]
+
+QT_END_NAMESPACE
+
+#include "plugin.moc"
diff --git a/src/imports/layouts/plugins.qmltypes b/src/imports/layouts/plugins.qmltypes
new file mode 100644
index 0000000000..b130215b62
--- /dev/null
+++ b/src/imports/layouts/plugins.qmltypes
@@ -0,0 +1,102 @@
+import QtQuick.tooling 1.2
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated by:
+// 'qmlplugindump -nonrelocatable QtQuick.Layouts 1.2'
+
+Module {
+ dependencies: []
+ Component {
+ name: "QQuickColumnLayout"
+ defaultProperty: "data"
+ prototype: "QQuickLinearLayout"
+ exports: ["QtQuick.Layouts/ColumnLayout 1.0"]
+ exportMetaObjectRevisions: [0]
+ }
+ Component {
+ name: "QQuickGridLayout"
+ defaultProperty: "data"
+ prototype: "QQuickGridLayoutBase"
+ exports: ["QtQuick.Layouts/GridLayout 1.0"]
+ exportMetaObjectRevisions: [0]
+ Enum {
+ name: "Flow"
+ values: {
+ "LeftToRight": 0,
+ "TopToBottom": 1
+ }
+ }
+ Property { name: "columnSpacing"; type: "double" }
+ Property { name: "rowSpacing"; type: "double" }
+ Property { name: "columns"; type: "int" }
+ Property { name: "rows"; type: "int" }
+ Property { name: "flow"; type: "Flow" }
+ }
+ Component {
+ name: "QQuickGridLayoutBase"
+ defaultProperty: "data"
+ prototype: "QQuickLayout"
+ Property { name: "layoutDirection"; revision: 1; type: "Qt::LayoutDirection" }
+ Signal { name: "layoutDirectionChanged"; revision: 1 }
+ }
+ Component {
+ name: "QQuickLayout"
+ defaultProperty: "data"
+ prototype: "QQuickItem"
+ exports: ["QtQuick.Layouts/Layout 1.0", "QtQuick.Layouts/Layout 1.2"]
+ isCreatable: false
+ exportMetaObjectRevisions: [0, 0]
+ attachedType: "QQuickLayoutAttached"
+ }
+ Component {
+ name: "QQuickLayoutAttached"
+ prototype: "QObject"
+ Property { name: "minimumWidth"; type: "double" }
+ Property { name: "minimumHeight"; type: "double" }
+ Property { name: "preferredWidth"; type: "double" }
+ Property { name: "preferredHeight"; type: "double" }
+ Property { name: "maximumWidth"; type: "double" }
+ Property { name: "maximumHeight"; type: "double" }
+ Property { name: "fillHeight"; type: "bool" }
+ Property { name: "fillWidth"; type: "bool" }
+ Property { name: "row"; type: "int" }
+ Property { name: "column"; type: "int" }
+ Property { name: "rowSpan"; type: "int" }
+ Property { name: "columnSpan"; type: "int" }
+ Property { name: "alignment"; type: "Qt::Alignment" }
+ Property { name: "margins"; type: "double" }
+ Property { name: "leftMargin"; type: "double" }
+ Property { name: "topMargin"; type: "double" }
+ Property { name: "rightMargin"; type: "double" }
+ Property { name: "bottomMargin"; type: "double" }
+ }
+ Component {
+ name: "QQuickLinearLayout"
+ defaultProperty: "data"
+ prototype: "QQuickGridLayoutBase"
+ Property { name: "spacing"; type: "double" }
+ }
+ Component {
+ name: "QQuickRowLayout"
+ defaultProperty: "data"
+ prototype: "QQuickLinearLayout"
+ exports: ["QtQuick.Layouts/RowLayout 1.0"]
+ exportMetaObjectRevisions: [0]
+ }
+ Component {
+ name: "QQuickStackLayout"
+ defaultProperty: "data"
+ prototype: "QQuickLayout"
+ exports: ["QtQuick.Layouts/StackLayout 1.3"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "count"; type: "int"; isReadonly: true }
+ Property { name: "currentIndex"; type: "int" }
+ Method {
+ name: "itemAt"
+ type: "QQuickItem*"
+ Parameter { name: "index"; type: "int" }
+ }
+ }
+}
diff --git a/src/imports/layouts/qmldir b/src/imports/layouts/qmldir
new file mode 100644
index 0000000000..00f85f7d64
--- /dev/null
+++ b/src/imports/layouts/qmldir
@@ -0,0 +1,5 @@
+module QtQuick.Layouts
+plugin qquicklayoutsplugin
+classname QtQuickLayoutsPlugin
+typeinfo plugins.qmltypes
+designersupported
diff --git a/src/imports/layouts/qquickgridlayoutengine.cpp b/src/imports/layouts/qquickgridlayoutengine.cpp
new file mode 100644
index 0000000000..fe716f0694
--- /dev/null
+++ b/src/imports/layouts/qquickgridlayoutengine.cpp
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Layouts module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickitem.h"
+#include "qquickgridlayoutengine_p.h"
+#include "qquicklayout_p.h"
+
+QT_BEGIN_NAMESPACE
+
+void QQuickGridLayoutEngine::setAlignment(QQuickItem *quickItem, Qt::Alignment alignment)
+{
+ if (QQuickGridLayoutItem *item = findLayoutItem(quickItem)) {
+ item->setAlignment(alignment);
+ invalidate();
+ }
+}
+
+Qt::Alignment QQuickGridLayoutEngine::alignment(QQuickItem *quickItem) const
+{
+ if (QGridLayoutItem *item = findLayoutItem(quickItem))
+ return item->alignment();
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/imports/layouts/qquickgridlayoutengine_p.h b/src/imports/layouts/qquickgridlayoutengine_p.h
new file mode 100644
index 0000000000..86f56a5af4
--- /dev/null
+++ b/src/imports/layouts/qquickgridlayoutengine_p.h
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Layouts module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKGRIDLAYOUTENGINE_P_H
+#define QQUICKGRIDLAYOUTENGINE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the graphics view layout classes. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qgridlayoutengine_p.h>
+#include <QtGui/private/qlayoutpolicy_p.h>
+#include <QtCore/qmath.h>
+
+#include "qquickitem.h"
+#include "qquicklayout_p.h"
+#include "qdebug.h"
+QT_BEGIN_NAMESPACE
+
+class QQuickGridLayoutItem : public QGridLayoutItem {
+public:
+ QQuickGridLayoutItem(QQuickItem *item, int row, int column,
+ int rowSpan = 1, int columnSpan = 1, Qt::Alignment alignment = 0)
+ : QGridLayoutItem(row, column, rowSpan, columnSpan, alignment), m_item(item), sizeHintCacheDirty(true), useFallbackToWidthOrHeight(true) {}
+
+
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+ {
+ Q_UNUSED(constraint); // Quick Layouts does not support constraint atm
+ return effectiveSizeHints()[which];
+ }
+
+ QSizeF *effectiveSizeHints() const
+ {
+ if (!sizeHintCacheDirty)
+ return cachedSizeHints;
+
+ QQuickLayout::effectiveSizeHints_helper(m_item, cachedSizeHints, 0, useFallbackToWidthOrHeight);
+ useFallbackToWidthOrHeight = false;
+
+ sizeHintCacheDirty = false;
+ return cachedSizeHints;
+ }
+
+ void setCachedSizeHints(QSizeF *sizeHints)
+ {
+ for (int i = 0; i < Qt::NSizeHints; ++i) {
+ cachedSizeHints[i] = sizeHints[i];
+ }
+ sizeHintCacheDirty = false;
+ }
+
+ void invalidate()
+ {
+ quickLayoutDebug() << "engine::invalidate()";
+ sizeHintCacheDirty = true;
+ }
+
+ QLayoutPolicy::Policy sizePolicy(Qt::Orientation orientation) const
+ {
+ return QQuickLayout::effectiveSizePolicy_helper(m_item, orientation, attachedLayoutObject(m_item, false));
+ }
+
+ void setGeometry(const QRectF &rect)
+ {
+ QQuickLayoutAttached *info = attachedLayoutObject(m_item, false);
+ const QRectF r = info ? rect.marginsRemoved(info->qMargins()) : rect;
+ const QSizeF oldSize(m_item->width(), m_item->height());
+ const QSizeF newSize = r.size();
+ m_item->setPosition(r.topLeft());
+ if (newSize == oldSize) {
+ if (QQuickLayout *lay = qobject_cast<QQuickLayout *>(m_item)) {
+ if (lay->arrangementIsDirty())
+ lay->rearrange(newSize);
+ }
+ } else {
+ m_item->setSize(newSize);
+ }
+ }
+
+ QQuickItem *layoutItem() const { return m_item; }
+
+ QQuickItem *m_item;
+private:
+ mutable QSizeF cachedSizeHints[Qt::NSizeHints];
+ mutable unsigned sizeHintCacheDirty : 1;
+ mutable unsigned useFallbackToWidthOrHeight : 1;
+};
+
+class QQuickGridLayoutEngine : public QGridLayoutEngine {
+public:
+ QQuickGridLayoutEngine() : QGridLayoutEngine(Qt::AlignVCenter, true /*snapToPixelGrid*/) { }
+
+ int indexOf(QQuickItem *item) const {
+ for (int i = 0; i < q_items.size(); ++i) {
+ if (item == static_cast<QQuickGridLayoutItem*>(q_items.at(i))->layoutItem())
+ return i;
+ }
+ return -1;
+ }
+
+ QQuickGridLayoutItem *findLayoutItem(QQuickItem *layoutItem) const
+ {
+ for (int i = q_items.count() - 1; i >= 0; --i) {
+ QQuickGridLayoutItem *item = static_cast<QQuickGridLayoutItem*>(q_items.at(i));
+ if (item->layoutItem() == layoutItem)
+ return item;
+ }
+ return 0;
+ }
+
+ void setAlignment(QQuickItem *quickItem, Qt::Alignment alignment);
+ Qt::Alignment alignment(QQuickItem *quickItem) const;
+
+};
+
+
+
+QT_END_NAMESPACE
+
+#endif // QQUICKGRIDLAYOUTENGINE_P_H
diff --git a/src/imports/layouts/qquicklayout.cpp b/src/imports/layouts/qquicklayout.cpp
new file mode 100644
index 0000000000..d4d4e1703d
--- /dev/null
+++ b/src/imports/layouts/qquicklayout.cpp
@@ -0,0 +1,1081 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Layouts module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquicklayout_p.h"
+#include <QEvent>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qnumeric.h>
+#include <QtCore/qmath.h>
+#include <limits>
+
+/*!
+ \qmltype Layout
+ \instantiates QQuickLayoutAttached
+ \inqmlmodule QtQuick.Layouts
+ \ingroup layouts
+ \brief Provides attached properties for items pushed onto a \l GridLayout,
+ \l RowLayout or \l ColumnLayout.
+
+ An object of type Layout is attached to children of the layout to provide layout specific
+ information about the item.
+ The properties of the attached object influence how the layout will arrange the items.
+
+ For instance, you can specify \l minimumWidth, \l preferredWidth, and
+ \l maximumWidth if the default values are not satisfactory.
+
+ When a layout is resized, items may grow or shrink. Due to this, items have a
+ \l{Layout::minimumWidth}{minimum size}, \l{Layout::preferredWidth}{preferred size} and a
+ \l{Layout::maximumWidth}{maximum size}.
+
+ If minimum size has not been explicitly specified on an item, the size is set to \c 0.
+ If maximum size has not been explicitly specified on an item, the size is set to
+ \c Number.POSITIVE_INFINITY.
+
+ For layouts, the implicit minimum and maximum sizes depend on the content of the layouts.
+
+ The \l fillWidth and \l fillHeight properties can either be \c true or \c false. If they are \c
+ false, the item's size will be fixed to its preferred size. Otherwise, it will grow or shrink
+ between its minimum and maximum size as the layout is resized.
+
+ \note It is not recommended to have bindings to the x, y, width, or height properties of items
+ in a layout, since this would conflict with the goals of Layout, and can also cause binding
+ loops.
+
+
+ \sa GridLayout
+ \sa RowLayout
+ \sa ColumnLayout
+*/
+
+QT_BEGIN_NAMESPACE
+
+QQuickLayoutAttached::QQuickLayoutAttached(QObject *parent)
+ : QObject(parent),
+ m_minimumWidth(0),
+ m_minimumHeight(0),
+ m_preferredWidth(-1),
+ m_preferredHeight(-1),
+ m_maximumWidth(std::numeric_limits<qreal>::infinity()),
+ m_maximumHeight(std::numeric_limits<qreal>::infinity()),
+ m_defaultMargins(0),
+ m_row(-1),
+ m_column(-1),
+ m_rowSpan(1),
+ m_columnSpan(1),
+ m_fillWidth(false),
+ m_fillHeight(false),
+ m_isFillWidthSet(false),
+ m_isFillHeightSet(false),
+ m_isMinimumWidthSet(false),
+ m_isMinimumHeightSet(false),
+ m_isMaximumWidthSet(false),
+ m_isMaximumHeightSet(false),
+ m_changesNotificationEnabled(true),
+ m_isLeftMarginSet(false),
+ m_isTopMarginSet(false),
+ m_isRightMarginSet(false),
+ m_isBottomMarginSet(false),
+ m_alignment(0)
+{
+
+}
+
+/*!
+ \qmlattachedproperty real Layout::minimumWidth
+
+ This property holds the minimum width of an item in a layout.
+ The default value is the item's implicit minimum width.
+
+ If the item is a layout, the implicit minimum width will be the minimum width the layout can
+ have without any of its items shrinking below their minimum width.
+ The implicit minimum width for any other item is \c 0.
+
+ Setting this value to -1 will reset the width back to its implicit minimum width.
+
+
+ \sa preferredWidth
+ \sa maximumWidth
+*/
+void QQuickLayoutAttached::setMinimumWidth(qreal width)
+{
+ if (qIsNaN(width))
+ return;
+ m_isMinimumWidthSet = width >= 0;
+ if (m_minimumWidth == width)
+ return;
+
+ m_minimumWidth = width;
+ invalidateItem();
+ emit minimumWidthChanged();
+}
+
+/*!
+ \qmlattachedproperty real Layout::minimumHeight
+
+ This property holds the minimum height of an item in a layout.
+ The default value is the item's implicit minimum height.
+
+ If the item is a layout, the implicit minimum height will be the minimum height the layout can
+ have without any of its items shrinking below their minimum height.
+ The implicit minimum height for any other item is \c 0.
+
+ Setting this value to -1 will reset the height back to its implicit minimum height.
+
+ \sa preferredHeight
+ \sa maximumHeight
+*/
+void QQuickLayoutAttached::setMinimumHeight(qreal height)
+{
+ if (qIsNaN(height))
+ return;
+ m_isMinimumHeightSet = height >= 0;
+ if (m_minimumHeight == height)
+ return;
+
+ m_minimumHeight = height;
+ invalidateItem();
+ emit minimumHeightChanged();
+}
+
+/*!
+ \qmlattachedproperty real Layout::preferredWidth
+
+ This property holds the preferred width of an item in a layout.
+ If the preferred width is \c -1 it will be ignored, and the layout
+ will use \l{Item::implicitWidth}{implicitWidth} instead.
+ The default is \c -1.
+
+ \sa minimumWidth
+ \sa maximumWidth
+*/
+void QQuickLayoutAttached::setPreferredWidth(qreal width)
+{
+ if (qIsNaN(width) || m_preferredWidth == width)
+ return;
+
+ m_preferredWidth = width;
+ invalidateItem();
+ emit preferredWidthChanged();
+}
+
+/*!
+ \qmlattachedproperty real Layout::preferredHeight
+
+ This property holds the preferred height of an item in a layout.
+ If the preferred height is \c -1 it will be ignored, and the layout
+ will use \l{Item::implicitHeight}{implicitHeight} instead.
+ The default is \c -1.
+
+ \sa minimumHeight
+ \sa maximumHeight
+*/
+void QQuickLayoutAttached::setPreferredHeight(qreal height)
+{
+ if (qIsNaN(height) || m_preferredHeight == height)
+ return;
+
+ m_preferredHeight = height;
+ invalidateItem();
+ emit preferredHeightChanged();
+}
+
+/*!
+ \qmlattachedproperty real Layout::maximumWidth
+
+ This property holds the maximum width of an item in a layout.
+ The default value is the item's implicit maximum width.
+
+ If the item is a layout, the implicit maximum width will be the maximum width the layout can
+ have without any of its items growing beyond their maximum width.
+ The implicit maximum width for any other item is \c Number.POSITIVE_INFINITY.
+
+ Setting this value to \c -1 will reset the width back to its implicit maximum width.
+
+ \sa minimumWidth
+ \sa preferredWidth
+*/
+void QQuickLayoutAttached::setMaximumWidth(qreal width)
+{
+ if (qIsNaN(width))
+ return;
+ m_isMaximumWidthSet = width >= 0;
+ if (m_maximumWidth == width)
+ return;
+
+ m_maximumWidth = width;
+ invalidateItem();
+ emit maximumWidthChanged();
+}
+
+/*!
+ \qmlattachedproperty real Layout::maximumHeight
+
+ The default value is the item's implicit maximum height.
+
+ If the item is a layout, the implicit maximum height will be the maximum height the layout can
+ have without any of its items growing beyond their maximum height.
+ The implicit maximum height for any other item is \c Number.POSITIVE_INFINITY.
+
+ Setting this value to \c -1 will reset the height back to its implicit maximum height.
+
+ \sa minimumHeight
+ \sa preferredHeight
+*/
+void QQuickLayoutAttached::setMaximumHeight(qreal height)
+{
+ if (qIsNaN(height))
+ return;
+ m_isMaximumHeightSet = height >= 0;
+ if (m_maximumHeight == height)
+ return;
+
+ m_maximumHeight = height;
+ invalidateItem();
+ emit maximumHeightChanged();
+}
+
+void QQuickLayoutAttached::setMinimumImplicitSize(const QSizeF &sz)
+{
+ bool emitWidthChanged = false;
+ bool emitHeightChanged = false;
+ if (!m_isMinimumWidthSet && m_minimumWidth != sz.width()) {
+ m_minimumWidth = sz.width();
+ emitWidthChanged = true;
+ }
+ if (!m_isMinimumHeightSet && m_minimumHeight != sz.height()) {
+ m_minimumHeight = sz.height();
+ emitHeightChanged = true;
+ }
+ // Only invalidate the item once, and make sure we emit signal changed after the call to
+ // invalidateItem()
+ if (emitWidthChanged || emitHeightChanged) {
+ invalidateItem();
+ if (emitWidthChanged)
+ emit minimumWidthChanged();
+ if (emitHeightChanged)
+ emit minimumHeightChanged();
+ }
+}
+
+void QQuickLayoutAttached::setMaximumImplicitSize(const QSizeF &sz)
+{
+ bool emitWidthChanged = false;
+ bool emitHeightChanged = false;
+ if (!m_isMaximumWidthSet && m_maximumWidth != sz.width()) {
+ m_maximumWidth = sz.width();
+ emitWidthChanged = true;
+ }
+ if (!m_isMaximumHeightSet && m_maximumHeight != sz.height()) {
+ m_maximumHeight = sz.height();
+ emitHeightChanged = true;
+ }
+ // Only invalidate the item once, and make sure we emit changed signal after the call to
+ // invalidateItem()
+ if (emitWidthChanged || emitHeightChanged) {
+ invalidateItem();
+ if (emitWidthChanged)
+ emit maximumWidthChanged();
+ if (emitHeightChanged)
+ emit maximumHeightChanged();
+ }
+}
+
+/*!
+ \qmlattachedproperty bool Layout::fillWidth
+
+ If this property is \c true, the item will be as wide as possible while respecting
+ the given constraints. If the property is \c false, the item will have a fixed width
+ set to the preferred width.
+ The default is \c false, except for layouts themselves, which default to \c true.
+
+ \sa fillHeight
+*/
+void QQuickLayoutAttached::setFillWidth(bool fill)
+{
+ m_isFillWidthSet = true;
+ if (m_fillWidth != fill) {
+ m_fillWidth = fill;
+ invalidateItem();
+ emit fillWidthChanged();
+ }
+}
+
+/*!
+ \qmlattachedproperty bool Layout::fillHeight
+
+ If this property is \c true, the item will be as tall as possible while respecting
+ the given constraints. If the property is \c false, the item will have a fixed height
+ set to the preferred height.
+ The default is \c false, except for layouts themselves, which default to \c true.
+
+ \sa fillWidth
+*/
+void QQuickLayoutAttached::setFillHeight(bool fill)
+{
+ m_isFillHeightSet = true;
+ if (m_fillHeight != fill) {
+ m_fillHeight = fill;
+ invalidateItem();
+ emit fillHeightChanged();
+ }
+}
+
+/*!
+ \qmlattachedproperty int Layout::row
+
+ This property allows you to specify the row position of an item in a \l GridLayout.
+
+ If both \l column and this property are not set, it is up to the layout to assign a cell to the item.
+
+ The default value is \c 0.
+
+ \sa column
+ \sa rowSpan
+*/
+void QQuickLayoutAttached::setRow(int row)
+{
+ if (row >= 0 && row != m_row) {
+ m_row = row;
+ repopulateLayout();
+ emit rowChanged();
+ }
+}
+
+/*!
+ \qmlattachedproperty int Layout::column
+
+ This property allows you to specify the column position of an item in a \l GridLayout.
+
+ If both \l row and this property are not set, it is up to the layout to assign a cell to the item.
+
+ The default value is \c 0.
+
+ \sa row
+ \sa columnSpan
+*/
+void QQuickLayoutAttached::setColumn(int column)
+{
+ if (column >= 0 && column != m_column) {
+ m_column = column;
+ repopulateLayout();
+ emit columnChanged();
+ }
+}
+
+
+/*!
+ \qmlattachedproperty Qt.Alignment Layout::alignment
+
+ This property allows you to specify the alignment of an item within the cell(s) it occupies.
+
+ The default value is \c 0, which means it will be \c{Qt.AlignVCenter | Qt.AlignLeft}
+
+ A valid alignment is a combination of the following flags:
+ \list
+ \li Qt::AlignLeft
+ \li Qt::AlignHCenter
+ \li Qt::AlignRight
+ \li Qt::AlignTop
+ \li Qt::AlignVCenter
+ \li Qt::AlignBottom
+ \li Qt::AlignBaseline
+ \endlist
+
+*/
+void QQuickLayoutAttached::setAlignment(Qt::Alignment align)
+{
+ if (align != m_alignment) {
+ m_alignment = align;
+ if (QQuickLayout *layout = parentLayout()) {
+ layout->setAlignment(item(), align);
+ invalidateItem();
+ }
+ emit alignmentChanged();
+ }
+}
+
+/*!
+ \qmlattachedproperty real Layout::margins
+
+ Sets the margins outside of an item to all have the same value. The item
+ itself does not evaluate its own margins. It is the parent's responsibility
+ to decide if it wants to evaluate the margins.
+
+ Specifically, margins are only evaluated by ColumnLayout, RowLayout,
+ GridLayout, and other layout-like containers, such as SplitView, where the
+ effective cell size of an item will be increased as the margins are
+ increased.
+
+ Therefore, if an item with margins is a child of another \c Item, its
+ position, size and implicit size will remain unchanged.
+
+ Combining margins with alignment will align the item \e including its
+ margins. For instance, a vertically-centered Item with a top margin of \c 1
+ and a bottom margin of \c 9 will cause the Items effective alignment within
+ the cell to be 4 pixels above the center.
+
+ The default value is \c 0.
+
+ \sa leftMargin
+ \sa topMargin
+ \sa rightMargin
+ \sa bottomMargin
+
+ \since QtQuick.Layouts 1.2
+*/
+void QQuickLayoutAttached::setMargins(qreal m)
+{
+ if (m == m_defaultMargins)
+ return;
+
+ m_defaultMargins = m;
+ invalidateItem();
+ if (!m_isLeftMarginSet && m_margins.left() != m)
+ emit leftMarginChanged();
+ if (!m_isTopMarginSet && m_margins.top() != m)
+ emit topMarginChanged();
+ if (!m_isRightMarginSet && m_margins.right() != m)
+ emit rightMarginChanged();
+ if (!m_isBottomMarginSet && m_margins.bottom() != m)
+ emit bottomMarginChanged();
+ emit marginsChanged();
+}
+
+/*!
+ \qmlattachedproperty real Layout::leftMargin
+
+ Specifies the left margin outside of an item.
+ If the value is not set, it will use the value from \l margins.
+
+ \sa margins
+
+ \since QtQuick.Layouts 1.2
+*/
+void QQuickLayoutAttached::setLeftMargin(qreal m)
+{
+ const bool changed = leftMargin() != m;
+ m_margins.setLeft(m);
+ m_isLeftMarginSet = true;
+ if (changed) {
+ invalidateItem();
+ emit leftMarginChanged();
+ }
+}
+
+void QQuickLayoutAttached::resetLeftMargin()
+{
+ const bool changed = m_isLeftMarginSet && (m_defaultMargins != m_margins.left());
+ m_isLeftMarginSet = false;
+ if (changed) {
+ invalidateItem();
+ emit leftMarginChanged();
+ }
+}
+
+/*!
+ \qmlattachedproperty real Layout::topMargin
+
+ Specifies the top margin outside of an item.
+ If the value is not set, it will use the value from \l margins.
+
+ \sa margins
+
+ \since QtQuick.Layouts 1.2
+*/
+void QQuickLayoutAttached::setTopMargin(qreal m)
+{
+ const bool changed = topMargin() != m;
+ m_margins.setTop(m);
+ m_isTopMarginSet = true;
+ if (changed) {
+ invalidateItem();
+ emit topMarginChanged();
+ }
+}
+
+void QQuickLayoutAttached::resetTopMargin()
+{
+ const bool changed = m_isTopMarginSet && (m_defaultMargins != m_margins.top());
+ m_isTopMarginSet = false;
+ if (changed) {
+ invalidateItem();
+ emit topMarginChanged();
+ }
+}
+
+/*!
+ \qmlattachedproperty real Layout::rightMargin
+
+ Specifies the right margin outside of an item.
+ If the value is not set, it will use the value from \l margins.
+
+ \sa margins
+
+ \since QtQuick.Layouts 1.2
+*/
+void QQuickLayoutAttached::setRightMargin(qreal m)
+{
+ const bool changed = rightMargin() != m;
+ m_margins.setRight(m);
+ m_isRightMarginSet = true;
+ if (changed) {
+ invalidateItem();
+ emit rightMarginChanged();
+ }
+}
+
+void QQuickLayoutAttached::resetRightMargin()
+{
+ const bool changed = m_isRightMarginSet && (m_defaultMargins != m_margins.right());
+ m_isRightMarginSet = false;
+ if (changed) {
+ invalidateItem();
+ emit rightMarginChanged();
+ }
+}
+
+/*!
+ \qmlattachedproperty real Layout::bottomMargin
+
+ Specifies the bottom margin outside of an item.
+ If the value is not set, it will use the value from \l margins.
+
+ \sa margins
+
+ \since QtQuick.Layouts 1.2
+*/
+void QQuickLayoutAttached::setBottomMargin(qreal m)
+{
+ const bool changed = bottomMargin() != m;
+ m_margins.setBottom(m);
+ m_isBottomMarginSet = true;
+ if (changed) {
+ invalidateItem();
+ emit bottomMarginChanged();
+ }
+}
+
+void QQuickLayoutAttached::resetBottomMargin()
+{
+ const bool changed = m_isBottomMarginSet && (m_defaultMargins != m_margins.bottom());
+ m_isBottomMarginSet = false;
+ if (changed) {
+ invalidateItem();
+ emit bottomMarginChanged();
+ }
+}
+
+
+/*!
+ \qmlattachedproperty int Layout::rowSpan
+
+ This property allows you to specify the row span of an item in a \l GridLayout.
+
+ The default value is \c 1.
+
+ \sa columnSpan
+ \sa row
+*/
+void QQuickLayoutAttached::setRowSpan(int span)
+{
+ if (span != m_rowSpan) {
+ m_rowSpan = span;
+ repopulateLayout();
+ emit rowSpanChanged();
+ }
+}
+
+
+/*!
+ \qmlattachedproperty int Layout::columnSpan
+
+ This property allows you to specify the column span of an item in a \l GridLayout.
+
+ The default value is \c 1.
+
+ \sa rowSpan
+ \sa column
+*/
+void QQuickLayoutAttached::setColumnSpan(int span)
+{
+ if (span != m_columnSpan) {
+ m_columnSpan = span;
+ repopulateLayout();
+ emit columnSpanChanged();
+ }
+}
+
+
+qreal QQuickLayoutAttached::sizeHint(Qt::SizeHint which, Qt::Orientation orientation) const
+{
+ qreal result = 0;
+ if (QQuickLayout *layout = qobject_cast<QQuickLayout *>(item())) {
+ const QSizeF sz = layout->sizeHint(which);
+ result = (orientation == Qt::Horizontal ? sz.width() : sz.height());
+ } else {
+ if (which == Qt::MaximumSize)
+ result = std::numeric_limits<qreal>::infinity();
+ }
+ return result;
+}
+
+void QQuickLayoutAttached::invalidateItem()
+{
+ if (!m_changesNotificationEnabled)
+ return;
+ quickLayoutDebug() << "QQuickLayoutAttached::invalidateItem";
+ if (QQuickLayout *layout = parentLayout()) {
+ layout->invalidate(item());
+ }
+}
+
+void QQuickLayoutAttached::repopulateLayout()
+{
+ if (QQuickLayout *layout = parentLayout())
+ layout->updateLayoutItems();
+}
+
+QQuickLayout *QQuickLayoutAttached::parentLayout() const
+{
+ QQuickItem *parentItem = item();
+ if (parentItem) {
+ parentItem = parentItem->parentItem();
+ return qobject_cast<QQuickLayout *>(parentItem);
+ } else {
+ qWarning("Layout must be attached to Item elements");
+ }
+ return 0;
+}
+
+QQuickItem *QQuickLayoutAttached::item() const
+{
+ return qobject_cast<QQuickItem *>(parent());
+}
+
+
+QQuickLayout::QQuickLayout(QQuickLayoutPrivate &dd, QQuickItem *parent)
+ : QQuickItem(dd, parent),
+ m_dirty(false)
+{
+}
+
+QQuickLayout::~QQuickLayout()
+{
+ d_func()->m_isReady = false;
+}
+
+QQuickLayoutAttached *QQuickLayout::qmlAttachedProperties(QObject *object)
+{
+ return new QQuickLayoutAttached(object);
+}
+
+void QQuickLayout::updatePolish()
+{
+ rearrange(QSizeF(width(), height()));
+}
+
+void QQuickLayout::componentComplete()
+{
+ Q_D(QQuickLayout);
+ d->m_disableRearrange = true;
+ QQuickItem::componentComplete(); // will call our geometryChanged(), (where isComponentComplete() == true)
+ d->m_disableRearrange = false;
+ d->m_isReady = true;
+}
+
+void QQuickLayout::invalidate(QQuickItem * /*childItem*/)
+{
+ if (m_dirty)
+ return;
+
+ m_dirty = true;
+
+ if (!qobject_cast<QQuickLayout *>(parentItem())) {
+ quickLayoutDebug() << "QQuickLayout::invalidate(), polish()";
+ polish();
+ }
+}
+
+bool QQuickLayout::shouldIgnoreItem(QQuickItem *child, QQuickLayoutAttached *&info, QSizeF *sizeHints) const
+{
+ Q_D(const QQuickLayout);
+ bool ignoreItem = true;
+ QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child);
+ if (childPrivate->explicitVisible) {
+ effectiveSizeHints_helper(child, sizeHints, &info, true);
+ QSizeF effectiveMaxSize = sizeHints[Qt::MaximumSize];
+ if (!effectiveMaxSize.isNull()) {
+ QSizeF &prefS = sizeHints[Qt::PreferredSize];
+ if (effectiveSizePolicy_helper(child, Qt::Horizontal, info) == QLayoutPolicy::Fixed)
+ effectiveMaxSize.setWidth(prefS.width());
+ if (effectiveSizePolicy_helper(child, Qt::Vertical, info) == QLayoutPolicy::Fixed)
+ effectiveMaxSize.setHeight(prefS.height());
+ }
+ ignoreItem = effectiveMaxSize.isNull();
+ }
+
+ if (ignoreItem)
+ d->m_ignoredItems << child;
+ return ignoreItem;
+}
+struct QQuickItemPublic : public QQuickItem {
+ static bool isCompleted(QQuickItem *item) {
+ return static_cast<QQuickItemPublic*>(item)->isComponentComplete();
+ }
+};
+
+void QQuickLayout::itemChange(ItemChange change, const ItemChangeData &value)
+{
+ if (change == ItemChildAddedChange) {
+ QQuickItem *item = value.item;
+ QObject::connect(item, SIGNAL(implicitWidthChanged()), this, SLOT(invalidateSenderItem()));
+ QObject::connect(item, SIGNAL(implicitHeightChanged()), this, SLOT(invalidateSenderItem()));
+ QObject::connect(item, SIGNAL(baselineOffsetChanged(qreal)), this, SLOT(invalidateSenderItem()));
+ QQuickItemPrivate::get(item)->addItemChangeListener(this, QQuickItemPrivate::SiblingOrder);
+ if (isReady())
+ updateLayoutItems();
+ } else if (change == ItemChildRemovedChange) {
+ QQuickItem *item = value.item;
+ QObject::disconnect(item, SIGNAL(implicitWidthChanged()), this, SLOT(invalidateSenderItem()));
+ QObject::disconnect(item, SIGNAL(implicitHeightChanged()), this, SLOT(invalidateSenderItem()));
+ QObject::disconnect(item, SIGNAL(baselineOffsetChanged(qreal)), this, SLOT(invalidateSenderItem()));
+ QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::SiblingOrder);
+ if (isReady())
+ updateLayoutItems();
+ }
+ QQuickItem::itemChange(change, value);
+}
+
+void QQuickLayout::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_D(QQuickLayout);
+ QQuickItem::geometryChanged(newGeometry, oldGeometry);
+ if (d->m_disableRearrange || !isReady() || !newGeometry.isValid())
+ return;
+
+ quickLayoutDebug() << "QQuickStackLayout::geometryChanged" << newGeometry << oldGeometry;
+ rearrange(newGeometry.size());
+}
+
+void QQuickLayout::invalidateSenderItem()
+{
+ if (!isReady())
+ return;
+ QQuickItem *item = static_cast<QQuickItem *>(sender());
+ Q_ASSERT(item);
+ invalidate(item);
+}
+
+bool QQuickLayout::isReady() const
+{
+ return d_func()->m_isReady;
+}
+
+void QQuickLayout::itemSiblingOrderChanged(QQuickItem *item)
+{
+ Q_UNUSED(item);
+ updateLayoutItems();
+}
+
+void QQuickLayout::rearrange(const QSizeF &/*size*/)
+{
+ m_dirty = false;
+}
+
+
+/*
+ The layout engine assumes:
+ 1. minimum <= preferred <= maximum
+ 2. descent is within minimum and maximum bounds (### verify)
+
+ This function helps to ensure that by the following rules (in the following order):
+ 1. If minimum > maximum, set minimum = maximum
+ 2. Clamp preferred to be between the [minimum,maximum] range.
+ 3. If descent > minimum, set descent = minimum (### verify if this is correct, it might
+ need some refinements to multiline texts)
+
+ If any values are "not set" (i.e. negative), they will be left untouched, so that we
+ know which values needs to be fetched from the implicit hints (not user hints).
+ */
+static void normalizeHints(qreal &minimum, qreal &preferred, qreal &maximum, qreal &descent)
+{
+ if (minimum >= 0 && maximum >= 0 && minimum > maximum)
+ minimum = maximum;
+
+ if (preferred >= 0) {
+ if (minimum >= 0 && preferred < minimum) {
+ preferred = minimum;
+ } else if (maximum >= 0 && preferred > maximum) {
+ preferred = maximum;
+ }
+ }
+
+ if (minimum >= 0 && descent > minimum)
+ descent = minimum;
+}
+
+static void boundSize(QSizeF &result, const QSizeF &size)
+{
+ if (size.width() >= 0 && size.width() < result.width())
+ result.setWidth(size.width());
+ if (size.height() >= 0 && size.height() < result.height())
+ result.setHeight(size.height());
+}
+
+static void expandSize(QSizeF &result, const QSizeF &size)
+{
+ if (size.width() >= 0 && size.width() > result.width())
+ result.setWidth(size.width());
+ if (size.height() >= 0 && size.height() > result.height())
+ result.setHeight(size.height());
+}
+
+static inline void combineHints(qreal &current, qreal fallbackHint)
+{
+ if (current < 0)
+ current = fallbackHint;
+}
+
+static inline void combineSize(QSizeF &result, const QSizeF &fallbackSize)
+{
+ combineHints(result.rwidth(), fallbackSize.width());
+ combineHints(result.rheight(), fallbackSize.height());
+}
+
+static inline void combineImplicitHints(QQuickLayoutAttached *info, Qt::SizeHint which, QSizeF *size)
+{
+ if (!info) return;
+
+ Q_ASSERT(which == Qt::MinimumSize || which == Qt::MaximumSize);
+
+ const QSizeF constraint(which == Qt::MinimumSize
+ ? QSizeF(info->minimumWidth(), info->minimumHeight())
+ : QSizeF(info->maximumWidth(), info->maximumHeight()));
+
+ if (!info->isExtentExplicitlySet(Qt::Horizontal, which))
+ combineHints(size->rwidth(), constraint.width());
+ if (!info->isExtentExplicitlySet(Qt::Vertical, which))
+ combineHints(size->rheight(), constraint.height());
+}
+
+typedef qreal (QQuickLayoutAttached::*SizeGetter)() const;
+
+/*!
+ \internal
+ Note: Can potentially return the attached QQuickLayoutAttached object through \a attachedInfo.
+
+ It is like this is because it enables it to be reused.
+
+ The goal of this function is to return the effective minimum, preferred and maximum size hints
+ that the layout will use for this item.
+ This function takes care of gathering all explicitly set size hints, normalizes them so
+ that min < pref < max.
+ Further, the hints _not_explicitly_ set will then be initialized with the implicit size hints,
+ which is usually derived from the content of the layouts (or items).
+
+ The following table illustrates the preference of the properties used for measuring layout
+ items. If present, the USER properties will be preferred. If USER properties are not present,
+ the HINT properties will be preferred. Finally, the FALLBACK properties will be used as an
+ ultimate fallback.
+
+ Note that one can query if the value of Layout.minimumWidth or Layout.maximumWidth has been
+ explicitly or implicitly set with QQuickLayoutAttached::isExtentExplicitlySet(). This
+ determines if it should be used as a USER or as a HINT value.
+
+ Fractional size hints will be ceiled to the closest integer. This is in order to give some
+ slack when the items are snapped to the pixel grid.
+
+ | *Minimum* | *Preferred* | *Maximum* |
++----------------+----------------------+-----------------------+--------------------------+
+|USER (explicit) | Layout.minimumWidth | Layout.preferredWidth | Layout.maximumWidth |
+|HINT (implicit) | Layout.minimumWidth | implicitWidth | Layout.maximumWidth |
+|FALLBACK | 0 | width | Number.POSITIVE_INFINITY |
++----------------+----------------------+-----------------------+--------------------------+
+ */
+void QQuickLayout::effectiveSizeHints_helper(QQuickItem *item, QSizeF *cachedSizeHints, QQuickLayoutAttached **attachedInfo, bool useFallbackToWidthOrHeight)
+{
+ for (int i = 0; i < Qt::NSizeHints; ++i)
+ cachedSizeHints[i] = QSizeF();
+ QQuickLayoutAttached *info = attachedLayoutObject(item, false);
+ // First, retrieve the user-specified hints from the attached "Layout." properties
+ if (info) {
+ struct Getters {
+ SizeGetter call[NSizes];
+ };
+
+ static Getters horGetters = {
+ {&QQuickLayoutAttached::minimumWidth, &QQuickLayoutAttached::preferredWidth, &QQuickLayoutAttached::maximumWidth},
+ };
+
+ static Getters verGetters = {
+ {&QQuickLayoutAttached::minimumHeight, &QQuickLayoutAttached::preferredHeight, &QQuickLayoutAttached::maximumHeight}
+ };
+ for (int i = 0; i < NSizes; ++i) {
+ SizeGetter getter = horGetters.call[i];
+ Q_ASSERT(getter);
+
+ if (info->isExtentExplicitlySet(Qt::Horizontal, (Qt::SizeHint)i))
+ cachedSizeHints[i].setWidth((info->*getter)());
+
+ getter = verGetters.call[i];
+ Q_ASSERT(getter);
+ if (info->isExtentExplicitlySet(Qt::Vertical, (Qt::SizeHint)i))
+ cachedSizeHints[i].setHeight((info->*getter)());
+ }
+ }
+
+ QSizeF &minS = cachedSizeHints[Qt::MinimumSize];
+ QSizeF &prefS = cachedSizeHints[Qt::PreferredSize];
+ QSizeF &maxS = cachedSizeHints[Qt::MaximumSize];
+ QSizeF &descentS = cachedSizeHints[Qt::MinimumDescent];
+
+ // For instance, will normalize the following user-set hints
+ // from: [10, 5, 60]
+ // to: [10, 10, 60]
+ normalizeHints(minS.rwidth(), prefS.rwidth(), maxS.rwidth(), descentS.rwidth());
+ normalizeHints(minS.rheight(), prefS.rheight(), maxS.rheight(), descentS.rheight());
+
+ // All explicit values gathered, now continue to gather the implicit sizes
+
+ //--- GATHER MAXIMUM SIZE HINTS ---
+ combineImplicitHints(info, Qt::MaximumSize, &maxS);
+ combineSize(maxS, QSizeF(std::numeric_limits<qreal>::infinity(), std::numeric_limits<qreal>::infinity()));
+ // implicit max or min sizes should not limit an explicitly set preferred size
+ expandSize(maxS, prefS);
+ expandSize(maxS, minS);
+
+ //--- GATHER MINIMUM SIZE HINTS ---
+ combineImplicitHints(info, Qt::MinimumSize, &minS);
+ expandSize(minS, QSizeF(0,0));
+ boundSize(minS, prefS);
+ boundSize(minS, maxS);
+
+ //--- GATHER PREFERRED SIZE HINTS ---
+ // First, from implicitWidth/Height
+ qreal &prefWidth = prefS.rwidth();
+ qreal &prefHeight = prefS.rheight();
+ if (prefWidth < 0 && item->implicitWidth() > 0)
+ prefWidth = qCeil(item->implicitWidth());
+ if (prefHeight < 0 && item->implicitHeight() > 0)
+ prefHeight = qCeil(item->implicitHeight());
+
+ // If that fails, make an ultimate fallback to width/height
+
+ if (!info && (prefWidth < 0 || prefHeight < 0))
+ info = attachedLayoutObject(item);
+
+ if (useFallbackToWidthOrHeight && info) {
+ /* This block is a bit hacky, but if we want to support using width/height
+ as preferred size hints in layouts, (which we think most people expect),
+ we only want to use the initial width.
+ This is because the width will change due to layout rearrangement, and the preferred
+ width should return the same value, regardless of the current width.
+ We therefore store the width in the implicitWidth attached property.
+ Since the layout listens to changes of implicitWidth, (it will
+ basically cause an invalidation of the layout), we have to disable that
+ notification while we set the implicit width (and height).
+
+ Only use this fallback the first time the size hint is queried. Otherwise, we might
+ end up picking a width that is different than what was specified in the QML.
+ */
+ if (prefWidth < 0 || prefHeight < 0) {
+ item->blockSignals(true);
+ if (prefWidth < 0) {
+ prefWidth = item->width();
+ item->setImplicitWidth(prefWidth);
+ }
+ if (prefHeight < 0) {
+ prefHeight = item->height();
+ item->setImplicitHeight(prefHeight);
+ }
+ item->blockSignals(false);
+ }
+ }
+
+
+
+ // Normalize again after the implicit hints have been gathered
+ expandSize(prefS, minS);
+ boundSize(prefS, maxS);
+
+ //--- GATHER DESCENT
+ // Minimum descent is only applicable for the effective minimum height,
+ // so we gather the descent last.
+ const qreal minimumDescent = minS.height() - item->baselineOffset();
+ descentS.setHeight(minimumDescent);
+
+ if (info) {
+ QMarginsF margins = info->qMargins();
+ QSizeF extraMargins(margins.left() + margins.right(), margins.top() + margins.bottom());
+ minS += extraMargins;
+ prefS += extraMargins;
+ maxS += extraMargins;
+ descentS += extraMargins;
+ }
+ if (attachedInfo)
+ *attachedInfo = info;
+}
+
+/*!
+ \internal
+
+ Assumes \a info is set (if the object has an attached property)
+ */
+QLayoutPolicy::Policy QQuickLayout::effectiveSizePolicy_helper(QQuickItem *item, Qt::Orientation orientation, QQuickLayoutAttached *info)
+{
+ bool fillExtent = false;
+ bool isSet = false;
+ if (info) {
+ if (orientation == Qt::Horizontal) {
+ isSet = info->isFillWidthSet();
+ if (isSet) fillExtent = info->fillWidth();
+ } else {
+ isSet = info->isFillHeightSet();
+ if (isSet) fillExtent = info->fillHeight();
+ }
+ }
+ if (!isSet && qobject_cast<QQuickLayout*>(item))
+ fillExtent = true;
+ return fillExtent ? QLayoutPolicy::Preferred : QLayoutPolicy::Fixed;
+
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/imports/layouts/qquicklayout_p.h b/src/imports/layouts/qquicklayout_p.h
new file mode 100644
index 0000000000..c7f04c1fed
--- /dev/null
+++ b/src/imports/layouts/qquicklayout_p.h
@@ -0,0 +1,326 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Layouts module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKLAYOUT_P_H
+#define QQUICKLAYOUT_P_H
+
+#include <QPointer>
+#include <QQuickItem>
+#include <private/qquickitem_p.h>
+#include <QtQuick/private/qquickitemchangelistener_p.h>
+#include <QtGui/private/qlayoutpolicy_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickLayoutAttached;
+
+#if 0 && !defined(QT_NO_DEBUG) && !defined(QT_NO_DEBUG_OUTPUT)
+# define quickLayoutDebug QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).debug
+#else
+# define quickLayoutDebug QT_NO_QDEBUG_MACRO
+#endif
+
+class QQuickLayoutPrivate;
+class QQuickLayout : public QQuickItem, public QQuickItemChangeListener
+
+{
+ Q_OBJECT
+public:
+ enum SizeHint {
+ MinimumSize = 0,
+ PreferredSize,
+ MaximumSize,
+ NSizes
+ };
+
+ explicit QQuickLayout(QQuickLayoutPrivate &dd, QQuickItem *parent = 0);
+ ~QQuickLayout();
+
+ static QQuickLayoutAttached *qmlAttachedProperties(QObject *object);
+
+
+ void componentComplete() Q_DECL_OVERRIDE;
+ virtual QSizeF sizeHint(Qt::SizeHint whichSizeHint) const = 0;
+ virtual void setAlignment(QQuickItem *item, Qt::Alignment align) = 0;
+ virtual void invalidate(QQuickItem * childItem = 0);
+ virtual void updateLayoutItems() = 0;
+
+ // iterator
+ virtual QQuickItem *itemAt(int index) const = 0;
+ virtual int itemCount() const = 0;
+
+ virtual void rearrange(const QSizeF &);
+ bool arrangementIsDirty() const { return m_dirty; }
+
+ static void effectiveSizeHints_helper(QQuickItem *item, QSizeF *cachedSizeHints, QQuickLayoutAttached **info, bool useFallbackToWidthOrHeight);
+ static QLayoutPolicy::Policy effectiveSizePolicy_helper(QQuickItem *item, Qt::Orientation orientation, QQuickLayoutAttached *info);
+ bool shouldIgnoreItem(QQuickItem *child, QQuickLayoutAttached *&info, QSizeF *sizeHints) const;
+
+ void itemChange(ItemChange change, const ItemChangeData &value) Q_DECL_OVERRIDE;
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE;
+ bool isReady() const;
+
+
+ /* QQuickItemChangeListener */
+ void itemSiblingOrderChanged(QQuickItem *item) Q_DECL_OVERRIDE;
+
+protected:
+ void updatePolish() Q_DECL_OVERRIDE;
+
+ enum Orientation {
+ Vertical = 0,
+ Horizontal,
+ NOrientations
+ };
+
+protected slots:
+ void invalidateSenderItem();
+
+private:
+ bool m_dirty;
+
+ Q_DECLARE_PRIVATE(QQuickLayout)
+
+ friend class QQuickLayoutAttached;
+};
+
+
+class QQuickLayoutPrivate : public QQuickItemPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickLayout)
+public:
+ QQuickLayoutPrivate() : m_isReady(false), m_disableRearrange(true) {}
+
+protected:
+ unsigned m_isReady : 1;
+ unsigned m_disableRearrange : 1;
+ mutable QSet<QQuickItem *> m_ignoredItems;
+};
+
+
+class QQuickLayoutAttached : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal minimumWidth READ minimumWidth WRITE setMinimumWidth NOTIFY minimumWidthChanged)
+ Q_PROPERTY(qreal minimumHeight READ minimumHeight WRITE setMinimumHeight NOTIFY minimumHeightChanged)
+ Q_PROPERTY(qreal preferredWidth READ preferredWidth WRITE setPreferredWidth NOTIFY preferredWidthChanged)
+ Q_PROPERTY(qreal preferredHeight READ preferredHeight WRITE setPreferredHeight NOTIFY preferredHeightChanged)
+ Q_PROPERTY(qreal maximumWidth READ maximumWidth WRITE setMaximumWidth NOTIFY maximumWidthChanged)
+ Q_PROPERTY(qreal maximumHeight READ maximumHeight WRITE setMaximumHeight NOTIFY maximumHeightChanged)
+ Q_PROPERTY(bool fillHeight READ fillHeight WRITE setFillHeight NOTIFY fillHeightChanged)
+ Q_PROPERTY(bool fillWidth READ fillWidth WRITE setFillWidth NOTIFY fillWidthChanged)
+ Q_PROPERTY(int row READ row WRITE setRow NOTIFY rowChanged)
+ Q_PROPERTY(int column READ column WRITE setColumn NOTIFY columnChanged)
+ Q_PROPERTY(int rowSpan READ rowSpan WRITE setRowSpan NOTIFY rowSpanChanged)
+ Q_PROPERTY(int columnSpan READ columnSpan WRITE setColumnSpan NOTIFY columnSpanChanged)
+ Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment NOTIFY alignmentChanged)
+
+ Q_PROPERTY(qreal margins READ margins WRITE setMargins NOTIFY marginsChanged)
+ Q_PROPERTY(qreal leftMargin READ leftMargin WRITE setLeftMargin RESET resetLeftMargin NOTIFY leftMarginChanged)
+ Q_PROPERTY(qreal topMargin READ topMargin WRITE setTopMargin RESET resetTopMargin NOTIFY topMarginChanged)
+ Q_PROPERTY(qreal rightMargin READ rightMargin WRITE setRightMargin RESET resetRightMargin NOTIFY rightMarginChanged)
+ Q_PROPERTY(qreal bottomMargin READ bottomMargin WRITE setBottomMargin RESET resetBottomMargin NOTIFY bottomMarginChanged)
+
+public:
+ QQuickLayoutAttached(QObject *object);
+
+ qreal minimumWidth() const { return !m_isMinimumWidthSet ? sizeHint(Qt::MinimumSize, Qt::Horizontal) : m_minimumWidth; }
+ void setMinimumWidth(qreal width);
+
+ qreal minimumHeight() const { return !m_isMinimumHeightSet ? sizeHint(Qt::MinimumSize, Qt::Vertical) : m_minimumHeight; }
+ void setMinimumHeight(qreal height);
+
+ qreal preferredWidth() const { return m_preferredWidth; }
+ void setPreferredWidth(qreal width);
+
+ qreal preferredHeight() const { return m_preferredHeight; }
+ void setPreferredHeight(qreal width);
+
+ qreal maximumWidth() const { return !m_isMaximumWidthSet ? sizeHint(Qt::MaximumSize, Qt::Horizontal) : m_maximumWidth; }
+ void setMaximumWidth(qreal width);
+
+ qreal maximumHeight() const { return !m_isMaximumHeightSet ? sizeHint(Qt::MaximumSize, Qt::Vertical) : m_maximumHeight; }
+ void setMaximumHeight(qreal height);
+
+ void setMinimumImplicitSize(const QSizeF &sz);
+ void setMaximumImplicitSize(const QSizeF &sz);
+
+ bool fillWidth() const { return m_fillWidth; }
+ void setFillWidth(bool fill);
+ bool isFillWidthSet() const { return m_isFillWidthSet; }
+
+ bool fillHeight() const { return m_fillHeight; }
+ void setFillHeight(bool fill);
+ bool isFillHeightSet() const { return m_isFillHeightSet; }
+
+ int row() const { return qMax(m_row, 0); }
+ void setRow(int row);
+ bool isRowSet() const { return m_row >= 0; }
+ int column() const { return qMax(m_column, 0); }
+ void setColumn(int column);
+ bool isColumnSet() const { return m_column >= 0; }
+
+ int rowSpan() const { return m_rowSpan; }
+ void setRowSpan(int span);
+ int columnSpan() const { return m_columnSpan; }
+ void setColumnSpan(int span);
+
+ Qt::Alignment alignment() const { return m_alignment; }
+ void setAlignment(Qt::Alignment align);
+
+ qreal margins() const { return m_defaultMargins; }
+ void setMargins(qreal m);
+
+ qreal leftMargin() const { return m_isLeftMarginSet ? m_margins.left() : m_defaultMargins; }
+ void setLeftMargin(qreal m);
+ void resetLeftMargin();
+
+ qreal topMargin() const { return m_isTopMarginSet ? m_margins.top() : m_defaultMargins; }
+ void setTopMargin(qreal m);
+ void resetTopMargin();
+
+ qreal rightMargin() const { return m_isRightMarginSet ? m_margins.right() : m_defaultMargins; }
+ void setRightMargin(qreal m);
+ void resetRightMargin();
+
+ qreal bottomMargin() const { return m_isBottomMarginSet ? m_margins.bottom() : m_defaultMargins; }
+ void setBottomMargin(qreal m);
+ void resetBottomMargin();
+
+ QMarginsF qMargins() const {
+ return QMarginsF(leftMargin(), topMargin(), rightMargin(), bottomMargin());
+ }
+
+ bool setChangesNotificationEnabled(bool enabled)
+ {
+ const bool old = m_changesNotificationEnabled;
+ m_changesNotificationEnabled = enabled;
+ return old;
+ }
+
+ qreal sizeHint(Qt::SizeHint which, Qt::Orientation orientation) const;
+
+ bool isExtentExplicitlySet(Qt::Orientation o, Qt::SizeHint whichSize) const
+ {
+ switch (whichSize) {
+ case Qt::MinimumSize:
+ return o == Qt::Horizontal ? m_isMinimumWidthSet : m_isMinimumHeightSet;
+ case Qt::MaximumSize:
+ return o == Qt::Horizontal ? m_isMaximumWidthSet : m_isMaximumHeightSet;
+ case Qt::PreferredSize:
+ return true; // Layout.preferredWidth is always explicitly set
+ case Qt::MinimumDescent: // Not supported
+ case Qt::NSizeHints:
+ return false;
+ }
+ return false;
+ }
+
+signals:
+ void minimumWidthChanged();
+ void minimumHeightChanged();
+ void preferredWidthChanged();
+ void preferredHeightChanged();
+ void maximumWidthChanged();
+ void maximumHeightChanged();
+ void fillWidthChanged();
+ void fillHeightChanged();
+ void leftMarginChanged();
+ void topMarginChanged();
+ void rightMarginChanged();
+ void bottomMarginChanged();
+ void marginsChanged();
+ void rowChanged();
+ void columnChanged();
+ void rowSpanChanged();
+ void columnSpanChanged();
+ void alignmentChanged();
+
+private:
+ void invalidateItem();
+ void repopulateLayout();
+ QQuickLayout *parentLayout() const;
+ QQuickItem *item() const;
+private:
+ qreal m_minimumWidth;
+ qreal m_minimumHeight;
+ qreal m_preferredWidth;
+ qreal m_preferredHeight;
+ qreal m_maximumWidth;
+ qreal m_maximumHeight;
+
+ qreal m_defaultMargins;
+ QMarginsF m_margins;
+
+ // GridLayout specific properties
+ int m_row;
+ int m_column;
+ int m_rowSpan;
+ int m_columnSpan;
+
+ unsigned m_fillWidth : 1;
+ unsigned m_fillHeight : 1;
+ unsigned m_isFillWidthSet : 1;
+ unsigned m_isFillHeightSet : 1;
+ unsigned m_isMinimumWidthSet : 1;
+ unsigned m_isMinimumHeightSet : 1;
+ // preferredWidth and preferredHeight are always explicit, since
+ // their implicit equivalent is implicitWidth and implicitHeight
+ unsigned m_isMaximumWidthSet : 1;
+ unsigned m_isMaximumHeightSet : 1;
+ unsigned m_changesNotificationEnabled : 1;
+ unsigned m_isLeftMarginSet : 1;
+ unsigned m_isTopMarginSet : 1;
+ unsigned m_isRightMarginSet : 1;
+ unsigned m_isBottomMarginSet : 1;
+ Qt::Alignment m_alignment;
+ friend class QQuickLayout;
+};
+
+inline QQuickLayoutAttached *attachedLayoutObject(QQuickItem *item, bool create = true)
+{
+ return static_cast<QQuickLayoutAttached *>(qmlAttachedPropertiesObject<QQuickLayout>(item, create));
+}
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickLayout)
+QML_DECLARE_TYPEINFO(QQuickLayout, QML_HAS_ATTACHED_PROPERTIES)
+
+#endif // QQUICKLAYOUT_P_H
diff --git a/src/imports/layouts/qquicklayoutstyleinfo.cpp b/src/imports/layouts/qquicklayoutstyleinfo.cpp
new file mode 100644
index 0000000000..c33ceffb2d
--- /dev/null
+++ b/src/imports/layouts/qquicklayoutstyleinfo.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Layouts module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/private/qfont_p.h>
+
+#include "qquicklayoutstyleinfo_p.h"
+
+
+QT_BEGIN_NAMESPACE
+
+QQuickLayoutStyleInfo::QQuickLayoutStyleInfo()
+{
+}
+
+qreal QQuickLayoutStyleInfo::spacing(Qt::Orientation /*orientation*/) const
+{
+#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(Q_OS_BLACKBERRY) || defined(Q_OS_QNX) || defined(Q_OS_WINRT)
+ // On Android and iOS the default spacing between each UI element is 8dp
+ qreal spacing = 8.0;
+#else
+ qreal spacing = 5.0;
+#endif
+
+#ifndef Q_OS_OSX
+ // On OS X the DPI is always 72 so we should not scale it
+ spacing = qRound(spacing * (qreal(qt_defaultDpiX()) / 96.0));
+#endif
+
+ return spacing;
+}
+
+qreal QQuickLayoutStyleInfo::windowMargin(Qt::Orientation /*orientation*/) const
+{
+ return 0;
+}
+
+bool QQuickLayoutStyleInfo::hasChangedCore() const
+{
+ // never changes
+ return false;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/imports/layouts/qquicklayoutstyleinfo_p.h b/src/imports/layouts/qquicklayoutstyleinfo_p.h
new file mode 100644
index 0000000000..ce86c2a37d
--- /dev/null
+++ b/src/imports/layouts/qquicklayoutstyleinfo_p.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Layouts module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKLAYOUTSTYLEINFO_P_H
+#define QQUICKLAYOUTSTYLEINFO_P_H
+
+#include <QtGui/private/qabstractlayoutstyleinfo_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickLayoutStyleInfo : public QAbstractLayoutStyleInfo
+{
+public:
+ QQuickLayoutStyleInfo();
+
+ qreal spacing(Qt::Orientation orientation) const Q_DECL_OVERRIDE;
+ qreal windowMargin(Qt::Orientation orientation) const Q_DECL_OVERRIDE;
+ bool hasChangedCore() const Q_DECL_OVERRIDE;
+
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKLAYOUTSTYLEINFO_P_H
diff --git a/src/imports/layouts/qquicklinearlayout.cpp b/src/imports/layouts/qquicklinearlayout.cpp
new file mode 100644
index 0000000000..2f8af4c58b
--- /dev/null
+++ b/src/imports/layouts/qquicklinearlayout.cpp
@@ -0,0 +1,908 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Layouts module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquicklinearlayout_p.h"
+#include "qquickgridlayoutengine_p.h"
+#include "qquicklayoutstyleinfo_p.h"
+#include <QtCore/qnumeric.h>
+#include "qdebug.h"
+#include <limits>
+
+/*!
+ \qmltype RowLayout
+ \instantiates QQuickRowLayout
+ \inherits Item
+ \inqmlmodule QtQuick.Layouts
+ \ingroup layouts
+ \brief Identical to \l GridLayout, but having only one row.
+
+ It is available as a convenience for developers, as it offers a cleaner API.
+
+ Items in a RowLayout support these attached properties:
+ \list
+ \li \l{Layout::minimumWidth}{Layout.minimumWidth}
+ \li \l{Layout::minimumHeight}{Layout.minimumHeight}
+ \li \l{Layout::preferredWidth}{Layout.preferredWidth}
+ \li \l{Layout::preferredHeight}{Layout.preferredHeight}
+ \li \l{Layout::maximumWidth}{Layout.maximumWidth}
+ \li \l{Layout::maximumHeight}{Layout.maximumHeight}
+ \li \l{Layout::fillWidth}{Layout.fillWidth}
+ \li \l{Layout::fillHeight}{Layout.fillHeight}
+ \li \l{Layout::alignment}{Layout.alignment}
+ \endlist
+
+ \image rowlayout.png
+
+ \code
+ RowLayout {
+ id: layout
+ anchors.fill: parent
+ spacing: 6
+ Rectangle {
+ color: 'teal'
+ Layout.fillWidth: true
+ Layout.minimumWidth: 50
+ Layout.preferredWidth: 100
+ Layout.maximumWidth: 300
+ Layout.minimumHeight: 150
+ Text {
+ anchors.centerIn: parent
+ text: parent.width + 'x' + parent.height
+ }
+ }
+ Rectangle {
+ color: 'plum'
+ Layout.fillWidth: true
+ Layout.minimumWidth: 100
+ Layout.preferredWidth: 200
+ Layout.preferredHeight: 100
+ Text {
+ anchors.centerIn: parent
+ text: parent.width + 'x' + parent.height
+ }
+ }
+ }
+ \endcode
+
+ Read more about attached properties \l{QML Object Attributes}{here}.
+ \sa ColumnLayout
+ \sa GridLayout
+ \sa Row
+*/
+
+/*!
+ \qmltype ColumnLayout
+ \instantiates QQuickColumnLayout
+ \inherits Item
+ \inqmlmodule QtQuick.Layouts
+ \ingroup layouts
+ \brief Identical to \l GridLayout, but having only one column.
+
+ It is available as a convenience for developers, as it offers a cleaner API.
+
+ Items in a ColumnLayout support these attached properties:
+ \list
+ \li \l{Layout::minimumWidth}{Layout.minimumWidth}
+ \li \l{Layout::minimumHeight}{Layout.minimumHeight}
+ \li \l{Layout::preferredWidth}{Layout.preferredWidth}
+ \li \l{Layout::preferredHeight}{Layout.preferredHeight}
+ \li \l{Layout::maximumWidth}{Layout.maximumWidth}
+ \li \l{Layout::maximumHeight}{Layout.maximumHeight}
+ \li \l{Layout::fillWidth}{Layout.fillWidth}
+ \li \l{Layout::fillHeight}{Layout.fillHeight}
+ \li \l{Layout::alignment}{Layout.alignment}
+ \endlist
+
+ \image columnlayout.png
+
+ \code
+ ColumnLayout{
+ spacing: 2
+
+ Rectangle {
+ Layout.alignment: Qt.AlignCenter
+ color: "red"
+ Layout.preferredWidth: 40
+ Layout.preferredHeight: 40
+ }
+
+ Rectangle {
+ Layout.alignment: Qt.AlignRight
+ color: "green"
+ Layout.preferredWidth: 40
+ Layout.preferredHeight: 70
+ }
+
+ Rectangle {
+ Layout.alignment: Qt.AlignBottom
+ Layout.fillHeight: true
+ color: "blue"
+ Layout.preferredWidth: 70
+ Layout.preferredHeight: 40
+ }
+ }
+ \endcode
+
+ Read more about attached properties \l{QML Object Attributes}{here}.
+
+ \sa RowLayout
+ \sa GridLayout
+ \sa Column
+*/
+
+
+/*!
+ \qmltype GridLayout
+ \instantiates QQuickGridLayout
+ \inherits Item
+ \inqmlmodule QtQuick.Layouts
+ \ingroup layouts
+ \brief Provides a way of dynamically arranging items in a grid.
+
+
+
+ If the GridLayout is resized, all items in the layout will be rearranged. It is similar
+ to the widget-based QGridLayout. All visible children of the GridLayout element will belong to
+ the layout. If you want a layout with just one row or one column, you can use the
+ \l RowLayout or \l ColumnLayout. These offer a bit more convenient API, and improve
+ readability.
+
+ By default items will be arranged according to the \l flow property. The default value of
+ the \l flow property is \c GridLayout.LeftToRight.
+
+ If the \l columns property is specified, it will be treated as a maximum limit of how many
+ columns the layout can have, before the auto-positioning wraps back to the beginning of the
+ next row. The \l columns property is only used when \l flow is \c GridLayout.LeftToRight.
+
+ \image gridlayout.png
+
+ \code
+ GridLayout {
+ id: grid
+ columns: 3
+
+ Text { text: "Three"; font.bold: true; }
+ Text { text: "words"; color: "red" }
+ Text { text: "in"; font.underline: true }
+ Text { text: "a"; font.pixelSize: 20 }
+ Text { text: "row"; font.strikeout: true }
+ }
+ \endcode
+
+ The \l rows property works in a similar way, but items are auto-positioned vertically. The \l
+ rows property is only used when \l flow is \c GridLayout.TopToBottom.
+
+ You can specify which cell you want an item to occupy by setting the
+ \l{Layout::row}{Layout.row} and \l{Layout::column}{Layout.column} properties. You can also
+ specify the row span or column span by setting the \l{Layout::rowSpan}{Layout.rowSpan} or
+ \l{Layout::columnSpan}{Layout.columnSpan} properties.
+
+
+ Items in a GridLayout support these attached properties:
+ \list
+ \li \l{Layout::row}{Layout.row}
+ \li \l{Layout::column}{Layout.column}
+ \li \l{Layout::rowSpan}{Layout.rowSpan}
+ \li \l{Layout::columnSpan}{Layout.columnSpan}
+ \li \l{Layout::minimumWidth}{Layout.minimumWidth}
+ \li \l{Layout::minimumHeight}{Layout.minimumHeight}
+ \li \l{Layout::preferredWidth}{Layout.preferredWidth}
+ \li \l{Layout::preferredHeight}{Layout.preferredHeight}
+ \li \l{Layout::maximumWidth}{Layout.maximumWidth}
+ \li \l{Layout::maximumHeight}{Layout.maximumHeight}
+ \li \l{Layout::fillWidth}{Layout.fillWidth}
+ \li \l{Layout::fillHeight}{Layout.fillHeight}
+ \li \l{Layout::alignment}{Layout.alignment}
+ \endlist
+
+ Read more about attached properties \l{QML Object Attributes}{here}.
+
+ \sa RowLayout
+ \sa ColumnLayout
+ \sa Grid
+*/
+
+
+
+QT_BEGIN_NAMESPACE
+
+QQuickGridLayoutBase::QQuickGridLayoutBase()
+ : QQuickLayout(*new QQuickGridLayoutBasePrivate)
+{
+
+}
+
+QQuickGridLayoutBase::QQuickGridLayoutBase(QQuickGridLayoutBasePrivate &dd,
+ Qt::Orientation orientation,
+ QQuickItem *parent /*= 0*/)
+ : QQuickLayout(dd, parent)
+{
+ Q_D(QQuickGridLayoutBase);
+ d->orientation = orientation;
+ d->styleInfo = new QQuickLayoutStyleInfo;
+}
+
+Qt::Orientation QQuickGridLayoutBase::orientation() const
+{
+ Q_D(const QQuickGridLayoutBase);
+ return d->orientation;
+}
+
+void QQuickGridLayoutBase::setOrientation(Qt::Orientation orientation)
+{
+ Q_D(QQuickGridLayoutBase);
+ if (d->orientation == orientation)
+ return;
+
+ d->orientation = orientation;
+ invalidate();
+}
+
+QSizeF QQuickGridLayoutBase::sizeHint(Qt::SizeHint whichSizeHint) const
+{
+ Q_D(const QQuickGridLayoutBase);
+ return d->engine.sizeHint(whichSizeHint, QSizeF(), d->styleInfo);
+}
+
+/*!
+ \qmlproperty enumeration GridLayout::layoutDirection
+ \since QtQuick.Layouts 1.1
+
+ This property holds the layout direction of the grid layout - it controls whether items are
+ laid out from left to right or right to left. If \c Qt.RightToLeft is specified,
+ left-aligned items will be right-aligned and right-aligned items will be left-aligned.
+
+ Possible values:
+
+ \list
+ \li Qt.LeftToRight (default) - Items are laid out from left to right.
+ \li Qt.RightToLeft - Items are laid out from right to left.
+ \endlist
+
+ \sa RowLayout::layoutDirection, ColumnLayout::layoutDirection
+*/
+Qt::LayoutDirection QQuickGridLayoutBase::layoutDirection() const
+{
+ Q_D(const QQuickGridLayoutBase);
+ return d->m_layoutDirection;
+}
+
+void QQuickGridLayoutBase::setLayoutDirection(Qt::LayoutDirection dir)
+{
+ Q_D(QQuickGridLayoutBase);
+ d->m_layoutDirection = dir;
+ invalidate();
+}
+
+Qt::LayoutDirection QQuickGridLayoutBase::effectiveLayoutDirection() const
+{
+ Q_D(const QQuickGridLayoutBase);
+ return !d->effectiveLayoutMirror == (layoutDirection() == Qt::LeftToRight)
+ ? Qt::LeftToRight : Qt::RightToLeft;
+}
+
+void QQuickGridLayoutBase::setAlignment(QQuickItem *item, Qt::Alignment alignment)
+{
+ Q_D(QQuickGridLayoutBase);
+ d->engine.setAlignment(item, alignment);
+}
+
+QQuickGridLayoutBase::~QQuickGridLayoutBase()
+{
+ Q_D(QQuickGridLayoutBase);
+
+ /* Avoid messy deconstruction, should give:
+ * Faster deconstruction
+ * Less risk of signals reaching already deleted objects
+ */
+ for (int i = 0; i < itemCount(); ++i) {
+ QQuickItem *item = itemAt(i);
+ QObject::disconnect(item, SIGNAL(destroyed()), this, SLOT(onItemDestroyed()));
+ QObject::disconnect(item, SIGNAL(visibleChanged()), this, SLOT(onItemVisibleChanged()));
+ QObject::disconnect(item, SIGNAL(implicitWidthChanged()), this, SLOT(invalidateSenderItem()));
+ QObject::disconnect(item, SIGNAL(implicitHeightChanged()), this, SLOT(invalidateSenderItem()));
+ }
+ delete d->styleInfo;
+}
+
+void QQuickGridLayoutBase::componentComplete()
+{
+ quickLayoutDebug() << objectName() << "QQuickGridLayoutBase::componentComplete()" << parent();
+ QQuickLayout::componentComplete();
+ updateLayoutItems();
+
+ QQuickItem *par = parentItem();
+ if (qobject_cast<QQuickLayout*>(par))
+ return;
+ rearrange(QSizeF(width(), height()));
+}
+
+/*
+ Invalidation happens like this as a reaction to that a size hint changes on an item "a":
+
+ Suppose we have the following Qml document:
+ RowLayout {
+ id: l1
+ RowLayout {
+ id: l2
+ Item {
+ id: a
+ }
+ Item {
+ id: b
+ }
+ }
+ }
+
+ 1. l2->invalidateChildItem(a) is called on l2, where item refers to "a".
+ (this will dirty the cached size hints of item "a")
+ 2. l2->invalidate() is called
+ this will :
+ i) invalidate the layout engine
+ ii) dirty the cached size hints of item "l2" (by calling parentLayout()->invalidateChildItem
+
+ */
+/*!
+ \internal
+
+ Invalidates \a childItem and this layout.
+ After a call to invalidate, the next call to retrieve e.g. sizeHint will be up-to date.
+ This function will also call QQuickLayout::invalidate(0), to ensure that the parent layout
+ is invalidated.
+ */
+void QQuickGridLayoutBase::invalidate(QQuickItem *childItem)
+{
+ Q_D(QQuickGridLayoutBase);
+ if (!isReady())
+ return;
+ if (d->m_rearranging) {
+ d->m_invalidateAfterRearrange << childItem;
+ return;
+ }
+
+ quickLayoutDebug() << "QQuickGridLayoutBase::invalidate()";
+
+ if (childItem) {
+ if (QQuickGridLayoutItem *layoutItem = d->engine.findLayoutItem(childItem))
+ layoutItem->invalidate();
+ if (d->m_ignoredItems.contains(childItem)) {
+ updateLayoutItems();
+ return;
+ }
+ }
+ // invalidate engine
+ d->engine.invalidate();
+
+ QQuickLayout::invalidate(this);
+
+ QQuickLayoutAttached *info = attachedLayoutObject(this);
+
+ const QSizeF min = sizeHint(Qt::MinimumSize);
+ const QSizeF pref = sizeHint(Qt::PreferredSize);
+ const QSizeF max = sizeHint(Qt::MaximumSize);
+
+ const bool old = info->setChangesNotificationEnabled(false);
+ info->setMinimumImplicitSize(min);
+ info->setMaximumImplicitSize(max);
+ info->setChangesNotificationEnabled(old);
+ if (pref.width() == implicitWidth() && pref.height() == implicitHeight()) {
+ // In case setImplicitSize does not emit implicit{Width|Height}Changed
+ if (QQuickLayout *parentLayout = qobject_cast<QQuickLayout *>(parentItem()))
+ parentLayout->invalidate(this);
+ } else {
+ setImplicitSize(pref.width(), pref.height());
+ }
+}
+
+void QQuickGridLayoutBase::updateLayoutItems()
+{
+ Q_D(QQuickGridLayoutBase);
+ if (!isReady())
+ return;
+ if (d->m_rearranging) {
+ d->m_updateAfterRearrange = true;
+ return;
+ }
+
+ quickLayoutDebug() << "QQuickGridLayoutBase::updateLayoutItems";
+ d->engine.deleteItems();
+ insertLayoutItems();
+
+ invalidate();
+ quickLayoutDebug() << "QQuickGridLayoutBase::updateLayoutItems LEAVING";
+}
+
+QQuickItem *QQuickGridLayoutBase::itemAt(int index) const
+{
+ Q_D(const QQuickGridLayoutBase);
+ return static_cast<QQuickGridLayoutItem*>(d->engine.itemAt(index))->layoutItem();
+}
+
+int QQuickGridLayoutBase::itemCount() const
+{
+ Q_D(const QQuickGridLayoutBase);
+ return d->engine.itemCount();
+}
+
+void QQuickGridLayoutBase::itemChange(ItemChange change, const ItemChangeData &value)
+{
+ if (change == ItemChildAddedChange) {
+ quickLayoutDebug() << "ItemChildAddedChange";
+ QQuickItem *item = value.item;
+ QObject::connect(item, SIGNAL(destroyed()), this, SLOT(onItemDestroyed()));
+ QObject::connect(item, SIGNAL(visibleChanged()), this, SLOT(onItemVisibleChanged()));
+ } else if (change == ItemChildRemovedChange) {
+ quickLayoutDebug() << "ItemChildRemovedChange";
+ QQuickItem *item = value.item;
+ QObject::disconnect(item, SIGNAL(destroyed()), this, SLOT(onItemDestroyed()));
+ QObject::disconnect(item, SIGNAL(visibleChanged()), this, SLOT(onItemVisibleChanged()));
+ }
+
+ QQuickLayout::itemChange(change, value);
+}
+
+void QQuickGridLayoutBase::removeGridItem(QGridLayoutItem *gridItem)
+{
+ Q_D(QQuickGridLayoutBase);
+ const int index = gridItem->firstRow(d->orientation);
+ d->engine.removeItem(gridItem);
+ d->engine.removeRows(index, 1, d->orientation);
+}
+
+void QQuickGridLayoutBase::onItemVisibleChanged()
+{
+ if (!isReady())
+ return;
+ quickLayoutDebug() << "QQuickGridLayoutBase::onItemVisibleChanged";
+ updateLayoutItems();
+}
+
+void QQuickGridLayoutBase::onItemDestroyed()
+{
+ if (!isReady())
+ return;
+ Q_D(QQuickGridLayoutBase);
+ quickLayoutDebug() << "QQuickGridLayoutBase::onItemDestroyed";
+ QQuickItem *inDestruction = static_cast<QQuickItem *>(sender());
+ if (QQuickGridLayoutItem *gridItem = d->engine.findLayoutItem(inDestruction)) {
+ removeGridItem(gridItem);
+ delete gridItem;
+ invalidate();
+ }
+}
+
+void QQuickGridLayoutBase::rearrange(const QSizeF &size)
+{
+ Q_D(QQuickGridLayoutBase);
+ if (!isReady())
+ return;
+
+ d->m_rearranging = true;
+ quickLayoutDebug() << objectName() << "QQuickGridLayoutBase::rearrange()" << size;
+ Qt::LayoutDirection visualDir = effectiveLayoutDirection();
+ d->engine.setVisualDirection(visualDir);
+
+ /*
+ qreal left, top, right, bottom;
+ left = top = right = bottom = 0; // ### support for margins?
+ if (visualDir == Qt::RightToLeft)
+ qSwap(left, right);
+ */
+
+ // Set m_dirty to false in case size hint changes during arrangement.
+ // This could happen if there is a binding like implicitWidth: height
+ QQuickLayout::rearrange(size);
+ d->engine.setGeometries(QRectF(QPointF(0,0), size), d->styleInfo);
+ d->m_rearranging = false;
+
+ for (QQuickItem *invalid : qAsConst(d->m_invalidateAfterRearrange))
+ invalidate(invalid);
+ d->m_invalidateAfterRearrange.clear();
+
+ if (d->m_updateAfterRearrange) {
+ updateLayoutItems();
+ d->m_updateAfterRearrange = false;
+ }
+}
+
+/**********************************
+ **
+ ** QQuickGridLayout
+ **
+ **/
+QQuickGridLayout::QQuickGridLayout(QQuickItem *parent /* = 0*/)
+ : QQuickGridLayoutBase(*new QQuickGridLayoutPrivate, Qt::Horizontal, parent)
+{
+}
+
+/*!
+ \qmlproperty real GridLayout::columnSpacing
+
+ This property holds the spacing between each column.
+ The default value is \c 5.
+*/
+qreal QQuickGridLayout::columnSpacing() const
+{
+ Q_D(const QQuickGridLayout);
+ return d->engine.spacing(Qt::Horizontal, d->styleInfo);
+}
+
+void QQuickGridLayout::setColumnSpacing(qreal spacing)
+{
+ Q_D(QQuickGridLayout);
+ if (qIsNaN(spacing) || columnSpacing() == spacing)
+ return;
+
+ d->engine.setSpacing(spacing, Qt::Horizontal);
+ invalidate();
+}
+
+/*!
+ \qmlproperty real GridLayout::rowSpacing
+
+ This property holds the spacing between each row.
+ The default value is \c 5.
+*/
+qreal QQuickGridLayout::rowSpacing() const
+{
+ Q_D(const QQuickGridLayout);
+ return d->engine.spacing(Qt::Vertical, d->styleInfo);
+}
+
+void QQuickGridLayout::setRowSpacing(qreal spacing)
+{
+ Q_D(QQuickGridLayout);
+ if (qIsNaN(spacing) || rowSpacing() == spacing)
+ return;
+
+ d->engine.setSpacing(spacing, Qt::Vertical);
+ invalidate();
+}
+
+/*!
+ \qmlproperty int GridLayout::columns
+
+ This property holds the column limit for items positioned if \l flow is
+ \c GridLayout.LeftToRight.
+ The default value is that there is no limit.
+*/
+int QQuickGridLayout::columns() const
+{
+ Q_D(const QQuickGridLayout);
+ return d->columns;
+}
+
+void QQuickGridLayout::setColumns(int columns)
+{
+ Q_D(QQuickGridLayout);
+ if (d->columns == columns)
+ return;
+ d->columns = columns;
+ updateLayoutItems();
+ emit columnsChanged();
+}
+
+
+/*!
+ \qmlproperty int GridLayout::rows
+
+ This property holds the row limit for items positioned if \l flow is \c GridLayout.TopToBottom.
+ The default value is that there is no limit.
+*/
+int QQuickGridLayout::rows() const
+{
+ Q_D(const QQuickGridLayout);
+ return d->rows;
+}
+
+void QQuickGridLayout::setRows(int rows)
+{
+ Q_D(QQuickGridLayout);
+ if (d->rows == rows)
+ return;
+ d->rows = rows;
+ updateLayoutItems();
+ emit rowsChanged();
+}
+
+
+/*!
+ \qmlproperty enumeration GridLayout::flow
+
+ This property holds the flow direction of items that does not have an explicit cell
+ position set.
+ It is used together with the \l columns or \l rows property, where
+ they specify when flow is reset to the next row or column respectively.
+
+ Possible values are:
+
+ \list
+ \li GridLayout.LeftToRight (default) - Items are positioned next to
+ each other, then wrapped to the next line.
+ \li GridLayout.TopToBottom - Items are positioned next to each
+ other from top to bottom, then wrapped to the next column.
+ \endlist
+
+ \sa rows
+ \sa columns
+*/
+QQuickGridLayout::Flow QQuickGridLayout::flow() const
+{
+ Q_D(const QQuickGridLayout);
+ return d->flow;
+}
+
+void QQuickGridLayout::setFlow(QQuickGridLayout::Flow flow)
+{
+ Q_D(QQuickGridLayout);
+ if (d->flow == flow)
+ return;
+ d->flow = flow;
+ // If flow is changed, the layout needs to be repopulated
+ updateLayoutItems();
+ emit flowChanged();
+}
+
+void QQuickGridLayout::insertLayoutItems()
+{
+ Q_D(QQuickGridLayout);
+
+ int nextCellPos[2] = {0,0};
+ int &nextColumn = nextCellPos[0];
+ int &nextRow = nextCellPos[1];
+
+ const int flowOrientation = flow();
+ int &flowColumn = nextCellPos[flowOrientation];
+ int &flowRow = nextCellPos[1 - flowOrientation];
+ int flowBound = (flowOrientation == QQuickGridLayout::LeftToRight) ? columns() : rows();
+
+ if (flowBound < 0)
+ flowBound = std::numeric_limits<int>::max();
+
+ d->m_ignoredItems.clear();
+ QSizeF sizeHints[Qt::NSizeHints];
+ const auto items = childItems();
+ for (QQuickItem *child : items) {
+ QQuickLayoutAttached *info = 0;
+
+ // Will skip all items with effective maximum width/height == 0
+ if (shouldIgnoreItem(child, info, sizeHints))
+ continue;
+
+ Qt::Alignment alignment = 0;
+ int row = -1;
+ int column = -1;
+ int span[2] = {1,1};
+ int &columnSpan = span[0];
+ int &rowSpan = span[1];
+
+ bool invalidRowColumn = false;
+ if (info) {
+ if (info->isRowSet() || info->isColumnSet()) {
+ // If row is specified and column is not specified (or vice versa),
+ // the unspecified component of the cell position should default to 0
+ row = column = 0;
+ if (info->isRowSet()) {
+ row = info->row();
+ invalidRowColumn = row < 0;
+ }
+ if (info->isColumnSet()) {
+ column = info->column();
+ invalidRowColumn = column < 0;
+ }
+ }
+ if (invalidRowColumn) {
+ qWarning("QQuickGridLayoutBase::insertLayoutItems: invalid row/column: %d",
+ row < 0 ? row : column);
+ return;
+ }
+ rowSpan = info->rowSpan();
+ columnSpan = info->columnSpan();
+ if (columnSpan < 1 || rowSpan < 1) {
+ qWarning("QQuickGridLayoutBase::addItem: invalid row span/column span: %d",
+ rowSpan < 1 ? rowSpan : columnSpan);
+ return;
+ }
+
+ alignment = info->alignment();
+ }
+
+ Q_ASSERT(columnSpan >= 1);
+ Q_ASSERT(rowSpan >= 1);
+ const int sp = span[flowOrientation];
+ if (sp > flowBound)
+ return;
+
+ if (row >= 0)
+ nextRow = row;
+ if (column >= 0)
+ nextColumn = column;
+
+ if (row < 0 || column < 0) {
+ /* if row or column is not specified, find next position by
+ advancing in the flow direction until there is a cell that
+ can accept the item.
+
+ The acceptance rules are pretty simple, but complexity arises
+ when an item requires several cells (due to spans):
+ 1. Check if the cells that the item will require
+ does not extend beyond columns (for LeftToRight) or
+ rows (for TopToBottom).
+ 2. Check if the cells that the item will require is not already
+ taken by another item.
+ */
+ bool cellAcceptsItem;
+ while (true) {
+ // Check if the item does not span beyond the layout bound
+ cellAcceptsItem = (flowColumn + sp) <= flowBound;
+
+ // Check if all the required cells are not taken
+ for (int rs = 0; cellAcceptsItem && rs < rowSpan; ++rs) {
+ for (int cs = 0; cellAcceptsItem && cs < columnSpan; ++cs) {
+ if (d->engine.itemAt(nextRow + rs, nextColumn + cs)) {
+ cellAcceptsItem = false;
+ }
+ }
+ }
+ if (cellAcceptsItem)
+ break;
+ ++flowColumn;
+ if (flowColumn == flowBound) {
+ flowColumn = 0;
+ ++flowRow;
+ }
+ }
+ }
+ column = nextColumn;
+ row = nextRow;
+ QQuickGridLayoutItem *layoutItem = new QQuickGridLayoutItem(child, row, column, rowSpan, columnSpan, alignment);
+ layoutItem->setCachedSizeHints(sizeHints);
+
+ d->engine.insertItem(layoutItem, -1);
+ }
+}
+
+/**********************************
+ **
+ ** QQuickLinearLayout
+ **
+ **/
+QQuickLinearLayout::QQuickLinearLayout(Qt::Orientation orientation,
+ QQuickItem *parent /*= 0*/)
+ : QQuickGridLayoutBase(*new QQuickLinearLayoutPrivate, orientation, parent)
+{
+}
+
+/*!
+ \qmlproperty enumeration RowLayout::layoutDirection
+ \since QtQuick.Layouts 1.1
+
+ This property holds the layout direction of the row layout - it controls whether items are laid
+ out from left ro right or right to left. If \c Qt.RightToLeft is specified,
+ left-aligned items will be right-aligned and right-aligned items will be left-aligned.
+
+ Possible values:
+
+ \list
+ \li Qt.LeftToRight (default) - Items are laid out from left to right.
+ \li Qt.RightToLeft - Items are laid out from right to left
+ \endlist
+
+ \sa GridLayout::layoutDirection, ColumnLayout::layoutDirection
+*/
+/*!
+ \qmlproperty enumeration ColumnLayout::layoutDirection
+ \since QtQuick.Layouts 1.1
+
+ This property holds the layout direction of the column layout - it controls whether items are laid
+ out from left ro right or right to left. If \c Qt.RightToLeft is specified,
+ left-aligned items will be right-aligned and right-aligned items will be left-aligned.
+
+ Possible values:
+
+ \list
+ \li Qt.LeftToRight (default) - Items are laid out from left to right.
+ \li Qt.RightToLeft - Items are laid out from right to left
+ \endlist
+
+ \sa GridLayout::layoutDirection, RowLayout::layoutDirection
+*/
+
+
+/*!
+ \qmlproperty real RowLayout::spacing
+
+ This property holds the spacing between each cell.
+ The default value is \c 5.
+*/
+/*!
+ \qmlproperty real ColumnLayout::spacing
+
+ This property holds the spacing between each cell.
+ The default value is \c 5.
+*/
+
+qreal QQuickLinearLayout::spacing() const
+{
+ Q_D(const QQuickLinearLayout);
+ return d->engine.spacing(d->orientation, d->styleInfo);
+}
+
+void QQuickLinearLayout::setSpacing(qreal space)
+{
+ Q_D(QQuickLinearLayout);
+ if (qIsNaN(space) || spacing() == space)
+ return;
+
+ d->engine.setSpacing(space, Qt::Horizontal | Qt::Vertical);
+ invalidate();
+}
+
+void QQuickLinearLayout::insertLayoutItems()
+{
+ Q_D(QQuickLinearLayout);
+ d->m_ignoredItems.clear();
+ QSizeF sizeHints[Qt::NSizeHints];
+ const auto items = childItems();
+ for (QQuickItem *child : items) {
+ Q_ASSERT(child);
+ QQuickLayoutAttached *info = 0;
+
+ // Will skip all items with effective maximum width/height == 0
+ if (shouldIgnoreItem(child, info, sizeHints))
+ continue;
+
+ Qt::Alignment alignment = 0;
+ if (info)
+ alignment = info->alignment();
+
+ const int index = d->engine.rowCount(d->orientation);
+ d->engine.insertRow(index, d->orientation);
+
+ int gridRow = 0;
+ int gridColumn = index;
+ if (d->orientation == Qt::Vertical)
+ qSwap(gridRow, gridColumn);
+ QQuickGridLayoutItem *layoutItem = new QQuickGridLayoutItem(child, gridRow, gridColumn, 1, 1, alignment);
+ layoutItem->setCachedSizeHints(sizeHints);
+ d->engine.insertItem(layoutItem, index);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/imports/layouts/qquicklinearlayout_p.h b/src/imports/layouts/qquicklinearlayout_p.h
new file mode 100644
index 0000000000..86404f8d79
--- /dev/null
+++ b/src/imports/layouts/qquicklinearlayout_p.h
@@ -0,0 +1,250 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Layouts module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKLINEARLAYOUT_P_H
+#define QQUICKLINEARLAYOUT_P_H
+
+#include "qquicklayout_p.h"
+#include "qquickgridlayoutengine_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/**********************************
+ **
+ ** QQuickGridLayoutBase
+ **
+ **/
+class QQuickGridLayoutBasePrivate;
+
+class QQuickGridLayoutBase : public QQuickLayout
+{
+ Q_OBJECT
+
+ Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1)
+
+public:
+
+ QQuickGridLayoutBase();
+
+ explicit QQuickGridLayoutBase(QQuickGridLayoutBasePrivate &dd,
+ Qt::Orientation orientation,
+ QQuickItem *parent = 0);
+
+ ~QQuickGridLayoutBase();
+ void componentComplete() Q_DECL_OVERRIDE;
+ void invalidate(QQuickItem *childItem = 0) Q_DECL_OVERRIDE;
+ Qt::Orientation orientation() const;
+ void setOrientation(Qt::Orientation orientation);
+ QSizeF sizeHint(Qt::SizeHint whichSizeHint) const Q_DECL_OVERRIDE;
+ Qt::LayoutDirection layoutDirection() const;
+ void setLayoutDirection(Qt::LayoutDirection dir);
+ Qt::LayoutDirection effectiveLayoutDirection() const;
+ void setAlignment(QQuickItem *item, Qt::Alignment align) Q_DECL_OVERRIDE;
+
+protected:
+ void updateLayoutItems() Q_DECL_OVERRIDE;
+ QQuickItem *itemAt(int index) const Q_DECL_OVERRIDE;
+ int itemCount() const Q_DECL_OVERRIDE;
+
+ void rearrange(const QSizeF &size) Q_DECL_OVERRIDE;
+ virtual void insertLayoutItems() {}
+ void itemChange(ItemChange change, const ItemChangeData &data) Q_DECL_OVERRIDE;
+
+signals:
+ Q_REVISION(1) void layoutDirectionChanged();
+
+protected slots:
+ void onItemVisibleChanged();
+ void onItemDestroyed();
+
+private:
+ void removeGridItem(QGridLayoutItem *gridItem);
+ Q_DECLARE_PRIVATE(QQuickGridLayoutBase)
+};
+
+class QQuickLayoutStyleInfo;
+
+class QQuickGridLayoutBasePrivate : public QQuickLayoutPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickGridLayoutBase)
+
+public:
+ QQuickGridLayoutBasePrivate() : m_rearranging(false)
+ , m_updateAfterRearrange(false)
+ , m_layoutDirection(Qt::LeftToRight)
+ {}
+
+ void mirrorChange() Q_DECL_OVERRIDE
+ {
+ Q_Q(QQuickGridLayoutBase);
+ q->invalidate();
+ }
+
+ QQuickGridLayoutEngine engine;
+ Qt::Orientation orientation;
+ unsigned m_rearranging : 1;
+ unsigned m_updateAfterRearrange : 1;
+ QVector<QQuickItem *> m_invalidateAfterRearrange;
+ Qt::LayoutDirection m_layoutDirection : 2;
+
+ QQuickLayoutStyleInfo *styleInfo;
+};
+
+/**********************************
+ **
+ ** QQuickGridLayout
+ **
+ **/
+class QQuickGridLayoutPrivate;
+class QQuickGridLayout : public QQuickGridLayoutBase
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal columnSpacing READ columnSpacing WRITE setColumnSpacing NOTIFY columnSpacingChanged)
+ Q_PROPERTY(qreal rowSpacing READ rowSpacing WRITE setRowSpacing NOTIFY rowSpacingChanged)
+ Q_PROPERTY(int columns READ columns WRITE setColumns NOTIFY columnsChanged)
+ Q_PROPERTY(int rows READ rows WRITE setRows NOTIFY rowsChanged)
+ Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged)
+public:
+ explicit QQuickGridLayout(QQuickItem *parent = 0);
+ qreal columnSpacing() const;
+ void setColumnSpacing(qreal spacing);
+ qreal rowSpacing() const;
+ void setRowSpacing(qreal spacing);
+
+ int columns() const;
+ void setColumns(int columns);
+ int rows() const;
+ void setRows(int rows);
+
+ Q_ENUMS(Flow)
+ enum Flow { LeftToRight, TopToBottom };
+ Flow flow() const;
+ void setFlow(Flow flow);
+
+ void insertLayoutItems();
+
+signals:
+ void columnSpacingChanged();
+ void rowSpacingChanged();
+
+ void columnsChanged();
+ void rowsChanged();
+
+ void flowChanged();
+private:
+ Q_DECLARE_PRIVATE(QQuickGridLayout)
+};
+
+class QQuickGridLayoutPrivate : public QQuickGridLayoutBasePrivate
+{
+ Q_DECLARE_PUBLIC(QQuickGridLayout)
+public:
+ QQuickGridLayoutPrivate(): columns(-1), rows(-1), flow(QQuickGridLayout::LeftToRight) {}
+ int columns;
+ int rows;
+ QQuickGridLayout::Flow flow;
+};
+
+
+/**********************************
+ **
+ ** QQuickLinearLayout
+ **
+ **/
+class QQuickLinearLayoutPrivate;
+class QQuickLinearLayout : public QQuickGridLayoutBase
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged)
+public:
+ explicit QQuickLinearLayout(Qt::Orientation orientation,
+ QQuickItem *parent = 0);
+ void insertLayoutItem(QQuickItem *item);
+ qreal spacing() const;
+ void setSpacing(qreal spacing);
+
+ void insertLayoutItems();
+
+signals:
+ void spacingChanged();
+private:
+ Q_DECLARE_PRIVATE(QQuickLinearLayout)
+};
+
+class QQuickLinearLayoutPrivate : public QQuickGridLayoutBasePrivate
+{
+ Q_DECLARE_PUBLIC(QQuickLinearLayout)
+public:
+ QQuickLinearLayoutPrivate() {}
+};
+
+
+/**********************************
+ **
+ ** QQuickRowLayout
+ **
+ **/
+class QQuickRowLayout : public QQuickLinearLayout
+{
+ Q_OBJECT
+
+public:
+ explicit QQuickRowLayout(QQuickItem *parent = 0)
+ : QQuickLinearLayout(Qt::Horizontal, parent) {}
+};
+
+
+/**********************************
+ **
+ ** QQuickColumnLayout
+ **
+ **/
+class QQuickColumnLayout : public QQuickLinearLayout
+{
+ Q_OBJECT
+
+public:
+ explicit QQuickColumnLayout(QQuickItem *parent = 0)
+ : QQuickLinearLayout(Qt::Vertical, parent) {}
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKLINEARLAYOUT_P_H
diff --git a/src/imports/layouts/qquickstacklayout.cpp b/src/imports/layouts/qquickstacklayout.cpp
new file mode 100644
index 0000000000..a223dd0374
--- /dev/null
+++ b/src/imports/layouts/qquickstacklayout.cpp
@@ -0,0 +1,339 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Layouts module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickstacklayout_p.h"
+#include <limits>
+
+/*!
+ \qmltype StackLayout
+ \instantiates QQuickStackLayout
+ \inherits Item
+ \inqmlmodule QtQuick.Layouts
+ \ingroup layouts
+ \brief The StackLayout class provides a stack of items where
+ only one item is visible at a time.
+
+ The current visible item can be modified by setting the \l currentIndex property.
+ The index corresponds to the order of the StackLayout's children.
+
+ In contrast to most other layouts, child Items' \l{Layout::fillWidth}{Layout.fillWidth} and \l{Layout::fillHeight}{Layout.fillHeight} properties
+ default to \c true. As a consequence, child items are by default filled to match the size of the StackLayout as long as their
+ \l{Layout::maximumWidth}{Layout.maximumWidth} or \l{Layout::maximumHeight}{Layout.maximumHeight} does not prevent it.
+
+ Items are added to the layout by reparenting the item to the layout. Similarly, removal is done by reparenting the item from the layout.
+ Both of these operations will affect the layout's \l count property.
+
+ The following code will create a StackLayout where only the 'plum' rectangle is visible.
+ \code
+ StackLayout {
+ id: layout
+ anchors.fill: parent
+ currentIndex: 1
+ Rectangle {
+ color: 'teal'
+ implicitWidth: 200
+ implicitHeight: 200
+ }
+ Rectangle {
+ color: 'plum'
+ implicitWidth: 300
+ implicitHeight: 200
+ }
+ }
+ \endcode
+
+ Items in a StackLayout support these attached properties:
+ \list
+ \li \l{Layout::minimumWidth}{Layout.minimumWidth}
+ \li \l{Layout::minimumHeight}{Layout.minimumHeight}
+ \li \l{Layout::preferredWidth}{Layout.preferredWidth}
+ \li \l{Layout::preferredHeight}{Layout.preferredHeight}
+ \li \l{Layout::maximumWidth}{Layout.maximumWidth}
+ \li \l{Layout::maximumHeight}{Layout.maximumHeight}
+ \li \l{Layout::fillWidth}{Layout.fillWidth}
+ \li \l{Layout::fillHeight}{Layout.fillHeight}
+ \endlist
+
+ Read more about attached properties \l{QML Object Attributes}{here}.
+ \sa ColumnLayout
+ \sa GridLayout
+ \sa RowLayout
+ \sa StackView
+*/
+
+QQuickStackLayout::QQuickStackLayout(QQuickItem *parent) :
+ QQuickLayout(*new QQuickStackLayoutPrivate, parent)
+{
+}
+
+/*!
+ \qmlproperty int StackLayout::count
+
+ This property holds the number of items that belong to the layout.
+
+ Only items that are children of the StackLayout will be candidates for layouting.
+*/
+int QQuickStackLayout::count() const
+{
+ Q_D(const QQuickStackLayout);
+ return d->count;
+}
+
+/*!
+ \qmlproperty int StackLayout::currentIndex
+
+ This property holds the index of the child item that is currently visible in the StackLayout.
+ By default it will be \c -1 for an empty layout, otherwise the default is \c 0 (referring to the first item).
+*/
+int QQuickStackLayout::currentIndex() const
+{
+ Q_D(const QQuickStackLayout);
+ return d->currentIndex;
+}
+
+void QQuickStackLayout::setCurrentIndex(int index)
+{
+ Q_D(QQuickStackLayout);
+ if (index != d->currentIndex) {
+ QQuickItem *prev = itemAt(d->currentIndex);
+ QQuickItem *next = itemAt(index);
+ d->currentIndex = index;
+ d->explicitCurrentIndex = true;
+ if (prev)
+ prev->setVisible(false);
+ if (next)
+ next->setVisible(true);
+
+ if (isComponentComplete()) {
+ rearrange(QSizeF(width(), height()));
+ emit currentIndexChanged();
+ }
+ }
+}
+
+void QQuickStackLayout::componentComplete()
+{
+ QQuickLayout::componentComplete(); // will call our geometryChange(), (where isComponentComplete() == true)
+
+ updateLayoutItems();
+
+ QQuickItem *par = parentItem();
+ if (qobject_cast<QQuickLayout*>(par))
+ return;
+
+ rearrange(QSizeF(width(), height()));
+}
+
+QSizeF QQuickStackLayout::sizeHint(Qt::SizeHint whichSizeHint) const
+{
+ QSizeF &askingFor = m_cachedSizeHints[whichSizeHint];
+ if (!askingFor.isValid()) {
+ QSizeF &minS = m_cachedSizeHints[Qt::MinimumSize];
+ QSizeF &prefS = m_cachedSizeHints[Qt::PreferredSize];
+ QSizeF &maxS = m_cachedSizeHints[Qt::MaximumSize];
+
+ minS = QSizeF(0,0);
+ prefS = QSizeF(0,0);
+ maxS = QSizeF(std::numeric_limits<qreal>::infinity(), std::numeric_limits<qreal>::infinity());
+
+ const int count = itemCount();
+ m_cachedItemSizeHints.resize(count);
+ for (int i = 0; i < count; ++i) {
+ SizeHints &hints = m_cachedItemSizeHints[i];
+ QQuickStackLayout::collectItemSizeHints(itemAt(i), hints.array);
+ minS = minS.expandedTo(hints.min());
+ prefS = prefS.expandedTo(hints.pref());
+ //maxS = maxS.boundedTo(hints.max()); // Can be resized to be larger than any of its items.
+ // This is the same as QStackLayout does it.
+ // Not sure how descent makes sense here...
+ }
+ }
+ return askingFor;
+}
+
+int QQuickStackLayout::indexOf(QQuickItem *childItem) const
+{
+ if (childItem) {
+ int indexOfItem = 0;
+ const auto items = childItems();
+ for (QQuickItem *item : items) {
+ if (shouldIgnoreItem(item))
+ continue;
+ if (childItem == item)
+ return indexOfItem;
+ ++indexOfItem;
+ }
+ }
+ return -1;
+}
+
+QQuickItem *QQuickStackLayout::itemAt(int index) const
+{
+ const auto items = childItems();
+ for (QQuickItem *item : items) {
+ if (shouldIgnoreItem(item))
+ continue;
+ if (index == 0)
+ return item;
+ --index;
+ }
+ return 0;
+}
+
+int QQuickStackLayout::itemCount() const
+{
+ int count = 0;
+ const auto items = childItems();
+ for (QQuickItem *item : items) {
+ if (shouldIgnoreItem(item))
+ continue;
+ ++count;
+ }
+ return count;
+}
+
+void QQuickStackLayout::setAlignment(QQuickItem * /*item*/, Qt::Alignment /*align*/)
+{
+ // ### Do we have to respect alignment?
+}
+
+void QQuickStackLayout::invalidate(QQuickItem *childItem)
+{
+ Q_D(QQuickStackLayout);
+ if (d->m_ignoredItems.contains(childItem)) {
+ // If an invalid item gets a valid size, it should be included, as it was added to the layout
+ updateLayoutItems();
+ return;
+ }
+
+ const int indexOfChild = indexOf(childItem);
+ if (indexOfChild >= 0 && indexOfChild < m_cachedItemSizeHints.count()) {
+ m_cachedItemSizeHints[indexOfChild].min() = QSizeF();
+ m_cachedItemSizeHints[indexOfChild].pref() = QSizeF();
+ m_cachedItemSizeHints[indexOfChild].max() = QSizeF();
+ }
+
+ for (int i = 0; i < Qt::NSizeHints; ++i)
+ m_cachedSizeHints[i] = QSizeF();
+ QQuickLayout::invalidate(this);
+
+ QQuickLayoutAttached *info = attachedLayoutObject(this);
+
+ const QSizeF min = sizeHint(Qt::MinimumSize);
+ const QSizeF pref = sizeHint(Qt::PreferredSize);
+ const QSizeF max = sizeHint(Qt::MaximumSize);
+
+ const bool old = info->setChangesNotificationEnabled(false);
+ info->setMinimumImplicitSize(min);
+ info->setMaximumImplicitSize(max);
+ info->setChangesNotificationEnabled(old);
+ if (pref.width() == implicitWidth() && pref.height() == implicitHeight()) {
+ // In case setImplicitSize does not emit implicit{Width|Height}Changed
+ if (QQuickLayout *parentLayout = qobject_cast<QQuickLayout *>(parentItem()))
+ parentLayout->invalidate(this);
+ } else {
+ setImplicitSize(pref.width(), pref.height());
+ }
+}
+
+void QQuickStackLayout::updateLayoutItems()
+{
+ Q_D(QQuickStackLayout);
+ d->m_ignoredItems.clear();
+ const int count = itemCount();
+ int oldIndex = d->currentIndex;
+ if (!d->explicitCurrentIndex)
+ d->currentIndex = (count > 0 ? 0 : -1);
+
+ if (d->currentIndex != oldIndex)
+ emit currentIndexChanged();
+
+ if (count != d->count) {
+ d->count = count;
+ emit countChanged();
+ }
+ for (int i = 0; i < count; ++i)
+ itemAt(i)->setVisible(d->currentIndex == i);
+
+ invalidate();
+}
+
+void QQuickStackLayout::rearrange(const QSizeF &newSize)
+{
+ Q_D(QQuickStackLayout);
+ if (newSize.isNull() || !newSize.isValid())
+ return;
+ (void)sizeHint(Qt::PreferredSize); // Make sure m_cachedItemSizeHints are valid
+
+ if (d->currentIndex == -1 || d->currentIndex >= m_cachedItemSizeHints.count())
+ return;
+ QQuickStackLayout::SizeHints &hints = m_cachedItemSizeHints[d->currentIndex];
+ QQuickItem *item = itemAt(d->currentIndex);
+ Q_ASSERT(item);
+ item->setPosition(QPointF(0,0)); // ### respect alignment?
+ item->setSize(newSize.expandedTo(hints.min()).boundedTo(hints.max()));
+ QQuickLayout::rearrange(newSize);
+}
+
+void QQuickStackLayout::collectItemSizeHints(QQuickItem *item, QSizeF *sizeHints)
+{
+ QQuickLayoutAttached *info = 0;
+ QQuickLayout::effectiveSizeHints_helper(item, sizeHints, &info, true);
+ if (!info)
+ return;
+ if (info->isFillWidthSet() && !info->fillWidth()) {
+ const qreal pref = sizeHints[Qt::PreferredSize].width();
+ sizeHints[Qt::MinimumSize].setWidth(pref);
+ sizeHints[Qt::MaximumSize].setWidth(pref);
+ }
+
+ if (info->isFillHeightSet() && !info->fillHeight()) {
+ const qreal pref = sizeHints[Qt::PreferredSize].height();
+ sizeHints[Qt::MinimumSize].setHeight(pref);
+ sizeHints[Qt::MaximumSize].setHeight(pref);
+ }
+}
+
+bool QQuickStackLayout::shouldIgnoreItem(QQuickItem *item) const
+{
+ const bool ignored = QQuickItemPrivate::get(item)->isTransparentForPositioner();
+ if (ignored)
+ d_func()->m_ignoredItems << item;
+ return ignored;
+}
diff --git a/src/imports/layouts/qquickstacklayout_p.h b/src/imports/layouts/qquickstacklayout_p.h
new file mode 100644
index 0000000000..7b6400c3a3
--- /dev/null
+++ b/src/imports/layouts/qquickstacklayout_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Layouts module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKSTACKLAYOUT_H
+#define QQUICKSTACKLAYOUT_H
+
+#include <qquicklayout_p.h>
+
+class QQuickStackLayoutPrivate;
+
+class QQuickStackLayout : public QQuickLayout
+{
+ Q_OBJECT
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+
+public:
+ explicit QQuickStackLayout(QQuickItem *parent = 0);
+ int count() const;
+ int currentIndex() const;
+ void setCurrentIndex(int index);
+
+ void componentComplete() Q_DECL_OVERRIDE;
+ QSizeF sizeHint(Qt::SizeHint whichSizeHint) const Q_DECL_OVERRIDE;
+ void setAlignment(QQuickItem *item, Qt::Alignment align) Q_DECL_OVERRIDE;
+ void invalidate(QQuickItem *childItem = 0) Q_DECL_OVERRIDE;
+ void updateLayoutItems() Q_DECL_OVERRIDE;
+ void rearrange(const QSizeF &) Q_DECL_OVERRIDE;
+
+ // iterator
+ Q_INVOKABLE QQuickItem *itemAt(int index) const Q_DECL_OVERRIDE;
+ int itemCount() const Q_DECL_OVERRIDE;
+ int indexOf(QQuickItem *item) const;
+
+
+
+signals:
+ void currentIndexChanged();
+ void countChanged();
+
+public slots:
+
+private:
+ static void collectItemSizeHints(QQuickItem *item, QSizeF *sizeHints);
+ bool shouldIgnoreItem(QQuickItem *item) const;
+ Q_DECLARE_PRIVATE(QQuickStackLayout)
+
+ QList<QQuickItem*> m_items;
+
+ typedef struct {
+ inline QSizeF &min() { return array[Qt::MinimumSize]; }
+ inline QSizeF &pref() { return array[Qt::PreferredSize]; }
+ inline QSizeF &max() { return array[Qt::MaximumSize]; }
+ QSizeF array[Qt::NSizeHints];
+ } SizeHints;
+
+ mutable QVector<SizeHints> m_cachedItemSizeHints;
+ mutable QSizeF m_cachedSizeHints[Qt::NSizeHints];
+};
+
+class QQuickStackLayoutPrivate : public QQuickLayoutPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickStackLayout)
+public:
+ QQuickStackLayoutPrivate() : count(0), currentIndex(-1), explicitCurrentIndex(false) {}
+private:
+ int count;
+ int currentIndex;
+ bool explicitCurrentIndex;
+};
+
+#endif // QQUICKSTACKLAYOUT_H
diff --git a/src/particles/particles.pro b/src/particles/particles.pro
index ba65ee3002..ab1c854253 100644
--- a/src/particles/particles.pro
+++ b/src/particles/particles.pro
@@ -1,4 +1,5 @@
TARGET = QtQuickParticles
+MODULE = quickparticles
CONFIG += internal_module
@@ -13,7 +14,6 @@ exists("qqml_enable_gcov") {
LIBS_PRIVATE += -lgcov
}
-MODULE = quickparticles
-load(qt_module)
-
include(particles.pri)
+
+load(qt_module)
diff --git a/src/particles/qquickparticleemitter.cpp b/src/particles/qquickparticleemitter.cpp
index 7e1a31f206..4d9f834492 100644
--- a/src/particles/qquickparticleemitter.cpp
+++ b/src/particles/qquickparticleemitter.cpp
@@ -343,7 +343,7 @@ void QQuickParticleEmitter::emitWindow(int timeStamp)
{
if (m_system == 0)
return;
- if ((!m_enabled || !m_particlesPerSecond)&& !m_pulseLeft && m_burstQueue.isEmpty()){
+ if ((!m_enabled || m_particlesPerSecond <= 0)&& !m_pulseLeft && m_burstQueue.isEmpty()){
m_reset_last = true;
return;
}
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro b/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro
index 3703d0fe0b..27b3a5b513 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro
+++ b/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro
@@ -1,10 +1,6 @@
TARGET = qmldbg_debugger
QT = qml-private core-private packetprotocol-private
-PLUGIN_TYPE = qmltooling
-PLUGIN_CLASS_NAME = QQmlDebuggerServiceFactory
-load(qt_plugin)
-
SOURCES += \
$$PWD/qdebugmessageservice.cpp \
$$PWD/qqmldebuggerservicefactory.cpp \
@@ -37,3 +33,6 @@ INCLUDEPATH += $$PWD \
OTHER_FILES += \
$$PWD/qqmldebuggerservice.json
+PLUGIN_TYPE = qmltooling
+PLUGIN_CLASS_NAME = QQmlDebuggerServiceFactory
+load(qt_plugin)
diff --git a/src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro b/src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro
index c2ee733db6..a8844944e0 100644
--- a/src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro
+++ b/src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro
@@ -1,10 +1,6 @@
TARGET = qmldbg_inspector
QT += qml-private quick-private core-private gui-private packetprotocol-private
-PLUGIN_TYPE = qmltooling
-PLUGIN_CLASS_NAME = QQmlInspectorServiceFactory
-load(qt_plugin)
-
INCLUDEPATH *= $$PWD $$PWD/../shared
SOURCES += \
@@ -24,3 +20,7 @@ HEADERS += \
OTHER_FILES += \
qqmlinspectorservice.json
+
+PLUGIN_TYPE = qmltooling
+PLUGIN_CLASS_NAME = QQmlInspectorServiceFactory
+load(qt_plugin)
diff --git a/src/plugins/qmltooling/qmldbg_local/qmldbg_local.pro b/src/plugins/qmltooling/qmldbg_local/qmldbg_local.pro
index 491be04b15..d731e47b7e 100644
--- a/src/plugins/qmltooling/qmldbg_local/qmldbg_local.pro
+++ b/src/plugins/qmltooling/qmldbg_local/qmldbg_local.pro
@@ -1,10 +1,6 @@
TARGET = qmldbg_local
QT = qml-private
-PLUGIN_TYPE = qmltooling
-PLUGIN_CLASS_NAME = QLocalClientConnectionFactory
-load(qt_plugin)
-
SOURCES += \
$$PWD/qlocalclientconnection.cpp
@@ -18,3 +14,7 @@ INCLUDEPATH += $$PWD \
OTHER_FILES += \
$$PWD/qlocalclientconnection.json
+
+PLUGIN_TYPE = qmltooling
+PLUGIN_CLASS_NAME = QLocalClientConnectionFactory
+load(qt_plugin)
diff --git a/src/plugins/qmltooling/qmldbg_native/qmldbg_native.pro b/src/plugins/qmltooling/qmldbg_native/qmldbg_native.pro
index d490d77e50..b3fe1681e8 100644
--- a/src/plugins/qmltooling/qmldbg_native/qmldbg_native.pro
+++ b/src/plugins/qmltooling/qmldbg_native/qmldbg_native.pro
@@ -1,10 +1,6 @@
TARGET = qmldbg_native
QT += qml-private core-private packetprotocol-private
-PLUGIN_TYPE = qmltooling
-PLUGIN_CLASS_NAME = QQmlNativeDebugConnectorFactory
-load(qt_plugin)
-
HEADERS += \
$$PWD/../shared/qqmldebugpacket.h \
$$PWD/qqmlnativedebugconnector.h
@@ -17,3 +13,7 @@ INCLUDEPATH += $$PWD \
OTHER_FILES += \
$$PWD/qqmlnativedebugconnector.json
+
+PLUGIN_TYPE = qmltooling
+PLUGIN_CLASS_NAME = QQmlNativeDebugConnectorFactory
+load(qt_plugin)
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qmldbg_profiler.pro b/src/plugins/qmltooling/qmldbg_profiler/qmldbg_profiler.pro
index 6efe9eacad..4629a7b81e 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qmldbg_profiler.pro
+++ b/src/plugins/qmltooling/qmldbg_profiler/qmldbg_profiler.pro
@@ -1,10 +1,6 @@
TARGET = qmldbg_profiler
QT = qml-private core-private packetprotocol-private
-PLUGIN_TYPE = qmltooling
-PLUGIN_CLASS_NAME = QQmlProfilerServiceFactory
-load(qt_plugin)
-
SOURCES += \
$$PWD/qqmlenginecontrolservice.cpp \
$$PWD/qqmlprofileradapter.cpp \
@@ -27,3 +23,6 @@ INCLUDEPATH += $$PWD \
OTHER_FILES += \
$$PWD/qqmlprofilerservice.json
+PLUGIN_TYPE = qmltooling
+PLUGIN_CLASS_NAME = QQmlProfilerServiceFactory
+load(qt_plugin)
diff --git a/src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro b/src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro
index 923faa01f3..fffdb4c888 100644
--- a/src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro
+++ b/src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro
@@ -1,10 +1,6 @@
TARGET = qmldbg_server
QT = qml-private packetprotocol-private
-PLUGIN_TYPE = qmltooling
-PLUGIN_CLASS_NAME = QQmlDebugServerFactory
-load(qt_plugin)
-
SOURCES += \
$$PWD/qqmldebugserver.cpp
@@ -19,3 +15,7 @@ INCLUDEPATH += $$PWD \
OTHER_FILES += \
qqmldebugserver.json
+
+PLUGIN_TYPE = qmltooling
+PLUGIN_CLASS_NAME = QQmlDebugServerFactory
+load(qt_plugin)
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro b/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro
index fd419aeb56..1face1813e 100644
--- a/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro
+++ b/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro
@@ -1,10 +1,6 @@
TARGET = qmldbg_tcp
QT = qml-private network
-PLUGIN_TYPE = qmltooling
-PLUGIN_CLASS_NAME = QTcpServerConnectionFactory
-load(qt_plugin)
-
SOURCES += \
$$PWD/qtcpserverconnection.cpp
@@ -18,3 +14,7 @@ INCLUDEPATH += $$PWD \
OTHER_FILES += \
$$PWD/qtcpserverconnection.json
+
+PLUGIN_TYPE = qmltooling
+PLUGIN_CLASS_NAME = QTcpServerConnectionFactory
+load(qt_plugin)
diff --git a/src/plugins/qmltooling/qmltooling.pro b/src/plugins/qmltooling/qmltooling.pro
index 3728126dd9..7682e7b075 100644
--- a/src/plugins/qmltooling/qmltooling.pro
+++ b/src/plugins/qmltooling/qmltooling.pro
@@ -1,30 +1,32 @@
TEMPLATE = subdirs
-# Utilities
-SUBDIRS += \
- packetprotocol
+!no_network {
+ # Utilities
+ SUBDIRS += \
+ packetprotocol
-# Connectors
-SUBDIRS += \
- qmldbg_native \
- qmldbg_server \
+ # Connectors
+ SUBDIRS += \
+ qmldbg_native \
+ qmldbg_server \
qmldbg_local \
qmldbg_tcp
-# Services
-SUBDIRS += \
- qmldbg_debugger \
- qmldbg_profiler
+ # Services
+ SUBDIRS += \
+ qmldbg_debugger \
+ qmldbg_profiler
-qmldbg_server.depends = packetprotocol
-qmldbg_native.depends = packetprotocol
-qmldbg_debugger.depends = packetprotocol
-qmldbg_profiler.depends = packetprotocol
+ qmldbg_server.depends = packetprotocol
+ qmldbg_native.depends = packetprotocol
+ qmldbg_debugger.depends = packetprotocol
+ qmldbg_profiler.depends = packetprotocol
-qtHaveModule(quick) {
- SUBDIRS += \
- qmldbg_inspector \
- qmldbg_quickprofiler
- qmldbg_inspector.depends = packetprotocol
- qmldbg_quickprofiler.depends = packetprotocol
+ qtHaveModule(quick) {
+ SUBDIRS += \
+ qmldbg_inspector \
+ qmldbg_quickprofiler
+ qmldbg_inspector.depends = packetprotocol
+ qmldbg_quickprofiler.depends = packetprotocol
+ }
}
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 9fcfe53b05..a34c1cbf0e 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -411,7 +411,7 @@ bool IRBuilder::generateFromQml(const QString &code, const QString &url, Documen
bool IRBuilder::isSignalPropertyName(const QString &name)
{
if (name.length() < 3) return false;
- if (!name.startsWith(QStringLiteral("on"))) return false;
+ if (!name.startsWith(QLatin1String("on"))) return false;
int ns = name.length();
for (int i = 2; i < ns; ++i) {
const QChar curr = name.at(i);
@@ -1061,7 +1061,7 @@ void IRBuilder::appendBinding(QQmlJS::AST::UiQualifiedId *name, QQmlJS::AST::Sta
Object *object = 0;
if (!resolveQualifiedId(&name, &object))
return;
- if (_object == object && name->name == QStringLiteral("id")) {
+ if (_object == object && name->name == QLatin1String("id")) {
setId(name->identifierToken, value);
return;
}
@@ -1097,7 +1097,7 @@ void IRBuilder::appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLo
void IRBuilder::appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLocation, const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex, int objectIndex, bool isListItem, bool isOnAssignment)
{
- if (stringAt(propertyNameIndex) == QStringLiteral("id")) {
+ if (stringAt(propertyNameIndex) == QLatin1String("id")) {
recordError(nameLocation, tr("Invalid component id specification"));
return;
}
@@ -1192,7 +1192,7 @@ bool IRBuilder::resolveQualifiedId(QQmlJS::AST::UiQualifiedId **nameToResolve, O
{
QQmlJS::AST::UiQualifiedId *qualifiedIdElement = *nameToResolve;
- if (qualifiedIdElement->name == QStringLiteral("id") && qualifiedIdElement->next)
+ if (qualifiedIdElement->name == QLatin1String("id") && qualifiedIdElement->next)
COMPILE_EXCEPTION(qualifiedIdElement->identifierToken, tr( "Invalid use of id property"));
// If it's a namespace, prepend the qualifier and we'll resolve it later to the correct type.
@@ -1918,7 +1918,7 @@ QQmlPropertyData *PropertyResolver::signal(const QString &name, bool *notInRevis
return d;
}
- if (name.endsWith(QStringLiteral("Changed"))) {
+ if (name.endsWith(QLatin1String("Changed"))) {
QString propName = name.mid(0, name.length() - static_cast<int>(strlen("Changed")));
d = property(propName, notInRevision);
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index 2b3cd93052..33716d57b8 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -972,7 +972,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
QmlIR::PropertyResolver resolver(propertyCache);
- Q_ASSERT(propertyName.startsWith(QStringLiteral("on")));
+ Q_ASSERT(propertyName.startsWith(QLatin1String("on")));
propertyName.remove(0, 2);
// Note that the property name could start with any alpha or '_' or '$' character,
@@ -1039,7 +1039,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
}
QHash<QString, QStringList>::ConstIterator entry = customSignals.constFind(propertyName);
- if (entry == customSignals.constEnd() && propertyName.endsWith(QStringLiteral("Changed"))) {
+ if (entry == customSignals.constEnd() && propertyName.endsWith(QLatin1String("Changed"))) {
QString alternateName = propertyName.mid(0, propertyName.length() - static_cast<int>(strlen("Changed")));
entry = customSignals.constFind(alternateName);
}
@@ -1163,6 +1163,17 @@ struct StaticQtMetaObject : public QObject
{ return &staticQtMetaObject; }
};
+bool QQmlEnumTypeResolver::assignEnumToBinding(QmlIR::Binding *binding, const QString &enumName, int enumValue, bool isQtObject)
+{
+ if (enumName.length() > 0 && enumName[0].isLower() && !isQtObject) {
+ COMPILE_EXCEPTION(binding, tr("Invalid property assignment: Enum value \"%1\" cannot start with a lowercase letter").arg(enumName));
+ }
+ binding->type = QV4::CompiledData::Binding::Type_Number;
+ binding->value.d = (double)enumValue;
+ binding->flags |= QV4::CompiledData::Binding::IsResolvedEnum;
+ return true;
+}
+
bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj, const QQmlPropertyCache *propertyCache, const QQmlPropertyData *prop, QmlIR::Binding *binding)
{
bool isIntProp = (prop->propType == QMetaType::Int) && !prop->isEnum();
@@ -1185,6 +1196,7 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj,
return true;
QHashedStringRef typeName(string.constData(), dot);
+ const bool isQtObject = (typeName == QLatin1String("Qt"));
QString enumValue = string.mid(dot+1);
if (isIntProp) {
@@ -1192,16 +1204,15 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj,
bool ok;
int enumval = evaluateEnum(typeName.toString(), enumValue.toUtf8(), &ok);
if (ok) {
- binding->type = QV4::CompiledData::Binding::Type_Number;
- binding->value.d = (double)enumval;
- binding->flags |= QV4::CompiledData::Binding::IsResolvedEnum;
+ if (!assignEnumToBinding(binding, enumValue, enumval, isQtObject))
+ return false;
}
return true;
}
QQmlType *type = 0;
imports->resolveType(typeName, &type, 0, 0, 0);
- if (!type && typeName != QLatin1String("Qt"))
+ if (!type && !isQtObject)
return true;
int value = 0;
@@ -1234,10 +1245,7 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj,
if (!ok)
return true;
- binding->type = QV4::CompiledData::Binding::Type_Number;
- binding->value.d = (double)value;
- binding->flags |= QV4::CompiledData::Binding::IsResolvedEnum;
- return true;
+ return assignEnumToBinding(binding, enumValue, value, isQtObject);
}
int QQmlEnumTypeResolver::evaluateEnum(const QString &scope, const QByteArray &enumValue, bool *ok) const
@@ -2749,7 +2757,7 @@ bool QQmlJavaScriptBindingExpressionSimplificationPass::simplifyBinding(QV4::IR:
bool QQmlJavaScriptBindingExpressionSimplificationPass::detectTranslationCallAndConvertBinding(QmlIR::Binding *binding)
{
- if (*_nameOfFunctionCalled == QStringLiteral("qsTr")) {
+ if (*_nameOfFunctionCalled == QLatin1String("qsTr")) {
QString translation;
QV4::CompiledData::TranslationData translationData;
translationData.number = -1;
@@ -2791,7 +2799,7 @@ bool QQmlJavaScriptBindingExpressionSimplificationPass::detectTranslationCallAnd
binding->stringIndex = compiler->registerString(translation);
binding->value.translationData = translationData;
return true;
- } else if (*_nameOfFunctionCalled == QStringLiteral("qsTrId")) {
+ } else if (*_nameOfFunctionCalled == QLatin1String("qsTrId")) {
QString id;
QV4::CompiledData::TranslationData translationData;
translationData.number = -1;
@@ -2825,7 +2833,7 @@ bool QQmlJavaScriptBindingExpressionSimplificationPass::detectTranslationCallAnd
binding->stringIndex = compiler->registerString(id);
binding->value.translationData = translationData;
return true;
- } else if (*_nameOfFunctionCalled == QStringLiteral("QT_TR_NOOP") || *_nameOfFunctionCalled == QStringLiteral("QT_TRID_NOOP")) {
+ } else if (*_nameOfFunctionCalled == QLatin1String("QT_TR_NOOP") || *_nameOfFunctionCalled == QLatin1String("QT_TRID_NOOP")) {
QVector<int>::ConstIterator param = _functionParameters.constBegin();
QVector<int>::ConstIterator end = _functionParameters.constEnd();
if (param == end)
@@ -2842,7 +2850,7 @@ bool QQmlJavaScriptBindingExpressionSimplificationPass::detectTranslationCallAnd
binding->type = QV4::CompiledData::Binding::Type_String;
binding->stringIndex = compiler->registerString(*stringParam->value);
return true;
- } else if (*_nameOfFunctionCalled == QStringLiteral("QT_TRANSLATE_NOOP")) {
+ } else if (*_nameOfFunctionCalled == QLatin1String("QT_TRANSLATE_NOOP")) {
QVector<int>::ConstIterator param = _functionParameters.constBegin();
QVector<int>::ConstIterator end = _functionParameters.constEnd();
if (param == end)
diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h
index 3404350ece..240f591f91 100644
--- a/src/qml/compiler/qqmltypecompiler_p.h
+++ b/src/qml/compiler/qqmltypecompiler_p.h
@@ -196,6 +196,7 @@ public:
bool resolveEnumBindings();
private:
+ bool assignEnumToBinding(QmlIR::Binding *binding, const QString &enumName, int enumValue, bool isQtObject);
bool tryQualifiedEnumAssignment(const QmlIR::Object *obj, const QQmlPropertyCache *propertyCache,
const QQmlPropertyData *prop,
QmlIR::Binding *binding);
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index eab5b7fd2d..d08d2aafa2 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -115,7 +115,7 @@ void Codegen::ScanFunctions::checkDirectivePrologue(SourceElements *ast)
if (strLit->literalToken.length < 2)
continue;
QStringRef str = _sourceCode.midRef(strLit->literalToken.offset + 1, strLit->literalToken.length - 2);
- if (str == QStringLiteral("use strict")) {
+ if (str == QLatin1String("use strict")) {
_env->isStrict = true;
} else {
// TODO: give a warning.
@@ -148,7 +148,7 @@ void Codegen::ScanFunctions::checkName(const QStringRef &name, const SourceLocat
void Codegen::ScanFunctions::checkForArguments(AST::FormalParameterList *parameters)
{
while (parameters) {
- if (parameters->name == QStringLiteral("arguments"))
+ if (parameters->name == QLatin1String("arguments"))
_env->usesArgumentsObject = Environment::ArgumentsObjectNotUsed;
parameters = parameters->next;
}
@@ -170,7 +170,7 @@ bool Codegen::ScanFunctions::visit(CallExpression *ast)
{
if (! _env->hasDirectEval) {
if (IdentifierExpression *id = cast<IdentifierExpression *>(ast->base)) {
- if (id->name == QStringLiteral("eval")) {
+ if (id->name == QLatin1String("eval")) {
if (_env->usesArgumentsObject == Environment::ArgumentsObjectUnknown)
_env->usesArgumentsObject = Environment::ArgumentsObjectUsed;
_env->hasDirectEval = true;
@@ -241,7 +241,7 @@ bool Codegen::ScanFunctions::visit(ExpressionStatement *ast)
return false;
} else {
SourceLocation firstToken = ast->firstSourceLocation();
- if (_sourceCode.midRef(firstToken.offset, firstToken.length) == QStringLiteral("function")) {
+ if (_sourceCode.midRef(firstToken.offset, firstToken.length) == QLatin1String("function")) {
_cg->throwSyntaxError(firstToken, QStringLiteral("unexpected token"));
}
}
@@ -1441,7 +1441,7 @@ IR::Expr *Codegen::identifier(const QString &name, int line, int col)
Q_ASSERT (index < e->members.size());
if (index != -1) {
IR::ArgLocal *al = _block->LOCAL(index, scope);
- if (name == QStringLiteral("arguments") || name == QStringLiteral("eval"))
+ if (name == QLatin1String("arguments") || name == QLatin1String("eval"))
al->isArgumentsOrEval = true;
return al;
}
diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp
index 49e7d5c66e..0ae08160ab 100644
--- a/src/qml/compiler/qv4isel_p.cpp
+++ b/src/qml/compiler/qv4isel_p.cpp
@@ -95,7 +95,7 @@ void IRDecoder::visitMove(IR::Move *s)
}
} else if (s->target->asTemp() || s->target->asArgLocal()) {
if (IR::Name *n = s->source->asName()) {
- if (n->id && *n->id == QStringLiteral("this")) // TODO: `this' should be a builtin.
+ if (n->id && *n->id == QLatin1String("this")) // TODO: `this' should be a builtin.
loadThisObject(s->target);
else if (n->builtin == IR::Name::builtin_qml_context)
loadQmlContext(s->target);
diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp
index c2b6fa477b..4c87b7557e 100644
--- a/src/qml/compiler/qv4jsir.cpp
+++ b/src/qml/compiler/qv4jsir.cpp
@@ -1145,7 +1145,7 @@ void IRPrinter::visitRegExp(RegExp *e)
void IRPrinter::visitName(Name *e)
{
if (e->id) {
- if (*e->id != QStringLiteral("this"))
+ if (*e->id != QLatin1String("this"))
*out << '.';
*out << *e->id;
} else {
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index 0ff3b52870..7881ab951a 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -570,7 +570,7 @@ class DominatorTree
bucket[s].push_back(n);
link(p, n);
if (bucket.contains(p)) {
- foreach (BasicBlockIndex v, bucket[p]) {
+ for (BasicBlockIndex v : bucket[p]) {
BasicBlockIndex y = ancestorWithLowestSemi(v, worklist);
BasicBlockIndex semi_v = d->semi[v];
if (d->semi[y] == semi_v)
@@ -670,7 +670,7 @@ public:
foreach (BasicBlock *y, function->basicBlock(node)->out)
if (idom[y->index()] != node)
S.insert(y);
- foreach (BasicBlockIndex child, np.children) {
+ for (BasicBlockIndex child : np.children) {
const BasicBlockSet &ws = DF[child];
for (BasicBlockSet::const_iterator it = ws.begin(), eit = ws.end(); it != eit; ++it) {
BasicBlock *w = *it;
@@ -1733,7 +1733,7 @@ void convertToSSA(IR::Function *function, const DominatorTree &df, DefUses &defU
W.reserve(8);
// Place phi functions:
- foreach (const Temp &a, variables.allTemps()) {
+ for (const Temp &a : variables.allTemps()) {
if (a.isInvalid())
continue;
if (!variables.isNonLocal(a))
@@ -1791,7 +1791,7 @@ void cleanupPhis(DefUses &defUses)
std::vector<Phi *> allPhis;
allPhis.reserve(32);
- foreach (const Temp *def, defUses.defs()) {
+ for (const Temp *def : defUses.defs()) {
Stmt *defStmt = defUses.defStmt(*def);
if (!defStmt)
continue;
@@ -1808,7 +1808,7 @@ void cleanupPhis(DefUses &defUses)
toRemove |= collectedPhis;
}
- foreach (Phi *phi, allPhis) {
+ for (Phi *phi : allPhis) {
if (!toRemove.at(phi->id()))
continue;
@@ -2070,7 +2070,7 @@ protected:
return;
// TODO: maybe we can distinguish between built-ins of which we know that they do not have
// a side-effect.
- if (e->builtin == Name::builtin_invalid || (e->id && *e->id != QStringLiteral("this")))
+ if (e->builtin == Name::builtin_invalid || (e->id && *e->id != QLatin1String("this")))
markAsSideEffect();
}
diff --git a/src/qml/debugger/qqmldebugconnector.cpp b/src/qml/debugger/qqmldebugconnector.cpp
index f00d4b24f7..6edd28ea01 100644
--- a/src/qml/debugger/qqmldebugconnector.cpp
+++ b/src/qml/debugger/qqmldebugconnector.cpp
@@ -129,7 +129,7 @@ QQmlDebugConnector *QQmlDebugConnector::instance()
if (!params->instance) {
const QString serverConnector = QStringLiteral("QQmlDebugServer");
const QString nativeConnector = QStringLiteral("QQmlNativeDebugConnector");
- const bool isNative = params->arguments.startsWith(QStringLiteral("native"));
+ const bool isNative = params->arguments.startsWith(QLatin1String("native"));
if (!params->pluginKey.isEmpty()) {
if (params->pluginKey == serverConnector || params->pluginKey == nativeConnector)
params->instance = loadQQmlDebugConnector(params->pluginKey);
diff --git a/src/qml/doc/src/qmlfunctions.qdoc b/src/qml/doc/src/qmlfunctions.qdoc
index 4203cca8b3..6f738752a7 100644
--- a/src/qml/doc/src/qmlfunctions.qdoc
+++ b/src/qml/doc/src/qmlfunctions.qdoc
@@ -30,8 +30,6 @@
\relates QQmlEngine
Equivalent to \c Q_DECLARE_METATYPE(TYPE *) and \c Q_DECLARE_METATYPE(QQmlListProperty<TYPE>)
-
- #include <QtQml> to use this macro.
*/
/*!
@@ -44,8 +42,6 @@
Current the only supported type info is \c QML_HAS_ATTACHED_PROPERTIES which
declares that the \a Type supports \l {Attached Properties and Attached Signal Handlers}
{attached properties}.
-
- #include <QtQml> to use this macro.
*/
/*!
@@ -58,8 +54,6 @@
Any existing QQmlEngines must be deleted before calling this function. This function
only affects the application global cache. Delete the QQmlEngine to clear all cached
data relating to that engine.
-
- #include <QtQml> to use this method.
*/
@@ -93,10 +87,6 @@
"com.mycompany.qmlcomponents":
\code
- #include <QtQml>
-
- ...
-
qmlRegisterType<MySliderItem>("com.mycompany.qmlcomponents", 1, 0, "Slider");
\endcode
@@ -151,8 +141,6 @@
Returns the QML type id.
- #include <QtQml> to use this function.
-
\sa qmlRegisterTypeNotAvailable()
*/
@@ -167,8 +155,6 @@
Returns the QML type id.
- #include <QtQml> to use this function.
-
\sa qmlRegisterType(), {Registering Extension Objects}
*/
@@ -190,8 +176,6 @@
Returns the QML type id.
- #include <QtQml> to use this function.
-
\sa qmlRegisterUncreatableType()
*/
@@ -208,8 +192,6 @@
the \a parser provided.
Returns the QML type id.
-
- #include <QtQml> to use this function.
*/
/*!
@@ -244,8 +226,6 @@
Without this, a generic "Game is not a type" message would be given.
- #include <QtQml> to use this function.
-
\sa qmlRegisterUncreatableType()
*/
@@ -258,8 +238,6 @@
system. Instances of this type cannot be created from the QML
system.
- #include <QtQml> to use this function.
-
Returns the QML type id.
*/
@@ -270,8 +248,6 @@
This template function registers the C++ type in the QML system
under the name \a typeName.
- #include <QtQml> to use this function.
-
Returns the QML type id.
*/
@@ -305,10 +281,7 @@
}
// Second, register the singleton type provider with QML by calling this function in an initialization function.
- #include <QtQml>
- ...
qmlRegisterSingletonType("Qt.example.qjsvalueApi", 1, 0, "MyApi", example_qjsvalue_singletontype_provider);
- ...
\endcode
In order to use the registered singleton type in QML, you must import the singleton type.
@@ -408,10 +381,7 @@
}
// Third, register the singleton type provider with QML by calling this function in an initialization function.
- #include <QtQml>
- ...
qmlRegisterSingletonType<SingletonTypeExample>("Qt.example.qobjectSingleton", 1, 0, "MyApi", example_qobject_singletontype_provider);
- ...
\endcode
In order to use the registered singleton type in QML, you must import the singleton type.
@@ -481,10 +451,7 @@
\code
// Second, register the QML singleton type by calling this function in an initialization function.
- #include <QtQml>
- ...
qmlRegisterSingletonType(QUrl("file:///absolute/path/SingletonType.qml"), "Qt.example.qobjectSingleton", 1, 0, "RegisteredSingleton");
- ...
\endcode
In order to use the registered singleton type in QML, you must import the singleton type.
@@ -514,8 +481,6 @@
Normally QML files can be loaded as types directly from other QML files, or using a qmldir file. This function allows
registration of files to types from C++ code, such as when the type mapping needs to be procedurally determined at startup.
- #include <QtQml> to use this function.
-
Returns -1 if the registration was not successful.
*/
@@ -538,8 +503,6 @@
uri, major version combination will lead to a runtime error. Call this after
you have registered all of your types with the engine.
- #include <QtQml> to use this function.
-
Returns true if the module with \a uri as a \l{Identified Modules}
{module identifier} and \a majVersion as a major version number was found
and locked, otherwise returns false. The module must contain exported types
diff --git a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
index c0b74c4fc6..04d769e4dc 100644
--- a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
+++ b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
@@ -448,8 +448,8 @@ right-hand-side of the property declaration must be a valid alias reference:
[default] property alias <name>: <alias reference>
\endcode
-Unlike an ordinary property, an alias can only refer to a object, or the
-property of a object, that is within the scope of the \l{QML Object Types}
+Unlike an ordinary property, an alias can only refer to an object, or the
+property of an object, that is within the scope of the \l{QML Object Types}
{type} within which the alias is declared. It cannot contain arbitrary
JavaScript expressions and it cannot refer to objects declared outside of
the scope of its type. Also note the \e {alias reference} is not optional,
diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp
index f66e3e0875..a6e085a913 100644
--- a/src/qml/jit/qv4regalloc.cpp
+++ b/src/qml/jit/qv4regalloc.cpp
@@ -1398,7 +1398,7 @@ LifeTimeInterval *RegisterAllocator::cloneFixedInterval(int reg, bool isFP, cons
void RegisterAllocator::prepareRanges()
{
LifeTimeInterval ltiWithCalls = createFixedInterval(int(_info->calls().size()));
- foreach (int callPosition, _info->calls())
+ for (int callPosition : _info->calls())
ltiWithCalls.addRange(callPosition, callPosition);
const int regCount = _normalRegisters.size();
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index c28df7d74a..317eb7a8a7 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -1250,7 +1250,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
return ld->d()->locale;
if (const QV4::DateObject *d = value.as<DateObject>())
return d->toQDateTime();
- if (const QV4::ArrayBuffer *d = value.as<ArrayBuffer>())
+ if (const ArrayBuffer *d = value.as<ArrayBuffer>())
return d->asByteArray();
// NOTE: since we convert QTime to JS Date, round trip will change the variant type (to QDateTime)!
@@ -1378,6 +1378,8 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
return QV4::Encode(*reinterpret_cast<const double*>(ptr));
case QMetaType::QString:
return newString(*reinterpret_cast<const QString*>(ptr))->asReturnedValue();
+ case QMetaType::QByteArray:
+ return newArrayBuffer(*reinterpret_cast<const QByteArray*>(ptr))->asReturnedValue();
case QMetaType::Float:
return QV4::Encode(*reinterpret_cast<const float*>(ptr));
case QMetaType::Short:
@@ -1554,6 +1556,8 @@ QV4::ReturnedValue ExecutionEngine::metaTypeToJS(int type, const void *data)
return QV4::Encode(*reinterpret_cast<const double*>(data));
case QMetaType::QString:
return newString(*reinterpret_cast<const QString*>(data))->asReturnedValue();
+ case QMetaType::QByteArray:
+ return newArrayBuffer(*reinterpret_cast<const QByteArray*>(data))->asReturnedValue();
case QMetaType::Float:
return QV4::Encode(*reinterpret_cast<const float*>(data));
case QMetaType::Short:
@@ -1646,6 +1650,12 @@ bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data)
else
*reinterpret_cast<QString*>(data) = value->toQString();
return true;
+ case QMetaType::QByteArray:
+ if (const ArrayBuffer *ab = value->as<ArrayBuffer>())
+ *reinterpret_cast<QByteArray*>(data) = ab->asByteArray();
+ else
+ *reinterpret_cast<QByteArray*>(data) = QByteArray();
+ return true;
case QMetaType::Float:
*reinterpret_cast<float*>(data) = value->toNumber();
return true;
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index 29f83da522..b3462fe9b1 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -41,8 +41,10 @@
#include "qv4scopedvalue_p.h"
#include <QtQml/qjsengine.h>
+#ifndef QT_NO_NETWORK
#include <QtNetwork/qnetworkrequest.h>
#include <QtNetwork/qnetworkreply.h>
+#endif
#include <QtCore/qfile.h>
#include <QtQml/qqmlfile.h>
@@ -57,7 +59,10 @@ QT_BEGIN_NAMESPACE
QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine,
QV4::QmlContext *qmlContext, const QV4::Value &callback)
- : v4(engine), m_network(0), m_reply(0), m_url(url), m_redirectCount(0)
+ : v4(engine), m_url(url)
+#ifndef QT_NO_NETWORK
+ , m_redirectCount(0), m_network(0) , m_reply(0)
+#endif
{
if (qmlContext)
m_qmlContext.set(engine, *qmlContext);
@@ -66,6 +71,7 @@ QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine,
m_resultObject.set(v4, resultValue(v4));
+#ifndef QT_NO_NETWORK
m_network = engine->v8Engine->networkAccessManager();
QNetworkRequest request;
@@ -73,11 +79,17 @@ QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine,
m_reply = m_network->get(request);
QObject::connect(m_reply, SIGNAL(finished()), this, SLOT(finished()));
+#else
+ finished();
+#endif
}
QV4Include::~QV4Include()
{
- delete m_reply; m_reply = 0;
+#ifndef QT_NO_NETWORK
+ delete m_reply;
+ m_reply = 0;
+#endif
}
QV4::ReturnedValue QV4Include::resultValue(QV4::ExecutionEngine *v4, Status status)
@@ -123,6 +135,7 @@ QV4::ReturnedValue QV4Include::result()
#define INCLUDE_MAXIMUM_REDIRECT_RECURSION 15
void QV4Include::finished()
{
+#ifndef QT_NO_NETWORK
m_redirectCount++;
if (m_redirectCount < INCLUDE_MAXIMUM_REDIRECT_RECURSION) {
@@ -166,6 +179,12 @@ void QV4Include::finished()
} else {
resultObj->put(status, QV4::ScopedValue(scope, QV4::Primitive::fromInt32(NetworkError)));
}
+#else
+ QV4::Scope scope(v4);
+ QV4::ScopedObject resultObj(scope, m_resultObject.value());
+ QV4::ScopedString status(scope, v4->newString(QStringLiteral("status")));
+ resultObj->put(status, QV4::ScopedValue(scope, QV4::Primitive::fromInt32(NetworkError)));
+#endif //QT_NO_NETWORK
QV4::ScopedValue cb(scope, m_callbackFunction.value());
callback(cb, resultObj);
@@ -188,14 +207,15 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
if (!context || !context->isJSContext)
V4THROW_ERROR("Qt.include(): Can only be called from JavaScript files");
- QUrl url(scope.engine->resolvedUrl(ctx->args()[0].toQStringNoThrow()));
- if (scope.engine->qmlEngine() && scope.engine->qmlEngine()->urlInterceptor())
- url = scope.engine->qmlEngine()->urlInterceptor()->intercept(url, QQmlAbstractUrlInterceptor::JavaScriptFile);
-
QV4::ScopedValue callbackFunction(scope, QV4::Primitive::undefinedValue());
if (ctx->argc() >= 2 && ctx->args()[1].as<QV4::FunctionObject>())
callbackFunction = ctx->args()[1];
+#ifndef QT_NO_NETWORK
+ QUrl url(scope.engine->resolvedUrl(ctx->args()[0].toQStringNoThrow()));
+ if (scope.engine->qmlEngine() && scope.engine->qmlEngine()->urlInterceptor())
+ url = scope.engine->qmlEngine()->urlInterceptor()->intercept(url, QQmlAbstractUrlInterceptor::JavaScriptFile);
+
QString localFile = QQmlFile::urlToLocalFileOrQrc(url);
QV4::ScopedValue result(scope);
@@ -243,6 +263,12 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
}
return result->asReturnedValue();
+#else
+ QV4::ScopedValue result(scope);
+ result = resultValue(scope.engine, NetworkError);
+ callback(callbackFunction, result);
+ return result->asReturnedValue();
+#endif
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4include_p.h b/src/qml/jsruntime/qv4include_p.h
index 257dc05e65..1750e6a7e1 100644
--- a/src/qml/jsruntime/qv4include_p.h
+++ b/src/qml/jsruntime/qv4include_p.h
@@ -62,7 +62,9 @@
QT_BEGIN_NAMESPACE
class QQmlEngine;
+#ifndef QT_NO_NETWORK
class QNetworkAccessManager;
+#endif
class QNetworkReply;
class QV4Include : public QObject
{
@@ -90,15 +92,16 @@ private:
static void callback(const QV4::Value &callback, const QV4::Value &status);
QV4::ExecutionEngine *v4;
- QNetworkAccessManager *m_network;
- QPointer<QNetworkReply> m_reply;
-
QUrl m_url;
+
+#ifndef QT_NO_NETWORK
int m_redirectCount;
+ QNetworkAccessManager *m_network;
+ QPointer<QNetworkReply> m_reply;
+#endif
QV4::PersistentValue m_callbackFunction;
QV4::PersistentValue m_resultObject;
-
QV4::PersistentValue m_qmlContext;
};
diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp
index f264ec028e..8c5e7d8be1 100644
--- a/src/qml/jsruntime/qv4mathobject.cpp
+++ b/src/qml/jsruntime/qv4mathobject.cpp
@@ -51,8 +51,6 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(MathObject);
-static const double qt_PI = 2.0 * ::asin(1.0);
-
Heap::MathObject::MathObject()
{
Scope scope(internalClass->engine);
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 8aae4dff1e..596a97a444 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -54,6 +54,7 @@
#include <private/qqmlbuiltinfunctions_p.h>
#include <private/qv8engine_p.h>
+#include <private/qv4arraybuffer_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qv4runtime_p.h>
#include <private/qv4variantobject_p.h>
@@ -336,6 +337,8 @@ ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *obje
} else if (property->isV4Function()) {
Scope scope(engine);
ScopedContext global(scope, engine->qmlContext());
+ if (!global)
+ global = engine->rootContext();
return QV4::QObjectMethod::create(global, object, property->coreIndex);
} else if (property->isSignalHandler()) {
QmlSignalHandler::initProto(engine);
@@ -1099,6 +1102,7 @@ private:
// Pointers to allocData
union {
QString *qstringPtr;
+ QByteArray *qbyteArrayPtr;
QVariant *qvariantPtr;
QList<QObject *> *qlistPtr;
QJSValue *qjsValuePtr;
@@ -1220,6 +1224,13 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
default:
return 10;
}
+ } else if (actual.as<ArrayBuffer>()) {
+ switch (conversionType) {
+ case QMetaType::QByteArray:
+ return 0;
+ default:
+ return 10;
+ }
} else if (actual.as<ArrayObject>()) {
switch (conversionType) {
case QMetaType::QJsonArray:
@@ -1476,6 +1487,8 @@ void CallArgument::cleanup()
{
if (type == QMetaType::QString) {
qstringPtr->~QString();
+ } else if (type == QMetaType::QByteArray) {
+ qbyteArrayPtr->~QByteArray();
} else if (type == -1 || type == QMetaType::QVariant) {
qvariantPtr->~QVariant();
} else if (type == qMetaTypeId<QJSValue>()) {
@@ -1578,6 +1591,12 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
else
qstringPtr = new (&allocData) QString(value.toQStringNoThrow());
type = callType;
+ } else if (callType == QMetaType::QByteArray) {
+ if (const ArrayBuffer *ab = value.as<ArrayBuffer>())
+ qbyteArrayPtr = new (&allocData) QByteArray(ab->asByteArray());
+ else
+ qbyteArrayPtr = new (&allocData) QByteArray();
+ type = callType;
} else if (callType == QMetaType::QObjectStar) {
qobjectPtr = 0;
if (const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
@@ -1675,6 +1694,8 @@ QV4::ReturnedValue CallArgument::toValue(QV4::ExecutionEngine *engine)
return QV4::Encode(floatValue);
} else if (type == QMetaType::QString) {
return QV4::Encode(engine->newString(*qstringPtr));
+ } else if (type == QMetaType::QByteArray) {
+ return QV4::Encode(engine->newArrayBuffer(*qbyteArrayPtr));
} else if (type == QMetaType::QObjectStar) {
QObject *object = qobjectPtr;
if (object)
diff --git a/src/qml/qml.pro b/src/qml/qml.pro
index d75262bf0b..b119aa12af 100644
--- a/src/qml/qml.pro
+++ b/src/qml/qml.pro
@@ -1,5 +1,11 @@
TARGET = QtQml
-QT = core-private network
+QT = core-private
+
+no_network {
+ DEFINES += QT_NO_NETWORK
+} else {
+ QT += network
+}
DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES
@@ -11,9 +17,6 @@ solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2
# Ensure this gcc optimization is switched off for mips platforms to avoid trouble with JIT.
gcc:isEqual(QT_ARCH, "mips"): QMAKE_CXXFLAGS += -fno-reorder-blocks
-MODULE_PLUGIN_TYPES = \
- qmltooling
-
exists("qqml_enable_gcov") {
QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage -fno-elide-constructors
LIBS_PRIVATE += -lgcov
@@ -29,8 +32,6 @@ greaterThan(QT_CLANG_MAJOR_VERSION, 3)|greaterThan(QT_CLANG_MINOR_VERSION, 3)| \
if(equals(QT_APPLE_CLANG_MAJOR_VERSION, 5):greaterThan(QT_APPLE_CLANG_MINOR_VERSION, 0)): \
WERROR += -Wno-error=unused-const-variable
-load(qt_module)
-
HEADERS += qtqmlglobal.h \
qtqmlglobal_p.h
@@ -46,3 +47,7 @@ include(qml/qml.pri)
include(debugger/debugger.pri)
include(animations/animations.pri)
include(types/types.pri)
+
+MODULE_PLUGIN_TYPES = \
+ qmltooling
+load(qt_module)
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index b8bd0f7f1d..fbd2d13e40 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -378,6 +378,13 @@ QQmlComponent::~QQmlComponent()
if (d->state.completePending) {
qWarning("QQmlComponent: Component destroyed while completion pending");
+
+ if (isError()) {
+ qWarning() << "This may have been caused by one of the following errors:";
+ foreach (const QQmlError &error, d->state.errors)
+ qWarning().nospace().noquote() << QLatin1String(" ") << error;
+ }
+
d->completeCreate();
}
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 0e99e4ca89..a5c920d28a 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -53,7 +53,6 @@
#include "qqmlscriptstring.h"
#include "qqmlglobal_p.h"
#include "qqmlcomponent_p.h"
-#include "qqmlnetworkaccessmanagerfactory.h"
#include "qqmldirparser_p.h"
#include "qqmlextensioninterface.h"
#include "qqmllist_p.h"
@@ -63,25 +62,25 @@
#include "qqmlincubator.h"
#include "qqmlabstracturlinterceptor.h"
#include <private/qqmlboundsignal_p.h>
-
#include <QtCore/qstandardpaths.h>
#include <QtCore/qsettings.h>
-
#include <QtCore/qmetaobject.h>
-#include <QNetworkAccessManager>
#include <QDebug>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qdir.h>
#include <QtCore/qmutex.h>
#include <QtCore/qthread.h>
#include <private/qthread_p.h>
+
+#ifndef QT_NO_NETWORK
+#include "qqmlnetworkaccessmanagerfactory.h"
+#include <QNetworkAccessManager>
#include <QtNetwork/qnetworkconfigmanager.h>
+#endif
#include <private/qobject_p.h>
#include <private/qmetaobject_p.h>
-
#include <private/qqmllocale_p.h>
-
#include <private/qqmlbind_p.h>
#include <private/qqmlconnections_p.h>
#include <private/qqmltimer_p.h>
@@ -493,6 +492,10 @@ The following functions are also on the Qt object.
from right to left.
\endlist
\row
+ \li \c application.font
+ \li This read-only property holds the default application font as
+ returned by \l QGuiApplication::font().
+ \row
\li \c application.arguments
\li This is a string list of the arguments the executable was invoked with.
\row
@@ -531,6 +534,7 @@ The following functions are also on the Qt object.
\li application.active
\li application.state
\li application.layoutDirection
+ \li application.font
\endlist
*/
@@ -605,9 +609,11 @@ QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
cleanup(0), erroredBindings(0), inProgressCreations(0),
workerScriptEngine(0),
activeObjectCreator(0),
- networkAccessManager(0), networkAccessManagerFactory(0), urlInterceptor(0),
- scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
- incubatorCount(0), incubationController(0)
+#ifndef QT_NO_NETWORK
+ networkAccessManager(0), networkAccessManagerFactory(0),
+#endif
+ urlInterceptor(0), scarceResourcesRefCount(0), importDatabase(e), typeLoader(e),
+ uniqueId(1), incubatorCount(0), incubationController(0)
{
}
@@ -1066,7 +1072,17 @@ QQmlAbstractUrlInterceptor *QQmlEngine::urlInterceptor() const
return d->urlInterceptor;
}
+void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
+{
+ if (activeObjectCreator) {
+ activeObjectCreator->finalizeCallbacks()->append(qMakePair(QPointer<QObject>(obj), index));
+ } else {
+ void *args[] = { 0 };
+ QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
+ }
+}
+#ifndef QT_NO_NETWORK
/*!
Sets the \a factory to use for creating QNetworkAccessManager(s).
@@ -1095,16 +1111,6 @@ QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
return d->networkAccessManagerFactory;
}
-void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
-{
- if (activeObjectCreator) {
- activeObjectCreator->finalizeCallbacks()->append(qMakePair(QPointer<QObject>(obj), index));
- } else {
- void *args[] = { 0 };
- QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
- }
-}
-
QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
{
QMutexLocker locker(&networkAccessManagerMutex);
@@ -1143,6 +1149,7 @@ QNetworkAccessManager *QQmlEngine::networkAccessManager() const
Q_D(const QQmlEngine);
return d->getNetworkAccessManager();
}
+#endif // QT_NO_NETWORK
/*!
diff --git a/src/qml/qml/qqmlengine.h b/src/qml/qml/qqmlengine.h
index eee0587531..28bd66047e 100644
--- a/src/qml/qml/qqmlengine.h
+++ b/src/qml/qml/qqmlengine.h
@@ -44,6 +44,7 @@
#include <QtCore/qobject.h>
#include <QtCore/qmap.h>
#include <QtQml/qjsengine.h>
+#include <QtQml/qqml.h>
#include <QtQml/qqmlerror.h>
#include <QtQml/qqmldebug.h>
@@ -86,8 +87,10 @@ class QQmlExpression;
class QQmlContext;
class QQmlType;
class QUrl;
+#ifndef QT_NO_NETWORK
class QNetworkAccessManager;
class QQmlNetworkAccessManagerFactory;
+#endif
class QQmlIncubationController;
class Q_QML_EXPORT QQmlEngine : public QJSEngine
{
@@ -114,10 +117,12 @@ public:
bool importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors);
+#ifndef QT_NO_NETWORK
void setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *);
QQmlNetworkAccessManagerFactory *networkAccessManagerFactory() const;
QNetworkAccessManager *networkAccessManager() const;
+#endif
void setUrlInterceptor(QQmlAbstractUrlInterceptor* urlInterceptor);
QQmlAbstractUrlInterceptor* urlInterceptor() const;
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index e56a3fc57f..7258ffe6ed 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -158,12 +158,12 @@ public:
void registerFinalizeCallback(QObject *obj, int index);
QQmlObjectCreator *activeObjectCreator;
-
+#ifndef QT_NO_NETWORK
QNetworkAccessManager *createNetworkAccessManager(QObject *parent) const;
QNetworkAccessManager *getNetworkAccessManager() const;
mutable QNetworkAccessManager *networkAccessManager;
mutable QQmlNetworkAccessManagerFactory *networkAccessManagerFactory;
-
+#endif
QHash<QString,QSharedPointer<QQmlImageProviderBase> > imageProviders;
QQmlAbstractUrlInterceptor* urlInterceptor;
@@ -172,9 +172,8 @@ public:
void referenceScarceResources();
void dereferenceScarceResources();
- QQmlTypeLoader typeLoader;
QQmlImportDatabase importDatabase;
-
+ QQmlTypeLoader typeLoader;
QString offlineStoragePath;
diff --git a/src/qml/qml/qqmlfile.cpp b/src/qml/qml/qqmlfile.cpp
index ea4e9a1013..8ce0cc2026 100644
--- a/src/qml/qml/qqmlfile.cpp
+++ b/src/qml/qml/qqmlfile.cpp
@@ -67,6 +67,8 @@ static char assets_string[] = "assets";
#endif
class QQmlFilePrivate;
+
+#ifndef QT_NO_NETWORK
class QQmlFileNetworkReply : public QObject
{
Q_OBJECT
@@ -97,6 +99,7 @@ private:
int m_redirectCount;
QNetworkReply *m_reply;
};
+#endif
class QQmlFilePrivate
{
@@ -114,10 +117,12 @@ public:
Error error;
QString errorString;
-
+#ifndef QT_NO_NETWORK
QQmlFileNetworkReply *reply;
+#endif
};
+#ifndef QT_NO_NETWORK
int QQmlFileNetworkReply::finishedIndex = -1;
int QQmlFileNetworkReply::downloadProgressIndex = -1;
int QQmlFileNetworkReply::networkFinishedIndex = -1;
@@ -200,9 +205,13 @@ void QQmlFileNetworkReply::networkDownloadProgress(qint64 a, qint64 b)
{
emit downloadProgress(a, b);
}
+#endif // QT_NO_NETWORK
QQmlFilePrivate::QQmlFilePrivate()
-: error(None), reply(0)
+: error(None)
+#ifndef QT_NO_NETWORK
+, reply(0)
+#endif
{
}
@@ -225,7 +234,9 @@ QQmlFile::QQmlFile(QQmlEngine *e, const QString &url)
QQmlFile::~QQmlFile()
{
+#ifndef QT_NO_NETWORK
delete d->reply;
+#endif
delete d;
d = 0;
}
@@ -263,8 +274,10 @@ QQmlFile::Status QQmlFile::status() const
{
if (d->url.isEmpty() && d->urlString.isEmpty())
return Null;
+#ifndef QT_NO_NETWORK
else if (d->reply)
return Loading;
+#endif
else if (d->error != QQmlFilePrivate::None)
return Error;
else
@@ -321,7 +334,11 @@ void QQmlFile::load(QQmlEngine *engine, const QUrl &url)
d->error = QQmlFilePrivate::NotFound;
}
} else {
+#ifndef QT_NO_NETWORK
d->reply = new QQmlFileNetworkReply(engine, d, url);
+#else
+ d->error = QQmlFilePrivate::NotFound;
+#endif
}
}
@@ -348,10 +365,14 @@ void QQmlFile::load(QQmlEngine *engine, const QString &url)
d->error = QQmlFilePrivate::NotFound;
}
} else {
+#ifndef QT_NO_NETWORK
QUrl qurl(url);
d->url = qurl;
d->urlString = QString();
d->reply = new QQmlFileNetworkReply(engine, d, qurl);
+#else
+ d->error = QQmlFilePrivate::NotFound;
+#endif
}
}
@@ -368,6 +389,7 @@ void QQmlFile::clear(QObject *)
clear();
}
+#ifndef QT_NO_NETWORK
bool QQmlFile::connectFinished(QObject *object, const char *method)
{
if (!d || !d->reply) {
@@ -411,6 +433,7 @@ bool QQmlFile::connectDownloadProgress(QObject *object, int method)
return QMetaObject::connect(d->reply, QQmlFileNetworkReply::downloadProgressIndex,
object, method);
}
+#endif
/*!
Returns true if QQmlFile will open \a url synchronously.
diff --git a/src/qml/qml/qqmlfile.h b/src/qml/qml/qqmlfile.h
index b0910cc0f4..3dd683a2cd 100644
--- a/src/qml/qml/qqmlfile.h
+++ b/src/qml/qml/qqmlfile.h
@@ -80,10 +80,12 @@ public:
void clear();
void clear(QObject *);
+#ifndef QT_NO_NETWORK
bool connectFinished(QObject *, const char *);
bool connectFinished(QObject *, int);
bool connectDownloadProgress(QObject *, const char *);
bool connectDownloadProgress(QObject *, int);
+#endif
static bool isSynchronous(const QString &url);
static bool isSynchronous(const QUrl &url);
diff --git a/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp b/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp
index f9fea0279e..c94db8e168 100644
--- a/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp
+++ b/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp
@@ -41,6 +41,8 @@
QT_BEGIN_NAMESPACE
+#ifndef QT_NO_NETWORK
+
/*!
\class QQmlNetworkAccessManagerFactory
\since 5.0
@@ -101,4 +103,6 @@ QQmlNetworkAccessManagerFactory::~QQmlNetworkAccessManagerFactory()
implementation of this method is reentrant.
*/
+#endif //QT_NO_NETWORK
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlnetworkaccessmanagerfactory.h b/src/qml/qml/qqmlnetworkaccessmanagerfactory.h
index 8e3b94fad3..ba3561b9f4 100644
--- a/src/qml/qml/qqmlnetworkaccessmanagerfactory.h
+++ b/src/qml/qml/qqmlnetworkaccessmanagerfactory.h
@@ -45,6 +45,7 @@
QT_BEGIN_NAMESPACE
+#ifndef QT_NO_NETWORK
class QNetworkAccessManager;
class Q_QML_EXPORT QQmlNetworkAccessManagerFactory
@@ -55,6 +56,8 @@ public:
};
+#endif //QT_NO_NETWORK
+
QT_END_NAMESPACE
#endif // QQMLNETWORKACCESSMANAGERFACTORY_H
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index b516cc7d89..1a7896bde8 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -640,7 +640,7 @@ void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip)
if (_compiledObject->idIndex) {
const QQmlPropertyData *idProperty = propertyData.last();
- Q_ASSERT(!idProperty || !idProperty->isValid() || idProperty->name(_qobject) == QStringLiteral("id"));
+ Q_ASSERT(!idProperty || !idProperty->isValid() || idProperty->name(_qobject) == QLatin1String("id"));
if (idProperty && idProperty->isValid() && idProperty->isWritable() && idProperty->propType == QMetaType::QString) {
QV4::CompiledData::Binding idBinding;
idBinding.propertyNameIndex = 0; // Not used
diff --git a/src/qml/qml/qqmlscriptstring.cpp b/src/qml/qml/qqmlscriptstring.cpp
index b027f043ec..3230e69b6d 100644
--- a/src/qml/qml/qqmlscriptstring.cpp
+++ b/src/qml/qml/qqmlscriptstring.cpp
@@ -135,10 +135,10 @@ bool QQmlScriptString::operator==(const QQmlScriptString &other) const
if (d->isStringLiteral || other.d->isStringLiteral)
return d->isStringLiteral && other.d->isStringLiteral && d->script == other.d->script;
- if (d->script == QStringLiteral("true") ||
- d->script == QStringLiteral("false") ||
- d->script == QStringLiteral("undefined") ||
- d->script == QStringLiteral("null"))
+ if (d->script == QLatin1String("true") ||
+ d->script == QLatin1String("false") ||
+ d->script == QLatin1String("undefined") ||
+ d->script == QLatin1String("null"))
return d->script == other.d->script;
return d->context == other.d->context &&
@@ -172,7 +172,7 @@ Returns whether the content of the QQmlScriptString is the \c undefined literal.
*/
bool QQmlScriptString::isUndefinedLiteral() const
{
- return d->script == QStringLiteral("undefined");
+ return d->script == QLatin1String("undefined");
}
/*!
@@ -180,7 +180,7 @@ Returns whether the content of the QQmlScriptString is the \c null literal.
*/
bool QQmlScriptString::isNullLiteral() const
{
- return d->script == QStringLiteral("null");
+ return d->script == QLatin1String("null");
}
/*!
@@ -211,8 +211,8 @@ sets \a ok to true. Otherwise returns false and sets \a ok to false.
*/
bool QQmlScriptString::booleanLiteral(bool *ok) const
{
- bool isTrue = d->script == QStringLiteral("true");
- bool isFalse = !isTrue && d->script == QStringLiteral("false");
+ bool isTrue = d->script == QLatin1String("true");
+ bool isFalse = !isTrue && d->script == QLatin1String("false");
if (ok)
*ok = isTrue || isFalse;
return isTrue ? true : false;
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 52a7562b58..15e8d62efc 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -112,6 +112,7 @@ namespace {
};
}
+#ifndef QT_NO_NETWORK
// This is a lame object that we need to ensure that slots connected to
// QNetworkReply get called in the correct thread (the loader thread).
// As QQmlTypeLoader lives in the main thread, and we can't use
@@ -131,6 +132,7 @@ public slots:
private:
QQmlTypeLoader *l;
};
+#endif // QT_NO_NETWORK
class QQmlTypeLoaderThread : public QQmlThread
{
@@ -138,9 +140,10 @@ class QQmlTypeLoaderThread : public QQmlThread
public:
QQmlTypeLoaderThread(QQmlTypeLoader *loader);
+#ifndef QT_NO_NETWORK
QNetworkAccessManager *networkAccessManager() const;
QQmlTypeLoaderNetworkReplyProxy *networkReplyProxy() const;
-
+#endif // QT_NO_NETWORK
void load(QQmlDataBlob *b);
void loadAsync(QQmlDataBlob *b);
void loadWithStaticData(QQmlDataBlob *b, const QByteArray &);
@@ -163,11 +166,13 @@ private:
void initializeEngineMain(QQmlExtensionInterface *iface, const char *uri);
QQmlTypeLoader *m_loader;
+#ifndef QT_NO_NETWORK
mutable QNetworkAccessManager *m_networkAccessManager;
mutable QQmlTypeLoaderNetworkReplyProxy *m_networkReplyProxy;
+#endif // QT_NO_NETWORK
};
-
+#ifndef QT_NO_NETWORK
QQmlTypeLoaderNetworkReplyProxy::QQmlTypeLoaderNetworkReplyProxy(QQmlTypeLoader *l)
: l(l)
{
@@ -196,7 +201,7 @@ void QQmlTypeLoaderNetworkReplyProxy::manualFinished(QNetworkReply *reply)
l->networkReplyProgress(reply, replySize, replySize);
l->networkReplyFinished(reply);
}
-
+#endif // QT_NO_NETWORK
/*!
\class QQmlDataBlob
@@ -480,6 +485,7 @@ void QQmlDataBlob::done()
{
}
+#ifndef QT_NO_NETWORK
/*!
Invoked if there is a network error while fetching this blob.
@@ -532,6 +538,7 @@ void QQmlDataBlob::networkError(QNetworkReply::NetworkError networkError)
setError(error);
}
+#endif // QT_NO_NETWORK
/*!
Called if \a blob, which was previously waited for, has an error.
@@ -730,12 +737,16 @@ void QQmlDataBlob::ThreadData::setProgress(quint8 v)
}
QQmlTypeLoaderThread::QQmlTypeLoaderThread(QQmlTypeLoader *loader)
-: m_loader(loader), m_networkAccessManager(0), m_networkReplyProxy(0)
+: m_loader(loader)
+#ifndef QT_NO_NETWORK
+, m_networkAccessManager(0), m_networkReplyProxy(0)
+#endif // QT_NO_NETWORK
{
// Do that after initializing all the members.
startup();
}
+#ifndef QT_NO_NETWORK
QNetworkAccessManager *QQmlTypeLoaderThread::networkAccessManager() const
{
Q_ASSERT(isThisThread());
@@ -753,6 +764,7 @@ QQmlTypeLoaderNetworkReplyProxy *QQmlTypeLoaderThread::networkReplyProxy() const
Q_ASSERT(m_networkReplyProxy); // Must call networkAccessManager() first
return m_networkReplyProxy;
}
+#endif // QT_NO_NETWORK
void QQmlTypeLoaderThread::load(QQmlDataBlob *b)
{
@@ -810,10 +822,12 @@ void QQmlTypeLoaderThread::initializeEngine(QQmlExtensionInterface *iface,
void QQmlTypeLoaderThread::shutdownThread()
{
+#ifndef QT_NO_NETWORK
delete m_networkAccessManager;
m_networkAccessManager = 0;
delete m_networkReplyProxy;
m_networkReplyProxy = 0;
+#endif // QT_NO_NETWORK
}
void QQmlTypeLoaderThread::loadThread(QQmlDataBlob *b)
@@ -899,12 +913,14 @@ void QQmlTypeLoader::invalidate()
m_thread = 0;
}
+#ifndef QT_NO_NETWORK
// Need to delete the network replies after
// the loader thread is shutdown as it could be
// getting new replies while we clear them
for (NetworkReplies::Iterator iter = m_networkReplies.begin(); iter != m_networkReplies.end(); ++iter)
(*iter)->release();
m_networkReplies.clear();
+#endif // QT_NO_NETWORK
}
void QQmlTypeLoader::lock()
@@ -1082,7 +1098,7 @@ void QQmlTypeLoader::loadThread(QQmlDataBlob *blob)
setData(blob, &file);
} else {
-
+#ifndef QT_NO_NETWORK
QNetworkReply *reply = m_thread->networkAccessManager()->get(QNetworkRequest(blob->m_url));
QQmlTypeLoaderNetworkReplyProxy *nrp = m_thread->networkReplyProxy();
blob->addref();
@@ -1099,13 +1115,14 @@ void QQmlTypeLoader::loadThread(QQmlDataBlob *blob)
#ifdef DATABLOB_DEBUG
qWarning("QQmlDataBlob: requested %s", qPrintable(blob->url().toString()));
-#endif
-
+#endif // DATABLOB_DEBUG
+#endif // QT_NO_NETWORK
}
}
#define DATALOADER_MAXIMUM_REDIRECT_RECURSION 16
+#ifndef QT_NO_NETWORK
void QQmlTypeLoader::networkReplyFinished(QNetworkReply *reply)
{
Q_ASSERT(m_thread->isThisThread());
@@ -1161,6 +1178,7 @@ void QQmlTypeLoader::networkReplyProgress(QNetworkReply *reply,
m_thread->callDownloadProgressChanged(blob, blob->m_data.progress());
}
}
+#endif // QT_NO_NETWORK
/*!
Return the QQmlEngine associated with this loader
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index 01d223bbce..49a4ac716a 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -53,7 +53,9 @@
#include <QtCore/qobject.h>
#include <QtCore/qatomic.h>
+#ifndef QT_NO_NETWORK
#include <QtNetwork/qnetworkreply.h>
+#endif
#include <QtQml/qqmlerror.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlfile.h>
@@ -156,7 +158,9 @@ protected:
virtual void dataReceived(const Data &) = 0;
virtual void initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit*) = 0;
virtual void done();
+#ifndef QT_NO_NETWORK
virtual void networkError(QNetworkReply::NetworkError);
+#endif
virtual void dependencyError(QQmlDataBlob *);
virtual void dependencyComplete(QQmlDataBlob *);
virtual void allDependenciesDone();
@@ -320,17 +324,21 @@ public:
private:
friend class QQmlDataBlob;
friend class QQmlTypeLoaderThread;
+#ifndef QT_NO_NETWORK
friend class QQmlTypeLoaderNetworkReplyProxy;
+#endif // QT_NO_NETWORK
void shutdownThread();
void loadThread(QQmlDataBlob *);
void loadWithStaticDataThread(QQmlDataBlob *, const QByteArray &);
void loadWithCachedUnitThread(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit);
+#ifndef QT_NO_NETWORK
void networkReplyFinished(QNetworkReply *);
void networkReplyProgress(QNetworkReply *, qint64, qint64);
typedef QHash<QNetworkReply *, QQmlDataBlob *> NetworkReplies;
+#endif
void setData(QQmlDataBlob *, const QByteArray &);
void setData(QQmlDataBlob *, QQmlFile *);
@@ -362,7 +370,9 @@ private:
QQmlEngine *m_engine;
QQmlTypeLoaderThread *m_thread;
+#ifndef QT_NO_NETWORK
NetworkReplies m_networkReplies;
+#endif
TypeCache m_typeCache;
ScriptCache m_scriptCache;
QmldirCache m_qmldirCache;
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index 2f2c6cf7dc..33fe655368 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -125,6 +125,28 @@ ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, Q
return w.asReturnedValue();
}
+static int enumForSingleton(String *name, QObject *qobjectSingleton)
+{
+ // ### Optimize
+ QByteArray enumName = name->toQString().toUtf8();
+ const QMetaObject *metaObject = qobjectSingleton->metaObject();
+ for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) {
+ QMetaEnum e = metaObject->enumerator(ii);
+ bool ok;
+ int value = e.keyToValue(enumName.constData(), &ok);
+ if (ok)
+ return value;
+ }
+ return -1;
+}
+
+static ReturnedValue throwLowercaseEnumError(QV4::ExecutionEngine *v4, String *name, QQmlType *type)
+{
+ const QString message =
+ QStringLiteral("Cannot access enum value '%1' of '%2', enum values need to start with an uppercase letter.")
+ .arg(name->toQString()).arg(QLatin1String(type->typeName()));
+ return v4->throwTypeError(message);
+}
ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasProperty)
{
@@ -141,9 +163,9 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope
QQmlContextData *context = v4->callingQmlContext();
QObject *object = w->d()->object;
+ QQmlType *type = w->d()->type;
- if (w->d()->type) {
- QQmlType *type = w->d()->type;
+ if (type) {
// singleton types are handled differently to other types.
if (type->isSingleton()) {
@@ -153,24 +175,29 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope
QObject *qobjectSingleton = siinfo->qobjectApi(e);
if (qobjectSingleton) {
+
// check for enum value
- if (name->startsWithUpper()) {
- if (w->d()->mode == Heap::QmlTypeWrapper::IncludeEnums) {
- // ### Optimize
- QByteArray enumName = name->toQString().toUtf8();
- const QMetaObject *metaObject = qobjectSingleton->metaObject();
- for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) {
- QMetaEnum e = metaObject->enumerator(ii);
- bool ok;
- int value = e.keyToValue(enumName.constData(), &ok);
- if (ok)
- return QV4::Primitive::fromInt32(value).asReturnedValue();
- }
- }
+ const bool includeEnums = w->d()->mode == Heap::QmlTypeWrapper::IncludeEnums;
+ if (includeEnums && name->startsWithUpper()) {
+ const int value = enumForSingleton(name, qobjectSingleton);
+ if (value != -1)
+ return QV4::Primitive::fromInt32(value).asReturnedValue();
}
// check for property.
- return QV4::QObjectWrapper::getQmlProperty(v4, context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, hasProperty);
+ bool ok;
+ const ReturnedValue result = QV4::QObjectWrapper::getQmlProperty(v4, context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, &ok);
+ if (hasProperty)
+ *hasProperty = ok;
+
+ // Warn when attempting to access a lowercased enum value, singleton case
+ if (!ok && includeEnums && !name->startsWithUpper()) {
+ const int value = enumForSingleton(name, qobjectSingleton);
+ if (value != -1)
+ return throwLowercaseEnumError(v4, name, type);
+ }
+
+ return result;
} else if (!siinfo->scriptApi(e).isUndefined()) {
// NOTE: if used in a binding, changes will not trigger re-evaluation since non-NOTIFYable.
QV4::ScopedObject o(scope, QJSValuePrivate::convertedToValue(v4, siinfo->scriptApi(e)));
@@ -227,9 +254,20 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope
Q_ASSERT(!"Unreachable");
}
+ bool ok = false;
+ const ReturnedValue result = Object::get(m, name, &ok);
if (hasProperty)
- *hasProperty = false;
- return Object::get(m, name, hasProperty);
+ *hasProperty = ok;
+
+ // Warn when attempting to access a lowercased enum value, non-singleton case
+ if (!ok && type && !type->isSingleton() && !name->startsWithUpper()) {
+ bool enumOk = false;
+ type->enumValue(QQmlEnginePrivate::get(v4->qmlEngine()), name, &enumOk);
+ if (enumOk)
+ return throwLowercaseEnumError(v4, name, type);
+ }
+
+ return result;
}
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index fe02c6633e..af94ec757c 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -70,7 +70,7 @@
using namespace QV4;
-#ifndef QT_NO_XMLSTREAMREADER
+#if !defined(QT_NO_XMLSTREAMREADER) && !defined(QT_NO_NETWORK)
#define V4THROW_REFERENCE(string) { \
ScopedObject error(scope, ctx->engine()->newReferenceErrorObject(QStringLiteral(string))); \
@@ -2040,6 +2040,6 @@ void *qt_add_qmlxmlhttprequest(ExecutionEngine *v4)
QT_END_NAMESPACE
-#endif // QT_NO_XMLSTREAMREADER
+#endif // QT_NO_XMLSTREAMREADER && QT_NO_NETWORK
#include <qqmlxmlhttprequest.moc>
diff --git a/src/qml/qml/qqmlxmlhttprequest_p.h b/src/qml/qml/qqmlxmlhttprequest_p.h
index 7bbfb5243c..df30873915 100644
--- a/src/qml/qml/qqmlxmlhttprequest_p.h
+++ b/src/qml/qml/qqmlxmlhttprequest_p.h
@@ -55,7 +55,7 @@
#include <QtCore/qglobal.h>
#include <private/qqmlglobal_p.h>
-#ifndef QT_NO_XMLSTREAMREADER
+#if !defined(QT_NO_XMLSTREAMREADER) && !defined(QT_NO_NETWORK)
QT_BEGIN_NAMESPACE
@@ -64,7 +64,7 @@ void qt_rem_qmlxmlhttprequest(QV4::ExecutionEngine *engine, void *);
QT_END_NAMESPACE
-#endif // QT_NO_XMLSTREAMREADER
+#endif // QT_NO_XMLSTREAMREADER && QT_NO_NETWORK
#endif // QQMLXMLHTTPREQUEST_P_H
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index d322088f61..89f128a0e7 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -159,18 +159,22 @@ QV8Engine::~QV8Engine()
delete m_extensionData[ii];
m_extensionData.clear();
+#if !defined(QT_NO_XMLSTREAMREADER) && defined(QT_NO_NETWORK)
qt_rem_qmlxmlhttprequest(m_v4Engine, m_xmlHttpRequestData);
m_xmlHttpRequestData = 0;
+#endif
delete m_listModelData;
m_listModelData = 0;
delete m_v4Engine;
}
+#ifndef QT_NO_NETWORK
QNetworkAccessManager *QV8Engine::networkAccessManager()
{
return QQmlEnginePrivate::get(m_engine)->getNetworkAccessManager();
}
+#endif
const QSet<QString> &QV8Engine::illegalNames() const
{
@@ -189,8 +193,10 @@ void QV8Engine::initializeGlobal()
QQmlDateExtension::registerExtension(m_v4Engine);
QQmlNumberExtension::registerExtension(m_v4Engine);
+#if !defined(QT_NO_XMLSTREAMREADER) && !defined(QT_NO_NETWORK)
qt_add_domexceptions(m_v4Engine);
m_xmlHttpRequestData = qt_add_qmlxmlhttprequest(m_v4Engine);
+#endif
qt_add_sqlexceptions(m_v4Engine);
diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h
index 4ffd36ca34..9054c731db 100644
--- a/src/qml/qml/v8/qv8engine_p.h
+++ b/src/qml/qml/v8/qv8engine_p.h
@@ -194,10 +194,12 @@ public:
void freezeObject(const QV4::Value &value);
+#ifndef QT_NO_NETWORK
// Return the network access manager for this engine. By default this returns the network
// access manager of the QQmlEngine. It is overridden in the case of a threaded v8
// instance (like in WorkerScript).
virtual QNetworkAccessManager *networkAccessManager();
+#endif
// Return the list of illegal id names (the names of the properties on the global object)
const QSet<QString> &illegalNames() const;
diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp
index e2063dee7d..ed9a8533c0 100644
--- a/src/qml/types/qqmlbind.cpp
+++ b/src/qml/types/qqmlbind.cpp
@@ -75,7 +75,7 @@ public:
void QQmlBindPrivate::validate(QObject *binding) const
{
- if (!obj)
+ if (!obj || (when.isValid() && !when))
return;
if (!prop.isValid()) {
@@ -185,6 +185,8 @@ void QQmlBind::setWhen(bool v)
return;
d->when = v;
+ if (v && d->componentComplete)
+ d->validate(this);
eval();
}
diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp
index e819e4ee7d..bc15b2fd9b 100644
--- a/src/qml/types/qquickworkerscript.cpp
+++ b/src/qml/types/qquickworkerscript.cpp
@@ -52,10 +52,12 @@
#include <QtCore/qwaitcondition.h>
#include <QtCore/qfile.h>
#include <QtCore/qdatetime.h>
-#include <QtNetwork/qnetworkaccessmanager.h>
#include <QtQml/qqmlinfo.h>
#include <QtQml/qqmlfile.h>
+#ifndef QT_NO_NETWORK
+#include <QtNetwork/qnetworkaccessmanager.h>
#include "qqmlnetworkaccessmanagerfactory.h"
+#endif
#include <private/qv8engine_p.h>
#include <private/qv4serialize_p.h>
@@ -141,7 +143,10 @@ public:
~WorkerEngine();
void init();
+
+#ifndef QT_NO_NETWORK
virtual QNetworkAccessManager *networkAccessManager();
+#endif
QQuickWorkerScriptEnginePrivate *p;
@@ -150,7 +155,9 @@ public:
QV4::PersistentValue onmessage;
private:
QV4::PersistentValue createsend;
+#ifndef QT_NO_NETWORK
QNetworkAccessManager *accessManager;
+#endif
};
WorkerEngine *workerEngine;
@@ -194,14 +201,19 @@ private:
};
QQuickWorkerScriptEnginePrivate::WorkerEngine::WorkerEngine(QQuickWorkerScriptEnginePrivate *parent)
-: QV8Engine(0), p(parent), accessManager(0)
+: QV8Engine(0), p(parent)
+#ifndef QT_NO_NETWORK
+, accessManager(0)
+#endif
{
m_v4Engine->v8Engine = this;
}
QQuickWorkerScriptEnginePrivate::WorkerEngine::~WorkerEngine()
{
+#ifndef QT_NO_NETWORK
delete accessManager;
+#endif
}
void QQuickWorkerScriptEnginePrivate::WorkerEngine::init()
@@ -262,6 +274,7 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::WorkerEngine::sendFunction(i
return v->asReturnedValue();
}
+#ifndef QT_NO_NETWORK
QNetworkAccessManager *QQuickWorkerScriptEnginePrivate::WorkerEngine::networkAccessManager()
{
if (!accessManager) {
@@ -273,6 +286,7 @@ QNetworkAccessManager *QQuickWorkerScriptEnginePrivate::WorkerEngine::networkAcc
}
return accessManager;
}
+#endif
QQuickWorkerScriptEnginePrivate::QQuickWorkerScriptEnginePrivate(QQmlEngine *engine)
: workerEngine(0), qmlengine(engine), m_nextId(0)
diff --git a/src/qmldevtools/qmldevtools.pro b/src/qmldevtools/qmldevtools.pro
index 0e32dc51e2..acd5c9729b 100644
--- a/src/qmldevtools/qmldevtools.pro
+++ b/src/qmldevtools/qmldevtools.pro
@@ -13,10 +13,10 @@ intel_icc: WERROR += -ww2415
clang:if(greaterThan(QT_CLANG_MAJOR_VERSION, 3)|greaterThan(QT_CLANG_MINOR_VERSION, 3)): \
WERROR += -Wno-error=unused-const-variable
-load(qt_module)
-
include(../3rdparty/masm/masm-defs.pri)
include(../qml/parser/parser.pri)
include(../qml/jsruntime/jsruntime.pri)
include(../qml/compiler/compiler.pri)
include(../qml/memory/memory.pri)
+
+load(qt_module)
diff --git a/src/qmltest/qmltest.pro b/src/qmltest/qmltest.pro
index 289a0584e0..42224e9751 100644
--- a/src/qmltest/qmltest.pro
+++ b/src/qmltest/qmltest.pro
@@ -13,8 +13,6 @@ qtHaveModule(widgets) {
DEFINES += QT_QMLTEST_WITH_WIDGETS
}
-load(qt_module)
-
# Install qmltestcase.prf into the Qt mkspecs so that "CONFIG += qmltestcase"
# can be used in customer applications to build against QtQuickTest.
feature.path = $$[QT_INSTALL_DATA]/mkspecs/features
@@ -33,3 +31,5 @@ HEADERS += \
$$PWD/qtestoptions_p.h
DEFINES += QT_QML_DEBUG_NO_WARNING
+
+load(qt_module)
diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp
index adee4330d3..9ba93a1241 100644
--- a/src/qmltest/quicktest.cpp
+++ b/src/qmltest/quicktest.cpp
@@ -296,7 +296,7 @@ int quick_test_main(int argc, char **argv, const char *name, const char *sourceD
const QFileInfo testPathInfo(testPath);
if (testPathInfo.isFile()) {
- if (!testPath.endsWith(QStringLiteral(".qml"))) {
+ if (!testPath.endsWith(QLatin1String(".qml"))) {
qWarning("'%s' does not have the suffix '.qml'.", qPrintable(testPath));
return 1;
}
diff --git a/src/quick/designer/qquickdesignersupportitems.cpp b/src/quick/designer/qquickdesignersupportitems.cpp
index 278e62d4f6..544ca04754 100644
--- a/src/quick/designer/qquickdesignersupportitems.cpp
+++ b/src/quick/designer/qquickdesignersupportitems.cpp
@@ -175,19 +175,19 @@ static QQmlType *getQmlType(const QString &typeName, int majorNumber, int minorN
static bool isCrashingType(QQmlType *type)
{
if (type) {
- if (type->qmlTypeName() == QStringLiteral("QtMultimedia/MediaPlayer"))
+ if (type->qmlTypeName() == QLatin1String("QtMultimedia/MediaPlayer"))
return true;
- if (type->qmlTypeName() == QStringLiteral("QtMultimedia/Audio"))
+ if (type->qmlTypeName() == QLatin1String("QtMultimedia/Audio"))
return true;
- if (type->qmlTypeName() == QStringLiteral("QtQuick.Controls/MenuItem"))
+ if (type->qmlTypeName() == QLatin1String("QtQuick.Controls/MenuItem"))
return true;
- if (type->qmlTypeName() == QStringLiteral("QtQuick.Controls/Menu"))
+ if (type->qmlTypeName() == QLatin1String("QtQuick.Controls/Menu"))
return true;
- if (type->qmlTypeName() == QStringLiteral("QtQuick/Timer"))
+ if (type->qmlTypeName() == QLatin1String("QtQuick/Timer"))
return true;
}
diff --git a/src/quick/doc/images/columnlayout.png b/src/quick/doc/images/columnlayout.png
new file mode 100644
index 0000000000..f03eb7b996
--- /dev/null
+++ b/src/quick/doc/images/columnlayout.png
Binary files differ
diff --git a/src/quick/doc/images/gridlayout.png b/src/quick/doc/images/gridlayout.png
new file mode 100644
index 0000000000..493813c481
--- /dev/null
+++ b/src/quick/doc/images/gridlayout.png
Binary files differ
diff --git a/src/quick/doc/images/qtquicklayouts-example-layouts.png b/src/quick/doc/images/qtquicklayouts-example-layouts.png
new file mode 100644
index 0000000000..94619bae3f
--- /dev/null
+++ b/src/quick/doc/images/qtquicklayouts-example-layouts.png
Binary files differ
diff --git a/src/quick/doc/images/rowlayout-minimum.png b/src/quick/doc/images/rowlayout-minimum.png
new file mode 100644
index 0000000000..5875325c54
--- /dev/null
+++ b/src/quick/doc/images/rowlayout-minimum.png
Binary files differ
diff --git a/src/quick/doc/images/rowlayout.png b/src/quick/doc/images/rowlayout.png
new file mode 100644
index 0000000000..519a62fddd
--- /dev/null
+++ b/src/quick/doc/images/rowlayout.png
Binary files differ
diff --git a/src/quick/doc/qtquick.qdocconf b/src/quick/doc/qtquick.qdocconf
index 044c1696ff..4f141a733a 100644
--- a/src/quick/doc/qtquick.qdocconf
+++ b/src/quick/doc/qtquick.qdocconf
@@ -33,7 +33,7 @@ qhp.QtQuick.subprojects.examples.selectors = fake:example
tagfile = ../../../doc/qtquick/qtquick.tags
-depends += qtcore qtxmlpatterns qtqml qtgui qtlinguist qtquickcontrols qtquicklayouts qtdoc qtquickdialogs qtsensors qtwidgets qmake qtmultimedia qtgraphicaleffects
+depends += qtcore qtxmlpatterns qtqml qtgui qtlinguist qtquickcontrols qtdoc qtquickdialogs qtsensors qtwidgets qmake qtmultimedia qtgraphicaleffects
headerdirs += ..\
../../quickwidgets
diff --git a/src/quick/doc/snippets/qml/windowconstraints.qml b/src/quick/doc/snippets/qml/windowconstraints.qml
new file mode 100644
index 0000000000..3f3534f494
--- /dev/null
+++ b/src/quick/doc/snippets/qml/windowconstraints.qml
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtQuick.Layouts 1.2
+import QtQuick.Window 2.2
+
+Window {
+ //! [binddefaultsize]
+ width: layout.implicitWidth
+ height: layout.implicitHeight
+ //! [binddefaultsize]
+ //! [bindconstraints]
+ minimumWidth: layout.Layout.minimumWidth
+ minimumHeight: layout.Layout.minimumHeight
+ maximumWidth: 1000
+ maximumHeight: layout.Layout.maximumHeight
+ //! [bindconstraints]
+
+ //! [rowlayout]
+ //! [anchoring]
+ RowLayout {
+ id: layout
+ anchors.fill: parent
+ //! [anchoring]
+ spacing: 6
+ Rectangle {
+ color: 'azure'
+ Layout.fillWidth: true
+ Layout.minimumWidth: 50
+ Layout.preferredWidth: 100
+ Layout.maximumWidth: 300
+ Layout.minimumHeight: 150
+ Text {
+ anchors.centerIn: parent
+ text: parent.width + 'x' + parent.height
+ }
+ }
+ Rectangle {
+ color: 'plum'
+ Layout.fillWidth: true
+ Layout.minimumWidth: 100
+ Layout.preferredWidth: 200
+ Layout.preferredHeight: 100
+ Text {
+ anchors.centerIn: parent
+ text: parent.width + 'x' + parent.height
+ }
+ }
+ }
+ //! [rowlayout]
+}
diff --git a/src/quick/doc/src/concepts/layouts/qtquicklayouts-index.qdoc b/src/quick/doc/src/concepts/layouts/qtquicklayouts-index.qdoc
new file mode 100644
index 0000000000..0be66fad2c
--- /dev/null
+++ b/src/quick/doc/src/concepts/layouts/qtquicklayouts-index.qdoc
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page qtquicklayouts-index.html
+ \title Qt Quick Layouts
+ \brief A module with a set of QML elements that arrange QML items in a user interface.
+
+ Qt Quick Layouts are a set of QML types used to arrange items in a user interface. In contrast
+ to \l{Item Positioners}{positioners}, Qt Quick Layouts can also resize their items. This makes
+ them well suited for resizable user interfaces. Since layouts are items they can consequently
+ be nested.
+
+ The module is new in Qt 5.1 and requires \l{Qt Quick} 2.1.
+
+ Visit the \l{Qt Quick Layouts Overview} page to get started.
+
+ \section1 Layouts
+
+ \annotatedlist layouts
+
+ \section1 Related information
+
+ \list
+ \li \l{Qt Quick}
+ \li \l{Qt Quick Layouts Overview}
+ \li \l{Qt Quick Layouts - Basic Example}
+ \li \l{Qt Quick Layouts QML Types}{Qt Quick Layouts QML Types}
+ \endlist
+*/
diff --git a/src/quick/doc/src/concepts/layouts/qtquicklayouts-overview.qdoc b/src/quick/doc/src/concepts/layouts/qtquicklayouts-overview.qdoc
new file mode 100644
index 0000000000..1b6e7dc539
--- /dev/null
+++ b/src/quick/doc/src/concepts/layouts/qtquicklayouts-overview.qdoc
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page qtquicklayouts-overview.html
+ \title Qt Quick Layouts Overview
+ \brief A set of APIs for arranging QML items in a user interface.
+
+ Qt Quick Layouts are items that are used to arrange items in a user interface. Since Qt Quick
+ Layouts also resize their items, they are well suited for resizable user interfaces.
+
+ \section1 Getting started
+
+ The QML types can be imported into your application using the following import statement in your \c {.qml} file.
+
+ \code
+ import QtQuick.Layouts 1.2
+ \endcode
+
+ \section1 Key Features
+
+
+ Some of the key features are:
+
+ \list
+ \li \l{Layout::alignment}{Alignment} of items can be specified with the
+ \l{Layout::alignment}{Layout.alignment} property
+ \li \l{Layout::fillWidth}{Resizable items} can be specified with the
+ \l{Layout::fillWidth}{Layout.fillWidth} and \l{Layout::fillHeight}{Layout.fillHeight}
+ properties.
+ \li \l{Size constraints} can be specified with
+ \l{Layout::minimumWidth}{Layout.minimumWidth},
+ \l{Layout::preferredWidth}{Layout.preferredWidth}, and
+ \l{Layout::maximumWidth}{Layout.maximumWidth} properties ("Width" can be replaced
+ with "Height" for specifying similar constraints to the height).
+ \li \l{RowLayout::spacing}{Spacings} can be specified with \l{RowLayout::spacing}{spacing},
+ \l{GridLayout::rowSpacing}{rowSpacing} or \l{GridLayout::columnSpacing}{columnSpacing}
+ \endlist
+
+ In addition to the above features, GridLayout adds these features:
+ \list
+ \li \l{Layout::row}{Grid coordinates} can be specified with the \l{Layout::row}{Layout.row} and
+ \l{Layout::column}{Layout.column}.
+ \li \l{GridLayout::flow}{Automatic grid coordinates} used together with the
+ \l{GridLayout::flow}{flow}, \l{GridLayout::rows}{rows}, and
+ \l{GridLayout::columns}{columns} properties.
+ \li \l{Layout::columnSpan}{Spans} across rows or columns can be specified with the
+ \l{Layout::rowSpan}{Layout.rowSpan} and \l{Layout::columnSpan}{Layout.columnSpan}
+ properties.
+ \endlist
+
+
+
+ \section1 Size Constraints
+ Since an item can be resized by its layout, the layout needs to know the
+ \l{Layout::minimumWidth}{minimum}, \l{Layout::preferredWidth}{preferred},
+ and \l{Layout::maximumWidth}{maximum} sizes of all items where \l{Layout::fillWidth}{Layout.fillWidth} or
+ \l{Layout::fillHeight}{Layout.fillHeight} is set to \c true.
+ For instance, the following will produce a layout with two rectangles lying side-by-side that
+ stretches horizontally. The azure rectangle can be resized from 50x150 to 300x150, and the plum
+ rectangle can be resized from 100x100 to ∞x100.
+
+ \snippet windowconstraints.qml rowlayout
+
+ \image rowlayout-minimum.png "RowLayout at its minimum"
+
+ Combining each item's constraints will give these implicit constraints to the layout element:
+
+ \table
+ \header
+ \li
+ \li minimum
+ \li preferred
+ \li maximum
+ \row
+ \li implicit constraints (width)
+ \li 156
+ \li 306
+ \li ∞ (\c Number.POSITIVE_INFINITY)
+ \row
+ \li implicit constraints (heights)
+ \li 150
+ \li 150
+ \li 150
+ \endtable
+
+ Thus, the layout cannot be narrower than 156 or be taller or shorter than 150 without breaking
+ any of the constraints of its child items.
+
+ \section2 Specifying Preferred Size
+ For each item, the effective preferred size may come from one of several candidate properties.
+ For determining the effective preferred size, it will query these candidate properties in the
+ following order, and use the first candidate with a valid width or height.
+
+ \table
+ \header
+ \li Candidate properties
+ \li Description
+ \row
+ \li \l{Layout::preferredWidth}{Layout.preferredWidth} or
+ \l{Layout::preferredHeight}{Layout.preferredHeight}
+ \li These properties are supposed to be modified by the application if the default implicit
+ size does not give the optimal arrangement.
+ \row
+ \li \l{Item::implicitWidth}{implicitWidth} or \l{Item::implicitHeight}{implicitHeight}
+ \li These properties are supposed to be supplied by each item to give a meaningful ideal size,
+ for example the size needed to display all the contents of a \l Text type.
+ An implicit width or height of \c 0 is interpreted as invalid.
+ \row
+ \li \l{Item::width}{width} and \l{Item::height}{height}
+ \li If none of the above properties are valid, the layout will resort to the
+ \l{Item::width}{width} and \l{Item::height}{height} properties.
+ \endtable
+
+ An item can specify \l{Layout::preferredWidth}{Layout.preferredWidth} without having to specify
+ \l{Layout::preferredHeight}{Layout.preferredHeight}. In this case, the effective preferred
+ height will be determined from the \l{Item::implicitHeight}{implicitHeight} (or ultimately
+ \l{Item::height}{height}).
+
+ \note Resorting to \l{Item::width}{width} or \l{Item::height}{height} properties is only
+ provided as a final fallback. If you want to override the preferred size, it is recommended to
+ use \l{Layout::preferredWidth}{Layout.preferredWidth} or
+ \l{Layout::preferredHeight}{Layout.preferredHeight}. Relying on the \l{Item::width}{width} or
+ \l{Item::height}{height} properties for specifying the preferred size might give some
+ unexpected behavior. For instance, changing the \l{Item::width}{width} or
+ \l{Item::height}{height} properties won't trigger a layout rearrangement. Also, when the layout
+ is forced to do a full rebuild it might use the actual width and height, and not the width and
+ height specified in the QML file.
+
+
+ \section1 Connecting windows and layouts
+ You can just use normal anchoring concepts to ensure that the layout will follow the window
+ resizing.
+
+ \snippet qml/windowconstraints.qml anchoring
+
+ The size constraints of layouts can be used to ensure that the window cannot be resized beyond
+ the layout constraints. You can take the size constraints from the layout and set these
+ constraints on the minimumWidth, minimumHeight, maximumWidth, and maximumHeight of the Window
+ element. The following code ensures that the window cannot be resized beyond the constraints of
+ the layout:
+
+ \snippet qml/windowconstraints.qml bindconstraints
+
+ \note Since layout.Layout.maximumWidth is infinite in this case, we cannot bind that to the
+ maximumWidth property of Window, since that is an integer number. We therefore set a fixed
+ maximum width to 1000.
+
+ Finally, you usually want the initial size of the window to be the layout's implicit size:
+
+ \snippet qml/windowconstraints.qml binddefaultsize
+*/
diff --git a/src/quick/doc/src/concepts/layouts/qtquicklayouts.qdoc b/src/quick/doc/src/concepts/layouts/qtquicklayouts.qdoc
new file mode 100644
index 0000000000..8f390c83db
--- /dev/null
+++ b/src/quick/doc/src/concepts/layouts/qtquicklayouts.qdoc
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \qmlmodule QtQuick.Layouts 1.3
+ \title Qt Quick Layouts QML Types
+ \ingroup qmlmodules
+ \brief Provides QML types for arranging QML items in a user interface.
+
+ The \l{Qt Quick Layouts} module provides QML types for arranging
+ QML items in a user interface.
+ These QML types work in conjunction with \l{Qt Quick} and
+ \l{Qt Quick Controls}.
+
+ The QML types can be imported into your application using the
+ following import statement in your .qml file.
+
+ \code
+ import QtQuick.Layouts 1.3
+ \endcode
+
+*/
diff --git a/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc b/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc
index dffcabbd5b..cb281a2d4a 100644
--- a/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc
+++ b/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc
@@ -102,7 +102,7 @@ has changed. If the QList changes, it is necessary to reset
the model by calling QQmlContext::setContextProperty() again.
-\section2 QAbstractItemModel
+\section2 QAbstractItemModel subclass
A model can be defined by subclassing QAbstractItemModel. This is the
best approach if you have a more complex model that cannot be supported
diff --git a/src/quick/doc/src/qtquick.qdoc b/src/quick/doc/src/qtquick.qdoc
index 98a77a48d8..4bdd02241d 100644
--- a/src/quick/doc/src/qtquick.qdoc
+++ b/src/quick/doc/src/qtquick.qdoc
@@ -101,6 +101,7 @@ Additional Qt Quick information:
containing a JavaScript interface for an SQLite database
\li \l{Qt Quick Particles QML Types}{Particles} - provides a particle
system for Qt Quick
+ \li \l{Qt Quick Layouts}{Layouts} - provides layouts for arranging Qt Quick items
\li \l{Qt Quick Window QML Types}{Window} - contains types for creating
top-level windows and accessing screen information
\li \l{Qt Quick Dialogs}{Dialogs} - contains types for creating and
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index 2d991bb670..bacdfad557 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -223,13 +223,13 @@ static bool qSetFontSizeFromToken(QFont &font, const QString &fontSizeToken)
const QString value = trimmedToken.left(trimmedToken.size() - 2);
bool ok = false;
int size = 0;
- if (unitStr == QStringLiteral("px")) {
+ if (unitStr == QLatin1String("px")) {
size = qParseFontSizeFromToken(value, ok);
if (ok) {
font.setPixelSize(size);
return true;
}
- } else if (unitStr == QStringLiteral("pt")) {
+ } else if (unitStr == QLatin1String("pt")) {
size = qParseFontSizeFromToken(value, ok);
if (ok) {
font.setPointSize(size);
@@ -368,9 +368,9 @@ static QFont qt_font_from_string(const QString& fontString, const QFont &current
// We know that font-size must be specified and it must be before font-family
// (which could potentially have "px" or "pt" in its name), so extract it now.
- int fontSizeEnd = fontString.indexOf(QStringLiteral("px"));
+ int fontSizeEnd = fontString.indexOf(QLatin1String("px"));
if (fontSizeEnd == -1)
- fontSizeEnd = fontString.indexOf(QStringLiteral("pt"));
+ fontSizeEnd = fontString.indexOf(QLatin1String("pt"));
if (fontSizeEnd == -1) {
qWarning().nospace() << "Context2D: Invalid font size unit in font string.";
return currentFont;
@@ -769,53 +769,53 @@ void qt_image_boxblur(QImage& image, int radius, bool quality)
static QPainter::CompositionMode qt_composite_mode_from_string(const QString &compositeOperator)
{
- if (compositeOperator == QStringLiteral("source-over")) {
+ if (compositeOperator == QLatin1String("source-over")) {
return QPainter::CompositionMode_SourceOver;
- } else if (compositeOperator == QStringLiteral("source-out")) {
+ } else if (compositeOperator == QLatin1String("source-out")) {
return QPainter::CompositionMode_SourceOut;
- } else if (compositeOperator == QStringLiteral("source-in")) {
+ } else if (compositeOperator == QLatin1String("source-in")) {
return QPainter::CompositionMode_SourceIn;
- } else if (compositeOperator == QStringLiteral("source-atop")) {
+ } else if (compositeOperator == QLatin1String("source-atop")) {
return QPainter::CompositionMode_SourceAtop;
- } else if (compositeOperator == QStringLiteral("destination-atop")) {
+ } else if (compositeOperator == QLatin1String("destination-atop")) {
return QPainter::CompositionMode_DestinationAtop;
- } else if (compositeOperator == QStringLiteral("destination-in")) {
+ } else if (compositeOperator == QLatin1String("destination-in")) {
return QPainter::CompositionMode_DestinationIn;
- } else if (compositeOperator == QStringLiteral("destination-out")) {
+ } else if (compositeOperator == QLatin1String("destination-out")) {
return QPainter::CompositionMode_DestinationOut;
- } else if (compositeOperator == QStringLiteral("destination-over")) {
+ } else if (compositeOperator == QLatin1String("destination-over")) {
return QPainter::CompositionMode_DestinationOver;
- } else if (compositeOperator == QStringLiteral("lighter")) {
+ } else if (compositeOperator == QLatin1String("lighter")) {
return QPainter::CompositionMode_Lighten;
- } else if (compositeOperator == QStringLiteral("copy")) {
+ } else if (compositeOperator == QLatin1String("copy")) {
return QPainter::CompositionMode_Source;
- } else if (compositeOperator == QStringLiteral("xor")) {
+ } else if (compositeOperator == QLatin1String("xor")) {
return QPainter::CompositionMode_Xor;
- } else if (compositeOperator == QStringLiteral("qt-clear")) {
+ } else if (compositeOperator == QLatin1String("qt-clear")) {
return QPainter::CompositionMode_Clear;
- } else if (compositeOperator == QStringLiteral("qt-destination")) {
+ } else if (compositeOperator == QLatin1String("qt-destination")) {
return QPainter::CompositionMode_Destination;
- } else if (compositeOperator == QStringLiteral("qt-multiply")) {
+ } else if (compositeOperator == QLatin1String("qt-multiply")) {
return QPainter::CompositionMode_Multiply;
- } else if (compositeOperator == QStringLiteral("qt-screen")) {
+ } else if (compositeOperator == QLatin1String("qt-screen")) {
return QPainter::CompositionMode_Screen;
- } else if (compositeOperator == QStringLiteral("qt-overlay")) {
+ } else if (compositeOperator == QLatin1String("qt-overlay")) {
return QPainter::CompositionMode_Overlay;
- } else if (compositeOperator == QStringLiteral("qt-darken")) {
+ } else if (compositeOperator == QLatin1String("qt-darken")) {
return QPainter::CompositionMode_Darken;
- } else if (compositeOperator == QStringLiteral("qt-lighten")) {
+ } else if (compositeOperator == QLatin1String("qt-lighten")) {
return QPainter::CompositionMode_Lighten;
- } else if (compositeOperator == QStringLiteral("qt-color-dodge")) {
+ } else if (compositeOperator == QLatin1String("qt-color-dodge")) {
return QPainter::CompositionMode_ColorDodge;
- } else if (compositeOperator == QStringLiteral("qt-color-burn")) {
+ } else if (compositeOperator == QLatin1String("qt-color-burn")) {
return QPainter::CompositionMode_ColorBurn;
- } else if (compositeOperator == QStringLiteral("qt-hard-light")) {
+ } else if (compositeOperator == QLatin1String("qt-hard-light")) {
return QPainter::CompositionMode_HardLight;
- } else if (compositeOperator == QStringLiteral("qt-soft-light")) {
+ } else if (compositeOperator == QLatin1String("qt-soft-light")) {
return QPainter::CompositionMode_SoftLight;
- } else if (compositeOperator == QStringLiteral("qt-difference")) {
+ } else if (compositeOperator == QLatin1String("qt-difference")) {
return QPainter::CompositionMode_Difference;
- } else if (compositeOperator == QStringLiteral("qt-exclusion")) {
+ } else if (compositeOperator == QLatin1String("qt-exclusion")) {
return QPainter::CompositionMode_Exclusion;
}
return QPainter::CompositionMode_SourceOver;
@@ -1314,7 +1314,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_globalCompositeOperation(QV4::C
QString mode = ctx->args()[0].toQString();
QPainter::CompositionMode cm = qt_composite_mode_from_string(mode);
- if (cm == QPainter::CompositionMode_SourceOver && mode != QStringLiteral("source-over"))
+ if (cm == QPainter::CompositionMode_SourceOver && mode != QLatin1String("source-over"))
return QV4::Encode::undefined();
if (cm != r->d()->context->state.globalCompositeOperation) {
@@ -1431,10 +1431,10 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_fillRule(QV4::CallContext *ctx)
QV4::ScopedValue value(scope, ctx->argument(0));
- if ((value->isString() && value->toQString() == QStringLiteral("WindingFill"))
+ if ((value->isString() && value->toQString() == QLatin1String("WindingFill"))
|| (value->isInt32() && value->integerValue() == Qt::WindingFill)) {
r->d()->context->state.fillRule = Qt::WindingFill;
- } else if ((value->isString() && value->toQStringNoThrow() == QStringLiteral("OddEvenFill"))
+ } else if ((value->isString() && value->toQStringNoThrow() == QLatin1String("OddEvenFill"))
|| (value->isInt32() && value->integerValue() == Qt::OddEvenFill)) {
r->d()->context->state.fillRule = Qt::OddEvenFill;
} else {
@@ -1730,16 +1730,16 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createPattern(QV4::CallCon
pattern->d()->brush.setTextureImage(patternTexture);
QString repetition = ctx->args()[1].toQStringNoThrow();
- if (repetition == QStringLiteral("repeat") || repetition.isEmpty()) {
+ if (repetition == QLatin1String("repeat") || repetition.isEmpty()) {
pattern->d()->patternRepeatX = true;
pattern->d()->patternRepeatY = true;
- } else if (repetition == QStringLiteral("repeat-x")) {
+ } else if (repetition == QLatin1String("repeat-x")) {
pattern->d()->patternRepeatX = true;
pattern->d()->patternRepeatY = false;
- } else if (repetition == QStringLiteral("repeat-y")) {
+ } else if (repetition == QLatin1String("repeat-y")) {
pattern->d()->patternRepeatX = false;
pattern->d()->patternRepeatY = true;
- } else if (repetition == QStringLiteral("no-repeat")) {
+ } else if (repetition == QLatin1String("no-repeat")) {
pattern->d()->patternRepeatX = false;
pattern->d()->patternRepeatY = false;
} else {
@@ -1793,11 +1793,11 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_lineCap(QV4::CallContext *ctx)
QString lineCap = ctx->args()[0].toQString();
Qt::PenCapStyle cap;
- if (lineCap == QStringLiteral("round"))
+ if (lineCap == QLatin1String("round"))
cap = Qt::RoundCap;
- else if (lineCap == QStringLiteral("butt"))
+ else if (lineCap == QLatin1String("butt"))
cap = Qt::FlatCap;
- else if (lineCap == QStringLiteral("square"))
+ else if (lineCap == QLatin1String("square"))
cap = Qt::SquareCap;
else
return QV4::Encode::undefined();
@@ -1852,11 +1852,11 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_lineJoin(QV4::CallContext *ctx)
QString lineJoin = ctx->args()[0].toQString();
Qt::PenJoinStyle join;
- if (lineJoin == QStringLiteral("round"))
+ if (lineJoin == QLatin1String("round"))
join = Qt::RoundJoin;
- else if (lineJoin == QStringLiteral("bevel"))
+ else if (lineJoin == QLatin1String("bevel"))
join = Qt::BevelJoin;
- else if (lineJoin == QStringLiteral("miter"))
+ else if (lineJoin == QLatin1String("miter"))
join = Qt::SvgMiterJoin;
else
return QV4::Encode::undefined();
@@ -2733,15 +2733,15 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_textBaseline(QV4::CallContext *
QString textBaseline = s->toQString();
QQuickContext2D::TextBaseLineType tb;
- if (textBaseline == QStringLiteral("alphabetic"))
+ if (textBaseline == QLatin1String("alphabetic"))
tb = QQuickContext2D::Alphabetic;
- else if (textBaseline == QStringLiteral("hanging"))
+ else if (textBaseline == QLatin1String("hanging"))
tb = QQuickContext2D::Hanging;
- else if (textBaseline == QStringLiteral("top"))
+ else if (textBaseline == QLatin1String("top"))
tb = QQuickContext2D::Top;
- else if (textBaseline == QStringLiteral("bottom"))
+ else if (textBaseline == QLatin1String("bottom"))
tb = QQuickContext2D::Bottom;
- else if (textBaseline == QStringLiteral("middle"))
+ else if (textBaseline == QLatin1String("middle"))
tb = QQuickContext2D::Middle;
else
return QV4::Encode::undefined();
diff --git a/src/quick/items/context2d/qquickcontext2dtexture.cpp b/src/quick/items/context2d/qquickcontext2dtexture.cpp
index 12bd95101f..f3513f447a 100644
--- a/src/quick/items/context2d/qquickcontext2dtexture.cpp
+++ b/src/quick/items/context2d/qquickcontext2dtexture.cpp
@@ -605,6 +605,11 @@ QPaintDevice* QQuickContext2DFBOTexture::beginPainting()
void QQuickContext2DFBOTexture::endPainting()
{
QQuickContext2DTexture::endPainting();
+
+ // There may not be an FBO due to zero width or height.
+ if (!m_fbo)
+ return;
+
if (m_multisampledFbo)
QOpenGLFramebufferObject::blitFramebuffer(m_fbo, m_multisampledFbo);
diff --git a/src/quick/items/qquickanimatedimage.cpp b/src/quick/items/qquickanimatedimage.cpp
index 3ae2512c98..42033b6135 100644
--- a/src/quick/items/qquickanimatedimage.cpp
+++ b/src/quick/items/qquickanimatedimage.cpp
@@ -47,8 +47,10 @@
#include <QtQml/qqmlfile.h>
#include <QtQml/qqmlengine.h>
#include <QtGui/qmovie.h>
+#ifndef QT_NO_NETWORK
#include <QtNetwork/qnetworkrequest.h>
#include <QtNetwork/qnetworkreply.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -144,8 +146,10 @@ QQuickAnimatedImage::QQuickAnimatedImage(QQuickItem *parent)
QQuickAnimatedImage::~QQuickAnimatedImage()
{
Q_D(QQuickAnimatedImage);
+#ifndef QT_NO_NETWORK
if (d->reply)
d->reply->deleteLater();
+#endif
delete d->_movie;
qDeleteAll(d->frameMap);
d->frameMap.clear();
@@ -264,10 +268,12 @@ void QQuickAnimatedImage::setSource(const QUrl &url)
if (url == d->url)
return;
+#ifndef QT_NO_NETWORK
if (d->reply) {
d->reply->deleteLater();
d->reply = 0;
}
+#endif
d->setImage(QImage());
qDeleteAll(d->frameMap);
@@ -318,6 +324,7 @@ void QQuickAnimatedImage::load()
d->_movie = new QMovie(lf);
movieRequestFinished();
} else {
+#ifndef QT_NO_NETWORK
if (d->status != Loading) {
d->status = Loading;
emit statusChanged(d->status);
@@ -334,6 +341,7 @@ void QQuickAnimatedImage::load()
this, SLOT(movieRequestFinished()));
QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)),
this, SLOT(requestProgress(qint64,qint64)));
+#endif
}
}
}
@@ -342,8 +350,10 @@ void QQuickAnimatedImage::load()
void QQuickAnimatedImage::movieRequestFinished()
{
+
Q_D(QQuickAnimatedImage);
+#ifndef QT_NO_NETWORK
if (d->reply) {
d->redirectCount++;
if (d->redirectCount < ANIMATEDIMAGE_MAXIMUM_REDIRECT_RECURSION) {
@@ -359,6 +369,7 @@ void QQuickAnimatedImage::movieRequestFinished()
d->redirectCount=0;
d->_movie = new QMovie(d->reply);
}
+#endif
if (!d->_movie->isValid()) {
qmlInfo(this) << "Error Reading Animated Image File " << d->url.toString();
diff --git a/src/quick/items/qquickanimatedimage_p_p.h b/src/quick/items/qquickanimatedimage_p_p.h
index 9474254252..9b284f966d 100644
--- a/src/quick/items/qquickanimatedimage_p_p.h
+++ b/src/quick/items/qquickanimatedimage_p_p.h
@@ -58,7 +58,9 @@
QT_BEGIN_NAMESPACE
class QMovie;
+#ifndef QT_NO_NETWORK
class QNetworkReply;
+#endif
class QQuickAnimatedImagePrivate : public QQuickImagePrivate
{
@@ -66,7 +68,10 @@ class QQuickAnimatedImagePrivate : public QQuickImagePrivate
public:
QQuickAnimatedImagePrivate()
- : playing(true), paused(false), preset_currentframe(0), _movie(0), reply(0), redirectCount(0), oldPlaying(false)
+ : playing(true), paused(false), preset_currentframe(0), _movie(0), oldPlaying(false)
+#ifndef QT_NO_NETWORK
+ , reply(0), redirectCount(0)
+#endif
{
}
@@ -76,9 +81,11 @@ public:
bool paused;
int preset_currentframe;
QMovie *_movie;
+ bool oldPlaying;
+#ifndef QT_NO_NETWORK
QNetworkReply *reply;
int redirectCount;
- bool oldPlaying;
+#endif
QMap<int, QQuickPixmap *> frameMap;
};
diff --git a/src/quick/items/qquickanimatedsprite.cpp b/src/quick/items/qquickanimatedsprite.cpp
index b3c1e8fb40..f5df5763bb 100644
--- a/src/quick/items/qquickanimatedsprite.cpp
+++ b/src/quick/items/qquickanimatedsprite.cpp
@@ -544,6 +544,7 @@ QSGGeometryNode* QQuickAnimatedSprite::buildNode()
m_node->setGeometry(g);
m_node->setMaterial(m_material);
m_node->setFlag(QSGGeometryNode::OwnsMaterial);
+ m_node->setFlag(QSGGeometryNode::OwnsGeometry);
sizeVertices();
return m_node;
}
diff --git a/src/quick/items/qquickborderimage.cpp b/src/quick/items/qquickborderimage.cpp
index 66f414d816..5f8dd7b989 100644
--- a/src/quick/items/qquickborderimage.cpp
+++ b/src/quick/items/qquickborderimage.cpp
@@ -43,7 +43,9 @@
#include <QtQml/qqmlinfo.h>
#include <QtQml/qqmlfile.h>
#include <QtQml/qqmlengine.h>
+#ifndef QT_NO_NETWORK
#include <QtNetwork/qnetworkreply.h>
+#endif
#include <QtCore/qfile.h>
#include <QtCore/qmath.h>
#include <QtGui/qguiapplication.h>
@@ -169,9 +171,11 @@ QQuickBorderImage::QQuickBorderImage(QQuickItem *parent)
QQuickBorderImage::~QQuickBorderImage()
{
+#ifndef QT_NO_NETWORK
Q_D(QQuickBorderImage);
if (d->sciReply)
d->sciReply->deleteLater();
+#endif
}
/*!
@@ -270,10 +274,12 @@ void QQuickBorderImage::setSource(const QUrl &url)
if (url == d->url)
return;
+#ifndef QT_NO_NETWORK
if (d->sciReply) {
d->sciReply->deleteLater();
d->sciReply = 0;
}
+#endif
d->url = url;
d->sciurl = QUrl();
@@ -311,6 +317,7 @@ void QQuickBorderImage::load()
setGridScaledImage(QQuickGridScaledImage(&file));
return;
} else {
+#ifndef QT_NO_NETWORK
if (d->progress != 0.0) {
d->progress = 0.0;
emit progressChanged(d->progress);
@@ -320,6 +327,7 @@ void QQuickBorderImage::load()
d->sciReply = qmlEngine(this)->networkAccessManager()->get(req);
qmlobject_connect(d->sciReply, QNetworkReply, SIGNAL(finished()),
this, QQuickBorderImage, SLOT(sciRequestFinished()))
+#endif
}
} else {
QQuickPixmap::Options options;
@@ -529,6 +537,7 @@ void QQuickBorderImage::requestFinished()
pixmapChange();
}
+#ifndef QT_NO_NETWORK
#define BORDERIMAGE_MAX_REDIRECT 16
void QQuickBorderImage::sciRequestFinished()
@@ -558,6 +567,7 @@ void QQuickBorderImage::sciRequestFinished()
setGridScaledImage(sci);
}
}
+#endif // QT_NO_NETWORK
void QQuickBorderImage::doUpdate()
{
diff --git a/src/quick/items/qquickborderimage_p.h b/src/quick/items/qquickborderimage_p.h
index 7f8b172a21..f2764660f6 100644
--- a/src/quick/items/qquickborderimage_p.h
+++ b/src/quick/items/qquickborderimage_p.h
@@ -101,7 +101,9 @@ private:
private Q_SLOTS:
void doUpdate();
void requestFinished() Q_DECL_OVERRIDE;
+#ifndef QT_NO_NETWORK
void sciRequestFinished();
+#endif
private:
Q_DISABLE_COPY(QQuickBorderImage)
diff --git a/src/quick/items/qquickborderimage_p_p.h b/src/quick/items/qquickborderimage_p_p.h
index 478de88a52..1dc530e34e 100644
--- a/src/quick/items/qquickborderimage_p_p.h
+++ b/src/quick/items/qquickborderimage_p_p.h
@@ -58,17 +58,20 @@
QT_BEGIN_NAMESPACE
+#ifndef QT_NO_NETWORK
class QNetworkReply;
+#endif
class QQuickBorderImagePrivate : public QQuickImageBasePrivate
{
Q_DECLARE_PUBLIC(QQuickBorderImage)
public:
QQuickBorderImagePrivate()
- : border(0), sciReply(0),
- horizontalTileMode(QQuickBorderImage::Stretch),
- verticalTileMode(QQuickBorderImage::Stretch),
- redirectCount(0), pixmapChanged(false)
+ : border(0), horizontalTileMode(QQuickBorderImage::Stretch),
+ verticalTileMode(QQuickBorderImage::Stretch), pixmapChanged(false)
+#ifndef QT_NO_NETWORK
+ , sciReply(0), redirectCount(0)
+#endif
{
}
@@ -90,12 +93,14 @@ public:
QQuickScaleGrid *border;
QUrl sciurl;
- QNetworkReply *sciReply;
QQuickBorderImage::TileMode horizontalTileMode;
QQuickBorderImage::TileMode verticalTileMode;
- int redirectCount;
-
bool pixmapChanged : 1;
+
+#ifndef QT_NO_NETWORK
+ QNetworkReply *sciReply;
+ int redirectCount;
+#endif
};
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index 3663b379bb..b0245f402b 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -65,6 +65,8 @@ static const int FlickThreshold = 15;
// will ensure the Flickable retains the grab on consecutive flicks.
static const int RetainGrabVelocity = 100;
+static const int MovementEndingTimerInterval = 100;
+
static qreal EaseOvershoot(qreal t) {
return qAtan(t);
}
@@ -244,6 +246,8 @@ void QQuickFlickablePrivate::init()
contentItem->setParentItem(q);
qmlobject_connect(&timeline, QQuickTimeLine, SIGNAL(completed()),
q, QQuickFlickable, SLOT(timelineCompleted()))
+ qmlobject_connect(&velocityTimeline, QQuickTimeLine, SIGNAL(completed()),
+ q, QQuickFlickable, SLOT(velocityTimelineCompleted()))
q->setAcceptedMouseButtons(Qt::LeftButton);
q->setFiltersChildMouseEvents(true);
QQuickItemPrivate *viewportPrivate = QQuickItemPrivate::get(contentItem);
@@ -1202,6 +1206,8 @@ void QQuickFlickablePrivate::drag(qint64 currentTimestamp, QEvent::Type eventTyp
hData.velocity = 0;
}
+ if (momentum && !hData.flicking && !vData.flicking)
+ flickingStarted(hData.velocity != 0, vData.velocity != 0);
draggingStarting();
if ((hMoved && !prevHMoved) || (vMoved && !prevVMoved))
@@ -1390,10 +1396,17 @@ void QQuickFlickable::wheelEvent(QWheelEvent *event)
d->timer.start();
d->maybeBeginDrag(currentTimestamp, event->posF());
break;
+ case Qt::NoScrollPhase: // default phase with an ordinary wheel mouse
case Qt::ScrollUpdate:
+ if (d->scrollingPhase) {
+ d->pressed = true;
+ d->movementEndingTimer.start(MovementEndingTimerInterval, this);
+ }
break;
case Qt::ScrollEnd:
+ d->pressed = false;
d->scrollingPhase = false;
+ d->movementEndingTimer.start(MovementEndingTimerInterval, this);
d->draggingEnding();
event->accept();
returnToBounds();
@@ -1415,7 +1428,6 @@ void QQuickFlickable::wheelEvent(QWheelEvent *event)
valid = true;
}
if (valid) {
- d->vData.flicking = false;
d->flickY(d->vData.velocity);
d->flickingStarted(false, true);
if (d->vData.flicking) {
@@ -1435,7 +1447,6 @@ void QQuickFlickable::wheelEvent(QWheelEvent *event)
valid = true;
}
if (valid) {
- d->hData.flicking = false;
d->flickX(d->hData.velocity);
d->flickingStarted(true, false);
if (d->hData.flicking) {
@@ -1548,6 +1559,12 @@ void QQuickFlickable::timerEvent(QTimerEvent *event)
if (d->delayedPressEvent) {
d->replayDelayedPress();
}
+ } else if (event->timerId() == d->movementEndingTimer.timerId()) {
+ d->movementEndingTimer.stop();
+ d->pressed = false;
+ d->stealMouse = false;
+ if (!d->velocityTimeline.isActive())
+ movementEnding(true, true);
}
}
@@ -2475,6 +2492,22 @@ bool QQuickFlickable::isMovingVertically() const
return d->vData.moving;
}
+void QQuickFlickable::velocityTimelineCompleted()
+{
+ Q_D(QQuickFlickable);
+ if ( (d->hData.transitionToBounds && d->hData.transitionToBounds->isActive())
+ || (d->vData.transitionToBounds && d->vData.transitionToBounds->isActive()) ) {
+ return;
+ }
+ // With subclasses such as GridView, velocityTimeline.completed is emitted repeatedly:
+ // for example setting currentIndex results in a visual "flick" which the user
+ // didn't initiate directly. We don't want to end movement repeatedly, and in
+ // that case movementEnding will happen after the sequence of movements ends.
+ if (d->vData.flicking)
+ movementEnding();
+ d->updateBeginningEnd();
+}
+
void QQuickFlickable::timelineCompleted()
{
Q_D(QQuickFlickable);
diff --git a/src/quick/items/qquickflickable_p.h b/src/quick/items/qquickflickable_p.h
index a7995c5025..6cf78dcf63 100644
--- a/src/quick/items/qquickflickable_p.h
+++ b/src/quick/items/qquickflickable_p.h
@@ -259,6 +259,7 @@ protected Q_SLOTS:
void movementStarting();
void movementEnding();
void movementEnding(bool hMovementEnding, bool vMovementEnding);
+ void velocityTimelineCompleted();
void timelineCompleted();
protected:
diff --git a/src/quick/items/qquickflickable_p_p.h b/src/quick/items/qquickflickable_p_p.h
index 83e38af8a9..3c59b19ec2 100644
--- a/src/quick/items/qquickflickable_p_p.h
+++ b/src/quick/items/qquickflickable_p_p.h
@@ -218,6 +218,7 @@ public:
bool calcVelocity : 1;
bool pixelAligned : 1;
QElapsedTimer timer;
+ QBasicTimer movementEndingTimer;
qint64 lastPosTime;
qint64 lastPressTime;
QPointF lastPos;
diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp
index 7da9801218..da48fd869d 100644
--- a/src/quick/items/qquickgridview.cpp
+++ b/src/quick/items/qquickgridview.cpp
@@ -182,6 +182,8 @@ public:
bool addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer) Q_DECL_OVERRIDE;
bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo) Q_DECL_OVERRIDE;
+ void removeItem(FxViewItem *item);
+
FxViewItem *newViewItem(int index, QQuickItem *item) Q_DECL_OVERRIDE;
void initializeViewItem(FxViewItem *item) Q_DECL_OVERRIDE;
void repositionItemAt(FxViewItem *item, int index, qreal sizeBuffer) Q_DECL_OVERRIDE;
@@ -567,6 +569,17 @@ bool QQuickGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal
return changed;
}
+void QQuickGridViewPrivate::removeItem(FxViewItem *item)
+{
+ if (item->transitionScheduledOrRunning()) {
+ qCDebug(lcItemViewDelegateLifecycle) << "\tnot releasing animating item:" << item->index << item->item->objectName();
+ item->releaseAfterTransition = true;
+ releasePendingTransition.append(item);
+ } else {
+ releaseItem(item);
+ }
+}
+
bool QQuickGridViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal bufferTo)
{
FxGridItemSG *item = 0;
@@ -581,13 +594,7 @@ bool QQuickGridViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer
if (item->index != -1)
visibleIndex++;
visibleItems.removeFirst();
- if (item->transitionScheduledOrRunning()) {
- qCDebug(lcItemViewDelegateLifecycle) << "\tnot releasing animating item:" << item->index << item->item->objectName();
- item->releaseAfterTransition = true;
- releasePendingTransition.append(item);
- } else {
- releaseItem(item);
- }
+ removeItem(item);
changed = true;
}
while (visibleItems.count() > 1
@@ -597,13 +604,7 @@ bool QQuickGridViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer
break;
qCDebug(lcItemViewDelegateLifecycle) << "refill: remove last" << visibleIndex+visibleItems.count()-1;
visibleItems.removeLast();
- if (item->transitionScheduledOrRunning()) {
- qCDebug(lcItemViewDelegateLifecycle) << "\tnot releasing animating item:" << item->index << item->item->objectName();
- item->releaseAfterTransition = true;
- releasePendingTransition.append(item);
- } else {
- releaseItem(item);
- }
+ removeItem(item);
changed = true;
}
@@ -1524,7 +1525,7 @@ void QQuickGridView::setHighlightFollowsCurrentItem(bool autoHighlight)
existing applications. When explicitly set, it will cease to be bound to
the interactive property.
- \sa \l {Flickable::}{interactive}
+ \sa {Flickable::}{interactive}
*/
/*!
@@ -2406,11 +2407,12 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
int i = count - 1;
int from = tempPos - buffer - displayMarginBeginning;
- while (i >= 0) {
- if (rowPos > from && insertionIdx < visibleIndex) {
- // item won't be visible, just note the size for repositioning
- insertResult->countChangeBeforeVisible++;
- } else {
+ if (rowPos > from && insertionIdx < visibleIndex) {
+ // items won't be visible, just note the size for repositioning
+ insertResult->countChangeBeforeVisible += count;
+ insertResult->sizeChangesBeforeVisiblePos += ((count + columns - 1) / columns) * rowSize();
+ } else {
+ while (i >= 0) {
// item is before first visible e.g. in cache buffer
FxViewItem *item = 0;
if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i))))
@@ -2426,19 +2428,40 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
insertResult->changedFirstItem = true;
if (!change.isMove()) {
addedItems->append(item);
- item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true);
+ if (transitioner)
+ item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true);
+ else
+ item->moveTo(QPointF(colPos, rowPos), true);
}
insertResult->sizeChangesBeforeVisiblePos += rowSize();
+
+ if (--colNum < 0 ) {
+ colNum = columns - 1;
+ rowPos -= rowSize();
+ }
+ colPos = colNum * colSize();
+ index++;
+ i--;
}
+ }
- if (--colNum < 0 ) {
- colNum = columns - 1;
- rowPos -= rowSize();
+ // There may be gaps in the index sequence of visibleItems because
+ // of the index shift/update done before the insertion just above.
+ // Find if there is any...
+ int firstOkIdx = -1;
+ for (int i = 0; i <= insertionIdx && i < visibleItems.count() - 1; i++) {
+ if (visibleItems.at(i)->index + 1 != visibleItems.at(i + 1)->index) {
+ firstOkIdx = i + 1;
+ break;
}
- colPos = colNum * colSize();
- index++;
- i--;
}
+ // ... and remove all the items before that one
+ for (int i = 0; i < firstOkIdx; i++) {
+ FxViewItem *nvItem = visibleItems.takeFirst();
+ addedItems->removeOne(nvItem);
+ removeItem(nvItem);
+ }
+
} else {
int i = 0;
int to = buffer+displayMarginEnd+tempPos+size()-1;
@@ -2463,7 +2486,10 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
movingIntoView->append(MovedItem(item, change.moveKey(item->index)));
} else {
addedItems->append(item);
- item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true);
+ if (transitioner)
+ item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true);
+ else
+ item->moveTo(QPointF(colPos, rowPos), true);
}
insertResult->sizeChangesAfterVisiblePos += rowSize();
diff --git a/src/quick/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp
index 866a83c42a..8117baa2fe 100644
--- a/src/quick/items/qquickimagebase.cpp
+++ b/src/quick/items/qquickimagebase.cpp
@@ -226,7 +226,7 @@ void QQuickImageBase::load()
// will be used, as usual.
bool setDevicePixelRatio = false;
if (!d->sourcesize.isValid()) {
- if (loadUrl.scheme() == QStringLiteral("image")) {
+ if (loadUrl.scheme() == QLatin1String("image")) {
setDevicePixelRatio = true;
} else {
QString stringUrl = loadUrl.path(QUrl::PrettyDecoded);
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 5be1c86fb4..b2c039660e 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -2074,6 +2074,10 @@ void QQuickItemPrivate::updateSubFocusItem(QQuickItem *scope, bool focus)
\value ItemRotationHasChanged The item's rotation has changed.
ItemChangeData::realValue contains the new rotation.
+
+ \value ItemDevicePixelRatioHasChanged The device pixel ratio of the screen
+ the item is on has changed. ItemChangedData::realValue contains the new
+ device pixel ratio.
*/
/*!
@@ -2477,6 +2481,7 @@ QQuickItem *QQuickItemPrivate::prevTabChildItem(const QQuickItem *item, int star
QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, bool forward)
{
Q_ASSERT(item);
+ qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: item:" << item << ", forward:" << forward;
if (!item->window())
return item;
@@ -2487,19 +2492,25 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo
bool all = QGuiApplication::styleHints()->tabFocusBehavior() == Qt::TabFocusAllControls;
QQuickItem *from = 0;
+ bool isTabFence = item->d_func()->isTabFence;
if (forward) {
- from = item->parentItem();
+ if (!isTabFence)
+ from = item->parentItem();
} else {
if (!item->childItems().isEmpty())
from = item->d_func()->childItems.constFirst();
- else
+ else if (!isTabFence)
from = item->parentItem();
}
bool skip = false;
QQuickItem * startItem = item;
QQuickItem * firstFromItem = from;
QQuickItem *current = item;
+ qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: startItem:" << startItem;
+ qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: firstFromItem:" << firstFromItem;
do {
+ qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: current:" << current;
+ qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: from:" << from;
skip = false;
QQuickItem *last = current;
@@ -2513,7 +2524,7 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo
else
lastChild = prevTabChildItem(current, -1);
}
- bool isTabFence = current->d_func()->isTabFence;
+ isTabFence = current->d_func()->isTabFence;
if (isTabFence && !hasChildren)
return current;
@@ -2568,9 +2579,14 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo
return startItem;
}
}
- if (!firstFromItem) { //start from root
- startItem = current;
- firstFromItem = from;
+ if (!firstFromItem) {
+ if (startItem->d_func()->isTabFence) {
+ if (current == startItem)
+ firstFromItem = from;
+ } else { //start from root
+ startItem = current;
+ firstFromItem = from;
+ }
}
} while (skip || !current->activeFocusOnTab() || !current->isEnabled() || !current->isVisible()
|| !(all || QQuickItemPrivate::canAcceptTabFocus(current)));
@@ -4563,9 +4579,9 @@ QQuickItem *QQuickItem::childAt(qreal x, qreal y) const
// Map coordinates to the child element's coordinate space
QPointF point = mapToItem(child, QPointF(x, y));
if (child->isVisible() && point.x() >= 0
- && child->width() >= point.x()
+ && child->width() > point.x()
&& point.y() >= 0
- && child->height() >= point.y())
+ && child->height() > point.y())
return child;
}
return 0;
@@ -5968,6 +5984,8 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt
}
break;
case QQuickItem::ItemAntialiasingHasChanged:
+ // fall through
+ case QQuickItem::ItemDevicePixelRatioHasChanged:
q->itemChange(change, data);
break;
}
@@ -6906,7 +6924,7 @@ void QQuickItem::setAcceptedMouseButtons(Qt::MouseButtons buttons)
}
/*!
- Returns whether mouse events of this item's children should be filtered
+ Returns whether mouse and touch events of this item's children should be filtered
through this item.
\sa setFiltersChildMouseEvents(), childMouseEventFilter()
@@ -6918,7 +6936,7 @@ bool QQuickItem::filtersChildMouseEvents() const
}
/*!
- Sets whether mouse events of this item's children should be filtered
+ Sets whether mouse and touch events of this item's children should be filtered
through this item.
If \a filter is true, childMouseEventFilter() will be called when
@@ -7256,7 +7274,7 @@ void QQuickItem::setKeepTouchGrab(bool keep)
}
/*!
- \qmlmethod object QtQuick::Item::contains(point point)
+ \qmlmethod bool QtQuick::Item::contains(point point)
Returns true if this item contains \a point, which is in local coordinates;
returns false otherwise.
diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h
index 8795c71b38..b33f3d8b6a 100644
--- a/src/quick/items/qquickitem.h
+++ b/src/quick/items/qquickitem.h
@@ -172,7 +172,8 @@ public:
ItemOpacityHasChanged, // value.realValue
ItemActiveFocusHasChanged, // value.boolValue
ItemRotationHasChanged, // value.realValue
- ItemAntialiasingHasChanged // value.boolValue
+ ItemAntialiasingHasChanged, // value.boolValue
+ ItemDevicePixelRatioHasChanged // value.realValue
};
union ItemChangeData {
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index 7009a8e328..188b347a20 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -2484,8 +2484,10 @@ void QQuickItemViewPrivate::updateUnrequestedIndexes()
void QQuickItemViewPrivate::updateUnrequestedPositions()
{
- for (QHash<QQuickItem*,int>::const_iterator it = unrequestedItems.cbegin(), cend = unrequestedItems.cend(); it != cend; ++it)
- repositionPackageItemAt(it.key(), it.value());
+ for (QHash<QQuickItem*,int>::const_iterator it = unrequestedItems.cbegin(), cend = unrequestedItems.cend(); it != cend; ++it) {
+ if (it.value() >= 0)
+ repositionPackageItemAt(it.key(), it.value());
+ }
}
void QQuickItemViewPrivate::updateVisibleIndex()
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index e42873f459..f843b09592 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -2195,7 +2195,7 @@ void QQuickListView::setOrientation(QQuickListView::Orientation orientation)
existing applications. When explicitly set, it will cease to be bound to
the interactive property.
- \sa \l {Flickable::}{interactive}
+ \sa {Flickable::}{interactive}
*/
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index 0f7f1961a1..f3254cf8d7 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -1465,7 +1465,8 @@ void QQuickText::itemChange(ItemChange change, const ItemChangeData &value)
{
Q_D(QQuickText);
Q_UNUSED(value);
- if (change == ItemAntialiasingHasChanged) {
+ switch (change) {
+ case ItemAntialiasingHasChanged:
if (!antialiasing())
d->font.setStyleStrategy(QFont::NoAntialias);
else
@@ -1473,6 +1474,22 @@ void QQuickText::itemChange(ItemChange change, const ItemChangeData &value)
d->implicitWidthValid = false;
d->implicitHeightValid = false;
d->updateLayout();
+ break;
+
+ case ItemDevicePixelRatioHasChanged:
+ if (d->renderType == NativeRendering) {
+ // Native rendering optimizes for a given pixel grid, so its results must not be scaled.
+ // Text layout code respects the current device pixel ratio automatically, we only need
+ // to rerun layout after the ratio changed.
+ // Changes of implicit size should be minimal; they are hard to avoid.
+ d->implicitWidthValid = false;
+ d->implicitHeightValid = false;
+ d->updateLayout();
+ }
+ break;
+
+ default:
+ break;
}
QQuickItem::itemChange(change, value);
}
diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp
index ab460034bb..127b51948a 100644
--- a/src/quick/items/qquicktextcontrol.cpp
+++ b/src/quick/items/qquicktextcontrol.cpp
@@ -44,6 +44,7 @@
#include <qcoreapplication.h>
#include <qfont.h>
+#include <qfontmetrics.h>
#include <qevent.h>
#include <qdebug.h>
#include <qdrag.h>
@@ -965,6 +966,14 @@ process:
{
QString text = e->text();
if (!text.isEmpty() && (text.at(0).isPrint() || text.at(0) == QLatin1Char('\t'))) {
+ if (overwriteMode
+ // no need to call deleteChar() if we have a selection, insertText
+ // does it already
+ && !cursor.hasSelection()
+ && !cursor.atBlockEnd()) {
+ cursor.deleteChar();
+ }
+
cursor.insertText(text);
selectionChanged();
} else {
@@ -1007,6 +1016,12 @@ QRectF QQuickTextControlPrivate::rectForPosition(int position) const
if (line.isValid()) {
qreal x = line.cursorToX(relativePos);
qreal w = 0;
+ if (overwriteMode) {
+ if (relativePos < line.textLength() - line.textStart())
+ w = line.cursorToX(relativePos + 1) - x;
+ else
+ w = QFontMetrics(block.layout()->font()).width(QLatin1Char(' ')); // in sync with QTextLine::draw()
+ }
r = QRectF(layoutPos.x() + x, layoutPos.y() + line.y(), textCursorWidth + w, line.height());
} else {
r = QRectF(layoutPos.x(), layoutPos.y(), textCursorWidth, 10); // #### correct height
@@ -1483,6 +1498,21 @@ bool QQuickTextControl::hasImState() const
return d->hasImState;
}
+bool QQuickTextControl::overwriteMode() const
+{
+ Q_D(const QQuickTextControl);
+ return d->overwriteMode;
+}
+
+void QQuickTextControl::setOverwriteMode(bool overwrite)
+{
+ Q_D(QQuickTextControl);
+ if (d->overwriteMode == overwrite)
+ return;
+ d->overwriteMode = overwrite;
+ emit overwriteModeChanged(overwrite);
+}
+
bool QQuickTextControl::cursorVisible() const
{
Q_D(const QQuickTextControl);
diff --git a/src/quick/items/qquicktextcontrol_p.h b/src/quick/items/qquicktextcontrol_p.h
index 23c91d555b..cee9cff064 100644
--- a/src/quick/items/qquicktextcontrol_p.h
+++ b/src/quick/items/qquicktextcontrol_p.h
@@ -94,6 +94,8 @@ public:
#endif
bool hasImState() const;
+ bool overwriteMode() const;
+ void setOverwriteMode(bool overwrite);
bool cursorVisible() const;
void setCursorVisible(bool visible);
QRectF cursorRect(const QTextCursor &cursor) const;
@@ -148,6 +150,7 @@ Q_SIGNALS:
void copyAvailable(bool b);
void selectionChanged();
void cursorPositionChanged();
+ void overwriteModeChanged(bool overwriteMode);
// control signals
void updateCursorRequest();
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index f6c3d2f09f..a3ceb1344c 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -1584,6 +1584,32 @@ bool QQuickTextEdit::event(QEvent *event)
}
/*!
+ \qmlproperty bool QtQuick::TextEdit::overwriteMode
+ \since 5.8
+ Whether text entered by the user will overwrite existing text.
+
+ As with many text editors, the text editor widget can be configured
+ to insert or overwrite existing text with new text entered by the user.
+
+ If this property is \c true, existing text is overwritten, character-for-character
+ by new text; otherwise, text is inserted at the cursor position, displacing
+ existing text.
+
+ By default, this property is \c false (new text does not overwrite existing text).
+*/
+bool QQuickTextEdit::overwriteMode() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->control->overwriteMode();
+}
+
+void QQuickTextEdit::setOverwriteMode(bool overwrite)
+{
+ Q_D(QQuickTextEdit);
+ d->control->setOverwriteMode(overwrite);
+}
+
+/*!
\overload
Handles the given key \a event.
*/
@@ -2186,6 +2212,7 @@ void QQuickTextEditPrivate::init()
qmlobject_connect(control, QQuickTextControl, SIGNAL(cursorRectangleChanged()), q, QQuickTextEdit, SLOT(moveCursorDelegate()));
qmlobject_connect(control, QQuickTextControl, SIGNAL(linkActivated(QString)), q, QQuickTextEdit, SIGNAL(linkActivated(QString)));
qmlobject_connect(control, QQuickTextControl, SIGNAL(linkHovered(QString)), q, QQuickTextEdit, SIGNAL(linkHovered(QString)));
+ qmlobject_connect(control, QQuickTextControl, SIGNAL(overwriteModeChanged(bool)), q, QQuickTextEdit, SIGNAL(overwriteModeChanged(bool)));
qmlobject_connect(control, QQuickTextControl, SIGNAL(textChanged()), q, QQuickTextEdit, SLOT(q_textChanged()));
qmlobject_connect(control, QQuickTextControl, SIGNAL(preeditTextChanged()), q, QQuickTextEdit, SIGNAL(preeditTextChanged()));
#ifndef QT_NO_CLIPBOARD
diff --git a/src/quick/items/qquicktextedit_p.h b/src/quick/items/qquicktextedit_p.h
index f6ecb984e3..42c9064860 100644
--- a/src/quick/items/qquicktextedit_p.h
+++ b/src/quick/items/qquicktextedit_p.h
@@ -86,6 +86,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextEdit : public QQuickImplicitSizeItem
Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged)
Q_PROPERTY(QRectF cursorRectangle READ cursorRectangle NOTIFY cursorRectangleChanged)
Q_PROPERTY(QQmlComponent* cursorDelegate READ cursorDelegate WRITE setCursorDelegate NOTIFY cursorDelegateChanged)
+ Q_PROPERTY(bool overwriteMode READ overwriteMode WRITE setOverwriteMode NOTIFY overwriteModeChanged)
Q_PROPERTY(int selectionStart READ selectionStart NOTIFY selectionStartChanged)
Q_PROPERTY(int selectionEnd READ selectionEnd NOTIFY selectionEndChanged)
Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectedTextChanged)
@@ -199,6 +200,9 @@ public:
QQmlComponent* cursorDelegate() const;
void setCursorDelegate(QQmlComponent*);
+ bool overwriteMode() const;
+ void setOverwriteMode(bool overwrite);
+
int selectionStart() const;
int selectionEnd() const;
@@ -313,6 +317,7 @@ Q_SIGNALS:
void readOnlyChanged(bool isReadOnly);
void cursorVisibleChanged(bool isCursorVisible);
void cursorDelegateChanged();
+ void overwriteModeChanged(bool overwriteMode);
void activeFocusOnPressChanged(bool activeFocusOnPressed);
void persistentSelectionChanged(bool isPersistentSelection);
void textMarginChanged(qreal textMargin);
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index 7a86e1a323..9664326af5 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -813,7 +813,14 @@ QRectF QQuickTextInput::cursorRectangle() const
return QRectF();
qreal x = l.cursorToX(c) - d->hscroll + leftPadding();
qreal y = l.y() - d->vscroll + topPadding();
- return QRectF(x, y, 1, l.height());
+ qreal w = 1;
+ if (d->overwriteMode) {
+ if (c < text().length())
+ w = l.cursorToX(c + 1) - x;
+ else
+ w = QFontMetrics(font()).width(QLatin1Char(' ')); // in sync with QTextLine::draw()
+ }
+ return QRectF(x, y, w, l.height());
}
/*!
@@ -1263,7 +1270,14 @@ QRectF QQuickTextInput::positionToRectangle(int pos) const
return QRectF();
qreal x = l.cursorToX(pos) - d->hscroll;
qreal y = l.y() - d->vscroll;
- return QRectF(x, y, 1, l.height());
+ qreal w = 1;
+ if (d->overwriteMode) {
+ if (pos < text().length())
+ w = l.cursorToX(pos + 1) - x;
+ else
+ w = QFontMetrics(font()).width(QLatin1Char(' ')); // in sync with QTextLine::draw()
+ }
+ return QRectF(x, y, w, l.height());
}
/*!
@@ -1345,6 +1359,36 @@ int QQuickTextInputPrivate::positionAt(qreal x, qreal y, QTextLine::CursorPositi
return line.isValid() ? line.xToCursor(x, position) : 0;
}
+/*!
+ \qmlproperty bool QtQuick::TextInput::overwriteMode
+ \since 5.8
+
+ Whether text entered by the user will overwrite existing text.
+
+ As with many text editors, the text editor widget can be configured
+ to insert or overwrite existing text with new text entered by the user.
+
+ If this property is \c true, existing text is overwritten, character-for-character
+ by new text; otherwise, text is inserted at the cursor position, displacing
+ existing text.
+
+ By default, this property is \c false (new text does not overwrite existing text).
+*/
+bool QQuickTextInput::overwriteMode() const
+{
+ Q_D(const QQuickTextInput);
+ return d->overwriteMode;
+}
+
+void QQuickTextInput::setOverwriteMode(bool overwrite)
+{
+ Q_D(QQuickTextInput);
+ if (d->overwriteMode == overwrite)
+ return;
+ d->overwriteMode = overwrite;
+ emit overwriteModeChanged(overwrite);
+}
+
void QQuickTextInput::keyPressEvent(QKeyEvent* ev)
{
Q_D(QQuickTextInput);
@@ -4409,6 +4453,14 @@ void QQuickTextInputPrivate::processKeyEvent(QKeyEvent* event)
if (unknown && !m_readOnly) {
QString t = event->text();
if (!t.isEmpty() && t.at(0).isPrint()) {
+ if (overwriteMode
+ // no need to call del() if we have a selection, insert
+ // does it already
+ && !hasSelectedText()
+ && !(m_cursor == q_func()->text().length())) {
+ del();
+ }
+
insert(t);
event->accept();
return;
diff --git a/src/quick/items/qquicktextinput_p.h b/src/quick/items/qquicktextinput_p.h
index 06ca1acb0d..d2dee2c284 100644
--- a/src/quick/items/qquicktextinput_p.h
+++ b/src/quick/items/qquicktextinput_p.h
@@ -79,6 +79,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextInput : public QQuickImplicitSizeItem
Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged)
Q_PROPERTY(QRectF cursorRectangle READ cursorRectangle NOTIFY cursorRectangleChanged)
Q_PROPERTY(QQmlComponent *cursorDelegate READ cursorDelegate WRITE setCursorDelegate NOTIFY cursorDelegateChanged)
+ Q_PROPERTY(bool overwriteMode READ overwriteMode WRITE setOverwriteMode NOTIFY overwriteModeChanged)
Q_PROPERTY(int selectionStart READ selectionStart NOTIFY selectionStartChanged)
Q_PROPERTY(int selectionEnd READ selectionEnd NOTIFY selectionEndChanged)
Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectedTextChanged)
@@ -245,6 +246,9 @@ public:
QQmlComponent* cursorDelegate() const;
void setCursorDelegate(QQmlComponent*);
+ bool overwriteMode() const;
+ void setOverwriteMode(bool overwrite);
+
bool focusOnPress() const;
void setFocusOnPress(bool);
@@ -325,6 +329,7 @@ Q_SIGNALS:
void readOnlyChanged(bool isReadOnly);
void cursorVisibleChanged(bool isCursorVisible);
void cursorDelegateChanged();
+ void overwriteModeChanged(bool overwriteMode);
void maximumLengthChanged(int maximumLength);
void validatorChanged();
void inputMaskChanged(const QString &inputMask);
diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h
index 24cbc7f74b..d5a138945d 100644
--- a/src/quick/items/qquicktextinput_p_p.h
+++ b/src/quick/items/qquicktextinput_p_p.h
@@ -158,6 +158,7 @@ public:
, m_passwordEchoEditing(false)
, inLayout(false)
, requireImplicitWidth(false)
+ , overwriteMode(false)
{
}
@@ -299,6 +300,7 @@ public:
bool m_passwordEchoEditing : 1;
bool inLayout:1;
bool requireImplicitWidth:1;
+ bool overwriteMode:1;
static inline QQuickTextInputPrivate *get(QQuickTextInput *t) {
return t->d_func();
diff --git a/src/quick/items/qquicktextnodeengine.cpp b/src/quick/items/qquicktextnodeengine.cpp
index 34b9d6efa2..7b600adf53 100644
--- a/src/quick/items/qquicktextnodeengine.cpp
+++ b/src/quick/items/qquicktextnodeengine.cpp
@@ -731,10 +731,13 @@ void QQuickTextNodeEngine::mergeProcessedNodes(QList<BinaryTreeNode *> *regularN
QVector<QPointF> glyphPositions = glyphRun.positions();
glyphPositions.reserve(count);
+ QRectF glyphBoundingRect = glyphRun.boundingRect();
+
for (int j = 1; j < nodes.size(); ++j) {
BinaryTreeNode *otherNode = nodes.at(j);
glyphIndexes += otherNode->glyphRun.glyphIndexes();
primaryNode->ranges += otherNode->ranges;
+ glyphBoundingRect = glyphBoundingRect.united(otherNode->glyphRun.boundingRect());
QVector<QPointF> otherPositions = otherNode->glyphRun.positions();
for (int k = 0; k < otherPositions.size(); ++k)
@@ -746,6 +749,7 @@ void QQuickTextNodeEngine::mergeProcessedNodes(QList<BinaryTreeNode *> *regularN
glyphRun.setGlyphIndexes(glyphIndexes);
glyphRun.setPositions(glyphPositions);
+ glyphRun.setBoundingRect(glyphBoundingRect);
}
}
}
@@ -828,14 +832,15 @@ void QQuickTextNodeEngine::addToSceneGraph(QQuickTextNode *parentNode,
for (int i = 0; i < node->ranges.size(); ++i) {
const QPair<int, int> &range = node->ranges.at(i);
- int rangeLength = range.second - range.first;
+ int rangeLength = range.second - range.first + 1;
if (previousNode != 0) {
for (int j = 0; j < previousNode->ranges.size(); ++j) {
const QPair<int, int> &otherRange = previousNode->ranges.at(j);
+
if (range.first < otherRange.second && range.second > otherRange.first) {
int start = qMax(range.first, otherRange.first);
int end = qMin(range.second, otherRange.second);
- rangeLength -= end - start;
+ rangeLength -= end - start + 1;
if (rangeLength == 0)
break;
}
@@ -849,7 +854,7 @@ void QQuickTextNodeEngine::addToSceneGraph(QQuickTextNode *parentNode,
if (range.first < otherRange.second && range.second > otherRange.first) {
int start = qMax(range.first, otherRange.first);
int end = qMin(range.second, otherRange.second);
- rangeLength -= end - start;
+ rangeLength -= end - start + 1;
if (rangeLength == 0)
break;
}
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 635f1da77e..b6d685fdf0 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -294,10 +294,43 @@ void QQuickWindow::update()
QQuickRenderControlPrivate::get(d->renderControl)->update();
}
+static void updatePixelRatioHelper(QQuickItem *item, float pixelRatio)
+{
+ if (item->flags() & QQuickItem::ItemHasContents) {
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ itemPrivate->itemChange(QQuickItem::ItemDevicePixelRatioHasChanged, pixelRatio);
+ }
+
+ QList <QQuickItem *> items = item->childItems();
+ for (int i = 0; i < items.size(); ++i)
+ updatePixelRatioHelper(items.at(i), pixelRatio);
+}
+
+void QQuickWindow::physicalDpiChanged()
+{
+ Q_D(QQuickWindow);
+ const qreal newPixelRatio = screen()->devicePixelRatio();
+ if (qFuzzyCompare(newPixelRatio, d->devicePixelRatio))
+ return;
+ d->devicePixelRatio = newPixelRatio;
+ if (d->contentItem)
+ updatePixelRatioHelper(d->contentItem, newPixelRatio);
+}
+
void QQuickWindow::handleScreenChanged(QScreen *screen)
{
Q_D(QQuickWindow);
- Q_UNUSED(screen)
+ if (screen) {
+ physicalDpiChanged();
+ // When physical DPI changes on the same screen, either the resolution or the device pixel
+ // ratio changed. We must check what it is. Device pixel ratio does not have its own
+ // ...Changed() signal.
+ d->physicalDpiChangedConnection = connect(screen, SIGNAL(physicalDotsPerInchChanged(qreal)),
+ this, SLOT(physicalDpiChanged()));
+ } else {
+ disconnect(d->physicalDpiChangedConnection);
+ }
+
d->forcePolish();
}
@@ -416,6 +449,7 @@ QQuickWindowPrivate::QQuickWindowPrivate()
, touchMouseId(-1)
, touchMousePressTimestamp(0)
, dirtyItemList(0)
+ , devicePixelRatio(0)
, context(0)
, renderer(0)
, windowManager(0)
@@ -470,6 +504,9 @@ void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control)
Q_ASSERT(windowManager || renderControl);
+ if (QScreen *screen = q->screen())
+ devicePixelRatio = screen->devicePixelRatio();
+
QSGContext *sg;
if (renderControl) {
QQuickRenderControlPrivate *renderControlPriv = QQuickRenderControlPrivate::get(renderControl);
@@ -2114,7 +2151,7 @@ bool QQuickWindowPrivate::deliverTouchPoints(QQuickItem *item, QTouchEvent *even
return (acceptedNewPoints->count() == newPoints.count() && updatedPoints->isEmpty());
}
-// touchEventForItemBounds has no means to generate a touch event that contains
+// touchEventForItem has no means to generate a touch event that contains
// only the points that are relevant for this item. Thus the need for
// matchingPoints to already be that set of interesting points.
// They are all pre-transformed, too.
@@ -2176,7 +2213,7 @@ bool QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QTouchEv
return touchEventAccepted;
}
-QTouchEvent *QQuickWindowPrivate::touchEventForItemBounds(QQuickItem *target, const QTouchEvent &originalEvent)
+QTouchEvent *QQuickWindowPrivate::touchEventForItem(QQuickItem *target, const QTouchEvent &originalEvent, bool alwaysCheckBounds)
{
const QList<QTouchEvent::TouchPoint> &touchPoints = originalEvent.touchPoints();
QList<QTouchEvent::TouchPoint> pointsInBounds;
@@ -2184,7 +2221,10 @@ QTouchEvent *QQuickWindowPrivate::touchEventForItemBounds(QQuickItem *target, co
if (originalEvent.touchPointStates() != Qt::TouchPointStationary) {
for (int i = 0; i < touchPoints.count(); ++i) {
const QTouchEvent::TouchPoint &tp = touchPoints.at(i);
- if (tp.state() == Qt::TouchPointPressed) {
+ // Touch presses are relevant to the target item only if they occur inside its bounds.
+ // Touch updates and releases are relevant if they occur inside, or if we want to
+ // finish the sequence because the press occurred inside.
+ if (tp.state() == Qt::TouchPointPressed || alwaysCheckBounds) {
QPointF p = target->mapFromScene(tp.scenePos());
if (target->contains(p))
pointsInBounds.append(tp);
@@ -2413,7 +2453,7 @@ bool QQuickWindowPrivate::sendFilteredTouchEvent(QQuickItem *target, QQuickItem
QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(target);
if (targetPrivate->filtersChildMouseEvents && !hasFiltered->contains(target)) {
hasFiltered->insert(target);
- QScopedPointer<QTouchEvent> targetEvent(touchEventForItemBounds(target, *event));
+ QScopedPointer<QTouchEvent> targetEvent(touchEventForItem(target, *event));
if (!targetEvent->touchPoints().isEmpty()) {
if (target->childMouseEventFilter(item, targetEvent.data())) {
qCDebug(DBG_TOUCH) << " - first chance intercepted on childMouseEventFilter by " << target;
@@ -2513,6 +2553,15 @@ bool QQuickWindowPrivate::dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent
return overThreshold;
}
+bool QQuickWindowPrivate::dragOverThreshold(qreal d, Qt::Axis axis, const QTouchEvent::TouchPoint *tp, int startDragThreshold)
+{
+ QStyleHints *styleHints = qApp->styleHints();
+ bool overThreshold = qAbs(d) > (startDragThreshold >= 0 ? startDragThreshold : styleHints->startDragDistance());
+ qreal velocity = axis == Qt::XAxis ? tp->velocity().x() : tp->velocity().y();
+ overThreshold |= qAbs(velocity) > styleHints->startDragVelocity();
+ return overThreshold;
+}
+
/*!
\qmlproperty list<Object> Window::data
\default
@@ -3872,6 +3921,14 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
+ \qmlattachedproperty Window Window::window
+ \since 5.7
+
+ This attached property holds the item's window.
+ The Window attached property can be attached to any Item.
+*/
+
+/*!
\qmlattachedproperty int Window::width
\qmlattachedproperty int Window::height
\since 5.5
diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h
index 262828ad1d..e04a4a1ce2 100644
--- a/src/quick/items/qquickwindow.h
+++ b/src/quick/items/qquickwindow.h
@@ -202,6 +202,7 @@ protected:
private Q_SLOTS:
void maybeUpdate();
void cleanupSceneGraph();
+ void physicalDpiChanged();
void handleScreenChanged(QScreen *screen);
void setTransientParent_helper(QQuickWindow *window);
void runJobsAfterSwap();
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index 652320c1c9..1486e20e1e 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -163,8 +163,8 @@ public:
void flushDelayedTouchEvent();
bool deliverHoverEvent(QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, bool &accepted);
bool deliverMatchingPointsToItem(QQuickItem *item, QTouchEvent *event, QSet<int> *acceptedNewPoints, const QSet<int> &matchingNewPoints, const QList<QTouchEvent::TouchPoint> &matchingPoints, QSet<QQuickItem*> *filtered);
- QTouchEvent *touchEventForItemBounds(QQuickItem *target, const QTouchEvent &originalEvent);
- QTouchEvent *touchEventWithPoints(const QTouchEvent &event, const QList<QTouchEvent::TouchPoint> &newPoints);
+ static QTouchEvent *touchEventForItem(QQuickItem *target, const QTouchEvent &originalEvent, bool alwaysCheckBounds = false);
+ static QTouchEvent *touchEventWithPoints(const QTouchEvent &event, const QList<QTouchEvent::TouchPoint> &newPoints);
bool sendFilteredTouchEvent(QQuickItem *target, QQuickItem *item, QTouchEvent *event, QSet<QQuickItem*> *filtered);
bool sendHoverEvent(QEvent::Type, QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos,
Qt::KeyboardModifiers modifiers, bool accepted);
@@ -211,6 +211,9 @@ public:
QVector<QQuickItem *> itemsToPolish;
+ qreal devicePixelRatio;
+ QMetaObject::Connection physicalDpiChangedConnection;
+
void updateDirtyNodes();
void cleanupNodes();
void cleanupNodesOnShutdown();
@@ -262,6 +265,7 @@ public:
static bool defaultAlphaBuffer;
static bool dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent *event, int startDragThreshold = -1);
+ static bool dragOverThreshold(qreal d, Qt::Axis axis, const QTouchEvent::TouchPoint *tp, int startDragThreshold = -1);
// data property
static void data_append(QQmlListProperty<QObject> *, QObject *);
diff --git a/src/quick/items/qquickwindowattached.cpp b/src/quick/items/qquickwindowattached.cpp
index e1cd3c82f2..c6380e2b9a 100644
--- a/src/quick/items/qquickwindowattached.cpp
+++ b/src/quick/items/qquickwindowattached.cpp
@@ -51,9 +51,9 @@ QQuickWindowAttached::QQuickWindowAttached(QObject* attachee)
{
m_attachee = qobject_cast<QQuickItem*>(attachee);
if (m_attachee && m_attachee->window()) // It might not be in a window yet
- windowChanged(m_attachee->window());
+ windowChange(m_attachee->window());
if (m_attachee)
- connect(m_attachee, &QQuickItem::windowChanged, this, &QQuickWindowAttached::windowChanged);
+ connect(m_attachee, &QQuickItem::windowChanged, this, &QQuickWindowAttached::windowChange);
}
QWindow::Visibility QQuickWindowAttached::visibility() const
@@ -86,7 +86,12 @@ int QQuickWindowAttached::height() const
return (m_window ? m_window->height() : 0);
}
-void QQuickWindowAttached::windowChanged(QQuickWindow *window)
+QQuickWindow *QQuickWindowAttached::window() const
+{
+ return m_window;
+}
+
+void QQuickWindowAttached::windowChange(QQuickWindow *window)
{
if (window != m_window) {
QQuickWindow* oldWindow = m_window;
@@ -95,21 +100,23 @@ void QQuickWindowAttached::windowChanged(QQuickWindow *window)
if (oldWindow)
oldWindow->disconnect(this);
- if (!window)
- return; // No values to get, therefore nothing to emit
+ emit windowChanged();
- if (!oldWindow || window->visibility() != oldWindow->visibility())
+ if (!oldWindow || !window || window->visibility() != oldWindow->visibility())
emit visibilityChanged();
- if (!oldWindow || window->isActive() != oldWindow->isActive())
+ if (!oldWindow || !window || window->isActive() != oldWindow->isActive())
emit activeChanged();
- if (!oldWindow || window->activeFocusItem() != oldWindow->activeFocusItem())
+ if (!oldWindow || !window || window->activeFocusItem() != oldWindow->activeFocusItem())
emit activeFocusItemChanged();
emit contentItemChanged();
- if (!oldWindow || window->width() != oldWindow->width())
+ if (!oldWindow || !window || window->width() != oldWindow->width())
emit widthChanged();
- if (!oldWindow || window->height() != oldWindow->height())
+ if (!oldWindow || !window || window->height() != oldWindow->height())
emit heightChanged();
+ if (!window)
+ return;
+
// QQuickWindowQmlImpl::visibilityChanged also exists, and window might even
// be QQuickWindowQmlImpl, but that's not what we are connecting to.
// So this is actual window state rather than a buffered or as-requested one.
diff --git a/src/quick/items/qquickwindowattached_p.h b/src/quick/items/qquickwindowattached_p.h
index 5e4b2c1721..3212508fd8 100644
--- a/src/quick/items/qquickwindowattached_p.h
+++ b/src/quick/items/qquickwindowattached_p.h
@@ -69,6 +69,7 @@ class Q_AUTOTEST_EXPORT QQuickWindowAttached : public QObject
Q_PROPERTY(QQuickItem* contentItem READ contentItem NOTIFY contentItemChanged)
Q_PROPERTY(int width READ width NOTIFY widthChanged)
Q_PROPERTY(int height READ height NOTIFY heightChanged)
+ Q_PROPERTY(QQuickWindow *window READ window NOTIFY windowChanged)
public:
QQuickWindowAttached(QObject* attachee);
@@ -79,6 +80,7 @@ public:
QQuickItem* contentItem() const;
int width() const;
int height() const;
+ QQuickWindow *window() const;
Q_SIGNALS:
@@ -88,9 +90,10 @@ Q_SIGNALS:
void contentItemChanged();
void widthChanged();
void heightChanged();
+ void windowChanged();
protected Q_SLOTS:
- void windowChanged(QQuickWindow*);
+ void windowChange(QQuickWindow*);
private:
QQuickWindow* m_window;
diff --git a/src/quick/quick.pro b/src/quick/quick.pro
index 4ff2d76a09..90ba867ea8 100644
--- a/src/quick/quick.pro
+++ b/src/quick/quick.pro
@@ -1,7 +1,12 @@
TARGET = QtQuick
QT = core-private gui-private qml-private
-QT_PRIVATE = network
+!no_network {
+ QT_PRIVATE = network
+}
+no_network {
+ DEFINES += QT_NO_NETWORK
+}
DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES
win32-msvc*:DEFINES *= _CRT_SECURE_NO_WARNINGS
@@ -24,12 +29,10 @@ ANDROID_BUNDLED_FILES += \
qml \
lib/libQt5QuickParticles.so
-load(qt_module)
-
include(util/util.pri)
include(scenegraph/scenegraph.pri)
include(items/items.pri)
-include(designer/designer.pri)
+!wince:include(designer/designer.pri)
contains(QT_CONFIG, accessibility) {
include(accessible/accessible.pri)
}
@@ -43,3 +46,5 @@ SOURCES += qtquick2.cpp
# To make #include "qquickcontext2d_jsclass.cpp" work
INCLUDEPATH += $$PWD
+
+load(qt_module)
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index a85a9ab3eb..bb5476c3e2 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -2698,7 +2698,9 @@ void Renderer::render()
if (m_alphaBatches.size())
std::sort(&m_alphaBatches.first(), &m_alphaBatches.last() + 1, qsg_sort_batch_increasing_order);
- m_zRange = 1.0 / (m_nextRenderOrder);
+ m_zRange = m_nextRenderOrder != 0
+ ? 1.0 / (m_nextRenderOrder)
+ : 0;
}
if (Q_UNLIKELY(debug_render())) timeSorting = timer.restart();
diff --git a/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp b/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp
index 1112eca27b..97d7e69407 100644
--- a/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp
+++ b/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp
@@ -274,7 +274,7 @@ int main(int argc, char **argv)
for (int i=0; i<args.length(); ++i) {
const QString &a = args.at(i);
- if (a == QStringLiteral("--file") && i < args.length() - 1) {
+ if (a == QLatin1String("--file") && i < args.length() - 1) {
qDebug() << "Reading file: " << args.at(i);
QFile file(args.at(++i));
if (!file.open(QFile::ReadOnly)) {
@@ -282,10 +282,10 @@ int main(int argc, char **argv)
return 1;
}
content = file.readAll();
- } else if (a == QStringLiteral("--selftest")) {
+ } else if (a == QLatin1String("--selftest")) {
qDebug() << "doing a selftest";
content = QByteArray(selftest);
- } else if (a == QStringLiteral("--help") || a == QStringLiteral("-h")) {
+ } else if (a == QLatin1String("--help") || a == QLatin1String("-h")) {
qDebug() << "usage:" << endl
<< " --file [name] A vertex shader file to rewrite" << endl;
}
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index 6572ceb2ce..2ba16e7328 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -136,9 +136,9 @@ public:
bool distanceFieldAntialiasingDecided;
};
-static bool qsg_useConsistentTiming()
+bool qsg_useConsistentTiming()
{
- static int use = -1;
+ int use = -1;
if (use < 0) {
use = !qEnvironmentVariableIsEmpty("QSG_FIXED_ANIMATION_STEP") && qgetenv("QSG_FIXED_ANIMATION_STEP") != "no"
? 1 : 0;
diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp
index b5f149eff7..cd0f77799b 100644
--- a/src/quick/scenegraph/qsgrenderloop.cpp
+++ b/src/quick/scenegraph/qsgrenderloop.cpp
@@ -67,7 +67,7 @@
QT_BEGIN_NAMESPACE
-
+extern bool qsg_useConsistentTiming();
extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
/*!
@@ -267,6 +267,10 @@ void QSGRenderLoop::handleContextCreationFailure(QQuickWindow *window,
QSGGuiThreadRenderLoop::QSGGuiThreadRenderLoop()
: gl(0)
{
+ if (qsg_useConsistentTiming()) {
+ QUnifiedTimer::instance(true)->setConsistentTiming(true);
+ qCDebug(QSG_LOG_INFO, "using fixed animation steps");
+ }
sg = QSGContext::createDefaultContext();
rc = sg->createRenderContext();
}
diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp
index 9d6e7f3b2a..57468e5799 100644
--- a/src/quick/scenegraph/util/qsgatlastexture.cpp
+++ b/src/quick/scenegraph/util/qsgatlastexture.cpp
@@ -141,9 +141,9 @@ Atlas::Atlas(const QSize &size)
QString *deviceName =
static_cast<QString *>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("AndroidDeviceName"));
static bool wrongfullyReportsBgra8888Support = deviceName != 0
- && (deviceName->compare(QStringLiteral("samsung SM-T211"), Qt::CaseInsensitive) == 0
- || deviceName->compare(QStringLiteral("samsung SM-T210"), Qt::CaseInsensitive) == 0
- || deviceName->compare(QStringLiteral("samsung SM-T215"), Qt::CaseInsensitive) == 0);
+ && (deviceName->compare(QLatin1String("samsung SM-T211"), Qt::CaseInsensitive) == 0
+ || deviceName->compare(QLatin1String("samsung SM-T210"), Qt::CaseInsensitive) == 0
+ || deviceName->compare(QLatin1String("samsung SM-T215"), Qt::CaseInsensitive) == 0);
#else
static bool wrongfullyReportsBgra8888Support = false;
// The Raspberry Pi (both 1 and 2) GPU refuses framebuffers with BGRA color attachments.
diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp
index 169f3ebe59..74390334c4 100644
--- a/src/quick/scenegraph/util/qsgtexture.cpp
+++ b/src/quick/scenegraph/util/qsgtexture.cpp
@@ -720,9 +720,9 @@ void QSGPlainTexture::bind()
QString *deviceName =
static_cast<QString *>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("AndroidDeviceName"));
static bool wrongfullyReportsBgra8888Support = deviceName != 0
- && (deviceName->compare(QStringLiteral("samsung SM-T211"), Qt::CaseInsensitive) == 0
- || deviceName->compare(QStringLiteral("samsung SM-T210"), Qt::CaseInsensitive) == 0
- || deviceName->compare(QStringLiteral("samsung SM-T215"), Qt::CaseInsensitive) == 0);
+ && (deviceName->compare(QLatin1String("samsung SM-T211"), Qt::CaseInsensitive) == 0
+ || deviceName->compare(QLatin1String("samsung SM-T210"), Qt::CaseInsensitive) == 0
+ || deviceName->compare(QLatin1String("samsung SM-T215"), Qt::CaseInsensitive) == 0);
#else
static bool wrongfullyReportsBgra8888Support = false;
#endif
diff --git a/src/quick/util/qquickanimator.cpp b/src/quick/util/qquickanimator.cpp
index f0d4caf7ab..abae6321b0 100644
--- a/src/quick/util/qquickanimator.cpp
+++ b/src/quick/util/qquickanimator.cpp
@@ -217,7 +217,8 @@ qreal QQuickAnimator::from() const
void QQuickAnimatorPrivate::apply(QQuickAnimatorJob *job,
const QString &propertyName,
QQuickStateActions &actions,
- QQmlProperties &modified)
+ QQmlProperties &modified,
+ QObject *defaultTarget)
{
if (actions.size()) {
@@ -249,14 +250,20 @@ void QQuickAnimatorPrivate::apply(QQuickAnimatorJob *job,
// the item when a transition is cancelled.
action.fromValue = action.toValue;
}
- } else {
+ }
+
+ if (modified.isEmpty()) {
job->setTarget(target);
job->setFrom(from);
job->setTo(to);
}
- if (!job->target() && defaultProperty.object())
- job->setTarget(qobject_cast<QQuickItem *>(defaultProperty.object()));
+ if (!job->target()) {
+ if (defaultProperty.object())
+ job->setTarget(qobject_cast<QQuickItem *>(defaultProperty.object()));
+ else
+ job->setTarget(qobject_cast<QQuickItem *>(defaultTarget));
+ }
job->setDuration(duration);
job->setLoopCount(loopCount);
@@ -266,7 +273,7 @@ void QQuickAnimatorPrivate::apply(QQuickAnimatorJob *job,
QAbstractAnimationJob *QQuickAnimator::transition(QQuickStateActions &actions,
QQmlProperties &modified,
TransitionDirection direction,
- QObject *)
+ QObject *defaultTarget)
{
Q_D(QQuickAnimator);
@@ -283,7 +290,7 @@ QAbstractAnimationJob *QQuickAnimator::transition(QQuickStateActions &actions,
if (!job)
return 0;
- d->apply(job, propertyName(), actions, modified);
+ d->apply(job, propertyName(), actions, modified, defaultTarget);
if (!job->target()) {
delete job;
diff --git a/src/quick/util/qquickanimator_p_p.h b/src/quick/util/qquickanimator_p_p.h
index 7a61462762..b176119c70 100644
--- a/src/quick/util/qquickanimator_p_p.h
+++ b/src/quick/util/qquickanimator_p_p.h
@@ -82,7 +82,7 @@ public:
uint isFromDefined : 1;
uint isToDefined : 1;
- void apply(QQuickAnimatorJob *job, const QString &propertyName, QQuickStateActions &actions, QQmlProperties &modified);
+ void apply(QQuickAnimatorJob *job, const QString &propertyName, QQuickStateActions &actions, QQmlProperties &modified, QObject *defaultTarget);
};
class QQuickRotationAnimatorPrivate : public QQuickAnimatorPrivate
diff --git a/src/quick/util/qquickapplication.cpp b/src/quick/util/qquickapplication.cpp
index a4e2f0eb0e..5c26b23ff7 100644
--- a/src/quick/util/qquickapplication.cpp
+++ b/src/quick/util/qquickapplication.cpp
@@ -90,4 +90,9 @@ Qt::ApplicationState QQuickApplication::state() const
return QGuiApplication::applicationState();
}
+QFont QQuickApplication::font() const
+{
+ return QGuiApplication::font();
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/util/qquickapplication_p.h b/src/quick/util/qquickapplication_p.h
index 971c9a203a..091cb094ed 100644
--- a/src/quick/util/qquickapplication_p.h
+++ b/src/quick/util/qquickapplication_p.h
@@ -52,6 +52,7 @@
//
#include <QtCore/QObject>
+#include <QtGui/QFont>
#include <qqml.h>
#include <QtQml/private/qqmlglobal_p.h>
#include <private/qtquickglobal_p.h>
@@ -66,6 +67,7 @@ class Q_AUTOTEST_EXPORT QQuickApplication : public QQmlApplication
Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection NOTIFY layoutDirectionChanged)
Q_PROPERTY(bool supportsMultipleWindows READ supportsMultipleWindows CONSTANT)
Q_PROPERTY(Qt::ApplicationState state READ state NOTIFY stateChanged)
+ Q_PROPERTY(QFont font READ font CONSTANT)
public:
explicit QQuickApplication(QObject *parent = 0);
@@ -74,6 +76,7 @@ public:
Qt::LayoutDirection layoutDirection() const;
bool supportsMultipleWindows() const;
Qt::ApplicationState state() const;
+ QFont font() const;
Q_SIGNALS:
void activeChanged();
diff --git a/src/quick/util/qquickfontloader.cpp b/src/quick/util/qquickfontloader.cpp
index 64fd458ef0..b7367f3934 100644
--- a/src/quick/util/qquickfontloader.cpp
+++ b/src/quick/util/qquickfontloader.cpp
@@ -45,14 +45,18 @@
#include <QStringList>
#include <QUrl>
#include <QDebug>
-#include <QNetworkRequest>
-#include <QNetworkReply>
+
#include <QFontDatabase>
#include <private/qobject_p.h>
#include <qqmlinfo.h>
#include <qqmlfile.h>
+#ifndef QT_NO_NETWORK
+#include <QNetworkRequest>
+#include <QNetworkReply>
+#endif
+
#include <QtCore/QCoreApplication>
QT_BEGIN_NAMESPACE
@@ -66,28 +70,37 @@ Q_OBJECT
public:
explicit QQuickFontObject(int _id = -1);
+#ifndef QT_NO_NETWORK
void download(const QUrl &url, QNetworkAccessManager *manager);
Q_SIGNALS:
void fontDownloaded(const QString&, QQuickFontLoader::Status);
+private:
+ int redirectCount;
+ QNetworkReply *reply;
+
private Q_SLOTS:
void replyFinished();
+#endif // QT_NO_NETWORK
public:
int id;
-private:
- QNetworkReply *reply;
- int redirectCount;
-
Q_DISABLE_COPY(QQuickFontObject)
};
QQuickFontObject::QQuickFontObject(int _id)
- : QObject(0), id(_id), reply(0), redirectCount(0) {}
+ : QObject(0)
+#ifndef QT_NO_NETWORK
+ ,redirectCount(0), reply(0)
+#endif
+ ,id(_id)
+{
+}
+#ifndef QT_NO_NETWORK
void QQuickFontObject::download(const QUrl &url, QNetworkAccessManager *manager)
{
QNetworkRequest req(url);
@@ -128,7 +141,7 @@ void QQuickFontObject::replyFinished()
reply = 0;
}
}
-
+#endif // QT_NO_NETWORK
class QQuickFontLoaderPrivate : public QObjectPrivate
{
@@ -255,6 +268,7 @@ void QQuickFontLoader::setSource(const QUrl &url)
}
} else {
if (!fontLoaderFonts()->map.contains(d->url)) {
+#ifndef QT_NO_NETWORK
QQuickFontObject *fo = new QQuickFontObject;
fontLoaderFonts()->map[d->url] = fo;
fo->download(d->url, qmlEngine(this)->networkAccessManager());
@@ -262,13 +276,20 @@ void QQuickFontLoader::setSource(const QUrl &url)
emit statusChanged();
QObject::connect(fo, SIGNAL(fontDownloaded(QString,QQuickFontLoader::Status)),
this, SLOT(updateFontInfo(QString,QQuickFontLoader::Status)));
+#else
+// Silently fail if compiled with no_network
+#endif
} else {
QQuickFontObject *fo = fontLoaderFonts()->map[d->url];
if (fo->id == -1) {
+#ifndef QT_NO_NETWORK
d->status = Loading;
emit statusChanged();
QObject::connect(fo, SIGNAL(fontDownloaded(QString,QQuickFontLoader::Status)),
this, SLOT(updateFontInfo(QString,QQuickFontLoader::Status)));
+#else
+// Silently fail if compiled with no_network
+#endif
}
else
updateFontInfo(QFontDatabase::applicationFontFamilies(fo->id).at(0), Ready);
diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp
index d669a7feda..23b2887fac 100644
--- a/src/quick/util/qquickpixmapcache.cpp
+++ b/src/quick/util/qquickpixmapcache.cpp
@@ -38,7 +38,6 @@
****************************************************************************/
#include "qquickpixmapcache_p.h"
-#include <qqmlnetworkaccessmanagerfactory.h>
#include <qquickimageprovider.h>
#include <qqmlengine.h>
@@ -55,7 +54,6 @@
#include <QCoreApplication>
#include <QImageReader>
#include <QHash>
-#include <QNetworkReply>
#include <QPixmapCache>
#include <QFile>
#include <QThread>
@@ -66,10 +64,15 @@
#include <QWaitCondition>
#include <QtCore/qdebug.h>
#include <private/qobject_p.h>
-#include <QSslError>
#include <QQmlFile>
#include <QMetaMethod>
+#ifndef QT_NO_NETWORK
+#include <qqmlnetworkaccessmanagerfactory.h>
+#include <QNetworkReply>
+#include <QSslError>
+#endif
+
#include <private/qquickprofiler_p.h>
#define IMAGEREQUEST_MAX_NETWORK_REQUEST_COUNT 8
@@ -203,7 +206,9 @@ private:
friend class QQuickPixmapReaderThreadObject;
void processJobs();
void processJob(QQuickPixmapReply *, const QUrl &, const QString &, AutoTransform, QQuickImageProvider::ImageType, QQuickImageProvider *);
+#ifndef QT_NO_NETWORK
void networkRequestDone(QNetworkReply *);
+#endif
void asyncResponseFinished(QQuickImageResponse *);
QList<QQuickPixmapReply*> jobs;
@@ -215,10 +220,11 @@ private:
QQuickPixmapReaderThreadObject *threadObject;
QWaitCondition waitCondition;
+#ifndef QT_NO_NETWORK
QNetworkAccessManager *networkAccessManager();
QNetworkAccessManager *accessManager;
-
QHash<QNetworkReply*,QQuickPixmapReply*> networkJobs;
+#endif
QHash<QQuickImageResponse*,QQuickPixmapReply*> asyncResponses;
static int replyDownloadProgress;
@@ -343,6 +349,7 @@ QQuickPixmapReply::Event::~Event()
delete textureFactory;
}
+#ifndef QT_NO_NETWORK
QNetworkAccessManager *QQuickPixmapReader::networkAccessManager()
{
if (!accessManager) {
@@ -351,6 +358,7 @@ QNetworkAccessManager *QQuickPixmapReader::networkAccessManager()
}
return accessManager;
}
+#endif
static void maybeRemoveAlpha(QImage *image)
{
@@ -421,7 +429,10 @@ static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *e
}
QQuickPixmapReader::QQuickPixmapReader(QQmlEngine *eng)
-: QThread(eng), engine(eng), threadObject(0), accessManager(0)
+: QThread(eng), engine(eng), threadObject(0)
+#ifndef QT_NO_NETWORK
+, accessManager(0)
+#endif
{
eventLoopQuitHack = new QObject;
eventLoopQuitHack->moveToThread(this);
@@ -443,6 +454,7 @@ QQuickPixmapReader::~QQuickPixmapReader()
delete reply;
}
jobs.clear();
+#ifndef QT_NO_NETWORK
QList<QQuickPixmapReply*> activeJobs = networkJobs.values() + asyncResponses.values();
foreach (QQuickPixmapReply *reply, activeJobs ) {
if (reply->loading) {
@@ -450,6 +462,7 @@ QQuickPixmapReader::~QQuickPixmapReader()
reply->data = 0;
}
}
+#endif
if (threadObject) threadObject->processJobs();
mutex.unlock();
@@ -457,6 +470,7 @@ QQuickPixmapReader::~QQuickPixmapReader()
wait();
}
+#ifndef QT_NO_NETWORK
void QQuickPixmapReader::networkRequestDone(QNetworkReply *reply)
{
QQuickPixmapReply *job = networkJobs.take(reply);
@@ -506,6 +520,7 @@ void QQuickPixmapReader::networkRequestDone(QNetworkReply *reply)
// kick off event loop again incase we have dropped below max request count
threadObject->processJobs();
}
+#endif // QT_NO_NETWORK
void QQuickPixmapReader::asyncResponseFinished(QQuickImageResponse *response)
{
@@ -557,8 +572,10 @@ bool QQuickPixmapReaderThreadObject::event(QEvent *e)
void QQuickPixmapReaderThreadObject::networkRequestDone()
{
+#ifndef QT_NO_NETWORK
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
reader->networkRequestDone(reply);
+#endif
}
void QQuickPixmapReaderThreadObject::asyncResponseFinished()
@@ -577,6 +594,7 @@ void QQuickPixmapReader::processJobs()
// Clean cancelled jobs
if (!cancelled.isEmpty()) {
+#ifndef QT_NO_NETWORK
for (int i = 0; i < cancelled.count(); ++i) {
QQuickPixmapReply *job = cancelled.at(i);
QNetworkReply *reply = networkJobs.key(job, 0);
@@ -599,6 +617,7 @@ void QQuickPixmapReader::processJobs()
job->deleteLater();
}
cancelled.clear();
+#endif
}
if (!jobs.isEmpty()) {
@@ -619,7 +638,11 @@ void QQuickPixmapReader::processJobs()
usableJob = true;
} else {
localFile = QQmlFile::urlToLocalFileOrQrc(url);
- usableJob = !localFile.isEmpty() || networkJobs.count() < IMAGEREQUEST_MAX_NETWORK_REQUEST_COUNT;
+ usableJob = !localFile.isEmpty()
+#ifndef QT_NO_NETWORK
+ || networkJobs.count() < IMAGEREQUEST_MAX_NETWORK_REQUEST_COUNT
+#endif
+ ;
}
@@ -744,6 +767,7 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u
runningJob->postReply(errorCode, errorStr, readSize, QQuickTextureFactory::textureFactoryForImage(image));
mutex.unlock();
} else {
+#ifndef QT_NO_NETWORK
// Network resource
QNetworkRequest req(url);
req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
@@ -753,6 +777,9 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u
QMetaObject::connect(reply, replyFinished, threadObject, threadNetworkRequestDone);
networkJobs.insert(reply, runningJob);
+#else
+// Silently fail if compiled with no_network
+#endif
}
}
}
@@ -809,11 +836,13 @@ void QQuickPixmapReader::cancel(QQuickPixmapReply *reply)
void QQuickPixmapReader::run()
{
if (replyDownloadProgress == -1) {
+#ifndef QT_NO_NETWORK
replyDownloadProgress = QMetaMethod::fromSignal(&QNetworkReply::downloadProgress).methodIndex();
replyFinished = QMetaMethod::fromSignal(&QNetworkReply::finished).methodIndex();
- downloadProgress = QMetaMethod::fromSignal(&QQuickPixmapReply::downloadProgress).methodIndex();
const QMetaObject *ir = &QQuickPixmapReaderThreadObject::staticMetaObject;
threadNetworkRequestDone = ir->indexOfSlot("networkRequestDone()");
+#endif
+ downloadProgress = QMetaMethod::fromSignal(&QQuickPixmapReply::downloadProgress).methodIndex();
}
mutex.lock();
@@ -1194,8 +1223,6 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q
*ok = true;
return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(image), readSize, requestSize, autoTransform, appliedTransform);
}
- errorString = QQuickPixmap::tr("Invalid image data: %1").arg(url.toString());
-
} else {
errorString = QQuickPixmap::tr("Cannot open: %1").arg(url.toString());
}
diff --git a/src/quick/util/qquickstate_p.h b/src/quick/util/qquickstate_p.h
index 5c33d4b6b5..7d22ca9f8c 100644
--- a/src/quick/util/qquickstate_p.h
+++ b/src/quick/util/qquickstate_p.h
@@ -64,7 +64,7 @@ class QQuickStateActionEvent;
class QQmlBinding;
class QQmlExpression;
-class QQuickStateAction
+class Q_QUICK_PRIVATE_EXPORT QQuickStateAction
{
public:
QQuickStateAction();
diff --git a/src/quickwidgets/quickwidgets.pro b/src/quickwidgets/quickwidgets.pro
index ab388ff9d3..87409e31c5 100644
--- a/src/quickwidgets/quickwidgets.pro
+++ b/src/quickwidgets/quickwidgets.pro
@@ -4,9 +4,6 @@ QT = core-private gui-private qml-private quick-private widgets-private
DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES
-
-load(qt_module)
-
HEADERS += \
qquickwidget.h \
qquickwidget_p.h \
@@ -15,5 +12,4 @@ HEADERS += \
SOURCES += \
qquickwidget.cpp
-
-
+load(qt_module)
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index fe3efcd948..253b050b15 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -185,6 +185,8 @@ private slots:
void argumentEvaluationOrder();
+ void v4FunctionWithoutQML();
+
signals:
void testSignal();
};
@@ -3794,6 +3796,30 @@ void tst_QJSEngine::argumentEvaluationOrder()
}
+class TestObject : public QObject
+{
+ Q_OBJECT
+public:
+ TestObject() : called(false) {}
+
+ bool called;
+
+ Q_INVOKABLE void callMe(QQmlV4Function *) {
+ called = true;
+ }
+};
+
+void tst_QJSEngine::v4FunctionWithoutQML()
+{
+ TestObject obj;
+ QJSEngine engine;
+ QJSValue wrapper = engine.newQObject(&obj);
+ QQmlEngine::setObjectOwnership(&obj, QQmlEngine::CppOwnership);
+ QVERIFY(!obj.called);
+ wrapper.property("callMe").call();
+ QVERIFY(obj.called);
+}
+
QTEST_MAIN(tst_QJSEngine)
#include "tst_qjsengine.moc"
diff --git a/tests/auto/qml/qqmlbinding/data/disabledReadonly.qml b/tests/auto/qml/qqmlbinding/data/disabledReadonly.qml
new file mode 100644
index 0000000000..2d1715364c
--- /dev/null
+++ b/tests/auto/qml/qqmlbinding/data/disabledReadonly.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.0
+
+Item {
+ id: root
+
+ readonly property string name: "John"
+
+ Binding {
+ target: root
+ property: "name"
+ value: "Doe"
+ when: false
+ }
+}
diff --git a/tests/auto/qml/qqmlbinding/data/disabledUnknown.qml b/tests/auto/qml/qqmlbinding/data/disabledUnknown.qml
new file mode 100644
index 0000000000..08e1cff5d1
--- /dev/null
+++ b/tests/auto/qml/qqmlbinding/data/disabledUnknown.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.0
+
+Item {
+ id: root
+
+ Binding {
+ target: root
+ property: "unknown"
+ value: 42
+ when: false
+ }
+}
diff --git a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
index 6eff3cce1f..3e8dfbdb12 100644
--- a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
+++ b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
@@ -47,6 +47,8 @@ private slots:
void deletedObject();
void warningOnUnknownProperty();
void warningOnReadOnlyProperty();
+ void disabledOnUnknownProperty();
+ void disabledOnReadonlyProperty();
private:
QQmlEngine engine;
@@ -253,6 +255,32 @@ void tst_qqmlbinding::warningOnReadOnlyProperty()
QCOMPARE(messageHandler.messages().first(), expectedMessage);
}
+void tst_qqmlbinding::disabledOnUnknownProperty()
+{
+ QQmlTestMessageHandler messageHandler;
+
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("disabledUnknown.qml"));
+ QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+ QVERIFY(item);
+ delete item;
+
+ QCOMPARE(messageHandler.messages().count(), 0);
+}
+
+void tst_qqmlbinding::disabledOnReadonlyProperty()
+{
+ QQmlTestMessageHandler messageHandler;
+
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("disabledReadonly.qml"));
+ QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+ QVERIFY(item);
+ delete item;
+
+ QCOMPARE(messageHandler.messages().count(), 0);
+}
+
QTEST_MAIN(tst_qqmlbinding)
#include "tst_qqmlbinding.moc"
diff --git a/tests/auto/qml/qqmllanguage/data/arraybuffer_method_arg.qml b/tests/auto/qml/qqmllanguage/data/arraybuffer_method_arg.qml
new file mode 100644
index 0000000000..b64a2e23c0
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/arraybuffer_method_arg.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.7
+import Test 1.0
+
+MyArrayBufferTestClass {
+ property bool ok: false
+ Component.onCompleted: {
+ var data = new Uint8Array([1, 2, 3]);
+ var sum = byteArrayMethod_Sum(data.buffer);
+ ok = sum == 6;
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/arraybuffer_method_overload.qml b/tests/auto/qml/qqmllanguage/data/arraybuffer_method_overload.qml
new file mode 100644
index 0000000000..9e1c91810a
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/arraybuffer_method_overload.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.7
+import Test 1.0
+
+MyArrayBufferTestClass {
+ property bool ok: false
+ Component.onCompleted: ok = byteArrayMethod_Overloaded(new ArrayBuffer());
+}
diff --git a/tests/auto/qml/qqmllanguage/data/arraybuffer_method_return.qml b/tests/auto/qml/qqmllanguage/data/arraybuffer_method_return.qml
new file mode 100644
index 0000000000..5a4f9fec0b
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/arraybuffer_method_return.qml
@@ -0,0 +1,15 @@
+import QtQuick 2.7
+import Test 1.0
+
+MyArrayBufferTestClass {
+ property bool ok: false
+ Component.onCompleted: {
+ var buf = byteArrayMethod_CountUp(1, 3);
+ var view = new DataView(buf);
+ ok = buf instanceof ArrayBuffer
+ && buf.byteLength == 3
+ && view.getUint8(0) == 1
+ && view.getUint8(1) == 2
+ && view.getUint8(2) == 3;
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/arraybuffer_property_get.qml b/tests/auto/qml/qqmllanguage/data/arraybuffer_property_get.qml
new file mode 100644
index 0000000000..78ebb1abe1
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/arraybuffer_property_get.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+
+MyArrayBufferTestClass {
+ property bool ok: byteArrayProperty instanceof ArrayBuffer
+}
diff --git a/tests/auto/qml/qqmllanguage/data/arraybuffer_property_set.qml b/tests/auto/qml/qqmllanguage/data/arraybuffer_property_set.qml
new file mode 100644
index 0000000000..e8a51273ca
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/arraybuffer_property_set.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.7
+import Test 1.0
+
+MyArrayBufferTestClass {
+ property bool ok: false
+ onByteArraySignal: ok = byteArrayProperty instanceof ArrayBuffer
+ Component.onCompleted: {
+ byteArrayProperty = new ArrayBuffer(42);
+ ok = byteArrayProperty instanceof ArrayBuffer && byteArrayProperty.byteLength == 42;
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/arraybuffer_signal_arg.qml b/tests/auto/qml/qqmllanguage/data/arraybuffer_signal_arg.qml
new file mode 100644
index 0000000000..d9f436e788
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/arraybuffer_signal_arg.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.7
+import Test 1.0
+
+MyArrayBufferTestClass {
+ property bool ok: false
+ onByteArraySignal: {
+ var view = new DataView(arg);
+ ok = arg instanceof ArrayBuffer
+ && arg.byteLength == 2
+ && view.getUint8(0) == 42
+ && view.getUint8(1) == 43;
+ }
+ Component.onCompleted: emitByteArraySignal(42, 2)
+}
diff --git a/tests/auto/qml/qqmllanguage/data/lowercaseEnumCompileTime.1.errors.txt b/tests/auto/qml/qqmllanguage/data/lowercaseEnumCompileTime.1.errors.txt
new file mode 100644
index 0000000000..33360e96cf
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/lowercaseEnumCompileTime.1.errors.txt
@@ -0,0 +1 @@
+5:5:Invalid property assignment: Enum value "lowercaseEnumVal" cannot start with a lowercase letter
diff --git a/tests/auto/qml/qqmllanguage/data/lowercaseEnumCompileTime.1.qml b/tests/auto/qml/qqmllanguage/data/lowercaseEnumCompileTime.1.qml
new file mode 100644
index 0000000000..f6c3e9b404
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/lowercaseEnumCompileTime.1.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.0
+import Test 1.0
+
+MyTypeObject {
+ intProperty: MyTypeObject.lowercaseEnumVal
+}
diff --git a/tests/auto/qml/qqmllanguage/data/lowercaseEnumCompileTime.2.errors.txt b/tests/auto/qml/qqmllanguage/data/lowercaseEnumCompileTime.2.errors.txt
new file mode 100644
index 0000000000..33360e96cf
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/lowercaseEnumCompileTime.2.errors.txt
@@ -0,0 +1 @@
+5:5:Invalid property assignment: Enum value "lowercaseEnumVal" cannot start with a lowercase letter
diff --git a/tests/auto/qml/qqmllanguage/data/lowercaseEnumCompileTime.2.qml b/tests/auto/qml/qqmllanguage/data/lowercaseEnumCompileTime.2.qml
new file mode 100644
index 0000000000..0dfe26c71d
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/lowercaseEnumCompileTime.2.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.0
+import Test 1.0
+
+MyTypeObject {
+ enumProperty: MyTypeObjectSingleton.lowercaseEnumVal
+}
diff --git a/tests/auto/qml/qqmllanguage/data/lowercaseEnumRuntime.1.qml b/tests/auto/qml/qqmllanguage/data/lowercaseEnumRuntime.1.qml
new file mode 100644
index 0000000000..866b49e1d5
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/lowercaseEnumRuntime.1.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.0
+import Test 1.0
+
+MyTypeObject {
+ enumProperty: MyTypeObject.EnumVal1
+ Component.onCompleted: {
+ var a = MyTypeObject.EnumVal1;
+ var b = MyTypeObject.lowercaseEnumVal
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/lowercaseEnumRuntime.2.qml b/tests/auto/qml/qqmllanguage/data/lowercaseEnumRuntime.2.qml
new file mode 100644
index 0000000000..686977a11a
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/lowercaseEnumRuntime.2.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.0
+import Test 1.0
+
+MyTypeObject {
+ intProperty: MyTypeObjectSingleton.EnumVal1
+ Component.onCompleted: {
+ var a = MyTypeObjectSingleton.EnumVal1;
+ var b = MyTypeObjectSingleton.lowercaseEnumVal;
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp
index 4153aae1dc..cc39422dce 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.cpp
+++ b/tests/auto/qml/qqmllanguage/testtypes.cpp
@@ -29,6 +29,14 @@
#include <private/qqmlcompiler_p.h>
+static QObject *myTypeObjectSingleton(QQmlEngine *engine, QJSEngine *scriptEngine)
+{
+ Q_UNUSED(engine)
+ Q_UNUSED(scriptEngine)
+
+ return new MyTypeObject();
+}
+
void registerTypes()
{
qmlRegisterInterface<MyInterface>("MyInterface");
@@ -88,6 +96,10 @@ void registerTypes()
qmlRegisterType<RootObjectInCreationTester>("Test", 1, 0, "RootObjectInCreationTester");
qmlRegisterType<MyCompositeBaseType>("Test", 1, 0, "MyCompositeBaseType");
+
+ qmlRegisterSingletonType<MyTypeObjectSingleton>("Test", 1, 0, "MyTypeObjectSingleton", myTypeObjectSingleton);
+
+ qmlRegisterType<MyArrayBufferTestClass>("Test", 1, 0, "MyArrayBufferTestClass");
}
QVariant myCustomVariantTypeConverter(const QString &data)
diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h
index 851ada9383..2344b6a03b 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.h
+++ b/tests/auto/qml/qqmllanguage/testtypes.h
@@ -292,7 +292,7 @@ public:
emit flagPropertyChanged();
}
- enum MyEnum { EnumVal1, EnumVal2 };
+ enum MyEnum { EnumVal1, EnumVal2, lowercaseEnumVal };
MyEnum enumPropertyValue;
MyEnum enumProperty() const {
return enumPropertyValue;
@@ -592,6 +592,12 @@ signals:
};
Q_DECLARE_OPERATORS_FOR_FLAGS(MyTypeObject::MyFlags)
+// FIXME: If no subclass is used for the singleton registration with qmlRegisterSingletonType(),
+// the valueTypes() test will fail.
+class MyTypeObjectSingleton : public MyTypeObject
+{
+ Q_OBJECT
+};
class MyContainer : public QObject
{
@@ -1084,6 +1090,58 @@ public:
static QObject *qmlAttachedProperties(QObject *parent) { return new QObject(parent); }
};
+class MyArrayBufferTestClass : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QByteArray byteArrayProperty READ byteArrayProperty WRITE setByteArrayProperty NOTIFY byteArrayPropertyChanged)
+
+signals:
+ void byteArrayPropertyChanged();
+ void byteArraySignal(QByteArray arg);
+
+public:
+ QByteArray byteArrayPropertyValue;
+ QByteArray byteArrayProperty() const {
+ return byteArrayPropertyValue;
+ }
+ void setByteArrayProperty(const QByteArray &v) {
+ byteArrayPropertyValue = v;
+ emit byteArrayPropertyChanged();
+ }
+ Q_INVOKABLE void emitByteArraySignal(char begin, char num) {
+ byteArraySignal(byteArrayMethod_CountUp(begin, num));
+ }
+ Q_INVOKABLE int byteArrayMethod_Sum(QByteArray arg) {
+ int sum = 0;
+ for (int i = 0; i < arg.size(); ++i) {
+ sum += arg[i];
+ }
+ return sum;
+ }
+ Q_INVOKABLE QByteArray byteArrayMethod_CountUp(char begin, int num) {
+ QByteArray ret;
+ for (int i = 0; i < num; ++i) {
+ ret.push_back(begin++);
+ }
+ return ret;
+ }
+ Q_INVOKABLE bool byteArrayMethod_Overloaded(QByteArray) {
+ return true;
+ }
+ Q_INVOKABLE bool byteArrayMethod_Overloaded(int) {
+ return false;
+ }
+ Q_INVOKABLE bool byteArrayMethod_Overloaded(QString) {
+ return false;
+ }
+ Q_INVOKABLE bool byteArrayMethod_Overloaded(QJSValue) {
+ return false;
+ }
+ Q_INVOKABLE bool byteArrayMethod_Overloaded(QVariant) {
+ return false;
+ }
+};
+
Q_DECLARE_METATYPE(MyEnum2Class::EnumB)
Q_DECLARE_METATYPE(MyEnum1Class::EnumA)
Q_DECLARE_METATYPE(Qt::TextFormat)
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 45507e83ea..dd7410dfd3 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -198,6 +198,10 @@ private slots:
void crash2();
void globalEnums();
+ void lowercaseEnumRuntime_data();
+ void lowercaseEnumRuntime();
+ void lowercaseEnumCompileTime_data();
+ void lowercaseEnumCompileTime();
void literals_data();
void literals();
@@ -246,6 +250,9 @@ private slots:
void deleteSingletons();
+ void arrayBuffer_data();
+ void arrayBuffer();
+
private:
QQmlEngine engine;
QStringList defaultImportPathList;
@@ -3495,6 +3502,45 @@ void tst_qqmllanguage::globalEnums()
delete o;
}
+void tst_qqmllanguage::lowercaseEnumRuntime_data()
+{
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<QString>("errorMessage");
+
+ QTest::newRow("enum from normal type") << "lowercaseEnumRuntime.1.qml" << ":8: TypeError: Cannot access enum value 'lowercaseEnumVal' of 'MyTypeObject', enum values need to start with an uppercase letter.";
+ QTest::newRow("enum from singleton type") << "lowercaseEnumRuntime.2.qml" << ":8: TypeError: Cannot access enum value 'lowercaseEnumVal' of 'MyTypeObjectSingleton', enum values need to start with an uppercase letter.";
+}
+
+void tst_qqmllanguage::lowercaseEnumRuntime()
+{
+ QFETCH(QString, file);
+ QFETCH(QString, errorMessage);
+
+ QQmlComponent component(&engine, testFileUrl(file));
+ VERIFY_ERRORS(0);
+ QString warning = component.url().toString() + errorMessage;
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
+ delete component.create();
+}
+
+void tst_qqmllanguage::lowercaseEnumCompileTime_data()
+{
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<QString>("errorFile");
+
+ QTest::newRow("assignment to int property") << "lowercaseEnumCompileTime.1.qml" << "lowercaseEnumCompileTime.1.errors.txt";
+ QTest::newRow("assignment to enum property") << "lowercaseEnumCompileTime.2.qml" << "lowercaseEnumCompileTime.2.errors.txt";
+}
+
+void tst_qqmllanguage::lowercaseEnumCompileTime()
+{
+ QFETCH(QString, file);
+ QFETCH(QString, errorFile);
+
+ QQmlComponent component(&engine, testFileUrl(file));
+ VERIFY_ERRORS(qPrintable(errorFile));
+}
+
void tst_qqmllanguage::literals_data()
{
QTest::addColumn<QString>("property");
@@ -4102,6 +4148,27 @@ void tst_qqmllanguage::deleteSingletons()
QVERIFY(singleton.data() == 0);
}
+void tst_qqmllanguage::arrayBuffer_data()
+{
+ QTest::addColumn<QString>("file");
+ QTest::newRow("arraybuffer_property_get") << "arraybuffer_property_get.qml";
+ QTest::newRow("arraybuffer_property_set") << "arraybuffer_property_set.qml";
+ QTest::newRow("arraybuffer_signal_arg") << "arraybuffer_signal_arg.qml";
+ QTest::newRow("arraybuffer_method_arg") << "arraybuffer_method_arg.qml";
+ QTest::newRow("arraybuffer_method_return") << "arraybuffer_method_return.qml";
+ QTest::newRow("arraybuffer_method_overload") << "arraybuffer_method_overload.qml";
+}
+
+void tst_qqmllanguage::arrayBuffer()
+{
+ QFETCH(QString, file);
+ QQmlComponent component(&engine, testFile(file));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("ok").toBool(), true);
+}
+
QTEST_MAIN(tst_qqmllanguage)
#include "tst_qqmllanguage.moc"
diff --git a/tests/auto/quick/examples/tst_examples.cpp b/tests/auto/quick/examples/tst_examples.cpp
index 240e8a791e..548b20a80a 100644
--- a/tests/auto/quick/examples/tst_examples.cpp
+++ b/tests/auto/quick/examples/tst_examples.cpp
@@ -291,7 +291,6 @@ void tst_examples::sgsnippets_data()
void tst_examples::sgsnippets()
{
- QQuickWindow window;
QFETCH(QString, file);
@@ -301,19 +300,26 @@ void tst_examples::sgsnippets()
QCOMPARE(component.status(), QQmlComponent::Ready);
QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQuickWindow *window = qobject_cast<QQuickWindow*>(object.data());
QQuickItem *root = qobject_cast<QQuickItem *>(object.data());
- if (!root)
+ if (!root && !window) {
component.completeCreate();
- QVERIFY(root);
+ QVERIFY(false);
+ }
+ if (!window)
+ window = new QQuickWindow;
- window.resize(240, 320);
- window.show();
- QVERIFY(QTest::qWaitForWindowExposed(&window));
+ window->resize(240, 320);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
- root->setParentItem(window.contentItem());
+ if (root)
+ root->setParentItem(window->contentItem());
component.completeCreate();
qApp->processEvents();
+ if (root)
+ delete window;
}
QTEST_MAIN(tst_examples)
diff --git a/tests/auto/quick/qquickanimators/data/positionerWithAnimator.qml b/tests/auto/quick/qquickanimators/data/positionerWithAnimator.qml
new file mode 100644
index 0000000000..bfd475266e
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/positionerWithAnimator.qml
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+
+Column {
+ width: 200
+ height: 200
+
+ property alias repeater: repeater
+ property alias transition: transition
+
+ anchors.centerIn: parent
+ populate: Transition {
+ id: transition
+ ScaleAnimator {
+ from: 0
+ to: 1
+ }
+ }
+
+ Repeater {
+ id: repeater
+ model: ["red", "green", "blue"]
+
+ Rectangle {
+ width: 100
+ height: 100
+ color: modelData
+ scale: 0
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickanimators/tst_qquickanimators.cpp b/tests/auto/quick/qquickanimators/tst_qquickanimators.cpp
index 6943bf5045..29142dee12 100644
--- a/tests/auto/quick/qquickanimators/tst_qquickanimators.cpp
+++ b/tests/auto/quick/qquickanimators/tst_qquickanimators.cpp
@@ -30,6 +30,8 @@
#include <QtQuick>
#include <private/qquickanimator_p.h>
+#include <private/qquickrepeater_p.h>
+#include <private/qquicktransition_p.h>
#include <QtQml>
@@ -40,6 +42,7 @@ class tst_Animators: public QObject
private slots:
void testMultiWinAnimator_data();
void testMultiWinAnimator();
+ void testTransitions();
};
void tst_Animators::testMultiWinAnimator_data()
@@ -94,6 +97,28 @@ void tst_Animators::testMultiWinAnimator()
QVERIFY(true);
}
+void tst_Animators::testTransitions()
+{
+ QQuickView view(QUrl::fromLocalFile("data/positionerWithAnimator.qml"));
+ view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+ QVERIFY(view.rootObject());
+
+ QQuickRepeater *repeater = view.rootObject()->property("repeater").value<QQuickRepeater *>();
+ QVERIFY(repeater);
+
+ QQuickItem *child = repeater->itemAt(0);
+ QVERIFY(child);
+ QCOMPARE(child->scale(), qreal(0.0));
+
+ QQuickTransition *transition = view.rootObject()->property("transition").value<QQuickTransition *>();
+ QVERIFY(transition);
+
+ QTRY_VERIFY(transition->running());
+ QTRY_VERIFY(!transition->running());
+ QCOMPARE(child->scale(), qreal(1.0));
+}
+
#include "tst_qquickanimators.moc"
QTEST_MAIN(tst_Animators)
diff --git a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
index 1bd163fc4a..114f906736 100644
--- a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
+++ b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
@@ -47,6 +47,7 @@ private slots:
void active();
void state();
void layoutDirection();
+ void font();
void inputMethod();
void styleHints();
void cleanup();
@@ -196,6 +197,21 @@ void tst_qquickapplication::layoutDirection()
QCOMPARE(Qt::LayoutDirection(item->property("layoutDirection").toInt()), Qt::LeftToRight);
}
+void tst_qquickapplication::font()
+{
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick 2.0; Item { property font defaultFont: Qt.application.font }", QUrl::fromLocalFile(""));
+ QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
+ QVERIFY(item);
+ QQuickView view;
+ item->setParentItem(view.rootObject());
+
+ QVariant defaultFontProperty = item->property("defaultFont");
+ QVERIFY(defaultFontProperty.isValid());
+ QCOMPARE(defaultFontProperty.type(), QVariant::Font);
+ QCOMPARE(defaultFontProperty.value<QFont>(), qApp->font());
+}
+
void tst_qquickapplication::inputMethod()
{
// technically not in QQuickApplication, but testing anyway here
diff --git a/tests/auto/quick/qquickgridview/data/qtbug48870.qml b/tests/auto/quick/qquickgridview/data/qtbug48870.qml
new file mode 100644
index 0000000000..7c0783fbb5
--- /dev/null
+++ b/tests/auto/quick/qquickgridview/data/qtbug48870.qml
@@ -0,0 +1,30 @@
+import QtQuick 2.6
+
+Rectangle {
+ width: 500
+ height: 500
+ color: "blue"
+
+ GridView {
+ id: view
+ objectName: "view"
+ anchors.fill: parent
+ model: testModel
+ cellWidth: 150
+ cellHeight: 150
+ readonly property int columns: Math.floor(width / cellWidth)
+
+ delegate: Rectangle {
+ width: GridView.view.cellWidth
+ height: GridView.view.cellHeight
+ color: (row & 1) != (col & 1) ? "green" : "red"
+ readonly property int row: index / view.columns
+ readonly property int col: index % view.columns
+
+ Text {
+ anchors.centerIn: parent
+ text: "Item " + index
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
index b3474db7de..07c03a57d7 100644
--- a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
+++ b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
@@ -36,6 +36,7 @@
#include <QtQml/qqmlincubator.h>
#include <QtQml/qqmlcontext.h>
#include <QtQuick/private/qquickitem_p.h>
+#include <QtQuick/private/qquickitemview_p_p.h>
#include <QtQuick/private/qquickgridview_p.h>
#include <QtQuick/private/qquicktext_p.h>
#include <QtQml/private/qqmllistmodel_p.h>
@@ -205,6 +206,7 @@ private slots:
void contentHeightWithDelayRemove();
void QTBUG_45640();
+ void QTBUG_48870_fastModelUpdates();
void keyNavigationEnabled();
@@ -6628,6 +6630,42 @@ void tst_QQuickGridView::keyNavigationEnabled()
QCOMPARE(gridView->currentIndex(), 1);
}
+void tst_QQuickGridView::QTBUG_48870_fastModelUpdates()
+{
+ StressTestModel model;
+
+ QScopedPointer<QQuickView> window(createView());
+ QQmlContext *ctxt = window->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ window->setSource(testFileUrl("qtbug48870.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickGridView *view = findItem<QQuickGridView>(window->rootObject(), "view");
+ QTRY_VERIFY(view != 0);
+
+ QQuickItemViewPrivate *priv = QQuickItemViewPrivate::get(view);
+ bool nonUnique;
+ FxViewItem *item = Q_NULLPTR;
+ int expectedIdx;
+ QVERIFY(testVisibleItems(priv, &nonUnique, &item, &expectedIdx));
+
+ for (int i = 0; i < 10; i++) {
+ QTest::qWait(100);
+ QVERIFY2(testVisibleItems(priv, &nonUnique, &item, &expectedIdx),
+ qPrintable(!item ? QString("Unexpected null item")
+ : nonUnique ? QString("Non-unique item at %1 and %2").arg(item->index).arg(expectedIdx)
+ : QString("Found index %1, expected index is %3").arg(item->index).arg(expectedIdx)));
+ if (i % 3 != 0) {
+ if (i & 1)
+ flick(window.data(), QPoint(100, 200), QPoint(100, 0), 100);
+ else
+ flick(window.data(), QPoint(100, 200), QPoint(100, 400), 100);
+ }
+ }
+}
+
QTEST_MAIN(tst_QQuickGridView)
#include "tst_qquickgridview.moc"
diff --git a/tests/auto/quick/qquickitem/data/childAtRectangle.qml b/tests/auto/quick/qquickitem/data/childAtRectangle.qml
new file mode 100644
index 0000000000..d459c2b3f1
--- /dev/null
+++ b/tests/auto/quick/qquickitem/data/childAtRectangle.qml
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Item {
+ width: 20
+ height: 20
+
+ Rectangle {
+ id: rect1
+
+ color: "red"
+ x: 0
+ y: 0
+ width: 16
+ height: 16
+ }
+
+ Rectangle {
+ id: rect2
+
+ color: "red"
+ x: 18
+ y: 0
+ width: 1
+ height: 1
+ }
+
+ Rectangle {
+ id: rect3
+
+ x: 19
+ y: 19
+ width: 0
+ height: 0
+ }
+
+}
+
diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
index 143f8f2b1c..4b2c86697e 100644
--- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
@@ -167,6 +167,8 @@ private slots:
void contains_data();
void contains();
+ void childAt();
+
private:
enum PaintOrderOp {
@@ -1966,6 +1968,46 @@ void tst_qquickitem::contains()
QCOMPARE(result.toBool(), contains);
}
+void tst_qquickitem::childAt()
+{
+ QQuickView view;
+ view.setSource(testFileUrl("childAtRectangle.qml"));
+ QQuickItem *root = qobject_cast<QQuickItem*>(view.rootObject());
+
+ int found = 0;
+ for (int i = 0; i < 16; i++)
+ {
+ if (root->childAt(i, 0))
+ found++;
+ }
+ QCOMPARE(found, 16);
+
+ found = 0;
+ for (int i = 0; i < 16; i++)
+ {
+ if (root->childAt(0, i))
+ found++;
+ }
+ QCOMPARE(found, 16);
+
+ found = 0;
+ for (int i = 0; i < 2; i++)
+ {
+ if (root->childAt(18 + i, 0))
+ found++;
+ }
+ QCOMPARE(found, 1);
+
+ found = 0;
+ for (int i = 0; i < 16; i++)
+ {
+ if (root->childAt(18, i))
+ found++;
+ }
+ QCOMPARE(found, 1);
+
+ QVERIFY(!root->childAt(19,19));
+}
QTEST_MAIN(tst_qquickitem)
diff --git a/tests/auto/quick/qquickitem2/data/qtbug_50516_2_1.qml b/tests/auto/quick/qquickitem2/data/qtbug_50516_2_1.qml
new file mode 100644
index 0000000000..d8b7833467
--- /dev/null
+++ b/tests/auto/quick/qquickitem2/data/qtbug_50516_2_1.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.1
+import Test 1.0
+
+TabFence2 {
+ objectName: "root"
+ focus: true
+ width: 800
+ height: 600
+ Item {
+ objectName: "item"
+ focus: true
+ }
+}
diff --git a/tests/auto/quick/qquickitem2/data/qtbug_50516_2_2.qml b/tests/auto/quick/qquickitem2/data/qtbug_50516_2_2.qml
new file mode 100644
index 0000000000..445dc6d2a1
--- /dev/null
+++ b/tests/auto/quick/qquickitem2/data/qtbug_50516_2_2.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.1
+import Test 1.0
+
+TabFence2 {
+ objectName: "root"
+ focus: true
+ width: 800
+ height: 600
+ Item {
+ objectName: "item"
+ }
+}
diff --git a/tests/auto/quick/qquickitem2/data/qtbug_50516_2_3.qml b/tests/auto/quick/qquickitem2/data/qtbug_50516_2_3.qml
new file mode 100644
index 0000000000..806d48ebeb
--- /dev/null
+++ b/tests/auto/quick/qquickitem2/data/qtbug_50516_2_3.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.1
+import Test 1.0
+
+TabFence2 {
+ objectName: "root"
+ focus: true
+ width: 800
+ height: 600
+ Item {
+ objectName: "item2"
+ focus: true
+ }
+ Item {
+ objectName: "item2"
+ }
+}
diff --git a/tests/auto/quick/qquickitem2/data/qtbug_50516_2_4.qml b/tests/auto/quick/qquickitem2/data/qtbug_50516_2_4.qml
new file mode 100644
index 0000000000..6fcf513b51
--- /dev/null
+++ b/tests/auto/quick/qquickitem2/data/qtbug_50516_2_4.qml
@@ -0,0 +1,15 @@
+import QtQuick 2.1
+import Test 1.0
+
+TabFence2 {
+ objectName: "root"
+ focus: true
+ width: 800
+ height: 600
+ Item {
+ objectName: "item2"
+ }
+ Item {
+ objectName: "item2"
+ }
+}
diff --git a/tests/auto/quick/qquickitem2/data/qtbug_50516_2_5.qml b/tests/auto/quick/qquickitem2/data/qtbug_50516_2_5.qml
new file mode 100644
index 0000000000..4f7b68a8de
--- /dev/null
+++ b/tests/auto/quick/qquickitem2/data/qtbug_50516_2_5.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.1
+import Test 1.0
+
+TabFence2 {
+ objectName: "root"
+ focus: true
+ width: 800
+ height: 600
+ TextInput {
+ objectName: "item1"
+ activeFocusOnTab: true
+ }
+ Item {
+ objectName: "item2"
+ }
+}
diff --git a/tests/auto/quick/qquickitem2/data/qtbug_50516_2_6.qml b/tests/auto/quick/qquickitem2/data/qtbug_50516_2_6.qml
new file mode 100644
index 0000000000..223476327a
--- /dev/null
+++ b/tests/auto/quick/qquickitem2/data/qtbug_50516_2_6.qml
@@ -0,0 +1,17 @@
+import QtQuick 2.1
+import Test 1.0
+
+TabFence2 {
+ objectName: "root"
+ focus: true
+ width: 800
+ height: 600
+ TextInput {
+ objectName: "item1"
+ activeFocusOnTab: true
+ }
+ TextInput {
+ objectName: "item2"
+ activeFocusOnTab: true
+ }
+}
diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
index 607dbccaed..62ff09e698 100644
--- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
@@ -70,6 +70,8 @@ private slots:
void tabFence();
void qtbug_50516();
+ void qtbug_50516_2_data();
+ void qtbug_50516_2();
void keys();
void standardKeys_data();
@@ -305,6 +307,22 @@ public:
QML_DECLARE_TYPE(TabFenceItem);
+class TabFenceItem2 : public QQuickItem
+{
+ Q_OBJECT
+
+public:
+ TabFenceItem2(QQuickItem *parent = Q_NULLPTR)
+ : QQuickItem(parent)
+ {
+ QQuickItemPrivate *d = QQuickItemPrivate::get(this);
+ d->isTabFence = true;
+ setFlag(ItemIsFocusScope);
+ }
+};
+
+QML_DECLARE_TYPE(TabFenceItem2);
+
tst_QQuickItem::tst_QQuickItem()
{
}
@@ -315,6 +333,7 @@ void tst_QQuickItem::initTestCase()
qmlRegisterType<KeyTestItem>("Test",1,0,"KeyTestItem");
qmlRegisterType<HollowTestItem>("Test", 1, 0, "HollowTestItem");
qmlRegisterType<TabFenceItem>("Test", 1, 0, "TabFence");
+ qmlRegisterType<TabFenceItem2>("Test", 1, 0, "TabFence2");
}
void tst_QQuickItem::cleanup()
@@ -1212,6 +1231,51 @@ void tst_QQuickItem::qtbug_50516()
delete window;
}
+void tst_QQuickItem::qtbug_50516_2_data()
+{
+ QTest::addColumn<QString>("filename");
+ QTest::addColumn<QString>("item1");
+ QTest::addColumn<QString>("item2");
+
+ QTest::newRow("FocusScope TabFence with one Item(focused)")
+ << QStringLiteral("qtbug_50516_2_1.qml") << QStringLiteral("root") << QStringLiteral("root");
+ QTest::newRow("FocusScope TabFence with one Item(unfocused)")
+ << QStringLiteral("qtbug_50516_2_2.qml") << QStringLiteral("root") << QStringLiteral("root");
+ QTest::newRow("FocusScope TabFence with two Items(focused)")
+ << QStringLiteral("qtbug_50516_2_3.qml") << QStringLiteral("root") << QStringLiteral("root");
+ QTest::newRow("FocusScope TabFence with two Items(unfocused)")
+ << QStringLiteral("qtbug_50516_2_4.qml") << QStringLiteral("root") << QStringLiteral("root");
+ QTest::newRow("FocusScope TabFence with one Item and one TextInput(unfocused)")
+ << QStringLiteral("qtbug_50516_2_5.qml") << QStringLiteral("item1") << QStringLiteral("item1");
+ QTest::newRow("FocusScope TabFence with two TextInputs(unfocused)")
+ << QStringLiteral("qtbug_50516_2_6.qml") << QStringLiteral("item1") << QStringLiteral("item2");
+}
+
+void tst_QQuickItem::qtbug_50516_2()
+{
+ QFETCH(QString, filename);
+ QFETCH(QString, item1);
+ QFETCH(QString, item2);
+
+ QQuickView *window = new QQuickView(0);
+ window->setBaseSize(QSize(800,600));
+
+ window->setSource(testFileUrl(filename));
+ window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(window));
+ QVERIFY(QGuiApplication::focusWindow() == window);
+ QVERIFY(window->rootObject()->hasActiveFocus());
+
+ QQuickItem *contentItem = window->rootObject();
+ QQuickItem *next = contentItem->nextItemInFocusChain(true);
+ QCOMPARE(next->objectName(), item1);
+ next = contentItem->nextItemInFocusChain(false);
+ QCOMPARE(next->objectName(), item2);
+
+ delete window;
+}
+
void tst_QQuickItem::keys()
{
QQuickView *window = new QQuickView(0);
@@ -2931,12 +2995,12 @@ void tst_QQuickItem::childAt()
child3.setParentItem(&parent);
QCOMPARE(parent.childAt(0, 0), &child1);
- QCOMPARE(parent.childAt(0, 100), &child1);
+ QCOMPARE(parent.childAt(0, 99), &child1);
QCOMPARE(parent.childAt(25, 25), &child1);
QCOMPARE(parent.childAt(25, 75), &child1);
QCOMPARE(parent.childAt(75, 25), &child1);
QCOMPARE(parent.childAt(75, 75), &child2);
- QCOMPARE(parent.childAt(150, 150), &child2);
+ QCOMPARE(parent.childAt(149, 149), &child2);
QCOMPARE(parent.childAt(25, 200), &child3);
QCOMPARE(parent.childAt(0, 150), static_cast<QQuickItem *>(0));
QCOMPARE(parent.childAt(300, 300), static_cast<QQuickItem *>(0));
diff --git a/tests/auto/quick/qquicklayouts/data/tst_gridlayout.qml b/tests/auto/quick/qquicklayouts/data/tst_gridlayout.qml
new file mode 100644
index 0000000000..6a1c0632ad
--- /dev/null
+++ b/tests/auto/quick/qquicklayouts/data/tst_gridlayout.qml
@@ -0,0 +1,1036 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+import QtQuick.Layouts 1.1
+
+Item {
+ id: container
+ width: 200
+ height: 200
+ TestCase {
+ id: testCase
+ name: "Tests_GridLayout"
+ when: windowShown
+ width: 200
+ height: 200
+
+ Component {
+ id: layout_flow_Component
+ GridLayout {
+ columns: 4
+ columnSpacing: 0
+ rowSpacing: 0
+ Repeater {
+ model: 6
+ Rectangle {
+ property var itemRect: [x, y, width, height]
+ color: "red"
+ Layout.preferredWidth: 10
+ Layout.preferredHeight: 10
+ Text { text: index }
+ }
+ }
+ }
+ }
+
+ function test_flow()
+ {
+ var layout = layout_flow_Component.createObject(container);
+ tryCompare(layout.children[0], "itemRect", [ 0, 0, 10, 10])
+ tryCompare(layout.children[1], "itemRect", [10, 0, 10, 10])
+ tryCompare(layout.children[2], "itemRect", [20, 0, 10, 10])
+ tryCompare(layout.children[3], "itemRect", [30, 0, 10, 10])
+
+ tryCompare(layout.children[4], "itemRect", [ 0, 10, 10, 10])
+ tryCompare(layout.children[5], "itemRect", [10, 10, 10, 10])
+
+ layout.rows = 4
+ layout.flow = GridLayout.TopToBottom
+ tryCompare(layout.children[0], "itemRect", [ 0, 0, 10, 10])
+ tryCompare(layout.children[1], "itemRect", [ 0, 10, 10, 10])
+ tryCompare(layout.children[2], "itemRect", [ 0, 20, 10, 10])
+ tryCompare(layout.children[3], "itemRect", [ 0, 30, 10, 10])
+
+ tryCompare(layout.children[4], "itemRect", [10, 0, 10, 10])
+ tryCompare(layout.children[5], "itemRect", [10, 10, 10, 10])
+
+ layout.destroy()
+ }
+
+ Component {
+ id: layout_flowLeftToRight_Component
+ GridLayout {
+ columns: 4
+ columnSpacing: 0
+ rowSpacing: 0
+ // red rectangles are auto-positioned
+ // black rectangles are explicitly positioned with row,column
+ Rectangle {
+ // First one should auto position itself at (0,0)
+ id: r1
+ color: "red"
+ width: 20
+ height: 20
+ }
+ Rectangle {
+ // (1,1)
+ id: r2
+ color: "black"
+ width: 20
+ height: 20
+ Layout.row: 1
+ Layout.column: 1
+ Layout.rowSpan: 2
+ Layout.columnSpan: 2
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ }
+ Rectangle {
+ // (0,1)
+ id: r3
+ color: "black"
+ width: 20
+ height: 20
+ Layout.row: 0
+ Layout.column: 1
+ }
+ Rectangle {
+ // This one won't fit on the left and right sides of the big black box
+ // inserted at (3,0)
+ id: r4
+ color: "red"
+ width: 20
+ height: 20
+ Layout.columnSpan: 2
+ Layout.rowSpan: 2
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ }
+ Rectangle {
+ // continue flow from (0,2)
+ id: r5
+ color: "black"
+ width: 20
+ height: 20
+ Layout.row: 0
+ Layout.column: 2
+ }
+ Repeater {
+ // ...and let the rest of the items automatically fill in the empty cells
+ model: 8
+ Rectangle {
+ color: "red"
+ width: 20
+ height: 20
+ Text { text: index }
+ }
+ }
+ }
+ }
+
+ function test_flowLeftToRight() {
+ var layout = layout_flowLeftToRight_Component.createObject(container);
+ compare(layout.implicitWidth, 80);
+ compare(layout.children[0].x, 0);
+ compare(layout.children[0].y, 0);
+ compare(layout.children[1].x, 20);
+ compare(layout.children[1].y, 20);
+ compare(layout.children[2].x, 20);
+ compare(layout.children[2].y, 0);
+ compare(layout.children[3].x, 0);
+ compare(layout.children[3].y, 60);
+ compare(layout.children[4].x, 40);
+ compare(layout.children[4].y, 0);
+
+ // assumes that the repeater is the last item among the items it creates
+ compare(layout.children[5].x, 60);
+ compare(layout.children[5].y, 00);
+ compare(layout.children[6].x, 00);
+ compare(layout.children[6].y, 20);
+ compare(layout.children[7].x, 60);
+ compare(layout.children[7].y, 20);
+ compare(layout.children[8].x, 00);
+ compare(layout.children[8].y, 40);
+ compare(layout.children[9].x, 60);
+ compare(layout.children[9].y, 40);
+ compare(layout.children[10].x, 40);
+ compare(layout.children[10].y, 60);
+ compare(layout.children[11].x, 60);
+ compare(layout.children[11].y, 60);
+ compare(layout.children[12].x, 40);
+ compare(layout.children[12].y, 80);
+
+ layout.destroy();
+ }
+
+
+ Component {
+ id: layout_flowLeftToRightDefaultPositions_Component
+ GridLayout {
+ columns: 2
+ columnSpacing: 0
+ rowSpacing: 0
+ // red rectangles are auto-positioned
+ // black rectangles are explicitly positioned with row,column
+ // gray rectangles are items with just one row or just one column specified
+ Rectangle {
+ // First one should auto position itself at (0,0)
+ id: r1
+ color: "red"
+ width: 20
+ height: 20
+ }
+ Rectangle {
+ // (1,0)
+ id: r2
+ color: "gray"
+ width: 20
+ height: 20
+ Layout.row: 1
+ }
+ Rectangle {
+ // (1,1)
+ id: r3
+ color: "black"
+ width: 20
+ height: 20
+ Layout.row: 1
+ Layout.column: 1
+ }
+ Rectangle {
+ // (1,0), warning emitted
+ id: r4
+ color: "gray"
+ width: 20
+ height: 20
+ Layout.row: 1
+ }
+ }
+ }
+
+ function test_flowLeftToRightDefaultPositions() {
+ ignoreWarning("QGridLayoutEngine::addItem: Cell (1, 0) already taken");
+ var layout = layout_flowLeftToRightDefaultPositions_Component.createObject(container);
+ compare(layout.implicitWidth, 40);
+ compare(layout.children[0].x, 0);
+ compare(layout.children[0].y, 0);
+ compare(layout.children[1].x, 0);
+ compare(layout.children[1].y, 20);
+ compare(layout.children[2].x, 20);
+ compare(layout.children[2].y, 20);
+ layout.destroy();
+ }
+
+
+ Component {
+ id: layout_flowTopToBottom_Component
+ GridLayout {
+ rows: 4
+ columnSpacing: 0
+ rowSpacing: 0
+ flow: GridLayout.TopToBottom
+ // red rectangles are auto-positioned
+ // black rectangles are explicitly positioned with row,column
+ Rectangle {
+ // First one should auto position itself at (0,0)
+ id: r1
+ color: "red"
+ width: 20
+ height: 20
+ }
+ Rectangle {
+ // (1,1)
+ id: r2
+ color: "black"
+ width: 20
+ height: 20
+ Layout.row: 1
+ Layout.column: 1
+ Layout.rowSpan: 2
+ Layout.columnSpan: 2
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ }
+ Rectangle {
+ // (2,0)
+ id: r3
+ color: "black"
+ width: 20
+ height: 20
+ Layout.row: 2
+ Layout.column: 0
+ }
+ Rectangle {
+ // This one won't fit on the left and right sides of the big black box
+ // inserted at (0,3)
+ id: r4
+ color: "red"
+ width: 20
+ height: 20
+ Layout.rowSpan: 2
+ Layout.fillHeight: true
+ }
+ Rectangle {
+ // continue flow from (1,0)
+ id: r5
+ color: "black"
+ width: 20
+ height: 20
+ Layout.row: 1
+ Layout.column: 0
+ }
+ Repeater {
+ // ...and let the rest of the items automatically fill in the empty cells
+ model: 8
+ Rectangle {
+ color: "red"
+ width: 20
+ height: 20
+ Text { text: index }
+ }
+ }
+ }
+ }
+
+ function test_flowTopToBottom() {
+ var layout = layout_flowTopToBottom_Component.createObject(container);
+ compare(layout.children[0].x, 0);
+ compare(layout.children[0].y, 0);
+ compare(layout.children[1].x, 20);
+ compare(layout.children[1].y, 20);
+ compare(layout.children[2].x, 0);
+ compare(layout.children[2].y, 40);
+ compare(layout.children[3].x, 60);
+ compare(layout.children[3].y, 0);
+ compare(layout.children[4].x, 0);
+ compare(layout.children[4].y, 20);
+
+ // The repeated items
+ compare(layout.children[5].x, 0);
+ compare(layout.children[5].y, 60);
+ compare(layout.children[6].x, 20);
+ compare(layout.children[6].y, 0);
+ compare(layout.children[7].x, 20);
+ compare(layout.children[7].y, 60);
+ compare(layout.children[8].x, 40);
+ compare(layout.children[8].y, 0);
+ compare(layout.children[9].x, 40);
+ compare(layout.children[9].y, 60);
+ compare(layout.children[10].x, 60);
+ compare(layout.children[10].y, 40);
+ compare(layout.children[11].x, 60);
+ compare(layout.children[11].y, 60);
+ compare(layout.children[12].x, 80);
+ compare(layout.children[12].y, 0);
+
+ layout.destroy();
+ }
+
+ Component {
+ id: layout_spanAcrossEmptyRows_Component
+ /* This test has a large number of empty rows and columns, but there is one item
+ that spans across some of these empty rows/columns.
+ Do not modify (especially do not add items unless you understand what this is
+ testing)
+ */
+
+ GridLayout {
+ columnSpacing: 0
+ rowSpacing: 0
+ // black rectangles are explicitly positioned with row,column
+ Rectangle {
+ // (0,0)
+ id: r0
+ color: "black"
+ Layout.row: 0
+ Layout.column: 0
+ Layout.preferredWidth: 20
+ Layout.preferredHeight: 20
+ Layout.maximumWidth: 40
+ Layout.maximumHeight: 40
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ }
+ Rectangle {
+ // (0,1)
+ id: r1
+ color: "black"
+ Layout.row: 0
+ Layout.column: 1
+ Layout.columnSpan: 2
+ Layout.rowSpan: 2
+ Layout.preferredWidth: 20
+ Layout.preferredHeight: 20
+ Layout.maximumWidth: 40
+ Layout.maximumHeight: 40
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ }
+ Rectangle {
+ // (0,99)
+ id: r2
+ color: "black"
+ Layout.row: 0
+ Layout.column: 99
+ Layout.preferredWidth: 20
+ Layout.preferredHeight: 20
+ Layout.maximumWidth: 40
+ Layout.maximumHeight: 40
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ }
+ }
+ }
+
+ function test_spanAcrossEmptyRows() {
+ var layout = layout_spanAcrossEmptyRows_Component.createObject(container);
+ compare(layout.children[0].x, 0);
+ compare(layout.children[0].y, 0);
+ compare(layout.children[1].x, 20);
+ compare(layout.children[1].y, 0);
+ compare(layout.children[2].x, 40);
+ compare(layout.children[2].y, 0);
+
+ compare(layout.implicitWidth, 60);
+ compare(layout.Layout.maximumWidth, 120);
+
+ layout.destroy();
+ }
+
+ Component {
+ id: layout_spanIsMoreThanColumns_Component
+
+ GridLayout {
+ columnSpacing: 1
+ rowSpacing: 1
+ columns: 2
+
+ Rectangle {
+ implicitWidth: 10
+ implicitHeight: 10
+ Layout.columnSpan: 3
+ }
+ }
+ }
+
+ function test_spanIsMoreThanColumns() {
+ var layout = layout_spanIsMoreThanColumns_Component.createObject(container);
+ // item was not added, therefore implicit width is 0
+ compare(layout.implicitWidth, 0);
+ layout.destroy();
+ }
+
+ function test_sizeHints() {
+ var layout = layout_spanAcrossEmptyRows_Component.createObject(container);
+ compare(layout.visible, true)
+
+ var minWidth = layout.Layout.minimumWidth
+ var minHeight = layout.Layout.minimumHeight
+
+ var prefWidth = layout.implicitWidth
+ var prefHeight = layout.implicitHeight
+
+ var maxWidth = layout.Layout.maximumWidth
+ var maxHeight = layout.Layout.maximumHeight
+
+ layout.visible = false
+ compare(minWidth, layout.Layout.minimumWidth)
+ compare(minHeight, layout.Layout.minimumHeight)
+ compare(prefWidth, layout.implicitWidth)
+ compare(prefHeight, layout.implicitHeight)
+ compare(maxWidth, layout.Layout.maximumWidth)
+ compare(maxHeight, layout.Layout.maximumHeight)
+
+ layout.destroy();
+ }
+
+ Component {
+ id: layout_alignment_Component
+ GridLayout {
+ columns: 2
+ columnSpacing: 0
+ rowSpacing: 0
+ Rectangle {
+ // First one should auto position itself at (0,0)
+ property var itemRect: [x, y, width, height]
+ color: "red"
+ Layout.preferredWidth: 20
+ Layout.preferredHeight: 20
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ }
+ Rectangle {
+ // (0,1)
+ property var itemRect: [x, y, width, height]
+ color: "red"
+ Layout.preferredWidth: 20
+ Layout.preferredHeight: 20
+ Layout.alignment: Qt.AlignBottom
+ }
+ Rectangle {
+ // (1,0)
+ property var itemRect: [x, y, width, height]
+ color: "red"
+ Layout.preferredWidth: 20
+ Layout.preferredHeight: 20
+ Layout.alignment: Qt.AlignRight
+ }
+ Rectangle {
+ // (1,1)
+ property var itemRect: [x, y, width, height]
+ color: "red"
+ Layout.preferredWidth: 10
+ Layout.preferredHeight: 10
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
+ }
+ Rectangle {
+ // (2,0)
+ property var itemRect: [x, y, width, height]
+ color: "red"
+ Layout.preferredWidth: 30
+ Layout.preferredHeight: 30
+ Layout.alignment: Qt.AlignRight
+ Layout.columnSpan: 2
+ }
+ Rectangle {
+ // (3,0)
+ property var itemRect: [x, y, width, height]
+ baselineOffset: 7
+ color: "red"
+ Layout.row: 3
+ Layout.column: 0
+ Layout.preferredWidth: 10
+ Layout.preferredHeight: 10
+ Layout.alignment: Qt.AlignLeft | Qt.AlignBaseline
+ }
+ Rectangle {
+ // (3,1)
+ property var itemRect: [x, y, width, height]
+ baselineOffset: 7
+ color: "red"
+ Layout.preferredWidth: 10
+ Layout.preferredHeight: 10
+ Layout.alignment: Qt.AlignRight | Qt.AlignBaseline
+ }
+
+ }
+ }
+
+ function test_alignment()
+ {
+ var layout = layout_alignment_Component.createObject(container);
+ layout.width = 60;
+ layout.height = 100;
+
+
+ tryCompare(layout.children[0], "itemRect", [ 0, 0, 40, 40]);
+ tryCompare(layout.children[1], "itemRect", [40, 20, 20, 20]);
+ tryCompare(layout.children[2], "itemRect", [20, 40, 20, 20]);
+ tryCompare(layout.children[3], "itemRect", [45, 40, 10, 10]);
+ tryCompare(layout.children[4], "itemRect", [30, 60, 30, 30]);
+ tryCompare(layout.children[5], "itemRect", [ 0, 90, 10, 10]);
+ tryCompare(layout.children[6], "itemRect", [50, 90, 10, 10]);
+
+
+ layout.children[1].Layout.alignment = Qt.AlignTop
+ tryCompare(layout.children[1], "x", 40);
+ tryCompare(layout.children[1], "y", 0);
+
+ layout.children[2].Layout.alignment = Qt.AlignLeft
+ tryCompare(layout.children[2], "x", 0);
+ tryCompare(layout.children[2], "y", 40);
+
+ layout.children[3].Layout.alignment = Qt.AlignLeft|Qt.AlignVCenter
+ tryCompare(layout.children[3], "x", 40);
+ tryCompare(layout.children[3], "y", 45);
+
+ layout.children[4].Layout.alignment = Qt.AlignLeft
+ tryCompare(layout.children[4], "x", 0);
+ tryCompare(layout.children[4], "y", 60);
+
+ layout.destroy();
+ }
+
+
+ Component {
+ id: layout_rightToLeft_Component
+ GridLayout {
+ layoutDirection: Qt.RightToLeft
+ columnSpacing: 0
+ rowSpacing: 0
+ columns: 3
+ Rectangle {
+ property var itemRect: [x, y, width, height]
+ color: "#cbffc4"
+ Layout.preferredWidth: 50
+ Layout.preferredHeight: 50
+ Layout.alignment: Qt.AlignCenter
+ }
+ Rectangle {
+ property var itemRect: [x, y, width, height]
+ color: "#c4d1ff"
+ Layout.preferredWidth: 50
+ Layout.preferredHeight: 50
+ Layout.alignment: Qt.AlignRight
+ }
+ Rectangle {
+ property var itemRect: [x, y, width, height]
+ color: "#ffd5c4"
+ Layout.preferredWidth: 50
+ Layout.preferredHeight: 50
+ Layout.alignment: Qt.AlignLeft
+ }
+ }
+ }
+
+ function verifyIsRightToLeft(layout)
+ {
+ tryCompare(layout.children[0], "itemRect", [125, 0, 50, 50]);
+ tryCompare(layout.children[1], "itemRect", [60, 0, 50, 50]);
+ tryCompare(layout.children[2], "itemRect", [10, 0, 50, 50]);
+ }
+
+ function verifyIsLeftToRight(layout)
+ {
+ tryCompare(layout.children[0], "itemRect", [5, 0, 50, 50]);
+ tryCompare(layout.children[1], "itemRect", [70, 0, 50, 50]);
+ tryCompare(layout.children[2], "itemRect", [120, 0, 50, 50]);
+ }
+
+ function test_rightToLeft()
+ {
+ var layout = layout_rightToLeft_Component.createObject(container);
+ layout.width = 180;
+ layout.height = 50;
+
+ // Right To Left
+ verifyIsRightToLeft(layout)
+ layout.LayoutMirroring.enabled = true
+ layout.layoutDirection = Qt.LeftToRight
+ verifyIsRightToLeft(layout)
+
+ // Left To Right
+ layout.LayoutMirroring.enabled = false
+ layout.layoutDirection = Qt.LeftToRight
+ verifyIsLeftToRight(layout);
+ layout.LayoutMirroring.enabled = true
+ layout.layoutDirection = Qt.RightToLeft
+ verifyIsLeftToRight(layout);
+
+ layout.LayoutMirroring.enabled = false
+ verifyIsRightToLeft(layout)
+
+ layout.layoutDirection = Qt.LeftToRight
+ verifyIsLeftToRight(layout);
+
+ layout.LayoutMirroring.enabled = true
+ verifyIsRightToLeft(layout)
+
+ layout.destroy();
+ }
+
+ Component {
+ id: layout_columnsOrRowsChanged_Component
+ GridLayout {
+ id: layout
+ rowSpacing: 0
+ columnSpacing: 0
+ Repeater {
+ model: 4
+ Rectangle {
+ property var itemRect: [x, y, width, height]
+ width: 10
+ height: 10
+ color: "#ff0000"
+ }
+ }
+ }
+ }
+
+ function test_columnsChanged()
+ {
+ var layout = layout_columnsOrRowsChanged_Component.createObject(container);
+ layout.width = 40;
+ layout.height = 20;
+ tryCompare(layout.children[0], "itemRect", [ 0, 5, 10, 10])
+ tryCompare(layout.children[1], "itemRect", [10, 5, 10, 10])
+ tryCompare(layout.children[2], "itemRect", [20, 5, 10, 10])
+ tryCompare(layout.children[3], "itemRect", [30, 5, 10, 10])
+
+ layout.columns = 2
+ tryCompare(layout.children[0], "itemRect", [ 0, 0, 10, 10])
+ tryCompare(layout.children[1], "itemRect", [20, 0, 10, 10])
+ tryCompare(layout.children[2], "itemRect", [ 0, 10, 10, 10])
+ tryCompare(layout.children[3], "itemRect", [20, 10, 10, 10])
+
+ layout.destroy()
+ }
+
+ function test_rowsChanged()
+ {
+ var layout = layout_columnsOrRowsChanged_Component.createObject(container);
+ layout.flow = GridLayout.TopToBottom
+ layout.width = 20;
+ layout.height = 40;
+ tryCompare(layout.children[0], "itemRect", [ 0, 0, 10, 10])
+ tryCompare(layout.children[1], "itemRect", [ 0, 10, 10, 10])
+ tryCompare(layout.children[2], "itemRect", [ 0, 20, 10, 10])
+ tryCompare(layout.children[3], "itemRect", [ 0, 30, 10, 10])
+
+ layout.rows = 2
+ tryCompare(layout.children[0], "itemRect", [ 0, 5, 10, 10])
+ tryCompare(layout.children[1], "itemRect", [ 0, 25, 10, 10])
+ tryCompare(layout.children[2], "itemRect", [10, 5, 10, 10])
+ tryCompare(layout.children[3], "itemRect", [10, 25, 10, 10])
+
+ layout.destroy()
+ }
+
+ Component {
+ id: layout_columnOrRowChanged_Component
+ GridLayout {
+ id: layout
+ rowSpacing: 0
+ columnSpacing: 0
+ Rectangle {
+ property var itemRect: [x, y, width, height]
+ width: 10
+ height: 10
+ Layout.column: 0
+ color: "#ff0000"
+ }
+ Rectangle {
+ property var itemRect: [x, y, width, height]
+ Layout.column: 1
+ width: 10
+ height: 10
+ color: "#ff0000"
+ }
+ Rectangle {
+ property var itemRect: [x, y, width, height]
+ //Layout.column: 2
+ width: 10
+ height: 10
+ color: "#ff0000"
+ }
+ }
+ }
+
+ function test_columnOrRowChanged()
+ {
+ var layout = layout_columnOrRowChanged_Component.createObject(container);
+ layout.width = layout.implicitWidth
+ layout.height = layout.implicitHeight
+ // c0-c1-c2
+ tryCompare(layout.children[0], "itemRect", [ 0, 0, 10, 10])
+ tryCompare(layout.children[1], "itemRect", [10, 0, 10, 10])
+ tryCompare(layout.children[2], "itemRect", [20, 0, 10, 10])
+
+ layout.children[0].Layout.column = 3
+ //c1-c2-c0
+ tryCompare(layout.children[0], "itemRect", [20, 0, 10, 10])
+ tryCompare(layout.children[1], "itemRect", [ 0, 0, 10, 10])
+ tryCompare(layout.children[2], "itemRect", [10, 0, 10, 10])
+
+ layout.children[2].Layout.column = 4
+ //c1-c0-c2
+ tryCompare(layout.children[0], "itemRect", [10, 0, 10, 10])
+ tryCompare(layout.children[1], "itemRect", [ 0, 0, 10, 10])
+ tryCompare(layout.children[2], "itemRect", [20, 0, 10, 10])
+
+ layout.children[0].Layout.row = 1
+ // two rows, so we adjust it to its new implicitHeight
+ layout.height = layout.implicitHeight
+ //c1 c2
+ // c0
+ tryCompare(layout.children[0], "itemRect", [10, 10, 10, 10])
+ tryCompare(layout.children[1], "itemRect", [ 0, 0, 10, 10])
+ tryCompare(layout.children[2], "itemRect", [20, 0, 10, 10])
+
+ layout.destroy()
+ }
+
+ Component {
+ id: layout_baselines_Component
+ GridLayout {
+ id: layout
+ columnSpacing: 0
+ Rectangle {
+ property var itemRect: [x, y, width, height]
+ implicitWidth: 10
+ implicitHeight: 10
+ baselineOffset: 10
+ }
+ Rectangle {
+ property var itemRect: [x, y, width, height]
+ implicitWidth: 10
+ implicitHeight: 10
+ }
+ }
+ }
+ function test_baselines()
+ {
+ var layout = layout_baselines_Component.createObject(container);
+ tryCompare(layout.children[0], "itemRect", [ 0, 0, 10, 10])
+ tryCompare(layout.children[1], "itemRect", [10, 0, 10, 10])
+ compare(layout.implicitWidth, 20)
+ compare(layout.implicitHeight, 10)
+
+ layout.children[0].Layout.alignment = Qt.AlignBaseline
+ layout.children[1].Layout.alignment = Qt.AlignBaseline
+
+ tryCompare(layout.children[0], "itemRect", [ 0, 0, 10, 10])
+ tryCompare(layout.children[1], "itemRect", [10, 10, 10, 10])
+ compare(layout.implicitWidth, 20)
+ compare(layout.implicitHeight, 20)
+
+ layout.destroy();
+ }
+
+ Component {
+ id: layout_spacings_Component
+ GridLayout {
+ id: layout
+ Repeater {
+ model: 2
+ Rectangle {
+ property var itemRect: [x, y, width, height]
+ implicitWidth: 10
+ implicitHeight: 10
+ }
+ }
+ }
+ }
+
+ function test_spacings()
+ {
+ var layout = layout_spacings_Component.createObject(container);
+
+ // breaks down below -19. This is acceptable, since it means that the implicit size of the layout is negative
+ var testSpacings = [Number.NaN, 0, 10, -5, -19]
+ layout.rowSpacing = 0
+ for (var i = 0; i < testSpacings.length; ++i) {
+ var sp = testSpacings[i]
+ if (isNaN(sp)) {
+ sp = 5 // Test defaults
+ } else {
+ layout.columnSpacing = sp
+ }
+ tryCompare(layout.children[0], "itemRect", [ 0, 0, 10, 10])
+ tryCompare(layout.children[1], "itemRect", [10 + sp, 0, 10, 10])
+ compare(layout.implicitWidth, 20 + sp)
+ }
+
+ // do not crash
+ layout.columnSpacing = -100
+ waitForRendering(layout)
+ verify(isFinite(layout.implicitWidth))
+ layout.destroy();
+ }
+
+ Component {
+ id: layout_alignToPixelGrid_Component
+ GridLayout {
+ columns: 3
+ rowSpacing: 0
+ columnSpacing: 2
+ Repeater {
+ model: 3*3
+ Rectangle {
+ color: "red"
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ }
+ }
+ }
+ }
+
+ function test_alignToPixelGrid()
+ {
+ var layout = layout_alignToPixelGrid_Component.createObject(container)
+ layout.width = 30
+ layout.height = 28
+
+ var rectWidth = (layout.width - 2 * layout.columnSpacing)/3
+ var rectHeight = layout.height/3
+
+ waitForRendering(layout);
+
+ var sp = layout.columnSpacing
+ var idealGeom = [0,0,rectWidth,rectHeight]
+ for (var r = 0; r < 3; ++r) {
+ idealGeom[0] = 0
+ idealGeom[2] = rectWidth
+ for (var c = 0; c < 3; ++c) {
+ var child = layout.children[3*r + c]
+ var visualGeom = [child.x, child.y, child.x + child.width, child.y + child.height]
+
+ // verify that visualGeom is an integer number
+ for (var i = 0; i < 2; ++i)
+ compare(visualGeom[i] % 1, 0)
+
+ // verify that x,y is no more than one pixel from idealGeom
+ fuzzyCompare(visualGeom[0], idealGeom[0], 1)
+ fuzzyCompare(visualGeom[1], idealGeom[1], 1)
+
+ // verify that the visual size is no more than 1 pixel taller/wider than the ideal size.
+ verify(visualGeom[2] <= idealGeom[2] + 1)
+ verify(visualGeom[3] <= idealGeom[3] + 1)
+ idealGeom[0] = idealGeom[2] + sp
+ idealGeom[2] = idealGeom[0] + rectWidth
+ }
+ idealGeom[1] = idealGeom[3]
+ idealGeom[3] = idealGeom[1] + rectHeight
+ }
+
+ layout.destroy()
+ }
+
+ Component {
+
+ id: layout_Margins_Component
+ GridLayout {
+ columns: 2
+ rowSpacing: 0
+ columnSpacing: 0
+ Rectangle {
+ color: "red"
+ Layout.preferredWidth: 20
+ Layout.preferredHeight: 20
+ Layout.margins: 10
+ Layout.leftMargin: 2
+ Layout.topMargin: 3
+ Layout.rightMargin: 4
+ Layout.bottomMargin: 4
+ }
+ Rectangle {
+ color: "red"
+ Layout.preferredWidth: 20
+ Layout.preferredHeight: 20
+ Layout.leftMargin: 4
+ Layout.topMargin: 5
+ Layout.rightMargin: 6
+ Layout.bottomMargin: 6
+ }
+ Rectangle {
+ color: "red"
+ Layout.preferredWidth: 20
+ Layout.preferredHeight: 20
+ Layout.leftMargin: 3
+ Layout.topMargin: 4
+ Layout.rightMargin: 5
+ Layout.bottomMargin: 5
+ }
+ }
+ }
+
+ function test_Margins()
+ {
+ var layout = layout_Margins_Component.createObject(container)
+
+ compare(layout.implicitWidth, 3 + 20 + 5 + 4 + 20 + 6)
+ compare(layout.implicitHeight, 5 + 20 + 6 + 4 + 20 + 5)
+ layout.width = layout.implicitWidth
+ layout.height = layout.implicitHeight
+
+ waitForRendering(layout)
+
+ var c0 = layout.children[0]
+ var c1 = layout.children[1]
+ var c2 = layout.children[2]
+
+ compare(c0.x, 2)
+ compare(c0.y, 5)
+ compare(c1.x, 3 + 20 + 5 + 4)
+ compare(c1.y, 5)
+ compare(c2.x, 3)
+ compare(c2.y, 5 + 20 + 6 + 4)
+
+ // reset left|rightMargin. It should then use the generic "margins" property
+ c0.Layout.leftMargin = undefined
+ compare(layout.implicitWidth, 10 + 20 + 4 + 4 + 20 + 6)
+ c0.Layout.bottomMargin = undefined
+ compare(layout.implicitHeight, 3 + 20 + 10 + 4 + 20 + 5)
+ }
+
+ Component {
+ id: layout_invalidateWhileRearranging_Component
+
+ GridLayout {
+ columns: 1
+ Rectangle {
+ height: 50
+ Layout.fillWidth: true
+ color: 'blue'
+ }
+
+ Rectangle {
+ height: 50
+ Layout.fillWidth: true
+ color: 'red'
+ onYChanged: {
+ visible = false;
+ }
+ }
+ }
+ }
+
+ function test_invalidateWhileRearranging_QTBUG_44139()
+ {
+ var layout = layout_invalidateWhileRearranging_Component.createObject(container)
+
+ waitForRendering(layout);
+ verify(layout.children[1].visible == false);
+ layout.destroy()
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml b/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml
new file mode 100644
index 0000000000..4b47b396a3
--- /dev/null
+++ b/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml
@@ -0,0 +1,921 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+import QtQuick.Layouts 1.0
+
+Item {
+ id: container
+ width: 200
+ height: 200
+ TestCase {
+ id: testCase
+ name: "Tests_RowLayout"
+ when: windowShown
+ width: 200
+ height: 200
+
+ function itemRect(item)
+ {
+ return [item.x, item.y, item.width, item.height];
+ }
+
+ function test_fixedAndExpanding() {
+ var test_layoutStr =
+ 'import QtQuick 2.2; \
+ import QtQuick.Layouts 1.0; \
+ RowLayout { \
+ id: row; \
+ width: 15; \
+ spacing: 0; \
+ property alias r1: _r1; \
+ Rectangle { \
+ id: _r1; \
+ width: 5; \
+ height: 10; \
+ color: "#8080ff"; \
+ Layout.fillWidth: false \
+ } \
+ property alias r2: _r2; \
+ Rectangle { \
+ id: _r2; \
+ width: 10; \
+ height: 20; \
+ color: "#c0c0ff"; \
+ Layout.fillWidth: true \
+ } \
+ } '
+
+ var lay = Qt.createQmlObject(test_layoutStr, container, '');
+ tryCompare(lay, 'implicitWidth', 15);
+ compare(lay.implicitHeight, 20);
+ compare(lay.height, 20);
+ lay.width = 30
+ compare(lay.r1.x, 0);
+ compare(lay.r1.width, 5);
+ compare(lay.r2.x, 5);
+ compare(lay.r2.width, 25);
+ lay.destroy()
+ }
+
+ function test_allExpanding() {
+ var test_layoutStr =
+ 'import QtQuick 2.2; \
+ import QtQuick.Layouts 1.0; \
+ RowLayout { \
+ id: row; \
+ width: 15; \
+ spacing: 0; \
+ property alias r1: _r1; \
+ Rectangle { \
+ id: _r1; \
+ width: 5; \
+ height: 10; \
+ color: "#8080ff"; \
+ Layout.fillWidth: true \
+ } \
+ property alias r2: _r2; \
+ Rectangle { \
+ id: _r2; \
+ width: 10; \
+ height: 20; \
+ color: "#c0c0ff"; \
+ Layout.fillWidth: true \
+ } \
+ } '
+
+ var tmp = Qt.createQmlObject(test_layoutStr, container, '');
+ tryCompare(tmp, 'implicitWidth', 15);
+ compare(tmp.implicitHeight, 20);
+ compare(tmp.height, 20);
+ tmp.width = 30
+ compare(tmp.r1.width, 10);
+ compare(tmp.r2.width, 20);
+ compare(tmp.Layout.minimumWidth, 0)
+ compare(tmp.Layout.maximumWidth, Number.POSITIVE_INFINITY)
+ tmp.destroy()
+ }
+
+ function test_initialNestedLayouts() {
+ var test_layoutStr =
+ 'import QtQuick 2.2; \
+ import QtQuick.Layouts 1.0; \
+ ColumnLayout { \
+ id : col; \
+ property alias row: _row; \
+ objectName: "col"; \
+ anchors.fill: parent; \
+ RowLayout { \
+ id : _row; \
+ property alias r1: _r1; \
+ property alias r2: _r2; \
+ objectName: "row"; \
+ spacing: 0; \
+ Rectangle { \
+ id: _r1; \
+ color: "red"; \
+ implicitWidth: 50; \
+ implicitHeight: 20; \
+ } \
+ Rectangle { \
+ id: _r2; \
+ color: "green"; \
+ implicitWidth: 50; \
+ implicitHeight: 20; \
+ Layout.fillWidth: true; \
+ } \
+ } \
+ } '
+ var col = Qt.createQmlObject(test_layoutStr, container, '');
+ tryCompare(col, 'width', 200);
+ tryCompare(col.row, 'width', 200);
+ tryCompare(col.row.r1, 'width', 50);
+ tryCompare(col.row.r2, 'width', 150);
+ col.destroy()
+ }
+
+ function test_implicitSize() {
+ var test_layoutStr =
+ 'import QtQuick 2.2; \
+ import QtQuick.Layouts 1.0; \
+ RowLayout { \
+ id: row; \
+ objectName: "row"; \
+ spacing: 0; \
+ height: 30; \
+ anchors.left: parent.left; \
+ anchors.right: parent.right; \
+ Rectangle { \
+ color: "red"; \
+ height: 2; \
+ Layout.minimumWidth: 50; \
+ } \
+ Rectangle { \
+ color: "green"; \
+ width: 10; \
+ Layout.minimumHeight: 4; \
+ } \
+ Rectangle { \
+ implicitWidth: 1000; \
+ Layout.maximumWidth: 40; \
+ implicitHeight: 6 \
+ } \
+ } '
+ var row = Qt.createQmlObject(test_layoutStr, container, '');
+ compare(row.implicitWidth, 50 + 10 + 40);
+ compare(row.implicitHeight, 6);
+ row.destroy()
+ }
+
+ function test_countGeometryChanges() {
+ var test_layoutStr =
+ 'import QtQuick 2.2; \
+ import QtQuick.Layouts 1.0; \
+ ColumnLayout { \
+ id : col; \
+ property alias row: _row; \
+ objectName: "col"; \
+ anchors.fill: parent; \
+ RowLayout { \
+ id : _row; \
+ property alias r1: _r1; \
+ property alias r2: _r2; \
+ objectName: "row"; \
+ spacing: 0; \
+ property int counter : 0; \
+ onWidthChanged: { ++counter; } \
+ Rectangle { \
+ id: _r1; \
+ color: "red"; \
+ implicitWidth: 50; \
+ implicitHeight: 20; \
+ property int counter : 0; \
+ onWidthChanged: { ++counter; } \
+ Layout.fillWidth: true; \
+ } \
+ Rectangle { \
+ id: _r2; \
+ color: "green"; \
+ implicitWidth: 50; \
+ implicitHeight: 20; \
+ property int counter : 0; \
+ onWidthChanged: { ++counter; } \
+ Layout.fillWidth: true; \
+ } \
+ } \
+ } '
+ var col = Qt.createQmlObject(test_layoutStr, container, '');
+ compare(col.width, 200);
+ compare(col.row.width, 200);
+ compare(col.row.r1.width, 100);
+ compare(col.row.r2.width, 100);
+ compare(col.row.r1.counter, 1);
+ compare(col.row.r2.counter, 1);
+ verify(col.row.counter <= 2);
+ col.destroy()
+ }
+
+ Component {
+ id: layoutItem_Component
+ Rectangle {
+ implicitWidth: 20
+ implicitHeight: 20
+ }
+ }
+
+ Component {
+ id: columnLayoutItem_Component
+ ColumnLayout {
+ spacing: 0
+ }
+ }
+
+ Component {
+ id: layout_addAndRemoveItems_Component
+ RowLayout {
+ spacing: 0
+ }
+ }
+
+ function test_addAndRemoveItems()
+ {
+ var layout = layout_addAndRemoveItems_Component.createObject(container)
+ compare(layout.implicitWidth, 0)
+ compare(layout.implicitHeight, 0)
+
+ var rect0 = layoutItem_Component.createObject(layout)
+ compare(layout.implicitWidth, 20)
+ compare(layout.implicitHeight, 20)
+
+ var rect1 = layoutItem_Component.createObject(layout)
+ rect1.Layout.preferredWidth = 30;
+ rect1.Layout.preferredHeight = 30;
+ compare(layout.implicitWidth, 50)
+ compare(layout.implicitHeight, 30)
+
+ var col = columnLayoutItem_Component.createObject(layout)
+ var rect2 = layoutItem_Component.createObject(col)
+ rect2.Layout.fillHeight = true
+ var rect3 = layoutItem_Component.createObject(col)
+ rect3.Layout.fillHeight = true
+
+ compare(layout.implicitWidth, 70)
+ compare(col.implicitHeight, 40)
+ compare(layout.implicitHeight, 40)
+
+ rect3.destroy()
+ wait(0) // this will hopefully effectuate the destruction of the object
+
+ col.destroy()
+ wait(0)
+ compare(layout.implicitWidth, 50)
+ compare(layout.implicitHeight, 30)
+
+ rect0.destroy()
+ wait(0)
+ compare(layout.implicitWidth, 30)
+ compare(layout.implicitHeight, 30)
+
+ rect1.destroy()
+ wait(0)
+ compare(layout.implicitWidth, 0)
+ compare(layout.implicitHeight, 0)
+
+ layout.destroy()
+ }
+
+ Component {
+ id: layout_alignment_Component
+ RowLayout {
+ spacing: 0
+ Rectangle {
+ color: "red"
+ Layout.preferredWidth: 20
+ Layout.preferredHeight: 20
+ Layout.fillHeight: true
+ }
+ Rectangle {
+ color: "red"
+ Layout.preferredWidth: 20
+ Layout.preferredHeight: 20
+ // use default alignment
+ }
+ Rectangle {
+ color: "red"
+ Layout.preferredWidth: 20
+ Layout.preferredHeight: 20
+ Layout.alignment: Qt.AlignTop
+ }
+ Rectangle {
+ color: "red"
+ Layout.preferredWidth: 20
+ Layout.preferredHeight: 20
+ Layout.alignment: Qt.AlignVCenter
+ }
+ Rectangle {
+ color: "red"
+ Layout.preferredWidth: 20
+ Layout.preferredHeight: 20
+ Layout.alignment: Qt.AlignBottom
+ }
+ }
+ }
+
+ function test_alignment()
+ {
+ var layout = layout_alignment_Component.createObject(container);
+ layout.width = 100;
+ layout.height = 40;
+
+ compare(itemRect(layout.children[0]), [ 0, 0, 20, 40]);
+ compare(itemRect(layout.children[1]), [20, 10, 20, 20]);
+ compare(itemRect(layout.children[2]), [40, 0, 20, 20]);
+ compare(itemRect(layout.children[3]), [60, 10, 20, 20]);
+ compare(itemRect(layout.children[4]), [80, 20, 20, 20]);
+ layout.destroy();
+ }
+
+ Component {
+ id: layout_sizeHintNormalization_Component
+ GridLayout {
+ columnSpacing: 0
+ rowSpacing: 0
+ Rectangle {
+ id: r1
+ color: "red"
+ Layout.minimumWidth: 1
+ Layout.preferredWidth: 2
+ Layout.maximumWidth: 3
+
+ Layout.minimumHeight: 20
+ Layout.preferredHeight: 20
+ Layout.maximumHeight: 20
+ Layout.fillWidth: true
+ }
+ }
+ }
+
+ function test_sizeHintNormalization_data() {
+ return [
+ { tag: "fallbackValues", widthHints: [-1, -1, -1], implicitWidth: 42, expected:[0,42,Number.POSITIVE_INFINITY]},
+ { tag: "acceptZeroWidths", widthHints: [0, 0, 0], implicitWidth: 42, expected:[0,0,0]},
+ { tag: "123", widthHints: [1,2,3], expected:[1,2,3]},
+ { tag: "132", widthHints: [1,3,2], expected:[1,2,2]},
+ { tag: "213", widthHints: [2,1,3], expected:[2,2,3]},
+ { tag: "231", widthHints: [2,3,1], expected:[1,1,1]},
+ { tag: "321", widthHints: [3,2,1], expected:[1,1,1]},
+ { tag: "312", widthHints: [3,1,2], expected:[2,2,2]},
+
+ { tag: "1i3", widthHints: [1,-1,3], implicitWidth: 2, expected:[1,2,3]},
+ { tag: "1i2", widthHints: [1,-1,2], implicitWidth: 3, expected:[1,2,2]},
+ { tag: "2i3", widthHints: [2,-1,3], implicitWidth: 1, expected:[2,2,3]},
+ { tag: "2i1", widthHints: [2,-1,1], implicitWidth: 3, expected:[1,1,1]},
+ { tag: "3i1", widthHints: [3,-1,1], implicitWidth: 2, expected:[1,1,1]},
+ { tag: "3i2", widthHints: [3,-1,2], implicitWidth: 1, expected:[2,2,2]},
+ ];
+ }
+
+ function test_sizeHintNormalization(data) {
+ var layout = layout_sizeHintNormalization_Component.createObject(container);
+ if (data.implicitWidth !== undefined) {
+ layout.children[0].implicitWidth = data.implicitWidth
+ }
+ layout.children[0].Layout.minimumWidth = data.widthHints[0];
+ layout.children[0].Layout.preferredWidth = data.widthHints[1];
+ layout.children[0].Layout.maximumWidth = data.widthHints[2];
+ wait(0); // Trigger processEvents() (allow LayoutRequest to be processed)
+ var normalizedResult = [layout.Layout.minimumWidth, layout.implicitWidth, layout.Layout.maximumWidth]
+ compare(normalizedResult, data.expected);
+ layout.destroy();
+ }
+
+ Component {
+ id: layout_sizeHint_Component
+ RowLayout {
+ property int implicitWidthChangedCount : 0
+ onImplicitWidthChanged: { ++implicitWidthChangedCount }
+ GridLayout {
+ columnSpacing: 0
+ rowSpacing: 0
+ Rectangle {
+ id: r1
+ color: "red"
+ Layout.minimumWidth: 1
+ Layout.preferredWidth: 2
+ Layout.maximumWidth: 3
+
+ Layout.minimumHeight: 20
+ Layout.preferredHeight: 20
+ Layout.maximumHeight: 20
+ Layout.fillWidth: true
+ }
+ }
+ }
+ }
+
+ function test_sizeHint_data() {
+ return [
+ { tag: "propagateNone", layoutHints: [10, 20, 30], childHints: [11, 21, 31], expected:[10, 20, 30]},
+ { tag: "propagateMinimumWidth", layoutHints: [-1, 20, 30], childHints: [10, 21, 31], expected:[10, 20, 30]},
+ { tag: "propagatePreferredWidth", layoutHints: [10, -1, 30], childHints: [11, 20, 31], expected:[10, 20, 30]},
+ { tag: "propagateMaximumWidth", layoutHints: [10, 20, -1], childHints: [11, 21, 30], expected:[10, 20, 30]},
+ { tag: "propagateAll", layoutHints: [-1, -1, -1], childHints: [10, 20, 30], expected:[10, 20, 30]},
+ { tag: "propagateCrazy", layoutHints: [-1, -1, -1], childHints: [40, 21, 30], expected:[30, 30, 30]},
+ { tag: "expandMinToExplicitPref", layoutHints: [-1, 1, -1], childHints: [11, 21, 31], expected:[ 1, 1, 31]},
+ { tag: "expandMaxToExplicitPref", layoutHints: [-1, 99, -1], childHints: [11, 21, 31], expected:[11, 99, 99]},
+ { tag: "expandAllToExplicitMin", layoutHints: [99, -1, -1], childHints: [11, 21, 31], expected:[99, 99, 99]},
+ { tag: "expandPrefToExplicitMin", layoutHints: [24, -1, -1], childHints: [11, 21, 31], expected:[24, 24, 31]},
+ { tag: "boundPrefToExplicitMax", layoutHints: [-1, -1, 19], childHints: [11, 21, 31], expected:[11, 19, 19]},
+ { tag: "boundAllToExplicitMax", layoutHints: [-1, -1, 9], childHints: [11, 21, 31], expected:[ 9, 9, 9]},
+ ];
+ }
+
+ function itemSizeHints(item) {
+ return [item.Layout.minimumWidth, item.implicitWidth, item.Layout.maximumWidth]
+ }
+
+ function test_sizeHint(data) {
+ var layout = layout_sizeHint_Component.createObject(container)
+
+ var grid = layout.children[0]
+ grid.Layout.minimumWidth = data.layoutHints[0]
+ grid.Layout.preferredWidth = data.layoutHints[1]
+ grid.Layout.maximumWidth = data.layoutHints[2]
+
+ var child = grid.children[0]
+ if (data.implicitWidth !== undefined) {
+ child.implicitWidth = data.implicitWidth
+ }
+ child.Layout.minimumWidth = data.childHints[0]
+ child.Layout.preferredWidth = data.childHints[1]
+ child.Layout.maximumWidth = data.childHints[2]
+
+ var effectiveSizeHintResult = [layout.Layout.minimumWidth, layout.implicitWidth, layout.Layout.maximumWidth]
+ compare(effectiveSizeHintResult, data.expected)
+ layout.destroy()
+ }
+
+ function test_sizeHintPropagationCount() {
+ var layout = layout_sizeHint_Component.createObject(container)
+ var child = layout.children[0].children[0]
+
+ child.Layout.minimumWidth = -1
+ compare(itemSizeHints(layout), [0, 2, 3])
+ child.Layout.preferredWidth = -1
+ compare(itemSizeHints(layout), [0, 0, 3])
+ child.Layout.maximumWidth = -1
+ compare(itemSizeHints(layout), [0, 0, Number.POSITIVE_INFINITY])
+ layout.Layout.maximumWidth = 1000
+ compare(itemSizeHints(layout), [0, 0, 1000])
+ layout.Layout.maximumWidth = -1
+ compare(itemSizeHints(layout), [0, 0, Number.POSITIVE_INFINITY])
+
+ layout.implicitWidthChangedCount = 0
+ child.Layout.minimumWidth = 10
+ compare(itemSizeHints(layout), [10, 10, Number.POSITIVE_INFINITY])
+ compare(layout.implicitWidthChangedCount, 1)
+
+ child.Layout.preferredWidth = 20
+ compare(itemSizeHints(layout), [10, 20, Number.POSITIVE_INFINITY])
+ compare(layout.implicitWidthChangedCount, 2)
+
+ child.Layout.maximumWidth = 30
+ compare(itemSizeHints(layout), [10, 20, 30])
+ compare(layout.implicitWidthChangedCount, 2)
+
+ child.Layout.maximumWidth = 15
+ compare(itemSizeHints(layout), [10, 15, 15])
+ compare(layout.implicitWidthChangedCount, 3)
+
+ child.Layout.maximumWidth = 30
+ compare(itemSizeHints(layout), [10, 20, 30])
+ compare(layout.implicitWidthChangedCount, 4)
+
+ layout.Layout.maximumWidth = 29
+ compare(layout.Layout.maximumWidth, 29)
+ layout.Layout.maximumWidth = -1
+ compare(layout.Layout.maximumWidth, 30)
+
+ layout.destroy()
+ }
+
+ Component {
+ id: layout_change_implicitWidth_during_rearrange
+ ColumnLayout {
+ width: 100
+ height: 20
+ RowLayout {
+ spacing: 0
+ Rectangle {
+ Layout.fillHeight: true
+ Layout.fillWidth: false
+ implicitWidth: height
+ color: "red"
+ }
+ Rectangle {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ color: "blue"
+ }
+ }
+ }
+ }
+
+ function test_change_implicitWidth_during_rearrange() {
+ var layout = layout_change_implicitWidth_during_rearrange.createObject(container)
+ var red = layout.children[0].children[0]
+ var blue = layout.children[0].children[1]
+ waitForRendering(layout);
+ tryCompare(red, 'width', 20)
+ tryCompare(blue, 'width', 80)
+ layout.height = 40
+ tryCompare(red, 'width', 40)
+ tryCompare(blue, 'width', 60)
+ layout.destroy()
+ }
+
+ Component {
+ id: layout_addIgnoredItem_Component
+ RowLayout {
+ spacing: 0
+ Rectangle {
+ id: r
+ }
+ }
+ }
+
+ function test_addIgnoredItem()
+ {
+ var layout = layout_addIgnoredItem_Component.createObject(container)
+ compare(layout.implicitWidth, 0)
+ compare(layout.implicitHeight, 0)
+ var r = layout.children[0]
+ r.Layout.preferredWidth = 20
+ r.Layout.preferredHeight = 30
+ compare(layout.implicitWidth, 20)
+ compare(layout.implicitHeight, 30)
+
+ layout.destroy();
+ }
+
+
+ Component {
+ id: layout_rowLayout_Component
+ RowLayout {
+ }
+ }
+
+ function test_stretchItem_data()
+ {
+ return [
+ { expectedWidth: 0},
+ { preferredWidth: 20, expectedWidth: 20},
+ { preferredWidth: 0, expectedWidth: 0},
+ { preferredWidth: 20, fillWidth: true, expectedWidth: 100},
+ { width: 20, fillWidth: true, expectedWidth: 100},
+ { width: 0, fillWidth: true, expectedWidth: 100},
+ { preferredWidth: 0, fillWidth: true, expectedWidth: 100},
+ { preferredWidth: 1, maximumWidth: 0, fillWidth: true, expectedWidth: 0},
+ { preferredWidth: 0, minimumWidth: 1, expectedWidth: 1},
+ ];
+ }
+
+ function test_stretchItem(data)
+ {
+ var layout = layout_rowLayout_Component.createObject(container)
+ var r = layoutItem_Component.createObject(layout)
+ // Reset previously relevant properties
+ r.width = 0
+ r.implicitWidth = 0
+ compare(layout.implicitWidth, 0)
+
+ if (data.preferredWidth !== undefined)
+ r.Layout.preferredWidth = data.preferredWidth
+ if (data.fillWidth !== undefined)
+ r.Layout.fillWidth = data.fillWidth
+ if (data.width !== undefined)
+ r.width = data.width
+ if (data.minimumWidth !== undefined)
+ r.Layout.minimumWidth = data.minimumWidth
+ if (data.maximumWidth !== undefined)
+ r.Layout.maximumWidth = data.maximumWidth
+
+ layout.width = 100
+
+ compare(r.width, data.expectedWidth)
+
+ layout.destroy();
+ }
+
+ Component {
+ id: layout_alignToPixelGrid_Component
+ RowLayout {
+ spacing: 2
+ Rectangle {
+ implicitWidth: 10
+ implicitHeight: 10
+ Layout.alignment: Qt.AlignVCenter
+ }
+ Rectangle {
+ implicitWidth: 10
+ implicitHeight: 10
+ Layout.alignment: Qt.AlignVCenter
+ }
+ }
+ }
+ function test_alignToPixelGrid()
+ {
+ var layout = layout_alignToPixelGrid_Component.createObject(container)
+ layout.width = 21
+ layout.height = 21
+ var r0 = layout.children[0]
+ compare(r0.x, 0) // 0.0
+ compare(r0.y, 6) // 5.5
+ var r1 = layout.children[1]
+ compare(r1.x, 12) // 11.5
+ compare(r1.y, 6) // 5.5
+ layout.destroy();
+ }
+
+ Component {
+ id: test_distributeToPixelGrid_Component
+ RowLayout {
+ spacing: 0
+ Rectangle {
+ color: 'red'
+ Layout.minimumWidth: 10
+ Layout.preferredWidth: 50
+ Layout.maximumWidth: 90
+ Layout.fillWidth: true
+ implicitHeight: 10
+ }
+ Rectangle {
+ color: 'red'
+ Layout.minimumWidth: 10
+ Layout.preferredWidth: 20
+ Layout.maximumWidth: 90
+ Layout.fillWidth: true
+ implicitHeight: 10
+ }
+ Rectangle {
+ color: 'red'
+ Layout.minimumWidth: 10
+ Layout.preferredWidth: 70
+ Layout.maximumWidth: 90
+ Layout.fillWidth: true
+ implicitHeight: 10
+ }
+ }
+ }
+
+ function test_distributeToPixelGrid_data() {
+ return [
+ { tag: "narrow", spacing: 0, width: 60 },
+ { tag: "belowPreferred", spacing: 0, width: 130 },
+ { tag: "belowPreferredWithSpacing", spacing: 10, width: 130 },
+ { tag: "abovePreferred", spacing: 0, width: 150 },
+ { tag: "stretchSomethingToMaximum", spacing: 0, width: 240,
+ expected: [90, 60, 90] },
+ { tag: "minSizeHasFractions", spacing: 2, width: 31 + 4, hints: [{min: 10+1/3}, {min: 10+1/3}, {min: 10+1/3}],
+ /*expected: [11, 11, 11]*/ }, /* verify that nothing gets allocated a size smaller than its minimum */
+ { tag: "maxSizeHasFractions", spacing: 2, width: 271 + 4, hints: [{max: 90+1/3}, {max: 90+1/3}, {max: 90+1/3}],
+ /*expected: [90, 90, 90]*/ }, /* verify that nothing gets allocated a size larger than its maximum */
+ { tag: "fixedSizeHasFractions", spacing: 2, width: 31 + 4, hints: [{min: 10+1/3, max: 10+1/3}, {min: 10+1/3, max: 10+1/3}, {min: 10+1/3, max: 10+1/3}],
+ /*expected: [11, 11, 11]*/ }, /* verify that nothing gets allocated a size smaller than its minimum */
+ ];
+ }
+
+ function test_distributeToPixelGrid(data)
+ {
+ // CONFIGURATION
+ var layout = test_distributeToPixelGrid_Component.createObject(container)
+ layout.spacing = data.spacing
+ layout.width = data.width
+ layout.height = 10
+ var kids = layout.children
+
+ if (data.hasOwnProperty('hints')) {
+ var hints = data.hints
+ for (var i = 0; i < hints.length; ++i) {
+ var h = hints[i]
+ if (h.hasOwnProperty('min'))
+ kids[i].Layout.minimumWidth = h.min
+ if (h.hasOwnProperty('pref'))
+ kids[i].Layout.preferredWidth = h.pref
+ if (h.hasOwnProperty('max'))
+ kids[i].Layout.maximumWidth = h.max
+ }
+ }
+ waitForRendering(layout)
+
+ var sum = 2 * layout.spacing
+ // TEST
+ for (var i = 0; i < kids.length; ++i) {
+ compare(kids[i].x % 1, 0) // checks if position is a whole integer
+ // verify if the items are within the size constraints as specified
+ verify(kids[i].width >= kids[i].Layout.minimumWidth)
+ verify(kids[i].width <= kids[i].Layout.maximumWidth)
+ if (data.hasOwnProperty('expected'))
+ compare(kids[i].width, data.expected[i])
+ sum += kids[i].width
+ }
+ fuzzyCompare(sum, layout.width, 1)
+
+ layout.destroy();
+ }
+
+
+
+ Component {
+ id: layout_deleteLayout
+ ColumnLayout {
+ property int dummyproperty: 0 // yes really - its needed
+ RowLayout {
+ Text { text: "label1" } // yes, both are needed
+ Text { text: "label2" }
+ }
+ }
+ }
+
+ function test_destroyLayout()
+ {
+ var layout = layout_deleteLayout.createObject(container)
+ layout.children[0].children[0].visible = true
+ layout.visible = false
+ layout.destroy() // Do not crash
+ }
+
+ function test_sizeHintWithHiddenChildren(data) {
+ var layout = layout_sizeHint_Component.createObject(container)
+ var grid = layout.children[0]
+ var child = grid.children[0]
+
+ // Implicit sizes are not affected by the visibility of the parent layout.
+ // This is in order for the layout to know the preferred size it should show itself at.
+ compare(grid.visible, true) // LAYOUT SHOWN
+ compare(grid.implicitWidth, 2);
+ child.visible = false
+ compare(grid.implicitWidth, 0);
+ child.visible = true
+ compare(grid.implicitWidth, 2);
+
+ grid.visible = false // LAYOUT HIDDEN
+ compare(grid.implicitWidth, 2);
+ child.visible = false
+ expectFail('', 'If GridLayout is hidden, GridLayout is not notified when child is explicitly hidden')
+ compare(grid.implicitWidth, 0);
+ child.visible = true
+ compare(grid.implicitWidth, 2);
+
+ layout.destroy();
+ }
+
+ Component {
+ id: row_sizeHint_Component
+ Row {
+ Rectangle {
+ id: r1
+ color: "red"
+ width: 2
+ height: 20
+ }
+ }
+ }
+
+ function test_sizeHintWithHiddenChildrenForRow(data) {
+ var row = row_sizeHint_Component.createObject(container)
+ var child = row.children[0]
+ compare(row.visible, true) // POSITIONER SHOWN
+ compare(row.implicitWidth, 2);
+ child.visible = false
+ tryCompare(row, 'implicitWidth', 0);
+ child.visible = true
+ tryCompare(row, 'implicitWidth', 2);
+
+ row.visible = false // POSITIONER HIDDEN
+ compare(row.implicitWidth, 2);
+ child.visible = false
+ expectFail('', 'If Row is hidden, Row is not notified when child is explicitly hidden')
+ compare(row.implicitWidth, 0);
+ child.visible = true
+ compare(row.implicitWidth, 2);
+ }
+
+ Component {
+ id: rearrangeNestedLayouts_Component
+ RowLayout {
+ id: layout
+ anchors.fill: parent
+ width: 200
+ height: 20
+ RowLayout {
+ id: row
+ spacing: 0
+
+ Rectangle {
+ id: fixed
+ color: 'red'
+ implicitWidth: 20
+ implicitHeight: 20
+ }
+ Rectangle {
+ id: filler
+ color: 'grey'
+ Layout.fillWidth: true
+ implicitHeight: 20
+ }
+ }
+ }
+ }
+
+ function test_rearrangeNestedLayouts()
+ {
+ var layout = rearrangeNestedLayouts_Component.createObject(container)
+ var fixed = layout.children[0].children[0]
+ var filler = layout.children[0].children[1]
+
+ compare(itemRect(fixed), [0,0,20,20])
+ compare(itemRect(filler), [20,0,180,20])
+
+ fixed.implicitWidth = 100
+ waitForRendering(layout)
+ compare(itemRect(fixed), [0,0,100,20])
+ compare(itemRect(filler), [100,0,100,20])
+ }
+
+ Component {
+ id: changeChildrenOfHiddenLayout_Component
+ RowLayout {
+ property int childCount: 1
+ Repeater {
+ model: parent.childCount
+ Text {
+ text: 'Just foo it'
+ }
+ }
+ }
+ }
+ function test_changeChildrenOfHiddenLayout()
+ {
+ var layout = changeChildrenOfHiddenLayout_Component.createObject(container)
+ var child = layout.children[0]
+ waitForRendering(layout)
+ layout.visible = false
+ waitForRendering(layout)
+ // Remove and add children to the hidden layout..
+ layout.childCount = 0
+ waitForRendering(layout)
+ layout.childCount = 1
+ waitForRendering(layout)
+ layout.destroy()
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklayouts/qquicklayouts.pro b/tests/auto/quick/qquicklayouts/qquicklayouts.pro
new file mode 100644
index 0000000000..9ed3e076be
--- /dev/null
+++ b/tests/auto/quick/qquicklayouts/qquicklayouts.pro
@@ -0,0 +1,13 @@
+QT += core-private gui-private qml-private
+TEMPLATE=app
+TARGET=tst_qquicklayouts
+
+CONFIG += qmltestcase
+SOURCES += tst_qquicklayouts.cpp
+
+TESTDATA = data/*
+
+OTHER_FILES += \
+ data/tst_rowlayout.qml \
+ data/tst_gridlayout.qml
+
diff --git a/tests/auto/quick/qquicklayouts/tst_qquicklayouts.cpp b/tests/auto/quick/qquicklayouts/tst_qquicklayouts.cpp
new file mode 100644
index 0000000000..373019091f
--- /dev/null
+++ b/tests/auto/quick/qquicklayouts/tst_qquicklayouts.cpp
@@ -0,0 +1,29 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtQuickTest/quicktest.h>
+QUICK_TEST_MAIN(qquicklayouts)
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index 405acad165..658ffa1f57 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -8264,99 +8264,9 @@ void tst_QQuickListView::keyNavigationEnabled()
QCOMPARE(listView->currentIndex(), 1);
}
-static bool testVisibleItems(const QQuickItemViewPrivate *priv, bool *nonUnique, FxViewItem **failItem, int *expectedIdx)
-{
- QHash<QQuickItem*, int> uniqueItems;
-
- int skip = 0;
- for (int i = 0; i < priv->visibleItems.count(); ++i) {
- FxViewItem *item = priv->visibleItems.at(i);
- if (!item) {
- *failItem = Q_NULLPTR;
- return false;
- }
-#if 0
- qDebug() << "\t" << item->index
- << item->item
- << item->position()
- << (!item->item || QQuickItemPrivate::get(item->item)->culled ? "hidden" : "visible");
-#endif
- if (item->index == -1) {
- ++skip;
- } else if (item->index != priv->visibleIndex + i - skip) {
- *nonUnique = false;
- *failItem = item;
- *expectedIdx = priv->visibleIndex + i - skip;
- return false;
- } else if (uniqueItems.contains(item->item)) {
- *nonUnique = true;
- *failItem = item;
- *expectedIdx = uniqueItems.find(item->item).value();
- return false;
- }
-
- uniqueItems.insert(item->item, item->index);
- }
-
- return true;
-}
-
-class QTBUG_48870_Model : public QAbstractListModel
-{
- Q_OBJECT
-
-public:
-
- QTBUG_48870_Model()
- : QAbstractListModel()
- , m_rowCount(20)
- {
- QTimer *t = new QTimer(this);
- t->setInterval(500);
- t->start();
-
- qsrand(qHash(QDateTime::currentDateTime()));
- connect(t, &QTimer::timeout, this, &QTBUG_48870_Model::updateModel);
- }
-
- int rowCount(const QModelIndex &) const
- {
- return m_rowCount;
- }
-
- QVariant data(const QModelIndex &, int) const
- {
- return QVariant();
- }
-
-public Q_SLOTS:
- void updateModel()
- {
- if (m_rowCount > 10) {
- for (int i = 0; i < 10; ++i) {
- int rnum = qrand() % m_rowCount;
- beginRemoveRows(QModelIndex(), rnum, rnum);
- m_rowCount--;
- endRemoveRows();
- }
- }
- if (m_rowCount < 20) {
- for (int i = 0; i < 10; ++i) {
- int rnum = qrand() % m_rowCount;
- beginInsertRows(QModelIndex(), rnum, rnum);
- m_rowCount++;
- endInsertRows();
- }
- }
- }
-
-private:
- int m_rowCount;
-};
-
void tst_QQuickListView::QTBUG_48870_fastModelUpdates()
{
- QTBUG_48870_Model model;
+ StressTestModel model;
QScopedPointer<QQuickView> window(createView());
QQmlContext *ctxt = window->rootContext();
diff --git a/tests/auto/quick/qquicktextedit/BLACKLIST b/tests/auto/quick/qquicktextedit/BLACKLIST
index 297146195b..492d81531a 100644
--- a/tests/auto/quick/qquicktextedit/BLACKLIST
+++ b/tests/auto/quick/qquicktextedit/BLACKLIST
@@ -1,6 +1,2 @@
[mouseSelection]
*
-[undo]
-*
-[undo_keypressevents]
-*
diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
index 50e06e5663..47baaaece8 100644
--- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
+++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
@@ -108,6 +108,7 @@ private slots:
void selectionOnFocusOut();
void focusOnPress();
void selection();
+ void overwriteMode();
void isRightToLeft_data();
void isRightToLeft();
void keySelection();
@@ -1466,6 +1467,74 @@ void tst_qquicktextedit::selection()
QVERIFY(textEditObject->selectedText().isNull());
}
+void tst_qquicktextedit::overwriteMode()
+{
+ QString componentStr = "import QtQuick 2.0\nTextEdit { focus: true; }";
+ QQmlComponent textEditComponent(&engine);
+ textEditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
+ QVERIFY(textEdit != 0);
+
+ QSignalSpy spy(textEdit, SIGNAL(overwriteModeChanged(bool)));
+
+ QQuickWindow window;
+ textEdit->setParentItem(window.contentItem());
+ window.show();
+ window.requestActivate();
+ QTest::qWaitForWindowActive(&window);
+
+ QVERIFY(textEdit->hasActiveFocus());
+
+ textEdit->setOverwriteMode(true);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(true, textEdit->overwriteMode());
+ textEdit->setOverwriteMode(false);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(false, textEdit->overwriteMode());
+
+ QVERIFY(!textEdit->overwriteMode());
+ QString insertString = "Some first text";
+ for (int j = 0; j < insertString.length(); j++)
+ QTest::keyClick(&window, insertString.at(j).toLatin1());
+
+ QCOMPARE(textEdit->text(), QString("Some first text"));
+
+ textEdit->setOverwriteMode(true);
+ QCOMPARE(spy.count(), 3);
+ textEdit->setCursorPosition(5);
+
+ insertString = "shiny";
+ for (int j = 0; j < insertString.length(); j++)
+ QTest::keyClick(&window, insertString.at(j).toLatin1());
+ QCOMPARE(textEdit->text(), QString("Some shiny text"));
+
+ textEdit->setCursorPosition(textEdit->text().length());
+ QTest::keyClick(&window, Qt::Key_Enter);
+
+ textEdit->setOverwriteMode(false);
+ QCOMPARE(spy.count(), 4);
+
+ insertString = "Second paragraph";
+
+ for (int j = 0; j < insertString.length(); j++)
+ QTest::keyClick(&window, insertString.at(j).toLatin1());
+ QCOMPARE(textEdit->lineCount(), 2);
+
+ textEdit->setCursorPosition(15);
+
+ QCOMPARE(textEdit->cursorPosition(), 15);
+
+ textEdit->setOverwriteMode(true);
+ QCOMPARE(spy.count(), 5);
+
+ insertString = " blah";
+ for (int j = 0; j < insertString.length(); j++)
+ QTest::keyClick(&window, insertString.at(j).toLatin1());
+ QCOMPARE(textEdit->lineCount(), 2);
+
+ QCOMPARE(textEdit->text(), QString("Some shiny text blah\nSecond paragraph"));
+}
+
void tst_qquicktextedit::isRightToLeft_data()
{
QTest::addColumn<QString>("text");
diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
index abb2c5b773..c899290594 100644
--- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
+++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
@@ -105,6 +105,7 @@ private slots:
void wrap();
void selection();
void persistentSelection();
+ void overwriteMode();
void isRightToLeft_data();
void isRightToLeft();
void moveCursorSelection_data();
@@ -777,6 +778,48 @@ void tst_qquicktextinput::persistentSelection()
QCOMPARE(input->property("selected").toString(), QLatin1String("ell"));
}
+void tst_qquicktextinput::overwriteMode()
+{
+ QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; }";
+ QQmlComponent textInputComponent(&engine);
+ textInputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
+ QVERIFY(textInput != 0);
+
+ QSignalSpy spy(textInput, SIGNAL(overwriteModeChanged(bool)));
+
+ QQuickWindow window;
+ textInput->setParentItem(window.contentItem());
+ window.show();
+ window.requestActivate();
+ QTest::qWaitForWindowActive(&window);
+
+ QVERIFY(textInput->hasActiveFocus());
+
+ textInput->setOverwriteMode(true);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(true, textInput->overwriteMode());
+ textInput->setOverwriteMode(false);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(false, textInput->overwriteMode());
+
+ QVERIFY(!textInput->overwriteMode());
+ QString insertString = "Some first text";
+ for (int j = 0; j < insertString.length(); j++)
+ QTest::keyClick(&window, insertString.at(j).toLatin1());
+
+ QCOMPARE(textInput->text(), QString("Some first text"));
+
+ textInput->setOverwriteMode(true);
+ QCOMPARE(spy.count(), 3);
+ textInput->setCursorPosition(5);
+
+ insertString = "shiny";
+ for (int j = 0; j < insertString.length(); j++)
+ QTest::keyClick(&window, insertString.at(j).toLatin1());
+ QCOMPARE(textInput->text(), QString("Some shiny text"));
+}
+
void tst_qquicktextinput::isRightToLeft_data()
{
QTest::addColumn<QString>("text");
diff --git a/tests/auto/quick/qquickwindow/data/windowattached.qml b/tests/auto/quick/qquickwindow/data/windowattached.qml
index a9f052d55e..9d61a02452 100644
--- a/tests/auto/quick/qquickwindow/data/windowattached.qml
+++ b/tests/auto/quick/qquickwindow/data/windowattached.qml
@@ -9,6 +9,7 @@ Rectangle {
property Item contentItem: root.Window.contentItem
property int windowWidth: root.Window.width
property int windowHeight: root.Window.height
+ property var window: root.Window.window
Text {
objectName: "rectangleWindowText"
anchors.centerIn: parent
@@ -26,6 +27,7 @@ Rectangle {
property Item contentItem: Window.contentItem
property int windowWidth: Window.width
property int windowHeight: Window.height
+ property var window: Window.window
}
}
}
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index 5d1897ab2d..ff8c80e3ae 100644
--- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -2033,6 +2033,7 @@ void tst_qquickwindow::attachedProperty()
QCOMPARE(view.rootObject()->property("contentItem").value<QQuickItem*>(), view.contentItem());
QCOMPARE(view.rootObject()->property("windowWidth").toInt(), view.width());
QCOMPARE(view.rootObject()->property("windowHeight").toInt(), view.height());
+ QCOMPARE(view.rootObject()->property("window").value<QQuickView*>(), &view);
QQuickWindow *innerWindow = view.rootObject()->findChild<QQuickWindow*>("extraWindow");
QVERIFY(innerWindow);
@@ -2045,6 +2046,13 @@ void tst_qquickwindow::attachedProperty()
QCOMPARE(text->property("contentItem").value<QQuickItem*>(), innerWindow->contentItem());
QCOMPARE(text->property("windowWidth").toInt(), innerWindow->width());
QCOMPARE(text->property("windowHeight").toInt(), innerWindow->height());
+ QCOMPARE(text->property("window").value<QQuickWindow*>(), innerWindow);
+
+ text->setParentItem(0);
+ QVERIFY(!text->property("contentItem").value<QQuickItem*>());
+ QCOMPARE(text->property("windowWidth").toInt(), 0);
+ QCOMPARE(text->property("windowHeight").toInt(), 0);
+ QVERIFY(!text->property("window").value<QQuickWindow*>());
}
class RenderJob : public QRunnable
diff --git a/tests/auto/quick/quick.pro b/tests/auto/quick/quick.pro
index f25a28d45b..13bd6d78e2 100644
--- a/tests/auto/quick/quick.pro
+++ b/tests/auto/quick/quick.pro
@@ -21,6 +21,7 @@ PRIVATETESTS += \
qquickfontloader_static \
qquickfontmetrics \
qquickimageprovider \
+ qquicklayouts \
qquickpath \
qquicksmoothedanimation \
qquickspringanimation \
diff --git a/tests/auto/quick/shared/viewtestutil.cpp b/tests/auto/quick/shared/viewtestutil.cpp
index 09c88acbe6..ab58aee648 100644
--- a/tests/auto/quick/shared/viewtestutil.cpp
+++ b/tests/auto/quick/shared/viewtestutil.cpp
@@ -35,6 +35,7 @@
#include <QtTest/QTest>
#include <private/qquickwindow_p.h>
+#include <private/qquickitemview_p_p.h>
QQuickView *QQuickViewTestUtil::createView()
@@ -347,6 +348,85 @@ QList<QPair<QString,QString> > QQuickViewTestUtil::ListRange::getModelDataValues
return data;
}
+QQuickViewTestUtil::StressTestModel::StressTestModel()
+ : QAbstractListModel()
+ , m_rowCount(20)
+{
+ QTimer *t = new QTimer(this);
+ t->setInterval(500);
+ t->start();
+
+ qsrand(qHash(QDateTime::currentDateTime()));
+ connect(t, &QTimer::timeout, this, &StressTestModel::updateModel);
+}
+
+int QQuickViewTestUtil::StressTestModel::rowCount(const QModelIndex &) const
+{
+ return m_rowCount;
+}
+
+QVariant QQuickViewTestUtil::StressTestModel::data(const QModelIndex &, int) const
+{
+ return QVariant();
+}
+
+void QQuickViewTestUtil::StressTestModel::updateModel()
+{
+ if (m_rowCount > 10) {
+ for (int i = 0; i < 10; ++i) {
+ int rnum = qrand() % m_rowCount;
+ beginRemoveRows(QModelIndex(), rnum, rnum);
+ m_rowCount--;
+ endRemoveRows();
+ }
+ }
+ if (m_rowCount < 20) {
+ for (int i = 0; i < 10; ++i) {
+ int rnum = qrand() % m_rowCount;
+ beginInsertRows(QModelIndex(), rnum, rnum);
+ m_rowCount++;
+ endInsertRows();
+ }
+ }
+}
+
+bool QQuickViewTestUtil::testVisibleItems(const QQuickItemViewPrivate *priv, bool *nonUnique, FxViewItem **failItem, int *expectedIdx)
+{
+ QHash<QQuickItem*, int> uniqueItems;
+
+ int skip = 0;
+ for (int i = 0; i < priv->visibleItems.count(); ++i) {
+ FxViewItem *item = priv->visibleItems.at(i);
+ if (!item) {
+ *failItem = Q_NULLPTR;
+ return false;
+ }
+#if 0
+ qDebug() << "\t" << item->index
+ << item->item
+ << item->position()
+ << (!item->item || QQuickItemPrivate::get(item->item)->culled ? "hidden" : "visible");
+#endif
+ if (item->index == -1) {
+ ++skip;
+ } else if (item->index != priv->visibleIndex + i - skip) {
+ *nonUnique = false;
+ *failItem = item;
+ *expectedIdx = priv->visibleIndex + i - skip;
+ return false;
+ } else if (uniqueItems.contains(item->item)) {
+ *nonUnique = true;
+ *failItem = item;
+ *expectedIdx = uniqueItems.find(item->item).value();
+ return false;
+ }
+
+ uniqueItems.insert(item->item, item->index);
+ }
+
+ return true;
+}
+
namespace QQuickTouchUtils {
/* QQuickWindow does event compression and only delivers events just
diff --git a/tests/auto/quick/shared/viewtestutil.h b/tests/auto/quick/shared/viewtestutil.h
index 0f50180809..b11d5e4859 100644
--- a/tests/auto/quick/shared/viewtestutil.h
+++ b/tests/auto/quick/shared/viewtestutil.h
@@ -34,6 +34,8 @@
#include <QtCore/QAbstractListModel>
QT_FORWARD_DECLARE_CLASS(QQuickView)
+QT_FORWARD_DECLARE_CLASS(QQuickItemViewPrivate)
+QT_FORWARD_DECLARE_CLASS(FxViewItem)
namespace QQuickViewTestUtil
{
@@ -154,6 +156,26 @@ namespace QQuickViewTestUtil
for (; f != replaced.end(); ++f, ++t)
*t = *f;
}
+
+ class StressTestModel : public QAbstractListModel
+ {
+ Q_OBJECT
+
+ public:
+
+ StressTestModel();
+
+ int rowCount(const QModelIndex &) const;
+ QVariant data(const QModelIndex &, int) const;
+
+ public Q_SLOTS:
+ void updateModel();
+
+ private:
+ int m_rowCount;
+ };
+
+ bool testVisibleItems(const QQuickItemViewPrivate *priv, bool *nonUnique, FxViewItem **failItem, int *expectedIdx);
}
namespace QQuickTouchUtils {
diff --git a/tests/manual/scenegraph_lancelot/data/text/textedit_multiline_selected_linebreaks_and_linewraps.qml b/tests/manual/scenegraph_lancelot/data/text/textedit_multiline_selected_linebreaks_and_linewraps.qml
new file mode 100644
index 0000000000..a1004d0374
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/text/textedit_multiline_selected_linebreaks_and_linewraps.qml
@@ -0,0 +1,22 @@
+import QtQuick 2.0
+
+Item {
+ width: 200
+ height: 480
+
+ TextEdit {
+ id: textEdit
+ anchors.centerIn: parent
+ font.family: "Arial"
+ font.pixelSize: 64
+ width: 200
+ textFormat: TextEdit.RichText
+ wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
+ text: "ABC ABC<br>ABC"
+
+ Component.onCompleted: {
+ textEdit.selectAll()
+ }
+ }
+
+}
diff --git a/tools/qmlimportscanner/main.cpp b/tools/qmlimportscanner/main.cpp
index af6b272fc6..dcb9709bb8 100644
--- a/tools/qmlimportscanner/main.cpp
+++ b/tools/qmlimportscanner/main.cpp
@@ -85,7 +85,7 @@ QVariantList findImportsInAst(QQmlJS::AST::UiHeaderItemList *headerItemList, con
if (!importNode->fileName.isEmpty()) {
QString name = importNode->fileName.toString();
import[QStringLiteral("name")] = name;
- if (name.endsWith(QStringLiteral(".js"))) {
+ if (name.endsWith(QLatin1String(".js"))) {
import[QStringLiteral("type")] = QStringLiteral("javascript");
} else {
import[QStringLiteral("type")] = QStringLiteral("directory");
@@ -188,7 +188,7 @@ QVariantList findPathsForModuleImports(const QVariantList &imports)
for (int i = 0; i < importsCopy.length(); ++i) {
QVariantMap import = qvariant_cast<QVariantMap>(importsCopy[i]);
- if (import[QStringLiteral("type")] == QStringLiteral("module")) {
+ if (import[QStringLiteral("type")] == QLatin1String("module")) {
QString path = resolveImportPath(import.value(QStringLiteral("name")).toString(), import.value(QStringLiteral("version")).toString());
if (!path.isEmpty())
import[QStringLiteral("path")] = path;
@@ -319,9 +319,9 @@ QVariantList findQmlImportsInFile(const QString &filePath)
QFile f;
if (f.open(stdin, QIODevice::ReadOnly))
imports = findQmlImportsInQmlCode(QLatin1String("<stdin>"), QString::fromUtf8(f.readAll()));
- } else if (filePath.endsWith(QStringLiteral(".qml"))) {
+ } else if (filePath.endsWith(QLatin1String(".qml"))) {
imports = findQmlImportsInQmlFile(filePath);
- } else if (filePath.endsWith(QStringLiteral(".js"))) {
+ } else if (filePath.endsWith(QLatin1String(".js"))) {
imports = findQmlImportsInJavascriptFile(filePath);
}
@@ -382,10 +382,10 @@ QVariantList findQmlImportsInDirectory(const QString &qmlDir)
continue;
// skip obvious build output directories
- if (path.contains(QStringLiteral("Debug-iphoneos")) || path.contains(QStringLiteral("Release-iphoneos")) ||
- path.contains(QStringLiteral("Debug-iphonesimulator")) || path.contains(QStringLiteral("Release-iphonesimulator"))
+ if (path.contains(QLatin1String("Debug-iphoneos")) || path.contains(QLatin1String("Release-iphoneos")) ||
+ path.contains(QLatin1String("Debug-iphonesimulator")) || path.contains(QLatin1String("Release-iphonesimulator"))
#ifdef Q_OS_WIN
- || path.contains(QStringLiteral("/release/")) || path.contains(QStringLiteral("/debug/"))
+ || path.contains(QLatin1String("/release/")) || path.contains(QLatin1String("/debug/"))
#endif
){
continue;
@@ -404,7 +404,7 @@ QSet<QString> importModulePaths(QVariantList imports) {
QVariantMap import = qvariant_cast<QVariantMap>(importVariant);
QString path = import.value(QStringLiteral("path")).toString();
QString type = import.value(QStringLiteral("type")).toString();
- if (type == QStringLiteral("module") && !path.isEmpty())
+ if (type == QLatin1String("module") && !path.isEmpty())
ret.insert(QDir(path).canonicalPath());
}
return ret;
diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp
index 776e19fdf4..7870e3a9df 100644
--- a/tools/qmlplugindump/main.cpp
+++ b/tools/qmlplugindump/main.cpp
@@ -51,9 +51,11 @@
#include <QtCore/private/qobject_p.h>
#include <QtCore/private/qmetaobject_p.h>
+#include <QRegularExpression>
#include <iostream>
#include <algorithm>
+#include "qmltypereader.h"
#include "qmlstreamwriter.h"
#ifdef QT_SIMULATOR
@@ -728,7 +730,7 @@ void sigSegvHandler(int) {
void printUsage(const QString &appName)
{
std::cerr << qPrintable(QString(
- "Usage: %1 [-v] [-noinstantiate] [-defaultplatform] [-[non]relocatable] [-dependencies <dependencies.json>] module.uri version [module/import/path]\n"
+ "Usage: %1 [-v] [-noinstantiate] [-defaultplatform] [-[non]relocatable] [-dependencies <dependencies.json>] [-merge <file-to-merge.qmltypes>] module.uri version [module/import/path]\n"
" %1 [-v] [-noinstantiate] -path path/to/qmldir/directory [version]\n"
" %1 [-v] -builtins\n"
"Example: %1 Qt.labs.folderlistmodel 2.0 /home/user/dev/qt-install/imports").arg(
@@ -982,6 +984,7 @@ int main(int argc, char *argv[])
QString pluginImportVersion;
bool relocatable = true;
QString dependenciesFile;
+ QString mergeFile;
enum Action { Uri, Path, Builtins };
Action action = Uri;
{
@@ -1000,6 +1003,13 @@ int main(int argc, char *argv[])
return EXIT_INVALIDARGUMENTS;
}
dependenciesFile = args.at(iArg);
+ } else if (arg == QLatin1String("--merge")
+ || arg == QLatin1String("-merge")) {
+ if (++iArg == args.size()) {
+ std::cerr << "missing merge file" << std::endl;
+ return EXIT_INVALIDARGUMENTS;
+ }
+ mergeFile = args.at(iArg);
} else if (arg == QLatin1String("--notrelocatable")
|| arg == QLatin1String("-notrelocatable")
|| arg == QLatin1String("--nonrelocatable")
@@ -1061,6 +1071,26 @@ int main(int argc, char *argv[])
QDir::setCurrent(pluginImportPath);
engine.addImportPath(pluginImportPath);
}
+
+ // Merge file.
+ QStringList mergeDependencies;
+ QString mergeComponents;
+ if (!mergeFile.isEmpty()) {
+ QStringList merge = readQmlTypes(mergeFile);
+ if (!merge.isEmpty()) {
+ QRegularExpression re("(\\w+\\.*\\w*\\s*\\d+\\.\\d+)");
+ QRegularExpressionMatchIterator i = re.globalMatch(merge[1]);
+ while (i.hasNext()) {
+ QRegularExpressionMatch m = i.next();
+ QString d = m.captured(1);
+ mergeDependencies << m.captured(1);
+ }
+ mergeComponents = merge [2];
+ }
+ }
+
+ // Dependencies.
+
bool calculateDependencies = !pluginImportUri.isEmpty() && !pluginImportVersion.isEmpty();
QStringList dependencies;
if (!dependenciesFile.isEmpty())
@@ -1210,6 +1240,13 @@ int main(int argc, char *argv[])
"// '%1 %2'\n"
"\n").arg(QFileInfo(args.at(0)).baseName(), args.mid(1).join(QLatin1Char(' '))));
qml.writeStartObject("Module");
+
+ // Insert merge dependencies.
+ if (!mergeDependencies.isEmpty()) {
+ dependencies << mergeDependencies;
+ }
+ compactDependencies(&dependencies);
+
QStringList quotedDependencies;
foreach (const QString &dep, dependencies)
quotedDependencies << enquote(dep);
@@ -1236,6 +1273,9 @@ int main(int argc, char *argv[])
if (pluginImportUri.isEmpty())
dumper.writeEasingCurve();
+ // Insert merge file.
+ qml.write(mergeComponents);
+
qml.writeEndObject();
qml.writeEndDocument();
diff --git a/tools/qmlplugindump/qmlplugindump.pro b/tools/qmlplugindump/qmlplugindump.pro
index 6fdcd349d1..e45a7fad83 100644
--- a/tools/qmlplugindump/qmlplugindump.pro
+++ b/tools/qmlplugindump/qmlplugindump.pro
@@ -6,10 +6,12 @@ QTPLUGIN.platforms = qminimal
SOURCES += \
main.cpp \
- qmlstreamwriter.cpp
+ qmlstreamwriter.cpp \
+ qmltypereader.cpp
HEADERS += \
- qmlstreamwriter.h
+ qmlstreamwriter.h \
+ qmltypereader.h
macx {
# Prevent qmlplugindump from popping up in the dock when launched.
diff --git a/tools/qmlplugindump/qmltypereader.cpp b/tools/qmlplugindump/qmltypereader.cpp
new file mode 100644
index 0000000000..67ba415388
--- /dev/null
+++ b/tools/qmlplugindump/qmltypereader.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmltypereader.h"
+
+#include <QFileInfo>
+#include <QFile>
+#include <QRegularExpression>
+
+#include <iostream>
+
+QStringList readQmlTypes(const QString &filename) {
+ QRegularExpression re("import QtQuick.tooling 1.2.*Module {\\s*dependencies:\\[([^\\]]*)\\](.*)}",
+ QRegularExpression::DotMatchesEverythingOption);
+ if (!QFileInfo(filename).exists()) {
+ std::cerr << "Non existing file: " << filename.toStdString() << std::endl;
+ return QStringList();
+ }
+ QFile f(filename);
+ if (!f.open(QFileDevice::ReadOnly)) {
+ std::cerr << "Error in opening file " << filename.toStdString() << " : "
+ << f.errorString().toStdString() << std::endl;
+ return QStringList();
+ }
+ QByteArray fileData = f.readAll();
+ QString data(fileData);
+ QRegularExpressionMatch m = re.match(data);
+ if (m.lastCapturedIndex() != 2) {
+ std::cerr << "Malformed file: " << filename.toStdString() << std::endl;
+ return QStringList();
+ }
+ return m.capturedTexts();
+}
diff --git a/tools/qmlplugindump/qmltypereader.h b/tools/qmlplugindump/qmltypereader.h
new file mode 100644
index 0000000000..b995566e0b
--- /dev/null
+++ b/tools/qmlplugindump/qmltypereader.h
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLTYPEREADER_H
+#define QMLTYPEREADER_H
+
+#include <QString>
+#include <QStringList>
+
+QStringList readQmlTypes(const QString &filename);
+
+#endif // QMLTYPEREADER_H