aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/declarative/debugger/debugger.pri6
-rw-r--r--src/declarative/debugger/qdeclarativedebugserver.cpp10
-rw-r--r--src/declarative/debugger/qdeclarativedebugservice.cpp20
-rw-r--r--src/declarative/debugger/qdeclarativedebugservice_p.h1
-rw-r--r--src/declarative/debugger/qjsdebuggeragent.cpp571
-rw-r--r--src/declarative/debugger/qjsdebuggeragent_p.h203
-rw-r--r--src/declarative/debugger/qjsdebugservice.cpp208
-rw-r--r--src/declarative/debugger/qv8debugservice.cpp274
-rw-r--r--src/declarative/debugger/qv8debugservice_p.h (renamed from src/declarative/debugger/qjsdebugservice_p.h)34
-rw-r--r--src/declarative/items/qsganimatedimage.cpp95
-rw-r--r--src/declarative/items/qsgborderimage.cpp249
-rw-r--r--src/declarative/items/qsgcanvas.cpp71
-rw-r--r--src/declarative/items/qsgcanvas_p.h4
-rw-r--r--src/declarative/items/qsgevents.cpp193
-rw-r--r--src/declarative/items/qsgflickable.cpp278
-rw-r--r--src/declarative/items/qsgflipable.cpp54
-rw-r--r--src/declarative/items/qsgfocusscope.cpp16
-rw-r--r--src/declarative/items/qsggridview.cpp495
-rw-r--r--src/declarative/items/qsgimage.cpp4
-rw-r--r--src/declarative/items/qsgitem.cpp1932
-rw-r--r--src/declarative/items/qsgitem.h1
-rw-r--r--src/declarative/items/qsgitemsmodule.cpp1
-rw-r--r--src/declarative/items/qsgitemview.cpp66
-rw-r--r--src/declarative/items/qsgitemview_p.h34
-rw-r--r--src/declarative/items/qsgitemview_p_p.h47
-rw-r--r--src/declarative/items/qsglistview.cpp589
-rw-r--r--src/declarative/items/qsgloader.cpp205
-rw-r--r--src/declarative/items/qsgmousearea.cpp368
-rw-r--r--src/declarative/items/qsgmousearea_p.h2
-rw-r--r--src/declarative/items/qsgpainteditem.cpp9
-rw-r--r--src/declarative/items/qsgpathview.cpp412
-rw-r--r--src/declarative/items/qsgpathview_p.h4
-rw-r--r--src/declarative/items/qsgpathview_p_p.h2
-rw-r--r--src/declarative/items/qsgpincharea.cpp182
-rw-r--r--src/declarative/items/qsgpositioners.cpp755
-rw-r--r--src/declarative/items/qsgpositioners_p.h51
-rw-r--r--src/declarative/items/qsgrectangle.cpp294
-rw-r--r--src/declarative/items/qsgrectangle_p_p.h12
-rw-r--r--src/declarative/items/qsgrepeater.cpp146
-rw-r--r--src/declarative/items/qsgscalegrid.cpp2
-rw-r--r--src/declarative/items/qsgshadereffectsource.cpp21
-rw-r--r--src/declarative/items/qsgtext.cpp455
-rw-r--r--src/declarative/items/qsgtext_p_p.h7
-rw-r--r--src/declarative/items/qsgtextedit.cpp850
-rw-r--r--src/declarative/items/qsgtextedit_p.h9
-rw-r--r--src/declarative/items/qsgtextedit_p_p.h22
-rw-r--r--src/declarative/items/qsgtextinput.cpp832
-rw-r--r--src/declarative/items/qsgtextinput_p.h4
-rw-r--r--src/declarative/items/qsgtextinput_p_p.h39
-rw-r--r--src/declarative/items/qsgtextnode.cpp781
-rw-r--r--src/declarative/items/qsgtextnode_p.h38
-rw-r--r--src/declarative/items/qsgtranslate.cpp22
-rw-r--r--src/declarative/items/qsgvisualitemmodel.cpp729
-rw-r--r--src/declarative/particles/defaultshaders/coloredfragment.shader9
-rw-r--r--src/declarative/particles/defaultshaders/coloredvertex.shader (renamed from src/declarative/particles/defaultshaders/trailsvertex.shader)31
-rw-r--r--src/declarative/particles/defaultshaders/ctfragment.shader11
-rw-r--r--src/declarative/particles/defaultshaders/ctvertex.shader38
-rw-r--r--src/declarative/particles/defaultshaders/deformablefragment.shader5
-rw-r--r--src/declarative/particles/defaultshaders/deformablevertex.shader70
-rw-r--r--src/declarative/particles/defaultshaders/imagefragment.shader45
-rw-r--r--src/declarative/particles/defaultshaders/imagevertex.shader (renamed from src/declarative/particles/defaultshaders/ultravertex.shader)129
-rw-r--r--src/declarative/particles/defaultshaders/simplefragment.shader4
-rw-r--r--src/declarative/particles/defaultshaders/simplevertex.shader33
-rw-r--r--src/declarative/particles/defaultshaders/spritefragment.shader9
-rw-r--r--src/declarative/particles/defaultshaders/spritevertex.shader90
-rw-r--r--src/declarative/particles/defaultshaders/superfragment.shader11
-rw-r--r--src/declarative/particles/defaultshaders/tabledfragment.shader23
-rw-r--r--src/declarative/particles/defaultshaders/tabledvertex.shader (renamed from src/declarative/particles/defaultshaders/supervertex.shader)13
-rw-r--r--src/declarative/particles/defaultshaders/trailsfragment.shader8
-rw-r--r--src/declarative/particles/defaultshaders/ultrafragment.shader16
-rw-r--r--src/declarative/particles/particles.pri6
-rw-r--r--src/declarative/particles/particles.qrc16
-rw-r--r--src/declarative/particles/qsgangleddirection.cpp1
-rw-r--r--src/declarative/particles/qsgcumulativedirection.cpp1
-rw-r--r--src/declarative/particles/qsgcustomaffector.cpp73
-rw-r--r--src/declarative/particles/qsgcustomemitter.cpp189
-rw-r--r--src/declarative/particles/qsgcustomemitter_p.h76
-rw-r--r--src/declarative/particles/qsgcustomparticle.cpp5
-rw-r--r--src/declarative/particles/qsgellipseextruder.cpp1
-rw-r--r--src/declarative/particles/qsgemitter.cpp262
-rw-r--r--src/declarative/particles/qsgemitter_p.h104
-rw-r--r--src/declarative/particles/qsgfollowemitter.cpp88
-rw-r--r--src/declarative/particles/qsgfollowemitter_p.h2
-rw-r--r--src/declarative/particles/qsgfriction.cpp1
-rw-r--r--src/declarative/particles/qsggravity.cpp1
-rw-r--r--src/declarative/particles/qsgimageparticle.cpp923
-rw-r--r--src/declarative/particles/qsgimageparticle_p.h114
-rw-r--r--src/declarative/particles/qsgitemparticle.cpp1
-rw-r--r--src/declarative/particles/qsgkill.cpp1
-rw-r--r--src/declarative/particles/qsglineextruder.cpp1
-rw-r--r--src/declarative/particles/qsgmaskextruder.cpp1
-rw-r--r--src/declarative/particles/qsgmodelparticle.cpp1
-rw-r--r--src/declarative/particles/qsgparticleaffector.cpp28
-rw-r--r--src/declarative/particles/qsgparticleaffector_p.h2
-rw-r--r--src/declarative/particles/qsgparticleemitter.cpp307
-rw-r--r--src/declarative/particles/qsgparticleemitter_p.h58
-rw-r--r--src/declarative/particles/qsgparticleextruder.cpp1
-rw-r--r--src/declarative/particles/qsgparticlepainter.cpp1
-rw-r--r--src/declarative/particles/qsgparticlesmodule.cpp18
-rw-r--r--src/declarative/particles/qsgparticlesystem.cpp3
-rw-r--r--src/declarative/particles/qsgpointattractor.cpp1
-rw-r--r--src/declarative/particles/qsgpointattractor_p.h2
-rw-r--r--src/declarative/particles/qsgpointdirection.cpp1
-rw-r--r--src/declarative/particles/qsgspritegoal.cpp1
-rw-r--r--src/declarative/particles/qsgstochasticdirection.cpp1
-rw-r--r--src/declarative/particles/qsgtargeteddirection.cpp1
-rw-r--r--src/declarative/particles/qsgturbulence.cpp1
-rw-r--r--src/declarative/particles/qsgwander.cpp1
-rw-r--r--src/declarative/qml/qdeclarative.h11
-rw-r--r--src/declarative/qml/qdeclarativecompiler.cpp45
-rw-r--r--src/declarative/qml/qdeclarativecustomparser_p.h3
-rw-r--r--src/declarative/qml/qdeclarativeengine.cpp21
-rw-r--r--src/declarative/qml/qdeclarativeinstruction.cpp3
-rw-r--r--src/declarative/qml/qdeclarativeinstruction_p.h12
-rw-r--r--src/declarative/qml/qdeclarativeparser.cpp2
-rw-r--r--src/declarative/qml/qdeclarativeparser_p.h1
-rw-r--r--src/declarative/qml/qdeclarativeproperty.cpp6
-rw-r--r--src/declarative/qml/qdeclarativescriptparser.cpp1
-rw-r--r--src/declarative/qml/qdeclarativestringconverters.cpp33
-rw-r--r--src/declarative/qml/qdeclarativestringconverters_p.h2
-rw-r--r--src/declarative/qml/qdeclarativevaluetype.cpp216
-rw-r--r--src/declarative/qml/qdeclarativevaluetype_p.h60
-rw-r--r--src/declarative/qml/qdeclarativevme.cpp10
-rw-r--r--src/declarative/qml/qdeclarativevmemetaobject.cpp2
-rw-r--r--src/declarative/qml/qdeclarativexmlhttprequest.cpp73
-rw-r--r--src/declarative/qml/qintrusivelist.cpp6
-rw-r--r--src/declarative/qml/qintrusivelist_p.h13
-rw-r--r--src/declarative/qml/v8/qhashedstring.cpp34
-rw-r--r--src/declarative/qml/v8/qhashedstring_p.h34
-rw-r--r--src/declarative/qml/v8/qjsconverter_p.h3
-rw-r--r--src/declarative/qml/v8/qjsengine.cpp178
-rw-r--r--src/declarative/qml/v8/qjsengine.h4
-rw-r--r--src/declarative/qml/v8/qjsvalue.cpp115
-rw-r--r--src/declarative/qml/v8/qjsvalue.h4
-rw-r--r--src/declarative/qml/v8/qjsvalue_impl_p.h53
-rw-r--r--src/declarative/qml/v8/qjsvalue_p.h33
-rw-r--r--src/declarative/qml/v8/qjsvalueiterator.cpp169
-rw-r--r--src/declarative/qml/v8/qjsvalueiterator.h4
-rw-r--r--src/declarative/qml/v8/qjsvalueiterator_impl_p.h121
-rw-r--r--src/declarative/qml/v8/qjsvalueiterator_p.h68
-rw-r--r--src/declarative/qml/v8/qscript_impl_p.h1
-rw-r--r--src/declarative/qml/v8/qscriptoriginalglobalobject_p.h4
-rw-r--r--src/declarative/qml/v8/qscripttools_p.h182
-rw-r--r--src/declarative/qml/v8/qv8_p.h41
-rw-r--r--src/declarative/qml/v8/qv8bindings.cpp34
-rw-r--r--src/declarative/qml/v8/qv8bindings_p.h34
-rw-r--r--src/declarative/qml/v8/qv8contextwrapper.cpp34
-rw-r--r--src/declarative/qml/v8/qv8debug_p.h1
-rw-r--r--src/declarative/qml/v8/qv8domerrors.cpp73
-rw-r--r--src/declarative/qml/v8/qv8domerrors_p.h (renamed from src/declarative/particles/qsgcustomaffector_p.h)67
-rw-r--r--src/declarative/qml/v8/qv8engine.cpp159
-rw-r--r--src/declarative/qml/v8/qv8engine_impl_p.h30
-rw-r--r--src/declarative/qml/v8/qv8engine_p.h53
-rw-r--r--src/declarative/qml/v8/qv8include.cpp34
-rw-r--r--src/declarative/qml/v8/qv8listwrapper.cpp36
-rw-r--r--src/declarative/qml/v8/qv8listwrapper_p.h34
-rw-r--r--src/declarative/qml/v8/qv8qobjectwrapper.cpp44
-rw-r--r--src/declarative/qml/v8/qv8qobjectwrapper_p.h34
-rw-r--r--src/declarative/qml/v8/qv8stringwrapper.cpp42
-rw-r--r--src/declarative/qml/v8/qv8stringwrapper_p.h34
-rw-r--r--src/declarative/qml/v8/qv8typewrapper.cpp52
-rw-r--r--src/declarative/qml/v8/qv8valuetypewrapper.cpp105
-rw-r--r--src/declarative/qml/v8/qv8valuetypewrapper_p.h6
-rw-r--r--src/declarative/qml/v8/qv8variantwrapper.cpp47
-rw-r--r--src/declarative/qml/v8/qv8variantwrapper_p.h1
-rw-r--r--src/declarative/qml/v8/qv8worker.cpp34
-rw-r--r--src/declarative/qml/v8/qv8worker_p.h34
-rw-r--r--src/declarative/qml/v8/script.pri4
-rw-r--r--src/declarative/qml/v8/v8.pri5
-rw-r--r--src/declarative/scenegraph/coreapi/qsgnode.cpp14
-rw-r--r--src/declarative/scenegraph/coreapi/qsgrenderer.cpp32
-rw-r--r--src/declarative/scenegraph/qsgadaptationlayer_p.h9
-rw-r--r--src/declarative/scenegraph/qsgcontext.cpp68
-rw-r--r--src/declarative/scenegraph/qsgcontext_p.h4
-rw-r--r--src/declarative/scenegraph/qsgdefaultglyphnode_p.h2
-rw-r--r--src/declarative/scenegraph/qsgdistancefieldglyphcache.cpp227
-rw-r--r--src/declarative/scenegraph/qsgdistancefieldglyphcache_p.h70
-rw-r--r--src/declarative/scenegraph/qsgdistancefieldglyphnode.cpp31
-rw-r--r--src/declarative/scenegraph/qsgdistancefieldglyphnode_p.cpp119
-rw-r--r--src/declarative/scenegraph/qsgdistancefieldglyphnode_p.h8
-rw-r--r--src/declarative/scenegraph/qsgdistancefieldglyphnode_p_p.h9
-rw-r--r--src/declarative/scenegraph/util/qsgflatcolormaterial.h2
-rw-r--r--src/declarative/util/qdeclarativeanimation.cpp102
-rw-r--r--src/declarative/util/qdeclarativebehavior.cpp6
-rw-r--r--src/declarative/util/qdeclarativebind.cpp31
-rw-r--r--src/declarative/util/qdeclarativechangeset.cpp688
-rw-r--r--src/declarative/util/qdeclarativechangeset_p.h123
-rw-r--r--src/declarative/util/qdeclarativeconnections.cpp6
-rw-r--r--src/declarative/util/qdeclarativefontloader.cpp8
-rw-r--r--src/declarative/util/qdeclarativelistmodel.cpp24
-rw-r--r--src/declarative/util/qdeclarativelistmodel_p.h1
-rw-r--r--src/declarative/util/qdeclarativepackage.cpp3
-rw-r--r--src/declarative/util/qdeclarativepath.cpp52
-rw-r--r--src/declarative/util/qdeclarativepropertychanges.cpp8
-rw-r--r--src/declarative/util/qdeclarativepropertymap.cpp1
-rw-r--r--src/declarative/util/qdeclarativesmoothedanimation.cpp10
-rw-r--r--src/declarative/util/qdeclarativespringanimation.cpp14
-rw-r--r--src/declarative/util/qdeclarativestate.cpp22
-rw-r--r--src/declarative/util/qdeclarativestate_p.h2
-rw-r--r--src/declarative/util/qdeclarativestate_p_p.h2
-rw-r--r--src/declarative/util/qdeclarativestategroup.cpp32
-rw-r--r--src/declarative/util/qdeclarativestategroup_p.h4
-rw-r--r--src/declarative/util/qdeclarativestateoperations.cpp5
-rw-r--r--src/declarative/util/qdeclarativesystempalette.cpp32
-rw-r--r--src/declarative/util/qdeclarativetimer.cpp18
-rw-r--r--src/declarative/util/qdeclarativetransition.cpp66
-rw-r--r--src/declarative/util/qdeclarativetransition_p.h5
-rw-r--r--src/declarative/util/qdeclarativetransitionmanager.cpp2
-rw-r--r--src/declarative/util/qdeclarativeutilmodule.cpp4
-rw-r--r--src/declarative/util/qdeclarativexmllistmodel.cpp347
-rw-r--r--src/declarative/util/qlistmodelinterface.cpp1
-rw-r--r--src/declarative/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch2
-rw-r--r--src/declarative/v8/0002-Add-a-bit-field-3-to-Map.patch2
-rw-r--r--src/declarative/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch2
-rw-r--r--src/declarative/v8/0004-Generalize-external-object-resources.patch2
-rw-r--r--src/declarative/v8/0005-Introduce-a-QML-compilation-mode.patch2
-rw-r--r--src/declarative/v8/0006-Allow-access-to-the-calling-script-data.patch2
-rw-r--r--src/declarative/v8/0007-Fix-warnings.patch2
-rw-r--r--src/declarative/v8/0008-Add-custom-object-compare-callback.patch2
-rw-r--r--src/declarative/v8/0009-Add-CallAsFunction-method-to-the-Object-class-in-the.patch (renamed from src/v8/0009-Add-CallAsFunction-method-to-the-Object-class-in-the.patch)26
-rw-r--r--src/declarative/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch (renamed from src/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch)36
-rw-r--r--src/declarative/v8/0011-QtScript-V8-Add-new-v8-api-to-check-if-a-value-is-an.patch (renamed from src/v8/0011-QtScript-V8-Add-new-v8-api-to-check-if-a-value-is-an.patch)10
-rw-r--r--src/declarative/v8/0012-Add-IsCallable-method-for-Object-in-the-API.patch116
-rw-r--r--src/declarative/v8/0013-Remove-execute-flag-from-v8-debug.h.patch15
-rw-r--r--src/declarative/v8/v8base.pri9
-rwxr-xr-xsrc/declarative/v8/wrapcc.pl36
-rw-r--r--src/imports/testlib/SignalSpy.qml6
-rw-r--r--src/imports/testlib/TestCase.qml4
-rw-r--r--src/imports/testlib/main.cpp8
-rw-r--r--src/qmltest/quicktest.cpp13
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeanimatedimage.cpp2
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeborderimage.cpp6
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeflickable.cpp9
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeflipable.cpp2
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativegridview.cpp22
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeimage.cpp2
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeitem.cpp10
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativelistview.cpp27
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeloader.cpp14
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativemousearea.cpp12
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativepath.cpp4
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativepathview.cpp27
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativepathview_p.h1
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativepositioners.cpp8
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativerectangle.cpp10
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativerepeater.cpp10
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativescalegrid.cpp2
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativetext.cpp2
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativevisualitemmodel.cpp6
-rw-r--r--src/qtquick1/util/qdeclarativeanimation.cpp30
-rw-r--r--src/qtquick1/util/qdeclarativebehavior.cpp2
-rw-r--r--src/qtquick1/util/qdeclarativebind.cpp3
-rw-r--r--src/qtquick1/util/qdeclarativelistmodel.cpp16
-rw-r--r--src/qtquick1/util/qdeclarativepropertychanges.cpp6
-rw-r--r--src/qtquick1/util/qdeclarativesmoothedanimation.cpp2
-rw-r--r--src/qtquick1/util/qdeclarativespringanimation.cpp2
-rw-r--r--src/qtquick1/util/qdeclarativestate.cpp4
-rw-r--r--src/qtquick1/util/qdeclarativestategroup.cpp4
-rw-r--r--src/qtquick1/util/qdeclarativestateoperations.cpp4
-rw-r--r--src/qtquick1/util/qdeclarativesystempalette.cpp2
-rw-r--r--src/qtquick1/util/qdeclarativetransition.cpp14
-rw-r--r--src/qtquick1/util/qdeclarativexmllistmodel.cpp6
262 files changed, 14669 insertions, 5259 deletions
diff --git a/src/declarative/debugger/debugger.pri b/src/declarative/debugger/debugger.pri
index 3134c79d98..e7462d4e78 100644
--- a/src/declarative/debugger/debugger.pri
+++ b/src/declarative/debugger/debugger.pri
@@ -10,8 +10,7 @@ SOURCES += \
$$PWD/qdeclarativedebughelper.cpp \
$$PWD/qdeclarativedebugserver.cpp \
$$PWD/qdeclarativeinspectorservice.cpp \
- $$PWD/qjsdebuggeragent.cpp \
- $$PWD/qjsdebugservice.cpp
+ $$PWD/qv8debugservice.cpp
HEADERS += \
$$PWD/qdeclarativedebuggerstatus_p.h \
@@ -26,5 +25,4 @@ HEADERS += \
$$PWD/qdeclarativedebugserverconnection_p.h \
$$PWD/qdeclarativeinspectorservice_p.h \
$$PWD/qdeclarativeinspectorinterface_p.h \
- $$PWD/qjsdebuggeragent_p.h \
- $$PWD/qjsdebugservice_p.h
+ $$PWD/qv8debugservice_p.h
diff --git a/src/declarative/debugger/qdeclarativedebugserver.cpp b/src/declarative/debugger/qdeclarativedebugserver.cpp
index a69e01a6fe..e7785d0f90 100644
--- a/src/declarative/debugger/qdeclarativedebugserver.cpp
+++ b/src/declarative/debugger/qdeclarativedebugserver.cpp
@@ -91,6 +91,7 @@ public:
QStringList clientPlugins;
bool gotHello;
QString waitingForMsgFromService;
+ bool waitingForMsgSucceeded;
private:
// private slot
@@ -100,7 +101,8 @@ private:
QDeclarativeDebugServerPrivate::QDeclarativeDebugServerPrivate() :
connection(0),
- gotHello(false)
+ gotHello(false),
+ waitingForMsgSucceeded(false)
{
}
@@ -313,7 +315,7 @@ void QDeclarativeDebugServer::receiveMessage(const QByteArray &message)
if (d->waitingForMsgFromService == name) {
// deliver directly so that it is delivered before waitForMessage is returning.
d->_q_deliverMessage(name, message);
- d->waitingForMsgFromService.clear();
+ d->waitingForMsgSucceeded = true;
} else {
// deliver message in next event loop run.
// Fixes the case that the service does start it's own event loop ...,
@@ -403,11 +405,13 @@ bool QDeclarativeDebugServer::waitForMessage(QDeclarativeDebugService *service)
|| !d->waitingForMsgFromService.isEmpty())
return false;
+ d->waitingForMsgSucceeded = false;
d->waitingForMsgFromService = service->name();
do {
d->connection->waitForMessage();
- } while (!d->waitingForMsgFromService.isEmpty());
+ } while (!d->waitingForMsgSucceeded);
+ d->waitingForMsgFromService.clear();
return true;
}
diff --git a/src/declarative/debugger/qdeclarativedebugservice.cpp b/src/declarative/debugger/qdeclarativedebugservice.cpp
index 969ab35ce8..7274211bf2 100644
--- a/src/declarative/debugger/qdeclarativedebugservice.cpp
+++ b/src/declarative/debugger/qdeclarativedebugservice.cpp
@@ -72,6 +72,26 @@ QDeclarativeDebugService::QDeclarativeDebugService(const QString &name, QObject
}
}
+QDeclarativeDebugService::QDeclarativeDebugService(QDeclarativeDebugServicePrivate &dd,
+ const QString &name, QObject *parent)
+ : QObject(dd, parent)
+{
+ Q_D(QDeclarativeDebugService);
+ d->name = name;
+ d->server = QDeclarativeDebugServer::instance();
+ d->status = QDeclarativeDebugService::NotConnected;
+
+ if (!d->server)
+ return;
+
+ if (d->server->serviceNames().contains(name)) {
+ qWarning() << "QDeclarativeDebugService: Conflicting plugin name" << name;
+ d->server = 0;
+ } else {
+ d->server->addService(this);
+ }
+}
+
QDeclarativeDebugService::~QDeclarativeDebugService()
{
Q_D(const QDeclarativeDebugService);
diff --git a/src/declarative/debugger/qdeclarativedebugservice_p.h b/src/declarative/debugger/qdeclarativedebugservice_p.h
index 4f1f1a6bd8..84e63c0ddc 100644
--- a/src/declarative/debugger/qdeclarativedebugservice_p.h
+++ b/src/declarative/debugger/qdeclarativedebugservice_p.h
@@ -80,6 +80,7 @@ public:
static bool hasDebuggingClient();
protected:
+ QDeclarativeDebugService(QDeclarativeDebugServicePrivate &dd, const QString &, QObject *parent = 0);
virtual void statusChanged(Status);
virtual void messageReceived(const QByteArray &);
diff --git a/src/declarative/debugger/qjsdebuggeragent.cpp b/src/declarative/debugger/qjsdebuggeragent.cpp
deleted file mode 100644
index f47def802a..0000000000
--- a/src/declarative/debugger/qjsdebuggeragent.cpp
+++ /dev/null
@@ -1,571 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "private/qjsdebuggeragent_p.h"
-#include "private/qdeclarativedebughelper_p.h"
-
-#include <QtCore/qdatetime.h>
-#include <QtCore/qcoreapplication.h>
-#include <QtCore/qset.h>
-#include <QtCore/qurl.h>
-#include <QtDeclarative/qjsengine.h>
-
-#include <QtCore/qstringlist.h>
-
-QT_BEGIN_NAMESPACE
-
-class QJSDebuggerAgentPrivate
-{
-public:
- QJSDebuggerAgentPrivate(QJSDebuggerAgent *q)
- : q(q), state(NoState), isInitialized(false)
- {}
-
- void continueExec();
- void recordKnownObjects(const QList<JSAgentWatchData> &);
- QList<JSAgentWatchData> getLocals(void *);
- void positionChange(qint64 scriptId, int lineNumber, int columnNumber);
- QJSEngine *engine() { return q->engine(); }
- void stopped();
-
-public:
- QJSDebuggerAgent *q;
- JSDebuggerState state;
- int stepDepth;
- int stepCount;
-
- QEventLoop loop;
- QHash<qint64, QString> filenames;
- JSAgentBreakpoints breakpoints;
- // breakpoints by filename (without path)
- QHash<QString, JSAgentBreakpointData> fileNameToBreakpoints;
- QStringList watchExpressions;
- QSet<qint64> knownObjectIds;
- bool isInitialized;
-};
-
-namespace {
-
-class SetupExecEnv
-{
-public:
- SetupExecEnv(QJSDebuggerAgentPrivate *a)
- : agent(a),
- previousState(a->state),
- hadException(a->engine()->hasUncaughtException())
- {
- agent->state = StoppedState;
- }
-
- ~SetupExecEnv()
- {
- if (!hadException && agent->engine()->hasUncaughtException())
- agent->engine()->clearExceptions();
- agent->state = previousState;
- }
-
-private:
- QJSDebuggerAgentPrivate *agent;
- JSDebuggerState previousState;
- bool hadException;
-};
-
-} // anonymous namespace
-
-static JSAgentWatchData fromScriptValue(const QString &expression,
- const QJSValue &value)
-{
- static const QString arrayStr = QCoreApplication::translate
- ("Debugger::JSAgentWatchData", "[Array of length %1]");
- static const QString undefinedStr = QCoreApplication::translate
- ("Debugger::JSAgentWatchData", "<undefined>");
-
- JSAgentWatchData data;
- data.exp = expression.toUtf8();
- data.name = data.exp;
- data.hasChildren = false;
- data.value = value.toString().toUtf8();
- // data.objectId = value.objectId();
- if (value.isArray()) {
- data.type = "Array";
- data.value = arrayStr.arg(value.property(QLatin1String("length")).toString()).toUtf8();
- data.hasChildren = true;
- } else if (value.isBool()) {
- data.type = "Bool";
- // data.value = value.toBool() ? "true" : "false";
- } else if (value.isDate()) {
- data.type = "Date";
- data.value = value.toDateTime().toString().toUtf8();
- } else if (value.isError()) {
- data.type = "Error";
- } else if (value.isFunction()) {
- data.type = "Function";
- } else if (value.isUndefined()) {
- data.type = undefinedStr.toUtf8();
- } else if (value.isNumber()) {
- data.type = "Number";
- } else if (value.isRegExp()) {
- data.type = "RegExp";
- } else if (value.isString()) {
- data.type = "String";
- } else if (value.isVariant()) {
- data.type = "Variant";
- } else if (value.isQObject()) {
- const QObject *obj = value.toQObject();
- data.type = "Object";
- data.value += '[';
- data.value += obj->metaObject()->className();
- data.value += ']';
- data.hasChildren = true;
- } else if (value.isObject()) {
- data.type = "Object";
- data.hasChildren = true;
- data.value = "[Object]";
- } else if (value.isNull()) {
- data.type = "<null>";
- } else {
- data.type = "<unknown>";
- }
- return data;
-}
-
-static QList<JSAgentWatchData> expandObject(const QJSValue &object)
-{
- QList<JSAgentWatchData> result;
-// QScriptValueIterator it(object);
-// while (it.hasNext()) {
-// it.next();
-// if (it.flags() & QScriptValue::SkipInEnumeration)
-// continue;
-// if (/*object.isQObject() &&*/ it.value().isFunction()) {
-// // Cosmetics: skip all functions and slot, there are too many of them,
-// // and it is not useful information in the debugger.
-// continue;
-// }
-// JSAgentWatchData data = fromScriptValue(it.name(), it.value());
-// result.append(data);
-// }
-// if (result.isEmpty()) {
-// JSAgentWatchData data;
-// data.name = "<no initialized data>";
-// data.hasChildren = false;
-// data.value = " ";
-// data.objectId = 0;
-// result.append(data);
-// }
- return result;
-}
-
-static QString fileName(const QString &fileUrl)
-{
- int lastDelimiterPos = fileUrl.lastIndexOf(QLatin1Char('/'));
- return fileUrl.mid(lastDelimiterPos, fileUrl.size() - lastDelimiterPos);
-}
-
-void QJSDebuggerAgentPrivate::recordKnownObjects(const QList<JSAgentWatchData>& list)
-{
- foreach (const JSAgentWatchData &data, list)
- knownObjectIds << data.objectId;
-}
-
-QList<JSAgentWatchData> QJSDebuggerAgentPrivate::getLocals(void *ctx)
-{
- QList<JSAgentWatchData> locals;
-// if (ctx) {
-// QScriptValue activationObject = ctx->activationObject();
-// QScriptValue thisObject = ctx->thisObject();
-// locals = expandObject(activationObject);
-// if (thisObject.isObject()
-// && thisObject.objectId() != engine()->globalObject().objectId()
-// && QScriptValueIterator(thisObject).hasNext())
-// locals.prepend(fromScriptValue(QLatin1String("this"), thisObject));
-// recordKnownObjects(locals);
-// knownObjectIds << activationObject.objectId();
-// }
- return locals;
-}
-
-/*!
- Constructs a new agent for the given \a engine. The agent will
- report debugging-related events (e.g. step completion) to the given
- \a backend.
-*/
-QJSDebuggerAgent::QJSDebuggerAgent(QJSEngine *engine, QObject *parent)
- : QObject(parent)
- , d(new QJSDebuggerAgentPrivate(this))
-{
- //QJSDebuggerAgent::engine()->setAgent(this);
-}
-
-QJSDebuggerAgent::QJSDebuggerAgent(QDeclarativeEngine *engine, QObject *parent)
- : QObject(parent)
- , d(new QJSDebuggerAgentPrivate(this))
-{
- //QJSDebuggerAgent::engine()->setAgent(this);
-}
-
-/*!
- Destroys this QJSDebuggerAgent.
-*/
-QJSDebuggerAgent::~QJSDebuggerAgent()
-{
- //engine()->setAgent(0);
- delete d;
-}
-
-/*!
- Indicates whether the agent got the list of breakpoints.
- */
-bool QJSDebuggerAgent::isInitialized() const
-{
- return d->isInitialized;
-}
-
-void QJSDebuggerAgent::setBreakpoints(const JSAgentBreakpoints &breakpoints)
-{
- d->breakpoints = breakpoints;
-
- d->fileNameToBreakpoints.clear();
- foreach (const JSAgentBreakpointData &bp, breakpoints)
- d->fileNameToBreakpoints.insertMulti(fileName(QString::fromUtf8(bp.fileUrl)), bp);
-
- d->isInitialized = true;
-}
-
-void QJSDebuggerAgent::setWatchExpressions(const QStringList &watchExpressions)
-{
- d->watchExpressions = watchExpressions;
-}
-
-void QJSDebuggerAgent::stepOver()
-{
- d->stepDepth = 0;
- d->state = SteppingOverState;
- d->continueExec();
-}
-
-void QJSDebuggerAgent::stepInto()
-{
- d->stepDepth = 0;
- d->state = SteppingIntoState;
- d->continueExec();
-}
-
-void QJSDebuggerAgent::stepOut()
-{
- d->stepDepth = 0;
- d->state = SteppingOutState;
- d->continueExec();
-}
-
-void QJSDebuggerAgent::continueExecution()
-{
- d->state = NoState;
- d->continueExec();
-}
-
-JSAgentWatchData QJSDebuggerAgent::executeExpression(const QString &expr)
-{
- SetupExecEnv execEnv(d);
-
- JSAgentWatchData data = fromScriptValue(expr, engine()->evaluate(expr));
- d->knownObjectIds << data.objectId;
- return data;
-}
-
-QList<JSAgentWatchData> QJSDebuggerAgent::expandObjectById(quint64 objectId)
-{
- SetupExecEnv execEnv(d);
-
- QJSValue v;
-// if (d->knownObjectIds.contains(objectId))
-// v = engine()->objectById(objectId);
-
- QList<JSAgentWatchData> result = expandObject(v);
- d->recordKnownObjects(result);
- return result;
-}
-
-QList<JSAgentWatchData> QJSDebuggerAgent::locals()
-{
- SetupExecEnv execEnv(d);
- return d->getLocals(0/*engine()->currentContext()*/);
-}
-
-QList<JSAgentWatchData> QJSDebuggerAgent::localsAtFrame(int frameId)
-{
- SetupExecEnv execEnv(d);
-
-// int deep = 0;
-// QScriptContext *ctx = engine()->currentContext();
-// while (ctx && deep < frameId) {
-// ctx = ctx->parentContext();
-// deep++;
-// }
-
- return d->getLocals(0/*ctx*/);
-}
-
-QList<JSAgentStackData> QJSDebuggerAgent::backtrace()
-{
- SetupExecEnv execEnv(d);
-
- QList<JSAgentStackData> backtrace;
-
-// for (QScriptContext *ctx = engine()->currentContext(); ctx; ctx = ctx->parentContext()) {
-// QScriptContextInfo info(ctx);
-
-// JSAgentStackData frame;
-// frame.functionName = info.functionName().toUtf8();
-// if (frame.functionName.isEmpty()) {
-// if (ctx->parentContext()) {
-// switch (info.functionType()) {
-// case QScriptContextInfo::ScriptFunction:
-// frame.functionName = "<anonymous>";
-// break;
-// case QScriptContextInfo::NativeFunction:
-// frame.functionName = "<native>";
-// break;
-// case QScriptContextInfo::QtFunction:
-// case QScriptContextInfo::QtPropertyFunction:
-// frame.functionName = "<native slot>";
-// break;
-// }
-// } else {
-// frame.functionName = "<global>";
-// }
-// }
-// frame.lineNumber = info.lineNumber();
-// // if the line number is unknown, fallback to the function line number
-// if (frame.lineNumber == -1)
-// frame.lineNumber = info.functionStartLineNumber();
-
-// frame.fileUrl = info.fileName().toUtf8();
-// backtrace.append(frame);
-// }
-
- return backtrace;
-}
-
-QList<JSAgentWatchData> QJSDebuggerAgent::watches()
-{
- SetupExecEnv execEnv(d);
-
- QList<JSAgentWatchData> watches;
- foreach (const QString &expr, d->watchExpressions)
- watches << fromScriptValue(expr, engine()->evaluate(expr));
- d->recordKnownObjects(watches);
- return watches;
-}
-
-void QJSDebuggerAgent::setProperty(qint64 objectId,
- const QString &property,
- const QString &value)
-{
- SetupExecEnv execEnv(d);
-
- if (d->knownObjectIds.contains(objectId)) {
- QJSValue object;// = engine()->objectById(objectId);
- if (object.isObject()) {
- QJSValue result = engine()->evaluate(value);
- object.setProperty(property, result);
- }
- }
-}
-
-/*!
- \reimp
-*/
-void QJSDebuggerAgent::scriptLoad(qint64 id, const QString &program,
- const QString &fileName, int)
-{
- Q_UNUSED(program);
- d->filenames.insert(id, fileName);
-}
-
-/*!
- \reimp
-*/
-void QJSDebuggerAgent::scriptUnload(qint64 id)
-{
- d->filenames.remove(id);
-}
-
-/*!
- \reimp
-*/
-void QJSDebuggerAgent::contextPush()
-{
-}
-
-/*!
- \reimp
-*/
-void QJSDebuggerAgent::contextPop()
-{
-}
-
-/*!
- \reimp
-*/
-void QJSDebuggerAgent::functionEntry(qint64 scriptId)
-{
- Q_UNUSED(scriptId);
- d->stepDepth++;
-}
-
-/*!
- \reimp
-*/
-void QJSDebuggerAgent::functionExit(qint64 scriptId, const QJSValue &returnValue)
-{
- Q_UNUSED(scriptId);
- Q_UNUSED(returnValue);
- d->stepDepth--;
-}
-
-/*!
- \reimp
-*/
-void QJSDebuggerAgent::positionChange(qint64 scriptId, int lineNumber, int columnNumber)
-{
- d->positionChange(scriptId, lineNumber, columnNumber);
-}
-
-void QJSDebuggerAgentPrivate::positionChange(qint64 scriptId, int lineNumber, int columnNumber)
-{
- Q_UNUSED(columnNumber);
-
-// if (state == StoppedState)
-// return; //no re-entrency
-
-// // check breakpoints
-// if (!breakpoints.isEmpty()) {
-// QHash<qint64, QString>::const_iterator it = filenames.constFind(scriptId);
-// QScriptContext *ctx = engine()->currentContext();
-// QScriptContextInfo info(ctx);
-// if (it == filenames.constEnd()) {
-// // It is possible that the scripts are loaded before the agent is attached
-// QString filename = info.fileName();
-
-// JSAgentStackData frame;
-// frame.functionName = info.functionName().toUtf8();
-
-// QPair<QString, qint32> key = qMakePair(filename, lineNumber);
-// it = filenames.insert(scriptId, filename);
-// }
-
-// const QString filePath = it.value();
-// JSAgentBreakpoints bps = fileNameToBreakpoints.values(fileName(filePath)).toSet();
-
-// foreach (const JSAgentBreakpointData &bp, bps) {
-// if (bp.lineNumber == lineNumber) {
-// stopped();
-// return;
-// }
-// }
-// }
-
-// switch (state) {
-// case NoState:
-// case StoppedState:
-// // Do nothing
-// break;
-// case SteppingOutState:
-// if (stepDepth >= 0)
-// break;
-// //fallthough
-// case SteppingOverState:
-// if (stepDepth > 0)
-// break;
-// //fallthough
-// case SteppingIntoState:
-// stopped();
-// break;
-// }
-
-}
-
-/*!
- \reimp
-*/
-void QJSDebuggerAgent::exceptionThrow(qint64 scriptId,
- const QJSValue &exception,
- bool hasHandler)
-{
- Q_UNUSED(scriptId);
- Q_UNUSED(exception);
- Q_UNUSED(hasHandler);
-// qDebug() << Q_FUNC_INFO << exception.toString() << hasHandler;
-#if 0 //sometimes, we get exceptions that we should just ignore.
- if (!hasHandler && state != StoppedState)
- stopped(true, exception);
-#endif
-}
-
-/*!
- \reimp
-*/
-void QJSDebuggerAgent::exceptionCatch(qint64 scriptId, const QJSValue &exception)
-{
- Q_UNUSED(scriptId);
- Q_UNUSED(exception);
-}
-
-void QJSDebuggerAgentPrivate::stopped()
-{
- bool becauseOfException = false;
- const QJSValue &exception = QJSValue();
-
- knownObjectIds.clear();
- state = StoppedState;
-
- emit q->stopped(becauseOfException, exception.toString());
-
- loop.exec(QEventLoop::ExcludeUserInputEvents);
-}
-
-void QJSDebuggerAgentPrivate::continueExec()
-{
- loop.quit();
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qjsdebuggeragent_p.h b/src/declarative/debugger/qjsdebuggeragent_p.h
deleted file mode 100644
index 30cbfe67b4..0000000000
--- a/src/declarative/debugger/qjsdebuggeragent_p.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QJSDEBUGGERAGENT_P_H
-#define QJSDEBUGGERAGENT_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qset.h>
-#include <QtDeclarative/qjsengine.h>
-
-QT_BEGIN_NAMESPACE
-class QJSValue;
-class QDeclarativeEngine;
-QT_END_NAMESPACE
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QJSDebuggerAgentPrivate;
-
-enum JSDebuggerState
-{
- NoState,
- SteppingIntoState,
- SteppingOverState,
- SteppingOutState,
- StoppedState
-};
-
-struct JSAgentWatchData
-{
- QByteArray exp;
- QByteArray name;
- QByteArray value;
- QByteArray type;
- bool hasChildren;
- quint64 objectId;
-};
-
-inline QDataStream &operator<<(QDataStream &s, const JSAgentWatchData &data)
-{
- return s << data.exp << data.name << data.value
- << data.type << data.hasChildren << data.objectId;
-}
-
-struct JSAgentStackData
-{
- QByteArray functionName;
- QByteArray fileUrl;
- qint32 lineNumber;
-};
-
-inline QDataStream &operator<<(QDataStream &s, const JSAgentStackData &data)
-{
- return s << data.functionName << data.fileUrl << data.lineNumber;
-}
-
-struct JSAgentBreakpointData
-{
- QByteArray functionName;
- QByteArray fileUrl;
- qint32 lineNumber;
-};
-
-typedef QSet<JSAgentBreakpointData> JSAgentBreakpoints;
-
-inline QDataStream &operator<<(QDataStream &s, const JSAgentBreakpointData &data)
-{
- return s << data.functionName << data.fileUrl << data.lineNumber;
-}
-
-inline QDataStream &operator>>(QDataStream &s, JSAgentBreakpointData &data)
-{
- return s >> data.functionName >> data.fileUrl >> data.lineNumber;
-}
-
-inline bool operator==(const JSAgentBreakpointData &b1, const JSAgentBreakpointData &b2)
-{
- return b1.lineNumber == b2.lineNumber && b1.fileUrl == b2.fileUrl;
-}
-
-inline uint qHash(const JSAgentBreakpointData &b)
-{
- return b.lineNumber ^ qHash(b.fileUrl);
-}
-
-
-class QJSDebuggerAgent : public QObject
-{
- Q_OBJECT
-
-public:
- QJSDebuggerAgent(QJSEngine *engine, QObject *parent = 0);
- QJSDebuggerAgent(QDeclarativeEngine *engine, QObject *parent = 0);
- ~QJSDebuggerAgent();
-
- bool isInitialized() const;
- QJSEngine * engine() {return 0; }
-
- void setBreakpoints(const JSAgentBreakpoints &);
- void setWatchExpressions(const QStringList &);
-
- void stepOver();
- void stepInto();
- void stepOut();
- void continueExecution();
-
- JSAgentWatchData executeExpression(const QString &expr);
- QList<JSAgentWatchData> expandObjectById(quint64 objectId);
- QList<JSAgentWatchData> locals();
- QList<JSAgentWatchData> localsAtFrame(int frameId);
- QList<JSAgentStackData> backtrace();
- QList<JSAgentWatchData> watches();
- void setProperty(qint64 objectId,
- const QString &property,
- const QString &value);
-
- // reimplemented
- void scriptLoad(qint64 id, const QString &program,
- const QString &fileName, int baseLineNumber);
- void scriptUnload(qint64 id);
-
- void contextPush();
- void contextPop();
-
- void functionEntry(qint64 scriptId);
- void functionExit(qint64 scriptId,
- const QJSValue &returnValue);
-
- void positionChange(qint64 scriptId,
- int lineNumber, int columnNumber);
-
- void exceptionThrow(qint64 scriptId,
- const QJSValue &exception,
- bool hasHandler);
- void exceptionCatch(qint64 scriptId,
- const QJSValue &exception);
-
-Q_SIGNALS:
- void stopped(bool becauseOfException,
- const QString &exception);
-
-private:
- friend class QJSDebuggerAgentPrivate;
- QJSDebuggerAgentPrivate *d;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QJSDEBUGGERAGENT_P_H
diff --git a/src/declarative/debugger/qjsdebugservice.cpp b/src/declarative/debugger/qjsdebugservice.cpp
deleted file mode 100644
index ad84f656f7..0000000000
--- a/src/declarative/debugger/qjsdebugservice.cpp
+++ /dev/null
@@ -1,208 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "private/qjsdebugservice_p.h"
-#include "private/qjsdebuggeragent_p.h"
-
-#include <QtCore/qdatastream.h>
-#include <QtCore/qdebug.h>
-#include <QtCore/qstringlist.h>
-#include <QtDeclarative/qdeclarativeengine.h>
-
-Q_GLOBAL_STATIC(QJSDebugService, serviceInstance)
-
-QJSDebugService::QJSDebugService(QObject *parent)
- : QDeclarativeDebugService(QLatin1String("JSDebugger"), parent)
- , m_agent(0)
-{
-}
-
-QJSDebugService::~QJSDebugService()
-{
- delete m_agent;
-}
-
-QJSDebugService *QJSDebugService::instance()
-{
- return serviceInstance();
-}
-
-void QJSDebugService::addEngine(QDeclarativeEngine *engine)
-{
- Q_ASSERT(engine);
- Q_ASSERT(!m_engines.contains(engine));
-
- m_engines.append(engine);
-
- if (status() == Enabled && !m_engines.isEmpty() && !m_agent) {
- m_agent = new QJSDebuggerAgent(engine, engine);
- connect(m_agent, SIGNAL(stopped(bool,QString)),
- this, SLOT(executionStopped(bool,QString)));
-
- while (!m_agent->isInitialized()) {
- waitForMessage();
- }
- }
-}
-
-void QJSDebugService::removeEngine(QDeclarativeEngine *engine)
-{
- Q_ASSERT(engine);
- Q_ASSERT(m_engines.contains(engine));
-
- m_engines.removeAll(engine);
-}
-
-void QJSDebugService::statusChanged(Status status)
-{
- if (status == Enabled && !m_engines.isEmpty() && !m_agent) {
- // Multiple engines are currently unsupported
- QDeclarativeEngine *engine = m_engines.first();
- m_agent = new QJSDebuggerAgent(engine, engine);
-
- connect(m_agent, SIGNAL(stopped(bool,QString)),
- this, SLOT(executionStopped(bool,QString)));
-
- } else if (status != Enabled && m_agent) {
- delete m_agent;
- m_agent = 0;
- }
-}
-
-void QJSDebugService::messageReceived(const QByteArray &message)
-{
- if (!m_agent) {
- qWarning() << "QJSDebugService::messageReceived: No QJSDebuggerAgent available";
- return;
- }
-
- QDataStream ds(message);
- QByteArray command;
- ds >> command;
- if (command == "BREAKPOINTS") {
- JSAgentBreakpoints breakpoints;
- ds >> breakpoints;
- m_agent->setBreakpoints(breakpoints);
-
- //qDebug() << "BREAKPOINTS";
- //foreach (const JSAgentBreakpointData &bp, breakpoints)
- // qDebug() << "BREAKPOINT: " << bp.fileUrl << bp.lineNumber;
- } else if (command == "WATCH_EXPRESSIONS") {
- QStringList watchExpressions;
- ds >> watchExpressions;
- m_agent->setWatchExpressions(watchExpressions);
- } else if (command == "STEPOVER") {
- m_agent->stepOver();
- } else if (command == "STEPINTO" || command == "INTERRUPT") {
- m_agent->stepInto();
- } else if (command == "STEPOUT") {
- m_agent->stepOut();
- } else if (command == "CONTINUE") {
- m_agent->continueExecution();
- } else if (command == "EXEC") {
- QByteArray id;
- QString expr;
- ds >> id >> expr;
-
- JSAgentWatchData data = m_agent->executeExpression(expr);
-
- QByteArray reply;
- QDataStream rs(&reply, QIODevice::WriteOnly);
- rs << QByteArray("RESULT") << id << data;
- sendMessage(reply);
- } else if (command == "EXPAND") {
- QByteArray requestId;
- quint64 objectId;
- ds >> requestId >> objectId;
-
- QList<JSAgentWatchData> result = m_agent->expandObjectById(objectId);
-
- QByteArray reply;
- QDataStream rs(&reply, QIODevice::WriteOnly);
- rs << QByteArray("EXPANDED") << requestId << result;
- sendMessage(reply);
- } else if (command == "ACTIVATE_FRAME") {
- int frameId;
- ds >> frameId;
-
- QList<JSAgentWatchData> locals = m_agent->localsAtFrame(frameId);
-
- QByteArray reply;
- QDataStream rs(&reply, QIODevice::WriteOnly);
- rs << QByteArray("LOCALS") << frameId << locals;
- sendMessage(reply);
- } else if (command == "SET_PROPERTY") {
- QByteArray id;
- qint64 objectId;
- QString property;
- QString value;
- ds >> id >> objectId >> property >> value;
-
- m_agent->setProperty(objectId, property, value);
-
- //TODO: feedback
- } else if (command == "PING") {
- int ping;
- ds >> ping;
- QByteArray reply;
- QDataStream rs(&reply, QIODevice::WriteOnly);
- rs << QByteArray("PONG") << ping;
- sendMessage(reply);
- } else {
- qDebug() << Q_FUNC_INFO << "Unknown command" << command;
- }
-
- QDeclarativeDebugService::messageReceived(message);
-}
-
-void QJSDebugService::executionStopped(bool becauseOfException,
- const QString &exception)
-{
- const QList<JSAgentStackData> backtrace = m_agent->backtrace();
- const QList<JSAgentWatchData> watches = m_agent->watches();
- const QList<JSAgentWatchData> locals = m_agent->locals();
-
- QByteArray reply;
- QDataStream rs(&reply, QIODevice::WriteOnly);
- rs << QByteArray("STOPPED") << backtrace << watches << locals
- << becauseOfException << exception;
- sendMessage(reply);
-}
diff --git a/src/declarative/debugger/qv8debugservice.cpp b/src/declarative/debugger/qv8debugservice.cpp
new file mode 100644
index 0000000000..7d3f45e35e
--- /dev/null
+++ b/src/declarative/debugger/qv8debugservice.cpp
@@ -0,0 +1,274 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv8debugservice_p.h"
+#include "qdeclarativedebugservice_p_p.h"
+#include "qv8debug_p.h"
+#include "qv8engine_p.h"
+#include "qdeclarativeengine_p.h"
+
+#include <QtCore/QEventLoop>
+#include <QtCore/QHash>
+#include <QtCore/QFileInfo>
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC(QV8DebugService, v8ServiceInstance)
+
+void DebugMessageHandler(const v8::Debug::Message& message)
+{
+ v8::DebugEvent event = message.GetEvent();
+ if (event != v8::Break && event != v8::Exception && event != v8::AfterCompile) {
+ return;
+ }
+
+ QByteArray response(QV8Engine::toStringStatic(message.GetJSON()).toUtf8());
+
+ QV8DebugService *service = QV8DebugService::instance();
+ service->debugMessageHandler(response);
+
+ if (event == v8::Break && !message.WillStartRunning()) {
+ service->executionStopped();
+ } else if (event == v8::AfterCompile) {
+ service->appendSourcePath(response);
+ } //TODO::v8::Exception
+}
+
+class QV8DebugServicePrivate : public QDeclarativeDebugServicePrivate
+{
+public:
+ QV8DebugServicePrivate()
+ :initialized(false)
+ {
+ //Create a new isolate
+ isolate = v8::Isolate::New();
+
+ //Enter the isolate and initialize
+ v8::Isolate::Scope i_scope(isolate);
+ v8::V8::Initialize();
+
+ //Create an instance in the new isolate
+ engine = new QJSEngine();
+ }
+
+ ~QV8DebugServicePrivate()
+ {
+ delete engine;
+ isolate->Dispose();
+ }
+
+ bool initialized;
+ QJSEngine *engine;
+ v8::Isolate *isolate;
+ QList<QDeclarativeEngine *> engines;
+ QEventLoop loop;
+ QHash<QString,QString> sourcePath;
+ QHash<QString,QByteArray> requestCache;
+};
+
+QV8DebugService::QV8DebugService(QObject *parent)
+ : QDeclarativeDebugService(*(new QV8DebugServicePrivate()), QLatin1String("V8Debugger"), parent)
+{
+ Q_D(QV8DebugService);
+ v8::Debug::SetMessageHandler2(DebugMessageHandler);
+ if (status() == Enabled) {
+ // ,block mode, client attached
+ while (!d->initialized) {
+ waitForMessage();
+ }
+ }
+}
+
+QV8DebugService::~QV8DebugService()
+{
+}
+
+QV8DebugService *QV8DebugService::instance()
+{
+ return v8ServiceInstance();
+}
+
+void QV8DebugService::addEngine(QDeclarativeEngine *engine)
+{
+ Q_D(QV8DebugService);
+ Q_ASSERT(engine);
+ Q_ASSERT(!d->engines.contains(engine));
+
+ d->engines.append(engine);
+}
+
+void QV8DebugService::removeEngine(QDeclarativeEngine *engine)
+{
+ Q_D(QV8DebugService);
+ Q_ASSERT(engine);
+ Q_ASSERT(d->engines.contains(engine));
+
+ d->engines.removeAll(engine);
+}
+
+void QV8DebugService::debugMessageHandler(QByteArray message)
+{
+ sendMessage(packMessage(message));
+}
+
+void QV8DebugService::executionStopped()
+{
+ Q_D(QV8DebugService);
+
+ if (!d->loop.isRunning()) {
+ d->loop.exec(QEventLoop::ExcludeUserInputEvents);
+ }
+}
+
+void QV8DebugService::appendSourcePath(QByteArray message)
+{
+ Q_D(QV8DebugService);
+
+ QVariantMap msgMap;
+ /* Parse the byte string in a separate isolate
+ This will ensure that the debug message handler does not
+ receive any messages related to this operation */
+ {
+ v8::Isolate::Scope i_scope(d->isolate);
+ QString req(message);
+ QJSValue parser = d->engine->evaluate(QLatin1String("JSON.parse"));
+ QJSValue out = parser.call(QJSValue(), QJSValueList() << QJSValue(req));
+ msgMap = out.toVariant().toMap();
+ }
+
+ QString sourcePath(msgMap.value(QLatin1String("body")).toMap().value(QLatin1String("script")).toMap().value(QLatin1String("name")).toString());
+ QString fileName(QFileInfo(sourcePath).fileName());
+
+ d->sourcePath.insert(fileName, sourcePath);
+
+ //Check if there are any pending breakpoint requests for this file
+ if (d->requestCache.contains(fileName)) {
+ QList<QByteArray> list = d->requestCache.values(fileName);
+ d->requestCache.remove(fileName);
+ foreach (QByteArray request, list) {
+ request.replace(fileName.toUtf8(), sourcePath.toUtf8());
+ sendDebugMessage(request);
+ }
+ }
+}
+
+void QV8DebugService::messageReceived(const QByteArray &message)
+{
+ Q_D(QV8DebugService);
+
+ QDataStream ds(message);
+ QByteArray command;
+ ds >> command;
+
+ if (command == "V8DEBUG") {
+ QByteArray request;
+ ds >> request;
+
+ QVariantMap reqMap;
+ /* Parse the byte string in a separate isolate
+ This will ensure that the debug message handler does not
+ receive any messages related to this operation */
+ {
+ v8::Isolate::Scope i_scope(d->isolate);
+ QString req(request);
+ QJSValue parser = d->engine->evaluate(QLatin1String("JSON.parse"));
+ QJSValue out = parser.call(QJSValue(), QJSValueList() << QJSValue(req));
+ reqMap = out.toVariant().toMap();
+ }
+
+ QString debugCommand(reqMap.value(QLatin1String("command")).toString());
+
+ if (debugCommand == QLatin1String("connect")) {
+ d->initialized = true;
+
+ } else if (debugCommand == QLatin1String("interrupt")) {
+ v8::Debug::DebugBreak();
+
+ } else {
+ bool ok = true;
+
+ if (debugCommand == QLatin1String("setbreakpoint")){
+ QVariantMap arguments = reqMap.value(QLatin1String("arguments")).toMap();
+ QString type(arguments.value(QLatin1String("type")).toString());
+
+ if (type == QLatin1String("script")) {
+ QString fileName(arguments.value(QLatin1String("target")).toString());
+
+ //Check if the filepath has been cached
+ if (d->sourcePath.contains(fileName)) {
+ QString filePath = d->sourcePath.value(fileName);
+ request.replace(fileName.toUtf8(), filePath.toUtf8());
+ } else {
+ //Store the setbreakpoint message till filepath is resolved
+ d->requestCache.insertMulti(fileName, request);
+ ok = false;
+ }
+ }
+ }
+ if (ok)
+ sendDebugMessage(request);
+ }
+ }
+
+ QDeclarativeDebugService::messageReceived(message);
+}
+
+void QV8DebugService::sendDebugMessage(const QByteArray &msg)
+{
+ Q_D(QV8DebugService);
+
+ QString message(msg);
+ if (d->loop.isRunning()) {
+ d->loop.exit();
+ }
+ v8::Debug::SendCommand(message.utf16(), message.size());
+}
+
+QByteArray QV8DebugService::packMessage(QByteArray &message)
+{
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ QByteArray cmd("V8DEBUG");
+ rs << cmd << message;
+ return reply;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qjsdebugservice_p.h b/src/declarative/debugger/qv8debugservice_p.h
index 7e7642eb9b..7666066f50 100644
--- a/src/declarative/debugger/qjsdebugservice_p.h
+++ b/src/declarative/debugger/qv8debugservice_p.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QJSDEBUGSERVICE_P_H
-#define QJSDEBUGSERVICE_P_H
+#ifndef QV8DEBUGSERVICE_P_H
+#define QV8DEBUGSERVICE_P_H
//
// W A R N I N G
@@ -64,36 +64,40 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
class QDeclarativeEngine;
-class QJSDebuggerAgent;
+class QJSEngine;
+class QV8DebugServicePrivate;
-class QJSDebugService : public QDeclarativeDebugService
+class QV8DebugService : public QDeclarativeDebugService
{
Q_OBJECT
-
public:
- QJSDebugService(QObject *parent = 0);
- ~QJSDebugService();
+ QV8DebugService(QObject *parent = 0);
+ ~QV8DebugService();
- static QJSDebugService *instance();
+ static QV8DebugService *instance();
void addEngine(QDeclarativeEngine *);
void removeEngine(QDeclarativeEngine *);
+ void debugMessageHandler(QByteArray message);
+ void executionStopped();
+
+ void appendSourcePath(QByteArray message);
+
protected:
- void statusChanged(Status status);
void messageReceived(const QByteArray &);
-private Q_SLOTS:
- void executionStopped(bool becauseOfException,
- const QString &exception);
+private:
+ void sendDebugMessage(const QByteArray &msg);
+ QByteArray packMessage(QByteArray &message);
private:
- QList<QDeclarativeEngine *> m_engines;
- QPointer<QJSDebuggerAgent> m_agent;
+ Q_DISABLE_COPY(QV8DebugService)
+ Q_DECLARE_PRIVATE(QV8DebugService)
};
QT_END_NAMESPACE
QT_END_HEADER
-#endif // QJSDEBUGSERVICE_P_H
+#endif // QV8DEBUGSERVICE_P_H
diff --git a/src/declarative/items/qsganimatedimage.cpp b/src/declarative/items/qsganimatedimage.cpp
index 0a9fdd1783..ea36153ef0 100644
--- a/src/declarative/items/qsganimatedimage.cpp
+++ b/src/declarative/items/qsganimatedimage.cpp
@@ -52,6 +52,75 @@
#include <private/qdeclarativeengine_p.h>
QT_BEGIN_NAMESPACE
+/*!
+ \qmlclass AnimatedImage QSGAnimatedImage
+ \inqmlmodule QtQuick 2
+ \inherits Image
+ \ingroup basic-visual-elements
+
+ The AnimatedImage element extends the features of the \l Image element, providing
+ a way to play animations stored as images containing a series of frames,
+ such as those stored in GIF files.
+
+ Information about the current frame and totla length of the animation can be
+ obtained using the \l currentFrame and \l frameCount properties. You can
+ start, pause and stop the animation by changing the values of the \l playing
+ and \l paused properties.
+
+ The full list of supported formats can be determined with QMovie::supportedFormats().
+
+ \section1 Example Usage
+
+ \beginfloatleft
+ \image animatedimageitem.gif
+ \endfloat
+
+ The following QML shows how to display an animated image and obtain information
+ about its state, such as the current frame and total number of frames.
+ The result is an animated image with a simple progress indicator underneath it.
+
+ \bold Note: Unlike images, animated images are not cached or shared internally.
+
+ \clearfloat
+ \snippet doc/src/snippets/declarative/animatedimage.qml document
+
+ \sa BorderImage, Image
+*/
+
+/*!
+ \qmlproperty url QtQuick2::AnimatedImage::source
+
+ This property holds the URL that refers to the source image.
+
+ AnimatedImage can handle any image format supported by Qt, loaded from any
+ URL scheme supported by Qt.
+
+ \sa QDeclarativeImageProvider
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::AnimatedImage::asynchronous
+
+ Specifies that images on the local filesystem should be loaded
+ asynchronously in a separate thread. The default value is
+ false, causing the user interface thread to block while the
+ image is loaded. Setting \a asynchronous to true is useful where
+ maintaining a responsive user interface is more desirable
+ than having images immediately visible.
+
+ Note that this property is only valid for images read from the
+ local filesystem. Images loaded via a network resource (e.g. HTTP)
+ are always loaded asynchonously.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::AnimatedImage::mirror
+
+ This property holds whether the image should be horizontally inverted
+ (effectively displaying a mirrored image).
+
+ The default value is false.
+*/
QSGAnimatedImage::QSGAnimatedImage(QSGItem *parent)
: QSGImage(*(new QSGAnimatedImagePrivate), parent)
@@ -64,6 +133,14 @@ QSGAnimatedImage::~QSGAnimatedImage()
delete d->_movie;
}
+/*!
+ \qmlproperty bool QtQuick2::AnimatedImage::paused
+ This property holds whether the animated image is paused.
+
+ By default, this property is false. Set it to true when you want to pause
+ the animation.
+*/
+
bool QSGAnimatedImage::isPaused() const
{
Q_D(const QSGAnimatedImage);
@@ -83,6 +160,14 @@ void QSGAnimatedImage::setPaused(bool pause)
d->_movie->setPaused(pause);
}
+/*!
+ \qmlproperty bool QtQuick2::AnimatedImage::playing
+ This property holds whether the animated image is playing.
+
+ By default, this property is true, meaning that the animation
+ will start playing immediately.
+*/
+
bool QSGAnimatedImage::isPlaying() const
{
Q_D(const QSGAnimatedImage);
@@ -105,6 +190,16 @@ void QSGAnimatedImage::setPlaying(bool play)
d->_movie->stop();
}
+/*!
+ \qmlproperty int QtQuick2::AnimatedImage::currentFrame
+ \qmlproperty int QtQuick2::AnimatedImage::frameCount
+
+ currentFrame is the frame that is currently visible. By monitoring this property
+ for changes, you can animate other items at the same time as the image.
+
+ frameCount is the number of frames in the animation. For some animation formats,
+ frameCount is unknown and has a value of zero.
+*/
int QSGAnimatedImage::currentFrame() const
{
Q_D(const QSGAnimatedImage);
diff --git a/src/declarative/items/qsgborderimage.cpp b/src/declarative/items/qsgborderimage.cpp
index 684ea0097b..8d54bce419 100644
--- a/src/declarative/items/qsgborderimage.cpp
+++ b/src/declarative/items/qsgborderimage.cpp
@@ -50,6 +50,119 @@
QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlclass BorderImage QSGBorderImage
+ \inqmlmodule QtQuick 2
+ \brief The BorderImage element provides an image that can be used as a border.
+ \inherits Item
+ \ingroup qml-basic-visual-elements
+
+ The BorderImage element is used to create borders out of images by scaling or tiling
+ parts of each image.
+
+ A BorderImage element breaks a source image, specified using the \l url property,
+ into 9 regions, as shown below:
+
+ \image declarative-scalegrid.png
+
+ When the image is scaled, regions of the source image are scaled or tiled to
+ create the displayed border image in the following way:
+
+ \list
+ \i The corners (regions 1, 3, 7, and 9) are not scaled at all.
+ \i Regions 2 and 8 are scaled according to
+ \l{BorderImage::horizontalTileMode}{horizontalTileMode}.
+ \i Regions 4 and 6 are scaled according to
+ \l{BorderImage::verticalTileMode}{verticalTileMode}.
+ \i The middle (region 5) is scaled according to both
+ \l{BorderImage::horizontalTileMode}{horizontalTileMode} and
+ \l{BorderImage::verticalTileMode}{verticalTileMode}.
+ \endlist
+
+ The regions of the image are defined using the \l border property group, which
+ describes the distance from each edge of the source image to use as a border.
+
+ \section1 Example Usage
+
+ The following examples show the effects of the different modes on an image.
+ Guide lines are overlaid onto the image to show the different regions of the
+ image as described above.
+
+ \beginfloatleft
+ \image qml-borderimage-normal-image.png
+ \endfloat
+
+ An unscaled image is displayed using an Image element. The \l border property is
+ used to determine the parts of the image that will lie inside the unscaled corner
+ areas and the parts that will be stretched horizontally and vertically.
+
+ \snippet doc/src/snippets/declarative/borderimage/normal-image.qml normal image
+
+ \clearfloat
+ \beginfloatleft
+ \image qml-borderimage-scaled.png
+ \endfloat
+
+ A BorderImage element is used to display the image, and it is given a size that is
+ larger than the original image. Since the \l horizontalTileMode property is set to
+ \l{BorderImage::horizontalTileMode}{BorderImage.Stretch}, the parts of image in
+ regions 2 and 8 are stretched horizontally. Since the \l verticalTileMode property
+ is set to \l{BorderImage::verticalTileMode}{BorderImage.Stretch}, the parts of image
+ in regions 4 and 6 are stretched vertically.
+
+ \snippet doc/src/snippets/declarative/borderimage/borderimage-scaled.qml scaled border image
+
+ \clearfloat
+ \beginfloatleft
+ \image qml-borderimage-tiled.png
+ \endfloat
+
+ Again, a large BorderImage element is used to display the image. With the
+ \l horizontalTileMode property set to \l{BorderImage::horizontalTileMode}{BorderImage.Repeat},
+ the parts of image in regions 2 and 8 are tiled so that they fill the space at the
+ top and bottom of the element. Similarly, the \l verticalTileMode property is set to
+ \l{BorderImage::verticalTileMode}{BorderImage.Repeat}, the parts of image in regions
+ 4 and 6 are tiled so that they fill the space at the left and right of the element.
+
+ \snippet doc/src/snippets/declarative/borderimage/borderimage-tiled.qml tiled border image
+
+ \clearfloat
+ In some situations, the width of regions 2 and 8 may not be an exact multiple of the width
+ of the corresponding regions in the source image. Similarly, the height of regions 4 and 6
+ may not be an exact multiple of the height of the corresponding regions. It can be useful
+ to use \l{BorderImage::horizontalTileMode}{BorderImage.Round} instead of
+ \l{BorderImage::horizontalTileMode}{BorderImage.Repeat} in cases like these.
+
+ The \l{declarative/imageelements/borderimage}{BorderImage example} shows how a BorderImage
+ can be used to simulate a shadow effect on a rectangular item.
+
+ \section1 Quality and Performance
+
+ By default, any scaled regions of the image are rendered without smoothing to improve
+ rendering speed. Setting the \l smooth property improves rendering quality of scaled
+ regions, but may slow down rendering.
+
+ The source image may not be loaded instantaneously, depending on its original location.
+ Loading progress can be monitored with the \l progress property.
+
+ \sa Image, AnimatedImage
+ */
+
+/*!
+ \qmlproperty bool QtQuick2::BorderImage::asynchronous
+
+ Specifies that images on the local filesystem should be loaded
+ asynchronously in a separate thread. The default value is
+ false, causing the user interface thread to block while the
+ image is loaded. Setting \a asynchronous to true is useful where
+ maintaining a responsive user interface is more desirable
+ than having images immediately visible.
+
+ Note that this property is only valid for images read from the
+ local filesystem. Images loaded via a network resource (e.g. HTTP)
+ are always loaded asynchonously.
+*/
QSGBorderImage::QSGBorderImage(QSGItem *parent)
: QSGImageBase(*(new QSGBorderImagePrivate), parent)
{
@@ -62,6 +175,99 @@ QSGBorderImage::~QSGBorderImage()
d->sciReply->deleteLater();
}
+/*!
+ \qmlproperty enumeration QtQuick2::BorderImage::status
+
+ This property describes the status of image loading. It can be one of:
+
+ \list
+ \o BorderImage.Null - no image has been set
+ \o BorderImage.Ready - the image has been loaded
+ \o BorderImage.Loading - the image is currently being loaded
+ \o BorderImage.Error - an error occurred while loading the image
+ \endlist
+
+ \sa progress
+*/
+
+/*!
+ \qmlproperty real QtQuick2::BorderImage::progress
+
+ This property holds the progress of image loading, from 0.0 (nothing loaded)
+ to 1.0 (finished).
+
+ \sa status
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::BorderImage::smooth
+
+ Set this property if you want the image to be smoothly filtered when scaled or
+ transformed. Smooth filtering gives better visual quality, but is slower. If
+ the image is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ By default, this property is set to false.
+
+ \note Generally scaling artifacts are only visible if the image is stationary on
+ the screen. A common pattern when animating an image is to disable smooth
+ filtering at the beginning of the animation and enable it at the conclusion.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::BorderImage::cache
+
+ Specifies whether the image should be cached. The default value is
+ true. Setting \a cache to false is useful when dealing with large images,
+ to make sure that they aren't cached at the expense of small 'ui element' images.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::BorderImage::mirror
+
+ This property holds whether the image should be horizontally inverted
+ (effectively displaying a mirrored image).
+
+ The default value is false.
+*/
+
+/*!
+ \qmlproperty url QtQuick2::BorderImage::source
+
+ This property holds the URL that refers to the source image.
+
+ BorderImage can handle any image format supported by Qt, loaded from any
+ URL scheme supported by Qt.
+
+ This property can also be used to refer to .sci files, which are
+ written in a QML-specific, text-based format that specifies the
+ borders, the image file and the tile rules for a given border image.
+
+ The following .sci file sets the borders to 10 on each side for the
+ image \c picture.png:
+
+ \code
+ border.left: 10
+ border.top: 10
+ border.bottom: 10
+ border.right: 10
+ source: "picture.png"
+ \endcode
+
+ The URL may be absolute, or relative to the URL of the component.
+
+ \sa QDeclarativeImageProvider
+*/
+
+/*!
+ \qmlproperty QSize QtQuick2::BorderImage::sourceSize
+
+ This property holds the actual width and height of the loaded image.
+
+ In BorderImage, this property is read-only.
+
+ \sa Image::sourceSize
+*/
void QSGBorderImage::setSource(const QUrl &url)
{
Q_D(QSGBorderImage);
@@ -160,12 +366,55 @@ void QSGBorderImage::load()
emit statusChanged(d->status);
}
+/*!
+ \qmlproperty int QtQuick2::BorderImage::border.left
+ \qmlproperty int QtQuick2::BorderImage::border.right
+ \qmlproperty int QtQuick2::BorderImage::border.top
+ \qmlproperty int QtQuick2::BorderImage::border.bottom
+
+ The 4 border lines (2 horizontal and 2 vertical) break the image into 9 sections,
+ as shown below:
+
+ \image declarative-scalegrid.png
+
+ Each border line (left, right, top, and bottom) specifies an offset in pixels
+ from the respective edge of the source image. By default, each border line has
+ a value of 0.
+
+ For example, the following definition sets the bottom line 10 pixels up from
+ the bottom of the image:
+
+ \qml
+ BorderImage {
+ border.bottom: 10
+ // ...
+ }
+ \endqml
+
+ The border lines can also be specified using a
+ \l {BorderImage::source}{.sci file}.
+*/
+
QSGScaleGrid *QSGBorderImage::border()
{
Q_D(QSGBorderImage);
return d->getScaleGrid();
}
+/*!
+ \qmlproperty enumeration QtQuick2::BorderImage::horizontalTileMode
+ \qmlproperty enumeration QtQuick2::BorderImage::verticalTileMode
+
+ This property describes how to repeat or stretch the middle parts of the border image.
+
+ \list
+ \o BorderImage.Stretch - Scales the image to fit to the available area.
+ \o BorderImage.Repeat - Tile the image until there is no more space. May crop the last image.
+ \o BorderImage.Round - Like Repeat, but scales the images down to ensure that the last image is not cropped.
+ \endlist
+
+ The default tile mode for each property is BorderImage.Stretch.
+*/
QSGBorderImage::TileMode QSGBorderImage::horizontalTileMode() const
{
Q_D(const QSGBorderImage);
diff --git a/src/declarative/items/qsgcanvas.cpp b/src/declarative/items/qsgcanvas.cpp
index 33d661e089..0d4001a393 100644
--- a/src/declarative/items/qsgcanvas.cpp
+++ b/src/declarative/items/qsgcanvas.cpp
@@ -332,7 +332,6 @@ QSGCanvasPrivate::QSGCanvasPrivate()
: rootItem(0)
, activeFocusItem(0)
, mouseGrabberItem(0)
- , hoverItem(0)
, dirtyItemList(0)
, context(0)
, animationRunning(false)
@@ -785,7 +784,6 @@ QSGCanvas::~QSGCanvas()
// manually cleanup for the root item (item destructor only handles these when an item is parented)
QSGItemPrivate *rootItemPrivate = QSGItemPrivate::get(d->rootItem);
rootItemPrivate->removeFromDirtyList();
- rootItemPrivate->canvas = 0;
delete d->rootItem; d->rootItem = 0;
d->cleanupNodes();
@@ -813,17 +811,19 @@ QSGItem *QSGCanvas::mouseGrabberItem() const
}
-void QSGCanvasPrivate::clearHover()
+bool QSGCanvasPrivate::clearHover()
{
Q_Q(QSGCanvas);
- if (!hoverItem)
- return;
+ if (hoverItems.isEmpty())
+ return false;
QPointF pos = QCursor::pos(); // ### refactor: q->mapFromGlobal(QCursor::pos());
- QSGItem *item = hoverItem;
- hoverItem = 0;
- sendHoverEvent(QEvent::HoverLeave, item, pos, pos, QApplication::keyboardModifiers(), true);
+ bool accepted = false;
+ foreach (QSGItem* item, hoverItems)
+ accepted = sendHoverEvent(QEvent::HoverLeave, item, pos, pos, QApplication::keyboardModifiers(), true) || accepted;
+ hoverItems.clear();
+ return accepted;
}
@@ -874,6 +874,9 @@ bool QSGCanvas::event(QEvent *e)
case QSGEvent::SGDragDrop:
d->deliverDragEvent(static_cast<QSGDragEvent *>(e));
break;
+ case QEvent::WindowDeactivate:
+ rootItem()->windowDeactivateEvent();
+ break;
default:
break;
}
@@ -1063,11 +1066,7 @@ void QSGCanvas::mouseMoveEvent(QMouseEvent *event)
bool delivered = d->deliverHoverEvent(d->rootItem, event->pos(), last, event->modifiers(), accepted);
if (!delivered) {
//take care of any exits
- if (d->hoverItem) {
- QSGItem *item = d->hoverItem;
- d->hoverItem = 0;
- accepted = d->sendHoverEvent(QEvent::HoverLeave, item, event->pos(), last, event->modifiers(), accepted);
- }
+ accepted = d->clearHover();
}
event->setAccepted(accepted);
return;
@@ -1105,20 +1104,43 @@ bool QSGCanvasPrivate::deliverHoverEvent(QSGItem *item, const QPointF &scenePos,
if (itemPrivate->hoverEnabled) {
QPointF p = item->mapFromScene(scenePos);
if (QRectF(0, 0, item->width(), item->height()).contains(p)) {
- if (hoverItem == item) {
+ if (!hoverItems.isEmpty() && hoverItems[0] == item) {
//move
accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, accepted);
} else {
- //exit from previous
- if (hoverItem) {
- QSGItem *item = hoverItem;
- hoverItem = 0;
- accepted = sendHoverEvent(QEvent::HoverLeave, item, scenePos, lastScenePos, modifiers, accepted);
+ QList<QSGItem*> parents;
+ QSGItem* parent = item;
+ parents << item;
+ while ((parent = parent->parentItem()))
+ parents << parent;
+
+ //exit from previous (excepting ancestors)
+ while (!hoverItems.isEmpty() && !parents.contains(hoverItems[0])){
+ sendHoverEvent(QEvent::HoverLeave, hoverItems[0], scenePos, lastScenePos, modifiers, accepted);
+ hoverItems.removeFirst();
}
- //enter new item
- hoverItem = item;
- accepted = sendHoverEvent(QEvent::HoverEnter, item, scenePos, lastScenePos, modifiers, accepted);
+ if (!hoverItems.isEmpty() && hoverItems[0] == item){//Not entering a new Item
+ accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, accepted);
+ } else {
+ //enter any ancestors that also wish to be hovered and aren't
+ int startIdx = -1;
+ if (!hoverItems.isEmpty())
+ startIdx = parents.indexOf(hoverItems[0]);
+ if (startIdx == -1)
+ startIdx = parents.count() - 1;
+
+ for (int i = startIdx; i >= 0; i--) {
+ if (QSGItemPrivate::get(parents[i])->hoverEnabled) {
+ hoverItems.prepend(parents[i]);
+ sendHoverEvent(QEvent::HoverEnter, parents[i], scenePos, lastScenePos, modifiers, accepted);
+ }
+ }
+
+ //enter new item
+ hoverItems.prepend(item);
+ accepted = sendHoverEvent(QEvent::HoverEnter, item, scenePos, lastScenePos, modifiers, accepted);
+ }
}
return true;
}
@@ -1143,7 +1165,7 @@ bool QSGCanvasPrivate::deliverWheelEvent(QSGItem *item, QWheelEvent *event)
QList<QSGItem *> children = itemPrivate->paintOrderChildItems();
for (int ii = children.count() - 1; ii >= 0; --ii) {
QSGItem *child = children.at(ii);
- if (!child->isEnabled())
+ if (!child->isVisible() || !child->isEnabled())
continue;
if (deliverWheelEvent(child, event))
return true;
@@ -1562,6 +1584,7 @@ void QSGCanvasPrivate::updateDirtyNode(QSGItem *item)
if (item->clip()) {
Q_ASSERT(itemPriv->clipNode == 0);
itemPriv->clipNode = new QSGDefaultClipNode(item->boundingRect());
+ itemPriv->clipNode->update();
if (child)
parent->removeChildNode(child);
@@ -1646,7 +1669,7 @@ void QSGCanvasPrivate::updateDirtyNode(QSGItem *item)
}
}
- if ((dirty & QSGItemPrivate::Size || clipEffectivelyChanged) && itemPriv->clipNode) {
+ if ((dirty & QSGItemPrivate::Size) && itemPriv->clipNode) {
itemPriv->clipNode->setRect(item->boundingRect());
itemPriv->clipNode->update();
}
diff --git a/src/declarative/items/qsgcanvas_p.h b/src/declarative/items/qsgcanvas_p.h
index e16d91685d..bf65e95812 100644
--- a/src/declarative/items/qsgcanvas_p.h
+++ b/src/declarative/items/qsgcanvas_p.h
@@ -119,11 +119,11 @@ public:
bool deliverHoverEvent(QSGItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, bool &accepted);
bool sendHoverEvent(QEvent::Type, QSGItem *, const QPointF &scenePos, const QPointF &lastScenePos,
Qt::KeyboardModifiers modifiers, bool accepted);
- void clearHover();
+ bool clearHover();
void deliverDragEvent(QSGDragEvent *);
bool deliverDragEvent(QSGItem *item, QSGDragEvent *);
- QDeclarativeGuard<QSGItem> hoverItem;
+ QList<QSGItem*> hoverItems;
enum FocusOption {
DontChangeFocusProperty = 0x01,
};
diff --git a/src/declarative/items/qsgevents.cpp b/src/declarative/items/qsgevents.cpp
index 0c5d8cac34..2173b4a21f 100644
--- a/src/declarative/items/qsgevents.cpp
+++ b/src/declarative/items/qsgevents.cpp
@@ -43,4 +43,197 @@
QT_BEGIN_NAMESPACE
+/*!
+ \qmlclass KeyEvent QSGKeyEvent
+ \inqmlmodule QtQuick 2
+ \ingroup qml-event-elements
+
+ \brief The KeyEvent object provides information about a key event.
+
+ For example, the following changes the Item's state property when the Enter
+ key is pressed:
+ \qml
+Item {
+ focus: true
+ Keys.onPressed: { if (event.key == Qt.Key_Enter) state = 'ShowDetails'; }
+}
+ \endqml
+*/
+
+/*!
+ \qmlproperty int QtQuick2::KeyEvent::key
+
+ This property holds the code of the key that was pressed or released.
+
+ See \l {Qt::Key}{Qt.Key} for the list of keyboard codes. These codes are
+ independent of the underlying window system. Note that this
+ function does not distinguish between capital and non-capital
+ letters, use the text() function (returning the Unicode text the
+ key generated) for this purpose.
+
+ A value of either 0 or \l {Qt::Key_unknown}{Qt.Key_Unknown} means that the event is not
+ the result of a known key; for example, it may be the result of
+ a compose sequence, a keyboard macro, or due to key event
+ compression.
+*/
+
+/*!
+ \qmlproperty string QtQuick2::KeyEvent::text
+
+ This property holds the Unicode text that the key generated.
+ The text returned can be an empty string in cases where modifier keys,
+ such as Shift, Control, Alt, and Meta, are being pressed or released.
+ In such cases \c key will contain a valid value
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::KeyEvent::isAutoRepeat
+
+ This property holds whether this event comes from an auto-repeating key.
+*/
+
+/*!
+ \qmlproperty int QtQuick2::KeyEvent::count
+
+ This property holds the number of keys involved in this event. If \l KeyEvent::text
+ is not empty, this is simply the length of the string.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::KeyEvent::accepted
+
+ Setting \a accepted to true prevents the key event from being
+ propagated to the item's parent.
+
+ Generally, if the item acts on the key event then it should be accepted
+ so that ancestor items do not also respond to the same event.
+*/
+
+/*!
+ \qmlproperty int QtQuick2::KeyEvent::modifiers
+
+ This property holds the keyboard modifier flags that existed immediately
+ before the event occurred.
+
+ It contains a bitwise combination of:
+ \list
+ \o Qt.NoModifier - No modifier key is pressed.
+ \o Qt.ShiftModifier - A Shift key on the keyboard is pressed.
+ \o Qt.ControlModifier - A Ctrl key on the keyboard is pressed.
+ \o Qt.AltModifier - An Alt key on the keyboard is pressed.
+ \o Qt.MetaModifier - A Meta key on the keyboard is pressed.
+ \o Qt.KeypadModifier - A keypad button is pressed.
+ \endlist
+
+ For example, to react to a Shift key + Enter key combination:
+ \qml
+ Item {
+ focus: true
+ Keys.onPressed: {
+ if ((event.key == Qt.Key_Enter) && (event.modifiers & Qt.ShiftModifier))
+ doSomething();
+ }
+ }
+ \endqml
+*/
+
+
+/*!
+ \qmlclass MouseEvent QSGMouseEvent
+ \inqmlmodule QtQuick 2
+ \ingroup qml-event-elements
+
+ \brief The MouseEvent object provides information about a mouse event.
+
+ The position of the mouse can be found via the \l x and \l y properties.
+ The button that caused the event is available via the \l button property.
+
+ \sa MouseArea
+*/
+
+/*!
+ \internal
+ \class QSGMouseEvent
+*/
+
+/*!
+ \qmlproperty int QtQuick2::MouseEvent::x
+ \qmlproperty int QtQuick2::MouseEvent::y
+
+ These properties hold the coordinates of the position supplied by the mouse event.
+*/
+
+
+/*!
+ \qmlproperty bool QtQuick2::MouseEvent::accepted
+
+ Setting \a accepted to true prevents the mouse event from being
+ propagated to items below this item.
+
+ Generally, if the item acts on the mouse event then it should be accepted
+ so that items lower in the stacking order do not also respond to the same event.
+*/
+
+/*!
+ \qmlproperty enumeration QtQuick2::MouseEvent::button
+
+ This property holds the button that caused the event. It can be one of:
+ \list
+ \o Qt.LeftButton
+ \o Qt.RightButton
+ \o Qt.MiddleButton
+ \endlist
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::MouseEvent::wasHeld
+
+ This property is true if the mouse button has been held pressed longer the
+ threshold (800ms).
+*/
+
+/*!
+ \qmlproperty int QtQuick2::MouseEvent::buttons
+
+ This property holds the mouse buttons pressed when the event was generated.
+ For mouse move events, this is all buttons that are pressed down. For mouse
+ press and double click events this includes the button that caused the event.
+ For mouse release events this excludes the button that caused the event.
+
+ It contains a bitwise combination of:
+ \list
+ \o Qt.LeftButton
+ \o Qt.RightButton
+ \o Qt.MiddleButton
+ \endlist
+*/
+
+/*!
+ \qmlproperty int QtQuick2::MouseEvent::modifiers
+
+ This property holds the keyboard modifier flags that existed immediately
+ before the event occurred.
+
+ It contains a bitwise combination of:
+ \list
+ \o Qt.NoModifier - No modifier key is pressed.
+ \o Qt.ShiftModifier - A Shift key on the keyboard is pressed.
+ \o Qt.ControlModifier - A Ctrl key on the keyboard is pressed.
+ \o Qt.AltModifier - An Alt key on the keyboard is pressed.
+ \o Qt.MetaModifier - A Meta key on the keyboard is pressed.
+ \o Qt.KeypadModifier - A keypad button is pressed.
+ \endlist
+
+ For example, to react to a Shift key + Left mouse button click:
+ \qml
+ MouseArea {
+ onClicked: {
+ if ((mouse.button == Qt.LeftButton) && (mouse.modifiers & Qt.ShiftModifier))
+ doSomething();
+ }
+ }
+ \endqml
+*/
+
+
QT_END_NAMESPACE
diff --git a/src/declarative/items/qsgflickable.cpp b/src/declarative/items/qsgflickable.cpp
index 1d8f107abc..e63698eca7 100644
--- a/src/declarative/items/qsgflickable.cpp
+++ b/src/declarative/items/qsgflickable.cpp
@@ -456,6 +456,107 @@ is finished.
touch/mouse button is released then a flick will start.
*/
+/*!
+ \qmlclass Flickable QSGFlickable
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-interaction-elements
+
+ \brief The Flickable item provides a surface that can be "flicked".
+ \inherits Item
+
+ The Flickable item places its children on a surface that can be dragged
+ and flicked, causing the view onto the child items to scroll. This
+ behavior forms the basis of Items that are designed to show large numbers
+ of child items, such as \l ListView and \l GridView.
+
+ In traditional user interfaces, views can be scrolled using standard
+ controls, such as scroll bars and arrow buttons. In some situations, it
+ is also possible to drag the view directly by pressing and holding a
+ mouse button while moving the cursor. In touch-based user interfaces,
+ this dragging action is often complemented with a flicking action, where
+ scrolling continues after the user has stopped touching the view.
+
+ Flickable does not automatically clip its contents. If it is not used as
+ a full-screen item, you should consider setting the \l{Item::}{clip} property
+ to true.
+
+ \section1 Example Usage
+
+ \div {class="float-right"}
+ \inlineimage flickable.gif
+ \enddiv
+
+ The following example shows a small view onto a large image in which the
+ user can drag or flick the image in order to view different parts of it.
+
+ \snippet doc/src/snippets/declarative/flickable.qml document
+
+ \clearfloat
+
+ Items declared as children of a Flickable are automatically parented to the
+ Flickable's \l contentItem. This should be taken into account when
+ operating on the children of the Flickable; it is usually the children of
+ \c contentItem that are relevant. For example, the bound of Items added
+ to the Flickable will be available by \c contentItem.childrenRect
+
+ \section1 Limitations
+
+ \note Due to an implementation detail, items placed inside a Flickable cannot anchor to it by
+ \c id. Use \c parent instead.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Flickable::onMovementStarted()
+
+ This handler is called when the view begins moving due to user
+ interaction.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Flickable::onMovementEnded()
+
+ This handler is called when the view stops moving due to user
+ interaction. If a flick was generated, this handler will
+ be triggered once the flick stops. If a flick was not
+ generated, the handler will be triggered when the
+ user stops dragging - i.e. a mouse or touch release.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Flickable::onFlickStarted()
+
+ This handler is called when the view is flicked. A flick
+ starts from the point that the mouse or touch is released,
+ while still in motion.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Flickable::onFlickEnded()
+
+ This handler is called when the view stops moving due to a flick.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Flickable::visibleArea.xPosition
+ \qmlproperty real QtQuick2::Flickable::visibleArea.widthRatio
+ \qmlproperty real QtQuick2::Flickable::visibleArea.yPosition
+ \qmlproperty real QtQuick2::Flickable::visibleArea.heightRatio
+
+ These properties describe the position and size of the currently viewed area.
+ The size is defined as the percentage of the full view currently visible,
+ scaled to 0.0 - 1.0. The page position is usually in the range 0.0 (beginning) to
+ 1.0 minus size ratio (end), i.e. \c yPosition is in the range 0.0 to 1.0-\c heightRatio.
+ However, it is possible for the contents to be dragged outside of the normal
+ range, resulting in the page positions also being outside the normal range.
+
+ These properties are typically used to draw a scrollbar. For example:
+
+ \snippet doc/src/snippets/declarative/flickableScrollbar.qml 0
+ \dots 8
+ \snippet doc/src/snippets/declarative/flickableScrollbar.qml 1
+
+ \sa {declarative/ui-components/scrollbar}{scrollbar example}
+*/
QSGFlickable::QSGFlickable(QSGItem *parent)
: QSGItem(*(new QSGFlickablePrivate), parent)
{
@@ -474,6 +575,14 @@ QSGFlickable::~QSGFlickable()
{
}
+/*!
+ \qmlproperty real QtQuick2::Flickable::contentX
+ \qmlproperty real QtQuick2::Flickable::contentY
+
+ These properties hold the surface coordinate currently at the top-left
+ corner of the Flickable. For example, if you flick an image up 100 pixels,
+ \c contentY will be 100.
+*/
qreal QSGFlickable::contentX() const
{
Q_D(const QSGFlickable);
@@ -510,6 +619,19 @@ void QSGFlickable::setContentY(qreal pos)
}
}
+/*!
+ \qmlproperty bool QtQuick2::Flickable::interactive
+
+ This property describes whether the user can interact with the Flickable.
+ A user cannot drag or flick a Flickable that is not interactive.
+
+ By default, this property is true.
+
+ This property is useful for temporarily disabling flicking. This allows
+ special interaction with Flickable's children; for example, you might want
+ to freeze a flickable map while scrolling through a pop-up dialog that
+ is a child of the Flickable.
+*/
bool QSGFlickable::isInteractive() const
{
Q_D(const QSGFlickable);
@@ -535,6 +657,14 @@ void QSGFlickable::setInteractive(bool interactive)
}
}
+/*!
+ \qmlproperty real QtQuick2::Flickable::horizontalVelocity
+ \qmlproperty real QtQuick2::Flickable::verticalVelocity
+
+ The instantaneous velocity of movement along the x and y axes, in pixels/sec.
+
+ The reported velocity is smoothed to avoid erratic output.
+*/
qreal QSGFlickable::horizontalVelocity() const
{
Q_D(const QSGFlickable);
@@ -547,6 +677,15 @@ qreal QSGFlickable::verticalVelocity() const
return d->vData.smoothVelocity.value();
}
+/*!
+ \qmlproperty bool QtQuick2::Flickable::atXBeginning
+ \qmlproperty bool QtQuick2::Flickable::atXEnd
+ \qmlproperty bool QtQuick2::Flickable::atYBeginning
+ \qmlproperty bool QtQuick2::Flickable::atYEnd
+
+ These properties are true if the flickable view is positioned at the beginning,
+ or end respecively.
+*/
bool QSGFlickable::isAtXEnd() const
{
Q_D(const QSGFlickable);
@@ -576,6 +715,24 @@ void QSGFlickable::ticked()
viewportMoved();
}
+/*!
+ \qmlproperty Item QtQuick2::Flickable::contentItem
+
+ The internal item that contains the Items to be moved in the Flickable.
+
+ Items declared as children of a Flickable are automatically parented to the Flickable's contentItem.
+
+ Items created dynamically need to be explicitly parented to the \e contentItem:
+ \code
+ Flickable {
+ id: myFlickable
+ function addItem(file) {
+ var component = Qt.createComponent(file)
+ component.createObject(myFlickable.contentItem);
+ }
+ }
+ \endcode
+*/
QSGItem *QSGFlickable::contentItem()
{
Q_D(QSGFlickable);
@@ -590,6 +747,21 @@ QSGFlickableVisibleArea *QSGFlickable::visibleArea()
return d->visibleArea;
}
+/*!
+ \qmlproperty enumeration QtQuick2::Flickable::flickableDirection
+
+ This property determines which directions the view can be flicked.
+
+ \list
+ \o Flickable.AutoFlickDirection (default) - allows flicking vertically if the
+ \e contentHeight is not equal to the \e height of the Flickable.
+ Allows flicking horizontally if the \e contentWidth is not equal
+ to the \e width of the Flickable.
+ \o Flickable.HorizontalFlick - allows flicking horizontally.
+ \o Flickable.VerticalFlick - allows flicking vertically.
+ \o Flickable.HorizontalAndVerticalFlick - allows flicking in both directions.
+ \endlist
+*/
QSGFlickable::FlickableDirection QSGFlickable::flickableDirection() const
{
Q_D(const QSGFlickable);
@@ -1118,6 +1290,27 @@ QDeclarativeListProperty<QSGItem> QSGFlickable::flickableChildren()
return QSGItemPrivate::get(d->contentItem)->children();
}
+/*!
+ \qmlproperty enumeration QtQuick2::Flickable::boundsBehavior
+ This property holds whether the surface may be dragged
+ beyond the Fickable's boundaries, or overshoot the
+ Flickable's boundaries when flicked.
+
+ This enables the feeling that the edges of the view are soft,
+ rather than a hard physical boundary.
+
+ The \c boundsBehavior can be one of:
+
+ \list
+ \o Flickable.StopAtBounds - the contents can not be dragged beyond the boundary
+ of the flickable, and flicks will not overshoot.
+ \o Flickable.DragOverBounds - the contents can be dragged beyond the boundary
+ of the Flickable, but flicks will not overshoot.
+ \o Flickable.DragAndOvershootBounds (default) - the contents can be dragged
+ beyond the boundary of the Flickable, and can overshoot the
+ boundary when flicked.
+ \endlist
+*/
QSGFlickable::BoundsBehavior QSGFlickable::boundsBehavior() const
{
Q_D(const QSGFlickable);
@@ -1133,6 +1326,23 @@ void QSGFlickable::setBoundsBehavior(BoundsBehavior b)
emit boundsBehaviorChanged();
}
+/*!
+ \qmlproperty real QtQuick2::Flickable::contentWidth
+ \qmlproperty real QtQuick2::Flickable::contentHeight
+
+ The dimensions of the content (the surface controlled by Flickable).
+ This should typically be set to the combined size of the items placed in the
+ Flickable.
+
+ The following snippet shows how these properties are used to display
+ an image that is larger than the Flickable item itself:
+
+ \snippet doc/src/snippets/declarative/flickable.qml document
+
+ In some cases, the the content dimensions can be automatically set
+ using the \l {Item::childrenRect.width}{childrenRect.width}
+ and \l {Item::childrenRect.height}{childrenRect.height} properties.
+*/
qreal QSGFlickable::contentWidth() const
{
Q_D(const QSGFlickable);
@@ -1189,6 +1399,19 @@ void QSGFlickable::setContentHeight(qreal h)
d->updateBeginningEnd();
}
+/*!
+ \qmlmethod QtQuick2::Flickable::resizeContent(real width, real height, QPointF center)
+ \preliminary
+
+ Resizes the content to \a width x \a height about \a center.
+
+ This does not scale the contents of the Flickable - it only resizes the \l contentWidth
+ and \l contentHeight.
+
+ Resizing the content may result in the content being positioned outside
+ the bounds of the Flickable. Calling \l returnToBounds() will
+ move the content back within legal bounds.
+*/
void QSGFlickable::resizeContent(qreal w, qreal h, QPointF center)
{
Q_D(QSGFlickable);
@@ -1215,6 +1438,15 @@ void QSGFlickable::resizeContent(qreal w, qreal h, QPointF center)
d->updateBeginningEnd();
}
+/*!
+ \qmlmethod QtQuick2::Flickable::returnToBounds()
+ \preliminary
+
+ Ensures the content is within legal bounds.
+
+ This may be called to ensure that the content is within legal bounds
+ after manually positioning the content.
+*/
void QSGFlickable::returnToBounds()
{
Q_D(QSGFlickable);
@@ -1332,6 +1564,9 @@ bool QSGFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event)
}
return stealThisEvent || d->delayedPressEvent || disabledItem;
+ } else if (d->lastPosTime.isValid()) {
+ d->lastPosTime.invalidate();
+ returnToBounds();
}
if (mouseEvent.type() == QEvent::GraphicsSceneMouseRelease) {
d->lastPosTime.invalidate();
@@ -1360,6 +1595,12 @@ bool QSGFlickable::childMouseEventFilter(QSGItem *i, QEvent *e)
return QSGItem::childMouseEventFilter(i, e);
}
+/*!
+ \qmlproperty real QtQuick2::Flickable::maximumFlickVelocity
+ This property holds the maximum velocity that the user can flick the view in pixels/second.
+
+ The default value is platform dependent.
+*/
qreal QSGFlickable::maximumFlickVelocity() const
{
Q_D(const QSGFlickable);
@@ -1375,6 +1616,12 @@ void QSGFlickable::setMaximumFlickVelocity(qreal v)
emit maximumFlickVelocityChanged();
}
+/*!
+ \qmlproperty real QtQuick2::Flickable::flickDeceleration
+ This property holds the rate at which a flick will decelerate.
+
+ The default value is platform dependent.
+*/
qreal QSGFlickable::flickDeceleration() const
{
Q_D(const QSGFlickable);
@@ -1396,6 +1643,14 @@ bool QSGFlickable::isFlicking() const
return d->flickingHorizontally || d->flickingVertically;
}
+/*!
+ \qmlproperty bool QtQuick2::Flickable::flicking
+ \qmlproperty bool QtQuick2::Flickable::flickingHorizontally
+ \qmlproperty bool QtQuick2::Flickable::flickingVertically
+
+ These properties describe whether the view is currently moving horizontally,
+ vertically or in either direction, due to the user flicking the view.
+*/
bool QSGFlickable::isFlickingHorizontally() const
{
Q_D(const QSGFlickable);
@@ -1470,6 +1725,20 @@ void QSGFlickablePrivate::draggingEnding()
}
}
+/*!
+ \qmlproperty int QtQuick2::Flickable::pressDelay
+
+ This property holds the time to delay (ms) delivering a press to
+ children of the Flickable. This can be useful where reacting
+ to a press before a flicking action has undesirable effects.
+
+ If the flickable is dragged/flicked before the delay times out
+ the press event will not be delivered. If the button is released
+ within the timeout, both the press and release will be delivered.
+
+ Note that for nested Flickables with pressDelay set, the pressDelay of
+ inner Flickables is overridden by the outermost Flickable.
+*/
int QSGFlickable::pressDelay() const
{
Q_D(const QSGFlickable);
@@ -1485,6 +1754,15 @@ void QSGFlickable::setPressDelay(int delay)
emit pressDelayChanged();
}
+/*!
+ \qmlproperty bool QtQuick2::Flickable::moving
+ \qmlproperty bool QtQuick2::Flickable::movingHorizontally
+ \qmlproperty bool QtQuick2::Flickable::movingVertically
+
+ These properties describe whether the view is currently moving horizontally,
+ vertically or in either direction, due to the user either dragging or
+ flicking the view.
+*/
bool QSGFlickable::isMoving() const
{
diff --git a/src/declarative/items/qsgflipable.cpp b/src/declarative/items/qsgflipable.cpp
index faceb29f73..ac68b3171c 100644
--- a/src/declarative/items/qsgflipable.cpp
+++ b/src/declarative/items/qsgflipable.cpp
@@ -87,6 +87,47 @@ public:
bool wantBackYFlipped;
};
+/*!
+ \qmlclass Flipable QSGFlipable
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-interaction-elements
+ \brief The Flipable item provides a surface that can be flipped.
+ \inherits Item
+
+ Flipable is an item that can be visibly "flipped" between its front and
+ back sides, like a card. It is used together with \l Rotation, \l State
+ and \l Transition elements to produce a flipping effect.
+
+ The \l front and \l back properties are used to hold the items that are
+ shown respectively on the front and back sides of the flipable item.
+
+ \section1 Example Usage
+
+ The following example shows a Flipable item that flips whenever it is
+ clicked, rotating about the y-axis.
+
+ This flipable item has a \c flipped boolean property that is toggled
+ whenever the MouseArea within the flipable is clicked. When
+ \c flipped is true, the item changes to the "back" state; in this
+ state, the \c angle of the \l Rotation item is changed to 180
+ degrees to produce the flipping effect. When \c flipped is false, the
+ item reverts to the default state, in which the \c angle value is 0.
+
+ \snippet doc/src/snippets/declarative/flipable/flipable.qml 0
+
+ \image flipable.gif
+
+ The \l Transition creates the animation that changes the angle over
+ four seconds. When the item changes between its "back" and
+ default states, the NumberAnimation animates the angle between
+ its old and new values.
+
+ See \l {QML States} for details on state changes and the default
+ state, and \l {QML Animation and Transitions} for more information on how
+ animations work within transitions.
+
+ \sa {declarative/ui-components/flipable}{Flipable example}
+*/
QSGFlipable::QSGFlipable(QSGItem *parent)
: QSGItem(*(new QSGFlipablePrivate), parent)
{
@@ -96,6 +137,13 @@ QSGFlipable::~QSGFlipable()
{
}
+/*!
+ \qmlproperty Item QtQuick2::Flipable::front
+ \qmlproperty Item QtQuick2::Flipable::back
+
+ The front and back sides of the flipable.
+*/
+
QSGItem *QSGFlipable::front()
{
Q_D(const QSGFlipable);
@@ -153,6 +201,12 @@ void QSGFlipable::retransformBack()
d->setBackTransform();
}
+/*!
+ \qmlproperty enumeration QtQuick2::Flipable::side
+
+ The side of the Flipable currently visible. Possible values are \c
+ Flipable.Front and \c Flipable.Back.
+*/
QSGFlipable::Side QSGFlipable::side() const
{
Q_D(const QSGFlipable);
diff --git a/src/declarative/items/qsgfocusscope.cpp b/src/declarative/items/qsgfocusscope.cpp
index 156869120d..2018d5ce7d 100644
--- a/src/declarative/items/qsgfocusscope.cpp
+++ b/src/declarative/items/qsgfocusscope.cpp
@@ -43,7 +43,21 @@
QT_BEGIN_NAMESPACE
-QSGFocusScope::QSGFocusScope(QSGItem *parent)
+/*!
+ \qmlclass FocusScope QSGFocusScope
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-interaction-elements
+
+ \brief The FocusScope object explicitly creates a focus scope.
+ \inherits Item
+
+ Focus scopes assist in keyboard focus handling when building reusable QML
+ components. All the details are covered in the
+ \l {qmlfocus}{keyboard focus documentation}.
+
+ \sa {declarative/keyinteraction/focus}{Keyboard focus example}
+*/
+QSGFocusScope::QSGFocusScope(QSGItem *parent)
: QSGItem(parent)
{
setFlag(ItemIsFocusScope);
diff --git a/src/declarative/items/qsggridview.cpp b/src/declarative/items/qsggridview.cpp
index 26347c1c93..bc4954a168 100644
--- a/src/declarative/items/qsggridview.cpp
+++ b/src/declarative/items/qsggridview.cpp
@@ -176,6 +176,8 @@ public:
virtual qreal headerSize() const;
virtual qreal footerSize() const;
+ virtual bool showHeaderForIndex(int index) const;
+ virtual bool showFooterForIndex(int index) const;
virtual void updateHeader();
virtual void updateFooter();
@@ -602,7 +604,8 @@ void QSGGridViewPrivate::updateHighlight()
{
if ((!currentItem && highlight) || (currentItem && !highlight))
createHighlight();
- if (currentItem && autoHighlight && highlight && !movingHorizontally && !movingVertically) {
+ bool strictHighlight = haveHighlightRange && highlightRange == QSGGridView::StrictlyEnforceRange;
+ if (currentItem && autoHighlight && highlight && (!strictHighlight || !pressed)) {
// auto-update highlight
highlightXAnimator->to = currentItem->item->x();
highlightYAnimator->to = currentItem->item->y();
@@ -637,6 +640,16 @@ qreal QSGGridViewPrivate::footerSize() const
return flow == QSGGridView::LeftToRight? footer->item->height() : footer->item->width();
}
+bool QSGGridViewPrivate::showHeaderForIndex(int index) const
+{
+ return index / columns == 0;
+}
+
+bool QSGGridViewPrivate::showFooterForIndex(int index) const
+{
+ return index / columns == (model->count()-1) / columns;
+}
+
void QSGGridViewPrivate::updateFooter()
{
Q_Q(QSGGridView);
@@ -955,6 +968,80 @@ void QSGGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent,
//----------------------------------------------------------------------------
+/*!
+ \qmlclass GridView QSGGridView
+ \inqmlmodule QtQuick 2
+ \ingroup qml-view-elements
+
+ \inherits Flickable
+ \brief The GridView item provides a grid view of items provided by a model.
+
+ A GridView displays data from models created from built-in QML elements like ListModel
+ and XmlListModel, or custom model classes defined in C++ that inherit from
+ QAbstractListModel.
+
+ A GridView has a \l model, which defines the data to be displayed, and
+ a \l delegate, which defines how the data should be displayed. Items in a
+ GridView are laid out horizontally or vertically. Grid views are inherently flickable
+ as GridView inherits from \l Flickable.
+
+ \section1 Example Usage
+
+ The following example shows the definition of a simple list model defined
+ in a file called \c ContactModel.qml:
+
+ \snippet doc/src/snippets/declarative/gridview/ContactModel.qml 0
+
+ \div {class="float-right"}
+ \inlineimage gridview-simple.png
+ \enddiv
+
+ This model can be referenced as \c ContactModel in other QML files. See \l{QML Modules}
+ for more information about creating reusable components like this.
+
+ Another component can display this model data in a GridView, as in the following
+ example, which creates a \c ContactModel component for its model, and a \l Column element
+ (containing \l Image and \l Text elements) for its delegate.
+
+ \clearfloat
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml import
+ \codeline
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml classdocs simple
+
+ \div {class="float-right"}
+ \inlineimage gridview-highlight.png
+ \enddiv
+
+ The view will create a new delegate for each item in the model. Note that the delegate
+ is able to access the model's \c name and \c portrait data directly.
+
+ An improved grid view is shown below. The delegate is visually improved and is moved
+ into a separate \c contactDelegate component.
+
+ \clearfloat
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml classdocs advanced
+
+ The currently selected item is highlighted with a blue \l Rectangle using the \l highlight property,
+ and \c focus is set to \c true to enable keyboard navigation for the grid view.
+ The grid view itself is a focus scope (see \l{qmlfocus#Acquiring Focus and Focus Scopes}{the focus documentation page} for more details).
+
+ Delegates are instantiated as needed and may be destroyed at any time.
+ State should \e never be stored in a delegate.
+
+ GridView attaches a number of properties to the root item of the delegate, for example
+ \c {GridView.isCurrentItem}. In the following example, the root delegate item can access
+ this attached property directly as \c GridView.isCurrentItem, while the child
+ \c contactInfo object must refer to this property as \c wrapper.GridView.isCurrentItem.
+
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml isCurrentItem
+
+ \note Views do not set the \l{Item::}{clip} property automatically.
+ If the view is not clipped by another item or the screen, it will be necessary
+ to set this property to true in order to clip the items that are partially or
+ fully outside the view.
+
+ \sa {declarative/modelviews/gridview}{GridView example}
+*/
QSGGridView::QSGGridView(QSGItem *parent)
: QSGItemView(*(new QSGGridViewPrivate), parent)
@@ -977,6 +1064,242 @@ void QSGGridView::setHighlightFollowsCurrentItem(bool autoHighlight)
}
}
+/*!
+ \qmlattachedproperty bool QtQuick2::GridView::isCurrentItem
+ This attached property is true if this delegate is the current item; otherwise false.
+
+ It is attached to each instance of the delegate.
+*/
+
+/*!
+ \qmlattachedproperty GridView QtQuick2::GridView::view
+ This attached property holds the view that manages this delegate instance.
+
+ It is attached to each instance of the delegate.
+
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml isCurrentItem
+*/
+
+/*!
+ \qmlattachedproperty bool QtQuick2::GridView::delayRemove
+ This attached property holds whether the delegate may be destroyed.
+
+ It is attached to each instance of the delegate.
+
+ It is sometimes necessary to delay the destruction of an item
+ until an animation completes.
+
+ The example below ensures that the animation completes before
+ the item is removed from the grid.
+
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml delayRemove
+*/
+
+/*!
+ \qmlattachedsignal QtQuick2::GridView::onAdd()
+ This attached handler is called immediately after an item is added to the view.
+*/
+
+/*!
+ \qmlattachedsignal QtQuick2::GridView::onRemove()
+ This attached handler is called immediately before an item is removed from the view.
+*/
+
+
+/*!
+ \qmlproperty model QtQuick2::GridView::model
+ This property holds the model providing data for the grid.
+
+ The model provides the set of data that is used to create the items
+ in the view. Models can be created directly in QML using \l ListModel, \l XmlListModel
+ or \l VisualItemModel, or provided by C++ model classes. If a C++ model class is
+ used, it must be a subclass of \l QAbstractItemModel or a simple list.
+
+ \sa {qmlmodels}{Data Models}
+*/
+
+/*!
+ \qmlproperty Component QtQuick2::GridView::delegate
+
+ The delegate provides a template defining each item instantiated by the view.
+ The index is exposed as an accessible \c index property. Properties of the
+ model are also available depending upon the type of \l {qmlmodels}{Data Model}.
+
+ The number of elements in the delegate has a direct effect on the
+ flicking performance of the view. If at all possible, place functionality
+ that is not needed for the normal display of the delegate in a \l Loader which
+ can load additional elements when needed.
+
+ The GridView will layout the items based on the size of the root item
+ in the delegate.
+
+ \note Delegates are instantiated as needed and may be destroyed at any time.
+ State should \e never be stored in a delegate.
+*/
+
+/*!
+ \qmlproperty int QtQuick2::GridView::currentIndex
+ \qmlproperty Item QtQuick2::GridView::currentItem
+
+ The \c currentIndex property holds the index of the current item, and
+ \c currentItem holds the current item. Setting the currentIndex to -1
+ will clear the highlight and set currentItem to null.
+
+ If highlightFollowsCurrentItem is \c true, setting either of these
+ properties will smoothly scroll the GridView so that the current
+ item becomes visible.
+
+ Note that the position of the current item
+ may only be approximate until it becomes visible in the view.
+*/
+
+
+/*!
+ \qmlproperty Item QtQuick2::GridView::highlightItem
+
+ This holds the highlight item created from the \l highlight component.
+
+ The highlightItem is managed by the view unless
+ \l highlightFollowsCurrentItem is set to false.
+
+ \sa highlight, highlightFollowsCurrentItem
+*/
+
+
+/*!
+ \qmlproperty int QtQuick2::GridView::count
+ This property holds the number of items in the view.
+*/
+
+
+/*!
+ \qmlproperty Component QtQuick2::GridView::highlight
+ This property holds the component to use as the highlight.
+
+ An instance of the highlight component is created for each view.
+ The geometry of the resulting component instance will be managed by the view
+ so as to stay with the current item, unless the highlightFollowsCurrentItem property is false.
+
+ \sa highlightItem, highlightFollowsCurrentItem
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::GridView::highlightFollowsCurrentItem
+ This property sets whether the highlight is managed by the view.
+
+ If this property is true (the default value), the highlight is moved smoothly
+ to follow the current item. Otherwise, the
+ highlight is not moved by the view, and any movement must be implemented
+ by the highlight.
+
+ Here is a highlight with its motion defined by a \l {SpringAnimation} item:
+
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml highlightFollowsCurrentItem
+*/
+
+
+/*!
+ \qmlproperty int QtQuick2::GridView::highlightMoveDuration
+ This property holds the move animation duration of the highlight delegate.
+
+ highlightFollowsCurrentItem must be true for this property
+ to have effect.
+
+ The default value for the duration is 150ms.
+
+ \sa highlightFollowsCurrentItem
+*/
+
+/*!
+ \qmlproperty real QtQuick2::GridView::preferredHighlightBegin
+ \qmlproperty real QtQuick2::GridView::preferredHighlightEnd
+ \qmlproperty enumeration QtQuick2::GridView::highlightRangeMode
+
+ These properties define the preferred range of the highlight (for the current item)
+ within the view. The \c preferredHighlightBegin value must be less than the
+ \c preferredHighlightEnd value.
+
+ These properties affect the position of the current item when the view is scrolled.
+ For example, if the currently selected item should stay in the middle of the
+ view when it is scrolled, set the \c preferredHighlightBegin and
+ \c preferredHighlightEnd values to the top and bottom coordinates of where the middle
+ item would be. If the \c currentItem is changed programmatically, the view will
+ automatically scroll so that the current item is in the middle of the view.
+ Furthermore, the behavior of the current item index will occur whether or not a
+ highlight exists.
+
+ Valid values for \c highlightRangeMode are:
+
+ \list
+ \o GridView.ApplyRange - the view attempts to maintain the highlight within the range.
+ However, the highlight can move outside of the range at the ends of the view or due
+ to mouse interaction.
+ \o GridView.StrictlyEnforceRange - the highlight never moves outside of the range.
+ The current item changes if a keyboard or mouse action would cause the highlight to move
+ outside of the range.
+ \o GridView.NoHighlightRange - this is the default value.
+ \endlist
+*/
+
+
+/*!
+ \qmlproperty enumeration QtQuick2::GridView::layoutDirection
+ This property holds the layout direction of the grid.
+
+ Possible values:
+
+ \list
+ \o Qt.LeftToRight (default) - Items will be laid out starting in the top, left corner. The flow is
+ dependent on the \l GridView::flow property.
+ \o Qt.RightToLeft - Items will be laid out starting in the top, right corner. The flow is dependent
+ on the \l GridView::flow property.
+ \endlist
+
+ \bold Note: If GridView::flow is set to GridView.LeftToRight, this is not to be confused if
+ GridView::layoutDirection is set to Qt.RightToLeft. The GridView.LeftToRight flow value simply
+ indicates that the flow is horizontal.
+*/
+
+
+/*!
+ \qmlproperty enumeration QtQuick2::GridView::effectiveLayoutDirection
+ This property holds the effective layout direction of the grid.
+
+ When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
+ the visual layout direction of the grid will be mirrored. However, the
+ property \l {GridView::layoutDirection}{layoutDirection} will remain unchanged.
+
+ \sa GridView::layoutDirection, {LayoutMirroring}{LayoutMirroring}
+*/
+/*!
+ \qmlproperty bool QtQuick2::GridView::keyNavigationWraps
+ This property holds whether the grid wraps key navigation
+
+ If this is true, key navigation that would move the current item selection
+ past one end of the view instead wraps around and moves the selection to
+ the other end of the view.
+
+ By default, key navigation is not wrapped.
+*/
+/*!
+ \qmlproperty int QtQuick2::GridView::cacheBuffer
+ This property determines whether delegates are retained outside the
+ visible area of the view.
+
+ If non-zero the view will keep as many delegates
+ instantiated as will fit within the buffer specified. For example,
+ if in a vertical view the delegate is 20 pixels high and \c cacheBuffer is
+ set to 40, then up to 2 delegates above and 2 delegates below the visible
+ area may be retained.
+
+ Note that cacheBuffer is not a pixel buffer - it only maintains additional
+ instantiated delegates.
+
+ Setting this value can make scrolling the list smoother at the expense
+ of additional memory usage. It is not a substitute for creating efficient
+ delegates; the fewer elements in a delegate, the faster a view may be
+ scrolled.
+*/
void QSGGridView::setHighlightMoveDuration(int duration)
{
Q_D(QSGGridView);
@@ -989,6 +1312,17 @@ void QSGGridView::setHighlightMoveDuration(int duration)
}
}
+/*!
+ \qmlproperty enumeration QtQuick2::GridView::flow
+ This property holds the flow of the grid.
+
+ Possible values:
+
+ \list
+ \o GridView.LeftToRight (default) - Items are laid out from left to right, and the view scrolls vertically
+ \o GridView.TopToBottom - Items are laid out from top to bottom, and the view scrolls horizontally
+ \endlist
+*/
QSGGridView::Flow QSGGridView::flow() const
{
Q_D(const QSGGridView);
@@ -1015,6 +1349,14 @@ void QSGGridView::setFlow(Flow flow)
}
+/*!
+ \qmlproperty int QtQuick2::GridView::cellWidth
+ \qmlproperty int QtQuick2::GridView::cellHeight
+
+ These properties holds the width and height of each cell in the grid.
+
+ The default cell size is 100x100.
+*/
int QSGGridView::cellWidth() const
{
Q_D(const QSGGridView);
@@ -1048,7 +1390,22 @@ void QSGGridView::setCellHeight(int cellHeight)
d->layout();
}
}
-
+/*!
+ \qmlproperty enumeration QtQuick2::GridView::snapMode
+
+ This property determines how the view scrolling will settle following a drag or flick.
+ The possible values are:
+
+ \list
+ \o GridView.NoSnap (default) - the view stops anywhere within the visible area.
+ \o GridView.SnapToRow - the view settles with a row (or column for \c GridView.TopToBottom flow)
+ aligned with the start of the view.
+ \o GridView.SnapOneRow - the view will settle no more than one row (or column for \c GridView.TopToBottom flow)
+ away from the first visible row at the time the mouse button is released.
+ This mode is particularly useful for moving one page at a time.
+ \endlist
+
+*/
QSGGridView::SnapMode QSGGridView::snapMode() const
{
Q_D(const QSGGridView);
@@ -1065,6 +1422,24 @@ void QSGGridView::setSnapMode(SnapMode mode)
}
+/*!
+ \qmlproperty Component QtQuick2::GridView::footer
+ This property holds the component to use as the footer.
+
+ An instance of the footer component is created for each view. The
+ footer is positioned at the end of the view, after any items.
+
+ \sa header
+*/
+/*!
+ \qmlproperty Component QtQuick2::GridView::header
+ This property holds the component to use as the header.
+
+ An instance of the header component is created for each view. The
+ header is positioned at the beginning of the view, before any items.
+
+ \sa footer
+*/
void QSGGridView::viewportMoved()
{
Q_D(QSGGridView);
@@ -1115,7 +1490,13 @@ void QSGGridView::viewportMoved()
if (pos < viewPos + highlightStart)
pos = viewPos + highlightStart;
- static_cast<FxGridItemSG*>(d->highlight)->setPosition(static_cast<FxGridItemSG*>(d->highlight)->colPos(), qRound(pos));
+ if (pos != d->highlight->position()) {
+ d->highlightXAnimator->stop();
+ d->highlightYAnimator->stop();
+ static_cast<FxGridItemSG*>(d->highlight)->setPosition(static_cast<FxGridItemSG*>(d->highlight)->colPos(), pos);
+ } else {
+ d->updateHighlight();
+ }
// update current index
int idx = d->snapIndex();
@@ -1164,6 +1545,16 @@ void QSGGridView::keyPressEvent(QKeyEvent *event)
event->ignore();
QSGItemView::keyPressEvent(event);
}
+/*!
+ \qmlmethod QtQuick2::GridView::moveCurrentIndexUp()
+
+ Move the currentIndex up one item in the view.
+ The current index will wrap if keyNavigationWraps is true and it
+ is currently at the end. This method has no effect if the \l count is zero.
+
+ \bold Note: methods should only be called after the Component has completed.
+*/
+
void QSGGridView::moveCurrentIndexUp()
{
@@ -1184,6 +1575,15 @@ void QSGGridView::moveCurrentIndexUp()
}
}
+/*!
+ \qmlmethod QtQuick2::GridView::moveCurrentIndexDown()
+
+ Move the currentIndex down one item in the view.
+ The current index will wrap if keyNavigationWraps is true and it
+ is currently at the end. This method has no effect if the \l count is zero.
+
+ \bold Note: methods should only be called after the Component has completed.
+*/
void QSGGridView::moveCurrentIndexDown()
{
Q_D(QSGGridView);
@@ -1203,6 +1603,15 @@ void QSGGridView::moveCurrentIndexDown()
}
}
+/*!
+ \qmlmethod QtQuick2::GridView::moveCurrentIndexLeft()
+
+ Move the currentIndex left one item in the view.
+ The current index will wrap if keyNavigationWraps is true and it
+ is currently at the end. This method has no effect if the \l count is zero.
+
+ \bold Note: methods should only be called after the Component has completed.
+*/
void QSGGridView::moveCurrentIndexLeft()
{
Q_D(QSGGridView);
@@ -1236,6 +1645,16 @@ void QSGGridView::moveCurrentIndexLeft()
}
}
+
+/*!
+ \qmlmethod QtQuick2::GridView::moveCurrentIndexRight()
+
+ Move the currentIndex right one item in the view.
+ The current index will wrap if keyNavigationWraps is true and it
+ is currently at the end. This method has no effect if the \l count is zero.
+
+ \bold Note: methods should only be called after the Component has completed.
+*/
void QSGGridView::moveCurrentIndexRight()
{
Q_D(QSGGridView);
@@ -1273,7 +1692,7 @@ void QSGGridView::moveCurrentIndexRight()
void QSGGridView::itemsInserted(int modelIndex, int count)
{
Q_D(QSGGridView);
- if (!isComponentComplete())
+ if (!isComponentComplete() || !d->model || !d->model->isValid())
return;
int index = d->visibleItems.count() ? d->mapFromModel(modelIndex) : 0;
@@ -1404,7 +1823,7 @@ void QSGGridView::itemsInserted(int modelIndex, int count)
void QSGGridView::itemsRemoved(int modelIndex, int count)
{
Q_D(QSGGridView);
- if (!isComponentComplete())
+ if (!isComponentComplete() || !d->model || !d->model->isValid())
return;
d->itemCount -= count;
@@ -1486,7 +1905,7 @@ void QSGGridView::itemsRemoved(int modelIndex, int count)
void QSGGridView::itemsMoved(int from, int to, int count)
{
Q_D(QSGGridView);
- if (!isComponentComplete())
+ if (!isComponentComplete() || !d->isValid())
return;
d->updateUnrequestedIndexes();
@@ -1614,7 +2033,71 @@ void QSGGridView::itemsMoved(int from, int to, int count)
d->layout();
}
+/*!
+ \qmlmethod QtQuick2::GridView::positionViewAtIndex(int index, PositionMode mode)
+
+ Positions the view such that the \a index is at the position specified by
+ \a mode:
+
+ \list
+ \o GridView.Beginning - position item at the top (or left for \c GridView.TopToBottom flow) of the view.
+ \o GridView.Center - position item in the center of the view.
+ \o GridView.End - position item at bottom (or right for horizontal orientation) of the view.
+ \o GridView.Visible - if any part of the item is visible then take no action, otherwise
+ bring the item into view.
+ \o GridView.Contain - ensure the entire item is visible. If the item is larger than
+ the view the item is positioned at the top (or left for \c GridView.TopToBottom flow) of the view.
+ \endlist
+
+ If positioning the view at the index would cause empty space to be displayed at
+ the beginning or end of the view, the view will be positioned at the boundary.
+
+ It is not recommended to use \l {Flickable::}{contentX} or \l {Flickable::}{contentY} to position the view
+ at a particular index. This is unreliable since removing items from the start
+ of the view does not cause all other items to be repositioned.
+ The correct way to bring an item into view is with \c positionViewAtIndex.
+
+ \bold Note: methods should only be called after the Component has completed. To position
+ the view at startup, this method should be called by Component.onCompleted. For
+ example, to position the view at the end:
+
+ \code
+ Component.onCompleted: positionViewAtIndex(count - 1, GridView.Beginning)
+ \endcode
+*/
+
+/*!
+ \qmlmethod QtQuick2::GridView::positionViewAtBeginning()
+ \qmlmethod QtQuick2::GridView::positionViewAtEnd()
+
+ Positions the view at the beginning or end, taking into account any header or footer.
+
+ It is not recommended to use \l {Flickable::}{contentX} or \l {Flickable::}{contentY} to position the view
+ at a particular index. This is unreliable since removing items from the start
+ of the list does not cause all other items to be repositioned, and because
+ the actual start of the view can vary based on the size of the delegates.
+
+ \bold Note: methods should only be called after the Component has completed. To position
+ the view at startup, this method should be called by Component.onCompleted. For
+ example, to position the view at the end on startup:
+
+ \code
+ Component.onCompleted: positionViewAtEnd()
+ \endcode
+*/
+
+/*!
+ \qmlmethod int QtQuick2::GridView::indexAt(int x, int y)
+
+ Returns the index of the visible item containing the point \a x, \a y in content
+ coordinates. If there is no item at the point specified, or the item is
+ not visible -1 is returned.
+
+ If the item is outside the visible area, -1 is returned, regardless of
+ whether an item will exist at that point when scrolled into view.
+ \bold Note: methods should only be called after the Component has completed.
+*/
QSGGridViewAttached *QSGGridView::qmlAttachedProperties(QObject *obj)
{
return new QSGGridViewAttached(obj);
diff --git a/src/declarative/items/qsgimage.cpp b/src/declarative/items/qsgimage.cpp
index dc5c8d11c7..cb12c177cd 100644
--- a/src/declarative/items/qsgimage.cpp
+++ b/src/declarative/items/qsgimage.cpp
@@ -95,7 +95,6 @@ QSGImagePrivate::QSGImagePrivate()
/*!
\qmlclass Image QSGImage
- \since QtQuick 1.0
\inqmlmodule QtQuick 2
\ingroup qml-basic-visual-elements
\brief The Image element displays an image in a declarative user interface
@@ -446,7 +445,6 @@ qreal QSGImage::paintedHeight() const
/*!
\qmlproperty bool QtQuick2::Image::cache
- \since Quick 1.1
Specifies whether the image should be cached. The default value is
true. Setting \a cache to false is useful when dealing with large images,
@@ -455,7 +453,6 @@ qreal QSGImage::paintedHeight() const
/*!
\qmlproperty bool QtQuick2::Image::mirror
- \since Quick 1.1
This property holds whether the image should be horizontally inverted
(effectively displaying a mirrored image).
@@ -466,7 +463,6 @@ qreal QSGImage::paintedHeight() const
/*!
\qmlproperty enumeration QtQuick2::Image::horizontalAlignment
\qmlproperty enumeration QtQuick2::Image::verticalAlignment
- \since Quick 2.0
Sets the horizontal and vertical alignment of the image. By default, the image is top-left aligned.
diff --git a/src/declarative/items/qsgitem.cpp b/src/declarative/items/qsgitem.cpp
index 163cec13ee..a7797630c0 100644
--- a/src/declarative/items/qsgitem.cpp
+++ b/src/declarative/items/qsgitem.cpp
@@ -71,6 +71,168 @@
QT_BEGIN_NAMESPACE
+/*!
+ \qmlclass Transform QSGTransform
+ \inqmlmodule QtQuick 2
+ \ingroup qml-transform-elements
+ \brief The Transform elements provide a way of building advanced transformations on Items.
+
+ The Transform element is a base type which cannot be instantiated directly.
+ The following concrete Transform types are available:
+
+ \list
+ \o \l Rotation
+ \o \l Scale
+ \o \l Translate
+ \endlist
+
+ The Transform elements let you create and control advanced transformations that can be configured
+ independently using specialized properties.
+
+ You can assign any number of Transform elements to an \l Item. Each Transform is applied in order,
+ one at a time.
+*/
+
+/*!
+ \qmlclass Translate QSGTranslate
+ \inqmlmodule QtQuick 2
+ \ingroup qml-transform-elements
+ \brief The Translate object provides a way to move an Item without changing its x or y properties.
+
+ The Translate object provides independent control over position in addition to the Item's x and y properties.
+
+ The following example moves the Y axis of the \l Rectangle elements while still allowing the \l Row element
+ to lay the items out as if they had not been transformed:
+ \qml
+ import QtQuick 1.0
+
+ Row {
+ Rectangle {
+ width: 100; height: 100
+ color: "blue"
+ transform: Translate { y: 20 }
+ }
+ Rectangle {
+ width: 100; height: 100
+ color: "red"
+ transform: Translate { y: -20 }
+ }
+ }
+ \endqml
+
+ \image translate.png
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Translate::x
+
+ The translation along the X axis.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Translate::y
+
+ The translation along the Y axis.
+*/
+
+/*!
+ \qmlclass Scale QSGScale
+ \inqmlmodule QtQuick 2
+ \ingroup qml-transform-elements
+ \brief The Scale element provides a way to scale an Item.
+
+ The Scale element gives more control over scaling than using \l Item's \l{Item::scale}{scale} property. Specifically,
+ it allows a different scale for the x and y axes, and allows the scale to be relative to an
+ arbitrary point.
+
+ The following example scales the X axis of the Rectangle, relative to its interior point 25, 25:
+ \qml
+ Rectangle {
+ width: 100; height: 100
+ color: "blue"
+ transform: Scale { origin.x: 25; origin.y: 25; xScale: 3}
+ }
+ \endqml
+
+ \sa Rotation, Translate
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Scale::origin.x
+ \qmlproperty real QtQuick2::Scale::origin.y
+
+ The point that the item is scaled from (i.e., the point that stays fixed relative to the parent as
+ the rest of the item grows). By default the origin is 0, 0.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Scale::xScale
+
+ The scaling factor for the X axis.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Scale::yScale
+
+ The scaling factor for the Y axis.
+*/
+
+/*!
+ \qmlclass Rotation QSGRotation
+ \inqmlmodule QtQuick 2
+ \ingroup qml-transform-elements
+ \brief The Rotation object provides a way to rotate an Item.
+
+ The Rotation object gives more control over rotation than using \l Item's \l{Item::rotation}{rotation} property.
+ Specifically, it allows (z axis) rotation to be relative to an arbitrary point.
+
+ The following example rotates a Rectangle around its interior point 25, 25:
+ \qml
+ Rectangle {
+ width: 100; height: 100
+ color: "blue"
+ transform: Rotation { origin.x: 25; origin.y: 25; angle: 45}
+ }
+ \endqml
+
+ Rotation also provides a way to specify 3D-like rotations for Items. For these types of
+ rotations you must specify the axis to rotate around in addition to the origin point.
+
+ The following example shows various 3D-like rotations applied to an \l Image.
+ \snippet doc/src/snippets/declarative/rotation.qml 0
+
+ \image axisrotation.png
+
+ \sa {declarative/ui-components/dialcontrol}{Dial Control example}, {declarative/toys/clocks}{Clocks example}
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Rotation::origin.x
+ \qmlproperty real QtQuick2::Rotation::origin.y
+
+ The origin point of the rotation (i.e., the point that stays fixed relative to the parent as
+ the rest of the item rotates). By default the origin is 0, 0.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Rotation::axis.x
+ \qmlproperty real QtQuick2::Rotation::axis.y
+ \qmlproperty real QtQuick2::Rotation::axis.z
+
+ The axis to rotate around. For simple (2D) rotation around a point, you do not need to specify an axis,
+ as the default axis is the z axis (\c{ axis { x: 0; y: 0; z: 1 } }).
+
+ For a typical 3D-like rotation you will usually specify both the origin and the axis.
+
+ \image 3d-rotation-axis.png
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Rotation::angle
+
+ The angle to rotate, in degrees clockwise.
+*/
+
QSGTransformPrivate::QSGTransformPrivate()
{
}
@@ -104,7 +266,7 @@ void QSGTransform::update()
}
}
-QSGContents::QSGContents(QSGItem *item)
+QSGContents::QSGContents(QSGItem *item)
: m_item(item), m_x(0), m_y(0), m_width(0), m_height(0)
{
//### optimize
@@ -283,6 +445,69 @@ void QSGItemKeyFilter::componentComplete()
{
if (m_next) m_next->componentComplete();
}
+/*!
+ \qmlclass KeyNavigation QSGKeyNavigationAttached
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-interaction-elements
+ \brief The KeyNavigation attached property supports key navigation by arrow keys.
+
+ Key-based user interfaces commonly allow the use of arrow keys to navigate between
+ focusable items. The KeyNavigation attached property enables this behavior by providing a
+ convenient way to specify the item that should gain focus when an arrow or tab key is pressed.
+
+ The following example provides key navigation for a 2x2 grid of items:
+
+ \snippet doc/src/snippets/declarative/keynavigation.qml 0
+
+ The top-left item initially receives focus by setting \l {Item::}{focus} to
+ \c true. When an arrow key is pressed, the focus will move to the
+ appropriate item, as defined by the value that has been set for
+ the KeyNavigation \l left, \l right, \l up or \l down properties.
+
+ Note that if a KeyNavigation attached property receives the key press and release
+ events for a requested arrow or tab key, the event is accepted and does not
+ propagate any further.
+
+ By default, KeyNavigation receives key events after the item to which it is attached.
+ If the item accepts the key event, the KeyNavigation attached property will not
+ receive an event for that key. Setting the \l priority property to
+ \c KeyNavigation.BeforeItem allows the event to be used for key navigation
+ before the item, rather than after.
+
+ If item to which the focus is switching is not enabled or visible, an attempt will
+ be made to skip this item and focus on the next. This is possible if there are
+ a chain of items with the same KeyNavigation handler. If multiple items in a row are not enabled
+ or visible, they will also be skipped.
+
+ KeyNavigation will implicitly set the other direction to return focus to this item. So if you set
+ \l left to another item, \l right will be set on that item's KeyNavigation to set focus back to this
+ item. However, if that item's KeyNavigation has had right explicitly set then no change will occur.
+ This means that the above example could have been written, with the same behaviour, without specifing
+ KeyNavigation.right or KeyNavigation.down for any of the items.
+
+ \sa {Keys}{Keys attached property}
+*/
+
+/*!
+ \qmlproperty Item QtQuick2::KeyNavigation::left
+ \qmlproperty Item QtQuick2::KeyNavigation::right
+ \qmlproperty Item QtQuick2::KeyNavigation::up
+ \qmlproperty Item QtQuick2::KeyNavigation::down
+ \qmlproperty Item QtQuick2::KeyNavigation::tab
+ \qmlproperty Item QtQuick2::KeyNavigation::backtab
+
+ These properties hold the item to assign focus to
+ when the left, right, up or down cursor keys, or the
+ tab key are pressed.
+*/
+
+/*!
+ \qmlproperty Item QtQuick2::KeyNavigation::tab
+ \qmlproperty Item QtQuick2::KeyNavigation::backtab
+
+ These properties hold the item to assign focus to
+ when the Tab key or Shift+Tab key combination (Backtab) are pressed.
+*/
QSGKeyNavigationAttached::QSGKeyNavigationAttached(QObject *parent)
: QObject(*(new QSGKeyNavigationAttachedPrivate), parent),
@@ -429,6 +654,21 @@ void QSGKeyNavigationAttached::setBacktab(QSGItem *i)
emit backtabChanged();
}
+/*!
+ \qmlproperty enumeration QtQuick2::KeyNavigation::priority
+
+ This property determines whether the keys are processed before
+ or after the attached item's own key handling.
+
+ \list
+ \o KeyNavigation.BeforeItem - process the key events before normal
+ item key processing. If the event is used for key navigation, it will be accepted and will not
+ be passed on to the item.
+ \o KeyNavigation.AfterItem (default) - process the key events after normal item key
+ handling. If the item accepts the key event it will not be
+ handled by the KeyNavigation attached property handler.
+ \endlist
+*/
QSGKeyNavigationAttached::Priority QSGKeyNavigationAttached::priority() const
{
return m_processPost ? AfterItem : BeforeItem;
@@ -617,6 +857,393 @@ bool QSGKeysAttachedPrivate::isConnected(const char *signalName)
return isSignalConnected(signalIndex(signalName));
}
+/*!
+ \qmlclass Keys QSGKeysAttached
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-interaction-elements
+ \brief The Keys attached property provides key handling to Items.
+
+ All visual primitives support key handling via the Keys
+ attached property. Keys can be handled via the onPressed
+ and onReleased signal properties.
+
+ The signal properties have a \l KeyEvent parameter, named
+ \e event which contains details of the event. If a key is
+ handled \e event.accepted should be set to true to prevent the
+ event from propagating up the item hierarchy.
+
+ \section1 Example Usage
+
+ The following example shows how the general onPressed handler can
+ be used to test for a certain key; in this case, the left cursor
+ key:
+
+ \snippet doc/src/snippets/declarative/keys/keys-pressed.qml key item
+
+ Some keys may alternatively be handled via specific signal properties,
+ for example \e onSelectPressed. These handlers automatically set
+ \e event.accepted to true.
+
+ \snippet doc/src/snippets/declarative/keys/keys-handler.qml key item
+
+ See \l{Qt::Key}{Qt.Key} for the list of keyboard codes.
+
+ \section1 Key Handling Priorities
+
+ The Keys attached property can be configured to handle key events
+ before or after the item it is attached to. This makes it possible
+ to intercept events in order to override an item's default behavior,
+ or act as a fallback for keys not handled by the item.
+
+ If \l priority is Keys.BeforeItem (default) the order of key event processing is:
+
+ \list 1
+ \o Items specified in \c forwardTo
+ \o specific key handlers, e.g. onReturnPressed
+ \o onKeyPress, onKeyRelease handlers
+ \o Item specific key handling, e.g. TextInput key handling
+ \o parent item
+ \endlist
+
+ If priority is Keys.AfterItem the order of key event processing is:
+
+ \list 1
+ \o Item specific key handling, e.g. TextInput key handling
+ \o Items specified in \c forwardTo
+ \o specific key handlers, e.g. onReturnPressed
+ \o onKeyPress, onKeyRelease handlers
+ \o parent item
+ \endlist
+
+ If the event is accepted during any of the above steps, key
+ propagation stops.
+
+ \sa KeyEvent, {KeyNavigation}{KeyNavigation attached property}
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::Keys::enabled
+
+ This flags enables key handling if true (default); otherwise
+ no key handlers will be called.
+*/
+
+/*!
+ \qmlproperty enumeration QtQuick2::Keys::priority
+
+ This property determines whether the keys are processed before
+ or after the attached item's own key handling.
+
+ \list
+ \o Keys.BeforeItem (default) - process the key events before normal
+ item key processing. If the event is accepted it will not
+ be passed on to the item.
+ \o Keys.AfterItem - process the key events after normal item key
+ handling. If the item accepts the key event it will not be
+ handled by the Keys attached property handler.
+ \endlist
+*/
+
+/*!
+ \qmlproperty list<Object> QtQuick2::Keys::forwardTo
+
+ This property provides a way to forward key presses, key releases, and keyboard input
+ coming from input methods to other items. This can be useful when you want
+ one item to handle some keys (e.g. the up and down arrow keys), and another item to
+ handle other keys (e.g. the left and right arrow keys). Once an item that has been
+ forwarded keys accepts the event it is no longer forwarded to items later in the
+ list.
+
+ This example forwards key events to two lists:
+ \qml
+ Item {
+ ListView {
+ id: list1
+ // ...
+ }
+ ListView {
+ id: list2
+ // ...
+ }
+ Keys.forwardTo: [list1, list2]
+ focus: true
+ }
+ \endqml
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onPressed(KeyEvent event)
+
+ This handler is called when a key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onReleased(KeyEvent event)
+
+ This handler is called when a key has been released. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onDigit0Pressed(KeyEvent event)
+
+ This handler is called when the digit '0' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onDigit1Pressed(KeyEvent event)
+
+ This handler is called when the digit '1' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onDigit2Pressed(KeyEvent event)
+
+ This handler is called when the digit '2' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onDigit3Pressed(KeyEvent event)
+
+ This handler is called when the digit '3' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onDigit4Pressed(KeyEvent event)
+
+ This handler is called when the digit '4' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onDigit5Pressed(KeyEvent event)
+
+ This handler is called when the digit '5' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onDigit6Pressed(KeyEvent event)
+
+ This handler is called when the digit '6' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onDigit7Pressed(KeyEvent event)
+
+ This handler is called when the digit '7' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onDigit8Pressed(KeyEvent event)
+
+ This handler is called when the digit '8' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onDigit9Pressed(KeyEvent event)
+
+ This handler is called when the digit '9' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onLeftPressed(KeyEvent event)
+
+ This handler is called when the Left arrow has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onRightPressed(KeyEvent event)
+
+ This handler is called when the Right arrow has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onUpPressed(KeyEvent event)
+
+ This handler is called when the Up arrow has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onDownPressed(KeyEvent event)
+
+ This handler is called when the Down arrow has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onTabPressed(KeyEvent event)
+
+ This handler is called when the Tab key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onBacktabPressed(KeyEvent event)
+
+ This handler is called when the Shift+Tab key combination (Backtab) has
+ been pressed. The \a event parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onAsteriskPressed(KeyEvent event)
+
+ This handler is called when the Asterisk '*' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onEscapePressed(KeyEvent event)
+
+ This handler is called when the Escape key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onReturnPressed(KeyEvent event)
+
+ This handler is called when the Return key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onEnterPressed(KeyEvent event)
+
+ This handler is called when the Enter key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onDeletePressed(KeyEvent event)
+
+ This handler is called when the Delete key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onSpacePressed(KeyEvent event)
+
+ This handler is called when the Space key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onBackPressed(KeyEvent event)
+
+ This handler is called when the Back key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onCancelPressed(KeyEvent event)
+
+ This handler is called when the Cancel key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onSelectPressed(KeyEvent event)
+
+ This handler is called when the Select key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onYesPressed(KeyEvent event)
+
+ This handler is called when the Yes key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onNoPressed(KeyEvent event)
+
+ This handler is called when the No key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onContext1Pressed(KeyEvent event)
+
+ This handler is called when the Context1 key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onContext2Pressed(KeyEvent event)
+
+ This handler is called when the Context2 key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onContext3Pressed(KeyEvent event)
+
+ This handler is called when the Context3 key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onContext4Pressed(KeyEvent event)
+
+ This handler is called when the Context4 key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onCallPressed(KeyEvent event)
+
+ This handler is called when the Call key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onHangupPressed(KeyEvent event)
+
+ This handler is called when the Hangup key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onFlipPressed(KeyEvent event)
+
+ This handler is called when the Flip key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onMenuPressed(KeyEvent event)
+
+ This handler is called when the Menu key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onVolumeUpPressed(KeyEvent event)
+
+ This handler is called when the VolumeUp key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onVolumeDownPressed(KeyEvent event)
+
+ This handler is called when the VolumeDown key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
QSGKeysAttached::QSGKeysAttached(QObject *parent)
: QObject(*(new QSGKeysAttachedPrivate), parent),
QSGItemKeyFilter(qobject_cast<QSGItem*>(parent))
@@ -759,7 +1386,7 @@ QVariant QSGKeysAttached::inputMethodQuery(Qt::InputMethodQuery query) const
if (d->item) {
for (int ii = 0; ii < d->targets.count(); ++ii) {
QSGItem *i = d->targets.at(ii);
- if (i && i->isVisible() && (i->flags() & QSGItem::ItemAcceptsInputMethod) && i == d->imeItem) {
+ if (i && i->isVisible() && (i->flags() & QSGItem::ItemAcceptsInputMethod) && i == d->imeItem) {
//### how robust is i == d->imeItem check?
QVariant v = i->inputMethodQuery(query);
if (v.userType() == QVariant::RectF)
@@ -776,6 +1403,69 @@ QSGKeysAttached *QSGKeysAttached::qmlAttachedProperties(QObject *obj)
return new QSGKeysAttached(obj);
}
+/*!
+ \qmlclass LayoutMirroring QSGLayoutMirroringAttached
+ \inqmlmodule QtQuick 2
+ \ingroup qml-utility-elements
+ \brief The LayoutMirroring attached property is used to mirror layout behavior.
+
+ The LayoutMirroring attached property is used to horizontally mirror \l {anchor-layout}{Item anchors},
+ \l{Using QML Positioner and Repeater Items}{positioner} elements (such as \l Row and \l Grid)
+ and views (such as \l GridView and horizontal \l ListView). Mirroring is a visual change: left
+ anchors become right anchors, and positioner elements like \l Grid and \l Row reverse the
+ horizontal layout of child items.
+
+ Mirroring is enabled for an item by setting the \l enabled property to true. By default, this
+ only affects the item itself; setting the \l childrenInherit property to true propagates the mirroring
+ behavior to all child elements as well. If the \c LayoutMirroring attached property has not been defined
+ for an item, mirroring is not enabled.
+
+ The following example shows mirroring in action. The \l Row below is specified as being anchored
+ to the left of its parent. However, since mirroring has been enabled, the anchor is horizontally
+ reversed and it is now anchored to the right. Also, since items in a \l Row are positioned
+ from left to right by default, they are now positioned from right to left instead, as demonstrated
+ by the numbering and opacity of the items:
+
+ \snippet doc/src/snippets/declarative/layoutmirroring.qml 0
+
+ \image layoutmirroring.png
+
+ Layout mirroring is useful when it is necessary to support both left-to-right and right-to-left
+ layout versions of an application to target different language areas. The \l childrenInherit
+ property allows layout mirroring to be applied without manually setting layout configurations
+ for every item in an application. Keep in mind, however, that mirroring does not affect any
+ positioning that is defined by the \l Item \l {Item::}{x} coordinate value, so even with
+ mirroring enabled, it will often be necessary to apply some layout fixes to support the
+ desired layout direction. Also, it may be necessary to disable the mirroring of individual
+ child items (by setting \l {enabled}{LayoutMirroring.enabled} to false for such items) if
+ mirroring is not the desired behavior, or if the child item already implements mirroring in
+ some custom way.
+
+ See \l {QML Right-to-left User Interfaces} for further details on using \c LayoutMirroring and
+ other related features to implement right-to-left support for an application.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::LayoutMirroring::enabled
+
+ This property holds whether the item's layout is mirrored horizontally. Setting this to true
+ horizontally reverses \l {anchor-layout}{anchor} settings such that left anchors become right,
+ and right anchors become left. For \l{Using QML Positioner and Repeater Items}{positioner} elements
+ (such as \l Row and \l Grid) and view elements (such as \l {GridView}{GridView} and \l {ListView}{ListView})
+ this also mirrors the horizontal layout direction of the item.
+
+ The default value is false.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::LayoutMirroring::childrenInherit
+
+ This property holds whether the \l {enabled}{LayoutMirroring.enabled} value for this item
+ is inherited by its children.
+
+ The default value is false.
+*/
+
QSGLayoutMirroringAttached::QSGLayoutMirroringAttached(QObject *parent) : QObject(parent), itemPrivate(0)
{
@@ -880,6 +1570,137 @@ void QSGItemPrivate::setLayoutMirror(bool mirror)
}
}
+/*!
+ \class QSGItem
+ \brief The QSGItem class provides the most basic of all visual items in QML.
+
+ All visual items in Qt Declarative inherit from QSGItem. Although QSGItem
+ has no visual appearance, it defines all the properties that are
+ common across visual items - such as the x and y position, the
+ width and height, \l {anchor-layout}{anchoring} and key handling.
+
+ You can subclass QSGItem to provide your own custom visual item that inherits
+ these features. Note that, because it does not draw anything, QSGItem sets the
+ QGraphicsItem::ItemHasNoContents flag. If you subclass QSGItem to create a visual
+ item, you will need to unset this flag.
+
+*/
+
+/*!
+ \qmlclass Item QSGItem
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-visual-elements
+ \brief The Item is the most basic of all visual items in QML.
+
+ All visual items in Qt Declarative inherit from Item. Although Item
+ has no visual appearance, it defines all the properties that are
+ common across visual items - such as the x and y position, the
+ width and height, \l {anchor-layout}{anchoring} and key handling.
+
+ Item is also useful for grouping items together.
+
+ \qml
+ Item {
+ Image {
+ source: "tile.png"
+ }
+ Image {
+ x: 80
+ width: 100
+ height: 100
+ source: "tile.png"
+ }
+ Image {
+ x: 190
+ width: 100
+ height: 100
+ fillMode: Image.Tile
+ source: "tile.png"
+ }
+ }
+ \endqml
+
+
+ \section1 Key Handling
+
+ Key handling is available to all Item-based visual elements via the \l {Keys}{Keys}
+ attached property. The \e Keys attached property provides basic handlers such
+ as \l {Keys::onPressed}{onPressed} and \l {Keys::onReleased}{onReleased},
+ as well as handlers for specific keys, such as
+ \l {Keys::onCancelPressed}{onCancelPressed}. The example below
+ assigns \l {qmlfocus}{focus} to the item and handles
+ the Left key via the general \e onPressed handler and the Select key via the
+ onSelectPressed handler:
+
+ \qml
+ Item {
+ focus: true
+ Keys.onPressed: {
+ if (event.key == Qt.Key_Left) {
+ console.log("move left");
+ event.accepted = true;
+ }
+ }
+ Keys.onSelectPressed: console.log("Selected");
+ }
+ \endqml
+
+ See the \l {Keys}{Keys} attached property for detailed documentation.
+
+ \section1 Layout Mirroring
+
+ Item layouts can be mirrored using the \l {LayoutMirroring}{LayoutMirroring} attached property.
+
+*/
+
+/*!
+ \fn void QSGItem::childrenRectChanged(const QRectF &)
+ \internal
+*/
+
+/*!
+ \fn void QSGItem::baselineOffsetChanged(qreal)
+ \internal
+*/
+
+/*!
+ \fn void QSGItem::stateChanged(const QString &state)
+ \internal
+*/
+
+/*!
+ \fn void QSGItem::parentChanged(QSGItem *)
+ \internal
+*/
+
+/*!
+ \fn void QSGItem::smoothChanged(bool)
+ \internal
+*/
+
+/*!
+ \fn void QSGItem::clipChanged(bool)
+ \internal
+*/
+
+/*! \fn void QSGItem::transformOriginChanged(TransformOrigin)
+ \internal
+*/
+
+/*!
+ \fn void QSGItem::focusChanged(bool)
+ \internal
+*/
+
+/*!
+ \fn void QSGItem::activeFocusChanged(bool)
+ \internal
+*/
+/*!
+ \fn QSGItem::QSGItem(QSGItem *parent)
+
+ Constructs a QSGItem with the given \a parent.
+*/
QSGItem::QSGItem(QSGItem* parent)
: QObject(*(new QSGItemPrivate), parent)
{
@@ -887,6 +1708,8 @@ QSGItem::QSGItem(QSGItem* parent)
d->init(parent);
}
+/*! \internal
+*/
QSGItem::QSGItem(QSGItemPrivate &dd, QSGItem *parent)
: QObject(dd, parent)
{
@@ -894,15 +1717,37 @@ QSGItem::QSGItem(QSGItemPrivate &dd, QSGItem *parent)
d->init(parent);
}
+#ifndef QT_NO_DEBUG
+static int qt_item_count = 0;
+
+static void qt_print_item_count()
+{
+ qDebug("Number of leaked items: %i", qt_item_count);
+ qt_item_count = -1;
+}
+#endif
+
+/*!
+ Destroys the QSGItem.
+*/
QSGItem::~QSGItem()
{
+#ifndef QT_NO_DEBUG
+ --qt_item_count;
+ if (qt_item_count < 0)
+ qDebug("Item destroyed after qt_print_item_count() was called.");
+#endif
+
Q_D(QSGItem);
+ if (d->parentItem)
+ setParentItem(0);
+ else if (d->canvas && d->itemNodeInstance)
+ QSGCanvasPrivate::get(d->canvas)->cleanup(d->itemNodeInstance); // cleanup root
// XXX todo - optimize
- setParentItem(0);
while (!d->childItems.isEmpty())
d->childItems.first()->setParentItem(0);
-
+
for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
QSGAnchorsPrivate *anchor = d->changeListeners.at(ii).listener->anchorPrivate();
if (anchor)
@@ -915,7 +1760,7 @@ QSGItem::~QSGItem()
if (anchor && anchor->item && anchor->item->parent() != this) //child will be deleted anyway
anchor->updateOnComplete();
}
-
+
for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
const QSGItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
if (change.types & QSGItemPrivate::Destroyed)
@@ -928,6 +1773,38 @@ QSGItem::~QSGItem()
delete d->_contents; d->_contents = 0;
}
+/*!
+ \qmlproperty enumeration QtQuick2::Item::transformOrigin
+ This property holds the origin point around which scale and rotation transform.
+
+ Nine transform origins are available, as shown in the image below.
+
+ \image declarative-transformorigin.png
+
+ This example rotates an image around its bottom-right corner.
+ \qml
+ Image {
+ source: "myimage.png"
+ transformOrigin: Item.BottomRight
+ rotation: 45
+ }
+ \endqml
+
+ The default transform origin is \c Item.Center.
+
+ To set an arbitrary transform origin point use the \l Scale or \l Rotation
+ transform elements.
+*/
+
+/*!
+ \qmlproperty Item QtQuick2::Item::parent
+ This property holds the parent of the item.
+*/
+
+/*!
+ \property QSGItem::parent
+ This property holds the parent of the item.
+*/
void QSGItem::setParentItem(QSGItem *parentItem)
{
Q_D(QSGItem);
@@ -952,10 +1829,10 @@ void QSGItem::setParentItem(QSGItem *parentItem)
scopeItem = oldParentItem;
while (!scopeItem->isFocusScope()) scopeItem = scopeItem->parentItem();
scopeFocusedItem = d->subFocusItem;
- }
+ }
- if (scopeFocusedItem)
- QSGCanvasPrivate::get(d->canvas)->clearFocusInScope(scopeItem, scopeFocusedItem,
+ if (scopeFocusedItem)
+ QSGCanvasPrivate::get(d->canvas)->clearFocusInScope(scopeItem, scopeFocusedItem,
QSGCanvasPrivate::DontChangeFocusProperty);
op->removeChild(this);
@@ -965,16 +1842,13 @@ void QSGItem::setParentItem(QSGItem *parentItem)
QSGCanvas *parentCanvas = parentItem?QSGItemPrivate::get(parentItem)->canvas:0;
if (d->canvas != parentCanvas) {
- if (d->canvas && d->itemNodeInstance)
- QSGCanvasPrivate::get(d->canvas)->cleanup(d->itemNodeInstance);
-
QSGItemPrivate::InitializationState initState;
initState.clear();
d->initCanvas(&initState, parentCanvas);
}
d->dirty(QSGItemPrivate::ParentChanged);
-
+
if (d->parentItem)
QSGItemPrivate::get(d->parentItem)->addChild(this);
@@ -991,7 +1865,7 @@ void QSGItem::setParentItem(QSGItem *parentItem)
QSGItemPrivate::get(scopeFocusedItem)->focus = false;
emit scopeFocusedItem->focusChanged(false);
} else {
- QSGCanvasPrivate::get(d->canvas)->setFocusInScope(scopeItem, scopeFocusedItem,
+ QSGCanvasPrivate::get(d->canvas)->setFocusInScope(scopeItem, scopeFocusedItem,
QSGCanvasPrivate::DontChangeFocusProperty);
}
}
@@ -1015,7 +1889,7 @@ void QSGItem::stackBefore(const QSGItem *sibling)
int myIndex = parentPrivate->childItems.indexOf(this);
int siblingIndex = parentPrivate->childItems.indexOf(const_cast<QSGItem *>(sibling));
-
+
Q_ASSERT(myIndex != -1 && siblingIndex != -1);
if (myIndex == siblingIndex - 1)
@@ -1029,7 +1903,7 @@ void QSGItem::stackBefore(const QSGItem *sibling)
parentPrivate->dirty(QSGItemPrivate::ChildrenStackingChanged);
- for (int ii = qMin(siblingIndex, myIndex); ii < parentPrivate->childItems.count(); ++ii)
+ for (int ii = qMin(siblingIndex, myIndex); ii < parentPrivate->childItems.count(); ++ii)
QSGItemPrivate::get(parentPrivate->childItems.at(ii))->siblingOrderChanged();
}
@@ -1045,7 +1919,7 @@ void QSGItem::stackAfter(const QSGItem *sibling)
int myIndex = parentPrivate->childItems.indexOf(this);
int siblingIndex = parentPrivate->childItems.indexOf(const_cast<QSGItem *>(sibling));
-
+
Q_ASSERT(myIndex != -1 && siblingIndex != -1);
if (myIndex == siblingIndex + 1)
@@ -1059,7 +1933,7 @@ void QSGItem::stackAfter(const QSGItem *sibling)
parentPrivate->dirty(QSGItemPrivate::ChildrenStackingChanged);
- for (int ii = qMin(myIndex, siblingIndex + 1); ii < parentPrivate->childItems.count(); ++ii)
+ for (int ii = qMin(myIndex, siblingIndex + 1); ii < parentPrivate->childItems.count(); ++ii)
QSGItemPrivate::get(parentPrivate->childItems.at(ii))->siblingOrderChanged();
}
@@ -1077,8 +1951,8 @@ QSGEngine *QSGItem::sceneGraphEngine() const
return canvas()->sceneGraphEngine();
}
-QSGCanvas *QSGItem::canvas() const
-{
+QSGCanvas *QSGItem::canvas() const
+{
Q_D(const QSGItem);
return d->canvas;
}
@@ -1128,13 +2002,13 @@ void QSGItemPrivate::removeChild(QSGItem *child)
emit q->childrenChanged();
}
-void QSGItemPrivate::InitializationState::clear()
-{
- focusScope = 0;
+void QSGItemPrivate::InitializationState::clear()
+{
+ focusScope = 0;
}
-void QSGItemPrivate::InitializationState::clear(QSGItem *fs)
-{
+void QSGItemPrivate::InitializationState::clear(QSGItem *fs)
+{
focusScope = fs;
}
@@ -1160,14 +2034,17 @@ void QSGItemPrivate::initCanvas(InitializationState *state, QSGCanvas *c)
c->itemsToPolish.remove(q);
if (c->mouseGrabberItem == q)
c->mouseGrabberItem = 0;
+ if ( hoverEnabled )
+ c->hoverItems.removeAll(q);
+ if (itemNodeInstance)
+ c->cleanup(itemNodeInstance);
}
canvas = c;
- if (canvas && polishScheduled)
+ if (canvas && polishScheduled)
QSGCanvasPrivate::get(canvas)->itemsToPolish.insert(q);
- // XXX todo - why aren't these added to the destroy list?
itemNodeInstance = 0;
opacityNode = 0;
clipNode = 0;
@@ -1248,6 +2125,55 @@ void QSGItemPrivate::itemToParentTransform(QTransform &t) const
}
}
+
+/*!
+ \qmlproperty real QtQuick2::Item::childrenRect.x
+ \qmlproperty real QtQuick2::Item::childrenRect.y
+ \qmlproperty real QtQuick2::Item::childrenRect.width
+ \qmlproperty real QtQuick2::Item::childrenRect.height
+
+ The childrenRect properties allow an item access to the geometry of its
+ children. This property is useful if you have an item that needs to be
+ sized to fit its children.
+*/
+
+
+/*!
+ \qmlproperty list<Item> QtQuick2::Item::children
+ \qmlproperty list<Object> QtQuick2::Item::resources
+
+ The children property contains the list of visual children of this item.
+ The resources property contains non-visual resources that you want to
+ reference by name.
+
+ Generally you can rely on Item's default property to handle all this for
+ you, but it can come in handy in some cases.
+
+ \qml
+ Item {
+ children: [
+ Text {},
+ Rectangle {}
+ ]
+ resources: [
+ Component {
+ id: myComponent
+ Text {}
+ }
+ ]
+ }
+ \endqml
+*/
+
+/*!
+ Returns true if construction of the QML component is complete; otherwise
+ returns false.
+
+ It is often desirable to delay some processing until the component is
+ completed.
+
+ \sa componentComplete()
+*/
bool QSGItem::isComponentComplete() const
{
Q_D(const QSGItem);
@@ -1255,11 +2181,11 @@ bool QSGItem::isComponentComplete() const
}
QSGItemPrivate::QSGItemPrivate()
-: _anchors(0), _contents(0), baselineOffset(0), _anchorLines(0), _stateGroup(0), origin(QSGItem::Center),
-
- flags(0), widthValid(false), heightValid(false), componentComplete(true),
+: _anchors(0), _contents(0), baselineOffset(0), _anchorLines(0), _stateGroup(0), origin(QSGItem::Center),
+
+ flags(0), widthValid(false), heightValid(false), componentComplete(true),
keepMouse(false), hoverEnabled(false), smooth(false), focus(false), activeFocus(false), notifiedFocus(false),
- notifiedActiveFocus(false), filtersChildMouseEvents(false), explicitVisible(true),
+ notifiedActiveFocus(false), filtersChildMouseEvents(false), explicitVisible(true),
effectiveVisible(true), explicitEnable(true), effectiveEnable(true), polishScheduled(false),
inheritedLayoutMirror(false), effectiveLayoutMirror(false), isMirrorImplicit(true),
inheritMirrorFromParent(false), inheritMirrorFromItem(false), childrenDoNotOverlap(false),
@@ -1268,12 +2194,12 @@ QSGItemPrivate::QSGItemPrivate()
subFocusItem(0),
- x(0), y(0), width(0), height(0), implicitWidth(0), implicitHeight(0),
+ x(0), y(0), width(0), height(0), implicitWidth(0), implicitHeight(0),
z(0), scale(1), rotation(0), opacity(1),
attachedLayoutDirection(0), acceptedMouseButtons(0),
imHints(Qt::ImhNone),
-
+
keyHandler(0),
dirtyAttributes(0), nextDirtyItem(0), prevDirtyItem(0),
@@ -1285,6 +2211,15 @@ QSGItemPrivate::QSGItemPrivate()
void QSGItemPrivate::init(QSGItem *parent)
{
+#ifndef QT_NO_DEBUG
+ ++qt_item_count;
+ static bool atexit_registered = false;
+ if (!atexit_registered) {
+ atexit(qt_print_item_count);
+ atexit_registered = true;
+ }
+#endif
+
Q_Q(QSGItem);
baselineOffset.invalidate();
@@ -1305,7 +2240,7 @@ void QSGItemPrivate::data_append(QDeclarativeListProperty<QObject> *prop, QObjec
// This test is measurably (albeit only slightly) faster than qobject_cast<>()
const QMetaObject *mo = o->metaObject();
while (mo && mo != &QSGItem::staticMetaObject) {
- if (mo == &QGraphicsObject::staticMetaObject)
+ if (mo == &QGraphicsObject::staticMetaObject)
qWarning("Cannot add a QtQuick 1.0 item (%s) into a QtQuick 2.0 scene!", o->metaObject()->className());
mo = mo->d.superdata;
}
@@ -1319,6 +2254,40 @@ void QSGItemPrivate::data_append(QDeclarativeListProperty<QObject> *prop, QObjec
}
}
+/*!
+ \qmlproperty list<Object> QtQuick2::Item::data
+ \default
+
+ The data property allows you to freely mix visual children and resources
+ in an item. If you assign a visual item to the data list it becomes
+ a child and if you assign any other object type, it is added as a resource.
+
+ So you can write:
+ \qml
+ Item {
+ Text {}
+ Rectangle {}
+ Timer {}
+ }
+ \endqml
+
+ instead of:
+ \qml
+ Item {
+ children: [
+ Text {},
+ Rectangle {}
+ ]
+ resources: [
+ Timer {}
+ ]
+ }
+ \endqml
+
+ data is a behind-the-scenes property: you should never need to explicitly
+ specify it.
+ */
+
int QSGItemPrivate::data_count(QDeclarativeListProperty<QObject> *prop)
{
Q_UNUSED(prop);
@@ -1483,6 +2452,227 @@ void QSGItemPrivate::transform_clear(QDeclarativeListProperty<QSGTransform> *pro
p->dirty(QSGItemPrivate::Transform);
}
+/*!
+ \property QSGItem::childrenRect
+ \brief The geometry of an item's children.
+
+ This property holds the (collective) position and size of the item's children.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Item::x
+ \qmlproperty real QtQuick2::Item::y
+ \qmlproperty real QtQuick2::Item::width
+ \qmlproperty real QtQuick2::Item::height
+
+ Defines the item's position and size relative to its parent.
+
+ \qml
+ Item { x: 100; y: 100; width: 100; height: 100 }
+ \endqml
+ */
+
+/*!
+ \qmlproperty real QtQuick2::Item::z
+
+ Sets the stacking order of sibling items. By default the stacking order is 0.
+
+ Items with a higher stacking value are drawn on top of siblings with a
+ lower stacking order. Items with the same stacking value are drawn
+ bottom up in the order they appear. Items with a negative stacking
+ value are drawn under their parent's content.
+
+ The following example shows the various effects of stacking order.
+
+ \table
+ \row
+ \o \image declarative-item_stacking1.png
+ \o Same \c z - later children above earlier children:
+ \qml
+ Item {
+ Rectangle {
+ color: "red"
+ width: 100; height: 100
+ }
+ Rectangle {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-item_stacking2.png
+ \o Higher \c z on top:
+ \qml
+ Item {
+ Rectangle {
+ z: 1
+ color: "red"
+ width: 100; height: 100
+ }
+ Rectangle {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-item_stacking3.png
+ \o Same \c z - children above parents:
+ \qml
+ Item {
+ Rectangle {
+ color: "red"
+ width: 100; height: 100
+ Rectangle {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-item_stacking4.png
+ \o Lower \c z below:
+ \qml
+ Item {
+ Rectangle {
+ color: "red"
+ width: 100; height: 100
+ Rectangle {
+ z: -1
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ }
+ \endqml
+ \endtable
+ */
+
+/*!
+ \qmlproperty bool QtQuick2::Item::visible
+
+ This property holds whether the item is visible. By default this is true.
+
+ Setting this property directly affects the \c visible value of child
+ items. When set to \c false, the \c visible values of all child items also
+ become \c false. When set to \c true, the \c visible values of child items
+ are returned to \c true, unless they have explicitly been set to \c false.
+
+ (Because of this flow-on behavior, using the \c visible property may not
+ have the intended effect if a property binding should only respond to
+ explicit property changes. In such cases it may be better to use the
+ \l opacity property instead.)
+
+ Setting this property to \c false automatically causes \l focus to be set
+ to \c false, and this item will longer receive mouse and keyboard events.
+ (In contrast, setting the \l opacity to 0 does not affect the \l focus
+ property and the receiving of key events.)
+
+ \note This property's value is only affected by changes to this property or
+ the parent's \c visible property. It does not change, for example, if this
+ item moves off-screen, or if the \l opacity changes to 0.
+*/
+
+
+/*!
+ \qmlproperty AnchorLine QtQuick2::Item::anchors.top
+ \qmlproperty AnchorLine QtQuick2::Item::anchors.bottom
+ \qmlproperty AnchorLine QtQuick2::Item::anchors.left
+ \qmlproperty AnchorLine QtQuick2::Item::anchors.right
+ \qmlproperty AnchorLine QtQuick2::Item::anchors.horizontalCenter
+ \qmlproperty AnchorLine QtQuick2::Item::anchors.verticalCenter
+ \qmlproperty AnchorLine QtQuick2::Item::anchors.baseline
+
+ \qmlproperty Item QtQuick2::Item::anchors.fill
+ \qmlproperty Item QtQuick2::Item::anchors.centerIn
+
+ \qmlproperty real QtQuick2::Item::anchors.margins
+ \qmlproperty real QtQuick2::Item::anchors.topMargin
+ \qmlproperty real QtQuick2::Item::anchors.bottomMargin
+ \qmlproperty real QtQuick2::Item::anchors.leftMargin
+ \qmlproperty real QtQuick2::Item::anchors.rightMargin
+ \qmlproperty real QtQuick2::Item::anchors.horizontalCenterOffset
+ \qmlproperty real QtQuick2::Item::anchors.verticalCenterOffset
+ \qmlproperty real QtQuick2::Item::anchors.baselineOffset
+
+ \qmlproperty bool QtQuick2::Item::anchors.mirrored
+
+ Anchors provide a way to position an item by specifying its
+ relationship with other items.
+
+ Margins apply to top, bottom, left, right, and fill anchors.
+ The \c anchors.margins property can be used to set all of the various margins at once, to the same value.
+ Note that margins are anchor-specific and are not applied if an item does not
+ use anchors.
+
+ Offsets apply for horizontal center, vertical center, and baseline anchors.
+
+ \table
+ \row
+ \o \image declarative-anchors_example.png
+ \o Text anchored to Image, horizontally centered and vertically below, with a margin.
+ \qml
+ Item {
+ Image {
+ id: pic
+ // ...
+ }
+ Text {
+ id: label
+ anchors.horizontalCenter: pic.horizontalCenter
+ anchors.top: pic.bottom
+ anchors.topMargin: 5
+ // ...
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-anchors_example2.png
+ \o
+ Left of Text anchored to right of Image, with a margin. The y
+ property of both defaults to 0.
+
+ \qml
+ Item {
+ Image {
+ id: pic
+ // ...
+ }
+ Text {
+ id: label
+ anchors.left: pic.right
+ anchors.leftMargin: 5
+ // ...
+ }
+ }
+ \endqml
+ \endtable
+
+ \c anchors.fill provides a convenient way for one item to have the
+ same geometry as another item, and is equivalent to connecting all
+ four directional anchors.
+
+ To clear an anchor value, set it to \c undefined.
+
+ \c anchors.mirrored returns true it the layout has been \l {LayoutMirroring}{mirrored}.
+
+ \note You can only anchor an item to siblings or a parent.
+
+ For more information see \l {anchor-layout}{Anchor Layouts}.
+*/
+
+/*!
+ \property QSGItem::baselineOffset
+ \brief The position of the item's baseline in local coordinates.
+
+ The baseline of a \l Text item is the imaginary line on which the text
+ sits. Controls containing text usually set their baseline to the
+ baseline of their text.
+
+ For non-text items, a default baseline offset of 0 is used.
+*/
QSGAnchors *QSGItemPrivate::anchors() const
{
if (!_anchors) {
@@ -1494,7 +2684,7 @@ QSGAnchors *QSGItemPrivate::anchors() const
return _anchors;
}
-QSGItemPrivate::AnchorLines *QSGItemPrivate::anchorLines() const
+QSGItemPrivate::AnchorLines *QSGItemPrivate::anchorLines() const
{
Q_Q(const QSGItem);
if (!_anchorLines) _anchorLines =
@@ -1553,6 +2743,12 @@ void QSGItem::setClip(bool c)
emit clipChanged(c);
}
+
+/*!
+ This function is called to handle this item's changes in
+ geometry from \a oldGeometry to \a newGeometry. If the two
+ geometries are the same, it doesn't do anything.
+ */
void QSGItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
Q_D(QSGItem);
@@ -1708,6 +2904,13 @@ bool QSGItem::childMouseEventFilter(QSGItem *, QEvent *)
return false;
}
+void QSGItem::windowDeactivateEvent()
+{
+ foreach (QSGItem* item, childItems()) {
+ item->windowDeactivateEvent();
+ }
+}
+
Qt::InputMethodHints QSGItem::inputMethodHints() const
{
Q_D(const QSGItem);
@@ -1866,7 +3069,7 @@ QTransform QSGItem::itemTransform(QSGItem *other, bool *ok) const
{
Q_D(const QSGItem);
- // XXX todo - we need to be able to handle common parents better and detect
+ // XXX todo - we need to be able to handle common parents better and detect
// invalid cases
if (ok) *ok = true;
@@ -1912,7 +3115,7 @@ void QSGItem::forceActiveFocus()
while (parent) {
if (parent->flags() & QSGItem::ItemIsFocusScope) {
parent->setFocus(true);
- }
+ }
parent = parent->parentItem();
}
}
@@ -1942,11 +3145,11 @@ QDeclarativeListProperty<QObject> QSGItemPrivate::resources()
QDeclarativeListProperty<QSGItem> QSGItemPrivate::children()
{
- return QDeclarativeListProperty<QSGItem>(q_func(), 0, QSGItemPrivate::children_append,
+ return QDeclarativeListProperty<QSGItem>(q_func(), 0, QSGItemPrivate::children_append,
QSGItemPrivate::children_count,
QSGItemPrivate::children_at,
QSGItemPrivate::children_clear);
-
+
}
QDeclarativeListProperty<QDeclarativeState> QSGItemPrivate::states()
@@ -2069,7 +3272,7 @@ void QSGItemPrivate::transformChanged()
void QSGItemPrivate::deliverKeyEvent(QKeyEvent *e)
{
Q_Q(QSGItem);
-
+
Q_ASSERT(e->isAccepted());
if (keyHandler) {
if (e->type() == QEvent::KeyPress)
@@ -2237,7 +3440,7 @@ QSGItem::TransformOrigin QSGItem::transformOrigin() const
void QSGItem::setTransformOrigin(TransformOrigin origin)
{
Q_D(QSGItem);
- if (origin == d->origin)
+ if (origin == d->origin)
return;
d->origin = origin;
@@ -2267,19 +3470,146 @@ void QSGItem::setZ(qreal v)
d->z = v;
d->dirty(QSGItemPrivate::ZValue);
- if (d->parentItem)
+ if (d->parentItem)
QSGItemPrivate::get(d->parentItem)->dirty(QSGItemPrivate::ChildrenStackingChanged);
emit zChanged();
}
-qreal QSGItem::rotation() const
-{
+
+/*!
+ \qmlproperty real QtQuick2::Item::rotation
+ This property holds the rotation of the item in degrees clockwise.
+
+ This specifies how many degrees to rotate the item around its transformOrigin.
+ The default rotation is 0 degrees (i.e. not rotated at all).
+
+ \table
+ \row
+ \o \image declarative-rotation.png
+ \o
+ \qml
+ Rectangle {
+ color: "blue"
+ width: 100; height: 100
+ Rectangle {
+ color: "red"
+ x: 25; y: 25; width: 50; height: 50
+ rotation: 30
+ }
+ }
+ \endqml
+ \endtable
+
+ \sa transform, Rotation
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Item::scale
+ This property holds the scale of the item.
+
+ A scale of less than 1 means the item will be displayed smaller than
+ normal, and a scale of greater than 1 means the item will be
+ displayed larger than normal. A negative scale means the item will
+ be mirrored.
+
+ By default, items are displayed at a scale of 1 (i.e. at their
+ normal size).
+
+ Scaling is from the item's transformOrigin.
+
+ \table
+ \row
+ \o \image declarative-scale.png
+ \o
+ \qml
+ Rectangle {
+ color: "blue"
+ width: 100; height: 100
+ Rectangle {
+ color: "green"
+ width: 25; height: 25
+ }
+ Rectangle {
+ color: "red"
+ x: 25; y: 25; width: 50; height: 50
+ scale: 1.4
+ }
+ }
+ \endqml
+ \endtable
+
+ \sa transform, Scale
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Item::opacity
+
+ This property holds the opacity of the item. Opacity is specified as a
+ number between 0 (fully transparent) and 1 (fully opaque). The default is 1.
+
+ When this property is set, the specified opacity is also applied
+ individually to child items. In almost all cases this is what you want,
+ but in some cases it may produce undesired results. For example in the
+ second set of rectangles below, the red rectangle has specified an opacity
+ of 0.5, which affects the opacity of its blue child rectangle even though
+ the child has not specified an opacity.
+
+ \table
+ \row
+ \o \image declarative-item_opacity1.png
+ \o
+ \qml
+ Item {
+ Rectangle {
+ color: "red"
+ width: 100; height: 100
+ Rectangle {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-item_opacity2.png
+ \o
+ \qml
+ Item {
+ Rectangle {
+ opacity: 0.5
+ color: "red"
+ width: 100; height: 100
+ Rectangle {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ }
+ \endqml
+ \endtable
+
+ If an item's opacity is set to 0, the item will no longer receive mouse
+ events, but will continue to receive key events and will retain the keyboard
+ \l focus if it has been set. (In contrast, setting the \l visible property
+ to \c false stops both mouse and keyboard events, and also removes focus
+ from the item.)
+*/
+
+/*!
+ Returns a value indicating whether mouse input should
+ remain with this item exclusively.
+
+ \sa setKeepMouseGrab()
+ */
+
+qreal QSGItem::rotation() const
+{
Q_D(const QSGItem);
return d->rotation;
}
-void QSGItem::setRotation(qreal r)
+void QSGItem::setRotation(qreal r)
{
Q_D(QSGItem);
if (d->rotation == r)
@@ -2294,13 +3624,13 @@ void QSGItem::setRotation(qreal r)
emit rotationChanged();
}
-qreal QSGItem::scale() const
-{
+qreal QSGItem::scale() const
+{
Q_D(const QSGItem);
return d->scale;
}
-void QSGItem::setScale(qreal s)
+void QSGItem::setScale(qreal s)
{
Q_D(QSGItem);
if (d->scale == s)
@@ -2326,7 +3656,7 @@ void QSGItem::setOpacity(qreal o)
return;
d->opacity = o;
-
+
d->dirty(QSGItemPrivate::OpacityValue);
d->itemChange(ItemOpacityHasChanged, o);
@@ -2400,7 +3730,7 @@ void QSGItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible)
q->ungrabMouse();
}
- for (int ii = 0; ii < childItems.count(); ++ii)
+ for (int ii = 0; ii < childItems.count(); ++ii)
QSGItemPrivate::get(childItems.at(ii))->setEffectiveVisibleRecur(newEffectiveVisible);
for(int ii = 0; ii < changeListeners.count(); ++ii) {
@@ -2444,7 +3774,7 @@ void QSGItemPrivate::setEffectiveEnableRecur(bool newEffectiveEnable)
q->ungrabMouse();
}
- for (int ii = 0; ii < childItems.count(); ++ii)
+ for (int ii = 0; ii < childItems.count(); ++ii)
QSGItemPrivate::get(childItems.at(ii))->setEffectiveEnableRecur(newEffectiveEnable);
emit q->enabledChanged();
@@ -2625,12 +3955,37 @@ void QSGItemPrivate::itemChange(QSGItem::ItemChange change, const QSGItem::ItemC
}
}
+/*!
+ \property QSGItem::smooth
+ \brief whether the item is smoothly transformed.
+
+ This property is provided purely for the purpose of optimization. Turning
+ smooth transforms off is faster, but looks worse; turning smooth
+ transformations on is slower, but looks better.
+
+ By default smooth transformations are off.
+*/
+
+/*!
+ Returns true if the item should be drawn with antialiasing and
+ smooth pixmap filtering, false otherwise.
+
+ The default is false.
+
+ \sa setSmooth()
+*/
bool QSGItem::smooth() const
{
Q_D(const QSGItem);
return d->smooth;
}
+/*!
+ Sets whether the item should be drawn with antialiasing and
+ smooth pixmap filtering to \a smooth.
+
+ \sa smooth()
+*/
void QSGItem::setSmooth(bool smooth)
{
Q_D(QSGItem);
@@ -2643,14 +3998,14 @@ void QSGItem::setSmooth(bool smooth)
emit smoothChanged(smooth);
}
-QSGItem::Flags QSGItem::flags() const
-{
+QSGItem::Flags QSGItem::flags() const
+{
Q_D(const QSGItem);
return (QSGItem::Flags)d->flags;
}
void QSGItem::setFlag(Flag flag, bool enabled)
-{
+{
Q_D(QSGItem);
if (enabled)
setFlags((Flags)(d->flags | (quint32)flag));
@@ -2658,8 +4013,8 @@ void QSGItem::setFlag(Flag flag, bool enabled)
setFlags((Flags)(d->flags & ~(quint32)flag));
}
-void QSGItem::setFlags(Flags flags)
-{
+void QSGItem::setFlags(Flags flags)
+{
Q_D(QSGItem);
if ((flags & ItemIsFocusScope) != (d->flags & ItemIsFocusScope)) {
@@ -2669,10 +4024,10 @@ void QSGItem::setFlags(Flags flags)
} else if (d->flags & ItemIsFocusScope) {
qWarning("QSGItem: Cannot unset FocusScope flag.");
flags |= ItemIsFocusScope;
- }
+ }
}
- if ((flags & ItemClipsChildrenToShape ) != (d->flags & ItemClipsChildrenToShape))
+ if ((flags & ItemClipsChildrenToShape ) != (d->flags & ItemClipsChildrenToShape))
d->dirty(QSGItemPrivate::Clip);
d->flags = flags;
@@ -2786,13 +4141,54 @@ qreal QSGItemPrivate::getImplicitWidth() const
{
return implicitWidth;
}
-
+/*!
+ Returns the width of the item that is implied by other properties that determine the content.
+*/
qreal QSGItem::implicitWidth() const
{
Q_D(const QSGItem);
return d->getImplicitWidth();
}
+/*!
+ \qmlproperty real QtQuick2::Item::implicitWidth
+ \qmlproperty real QtQuick2::Item::implicitHeight
+
+ Defines the natural width or height of the Item if no \l width or \l height is specified.
+
+ The default implicit size for most items is 0x0, however some elements have an inherent
+ implicit size which cannot be overridden, e.g. Image, Text.
+
+ Setting the implicit size is useful for defining components that have a preferred size
+ based on their content, for example:
+
+ \qml
+ // Label.qml
+ import QtQuick 1.1
+
+ Item {
+ property alias icon: image.source
+ property alias label: text.text
+ implicitWidth: text.implicitWidth + image.implicitWidth
+ implicitHeight: Math.max(text.implicitHeight, image.implicitHeight)
+ Image { id: image }
+ Text {
+ id: text
+ wrapMode: Text.Wrap
+ anchors.left: image.right; anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ }
+ \endqml
+
+ \bold Note: using implicitWidth of Text or TextEdit and setting the width explicitly
+ incurs a performance penalty as the text must be laid out twice.
+*/
+
+/*!
+ Sets the implied width of the item to \a w.
+ This is the width implied by other properties that determine the content.
+*/
void QSGItem::setImplicitWidth(qreal w)
{
Q_D(QSGItem);
@@ -2802,11 +4198,11 @@ void QSGItem::setImplicitWidth(qreal w)
if (changed)
d->implicitWidthChanged();
return;
- }
+ }
qreal oldWidth = d->width;
d->width = w;
-
+
d->dirty(QSGItemPrivate::Size);
geometryChanged(QRectF(x(), y(), width(), height()),
@@ -2816,6 +4212,9 @@ void QSGItem::setImplicitWidth(qreal w)
d->implicitWidthChanged();
}
+/*!
+ Returns whether the width property has been set explicitly.
+*/
bool QSGItem::widthValid() const
{
Q_D(const QSGItem);
@@ -2865,12 +4264,20 @@ qreal QSGItemPrivate::getImplicitHeight() const
return implicitHeight;
}
+/*!
+ Returns the height of the item that is implied by other properties that determine the content.
+*/
qreal QSGItem::implicitHeight() const
{
Q_D(const QSGItem);
return d->getImplicitHeight();
}
+
+/*!
+ Sets the implied height of the item to \a h.
+ This is the height implied by other properties that determine the content.
+*/
void QSGItem::setImplicitHeight(qreal h)
{
Q_D(QSGItem);
@@ -2894,6 +4301,9 @@ void QSGItem::setImplicitHeight(qreal h)
d->implicitHeightChanged();
}
+/*!
+ Returns whether the height property has been set explicitly.
+*/
bool QSGItem::heightValid() const
{
Q_D(const QSGItem);
@@ -2963,19 +4373,19 @@ QSGItem *QSGItem::scopedFocusItem() const
Q_D(const QSGItem);
if (!isFocusScope())
return 0;
- else
+ else
return d->subFocusItem;
}
-Qt::MouseButtons QSGItem::acceptedMouseButtons() const
-{
+Qt::MouseButtons QSGItem::acceptedMouseButtons() const
+{
Q_D(const QSGItem);
return d->acceptedMouseButtons;
}
-void QSGItem::setAcceptedMouseButtons(Qt::MouseButtons buttons)
-{
+void QSGItem::setAcceptedMouseButtons(Qt::MouseButtons buttons)
+{
Q_D(QSGItem);
d->acceptedMouseButtons = buttons;
}
@@ -2986,13 +4396,13 @@ bool QSGItem::filtersChildMouseEvents() const
return d->filtersChildMouseEvents;
}
-void QSGItem::setFiltersChildMouseEvents(bool filter)
-{
+void QSGItem::setFiltersChildMouseEvents(bool filter)
+{
Q_D(QSGItem);
d->filtersChildMouseEvents = filter;
}
-bool QSGItem::isUnderMouse() const
+bool QSGItem::isUnderMouse() const
{
Q_D(const QSGItem);
if (!d->canvas)
@@ -3001,17 +4411,17 @@ bool QSGItem::isUnderMouse() const
QPoint cursorPos = QCursor::pos();
if (QRectF(0, 0, width(), height()).contains(mapFromScene(cursorPos))) // ### refactor: d->canvas->mapFromGlobal(cursorPos))))
return true;
- return false;
+ return false;
}
-bool QSGItem::acceptHoverEvents() const
-{
+bool QSGItem::acceptHoverEvents() const
+{
Q_D(const QSGItem);
return d->hoverEnabled;
}
-void QSGItem::setAcceptHoverEvents(bool enabled)
-{
+void QSGItem::setAcceptHoverEvents(bool enabled)
+{
Q_D(QSGItem);
d->hoverEnabled = enabled;
}
@@ -3031,7 +4441,7 @@ void QSGItem::grabMouse()
oldGrabber->mouseUngrabEvent();
}
-void QSGItem::ungrabMouse()
+void QSGItem::ungrabMouse()
{
Q_D(QSGItem);
if (!d->canvas)
@@ -3052,22 +4462,60 @@ bool QSGItem::keepMouseGrab() const
return d->keepMouse;
}
+/*!
+ The flag indicating whether the mouse should remain
+ with this item is set to \a keep.
+
+ This is useful for items that wish to grab and keep mouse
+ interaction following a predefined gesture. For example,
+ an item that is interested in horizontal mouse movement
+ may set keepMouseGrab to true once a threshold has been
+ exceeded. Once keepMouseGrab has been set to true, filtering
+ items will not react to mouse events.
+
+ If the item does not indicate that it wishes to retain mouse grab,
+ a filtering item may steal the grab. For example, Flickable may attempt
+ to steal a mouse grab if it detects that the user has begun to
+ move the viewport.
+
+ \sa keepMouseGrab()
+ */
void QSGItem::setKeepMouseGrab(bool keep)
{
Q_D(QSGItem);
d->keepMouse = keep;
}
-QPointF QSGItem::mapToItem(const QSGItem *item, const QPointF &point) const
-{
+/*!
+ \qmlmethod object QtQuick2::Item::mapFromItem(Item item, real x, real y)
+
+ Maps the point (\a x, \a y), which is in \a item's coordinate system, to
+ this item's coordinate system, and returns an object with \c x and \c y
+ properties matching the mapped cooordinate.
+
+ If \a item is a \c null value, this maps the point from the coordinate
+ system of the root QML view.
+*/
+/*!
+ \qmlmethod object QtQuick2::Item::mapToItem(Item item, real x, real y)
+
+ Maps the point (\a x, \a y), which is in this item's coordinate system, to
+ \a item's coordinate system, and returns an object with \c x and \c y
+ properties matching the mapped cooordinate.
+
+ If \a item is a \c null value, this maps \a x and \a y to the coordinate
+ system of the root QML view.
+*/
+QPointF QSGItem::mapToItem(const QSGItem *item, const QPointF &point) const
+{
QPointF p = mapToScene(point);
if (item)
p = item->mapFromScene(p);
return p;
}
-QPointF QSGItem::mapToScene(const QPointF &point) const
-{
+QPointF QSGItem::mapToScene(const QPointF &point) const
+{
Q_D(const QSGItem);
return d->itemToCanvasTransform().map(point);
}
@@ -3081,26 +4529,26 @@ QRectF QSGItem::mapRectToItem(const QSGItem *item, const QRectF &rect) const
return t.mapRect(rect);
}
-QRectF QSGItem::mapRectToScene(const QRectF &rect) const
-{
+QRectF QSGItem::mapRectToScene(const QRectF &rect) const
+{
Q_D(const QSGItem);
return d->itemToCanvasTransform().mapRect(rect);
}
-QPointF QSGItem::mapFromItem(const QSGItem *item, const QPointF &point) const
-{
+QPointF QSGItem::mapFromItem(const QSGItem *item, const QPointF &point) const
+{
QPointF p = item?item->mapToScene(point):point;
return mapFromScene(p);
}
-QPointF QSGItem::mapFromScene(const QPointF &point) const
-{
+QPointF QSGItem::mapFromScene(const QPointF &point) const
+{
Q_D(const QSGItem);
return d->canvasToItemTransform().map(point);
}
-QRectF QSGItem::mapRectFromItem(const QSGItem *item, const QRectF &rect) const
-{
+QRectF QSGItem::mapRectFromItem(const QSGItem *item, const QRectF &rect) const
+{
Q_D(const QSGItem);
QTransform t = item?QSGItemPrivate::get(item)->itemToCanvasTransform():QTransform();
t *= d->canvasToItemTransform();
@@ -3113,6 +4561,318 @@ QRectF QSGItem::mapRectFromScene(const QRectF &rect) const
return d->canvasToItemTransform().mapRect(rect);
}
+
+/*!
+ \qmlmethod QtQuick2::Item::forceActiveFocus()
+
+ Forces active focus on the item.
+
+ This method sets focus on the item and makes sure that all the focus scopes
+ higher in the object hierarchy are also given the focus.
+*/
+
+/*!
+ Forces active focus on the item.
+
+ This method sets focus on the item and makes sure that all the focus scopes
+ higher in the object hierarchy are also given the focus.
+*/
+
+/*!
+ \qmlmethod QtQuick2::Item::childAt(real x, real y)
+
+ Returns the visible child item at point (\a x, \a y), which is in this
+ item's coordinate system, or \c null if there is no such item.
+*/
+
+/*!
+ Returns the visible child item at point (\a x, \a y), which is in this
+ item's coordinate system, or 0 if there is no such item.
+*/
+
+/*!
+ \qmlproperty list<State> QtQuick2::Item::states
+ This property holds a list of states defined by the item.
+
+ \qml
+ Item {
+ states: [
+ State {
+ // ...
+ },
+ State {
+ // ...
+ }
+ // ...
+ ]
+ }
+ \endqml
+
+ \sa {qmlstate}{States}
+*/
+/*!
+ \qmlproperty list<Transition> QtQuick2::Item::transitions
+ This property holds a list of transitions defined by the item.
+
+ \qml
+ Item {
+ transitions: [
+ Transition {
+ // ...
+ },
+ Transition {
+ // ...
+ }
+ // ...
+ ]
+ }
+ \endqml
+
+ \sa {QML Animation and Transitions}{Transitions}
+*/
+/*
+ \qmlproperty list<Filter> QtQuick2::Item::filter
+ This property holds a list of graphical filters to be applied to the item.
+
+ \l {Filter}{Filters} include things like \l {Blur}{blurring}
+ the item, or giving it a \l Reflection. Some
+ filters may not be available on all canvases; if a filter is not
+ available on a certain canvas, it will simply not be applied for
+ that canvas (but the QML will still be considered valid).
+
+ \qml
+ Item {
+ filter: [
+ Blur {
+ // ...
+ },
+ Reflection {
+ // ...
+ }
+ // ...
+ ]
+ }
+ \endqml
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::Item::clip
+ This property holds whether clipping is enabled. The default clip value is \c false.
+
+ If clipping is enabled, an item will clip its own painting, as well
+ as the painting of its children, to its bounding rectangle.
+
+ Non-rectangular clipping regions are not supported for performance reasons.
+*/
+
+/*!
+ \property QSGItem::clip
+ This property holds whether clipping is enabled. The default clip value is \c false.
+
+ If clipping is enabled, an item will clip its own painting, as well
+ as the painting of its children, to its bounding rectangle. If you set
+ clipping during an item's paint operation, remember to re-set it to
+ prevent clipping the rest of your scene.
+
+ Non-rectangular clipping regions are not supported for performance reasons.
+*/
+
+/*!
+ \qmlproperty string QtQuick2::Item::state
+
+ This property holds the name of the current state of the item.
+
+ This property is often used in scripts to change between states. For
+ example:
+
+ \js
+ function toggle() {
+ if (button.state == 'On')
+ button.state = 'Off';
+ else
+ button.state = 'On';
+ }
+ \endjs
+
+ If the item is in its base state (i.e. no explicit state has been
+ set), \c state will be a blank string. Likewise, you can return an
+ item to its base state by setting its current state to \c ''.
+
+ \sa {qmlstates}{States}
+*/
+
+/*!
+ \qmlproperty list<Transform> QtQuick2::Item::transform
+ This property holds the list of transformations to apply.
+
+ For more information see \l Transform.
+*/
+
+/*!
+ \enum QSGItem::TransformOrigin
+
+ Controls the point about which simple transforms like scale apply.
+
+ \value TopLeft The top-left corner of the item.
+ \value Top The center point of the top of the item.
+ \value TopRight The top-right corner of the item.
+ \value Left The left most point of the vertical middle.
+ \value Center The center of the item.
+ \value Right The right most point of the vertical middle.
+ \value BottomLeft The bottom-left corner of the item.
+ \value Bottom The center point of the bottom of the item.
+ \value BottomRight The bottom-right corner of the item.
+*/
+
+
+/*!
+ \qmlproperty bool QtQuick2::Item::activeFocus
+
+ This property indicates whether the item has active focus.
+
+ An item with active focus will receive keyboard input,
+ or is a FocusScope ancestor of the item that will receive keyboard input.
+
+ Usually, activeFocus is gained by setting focus on an item and its enclosing
+ FocusScopes. In the following example \c input will have activeFocus.
+ \qml
+ Rectangle {
+ FocusScope {
+ focus: true
+ TextInput {
+ id: input
+ focus: true
+ }
+ }
+ }
+ \endqml
+
+ \sa focus, {qmlfocus}{Keyboard Focus}
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::Item::focus
+ This property indicates whether the item has focus within the enclosing focus scope. If true, this item
+ will gain active focus when the enclosing focus scope gains active focus.
+ In the following example, \c input will be given active focus when \c scope gains active focus.
+ \qml
+ Rectangle {
+ FocusScope {
+ id: scope
+ TextInput {
+ id: input
+ focus: true
+ }
+ }
+ }
+ \endqml
+
+ For the purposes of this property, the scene as a whole is assumed to act like a focus scope.
+ On a practical level, that means the following QML will give active focus to \c input on startup.
+
+ \qml
+ Rectangle {
+ TextInput {
+ id: input
+ focus: true
+ }
+ }
+ \endqml
+
+ \sa activeFocus, {qmlfocus}{Keyboard Focus}
+*/
+
+
+/*!
+ \property QSGItem::anchors
+ \internal
+*/
+
+/*!
+ \property QSGItem::left
+ \internal
+*/
+
+/*!
+ \property QSGItem::right
+ \internal
+*/
+
+/*!
+ \property QSGItem::horizontalCenter
+ \internal
+*/
+
+/*!
+ \property QSGItem::top
+ \internal
+*/
+
+/*!
+ \property QSGItem::bottom
+ \internal
+*/
+
+/*!
+ \property QSGItem::verticalCenter
+ \internal
+*/
+
+/*!
+ \property QSGItem::focus
+ \internal
+*/
+
+/*!
+ \property QSGItem::transform
+ \internal
+*/
+
+/*!
+ \property QSGItem::transformOrigin
+ \internal
+*/
+
+/*!
+ \property QSGItem::activeFocus
+ \internal
+*/
+
+/*!
+ \property QSGItem::baseline
+ \internal
+*/
+
+/*!
+ \property QSGItem::data
+ \internal
+*/
+
+/*!
+ \property QSGItem::resources
+ \internal
+*/
+
+/*!
+ \property QSGItem::state
+ \internal
+*/
+
+/*!
+ \property QSGItem::states
+ \internal
+*/
+
+/*!
+ \property QSGItem::transformOriginPoint
+ \internal
+*/
+
+/*!
+ \property QSGItem::transitions
+ \internal
+*/
+
bool QSGItem::event(QEvent *ev)
{
return QObject::event(ev);
diff --git a/src/declarative/items/qsgitem.h b/src/declarative/items/qsgitem.h
index f8e52cf848..02a7a33ed8 100644
--- a/src/declarative/items/qsgitem.h
+++ b/src/declarative/items/qsgitem.h
@@ -375,6 +375,7 @@ protected:
virtual void dragExitEvent(QSGDragEvent *event);
virtual void dragDropEvent(QSGDragEvent *event);
virtual bool childMouseEventFilter(QSGItem *, QEvent *);
+ virtual void windowDeactivateEvent();
virtual void geometryChanged(const QRectF &newGeometry,
const QRectF &oldGeometry);
diff --git a/src/declarative/items/qsgitemsmodule.cpp b/src/declarative/items/qsgitemsmodule.cpp
index 62a4bd06cb..9359906f25 100644
--- a/src/declarative/items/qsgitemsmodule.cpp
+++ b/src/declarative/items/qsgitemsmodule.cpp
@@ -126,6 +126,7 @@ static void qt_sgitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QDeclarativePathPercent>(uri,major,minor,"PathPercent");
qmlRegisterType<QDeclarativePathQuad>(uri,major,minor,"PathQuad");
qmlRegisterType<QSGPathView>(uri,major,minor,"PathView");
+ qmlRegisterUncreatableType<QSGBasePositioner>(uri,major,minor,"Positioner","Positioner is an abstract type that is only available as an attached property.");
#ifndef QT_NO_VALIDATOR
qmlRegisterType<QIntValidator>(uri,major,minor,"IntValidator");
qmlRegisterType<QDoubleValidator>(uri,major,minor,"DoubleValidator");
diff --git a/src/declarative/items/qsgitemview.cpp b/src/declarative/items/qsgitemview.cpp
index bcb4a8a97c..5543f12f6d 100644
--- a/src/declarative/items/qsgitemview.cpp
+++ b/src/declarative/items/qsgitemview.cpp
@@ -7,28 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying ** this package.
-**
** 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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
@@ -723,7 +724,6 @@ void QSGItemView::trackedPositionChanged()
qreal trackedPos = d->trackedItem->position();
qreal trackedSize = d->trackedItem->size();
if (d->trackedItem != d->currentItem) {
- trackedPos -= d->currentItem->sectionSize();
trackedSize += d->currentItem->sectionSize();
}
qreal viewPos;
@@ -756,16 +756,32 @@ void QSGItemView::trackedPositionChanged()
pos = d->startPosition();
}
} else {
- if (trackedPos < viewPos && d->currentItem->position() < viewPos) {
- pos = qMax(trackedPos, d->currentItem->position());
- } else if (d->trackedItem->endPosition() >= viewPos + d->size()
- && d->currentItem->endPosition() >= viewPos + d->size()) {
- if (d->trackedItem->endPosition() <= d->currentItem->endPosition()) {
- pos = d->trackedItem->endPosition() - d->size();
+ qreal trackedEndPos = d->trackedItem->endPosition();
+ qreal toItemPos = d->currentItem->position();
+ qreal toItemEndPos = d->currentItem->endPosition();
+
+ if (d->header && d->showHeaderForIndex(d->currentIndex)) {
+ trackedPos -= d->headerSize();
+ trackedEndPos -= d->headerSize();
+ toItemPos -= d->headerSize();
+ toItemEndPos -= d->headerSize();
+ } else if (d->footer && d->showFooterForIndex(d->currentIndex)) {
+ trackedPos += d->footerSize();
+ trackedEndPos += d->footerSize();
+ toItemPos += d->footerSize();
+ toItemEndPos += d->footerSize();
+ }
+
+ if (trackedPos < viewPos && toItemPos < viewPos) {
+ pos = qMax(trackedPos, toItemPos);
+ } else if (trackedEndPos >= viewPos + d->size()
+ && toItemEndPos >= viewPos + d->size()) {
+ if (trackedEndPos <= toItemEndPos) {
+ pos = trackedEndPos - d->size();
if (trackedSize > d->size())
pos = trackedPos;
} else {
- pos = d->currentItem->endPosition() - d->size();
+ pos = toItemEndPos - d->size();
if (d->currentItem->size() > d->size())
pos = d->currentItem->position();
}
@@ -1082,7 +1098,7 @@ int QSGItemViewPrivate::mapFromModel(int modelIndex) const
for (int i = 0; i < visibleItems.count(); ++i) {
FxViewItem *item = visibleItems.at(i);
if (item->index == modelIndex)
- return i + visibleIndex;
+ return i;
if (item->index > modelIndex)
return -1;
}
diff --git a/src/declarative/items/qsgitemview_p.h b/src/declarative/items/qsgitemview_p.h
index 4c5b91fcde..b784015f66 100644
--- a/src/declarative/items/qsgitemview_p.h
+++ b/src/declarative/items/qsgitemview_p.h
@@ -7,29 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** 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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
diff --git a/src/declarative/items/qsgitemview_p_p.h b/src/declarative/items/qsgitemview_p_p.h
index 3113a8b754..f20f4cca3e 100644
--- a/src/declarative/items/qsgitemview_p_p.h
+++ b/src/declarative/items/qsgitemview_p_p.h
@@ -7,29 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** 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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
@@ -95,10 +95,10 @@ public:
void adjustMoveParameters(int *from, int *to, int *count) const;
virtual void init();
- virtual void updateCurrent(int modelIndex);
virtual void clear();
- virtual void regenerate();
virtual void updateViewport();
+
+ void regenerate();
void layout();
void refill();
void refill(qreal from, qreal to, bool doBuffer = false);
@@ -111,6 +111,7 @@ public:
QSGItem *createHighlightItem();
QSGItem *createComponentItem(QDeclarativeComponent *component, bool receiveItemGeometryChanges, bool createDefault = false);
+ void updateCurrent(int modelIndex);
void updateTrackedItem();
void updateUnrequestedIndexes();
void updateUnrequestedPositions();
@@ -176,6 +177,8 @@ protected:
virtual qreal headerSize() const = 0;
virtual qreal footerSize() const = 0;
+ virtual bool showHeaderForIndex(int index) const = 0;
+ virtual bool showFooterForIndex(int index) const = 0;
virtual void updateHeader() = 0;
virtual void updateFooter() = 0;
@@ -191,14 +194,14 @@ protected:
virtual void visibleItemsChanged() = 0;
virtual FxViewItem *newViewItem(int index, QSGItem *item) = 0;
- virtual void initializeViewItem(FxViewItem *) {}
virtual void repositionPackageItemAt(QSGItem *item, int index) = 0;
virtual void layoutVisibleItems() = 0;
-
- virtual void updateSections() {}
virtual void changedVisibleIndex(int newIndex) = 0;
+
+ virtual void initializeViewItem(FxViewItem *) {}
virtual void initializeCurrentItem() {}
+ virtual void updateSections() {}
virtual void itemGeometryChanged(QSGItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
};
diff --git a/src/declarative/items/qsglistview.cpp b/src/declarative/items/qsglistview.cpp
index 641dd35104..3be4a4bd58 100644
--- a/src/declarative/items/qsglistview.cpp
+++ b/src/declarative/items/qsglistview.cpp
@@ -223,6 +223,8 @@ public:
virtual qreal headerSize() const;
virtual qreal footerSize() const;
+ virtual bool showHeaderForIndex(int index) const;
+ virtual bool showFooterForIndex(int index) const;
virtual void updateHeader();
virtual void updateFooter();
@@ -434,6 +436,7 @@ qreal QSGListViewPrivate::snapPosAt(qreal pos)
FxViewItem *QSGListViewPrivate::snapItemAt(qreal pos)
{
FxViewItem *snapItem = 0;
+ qreal prevItemSize = 0;
for (int i = 0; i < visibleItems.count(); ++i) {
FxViewItem *item = visibleItems.at(i);
if (item->index == -1)
@@ -441,8 +444,9 @@ FxViewItem *QSGListViewPrivate::snapItemAt(qreal pos)
qreal itemTop = item->position();
if (highlight && itemTop >= pos && item->endPosition() <= pos + highlight->size())
return item;
- if (itemTop+item->size()/2 >= pos && itemTop-item->size()/2 < pos)
+ if (itemTop+item->size()/2 >= pos && itemTop-prevItemSize/2 < pos)
snapItem = item;
+ prevItemSize = item->size();
}
return snapItem;
}
@@ -455,6 +459,7 @@ void QSGListViewPrivate::changedVisibleIndex(int newIndex)
void QSGListViewPrivate::init()
{
+ QSGItemViewPrivate::init();
::memset(sectionCache, 0, sizeof(QSGItem*) * sectionCacheSize);
}
@@ -498,6 +503,8 @@ FxViewItem *QSGListViewPrivate::newViewItem(int modelIndex, QSGItem *item)
void QSGListViewPrivate::initializeViewItem(FxViewItem *item)
{
+ QSGItemViewPrivate::initializeViewItem(item);
+
QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item->item);
itemPrivate->addItemChangeListener(this, QSGItemPrivate::Geometry);
@@ -600,6 +607,8 @@ bool QSGListViewPrivate::removeNonVisibleItems(int bufferFrom, int bufferTo)
while (visibleItems.count() > 1 && (item = visibleItems.first()) && item->endPosition() <= bufferFrom) {
if (item->attached->delayRemove())
break;
+ if (item->size() == 0)
+ break;
// qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endPosition();
if (item->index != -1)
visibleIndex++;
@@ -726,7 +735,8 @@ void QSGListViewPrivate::updateHighlight()
{
if ((!currentItem && highlight) || (currentItem && !highlight))
createHighlight();
- if (currentItem && autoHighlight && highlight && !movingHorizontally && !movingVertically) {
+ bool strictHighlight = haveHighlightRange && highlightRange == QSGListView::StrictlyEnforceRange;
+ if (currentItem && autoHighlight && highlight && (!strictHighlight || !pressed)) {
// auto-update highlight
FxListItemSG *listItem = static_cast<FxListItemSG*>(currentItem);
highlightPosAnimator->to = isRightToLeft()
@@ -814,6 +824,8 @@ void QSGListViewPrivate::createSection(FxListItemSG *listItem)
void QSGListViewPrivate::updateSections()
{
+ QSGItemViewPrivate::updateSections();
+
if (sectionCriteria && !visibleItems.isEmpty()) {
QString prevSection;
if (visibleIndex > 0)
@@ -870,6 +882,8 @@ void QSGListViewPrivate::updateCurrentSection()
void QSGListViewPrivate::initializeCurrentItem()
{
+ QSGItemViewPrivate::initializeCurrentItem();
+
if (currentItem) {
FxListItemSG *listItem = static_cast<FxListItemSG *>(currentItem);
@@ -913,6 +927,16 @@ qreal QSGListViewPrivate::footerSize() const
return footer ? footer->size() : 0.0;
}
+bool QSGListViewPrivate::showHeaderForIndex(int index) const
+{
+ return index == 0;
+}
+
+bool QSGListViewPrivate::showFooterForIndex(int index) const
+{
+ return index == model->count()-1;
+}
+
void QSGListViewPrivate::updateFooter()
{
Q_Q(QSGListView);
@@ -1241,6 +1265,68 @@ void QSGListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent,
//----------------------------------------------------------------------------
+/*!
+ \qmlclass ListView QSGListView
+ \inqmlmodule QtQuick 2
+ \ingroup qml-view-elements
+ \inherits Flickable
+ \brief The ListView item provides a list view of items provided by a model.
+
+ A ListView displays data from models created from built-in QML elements like ListModel
+ and XmlListModel, or custom model classes defined in C++ that inherit from
+ QAbstractListModel.
+
+ A ListView has a \l model, which defines the data to be displayed, and
+ a \l delegate, which defines how the data should be displayed. Items in a
+ ListView are laid out horizontally or vertically. List views are inherently
+ flickable because ListView inherits from \l Flickable.
+
+ \section1 Example Usage
+
+ The following example shows the definition of a simple list model defined
+ in a file called \c ContactModel.qml:
+
+ \snippet doc/src/snippets/declarative/listview/ContactModel.qml 0
+
+ Another component can display this model data in a ListView, like this:
+
+ \snippet doc/src/snippets/declarative/listview/listview.qml import
+ \codeline
+ \snippet doc/src/snippets/declarative/listview/listview.qml classdocs simple
+
+ \image listview-simple.png
+
+ Here, the ListView creates a \c ContactModel component for its model, and a \l Text element
+ for its delegate. The view will create a new \l Text component for each item in the model. Notice
+ the delegate is able to access the model's \c name and \c number data directly.
+
+ An improved list view is shown below. The delegate is visually improved and is moved
+ into a separate \c contactDelegate component.
+
+ \snippet doc/src/snippets/declarative/listview/listview.qml classdocs advanced
+ \image listview-highlight.png
+
+ The currently selected item is highlighted with a blue \l Rectangle using the \l highlight property,
+ and \c focus is set to \c true to enable keyboard navigation for the list view.
+ The list view itself is a focus scope (see \l{qmlfocus#Acquiring Focus and Focus Scopes}{the focus documentation page} for more details).
+
+ Delegates are instantiated as needed and may be destroyed at any time.
+ State should \e never be stored in a delegate.
+
+ ListView attaches a number of properties to the root item of the delegate, for example
+ \c {ListView.isCurrentItem}. In the following example, the root delegate item can access
+ this attached property directly as \c ListView.isCurrentItem, while the child
+ \c contactInfo object must refer to this property as \c wrapper.ListView.isCurrentItem.
+
+ \snippet doc/src/snippets/declarative/listview/listview.qml isCurrentItem
+
+ \note Views do not enable \e clip automatically. If the view
+ is not clipped by another item or the screen, it will be necessary
+ to set \e {clip: true} in order to have the out of view items clipped
+ nicely.
+
+ \sa {QML Data Models}, GridView, {declarative/modelviews/listview}{ListView examples}
+*/
QSGListView::QSGListView(QSGItem *parent)
: QSGItemView(*(new QSGListViewPrivate), parent)
{
@@ -1250,6 +1336,203 @@ QSGListView::~QSGListView()
{
}
+/*!
+ \qmlattachedproperty bool QtQuick2::ListView::isCurrentItem
+ This attached property is true if this delegate is the current item; otherwise false.
+
+ It is attached to each instance of the delegate.
+
+ This property may be used to adjust the appearance of the current item, for example:
+
+ \snippet doc/src/snippets/declarative/listview/listview.qml isCurrentItem
+*/
+
+/*!
+ \qmlattachedproperty ListView QtQuick2::ListView::view
+ This attached property holds the view that manages this delegate instance.
+
+ It is attached to each instance of the delegate.
+*/
+
+/*!
+ \qmlattachedproperty string QtQuick2::ListView::previousSection
+ This attached property holds the section of the previous element.
+
+ It is attached to each instance of the delegate.
+
+ The section is evaluated using the \l {ListView::section.property}{section} properties.
+*/
+
+/*!
+ \qmlattachedproperty string QtQuick2::ListView::nextSection
+ This attached property holds the section of the next element.
+
+ It is attached to each instance of the delegate.
+
+ The section is evaluated using the \l {ListView::section.property}{section} properties.
+*/
+
+/*!
+ \qmlattachedproperty string QtQuick2::ListView::section
+ This attached property holds the section of this element.
+
+ It is attached to each instance of the delegate.
+
+ The section is evaluated using the \l {ListView::section.property}{section} properties.
+*/
+
+/*!
+ \qmlattachedproperty bool QtQuick2::ListView::delayRemove
+ This attached property holds whether the delegate may be destroyed.
+
+ It is attached to each instance of the delegate.
+
+ It is sometimes necessary to delay the destruction of an item
+ until an animation completes.
+
+ The example delegate below ensures that the animation completes before
+ the item is removed from the list.
+
+ \snippet doc/src/snippets/declarative/listview/listview.qml delayRemove
+*/
+
+/*!
+ \qmlattachedsignal QtQuick2::ListView::onAdd()
+ This attached handler is called immediately after an item is added to the view.
+*/
+
+/*!
+ \qmlattachedsignal QtQuick2::ListView::onRemove()
+ This attached handler is called immediately before an item is removed from the view.
+*/
+
+/*!
+ \qmlproperty model QtQuick2::ListView::model
+ This property holds the model providing data for the list.
+
+ The model provides the set of data that is used to create the items
+ in the view. Models can be created directly in QML using \l ListModel, \l XmlListModel
+ or \l VisualItemModel, or provided by C++ model classes. If a C++ model class is
+ used, it must be a subclass of \l QAbstractItemModel or a simple list.
+
+ \sa {qmlmodels}{Data Models}
+*/
+
+/*!
+ \qmlproperty Component QtQuick2::ListView::delegate
+
+ The delegate provides a template defining each item instantiated by the view.
+ The index is exposed as an accessible \c index property. Properties of the
+ model are also available depending upon the type of \l {qmlmodels}{Data Model}.
+
+ The number of elements in the delegate has a direct effect on the
+ flicking performance of the view. If at all possible, place functionality
+ that is not needed for the normal display of the delegate in a \l Loader which
+ can load additional elements when needed.
+
+ The ListView will lay out the items based on the size of the root item
+ in the delegate.
+
+ It is recommended that the delagate's size be a whole number to avoid sub-pixel
+ alignment of items.
+
+ \note Delegates are instantiated as needed and may be destroyed at any time.
+ State should \e never be stored in a delegate.
+*/
+/*!
+ \qmlproperty int QtQuick2::ListView::currentIndex
+ \qmlproperty Item QtQuick2::ListView::currentItem
+
+ The \c currentIndex property holds the index of the current item, and
+ \c currentItem holds the current item. Setting the currentIndex to -1
+ will clear the highlight and set currentItem to null.
+
+ If highlightFollowsCurrentItem is \c true, setting either of these
+ properties will smoothly scroll the ListView so that the current
+ item becomes visible.
+
+ Note that the position of the current item
+ may only be approximate until it becomes visible in the view.
+*/
+
+/*!
+ \qmlproperty Item QtQuick2::ListView::highlightItem
+
+ This holds the highlight item created from the \l highlight component.
+
+ The \c highlightItem is managed by the view unless
+ \l highlightFollowsCurrentItem is set to false.
+
+ \sa highlight, highlightFollowsCurrentItem
+*/
+
+/*!
+ \qmlproperty int QtQuick2::ListView::count
+ This property holds the number of items in the view.
+*/
+
+/*!
+ \qmlproperty Component QtQuick2::ListView::highlight
+ This property holds the component to use as the highlight.
+
+ An instance of the highlight component is created for each list.
+ The geometry of the resulting component instance is managed by the list
+ so as to stay with the current item, unless the highlightFollowsCurrentItem
+ property is false.
+
+ \sa highlightItem, highlightFollowsCurrentItem, {declarative/modelviews/listview}{ListView examples}
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::ListView::highlightFollowsCurrentItem
+ This property holds whether the highlight is managed by the view.
+
+ If this property is true (the default value), the highlight is moved smoothly
+ to follow the current item. Otherwise, the
+ highlight is not moved by the view, and any movement must be implemented
+ by the highlight.
+
+ Here is a highlight with its motion defined by a \l {SpringAnimation} item:
+
+ \snippet doc/src/snippets/declarative/listview/listview.qml highlightFollowsCurrentItem
+
+ Note that the highlight animation also affects the way that the view
+ is scrolled. This is because the view moves to maintain the
+ highlight within the preferred highlight range (or visible viewport).
+
+ \sa highlight, highlightMoveSpeed
+*/
+//###Possibly rename these properties, since they are very useful even without a highlight?
+/*!
+ \qmlproperty real QtQuick2::ListView::preferredHighlightBegin
+ \qmlproperty real QtQuick2::ListView::preferredHighlightEnd
+ \qmlproperty enumeration QtQuick2::ListView::highlightRangeMode
+
+ These properties define the preferred range of the highlight (for the current item)
+ within the view. The \c preferredHighlightBegin value must be less than the
+ \c preferredHighlightEnd value.
+
+ These properties affect the position of the current item when the list is scrolled.
+ For example, if the currently selected item should stay in the middle of the
+ list when the view is scrolled, set the \c preferredHighlightBegin and
+ \c preferredHighlightEnd values to the top and bottom coordinates of where the middle
+ item would be. If the \c currentItem is changed programmatically, the list will
+ automatically scroll so that the current item is in the middle of the view.
+ Furthermore, the behavior of the current item index will occur whether or not a
+ highlight exists.
+
+ Valid values for \c highlightRangeMode are:
+
+ \list
+ \o ListView.ApplyRange - the view attempts to maintain the highlight within the range.
+ However, the highlight can move outside of the range at the ends of the list or due
+ to mouse interaction.
+ \o ListView.StrictlyEnforceRange - the highlight never moves outside of the range.
+ The current item changes if a keyboard or mouse action would cause the highlight to move
+ outside of the range.
+ \o ListView.NoHighlightRange - this is the default value.
+ \endlist
+*/
void QSGListView::setHighlightFollowsCurrentItem(bool autoHighlight)
{
Q_D(QSGListView);
@@ -1264,6 +1547,13 @@ void QSGListView::setHighlightFollowsCurrentItem(bool autoHighlight)
}
}
+/*!
+ \qmlproperty real QtQuick2::ListView::spacing
+
+ This property holds the spacing between items.
+
+ The default value is 0.
+*/
qreal QSGListView::spacing() const
{
Q_D(const QSGListView);
@@ -1280,6 +1570,27 @@ void QSGListView::setSpacing(qreal spacing)
}
}
+/*!
+ \qmlproperty enumeration QtQuick2::ListView::orientation
+ This property holds the orientation of the list.
+
+ Possible values:
+
+ \list
+ \o ListView.Horizontal - Items are laid out horizontally
+ \o ListView.Vertical (default) - Items are laid out vertically
+ \endlist
+
+ \table
+ \row
+ \o Horizontal orientation:
+ \image ListViewHorizontal.png
+
+ \row
+ \o Vertical orientation:
+ \image listview-highlight.png
+ \endtable
+*/
QSGListView::Orientation QSGListView::orientation() const
{
Q_D(const QSGListView);
@@ -1305,6 +1616,116 @@ void QSGListView::setOrientation(QSGListView::Orientation orientation)
}
}
+/*!
+ \qmlproperty enumeration QtQuick2::ListView::layoutDirection
+ This property holds the layout direction of the horizontal list.
+
+ Possible values:
+
+ \list
+ \o Qt.LeftToRight (default) - Items will be laid out from left to right.
+ \o Qt.RightToLeft - Items will be laid out from right to let.
+ \endlist
+
+ \sa ListView::effectiveLayoutDirection
+*/
+
+
+/*!
+ \qmlproperty enumeration QtQuick2::ListView::effectiveLayoutDirection
+ This property holds the effective layout direction of the horizontal list.
+
+ When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
+ the visual layout direction of the horizontal list will be mirrored. However, the
+ property \l {ListView::layoutDirection}{layoutDirection} will remain unchanged.
+
+ \sa ListView::layoutDirection, {LayoutMirroring}{LayoutMirroring}
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::ListView::keyNavigationWraps
+ This property holds whether the list wraps key navigation.
+
+ If this is true, key navigation that would move the current item selection
+ past the end of the list instead wraps around and moves the selection to
+ the start of the list, and vice-versa.
+
+ By default, key navigation is not wrapped.
+*/
+
+
+/*!
+ \qmlproperty int QtQuick2::ListView::cacheBuffer
+ This property determines whether delegates are retained outside the
+ visible area of the view.
+
+ If this value is non-zero, the view keeps as many delegates
+ instantiated as it can fit within the buffer specified. For example,
+ if in a vertical view the delegate is 20 pixels high and \c cacheBuffer is
+ set to 40, then up to 2 delegates above and 2 delegates below the visible
+ area may be retained.
+
+ Note that cacheBuffer is not a pixel buffer - it only maintains additional
+ instantiated delegates.
+
+ Setting this value can improve the smoothness of scrolling behavior at the expense
+ of additional memory usage. It is not a substitute for creating efficient
+ delegates; the fewer elements in a delegate, the faster a view can be
+ scrolled.
+*/
+
+
+/*!
+ \qmlproperty string QtQuick2::ListView::section.property
+ \qmlproperty enumeration QtQuick2::ListView::section.criteria
+ \qmlproperty Component QtQuick2::ListView::section.delegate
+
+ These properties hold the expression to be evaluated for the \l section attached property.
+
+ The \l section attached property enables a ListView to be visually
+ separated into different parts. These properties determine how sections
+ are created.
+
+ \c section.property holds the name of the property that is the basis
+ of each section.
+
+ \c section.criteria holds the criteria for forming each section based on
+ \c section.property. This value can be one of:
+
+ \list
+ \o ViewSection.FullString (default) - sections are created based on the
+ \c section.property value.
+ \o ViewSection.FirstCharacter - sections are created based on the first
+ character of the \c section.property value (for example, 'A', 'B', 'C'
+ sections, etc. for an address book)
+ \endlist
+
+ \c section.delegate holds the delegate component for each section.
+
+ Each item in the list has attached properties named \c ListView.section,
+ \c ListView.previousSection and \c ListView.nextSection. These may be
+ used to place a section header for related items.
+
+ For example, here is a ListView that displays a list of animals, separated
+ into sections. Each item in the ListView is placed in a different section
+ depending on the "size" property of the model item. The \c sectionHeading
+ delegate component provides the light blue bar that marks the beginning of
+ each section.
+
+
+ \snippet examples/declarative/modelviews/listview/sections.qml 0
+
+ \image qml-listview-sections-example.png
+
+ \note Adding sections to a ListView does not automatically re-order the
+ list items by the section criteria.
+ If the model is not ordered by section, then it is possible that
+ the sections created will not be unique; each boundary between
+ differing sections will result in a section header being created
+ even if that section exists elsewhere.
+
+ \sa {declarative/modelviews/listview}{ListView examples}
+*/
QSGViewSection *QSGListView::sectionCriteria()
{
Q_D(QSGListView);
@@ -1315,12 +1736,35 @@ QSGViewSection *QSGListView::sectionCriteria()
return d->sectionCriteria;
}
+/*!
+ \qmlproperty string QtQuick2::ListView::currentSection
+ This property holds the section that is currently at the beginning of the view.
+*/
QString QSGListView::currentSection() const
{
Q_D(const QSGListView);
return d->currentSection;
}
+/*!
+ \qmlproperty real QtQuick2::ListView::highlightMoveSpeed
+ \qmlproperty int QtQuick2::ListView::highlightMoveDuration
+ \qmlproperty real QtQuick2::ListView::highlightResizeSpeed
+ \qmlproperty int QtQuick2::ListView::highlightResizeDuration
+
+ These properties hold the move and resize animation speed of the highlight delegate.
+
+ \l highlightFollowsCurrentItem must be true for these properties
+ to have effect.
+
+ The default value for the speed properties is 400 pixels/second.
+ The default value for the duration properties is -1, i.e. the
+ highlight will take as much time as necessary to move at the set speed.
+
+ These properties have the same characteristics as a SmoothedAnimation.
+
+ \sa highlightFollowsCurrentItem
+*/
qreal QSGListView::highlightMoveSpeed() const
{
Q_D(const QSGListView);
@@ -1382,6 +1826,27 @@ void QSGListView::setHighlightResizeDuration(int duration)
}
}
+/*!
+ \qmlproperty enumeration QtQuick2::ListView::snapMode
+
+ This property determines how the view scrolling will settle following a drag or flick.
+ The possible values are:
+
+ \list
+ \o ListView.NoSnap (default) - the view stops anywhere within the visible area.
+ \o ListView.SnapToItem - the view settles with an item aligned with the start of
+ the view.
+ \o ListView.SnapOneItem - the view settles no more than one item away from the first
+ visible item at the time the mouse button is released. This mode is particularly
+ useful for moving one page at a time.
+ \endlist
+
+ \c snapMode does not affect the \l currentIndex. To update the
+ \l currentIndex as the list is moved, set \l highlightRangeMode
+ to \c ListView.StrictlyEnforceRange.
+
+ \sa highlightRangeMode
+*/
QSGListView::SnapMode QSGListView::snapMode() const
{
Q_D(const QSGListView);
@@ -1397,6 +1862,28 @@ void QSGListView::setSnapMode(SnapMode mode)
}
}
+
+/*!
+ \qmlproperty Component QtQuick2::ListView::footer
+ This property holds the component to use as the footer.
+
+ An instance of the footer component is created for each view. The
+ footer is positioned at the end of the view, after any items.
+
+ \sa header
+*/
+
+
+/*!
+ \qmlproperty Component QtQuick2::ListView::header
+ This property holds the component to use as the header.
+
+ An instance of the header component is created for each view. The
+ header is positioned at the beginning of the view, before any items.
+
+ \sa footer
+*/
+
void QSGListView::viewportMoved()
{
Q_D(QSGListView);
@@ -1432,8 +1919,12 @@ void QSGListView::viewportMoved()
pos = viewPos + highlightEnd - d->highlight->size();
if (pos < viewPos + highlightStart)
pos = viewPos + highlightStart;
- d->highlightPosAnimator->stop();
- static_cast<FxListItemSG*>(d->highlight)->setPosition(qRound(pos));
+ if (pos != d->highlight->position()) {
+ d->highlightPosAnimator->stop();
+ static_cast<FxListItemSG*>(d->highlight)->setPosition(pos);
+ } else {
+ d->updateHighlight();
+ }
// update current index
if (FxViewItem *snapItem = d->snapItemAt(d->highlight->position())) {
@@ -1527,6 +2018,15 @@ void QSGListView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGe
}
+/*!
+ \qmlmethod QtQuick2::ListView::incrementCurrentIndex()
+
+ Increments the current index. The current index will wrap
+ if keyNavigationWraps is true and it is currently at the end.
+ This method has no effect if the \l count is zero.
+
+ \bold Note: methods should only be called after the Component has completed.
+*/
void QSGListView::incrementCurrentIndex()
{
Q_D(QSGListView);
@@ -1538,6 +2038,15 @@ void QSGListView::incrementCurrentIndex()
}
}
+/*!
+ \qmlmethod QtQuick2::ListView::decrementCurrentIndex()
+
+ Decrements the current index. The current index will wrap
+ if keyNavigationWraps is true and it is currently at the beginning.
+ This method has no effect if the \l count is zero.
+
+ \bold Note: methods should only be called after the Component has completed.
+*/
void QSGListView::decrementCurrentIndex()
{
Q_D(QSGListView);
@@ -1566,7 +2075,7 @@ void QSGListView::updateSections()
void QSGListView::itemsInserted(int modelIndex, int count)
{
Q_D(QSGListView);
- if (!isComponentComplete())
+ if (!isComponentComplete() || !d->model || !d->model->isValid())
return;
d->updateUnrequestedIndexes();
d->moveReason = QSGListViewPrivate::Other;
@@ -1706,7 +2215,7 @@ void QSGListView::itemsInserted(int modelIndex, int count)
void QSGListView::itemsRemoved(int modelIndex, int count)
{
Q_D(QSGListView);
- if (!isComponentComplete())
+ if (!isComponentComplete() || !d->model || !d->model->isValid())
return;
d->moveReason = QSGListViewPrivate::Other;
d->updateUnrequestedIndexes();
@@ -1803,7 +2312,7 @@ void QSGListView::itemsRemoved(int modelIndex, int count)
void QSGListView::itemsMoved(int from, int to, int count)
{
Q_D(QSGListView);
- if (!isComponentComplete())
+ if (!isComponentComplete() || !d->isValid())
return;
d->updateUnrequestedIndexes();
@@ -1926,6 +2435,72 @@ void QSGListView::itemsMoved(int from, int to, int count)
d->layout();
}
+/*!
+ \qmlmethod QtQuick2::ListView::positionViewAtIndex(int index, PositionMode mode)
+
+ Positions the view such that the \a index is at the position specified by
+ \a mode:
+
+ \list
+ \o ListView.Beginning - position item at the top (or left for horizontal orientation) of the view.
+ \o ListView.Center - position item in the center of the view.
+ \o ListView.End - position item at bottom (or right for horizontal orientation) of the view.
+ \o ListView.Visible - if any part of the item is visible then take no action, otherwise
+ bring the item into view.
+ \o ListView.Contain - ensure the entire item is visible. If the item is larger than
+ the view the item is positioned at the top (or left for horizontal orientation) of the view.
+ \endlist
+
+ If positioning the view at \a index would cause empty space to be displayed at
+ the beginning or end of the view, the view will be positioned at the boundary.
+
+ It is not recommended to use \l {Flickable::}{contentX} or \l {Flickable::}{contentY} to position the view
+ at a particular index. This is unreliable since removing items from the start
+ of the list does not cause all other items to be repositioned, and because
+ the actual start of the view can vary based on the size of the delegates.
+ The correct way to bring an item into view is with \c positionViewAtIndex.
+
+ \bold Note: methods should only be called after the Component has completed. To position
+ the view at startup, this method should be called by Component.onCompleted. For
+ example, to position the view at the end:
+
+ \code
+ Component.onCompleted: positionViewAtIndex(count - 1, ListView.Beginning)
+ \endcode
+*/
+
+/*!
+ \qmlmethod QtQuick2::ListView::positionViewAtBeginning()
+ \qmlmethod QtQuick2::ListView::positionViewAtEnd()
+
+ Positions the view at the beginning or end, taking into account any header or footer.
+
+ It is not recommended to use \l {Flickable::}{contentX} or \l {Flickable::}{contentY} to position the view
+ at a particular index. This is unreliable since removing items from the start
+ of the list does not cause all other items to be repositioned, and because
+ the actual start of the view can vary based on the size of the delegates.
+
+ \bold Note: methods should only be called after the Component has completed. To position
+ the view at startup, this method should be called by Component.onCompleted. For
+ example, to position the view at the end on startup:
+
+ \code
+ Component.onCompleted: positionViewAtEnd()
+ \endcode
+*/
+
+/*!
+ \qmlmethod int QtQuick2::ListView::indexAt(int x, int y)
+
+ Returns the index of the visible item containing the point \a x, \a y in content
+ coordinates. If there is no item at the point specified, or the item is
+ not visible -1 is returned.
+
+ If the item is outside the visible area, -1 is returned, regardless of
+ whether an item will exist at that point when scrolled into view.
+
+ \bold Note: methods should only be called after the Component has completed.
+*/
QSGListViewAttached *QSGListView::qmlAttachedProperties(QObject *obj)
{
diff --git a/src/declarative/items/qsgloader.cpp b/src/declarative/items/qsgloader.cpp
index ccf16896fb..999c174ee9 100644
--- a/src/declarative/items/qsgloader.cpp
+++ b/src/declarative/items/qsgloader.cpp
@@ -103,6 +103,115 @@ void QSGLoaderPrivate::initResize()
_q_updateSize();
}
+/*!
+ \qmlclass Loader QSGLoader
+ \inqmlmodule QtQuick 2
+ \ingroup qml-utility-elements
+ \inherits Item
+
+ \brief The Loader item allows dynamically loading an Item-based
+ subtree from a URL or Component.
+
+ Loader is used to dynamically load visual QML components. It can load a
+ QML file (using the \l source property) or a \l Component object (using
+ the \l sourceComponent property). It is useful for delaying the creation
+ of a component until it is required: for example, when a component should
+ be created on demand, or when a component should not be created
+ unnecessarily for performance reasons.
+
+ Here is a Loader that loads "Page1.qml" as a component when the
+ \l MouseArea is clicked:
+
+ \snippet doc/src/snippets/declarative/loader/simple.qml 0
+
+ The loaded item can be accessed using the \l item property.
+
+ If the \l source or \l sourceComponent changes, any previously instantiated
+ items are destroyed. Setting \l source to an empty string or setting
+ \l sourceComponent to \c undefined destroys the currently loaded item,
+ freeing resources and leaving the Loader empty.
+
+ \section2 Loader sizing behavior
+
+ Loader is like any other visual item and must be positioned and sized
+ accordingly to become visible.
+
+ \list
+ \o If an explicit size is not specified for the Loader, the Loader
+ is automatically resized to the size of the loaded item once the
+ component is loaded.
+ \o If the size of the Loader is specified explicitly by setting
+ the width, height or by anchoring, the loaded item will be resized
+ to the size of the Loader.
+ \endlist
+
+ In both scenarios the size of the item and the Loader are identical.
+ This ensures that anchoring to the Loader is equivalent to anchoring
+ to the loaded item.
+
+ \table
+ \row
+ \o sizeloader.qml
+ \o sizeitem.qml
+ \row
+ \o \snippet doc/src/snippets/declarative/loader/sizeloader.qml 0
+ \o \snippet doc/src/snippets/declarative/loader/sizeitem.qml 0
+ \row
+ \o The red rectangle will be sized to the size of the root item.
+ \o The red rectangle will be 50x50, centered in the root item.
+ \endtable
+
+
+ \section2 Receiving signals from loaded items
+
+ Any signals emitted from the loaded item can be received using the
+ \l Connections element. For example, the following \c application.qml
+ loads \c MyItem.qml, and is able to receive the \c message signal from
+ the loaded item through a \l Connections object:
+
+ \table
+ \row
+ \o application.qml
+ \o MyItem.qml
+ \row
+ \o \snippet doc/src/snippets/declarative/loader/connections.qml 0
+ \o \snippet doc/src/snippets/declarative/loader/MyItem.qml 0
+ \endtable
+
+ Alternatively, since \c MyItem.qml is loaded within the scope of the
+ Loader, it could also directly call any function defined in the Loader or
+ its parent \l Item.
+
+
+ \section2 Focus and key events
+
+ Loader is a focus scope. Its \l {Item::}{focus} property must be set to
+ \c true for any of its children to get the \e {active focus}. (See
+ \l{qmlfocus#Acquiring Focus and Focus Scopes}{the focus documentation page}
+ for more details.) Any key events received in the loaded item should likely
+ also be \l {KeyEvent::}{accepted} so they are not propagated to the Loader.
+
+ For example, the following \c application.qml loads \c KeyReader.qml when
+ the \l MouseArea is clicked. Notice the \l {Item::}{focus} property is
+ set to \c true for the Loader as well as the \l Item in the dynamically
+ loaded object:
+
+ \table
+ \row
+ \o application.qml
+ \o KeyReader.qml
+ \row
+ \o \snippet doc/src/snippets/declarative/loader/focus.qml 0
+ \o \snippet doc/src/snippets/declarative/loader/KeyReader.qml 0
+ \endtable
+
+ Once \c KeyReader.qml is loaded, it accepts key events and sets
+ \c event.accepted to \c true so that the event is not propagated to the
+ parent \l Rectangle.
+
+ \sa {dynamic-object-creation}{Dynamic Object Creation}
+*/
+
QSGLoader::QSGLoader(QSGItem *parent)
: QSGImplicitSizeItem(*(new QSGLoaderPrivate), parent)
{
@@ -118,6 +227,19 @@ QSGLoader::~QSGLoader()
}
}
+/*!
+ \qmlproperty url QtQuick2::Loader::source
+ This property holds the URL of the QML component to instantiate.
+
+ Note the QML component must be an \l{Item}-based component. The loader
+ cannot load non-visual components.
+
+ To unload the currently loaded item, set this property to an empty string,
+ or set \l sourceComponent to \c undefined. Setting \c source to a
+ new URL will also cause the item created by the previous URL to be unloaded.
+
+ \sa sourceComponent, status, progress
+*/
QUrl QSGLoader::source() const
{
Q_D(const QSGLoader);
@@ -148,6 +270,28 @@ void QSGLoader::setSource(const QUrl &url)
d->load();
}
+/*!
+ \qmlproperty Component QtQuick2::Loader::sourceComponent
+ This property holds the \l{Component} to instantiate.
+
+ \qml
+ Item {
+ Component {
+ id: redSquare
+ Rectangle { color: "red"; width: 10; height: 10 }
+ }
+
+ Loader { sourceComponent: redSquare }
+ Loader { sourceComponent: redSquare; x: 10 }
+ }
+ \endqml
+
+ To unload the currently loaded item, set this property to an empty string
+ or \c undefined.
+
+ \sa source, progress
+*/
+
QDeclarativeComponent *QSGLoader::sourceComponent() const
{
Q_D(const QSGLoader);
@@ -270,6 +414,46 @@ void QSGLoaderPrivate::_q_sourceLoaded()
}
}
+/*!
+ \qmlproperty enumeration QtQuick2::Loader::status
+
+ This property holds the status of QML loading. It can be one of:
+ \list
+ \o Loader.Null - no QML source has been set
+ \o Loader.Ready - the QML source has been loaded
+ \o Loader.Loading - the QML source is currently being loaded
+ \o Loader.Error - an error occurred while loading the QML source
+ \endlist
+
+ Use this status to provide an update or respond to the status change in some way.
+ For example, you could:
+
+ \list
+ \o Trigger a state change:
+ \qml
+ State { name: 'loaded'; when: loader.status == Loader.Ready }
+ \endqml
+
+ \o Implement an \c onStatusChanged signal handler:
+ \qml
+ Loader {
+ id: loader
+ onStatusChanged: if (loader.status == Loader.Ready) console.log('Loaded')
+ }
+ \endqml
+
+ \o Bind to the status value:
+ \qml
+ Text { text: loader.status == Loader.Ready ? 'Loaded' : 'Not loaded' }
+ \endqml
+ \endlist
+
+ Note that if the source is a local file, the status will initially be Ready (or Error). While
+ there will be no onStatusChanged signal in that case, the onLoaded will still be invoked.
+
+ \sa progress
+*/
+
QSGLoader::Status QSGLoader::status() const
{
Q_D(const QSGLoader);
@@ -290,6 +474,23 @@ void QSGLoader::componentComplete()
d->load();
}
+/*!
+ \qmlsignal QtQuick2::Loader::onLoaded()
+
+ This handler is called when the \l status becomes \c Loader.Ready, or on successful
+ initial load.
+*/
+
+
+/*!
+\qmlproperty real QtQuick2::Loader::progress
+
+This property holds the progress of loading QML data from the network, from
+0.0 (nothing loaded) to 1.0 (finished). Most QML files are quite small, so
+this value will rapidly change from 0 to 1.
+
+\sa status
+*/
qreal QSGLoader::progress() const
{
Q_D(const QSGLoader);
@@ -328,6 +529,10 @@ void QSGLoaderPrivate::_q_updateSize(bool loaderGeometryChanged)
updatingSize = false;
}
+/*!
+ \qmlproperty Item QtQuick2::Loader::item
+ This property holds the top-level item that is currently loaded.
+*/
QSGItem *QSGLoader::item() const
{
Q_D(const QSGLoader);
diff --git a/src/declarative/items/qsgmousearea.cpp b/src/declarative/items/qsgmousearea.cpp
index b35c14624a..7d86d2e248 100644
--- a/src/declarative/items/qsgmousearea.cpp
+++ b/src/declarative/items/qsgmousearea.cpp
@@ -85,7 +85,7 @@ void QSGDrag::resetTarget()
}
/*!
- \qmlproperty Item MouseArea::drag.dropItem
+ \qmlproperty Item QtQuick2::MouseArea::drag.dropItem
This property holds the item an active drag will be dropped on if released
at the current position.
@@ -115,7 +115,7 @@ void QSGDrag::setGrabItem(QSGItem *item)
}
/*!
- \qmlproperty variant MouseArea::drag.data
+ \qmlproperty variant QtQuick2::MouseArea::drag.data
This property holds the data sent to recipients of drag events generated
by a MouseArea.
@@ -234,7 +234,7 @@ void QSGDrag::setFilterChildren(bool filter)
}
/*!
- \qmlproperty stringlist MouseArea::drag.keys
+ \qmlproperty stringlist QtQuick2::MouseArea::drag.keys
This property holds a list of keys drag recipients can use to identify the
source or data type of a drag event.
@@ -272,7 +272,7 @@ void QSGMouseAreaPrivate::init()
q->setFiltersChildMouseEvents(true);
}
-void QSGMouseAreaPrivate::saveEvent(QGraphicsSceneMouseEvent *event)
+void QSGMouseAreaPrivate::saveEvent(QGraphicsSceneMouseEvent *event)
{
lastPos = event->pos();
lastScenePos = event->scenePos();
@@ -287,14 +287,14 @@ void QSGMouseAreaPrivate::forwardEvent(QGraphicsSceneMouseEvent* event)
event->setPos(q->mapFromScene(event->scenePos()));
}
-bool QSGMouseAreaPrivate::isPressAndHoldConnected()
+bool QSGMouseAreaPrivate::isPressAndHoldConnected()
{
Q_Q(QSGMouseArea);
static int idx = QObjectPrivate::get(q)->signalIndex("pressAndHold(QSGMouseEvent*)");
return QObjectPrivate::get(q)->isSignalConnected(idx);
}
-bool QSGMouseAreaPrivate::isDoubleClickConnected()
+bool QSGMouseAreaPrivate::isDoubleClickConnected()
{
Q_Q(QSGMouseArea);
static int idx = QObjectPrivate::get(q)->signalIndex("doubleClicked(QSGMouseEvent*)");
@@ -373,7 +373,65 @@ bool QSGMouseAreaPrivate::propagateHelper(QSGMouseEvent *ev, QSGItem *item,const
}
-/*
+/*!
+ \qmlclass MouseArea QSGMouseArea
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-interaction-elements
+ \brief The MouseArea item enables simple mouse handling.
+ \inherits Item
+
+ A MouseArea is an invisible item that is typically used in conjunction with
+ a visible item in order to provide mouse handling for that item.
+ By effectively acting as a proxy, the logic for mouse handling can be
+ contained within a MouseArea item.
+
+ For basic key handling, see the \l{Keys}{Keys attached property}.
+
+ The \l enabled property is used to enable and disable mouse handling for
+ the proxied item. When disabled, the mouse area becomes transparent to
+ mouse events.
+
+ The \l pressed read-only property indicates whether or not the user is
+ holding down a mouse button over the mouse area. This property is often
+ used in bindings between properties in a user interface. The containsMouse
+ read-only property indicates the presence of the mouse cursor over the
+ mouse area but, by default, only when a mouse button is held down; see below
+ for further details.
+
+ Information about the mouse position and button clicks are provided via
+ signals for which event handler properties are defined. The most commonly
+ used involved handling mouse presses and clicks: onClicked, onDoubleClicked,
+ onPressed, onReleased and onPressAndHold.
+
+ By default, MouseArea items only report mouse clicks and not changes to the
+ position of the mouse cursor. Setting the hoverEnabled property ensures that
+ handlers defined for onPositionChanged, onEntered and onExited are used and
+ that the containsMouse property is updated even when no mouse buttons are
+ pressed.
+
+ \section1 Example Usage
+
+ \div {class="float-right"}
+ \inlineimage qml-mousearea-snippet.png
+ \enddiv
+
+ The following example uses a MouseArea in a \l Rectangle that changes
+ the \l Rectangle color to red when clicked:
+
+ \snippet doc/src/snippets/declarative/mousearea/mousearea.qml import
+ \codeline
+ \snippet doc/src/snippets/declarative/mousearea/mousearea.qml intro
+
+ \clearfloat
+ Many MouseArea signals pass a \l{MouseEvent}{mouse} parameter that contains
+ additional information about the mouse event, such as the position, button,
+ and any key modifiers.
+
+ Here is an extension of the previous example that produces a different
+ color when the area is right clicked:
+
+ \snippet doc/src/snippets/declarative/mousearea/mousearea.qml intro-extended
+
Behavioral Change in QtQuick 2.0
From QtQuick 2.0, the signals clicked, doubleClicked and pressAndHold have a different interaction
@@ -385,7 +443,149 @@ bool QSGMouseAreaPrivate::propagateHelper(QSGMouseEvent *ev, QSGItem *item,const
Note that to get the same behavior as a QtQuick 1.0 MouseArea{} with regard to absorbing all mouse events, you will
now need to add empty signal handlers for these three signals.
- */
+
+ \sa MouseEvent, {declarative/touchinteraction/mousearea}{MouseArea example}
+*/
+
+/*!
+ \qmlsignal QtQuick2::MouseArea::onEntered()
+
+ This handler is called when the mouse enters the mouse area.
+
+ By default the onEntered handler is only called while a button is
+ pressed. Setting hoverEnabled to true enables handling of
+ onEntered when no mouse button is pressed.
+
+ \sa hoverEnabled
+*/
+
+/*!
+ \qmlsignal QtQuick2::MouseArea::onExited()
+
+ This handler is called when the mouse exits the mouse area.
+
+ By default the onExited handler is only called while a button is
+ pressed. Setting hoverEnabled to true enables handling of
+ onExited when no mouse button is pressed.
+
+ The example below shows a fairly typical relationship between
+ two MouseAreas, with \c mouseArea2 on top of \c mouseArea1. Moving the
+ mouse into \c mouseArea2 from \c mouseArea1 will cause \c onExited
+ to be called for \c mouseArea1.
+ \qml
+ Rectangle {
+ width: 400; height: 400
+ MouseArea {
+ id: mouseArea1
+ anchors.fill: parent
+ hoverEnabled: true
+ }
+ MouseArea {
+ id: mouseArea2
+ width: 100; height: 100
+ anchors.centerIn: parent
+ hoverEnabled: true
+ }
+ }
+ \endqml
+
+ If instead you give the two mouseAreas a parent-child relationship,
+ moving the mouse into \c mouseArea2 from \c mouseArea1 will \b not
+ cause \c onExited to be called for \c mouseArea1. Instead, they will
+ both be considered to be simultaneously hovered.
+
+ \sa hoverEnabled
+*/
+
+/*!
+ \qmlsignal QtQuick2::MouseArea::onPositionChanged(MouseEvent mouse)
+
+ This handler is called when the mouse position changes.
+
+ The \l {MouseEvent}{mouse} parameter provides information about the mouse, including the x and y
+ position, and any buttons currently pressed.
+
+ The \e accepted property of the MouseEvent parameter is ignored in this handler.
+
+ By default the onPositionChanged handler is only called while a button is
+ pressed. Setting hoverEnabled to true enables handling of
+ onPositionChanged when no mouse button is pressed.
+*/
+
+/*!
+ \qmlsignal QtQuick2::MouseArea::onClicked(MouseEvent mouse)
+
+ This handler is called when there is a click. A click is defined as a press followed by a release,
+ both inside the MouseArea (pressing, moving outside the MouseArea, and then moving back inside and
+ releasing is also considered a click).
+
+ The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
+ position of the release of the click, and whether the click was held.
+
+ The \e accepted property of the MouseEvent parameter is ignored in this handler.
+*/
+
+/*!
+ \qmlsignal QtQuick2::MouseArea::onPressed(MouseEvent mouse)
+
+ This handler is called when there is a press.
+ The \l {MouseEvent}{mouse} parameter provides information about the press, including the x and y
+ position and which button was pressed.
+
+ The \e accepted property of the MouseEvent parameter determines whether this MouseArea
+ will handle the press and all future mouse events until release. The default is to accept
+ the event and not allow other MouseArea beneath this one to handle the event. If \e accepted
+ is set to false, no further events will be sent to this MouseArea until the button is next
+ pressed.
+*/
+
+/*!
+ \qmlsignal QtQuick2::MouseArea::onReleased(MouseEvent mouse)
+
+ This handler is called when there is a release.
+ The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
+ position of the release of the click, and whether the click was held.
+
+ The \e accepted property of the MouseEvent parameter is ignored in this handler.
+
+ \sa onCanceled
+*/
+
+/*!
+ \qmlsignal QtQuick2::MouseArea::onPressAndHold(MouseEvent mouse)
+
+ This handler is called when there is a long press (currently 800ms).
+ The \l {MouseEvent}{mouse} parameter provides information about the press, including the x and y
+ position of the press, and which button is pressed.
+
+ The \e accepted property of the MouseEvent parameter is ignored in this handler.
+*/
+
+/*!
+ \qmlsignal QtQuick2::MouseArea::onDoubleClicked(MouseEvent mouse)
+
+ This handler is called when there is a double-click (a press followed by a release followed by a press).
+ The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
+ position of the release of the click, and whether the click was held.
+
+ If the \e accepted property of the \l {MouseEvent}{mouse} parameter is set to false
+ in the handler, the onPressed/onReleased/onClicked handlers will be called for the second
+ click; otherwise they are suppressed. The accepted property defaults to true.
+*/
+
+/*!
+ \qmlsignal QtQuick2::MouseArea::onCanceled()
+
+ This handler is called when mouse events have been canceled, either because an event was not accepted, or
+ because another element stole the mouse event handling.
+
+ This signal is for advanced use: it is useful when there is more than one MouseArea
+ that is handling input, or when there is a MouseArea inside a \l Flickable. In the latter
+ case, if you execute some logic on the pressed signal and then start dragging, the
+ \l Flickable will steal the mouse handling from the MouseArea. In these cases, to reset
+ the logic when the MouseArea has lost the mouse handling to the \l Flickable,
+ \c onCanceled should be used in addition to onReleased.
+*/
QSGMouseArea::QSGMouseArea(QSGItem *parent)
: QSGItem(*(new QSGMouseAreaPrivate), parent)
{
@@ -397,6 +597,25 @@ QSGMouseArea::~QSGMouseArea()
{
}
+/*!
+ \qmlproperty real QtQuick2::MouseArea::mouseX
+ \qmlproperty real QtQuick2::MouseArea::mouseY
+ These properties hold the coordinates of the mouse cursor.
+
+ If the hoverEnabled property is false then these properties will only be valid
+ while a button is pressed, and will remain valid as long as the button is held
+ down even if the mouse is moved outside the area.
+
+ By default, this property is false.
+
+ If hoverEnabled is true then these properties will be valid when:
+ \list
+ \i no button is pressed, but the mouse is within the MouseArea (containsMouse is true).
+ \i a button is pressed and held, even if it has since moved out of the area.
+ \endlist
+
+ The coordinates are relative to the MouseArea.
+*/
qreal QSGMouseArea::mouseX() const
{
Q_D(const QSGMouseArea);
@@ -409,6 +628,12 @@ qreal QSGMouseArea::mouseY() const
return d->lastPos.y();
}
+/*!
+ \qmlproperty bool QtQuick2::MouseArea::enabled
+ This property holds whether the item accepts mouse events.
+
+ By default, this property is true.
+*/
bool QSGMouseArea::isEnabled() const
{
Q_D(const QSGMouseArea);
@@ -424,6 +649,22 @@ void QSGMouseArea::setEnabled(bool a)
}
}
+/*!
+ \qmlproperty bool QtQuick2::MouseArea::preventStealing
+ This property holds whether the mouse events may be stolen from this
+ MouseArea.
+
+ If a MouseArea is placed within an item that filters child mouse
+ events, such as Flickable, the mouse
+ events may be stolen from the MouseArea if a gesture is recognized
+ by the parent element, e.g. a flick gesture. If preventStealing is
+ set to true, no element will steal the mouse events.
+
+ Note that setting preventStealing to true once an element has started
+ stealing events will have no effect until the next press event.
+
+ By default this property is false.
+*/
bool QSGMouseArea::preventStealing() const
{
Q_D(const QSGMouseArea);
@@ -440,6 +681,23 @@ void QSGMouseArea::setPreventStealing(bool prevent)
}
}
+/*!
+ \qmlproperty MouseButtons QtQuick2::MouseArea::pressedButtons
+ This property holds the mouse buttons currently pressed.
+
+ It contains a bitwise combination of:
+ \list
+ \o Qt.LeftButton
+ \o Qt.RightButton
+ \o Qt.MiddleButton
+ \endlist
+
+ The code below displays "right" when the right mouse buttons is pressed:
+
+ \snippet doc/src/snippets/declarative/mousearea/mousearea.qml mousebuttons
+
+ \sa acceptedButtons
+*/
Qt::MouseButtons QSGMouseArea::pressedButtons() const
{
Q_D(const QSGMouseArea);
@@ -682,7 +940,7 @@ void QSGMouseArea::hoverLeaveEvent(QHoverEvent *event)
setHovered(false);
}
-void QSGMouseArea::mouseUngrabEvent()
+void QSGMouseArea::ungrabMouse()
{
Q_D(QSGMouseArea);
if (d->pressed) {
@@ -700,6 +958,11 @@ void QSGMouseArea::mouseUngrabEvent()
}
}
+void QSGMouseArea::mouseUngrabEvent()
+{
+ ungrabMouse();
+}
+
bool QSGMouseArea::sendMouseEvent(QGraphicsSceneMouseEvent *event)
{
Q_D(QSGMouseArea);
@@ -794,6 +1057,12 @@ void QSGMouseArea::timerEvent(QTimerEvent *event)
}
}
+void QSGMouseArea::windowDeactivateEvent()
+{
+ ungrabMouse();
+ QSGItem::windowDeactivateEvent();
+}
+
void QSGMouseArea::geometryChanged(const QRectF &newGeometry,
const QRectF &oldGeometry)
{
@@ -821,6 +1090,17 @@ void QSGMouseArea::itemChange(ItemChange change, const ItemChangeData &value)
QSGItem::itemChange(change, value);
}
+/*!
+ \qmlproperty bool QtQuick2::MouseArea::hoverEnabled
+ This property holds whether hover events are handled.
+
+ By default, mouse events are only handled in response to a button event, or when a button is
+ pressed. Hover enables handling of all mouse events even when no mouse button is
+ pressed.
+
+ This property affects the containsMouse property and the onEntered, onExited and
+ onPositionChanged signals.
+*/
bool QSGMouseArea::hoverEnabled() const
{
return acceptHoverEvents();
@@ -834,16 +1114,26 @@ void QSGMouseArea::setHoverEnabled(bool h)
setAcceptHoverEvents(h);
emit hoverEnabledChanged();
- if (d->hovered != isUnderMouse())
- setHovered(!d->hovered);
}
+
+/*!
+ \qmlproperty bool QtQuick2::MouseArea::containsMouse
+ This property holds whether the mouse is currently inside the mouse area.
+
+ \warning This property is not updated if the area moves under the mouse: \e containsMouse will not change.
+ In addition, if hoverEnabled is false, containsMouse will only be valid when the mouse is pressed.
+*/
bool QSGMouseArea::hovered() const
{
Q_D(const QSGMouseArea);
return d->hovered;
}
+/*!
+ \qmlproperty bool QtQuick2::MouseArea::pressed
+ This property holds whether the mouse area is currently pressed.
+*/
bool QSGMouseArea::pressed() const
{
Q_D(const QSGMouseArea);
@@ -859,7 +1149,26 @@ void QSGMouseArea::setHovered(bool h)
d->hovered ? emit entered() : emit exited();
}
}
+/*!
+ \qmlproperty QtQuick2::Qt::MouseButtons MouseArea::acceptedButtons
+ This property holds the mouse buttons that the mouse area reacts to.
+ The available buttons are:
+ \list
+ \o Qt.LeftButton
+ \o Qt.RightButton
+ \o Qt.MiddleButton
+ \endlist
+
+ To accept more than one button the flags can be combined with the
+ "|" (or) operator:
+
+ \code
+ MouseArea { acceptedButtons: Qt.LeftButton | Qt.RightButton }
+ \endcode
+
+ The default value is \c Qt.LeftButton.
+*/
Qt::MouseButtons QSGMouseArea::acceptedButtons() const
{
return acceptedMouseButtons();
@@ -907,6 +1216,43 @@ bool QSGMouseArea::setPressed(bool p)
return false;
}
+/*!
+ \qmlproperty Item QtQuick2::MouseArea::drag.target
+ \qmlproperty bool QtQuick2::MouseArea::drag.active
+ \qmlproperty enumeration QtQuick2::MouseArea::drag.axis
+ \qmlproperty real QtQuick2::MouseArea::drag.minimumX
+ \qmlproperty real QtQuick2::MouseArea::drag.maximumX
+ \qmlproperty real QtQuick2::MouseArea::drag.minimumY
+ \qmlproperty real QtQuick2::MouseArea::drag.maximumY
+ \qmlproperty bool QtQuick2::MouseArea::drag.filterChildren
+
+ \c drag provides a convenient way to make an item draggable.
+
+ \list
+ \i \c drag.target specifies the id of the item to drag.
+ \i \c drag.active specifies if the target item is currently being dragged.
+ \i \c drag.axis specifies whether dragging can be done horizontally (\c Drag.XAxis), vertically (\c Drag.YAxis), or both (\c Drag.XandYAxis)
+ \i \c drag.minimum and \c drag.maximum limit how far the target can be dragged along the corresponding axes.
+ \endlist
+
+ The following example displays a \l Rectangle that can be dragged along the X-axis. The opacity
+ of the rectangle is reduced when it is dragged to the right.
+
+ \snippet doc/src/snippets/declarative/mousearea/mousearea.qml drag
+
+ \note Items cannot be dragged if they are anchored for the requested
+ \c drag.axis. For example, if \c anchors.left or \c anchors.right was set
+ for \c rect in the above example, it cannot be dragged along the X-axis.
+ This can be avoided by settng the anchor value to \c undefined in
+ an \l onPressed handler.
+
+ If \c drag.filterChildren is set to true, a drag can override descendant MouseAreas. This
+ enables a parent MouseArea to handle drags, for example, while descendants handle clicks:
+
+ \snippet doc/src/snippets/declarative/mousearea/mouseareadragfilter.qml dragfilter
+
+*/
+
QSGDrag *QSGMouseArea::drag()
{
Q_D(QSGMouseArea);
diff --git a/src/declarative/items/qsgmousearea_p.h b/src/declarative/items/qsgmousearea_p.h
index aac829f6a9..ff3863c3bb 100644
--- a/src/declarative/items/qsgmousearea_p.h
+++ b/src/declarative/items/qsgmousearea_p.h
@@ -223,6 +223,7 @@ protected:
virtual void hoverLeaveEvent(QHoverEvent *event);
virtual bool childMouseEventFilter(QSGItem *i, QEvent *e);
virtual void timerEvent(QTimerEvent *event);
+ virtual void windowDeactivateEvent();
virtual void geometryChanged(const QRectF &newGeometry,
const QRectF &oldGeometry);
@@ -231,6 +232,7 @@ protected:
private:
void handlePress();
void handleRelease();
+ void ungrabMouse();
private:
Q_DISABLE_COPY(QSGMouseArea)
diff --git a/src/declarative/items/qsgpainteditem.cpp b/src/declarative/items/qsgpainteditem.cpp
index d4543c94f4..95aa2b4fb2 100644
--- a/src/declarative/items/qsgpainteditem.cpp
+++ b/src/declarative/items/qsgpainteditem.cpp
@@ -150,15 +150,10 @@ void QSGPaintedItem::update(const QRect &rect)
Q_D(QSGPaintedItem);
d->contentsDirty = true;
- QRect srect(qCeil(rect.x()*d->contentsScale),
- qCeil(rect.y()*d->contentsScale),
- qCeil(rect.width()*d->contentsScale),
- qCeil(rect.height()*d->contentsScale));
-
- if (srect.isNull() && !d->dirtyRect.isNull())
+ if (rect.isNull() && !d->dirtyRect.isNull())
d->dirtyRect = contentsBoundingRect().toAlignedRect();
else
- d->dirtyRect |= (contentsBoundingRect() & srect).toAlignedRect();
+ d->dirtyRect |= (contentsBoundingRect() & rect).toAlignedRect();
QSGItem::update();
}
diff --git a/src/declarative/items/qsgpathview.cpp b/src/declarative/items/qsgpathview.cpp
index 0bc45fd037..2c3e3cee71 100644
--- a/src/declarative/items/qsgpathview.cpp
+++ b/src/declarative/items/qsgpathview.cpp
@@ -111,7 +111,7 @@ void QSGPathViewPrivate::init()
q, movementEndingIdx, Qt::DirectConnection);
}
-QSGItem *QSGPathViewPrivate::getItem(int modelIndex)
+QSGItem *QSGPathViewPrivate::getItem(int modelIndex, bool onPath)
{
Q_Q(QSGPathView);
requestedIndex = modelIndex;
@@ -128,7 +128,7 @@ QSGItem *QSGPathViewPrivate::getItem(int modelIndex)
qPathViewAttachedType = 0;
if (att) {
att->m_view = q;
- att->setOnPath(true);
+ att->setOnPath(onPath);
}
item->setParentItem(q);
QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item);
@@ -158,6 +158,10 @@ QSGPathViewAttached *QSGPathViewPrivate::attached(QSGItem *item)
void QSGPathViewPrivate::clear()
{
+ if (currentItem) {
+ releaseItem(currentItem);
+ currentItem = 0;
+ }
for (int i=0; i<items.count(); i++){
QSGItem *p = items[i];
releaseItem(p);
@@ -345,6 +349,71 @@ void QSGPathViewPrivate::regenerate()
q->refill();
}
+/*!
+ \qmlclass PathView QSGPathView
+ \inqmlmodule QtQuick 2
+ \ingroup qml-view-elements
+ \brief The PathView element lays out model-provided items on a path.
+ \inherits Item
+
+ A PathView displays data from models created from built-in QML elements like ListModel
+ and XmlListModel, or custom model classes defined in C++ that inherit from
+ QAbstractListModel.
+
+ The view has a \l model, which defines the data to be displayed, and
+ a \l delegate, which defines how the data should be displayed.
+ The \l delegate is instantiated for each item on the \l path.
+ The items may be flicked to move them along the path.
+
+ For example, if there is a simple list model defined in a file \c ContactModel.qml like this:
+
+ \snippet doc/src/snippets/declarative/pathview/ContactModel.qml 0
+
+ This data can be represented as a PathView, like this:
+
+ \snippet doc/src/snippets/declarative/pathview/pathview.qml 0
+
+ \image pathview.gif
+
+ (Note the above example uses PathAttribute to scale and modify the
+ opacity of the items as they rotate. This additional code can be seen in the
+ PathAttribute documentation.)
+
+ PathView does not automatically handle keyboard navigation. This is because
+ the keys to use for navigation will depend upon the shape of the path. Navigation
+ can be added quite simply by setting \c focus to \c true and calling
+ \l decrementCurrentIndex() or \l incrementCurrentIndex(), for example to navigate
+ using the left and right arrow keys:
+
+ \qml
+ PathView {
+ // ...
+ focus: true
+ Keys.onLeftPressed: decrementCurrentIndex()
+ Keys.onRightPressed: incrementCurrentIndex()
+ }
+ \endqml
+
+ The path view itself is a focus scope (see \l{qmlfocus#Acquiring Focus and Focus Scopes}{the focus documentation page} for more details).
+
+ Delegates are instantiated as needed and may be destroyed at any time.
+ State should \e never be stored in a delegate.
+
+ PathView attaches a number of properties to the root item of the delegate, for example
+ \c {PathView.isCurrentItem}. In the following example, the root delegate item can access
+ this attached property directly as \c PathView.isCurrentItem, while the child
+ \c nameText object must refer to this property as \c wrapper.PathView.isCurrentItem.
+
+ \snippet doc/src/snippets/declarative/pathview/pathview.qml 1
+
+ \bold Note that views do not enable \e clip automatically. If the view
+ is not clipped by another item or the screen, it will be necessary
+ to set \e {clip: true} in order to have the out of view items clipped
+ nicely.
+
+ \sa Path, {declarative/modelviews/pathview}{PathView example}
+*/
+
QSGPathView::QSGPathView(QSGItem *parent)
: QSGItem(*(new QSGPathViewPrivate), parent)
{
@@ -362,6 +431,54 @@ QSGPathView::~QSGPathView()
delete d->model;
}
+/*!
+ \qmlattachedproperty PathView QtQuick2::PathView::view
+ This attached property holds the view that manages this delegate instance.
+
+ It is attached to each instance of the delegate.
+*/
+
+/*!
+ \qmlattachedproperty bool QtQuick2::PathView::onPath
+ This attached property holds whether the item is currently on the path.
+
+ If a pathItemCount has been set, it is possible that some items may
+ be instantiated, but not considered to be currently on the path.
+ Usually, these items would be set invisible, for example:
+
+ \qml
+ Component {
+ Rectangle {
+ visible: PathView.onPath
+ // ...
+ }
+ }
+ \endqml
+
+ It is attached to each instance of the delegate.
+*/
+
+/*!
+ \qmlattachedproperty bool QtQuick2::PathView::isCurrentItem
+ This attached property is true if this delegate is the current item; otherwise false.
+
+ It is attached to each instance of the delegate.
+
+ This property may be used to adjust the appearance of the current item.
+
+ \snippet doc/src/snippets/declarative/pathview/pathview.qml 1
+*/
+
+/*!
+ \qmlproperty model QtQuick2::PathView::model
+ This property holds the model providing data for the view.
+
+ The model provides a set of data that is used to create the items for the view.
+ For large or dynamic datasets the model is usually provided by a C++ model object.
+ Models can also be created directly in QML, using the ListModel element.
+
+ \sa {qmlmodels}{Data Models}
+*/
QVariant QSGPathView::model() const
{
Q_D(const QSGPathView);
@@ -426,12 +543,21 @@ void QSGPathView::setModel(const QVariant &model)
emit modelChanged();
}
+/*!
+ \qmlproperty int QtQuick2::PathView::count
+ This property holds the number of items in the model.
+*/
int QSGPathView::count() const
{
Q_D(const QSGPathView);
return d->model ? d->modelCount : 0;
}
+/*!
+ \qmlproperty Path QtQuick2::PathView::path
+ This property holds the path used to lay out the items.
+ For more information see the \l Path documentation.
+*/
QDeclarativePath *QSGPathView::path() const
{
Q_D(const QSGPathView);
@@ -458,6 +584,10 @@ void QSGPathView::setPath(QDeclarativePath *path)
emit pathChanged();
}
+/*!
+ \qmlproperty int QtQuick2::PathView::currentIndex
+ This property holds the index of the current item.
+*/
int QSGPathView::currentIndex() const
{
Q_D(const QSGPathView);
@@ -470,28 +600,31 @@ void QSGPathView::setCurrentIndex(int idx)
if (d->model && d->modelCount)
idx = qAbs(idx % d->modelCount);
if (d->model && idx != d->currentIndex) {
- if (d->modelCount) {
- int itemIndex = (d->currentIndex - d->firstIndex + d->modelCount) % d->modelCount;
- if (itemIndex < d->items.count()) {
- if (QSGItem *item = d->items.at(itemIndex)) {
- if (QSGPathViewAttached *att = d->attached(item))
- att->setIsCurrentItem(false);
- }
- }
+ if (d->currentItem) {
+ if (QSGPathViewAttached *att = d->attached(d->currentItem))
+ att->setIsCurrentItem(false);
+ d->releaseItem(d->currentItem);
}
d->currentItem = 0;
d->moveReason = QSGPathViewPrivate::SetIndex;
d->currentIndex = idx;
if (d->modelCount) {
- if (d->haveHighlightRange && d->highlightRangeMode == QSGPathView::StrictlyEnforceRange)
- d->snapToCurrent();
int itemIndex = (idx - d->firstIndex + d->modelCount) % d->modelCount;
if (itemIndex < d->items.count()) {
- d->currentItem = d->items.at(itemIndex);
+ d->currentItem = d->model->item(d->currentIndex, true);
d->currentItem->setFocus(true);
if (QSGPathViewAttached *att = d->attached(d->currentItem))
att->setIsCurrentItem(true);
+ } else {
+ d->currentItem = d->getItem(d->currentIndex, false);
+ d->updateItem(d->currentItem, d->currentIndex < d->firstIndex ? 0.0 : 1.0);
+ if (QSGPathViewAttached *att = d->attached(d->currentItem))
+ att->setIsCurrentItem(true);
+ if (d->model->completePending())
+ d->model->completeItem();
}
+ if (d->haveHighlightRange && d->highlightRangeMode == QSGPathView::StrictlyEnforceRange)
+ d->snapToCurrent();
d->currentItemOffset = d->positionOfIndex(d->currentIndex);
d->updateHighlight();
}
@@ -499,6 +632,19 @@ void QSGPathView::setCurrentIndex(int idx)
}
}
+QSGItem *QSGPathView::currentItem() const
+{
+ Q_D(const QSGPathView);
+ return d->currentItem;
+}
+
+/*!
+ \qmlmethod QtQuick2::PathView::incrementCurrentIndex()
+
+ Increments the current index.
+
+ \bold Note: methods should only be called after the Component has completed.
+*/
void QSGPathView::incrementCurrentIndex()
{
Q_D(QSGPathView);
@@ -506,6 +652,13 @@ void QSGPathView::incrementCurrentIndex()
setCurrentIndex(currentIndex()+1);
}
+/*!
+ \qmlmethod QtQuick2::PathView::decrementCurrentIndex()
+
+ Decrements the current index.
+
+ \bold Note: methods should only be called after the Component has completed.
+*/
void QSGPathView::decrementCurrentIndex()
{
Q_D(QSGPathView);
@@ -518,6 +671,12 @@ void QSGPathView::decrementCurrentIndex()
}
}
+/*!
+ \qmlproperty real QtQuick2::PathView::offset
+
+ The offset specifies how far along the path the items are from their initial positions.
+ This is a real number that ranges from 0.0 to the count of items in the model.
+*/
qreal QSGPathView::offset() const
{
Q_D(const QSGPathView);
@@ -552,6 +711,30 @@ void QSGPathViewPrivate::setAdjustedOffset(qreal o)
setOffset(o+offsetAdj);
}
+/*!
+ \qmlproperty Component QtQuick2::PathView::highlight
+ This property holds the component to use as the highlight.
+
+ An instance of the highlight component will be created for each view.
+ The geometry of the resultant component instance will be managed by the view
+ so as to stay with the current item.
+
+ The below example demonstrates how to make a simple highlight. Note the use
+ of the \l{PathView::onPath}{PathView.onPath} attached property to ensure that
+ the highlight is hidden when flicked away from the path.
+
+ \qml
+ Component {
+ Rectangle {
+ visible: PathView.onPath
+ // ...
+ }
+ }
+ \endqml
+
+ \sa highlightItem, highlightRangeMode
+*/
+
QDeclarativeComponent *QSGPathView::highlight() const
{
Q_D(const QSGPathView);
@@ -569,12 +752,54 @@ void QSGPathView::setHighlight(QDeclarativeComponent *highlight)
}
}
+/*!
+ \qmlproperty Item QtQuick2::PathView::highlightItem
+
+ \c highlightItem holds the highlight item, which was created
+ from the \l highlight component.
+
+ \sa highlight
+*/
QSGItem *QSGPathView::highlightItem()
{
Q_D(const QSGPathView);
return d->highlightItem;
}
-
+/*!
+ \qmlproperty real QtQuick2::PathView::preferredHighlightBegin
+ \qmlproperty real QtQuick2::PathView::preferredHighlightEnd
+ \qmlproperty enumeration QtQuick2::PathView::highlightRangeMode
+
+ These properties set the preferred range of the highlight (current item)
+ within the view. The preferred values must be in the range 0.0-1.0.
+
+ If highlightRangeMode is set to \e PathView.NoHighlightRange
+
+ If highlightRangeMode is set to \e PathView.ApplyRange the view will
+ attempt to maintain the highlight within the range, however
+ the highlight can move outside of the range at the ends of the path
+ or due to a mouse interaction.
+
+ If highlightRangeMode is set to \e PathView.StrictlyEnforceRange the highlight will never
+ move outside of the range. This means that the current item will change
+ if a keyboard or mouse action would cause the highlight to move
+ outside of the range.
+
+ Note that this is the correct way to influence where the
+ current item ends up when the view moves. For example, if you want the
+ currently selected item to be in the middle of the path, then set the
+ highlight range to be 0.5,0.5 and highlightRangeMode to PathView.StrictlyEnforceRange.
+ Then, when the path scrolls,
+ the currently selected item will be the item at that position. This also applies to
+ when the currently selected item changes - it will scroll to within the preferred
+ highlight range. Furthermore, the behaviour of the current item index will occur
+ whether or not a highlight exists.
+
+ The default value is \e PathView.StrictlyEnforceRange.
+
+ Note that a valid range requires preferredHighlightEnd to be greater
+ than or equal to preferredHighlightBegin.
+*/
qreal QSGPathView::preferredHighlightBegin() const
{
Q_D(const QSGPathView);
@@ -625,6 +850,15 @@ void QSGPathView::setHighlightRangeMode(HighlightRangeMode mode)
emit highlightRangeModeChanged();
}
+/*!
+ \qmlproperty int QtQuick2::PathView::highlightMoveDuration
+ This property holds the move animation duration of the highlight delegate.
+
+ If the highlightRangeMode is StrictlyEnforceRange then this property
+ determines the speed that the items move along the path.
+
+ The default value for the duration is 300ms.
+*/
int QSGPathView::highlightMoveDuration() const
{
Q_D(const QSGPathView);
@@ -640,6 +874,14 @@ void QSGPathView::setHighlightMoveDuration(int duration)
emit highlightMoveDurationChanged();
}
+/*!
+ \qmlproperty real QtQuick2::PathView::dragMargin
+ This property holds the maximum distance from the path that initiate mouse dragging.
+
+ By default the path can only be dragged by clicking on an item. If
+ dragMargin is greater than zero, a drag can be initiated by clicking
+ within dragMargin pixels of the path.
+*/
qreal QSGPathView::dragMargin() const
{
Q_D(const QSGPathView);
@@ -655,6 +897,12 @@ void QSGPathView::setDragMargin(qreal dragMargin)
emit dragMarginChanged();
}
+/*!
+ \qmlproperty real QtQuick2::PathView::flickDeceleration
+ This property holds the rate at which a flick will decelerate.
+
+ The default is 100.
+*/
qreal QSGPathView::flickDeceleration() const
{
Q_D(const QSGPathView);
@@ -670,6 +918,14 @@ void QSGPathView::setFlickDeceleration(qreal dec)
emit flickDecelerationChanged();
}
+/*!
+ \qmlproperty bool QtQuick2::PathView::interactive
+
+ A user cannot drag or flick a PathView that is not interactive.
+
+ This property is useful for temporarily disabling flicking. This allows
+ special interaction with PathView's children.
+*/
bool QSGPathView::isInteractive() const
{
Q_D(const QSGPathView);
@@ -687,18 +943,79 @@ void QSGPathView::setInteractive(bool interactive)
}
}
+/*!
+ \qmlproperty bool QtQuick2::PathView::moving
+
+ This property holds whether the view is currently moving
+ due to the user either dragging or flicking the view.
+*/
bool QSGPathView::isMoving() const
{
Q_D(const QSGPathView);
return d->moving;
}
+/*!
+ \qmlproperty bool QtQuick2::PathView::flicking
+
+ This property holds whether the view is currently moving
+ due to the user flicking the view.
+*/
bool QSGPathView::isFlicking() const
{
Q_D(const QSGPathView);
return d->flicking;
}
+/*!
+ \qmlsignal QtQuick2::PathView::onMovementStarted()
+
+ This handler is called when the view begins moving due to user
+ interaction.
+*/
+
+/*!
+ \qmlsignal QtQuick2::PathView::onMovementEnded()
+
+ This handler is called when the view stops moving due to user
+ interaction. If a flick was generated, this handler will
+ be triggered once the flick stops. If a flick was not
+ generated, the handler will be triggered when the
+ user stops dragging - i.e. a mouse or touch release.
+*/
+
+/*!
+ \qmlsignal QtQuick2::PathView::onFlickStarted()
+
+ This handler is called when the view is flicked. A flick
+ starts from the point that the mouse or touch is released,
+ while still in motion.
+*/
+
+/*!
+ \qmlsignal QtQuick2::PathView::onFlickEnded()
+
+ This handler is called when the view stops moving due to a flick.
+*/
+
+/*!
+ \qmlproperty Component QtQuick2::PathView::delegate
+
+ The delegate provides a template defining each item instantiated by the view.
+ The index is exposed as an accessible \c index property. Properties of the
+ model are also available depending upon the type of \l {qmlmodels}{Data Model}.
+
+ The number of elements in the delegate has a direct effect on the
+ flicking performance of the view when pathItemCount is specified. If at all possible, place functionality
+ that is not needed for the normal display of the delegate in a \l Loader which
+ can load additional elements when needed.
+
+ Note that the PathView will layout the items based on the size of the root
+ item in the delegate.
+
+ Here is an example delegate:
+ \snippet doc/src/snippets/declarative/pathview/pathview.qml 1
+*/
QDeclarativeComponent *QSGPathView::delegate() const
{
Q_D(const QSGPathView);
@@ -730,6 +1047,10 @@ void QSGPathView::setDelegate(QDeclarativeComponent *delegate)
}
}
+/*!
+ \qmlproperty int QtQuick2::PathView::pathItemCount
+ This property holds the number of items visible on the path at any one time.
+*/
int QSGPathView::pathItemCount() const
{
Q_D(const QSGPathView);
@@ -976,6 +1297,7 @@ bool QSGPathView::sendMouseEvent(QGraphicsSceneMouseEvent *event)
return d->stealMouse;
} else if (d->lastPosTime.isValid()) {
d->lastPosTime.invalidate();
+ d->fixOffset();
}
if (mouseEvent.type() == QEvent::GraphicsSceneMouseRelease)
d->stealMouse = false;
@@ -1000,6 +1322,18 @@ bool QSGPathView::childMouseEventFilter(QSGItem *i, QEvent *e)
return QSGItem::childMouseEventFilter(i, e);
}
+void QSGPathView::mouseUngrabEvent()
+{
+ Q_D(QSGPathView);
+ if (d->stealMouse) {
+ // if our mouse grab has been removed (probably by a Flickable),
+ // fix our state
+ d->stealMouse = false;
+ setKeepMouseGrab(false);
+ d->lastPosTime.invalidate();
+ }
+}
+
void QSGPathView::updatePolish()
{
QSGItem::updatePolish();
@@ -1079,12 +1413,8 @@ void QSGPathView::refill()
if (d->model->completePending())
item->setZ(idx+1);
if (d->currentIndex == idx) {
- item->setFocus(true);
- if (QSGPathViewAttached *att = d->attached(item))
- att->setIsCurrentItem(true);
currentVisible = true;
d->currentItemOffset = pos;
- d->currentItem = item;
}
if (d->items.count() == 0)
d->firstIndex = idx;
@@ -1108,12 +1438,8 @@ void QSGPathView::refill()
if (d->model->completePending())
item->setZ(idx+1);
if (d->currentIndex == idx) {
- item->setFocus(true);
- if (QSGPathViewAttached *att = d->attached(item))
- att->setIsCurrentItem(true);
currentVisible = true;
d->currentItemOffset = pos;
- d->currentItem = item;
}
d->items.prepend(item);
d->updateItem(item, pos);
@@ -1128,8 +1454,25 @@ void QSGPathView::refill()
}
}
- if (!currentVisible)
+ if (!currentVisible) {
d->currentItemOffset = 1.0;
+ if (d->currentItem) {
+ if (QSGPathViewAttached *att = d->attached(d->currentItem))
+ att->setOnPath(false);
+ } else if (d->currentIndex >= 0 && d->currentIndex < d->modelCount) {
+ d->currentItem = d->getItem(d->currentIndex, false);
+ d->updateItem(d->currentItem, d->currentIndex < d->firstIndex ? 0.0 : 1.0);
+ if (QSGPathViewAttached *att = d->attached(d->currentItem))
+ att->setIsCurrentItem(true);
+ if (d->model->completePending())
+ d->model->completeItem();
+ }
+ } else if (!d->currentItem) {
+ d->currentItem = d->model->item(d->currentIndex, true);
+ d->currentItem->setFocus(true);
+ if (QSGPathViewAttached *att = d->attached(d->currentItem))
+ att->setIsCurrentItem(true);
+ }
if (d->highlightItem && d->haveHighlightRange && d->highlightRangeMode == QSGPathView::StrictlyEnforceRange) {
d->updateItem(d->highlightItem, d->highlightRangeStart);
@@ -1193,6 +1536,8 @@ void QSGPathView::itemsRemoved(int modelIndex, int count)
if (d->currentItem) {
if (QSGPathViewAttached *att = d->attached(d->currentItem))
att->setIsCurrentItem(true);
+ d->releaseItem(d->currentItem);
+ d->currentItem = 0;
}
currentChanged = true;
}
@@ -1332,21 +1677,26 @@ void QSGPathViewPrivate::updateCurrent()
int idx = calcCurrentIndex();
if (model && idx != currentIndex) {
- int itemIndex = (currentIndex - firstIndex + modelCount) % modelCount;
- if (itemIndex < items.count()) {
- if (QSGItem *item = items.at(itemIndex)) {
- if (QSGPathViewAttached *att = attached(item))
- att->setIsCurrentItem(false);
- }
+ if (currentItem) {
+ if (QSGPathViewAttached *att = attached(currentItem))
+ att->setIsCurrentItem(false);
+ releaseItem(currentItem);
}
currentIndex = idx;
currentItem = 0;
- itemIndex = (idx - firstIndex + modelCount) % modelCount;
+ int itemIndex = (idx - firstIndex + modelCount) % modelCount;
if (itemIndex < items.count()) {
- currentItem = items.at(itemIndex);
+ currentItem = model->item(currentIndex, true);
currentItem->setFocus(true);
if (QSGPathViewAttached *att = attached(currentItem))
att->setIsCurrentItem(true);
+ } else if (currentIndex >= 0 && currentIndex < modelCount) {
+ currentItem = getItem(currentIndex, false);
+ updateItem(currentItem, currentIndex < firstIndex ? 0.0 : 1.0);
+ if (QSGPathViewAttached *att = attached(currentItem))
+ att->setIsCurrentItem(true);
+ if (model->completePending())
+ model->completeItem();
}
emit q->currentIndexChanged();
}
diff --git a/src/declarative/items/qsgpathview_p.h b/src/declarative/items/qsgpathview_p.h
index 31f2f6a113..a271e323cd 100644
--- a/src/declarative/items/qsgpathview_p.h
+++ b/src/declarative/items/qsgpathview_p.h
@@ -62,6 +62,7 @@ class Q_AUTOTEST_EXPORT QSGPathView : public QSGItem
Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
Q_PROPERTY(QDeclarativePath *path READ path WRITE setPath NOTIFY pathChanged)
Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+ Q_PROPERTY(QSGItem *currentItem READ currentItem NOTIFY currentIndexChanged)
Q_PROPERTY(qreal offset READ offset WRITE setOffset NOTIFY offsetChanged)
Q_PROPERTY(QDeclarativeComponent *highlight READ highlight WRITE setHighlight NOTIFY highlightChanged)
@@ -98,6 +99,8 @@ public:
int currentIndex() const;
void setCurrentIndex(int idx);
+ QSGItem *currentItem() const;
+
qreal offset() const;
void setOffset(qreal offset);
@@ -176,6 +179,7 @@ protected:
void mouseReleaseEvent(QGraphicsSceneMouseEvent *);
bool sendMouseEvent(QGraphicsSceneMouseEvent *event);
bool childMouseEventFilter(QSGItem *, QEvent *);
+ void mouseUngrabEvent();
void componentComplete();
private Q_SLOTS:
diff --git a/src/declarative/items/qsgpathview_p_p.h b/src/declarative/items/qsgpathview_p_p.h
index a133e80abc..1575c6c1ca 100644
--- a/src/declarative/items/qsgpathview_p_p.h
+++ b/src/declarative/items/qsgpathview_p_p.h
@@ -111,7 +111,7 @@ public:
}
}
- QSGItem *getItem(int modelIndex);
+ QSGItem *getItem(int modelIndex, bool onPath = true);
void releaseItem(QSGItem *item);
QSGPathViewAttached *attached(QSGItem *item);
void clear();
diff --git a/src/declarative/items/qsgpincharea.cpp b/src/declarative/items/qsgpincharea.cpp
index f86c18dfcf..54c32e5025 100644
--- a/src/declarative/items/qsgpincharea.cpp
+++ b/src/declarative/items/qsgpincharea.cpp
@@ -50,6 +50,102 @@
QT_BEGIN_NAMESPACE
+/*!
+ \qmlclass PinchEvent QSGPinchEvent
+ \inqmlmodule QtQuick 2
+ \ingroup qml-event-elements
+ \brief The PinchEvent object provides information about a pinch event.
+
+ \bold {The PinchEvent element was added in QtQuick 1.1}
+
+ The \c center, \c startCenter, \c previousCenter properties provide the center position between the two touch points.
+
+ The \c scale and \c previousScale properties provide the scale factor.
+
+ The \c angle, \c previousAngle and \c rotation properties provide the angle between the two points and the amount of rotation.
+
+ The \c point1, \c point2, \c startPoint1, \c startPoint2 properties provide the positions of the touch points.
+
+ The \c accepted property may be set to false in the \c onPinchStarted handler if the gesture should not
+ be handled.
+
+ \sa PinchArea
+*/
+
+/*!
+ \qmlproperty QPointF QtQuick2::PinchEvent::center
+ \qmlproperty QPointF QtQuick2::PinchEvent::startCenter
+ \qmlproperty QPointF QtQuick2::PinchEvent::previousCenter
+
+ These properties hold the position of the center point between the two touch points.
+
+ \list
+ \o \c center is the current center point
+ \o \c previousCenter is the center point of the previous event.
+ \o \c startCenter is the center point when the gesture began
+ \endlist
+*/
+
+/*!
+ \qmlproperty real QtQuick2::PinchEvent::scale
+ \qmlproperty real QtQuick2::PinchEvent::previousScale
+
+ These properties hold the scale factor determined by the change in distance between the two touch points.
+
+ \list
+ \o \c scale is the current scale factor.
+ \o \c previousScale is the scale factor of the previous event.
+ \endlist
+
+ When a pinch gesture is started, the scale is 1.0.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::PinchEvent::angle
+ \qmlproperty real QtQuick2::PinchEvent::previousAngle
+ \qmlproperty real QtQuick2::PinchEvent::rotation
+
+ These properties hold the angle between the two touch points.
+
+ \list
+ \o \c angle is the current angle between the two points in the range -180 to 180.
+ \o \c previousAngle is the angle of the previous event.
+ \o \c rotation is the total rotation since the pinch gesture started.
+ \endlist
+
+ When a pinch gesture is started, the rotation is 0.0.
+*/
+
+/*!
+ \qmlproperty QPointF QtQuick2::PinchEvent::point1
+ \qmlproperty QPointF QtQuick2::PinchEvent::startPoint1
+ \qmlproperty QPointF QtQuick2::PinchEvent::point2
+ \qmlproperty QPointF QtQuick2::PinchEvent::startPoint2
+
+ These properties provide the actual touch points generating the pinch.
+
+ \list
+ \o \c point1 and \c point2 hold the current positions of the points.
+ \o \c startPoint1 and \c startPoint2 hold the positions of the points when the second point was touched.
+ \endlist
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::PinchEvent::accepted
+
+ Setting this property to false in the \c PinchArea::onPinchStarted handler
+ will result in no further pinch events being generated, and the gesture
+ ignored.
+*/
+
+/*!
+ \qmlproperty int QtQuick2::PinchEvent::pointCount
+
+ Holds the number of points currently touched. The PinchArea will not react
+ until two touch points have initited a gesture, but will remain active until
+ all touch points have been released.
+*/
+
QSGPinch::QSGPinch()
: m_target(0), m_minScale(1.0), m_maxScale(1.0)
, m_minRotation(0.0), m_maxRotation(0.0)
@@ -63,6 +159,87 @@ QSGPinchAreaPrivate::~QSGPinchAreaPrivate()
delete pinch;
}
+/*!
+ \qmlclass PinchArea QSGPinchArea
+ \inqmlmodule QtQuick 2
+ \brief The PinchArea item enables simple pinch gesture handling.
+ \inherits Item
+
+ \bold {The PinchArea element was added in QtQuick 1.1}
+
+ A PinchArea is an invisible item that is typically used in conjunction with
+ a visible item in order to provide pinch gesture handling for that item.
+
+ The \l enabled property is used to enable and disable pinch handling for
+ the proxied item. When disabled, the pinch area becomes transparent to
+ mouse/touch events.
+
+ PinchArea can be used in two ways:
+
+ \list
+ \o setting a \c pinch.target to provide automatic interaction with an element
+ \o using the onPinchStarted, onPinchUpdated and onPinchFinished handlers
+ \endlist
+
+ \sa PinchEvent
+*/
+
+/*!
+ \qmlsignal QtQuick2::PinchArea::onPinchStarted()
+
+ This handler is called when the pinch area detects that a pinch gesture has started.
+
+ The \l {PinchEvent}{pinch} parameter provides information about the pinch gesture,
+ including the scale, center and angle of the pinch.
+
+ To ignore this gesture set the \c pinch.accepted property to false. The gesture
+ will be cancelled and no further events will be sent.
+*/
+
+/*!
+ \qmlsignal QtQuick2::PinchArea::onPinchUpdated()
+
+ This handler is called when the pinch area detects that a pinch gesture has changed.
+
+ The \l {PinchEvent}{pinch} parameter provides information about the pinch gesture,
+ including the scale, center and angle of the pinch.
+*/
+
+/*!
+ \qmlsignal QtQuick2::PinchArea::onPinchFinished()
+
+ This handler is called when the pinch area detects that a pinch gesture has finished.
+
+ The \l {PinchEvent}{pinch} parameter provides information about the pinch gesture,
+ including the scale, center and angle of the pinch.
+*/
+
+
+/*!
+ \qmlproperty Item QtQuick2::PinchArea::pinch.target
+ \qmlproperty bool QtQuick2::PinchArea::pinch.active
+ \qmlproperty real QtQuick2::PinchArea::pinch.minimumScale
+ \qmlproperty real QtQuick2::PinchArea::pinch.maximumScale
+ \qmlproperty real QtQuick2::PinchArea::pinch.minimumRotation
+ \qmlproperty real QtQuick2::PinchArea::pinch.maximumRotation
+ \qmlproperty enumeration QtQuick2::PinchArea::pinch.dragAxis
+ \qmlproperty real QtQuick2::PinchArea::pinch.minimumX
+ \qmlproperty real QtQuick2::PinchArea::pinch.maximumX
+ \qmlproperty real QtQuick2::PinchArea::pinch.minimumY
+ \qmlproperty real QtQuick2::PinchArea::pinch.maximumY
+
+ \c pinch provides a convenient way to make an item react to pinch gestures.
+
+ \list
+ \i \c pinch.target specifies the id of the item to drag.
+ \i \c pinch.active specifies if the target item is currently being dragged.
+ \i \c pinch.minimumScale and \c pinch.maximumScale limit the range of the Item::scale property.
+ \i \c pinch.minimumRotation and \c pinch.maximumRotation limit the range of the Item::rotation property.
+ \i \c pinch.dragAxis specifies whether dragging in not allowed (\c Pinch.NoDrag), can be done horizontally (\c Pinch.XAxis), vertically (\c Pinch.YAxis), or both (\c Pinch.XandYAxis)
+ \i \c pinch.minimum and \c pinch.maximum limit how far the target can be dragged along the corresponding axes.
+ \endlist
+*/
+
QSGPinchArea::QSGPinchArea(QSGItem *parent)
: QSGItem(*(new QSGPinchAreaPrivate), parent)
{
@@ -73,7 +250,12 @@ QSGPinchArea::QSGPinchArea(QSGItem *parent)
QSGPinchArea::~QSGPinchArea()
{
}
+/*!
+ \qmlproperty bool QtQuick2::PinchArea::enabled
+ This property holds whether the item accepts pinch gestures.
+ This property defaults to true.
+*/
bool QSGPinchArea::isEnabled() const
{
Q_D(const QSGPinchArea);
diff --git a/src/declarative/items/qsgpositioners.cpp b/src/declarative/items/qsgpositioners.cpp
index da3c7fea04..fca0aa1877 100644
--- a/src/declarative/items/qsgpositioners.cpp
+++ b/src/declarative/items/qsgpositioners.cpp
@@ -50,6 +50,7 @@
#include <private/qdeclarativestate_p.h>
#include <private/qdeclarativestategroup_p.h>
#include <private/qdeclarativestateoperations_p.h>
+#include <private/qdeclarativetransition_p.h>
QT_BEGIN_NAMESPACE
@@ -77,6 +78,22 @@ QSGBasePositioner::QSGBasePositioner(PositionerType at, QSGItem *parent)
Q_D(QSGBasePositioner);
d->init(at);
}
+/*!
+ \internal
+ \class QSGBasePositioner
+ \brief The QSGBasePositioner class provides a base for QSGGraphics layouts.
+
+ To create a QSGGraphics Positioner, simply subclass QSGBasePositioner and implement
+ doLayout(), which is automatically called when the layout might need
+ updating. In doLayout() use the setX and setY functions from QSGBasePositioner, and the
+ base class will apply the positions along with the appropriate transitions. The items to
+ position are provided in order as the protected member positionedItems.
+
+ You also need to set a PositionerType, to declare whether you are positioning the x, y or both
+ for the child items. Depending on the chosen type, only x or y changes will be applied.
+
+ Note that the subclass is responsible for adding the spacing in between items.
+*/
QSGBasePositioner::QSGBasePositioner(QSGBasePositionerPrivate &dd, PositionerType at, QSGItem *parent)
: QSGImplicitSizeItem(dd, parent)
@@ -213,7 +230,8 @@ void QSGBasePositioner::prePositioning()
}
QSizeF contentSize(0,0);
doPositioning(&contentSize);
- if(d->addTransition || d->moveTransition)
+ updateAttachedProperties();
+ if (!d->addActions.isEmpty() || !d->moveActions.isEmpty())
finishApplyTransitions();
d->doingPositioning = false;
//Set implicit size to the size of its children
@@ -226,12 +244,12 @@ void QSGBasePositioner::positionX(int x, const PositionedItem &target)
Q_D(QSGBasePositioner);
if(d->type == Horizontal || d->type == Both){
if (target.isNew) {
- if (!d->addTransition)
+ if (!d->addTransition || !d->addTransition->enabled())
target.item->setX(x);
else
d->addActions << QDeclarativeAction(target.item, QLatin1String("x"), QVariant(x));
} else if (x != target.item->x()) {
- if (!d->moveTransition)
+ if (!d->moveTransition || !d->moveTransition->enabled())
target.item->setX(x);
else
d->moveActions << QDeclarativeAction(target.item, QLatin1String("x"), QVariant(x));
@@ -244,12 +262,12 @@ void QSGBasePositioner::positionY(int y, const PositionedItem &target)
Q_D(QSGBasePositioner);
if(d->type == Vertical || d->type == Both){
if (target.isNew) {
- if (!d->addTransition)
+ if (!d->addTransition || !d->addTransition->enabled())
target.item->setY(y);
else
d->addActions << QDeclarativeAction(target.item, QLatin1String("y"), QVariant(y));
} else if (y != target.item->y()) {
- if (!d->moveTransition)
+ if (!d->moveTransition || !d->moveTransition->enabled())
target.item->setY(y);
else
d->moveActions << QDeclarativeAction(target.item, QLatin1String("y"), QVariant(y));
@@ -268,6 +286,233 @@ void QSGBasePositioner::finishApplyTransitions()
d->moveActions.clear();
}
+QSGPositionerAttached *QSGBasePositioner::qmlAttachedProperties(QObject *obj)
+{
+ return new QSGPositionerAttached(obj);
+}
+
+void QSGBasePositioner::updateAttachedProperties(QSGPositionerAttached *specificProperty, QSGItem *specificPropertyOwner) const
+{
+ // If this function is deemed too expensive or shows up in profiles, it could
+ // be changed to run only when there are attached properties present. This
+ // could be a flag in the positioner that is set by the attached property
+ // constructor.
+ QSGPositionerAttached *prevLastProperty = 0;
+ QSGPositionerAttached *lastProperty = 0;
+
+ int visibleItemIndex = 0;
+ for (int ii = 0; ii < positionedItems.count(); ++ii) {
+ const PositionedItem &child = positionedItems.at(ii);
+ if (!child.item)
+ continue;
+
+ QSGPositionerAttached *property = 0;
+
+ if (specificProperty) {
+ if (specificPropertyOwner == child.item) {
+ property = specificProperty;
+ }
+ } else {
+ property = static_cast<QSGPositionerAttached *>(qmlAttachedPropertiesObject<QSGBasePositioner>(child.item, false));
+ }
+
+ if (child.isVisible) {
+ if (property) {
+ property->setIndex(visibleItemIndex);
+ property->setIsFirstItem(visibleItemIndex == 0);
+
+ if (property->isLastItem())
+ prevLastProperty = property;
+ }
+
+ lastProperty = property;
+ ++visibleItemIndex;
+ } else if (property) {
+ property->setIndex(-1);
+ property->setIsFirstItem(false);
+ property->setIsLastItem(false);
+ }
+ }
+
+ if (prevLastProperty && prevLastProperty != lastProperty)
+ prevLastProperty->setIsLastItem(false);
+ if (lastProperty)
+ lastProperty->setIsLastItem(true);
+}
+
+/*!
+ \qmlclass Positioner QSGPositionerAttached
+ \inqmlmodule QtQuick 2
+ \ingroup qml-positioning-elements
+ \brief The Positioner type provides attached properties that contain details on where an item exists in a positioner.
+
+ Positioner items (such as Column, Row, Flow and Grid) provide automatic layout
+ for child items. Attaching this property allows a child item to determine
+ where it exists within the positioner.
+*/
+
+QSGPositionerAttached::QSGPositionerAttached(QObject *parent) : QObject(parent), m_index(-1), m_isFirstItem(false), m_isLastItem(false)
+{
+ QSGItem *attachedItem = qobject_cast<QSGItem *>(parent);
+ if (attachedItem) {
+ QSGBasePositioner *positioner = qobject_cast<QSGBasePositioner *>(attachedItem->parent());
+ if (positioner) {
+ positioner->updateAttachedProperties(this, attachedItem);
+ }
+ }
+}
+
+/*!
+ \qmlattachedproperty Item QtQuick2::Positioner::index
+
+ This property allows the item to determine
+ its index within the positioner.
+*/
+void QSGPositionerAttached::setIndex(int index)
+{
+ if (m_index == index)
+ return;
+ m_index = index;
+ emit indexChanged();
+}
+
+/*!
+ \qmlattachedproperty Item QtQuick2::Positioner::isFirstItem
+ \qmlattachedproperty Item QtQuick2::Positioner::isLastItem
+
+ These properties allow the item to determine if it
+ is the first or last item in the positioner, respectively.
+*/
+void QSGPositionerAttached::setIsFirstItem(bool isFirstItem)
+{
+ if (m_isFirstItem == isFirstItem)
+ return;
+ m_isFirstItem = isFirstItem;
+ emit isFirstItemChanged();
+}
+
+void QSGPositionerAttached::setIsLastItem(bool isLastItem)
+{
+ if (m_isLastItem == isLastItem)
+ return;
+ m_isLastItem = isLastItem;
+ emit isLastItemChanged();
+}
+
+/*!
+ \qmlclass Column QSGColumn
+ \inqmlmodule QtQuick 2
+ \ingroup qml-positioning-elements
+ \brief The Column item arranges its children vertically.
+ \inherits Item
+
+ The Column item positions its child items so that they are vertically
+ aligned and not overlapping.
+
+ Spacing between items can be added using the \l spacing property.
+ Transitions can be used for cases where items managed by a Column are
+ added or moved. These are stored in the \l add and \l move properties
+ respectively.
+
+ See \l{Using QML Positioner and Repeater Items} for more details about this item and other
+ related items.
+
+ \section1 Example Usage
+
+ The following example positions differently shaped rectangles using a Column
+ item.
+
+ \image verticalpositioner_example.png
+
+ \snippet doc/src/snippets/declarative/column/vertical-positioner.qml document
+
+ \section1 Using Transitions
+
+ Transitions can be used to animate items that are added to, moved within,
+ or removed from a Column item. The \l add and \l move properties can be set to
+ the transitions that will be applied when items are added to, removed from,
+ or re-positioned within a Column item.
+
+ The use of transitions with positioners is described in more detail in the
+ \l{Using QML Positioner and Repeater Items#Using Transitions}{Using QML
+ Positioner and Repeater Items} document.
+
+ \image verticalpositioner_transition.gif
+
+ \qml
+ Column {
+ spacing: 2
+ add: Transition {
+ // Define an animation for adding a new item...
+ }
+ move: Transition {
+ // Define an animation for moving items within the column...
+ }
+ // ...
+ }
+ \endqml
+
+ \section1 Limitations
+
+ Note that the positioner assumes that the x and y positions of its children
+ will not change. If you manually change the x or y properties in script, bind
+ the x or y properties, use anchors on a child of a positioner, or have the
+ height of a child depend on the position of a child, then the
+ positioner may exhibit strange behavior. If you need to perform any of these
+ actions, consider positioning the items without the use of a Column.
+
+ Items with a width or height of 0 will not be positioned.
+
+ \sa Row, Grid, Flow, Positioner, {declarative/positioners}{Positioners example}
+*/
+/*!
+ \qmlproperty Transition QtQuick2::Column::add
+
+ This property holds the transition to be applied when adding an
+ item to the positioner. The transition will only be applied to the
+ added item(s). Positioner transitions will only affect the
+ position (x, y) of items.
+
+ For a positioner, adding an item can mean that either the object
+ has been created or reparented, and thus is now a child or the
+ positioner, or that the object has had its opacity increased from
+ zero, and thus is now visible.
+
+ \sa move
+*/
+/*!
+ \qmlproperty Transition QtQuick2::Column::move
+
+ This property holds the transition to apply when moving an item
+ within the positioner. Positioner transitions will only affect
+ the position (x, y) of items.
+
+ This transition can be performed when other items are added or removed
+ from the positioner, or when items resize themselves.
+
+ \image positioner-move.gif
+
+ \qml
+ Column {
+ move: Transition {
+ NumberAnimation {
+ properties: "y"
+ duration: 1000
+ }
+ }
+ }
+ \endqml
+
+ \sa add, {declarative/positioners}{Positioners example}
+*/
+/*!
+ \qmlproperty int QtQuick2::Column::spacing
+
+ The spacing is the amount in pixels left empty between adjacent
+ items. The default spacing is 0.
+
+ \sa Grid::spacing
+*/
QSGColumn::QSGColumn(QSGItem *parent)
: QSGBasePositioner(Vertical, parent)
{
@@ -288,10 +533,11 @@ void QSGColumn::doPositioning(QSizeF *contentSize)
contentSize->setWidth(qMax(contentSize->width(), child.item->width()));
voffset += child.item->height();
- if (ii != positionedItems.count() - 1)
- voffset += spacing();
+ voffset += spacing();
}
+ if (voffset != 0)//If we positioned any items, undo the spacing from the last item
+ voffset -= spacing();
contentSize->setHeight(voffset);
}
@@ -318,11 +564,119 @@ void QSGColumn::reportConflictingAnchors()
qmlInfo(this) << "Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column";
}
}
+/*!
+ \qmlclass Row QSGRow
+ \inqmlmodule QtQuick 2
+ \ingroup qml-positioning-elements
+ \brief The Row item arranges its children horizontally.
+ \inherits Item
+
+ The Row item positions its child items so that they are horizontally
+ aligned and not overlapping.
+
+ Use \l spacing to set the spacing between items in a Row, and use the
+ \l add and \l move properties to set the transitions that should be applied
+ when items are added to, removed from, or re-positioned within the Row.
+
+ See \l{Using QML Positioner and Repeater Items} for more details about this item and other
+ related items.
+
+ \section1 Example Usage
+
+ The following example lays out differently shaped rectangles using a Row.
+
+ \image horizontalpositioner_example.png
+
+ \snippet doc/src/snippets/declarative/row/row.qml document
+
+ \section1 Using Transitions
+
+ Transitions can be used to animate items that are added to, moved within,
+ or removed from a Grid item. The \l add and \l move properties can be set to
+ the transitions that will be applied when items are added to, removed from,
+ or re-positioned within a Row item.
+
+ \section1 Limitations
+
+ Note that the positioner assumes that the x and y positions of its children
+ will not change. If you manually change the x or y properties in script, bind
+ the x or y properties, use anchors on a child of a positioner, or have the
+ width of a child depend on the position of a child, then the
+ positioner may exhibit strange behaviour. If you need to perform any of these
+ actions, consider positioning the items without the use of a Row.
+
+ Items with a width or height of 0 will not be positioned.
+
+ \sa Column, Grid, Flow, Positioner, {declarative/positioners}{Positioners example}
+*/
+/*!
+ \qmlproperty Transition QtQuick2::Row::add
+
+ This property holds the transition to be applied when adding an
+ item to the positioner. The transition will only be applied to the
+ added item(s). Positioner transitions will only affect the
+ position (x, y) of items.
+
+ For a positioner, adding an item can mean that either the object
+ has been created or reparented, and thus is now a child or the
+ positioner, or that the object has had its opacity increased from
+ zero, and thus is now visible.
+
+ \sa move
+*/
+/*!
+ \qmlproperty Transition QtQuick2::Row::move
+
+ This property holds the transition to be applied when moving an
+ item within the positioner. Positioner transitions will only affect
+ the position (x, y) of items.
+
+ This transition can be performed when other items are added or removed
+ from the positioner, or when items resize themselves.
+
+ \qml
+ Row {
+ id: positioner
+ move: Transition {
+ NumberAnimation {
+ properties: "x"
+ duration: 1000
+ }
+ }
+ }
+ \endqml
+
+ \sa add, {declarative/positioners}{Positioners example}
+*/
+/*!
+ \qmlproperty int QtQuick2::Row::spacing
+
+ The spacing is the amount in pixels left empty between adjacent
+ items. The default spacing is 0.
+
+ \sa Grid::spacing
+*/
QSGRow::QSGRow(QSGItem *parent)
: QSGBasePositioner(Horizontal, parent)
{
}
+/*!
+ \qmlproperty enumeration QtQuick2::Row::layoutDirection
+
+ This property holds the layoutDirection of the row.
+
+ Possible values:
+
+ \list
+ \o Qt.LeftToRight (default) - Items are laid out from left to right. If the width of the row is explicitly set,
+ the left anchor remains to the left of the row.
+ \o Qt.RightToLeft - Items are laid out from right to left. If the width of the row is explicitly set,
+ the right anchor remains to the right of the row.
+ \endlist
+
+ \sa Grid::layoutDirection, Flow::layoutDirection, {declarative/righttoleft/layoutdirection}{Layout directions example}
+*/
Qt::LayoutDirection QSGRow::layoutDirection() const
{
@@ -344,6 +698,16 @@ void QSGRow::setLayoutDirection(Qt::LayoutDirection layoutDirection)
emit effectiveLayoutDirectionChanged();
}
}
+/*!
+ \qmlproperty enumeration QtQuick2::Row::effectiveLayoutDirection
+ This property holds the effective layout direction of the row positioner.
+
+ When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
+ the visual layout direction of the row positioner will be mirrored. However, the
+ property \l {Row::layoutDirection}{layoutDirection} will remain unchanged.
+
+ \sa Row::layoutDirection, {LayoutMirroring}{LayoutMirroring}
+*/
Qt::LayoutDirection QSGRow::effectiveLayoutDirection() const
{
@@ -371,10 +735,11 @@ void QSGRow::doPositioning(QSizeF *contentSize)
contentSize->setHeight(qMax(contentSize->height(), child.item->height()));
hoffset += child.item->width();
- if (ii != positionedItems.count() - 1)
- hoffset += spacing();
+ hoffset += spacing();
}
+ if (hoffset != 0)//If we positioned any items, undo the extra spacing from the last item
+ hoffset -= spacing();
contentSize->setWidth(hoffset);
if (d->isLeftToRight())
@@ -421,11 +786,138 @@ void QSGRow::reportConflictingAnchors()
qmlInfo(this) << "Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row";
}
+/*!
+ \qmlclass Grid QSGGrid
+ \inqmlmodule QtQuick 2
+ \ingroup qml-positioning-elements
+ \brief The Grid item positions its children in a grid.
+ \inherits Item
+
+ The Grid item positions its child items so that they are
+ aligned in a grid and are not overlapping.
+
+ The grid positioner calculates a grid of rectangular cells of sufficient
+ size to hold all items, placing the items in the cells, from left to right
+ and top to bottom. Each item is positioned in the top-left corner of its
+ cell with position (0, 0).
+
+ A Grid defaults to four columns, and as many rows as are necessary to
+ fit all child items. The number of rows and columns can be constrained
+ by setting the \l rows and \l columns properties.
+
+ Spacing can be added between child items by setting the \l spacing
+ property. The amount of spacing applied will be the same in the
+ horizontal and vertical directions.
+
+ See \l{Using QML Positioner and Repeater Items} for more details about this item and other
+ related items.
+
+ \section1 Example Usage
+
+ The following example demonstrates this.
+
+ \image gridLayout_example.png
+
+ \snippet doc/src/snippets/declarative/grid/grid.qml document
+
+ \section1 Using Transitions
+
+ Transitions can be used to animate items that are added to, moved within,
+ or removed from a Grid item. The \l add and \l move properties can be set to
+ the transitions that will be applied when items are added to, removed from,
+ or re-positioned within a Grid item.
+
+ \section1 Limitations
+
+ Note that the positioner assumes that the x and y positions of its children
+ will not change. If you manually change the x or y properties in script, bind
+ the x or y properties, use anchors on a child of a positioner, or have the
+ width or height of a child depend on the position of a child, then the
+ positioner may exhibit strange behaviour. If you need to perform any of these
+ actions, consider positioning the items without the use of a Grid.
+
+ Items with a width or height of 0 will not be positioned.
+
+ \sa Flow, Row, Column, Positioner, {declarative/positioners}{Positioners example}
+*/
+/*!
+ \qmlproperty Transition QtQuick2::Grid::add
+
+ This property holds the transition to be applied when adding an
+ item to the positioner. The transition will only be applied to the
+ added item(s). Positioner transitions will only affect the
+ position (x, y) of items.
+
+ For a positioner, adding an item can mean that either the object
+ has been created or reparented, and thus is now a child or the
+ positioner, or that the object has had its opacity increased from
+ zero, and thus is now visible.
+
+ \sa move
+*/
+/*!
+ \qmlproperty Transition QtQuick2::Grid::move
+
+ This property holds the transition to be applied when moving an
+ item within the positioner. Positioner transitions will only affect
+ the position (x, y) of items.
+
+ This transition can be performed when other items are added or removed
+ from the positioner, or when items resize themselves.
+
+ \qml
+ Grid {
+ move: Transition {
+ NumberAnimation {
+ properties: "x,y"
+ duration: 1000
+ }
+ }
+ }
+ \endqml
+
+ \sa add, {declarative/positioners}{Positioners example}
+*/
+/*!
+ \qmlproperty int QtQuick2::Grid::spacing
+
+ The spacing is the amount in pixels left empty between adjacent
+ items. The default spacing is 0.
+
+ The below example places a Grid containing a red, a blue and a
+ green rectangle on a gray background. The area the grid positioner
+ occupies is colored white. The positioner on the left has the
+ no spacing (the default), and the positioner on the right has
+ a spacing of 6.
+
+ \inlineimage qml-grid-no-spacing.png
+ \inlineimage qml-grid-spacing.png
+
+ \sa rows, columns
+*/
QSGGrid::QSGGrid(QSGItem *parent) :
- QSGBasePositioner(Both, parent), m_rows(-1), m_columns(-1), m_flow(LeftToRight)
+ QSGBasePositioner(Both, parent), m_rows(-1), m_columns(-1), m_rowSpacing(-1), m_columnSpacing(-1), m_flow(LeftToRight)
{
}
+/*!
+ \qmlproperty int QtQuick2::Grid::columns
+
+ This property holds the number of columns in the grid. The default
+ number of columns is 4.
+
+ If the grid does not have enough items to fill the specified
+ number of columns, some columns will be of zero width.
+*/
+
+/*!
+ \qmlproperty int QtQuick2::Grid::rows
+ This property holds the number of rows in the grid.
+
+ If the grid does not have enough items to fill the specified
+ number of rows, some rows will be of zero width.
+*/
+
void QSGGrid::setColumns(const int columns)
{
if (columns == m_columns)
@@ -444,6 +936,19 @@ void QSGGrid::setRows(const int rows)
emit rowsChanged();
}
+/*!
+ \qmlproperty enumeration QtQuick2::Grid::flow
+ This property holds the flow of the layout.
+
+ Possible values are:
+
+ \list
+ \o Grid.LeftToRight (default) - Items are positioned next to
+ each other in the \l layoutDirection, then wrapped to the next line.
+ \o Grid.TopToBottom - Items are positioned next to each
+ other from top to bottom, then wrapped to the next column.
+ \endlist
+*/
QSGGrid::Flow QSGGrid::flow() const
{
return m_flow;
@@ -458,6 +963,58 @@ void QSGGrid::setFlow(Flow flow)
}
}
+/*!
+ \qmlproperty int QtQuick2::Grid::rowSpacing
+
+ This property holds the spacing in pixels between rows.
+
+ \sa columnSpacing
+ \since QtQuick2.0
+*/
+void QSGGrid::setRowSpacing(const int rowSpacing)
+{
+ if (rowSpacing == m_rowSpacing)
+ return;
+ m_rowSpacing = rowSpacing;
+ prePositioning();
+ emit rowSpacingChanged();
+}
+
+/*!
+ \qmlproperty int QtQuick2::Grid::columnSpacing
+
+ This property holds the spacing in pixels between columns.
+
+ \sa rowSpacing
+ \since QtQuick2.0
+*/
+void QSGGrid::setColumnSpacing(const int columnSpacing)
+{
+ if (columnSpacing == m_columnSpacing)
+ return;
+ m_columnSpacing = columnSpacing;
+ prePositioning();
+ emit columnSpacingChanged();
+}
+
+/*!
+ \qmlproperty enumeration QtQuick2::Grid::layoutDirection
+
+ This property holds the layout direction of the layout.
+
+ Possible values are:
+
+ \list
+ \o Qt.LeftToRight (default) - Items are positioned from the top to bottom,
+ and left to right. The flow direction is dependent on the
+ \l Grid::flow property.
+ \o Qt.RightToLeft - Items are positioned from the top to bottom,
+ and right to left. The flow direction is dependent on the
+ \l Grid::flow property.
+ \endlist
+
+ \sa Flow::layoutDirection, Row::layoutDirection, {declarative/righttoleft/layoutdirection}{Layout directions example}
+*/
Qt::LayoutDirection QSGGrid::layoutDirection() const
{
return QSGBasePositionerPrivate::getLayoutDirection(this);
@@ -479,6 +1036,16 @@ void QSGGrid::setLayoutDirection(Qt::LayoutDirection layoutDirection)
}
}
+/*!
+ \qmlproperty enumeration QtQuick2::Grid::effectiveLayoutDirection
+ This property holds the effective layout direction of the grid positioner.
+
+ When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
+ the visual layout direction of the grid positioner will be mirrored. However, the
+ property \l {Grid::layoutDirection}{layoutDirection} will remain unchanged.
+
+ \sa Grid::layoutDirection, {LayoutMirroring}{LayoutMirroring}
+*/
Qt::LayoutDirection QSGGrid::effectiveLayoutDirection() const
{
return QSGBasePositionerPrivate::getEffectiveLayoutDirection(this);
@@ -550,17 +1117,25 @@ void QSGGrid::doPositioning(QSizeF *contentSize)
}
}
+ int columnSpacing = m_columnSpacing;
+ if (columnSpacing == -1)
+ columnSpacing = spacing();
+
+ int rowSpacing = m_rowSpacing;
+ if (rowSpacing == -1)
+ rowSpacing = spacing();
+
int widthSum = 0;
for (int j=0; j < maxColWidth.size(); j++){
if (j)
- widthSum += spacing();
+ widthSum += columnSpacing;
widthSum += maxColWidth[j];
}
int heightSum = 0;
for (int i=0; i < maxRowHeight.size(); i++){
if (i)
- heightSum += spacing();
+ heightSum += rowSpacing;
heightSum += maxRowHeight[i];
}
@@ -591,13 +1166,13 @@ void QSGGrid::doPositioning(QSizeF *contentSize)
if (m_flow == LeftToRight) {
if (d->isLeftToRight())
- xoffset += maxColWidth[curCol]+spacing();
+ xoffset += maxColWidth[curCol]+columnSpacing;
else
- xoffset -= maxColWidth[curCol]+spacing();
+ xoffset -= maxColWidth[curCol]+columnSpacing;
curCol++;
curCol%=c;
if (!curCol){
- yoffset += maxRowHeight[curRow]+spacing();
+ yoffset += maxRowHeight[curRow]+rowSpacing;
if (d->isLeftToRight())
xoffset = 0;
else
@@ -607,14 +1182,14 @@ void QSGGrid::doPositioning(QSizeF *contentSize)
break;
}
} else {
- yoffset+=maxRowHeight[curRow]+spacing();
+ yoffset+=maxRowHeight[curRow]+rowSpacing;
curRow++;
curRow%=r;
if (!curRow){
if (d->isLeftToRight())
- xoffset += maxColWidth[curCol]+spacing();
+ xoffset += maxColWidth[curCol]+columnSpacing;
else
- xoffset -= maxColWidth[curCol]+spacing();
+ xoffset -= maxColWidth[curCol]+columnSpacing;
yoffset=0;
curCol++;
if (curCol>=c)
@@ -641,6 +1216,105 @@ void QSGGrid::reportConflictingAnchors()
qmlInfo(this) << "Cannot specify anchors for items inside Grid";
}
+/*!
+ \qmlclass Flow QSGFlow
+ \inqmlmodule QtQuick 2
+ \ingroup qml-positioning-elements
+ \brief The Flow item arranges its children side by side, wrapping as necessary.
+ \inherits Item
+
+ The Flow item positions its child items like words on a page, wrapping them
+ to create rows or columns of items that do not overlap.
+
+ Spacing between items can be added using the \l spacing property.
+ Transitions can be used for cases where items managed by a Column are
+ added or moved. These are stored in the \l add and \l move properties
+ respectively.
+
+ See \l{Using QML Positioner and Repeater Items} for more details about this item and other
+ related items.
+
+ \section1 Example Usage
+
+ The following example positions \l Text items within a parent item using
+ a Flow item.
+
+ \image qml-flow-snippet.png
+
+ \snippet doc/src/snippets/declarative/flow.qml flow item
+
+ \section1 Using Transitions
+
+ Transitions can be used to animate items that are added to, moved within,
+ or removed from a Flow item. The \l add and \l move properties can be set to
+ the transitions that will be applied when items are added to, removed from,
+ or re-positioned within a Flow item.
+
+ The use of transitions with positioners is described in more detail in the
+ \l{Using QML Positioner and Repeater Items#Using Transitions}{Using QML
+ Positioner and Repeater Items} document.
+
+ \section1 Limitations
+
+ Note that the positioner assumes that the x and y positions of its children
+ will not change. If you manually change the x or y properties in script, bind
+ the x or y properties, use anchors on a child of a positioner, or have the
+ width or height of a child depend on the position of a child, then the
+ positioner may exhibit strange behaviour. If you need to perform any of these
+ actions, consider positioning the items without the use of a Flow.
+
+ Items with a width or height of 0 will not be positioned.
+
+ \sa Column, Row, Grid, Positioner, {declarative/positioners}{Positioners example}
+*/
+/*!
+ \qmlproperty Transition QtQuick2::Flow::add
+
+ This property holds the transition to be applied when adding an
+ item to the positioner. The transition will only be applied to the
+ added item(s). Positioner transitions will only affect the
+ position (x, y) of items.
+
+ For a positioner, adding an item can mean that either the object
+ has been created or reparented, and thus is now a child or the
+ positioner, or that the object has had its opacity increased from
+ zero, and thus is now visible.
+
+ \sa move
+*/
+/*!
+ \qmlproperty Transition QtQuick2::Flow::move
+
+ This property holds the transition to be applied when moving an
+ item within the positioner. Positioner transitions will only affect
+ the position (x, y) of items.
+
+ This transition can be performed when other items are added or removed
+ from the positioner, or when items resize themselves.
+
+ \qml
+ Flow {
+ id: positioner
+ move: Transition {
+ NumberAnimation {
+ properties: "x,y"
+ ease: "easeOutBounce"
+ }
+ }
+ }
+ \endqml
+
+ \sa add, {declarative/positioners}{Positioners example}
+*/
+/*!
+ \qmlproperty int QtQuick2::Flow::spacing
+
+ spacing is the amount in pixels left empty between each adjacent
+ item, and defaults to 0.
+
+ \sa Grid::spacing
+*/
+
class QSGFlowPrivate : public QSGBasePositionerPrivate
{
Q_DECLARE_PUBLIC(QSGFlow)
@@ -661,6 +1335,21 @@ QSGFlow::QSGFlow(QSGItem *parent)
d->addItemChangeListener(d, QSGItemPrivate::Geometry);
}
+/*!
+ \qmlproperty enumeration QtQuick2::Flow::flow
+ This property holds the flow of the layout.
+
+ Possible values are:
+
+ \list
+ \o Flow.LeftToRight (default) - Items are positioned next to
+ to each other according to the \l layoutDirection until the width of the Flow
+ is exceeded, then wrapped to the next line.
+ \o Flow.TopToBottom - Items are positioned next to each
+ other from top to bottom until the height of the Flow is exceeded,
+ then wrapped to the next column.
+ \endlist
+*/
QSGFlow::Flow QSGFlow::flow() const
{
Q_D(const QSGFlow);
@@ -677,6 +1366,25 @@ void QSGFlow::setFlow(Flow flow)
}
}
+/*!
+ \qmlproperty enumeration QtQuick2::Flow::layoutDirection
+
+ This property holds the layout direction of the layout.
+
+ Possible values are:
+
+ \list
+ \o Qt.LeftToRight (default) - Items are positioned from the top to bottom,
+ and left to right. The flow direction is dependent on the
+ \l Flow::flow property.
+ \o Qt.RightToLeft - Items are positioned from the top to bottom,
+ and right to left. The flow direction is dependent on the
+ \l Flow::flow property.
+ \endlist
+
+ \sa Grid::layoutDirection, Row::layoutDirection, {declarative/righttoleft/layoutdirection}{Layout directions example}
+*/
+
Qt::LayoutDirection QSGFlow::layoutDirection() const
{
Q_D(const QSGFlow);
@@ -694,6 +1402,17 @@ void QSGFlow::setLayoutDirection(Qt::LayoutDirection layoutDirection)
}
}
+/*!
+ \qmlproperty enumeration QtQuick2::Flow::effectiveLayoutDirection
+ This property holds the effective layout direction of the flow positioner.
+
+ When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
+ the visual layout direction of the grid positioner will be mirrored. However, the
+ property \l {Flow::layoutDirection}{layoutDirection} will remain unchanged.
+
+ \sa Flow::layoutDirection, {LayoutMirroring}{LayoutMirroring}
+*/
+
Qt::LayoutDirection QSGFlow::effectiveLayoutDirection() const
{
return QSGBasePositionerPrivate::getEffectiveLayoutDirection(this);
diff --git a/src/declarative/items/qsgpositioners_p.h b/src/declarative/items/qsgpositioners_p.h
index a23c9d446c..7200b6da8d 100644
--- a/src/declarative/items/qsgpositioners_p.h
+++ b/src/declarative/items/qsgpositioners_p.h
@@ -59,6 +59,37 @@ QT_MODULE(Declarative)
class QSGBasePositionerPrivate;
+class QSGPositionerAttached : public QObject
+{
+ Q_OBJECT
+
+public:
+ QSGPositionerAttached(QObject *parent);
+
+ Q_PROPERTY(int index READ index NOTIFY indexChanged)
+ Q_PROPERTY(bool isFirstItem READ isFirstItem NOTIFY isFirstItemChanged)
+ Q_PROPERTY(bool isLastItem READ isLastItem NOTIFY isLastItemChanged)
+
+ int index() const { return m_index; }
+ void setIndex(int index);
+
+ bool isFirstItem() const { return m_isFirstItem; }
+ void setIsFirstItem(bool isFirstItem);
+
+ bool isLastItem() const { return m_isLastItem; }
+ void setIsLastItem(bool isLastItem);
+
+Q_SIGNALS:
+ void indexChanged();
+ void isFirstItemChanged();
+ void isLastItemChanged();
+
+private:
+ int m_index;
+ bool m_isFirstItem;
+ bool m_isLastItem;
+};
+
class Q_DECLARATIVE_PRIVATE_EXPORT QSGBasePositioner : public QSGImplicitSizeItem
{
Q_OBJECT
@@ -80,6 +111,10 @@ public:
QDeclarativeTransition *add() const;
void setAdd(QDeclarativeTransition *);
+ static QSGPositionerAttached *qmlAttachedProperties(QObject *obj);
+
+ void updateAttachedProperties(QSGPositionerAttached *specificProperty = 0, QSGItem *specificPropertyOwner = 0) const;
+
protected:
QSGBasePositioner(QSGBasePositionerPrivate &dd, PositionerType at, QSGItem *parent);
virtual void componentComplete();
@@ -120,6 +155,7 @@ class Q_AUTOTEST_EXPORT QSGColumn : public QSGBasePositioner
Q_OBJECT
public:
QSGColumn(QSGItem *parent=0);
+
protected:
virtual void doPositioning(QSizeF *contentSize);
virtual void reportConflictingAnchors();
@@ -155,6 +191,8 @@ class Q_AUTOTEST_EXPORT QSGGrid : public QSGBasePositioner
Q_OBJECT
Q_PROPERTY(int rows READ rows WRITE setRows NOTIFY rowsChanged)
Q_PROPERTY(int columns READ columns WRITE setColumns NOTIFY columnsChanged)
+ Q_PROPERTY(int rowSpacing READ rowSpacing WRITE setRowSpacing NOTIFY rowSpacingChanged)
+ Q_PROPERTY(int columnSpacing READ columnSpacing WRITE setColumnSpacing NOTIFY columnSpacingChanged)
Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged)
Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged)
Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged)
@@ -168,6 +206,12 @@ public:
int columns() const {return m_columns;}
void setColumns(const int columns);
+ int rowSpacing() const { return m_rowSpacing; }
+ void setRowSpacing(int);
+
+ int columnSpacing() const { return m_columnSpacing; }
+ void setColumnSpacing(int);
+
Q_ENUMS(Flow)
enum Flow { LeftToRight, TopToBottom };
Flow flow() const;
@@ -183,6 +227,8 @@ Q_SIGNALS:
void flowChanged();
void layoutDirectionChanged();
void effectiveLayoutDirectionChanged();
+ void rowSpacingChanged();
+ void columnSpacingChanged();
protected:
virtual void doPositioning(QSizeF *contentSize);
@@ -191,6 +237,8 @@ protected:
private:
int m_rows;
int m_columns;
+ int m_rowSpacing;
+ int m_columnSpacing;
Flow m_flow;
Q_DISABLE_COPY(QSGGrid)
};
@@ -237,6 +285,9 @@ QML_DECLARE_TYPE(QSGRow)
QML_DECLARE_TYPE(QSGGrid)
QML_DECLARE_TYPE(QSGFlow)
+QML_DECLARE_TYPE(QSGBasePositioner)
+QML_DECLARE_TYPEINFO(QSGBasePositioner, QML_HAS_ATTACHED_PROPERTIES)
+
QT_END_HEADER
#endif // QSGPOSITIONERS_P_H
diff --git a/src/declarative/items/qsgrectangle.cpp b/src/declarative/items/qsgrectangle.cpp
index cb648e25d7..25f0eda5d5 100644
--- a/src/declarative/items/qsgrectangle.cpp
+++ b/src/declarative/items/qsgrectangle.cpp
@@ -52,6 +52,24 @@
QT_BEGIN_NAMESPACE
// XXX todo - should we change rectangle to draw entirely within its width/height?
+/*!
+ \internal
+ \class QSGPen
+ \brief The QSGPen class provides a pen used for drawing rectangle borders on a QSGView.
+
+ By default, the pen is invalid and nothing is drawn. You must either set a color (then the default
+ width is 1) or a width (then the default color is black).
+
+ A width of 1 indicates is a single-pixel line on the border of the item being painted.
+
+ Example:
+ \qml
+ Rectangle {
+ border.width: 2
+ border.color: "red"
+ }
+ \endqml
+*/
QSGPen::QSGPen(QObject *parent)
: QObject(parent)
@@ -63,7 +81,7 @@ QSGPen::QSGPen(QObject *parent)
}
qreal QSGPen::width() const
-{
+{
return m_width;
}
@@ -77,9 +95,9 @@ void QSGPen::setWidth(qreal w)
emit penChanged();
}
-QColor QSGPen::color() const
-{
- return m_color;
+QColor QSGPen::color() const
+{
+ return m_color;
}
void QSGPen::setColor(const QColor &c)
@@ -104,33 +122,53 @@ void QSGPen::setAligned(bool aligned)
}
bool QSGPen::isValid() const
-{
+{
return m_valid;
}
-QSGGradientStop::QSGGradientStop(QObject *parent)
+/*!
+ \qmlclass GradientStop QSGGradientStop
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-visual-elements
+ \brief The GradientStop item defines the color at a position in a Gradient.
+
+ \sa Gradient
+*/
+
+/*!
+ \qmlproperty real QtQuick2::GradientStop::position
+ \qmlproperty color QtQuick2::GradientStop::color
+
+ The position and color properties describe the color used at a given
+ position in a gradient, as represented by a gradient stop.
+
+ The default position is 0.0; the default color is black.
+
+ \sa Gradient
+*/
+QSGGradientStop::QSGGradientStop(QObject *parent)
: QObject(parent)
{
}
-qreal QSGGradientStop::position() const
+qreal QSGGradientStop::position() const
{
- return m_position;
+ return m_position;
}
-void QSGGradientStop::setPosition(qreal position)
+void QSGGradientStop::setPosition(qreal position)
{
- m_position = position; updateGradient();
+ m_position = position; updateGradient();
}
-QColor QSGGradientStop::color() const
+QColor QSGGradientStop::color() const
{
- return m_color;
+ return m_color;
}
-void QSGGradientStop::setColor(const QColor &color)
+void QSGGradientStop::setColor(const QColor &color)
{
- m_color = color; updateGradient();
+ m_color = color; updateGradient();
}
void QSGGradientStop::updateGradient()
@@ -139,19 +177,80 @@ void QSGGradientStop::updateGradient()
grad->doUpdate();
}
-QSGGradient::QSGGradient(QObject *parent)
-: QObject(parent), m_gradient(0)
+/*!
+ \qmlclass Gradient QSGGradient
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-visual-elements
+ \brief The Gradient item defines a gradient fill.
+
+ A gradient is defined by two or more colors, which will be blended seamlessly.
+
+ The colors are specified as a set of GradientStop child items, each of
+ which defines a position on the gradient from 0.0 to 1.0 and a color.
+ The position of each GradientStop is defined by setting its
+ \l{GradientStop::}{position} property; its color is defined using its
+ \l{GradientStop::}{color} property.
+
+ A gradient without any gradient stops is rendered as a solid white fill.
+
+ Note that this item is not a visual representation of a gradient. To display a
+ gradient, use a visual element (like \l Rectangle) which supports the use
+ of gradients.
+
+ \section1 Example Usage
+
+ \div {class="float-right"}
+ \inlineimage qml-gradient.png
+ \enddiv
+
+ The following example declares a \l Rectangle item with a gradient starting
+ with red, blending to yellow at one third of the height of the rectangle,
+ and ending with green:
+
+ \snippet doc/src/snippets/declarative/gradient.qml code
+
+ \clearfloat
+ \section1 Performance and Limitations
+
+ Calculating gradients can be computationally expensive compared to the use
+ of solid color fills or images. Consider using gradients for static items
+ in a user interface.
+
+ In Qt 4.7, only vertical, linear gradients can be applied to items. If you
+ need to apply different orientations of gradients, a combination of rotation
+ and clipping will need to be applied to the relevant items. This can
+ introduce additional performance requirements for your application.
+
+ The use of animations involving gradient stops may not give the desired
+ result. An alternative way to animate gradients is to use pre-generated
+ images or SVG drawings containing gradients.
+
+ \sa GradientStop
+*/
+
+/*!
+ \qmlproperty list<GradientStop> QtQuick2::Gradient::stops
+ \default
+
+ This property holds the gradient stops describing the gradient.
+
+ By default, this property contains an empty list.
+
+ To set the gradient stops, define them as children of the Gradient element.
+*/
+QSGGradient::QSGGradient(QObject *parent)
+: QObject(parent), m_gradient(0)
{
}
-QSGGradient::~QSGGradient()
+QSGGradient::~QSGGradient()
{
- delete m_gradient;
+ delete m_gradient;
}
-QDeclarativeListProperty<QSGGradientStop> QSGGradient::stops()
+QDeclarativeListProperty<QSGGradientStop> QSGGradient::stops()
{
- return QDeclarativeListProperty<QSGGradientStop>(this, m_stops);
+ return QDeclarativeListProperty<QSGGradientStop>(this, m_stops);
}
const QGradient *QSGGradient::gradient() const
@@ -177,6 +276,51 @@ void QSGGradient::doUpdate()
int QSGRectanglePrivate::doUpdateSlotIdx = -1;
+/*!
+ \qmlclass Rectangle QSGRectangle
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-visual-elements
+ \brief The Rectangle item provides a filled rectangle with an optional border.
+ \inherits Item
+
+ Rectangle items are used to fill areas with solid color or gradients, and are
+ often used to hold other items.
+
+ \section1 Appearance
+
+ Each Rectangle item is painted using either a solid fill color, specified using
+ the \l color property, or a gradient, defined using a Gradient element and set
+ using the \l gradient property. If both a color and a gradient are specified,
+ the gradient is used.
+
+ You can add an optional border to a rectangle with its own color and thickness
+ by settting the \l border.color and \l border.width properties.
+
+ You can also create rounded rectangles using the \l radius property. Since this
+ introduces curved edges to the corners of a rectangle, it may be appropriate to
+ set the \l smooth property to improve its appearance.
+
+ \section1 Example Usage
+
+ \div {class="float-right"}
+ \inlineimage declarative-rect.png
+ \enddiv
+
+ The following example shows the effects of some of the common properties on a
+ Rectangle item, which in this case is used to create a square:
+
+ \snippet doc/src/snippets/declarative/rectangle/rectangle.qml document
+
+ \clearfloat
+ \section1 Performance
+
+ Using the \l smooth property improves the appearance of a rounded rectangle at
+ the cost of rendering performance. You should consider unsetting this property
+ for rectangles in motion, and only set it when they are stationary.
+
+ \sa Image
+*/
+
QSGRectangle::QSGRectangle(QSGItem *parent)
: QSGItem(*(new QSGRectanglePrivate), parent)
{
@@ -186,17 +330,77 @@ QSGRectangle::QSGRectangle(QSGItem *parent)
void QSGRectangle::doUpdate()
{
Q_D(QSGRectangle);
- const int pw = d->pen && d->pen->isValid() ? d->pen->width() : 0;
- d->setPaintMargin((pw+1)/2);
+ qreal penMargin = 0;
+ qreal penOffset = 0;
+ if (d->pen && d->pen->isValid()) {
+ if (d->pen->aligned()) {
+ const int pw = qRound(d->pen->width());
+ penMargin = qreal(0.5) * pw;
+ penOffset = (pw & 1) * qreal(0.5);
+ } else {
+ penMargin = qreal(0.5) * d->pen->width();
+ }
+ }
+ if (penMargin != d->penMargin || penOffset != d->penOffset) {
+ d->penMargin = penMargin;
+ d->penOffset = penOffset;
+ d->dirty(QSGItemPrivate::Size); // update clip
+ }
update();
}
+/*!
+ \qmlproperty int QtQuick2::Rectangle::border.width
+ \qmlproperty color QtQuick2::Rectangle::border.color
+
+ The width and color used to draw the border of the rectangle.
+
+ A width of 1 creates a thin line. For no line, use a width of 0 or a transparent color.
+
+ \note The width of the rectangle's border does not affect the geometry of the
+ rectangle itself or its position relative to other items if anchors are used.
+
+ If \c border.width is an odd number, the rectangle is painted at a half-pixel offset to retain
+ border smoothness. Also, the border is rendered evenly on either side of the
+ rectangle's boundaries, and the spare pixel is rendered to the right and below the
+ rectangle (as documented for QRect rendering). This can cause unintended effects if
+ \c border.width is 1 and the rectangle is \l{Item::clip}{clipped} by a parent item:
+
+ \div {class="float-right"}
+ \inlineimage rect-border-width.png
+ \enddiv
+
+ \snippet doc/src/snippets/declarative/rectangle/rect-border-width.qml 0
+
+ \clearfloat
+ Here, the innermost rectangle's border is clipped on the bottom and right edges by its
+ parent. To avoid this, the border width can be set to two instead of one.
+*/
QSGPen *QSGRectangle::border()
{
Q_D(QSGRectangle);
return d->getPen();
}
+/*!
+ \qmlproperty Gradient QtQuick2::Rectangle::gradient
+
+ The gradient to use to fill the rectangle.
+
+ This property allows for the construction of simple vertical gradients.
+ Other gradients may by formed by adding rotation to the rectangle.
+
+ \div {class="float-left"}
+ \inlineimage declarative-rect_gradient.png
+ \enddiv
+
+ \snippet doc/src/snippets/declarative/rectangle/rectangle-gradient.qml rectangles
+ \clearfloat
+
+ If both a gradient and a color are specified, the gradient will be used.
+
+ \sa Gradient, color
+*/
QSGGradient *QSGRectangle::gradient() const
{
Q_D(const QSGRectangle);
@@ -221,6 +425,14 @@ void QSGRectangle::setGradient(QSGGradient *gradient)
update();
}
+/*!
+ \qmlproperty real QtQuick2::Rectangle::radius
+ This property holds the corner radius used to draw a rounded rectangle.
+
+ If radius is non-zero, the rectangle will be painted as a rounded rectangle, otherwise it will be
+ painted as a normal rectangle. The same radius is used by all 4 corners; there is currently
+ no way to specify different radii for different corners.
+*/
qreal QSGRectangle::radius() const
{
Q_D(const QSGRectangle);
@@ -238,6 +450,26 @@ void QSGRectangle::setRadius(qreal radius)
emit radiusChanged();
}
+/*!
+ \qmlproperty color QtQuick2::Rectangle::color
+ This property holds the color used to fill the rectangle.
+
+ The default color is white.
+
+ \div {class="float-right"}
+ \inlineimage rect-color.png
+ \enddiv
+
+ The following example shows rectangles with colors specified
+ using hexadecimal and named color notation:
+
+ \snippet doc/src/snippets/declarative/rectangle/rectangle-colors.qml rectangles
+
+ \clearfloat
+ If both a gradient and a color are specified, the gradient will be used.
+
+ \sa gradient
+*/
QColor QSGRectangle::color() const
{
Q_D(const QSGRectangle);
@@ -297,11 +529,27 @@ QSGNode *QSGRectangle::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *da
return rectangle;
}
+/*!
+ \qmlproperty bool QtQuick2::Rectangle::smooth
+
+ Set this property if you want the item to be smoothly scaled or
+ transformed. Smooth filtering gives better visual quality, but is slower. If
+ the item is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the item is stationary on
+ the screen. A common pattern when animating an item is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+
+ \image rect-smooth.png
+ On this image, smooth is turned off on the top half and on on the bottom half.
+*/
QRectF QSGRectangle::boundingRect() const
{
Q_D(const QSGRectangle);
- return QRectF(-d->paintmargin, -d->paintmargin, width()+d->paintmargin*2, height()+d->paintmargin*2);
+ return QRectF(d->penOffset - d->penMargin, d->penOffset - d->penMargin,
+ d->width + 2 * d->penMargin, d->height + 2 * d->penMargin);
}
QT_END_NAMESPACE
diff --git a/src/declarative/items/qsgrectangle_p_p.h b/src/declarative/items/qsgrectangle_p_p.h
index 6e1beb7bdb..234a029aaf 100644
--- a/src/declarative/items/qsgrectangle_p_p.h
+++ b/src/declarative/items/qsgrectangle_p_p.h
@@ -66,7 +66,7 @@ class QSGRectanglePrivate : public QSGItemPrivate
public:
QSGRectanglePrivate() :
- color(Qt::white), gradient(0), pen(0), radius(0), paintmargin(0)
+ color(Qt::white), gradient(0), pen(0), radius(0), penMargin(0), penOffset(0)
{
}
@@ -79,7 +79,8 @@ public:
QSGGradient *gradient;
QSGPen *pen;
qreal radius;
- qreal paintmargin;
+ qreal penMargin;
+ qreal penOffset;
static int doUpdateSlotIdx;
QSGPen *getPen() {
@@ -95,13 +96,6 @@ public:
}
return pen;
}
-
- void setPaintMargin(qreal margin)
- {
- if (margin == paintmargin)
- return;
- paintmargin = margin;
- }
};
QT_END_NAMESPACE
diff --git a/src/declarative/items/qsgrepeater.cpp b/src/declarative/items/qsgrepeater.cpp
index cdada2d59d..bdb3a3d98a 100644
--- a/src/declarative/items/qsgrepeater.cpp
+++ b/src/declarative/items/qsgrepeater.cpp
@@ -60,6 +60,90 @@ QSGRepeaterPrivate::~QSGRepeaterPrivate()
delete model;
}
+/*!
+ \qmlclass Repeater QSGRepeater
+ \inqmlmodule QtQuick 2
+ \ingroup qml-utility-elements
+ \inherits Item
+
+ \brief The Repeater element allows you to repeat an Item-based component using a model.
+
+ The Repeater element is used to create a large number of
+ similar items. Like other view elements, a Repeater has a \l model and a \l delegate:
+ for each entry in the model, the delegate is instantiated
+ in a context seeded with data from the model. A Repeater item is usually
+ enclosed in a positioner element such as \l Row or \l Column to visually
+ position the multiple delegate items created by the Repeater.
+
+ The following Repeater creates three instances of a \l Rectangle item within
+ a \l Row:
+
+ \snippet doc/src/snippets/declarative/repeaters/repeater.qml import
+ \codeline
+ \snippet doc/src/snippets/declarative/repeaters/repeater.qml simple
+
+ \image repeater-simple.png
+
+ A Repeater's \l model can be any of the supported \l {qmlmodels}{data models}.
+ Additionally, like delegates for other views, a Repeater delegate can access
+ its index within the repeater, as well as the model data relevant to the
+ delegate. See the \l delegate property documentation for details.
+
+ Items instantiated by the Repeater are inserted, in order, as
+ children of the Repeater's parent. The insertion starts immediately after
+ the repeater's position in its parent stacking list. This allows
+ a Repeater to be used inside a layout. For example, the following Repeater's
+ items are stacked between a red rectangle and a blue rectangle:
+
+ \snippet doc/src/snippets/declarative/repeaters/repeater.qml layout
+
+ \image repeater.png
+
+
+ \note A Repeater item owns all items it instantiates. Removing or dynamically destroying
+ an item created by a Repeater results in unpredictable behavior.
+
+
+ \section2 Considerations when using Repeater
+
+ The Repeater element creates all of its delegate items when the repeater is first
+ created. This can be inefficient if there are a large number of delegate items and
+ not all of the items are required to be visible at the same time. If this is the case,
+ consider using other view elements like ListView (which only creates delegate items
+ when they are scrolled into view) or use the \l {Dynamic Object Creation} methods to
+ create items as they are required.
+
+ Also, note that Repeater is \l {Item}-based, and can only repeat \l {Item}-derived objects.
+ For example, it cannot be used to repeat QtObjects:
+ \badcode
+ Item {
+ //XXX does not work! Can't repeat QtObject as it doesn't derive from Item.
+ Repeater {
+ model: 10
+ QtObject {}
+ }
+ }
+ \endcode
+ */
+
+/*!
+ \qmlsignal QtQuick2::Repeater::onItemAdded(int index, Item item)
+
+ This handler is called when an item is added to the repeater. The \a index
+ parameter holds the index at which the item has been inserted within the
+ repeater, and the \a item parameter holds the \l Item that has been added.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Repeater::onItemRemoved(int index, Item item)
+
+ This handler is called when an item is removed from the repeater. The \a index
+ parameter holds the index at which the item was removed from the repeater,
+ and the \a item parameter holds the \l Item that was removed.
+
+ Do not keep a reference to \a item if it was created by this repeater, as
+ in these cases it will be deleted shortly after the handler is called.
+*/
QSGRepeater::QSGRepeater(QSGItem *parent)
: QSGItem(*(new QSGRepeaterPrivate), parent)
{
@@ -69,6 +153,24 @@ QSGRepeater::~QSGRepeater()
{
}
+/*!
+ \qmlproperty any QtQuick2::Repeater::model
+
+ The model providing data for the repeater.
+
+ This property can be set to any of the supported \l {qmlmodels}{data models}:
+
+ \list
+ \o A number that indicates the number of delegates to be created by the repeater
+ \o A model (e.g. a ListModel item, or a QAbstractItemModel subclass)
+ \o A string list
+ \o An object list
+ \endlist
+
+ The type of model affects the properties that are exposed to the \l delegate.
+
+ \sa {qmlmodels}{Data Models}
+*/
QVariant QSGRepeater::model() const
{
Q_D(const QSGRepeater);
@@ -124,6 +226,39 @@ void QSGRepeater::setModel(const QVariant &model)
emit countChanged();
}
+/*!
+ \qmlproperty Component QtQuick2::Repeater::delegate
+ \default
+
+ The delegate provides a template defining each item instantiated by the repeater.
+
+ Delegates are exposed to a read-only \c index property that indicates the index
+ of the delegate within the repeater. For example, the following \l Text delegate
+ displays the index of each repeated item:
+
+ \table
+ \row
+ \o \snippet doc/src/snippets/declarative/repeaters/repeater.qml index
+ \o \image repeater-index.png
+ \endtable
+
+ If the \l model is a \l{QStringList-based model}{string list} or
+ \l{QObjectList-based model}{object list}, the delegate is also exposed to
+ a read-only \c modelData property that holds the string or object data. For
+ example:
+
+ \table
+ \row
+ \o \snippet doc/src/snippets/declarative/repeaters/repeater.qml modeldata
+ \o \image repeater-modeldata.png
+ \endtable
+
+ If the \l model is a model object (such as a \l ListModel) the delegate
+ can access all model roles as named properties, in the same way that delegates
+ do for view classes like ListView.
+
+ \sa {QML Data Models}
+ */
QDeclarativeComponent *QSGRepeater::delegate() const
{
Q_D(const QSGRepeater);
@@ -153,6 +288,11 @@ void QSGRepeater::setDelegate(QDeclarativeComponent *delegate)
}
}
+/*!
+ \qmlproperty int QtQuick2::Repeater::count
+
+ This property holds the number of items in the repeater.
+*/
int QSGRepeater::count() const
{
Q_D(const QSGRepeater);
@@ -161,6 +301,12 @@ int QSGRepeater::count() const
return 0;
}
+/*!
+ \qmlmethod Item QtQuick2::Repeater::itemAt(index)
+
+ Returns the \l Item that has been created at the given \a index, or \c null
+ if no item exists at \a index.
+*/
QSGItem *QSGRepeater::itemAt(int index) const
{
Q_D(const QSGRepeater);
diff --git a/src/declarative/items/qsgscalegrid.cpp b/src/declarative/items/qsgscalegrid.cpp
index a9eb080d86..e1b76c4158 100644
--- a/src/declarative/items/qsgscalegrid.cpp
+++ b/src/declarative/items/qsgscalegrid.cpp
@@ -164,6 +164,8 @@ QSGGridScaledImage::QSGGridScaledImage(QIODevice *data)
_l = l; _r = r; _t = t; _b = b;
_pix = imgFile;
+ if (_pix.startsWith(QLatin1Char('"')) && _pix.endsWith(QLatin1Char('"')))
+ _pix = _pix.mid(1, _pix.size() - 2); // remove leading/trailing quotes.
}
QSGBorderImage::TileMode QSGGridScaledImage::stringToRule(const QString &s)
diff --git a/src/declarative/items/qsgshadereffectsource.cpp b/src/declarative/items/qsgshadereffectsource.cpp
index f9dbfe58ec..ef6dd64532 100644
--- a/src/declarative/items/qsgshadereffectsource.cpp
+++ b/src/declarative/items/qsgshadereffectsource.cpp
@@ -619,8 +619,12 @@ void QSGShaderEffectSource::setSourceRect(const QRectF &rect)
/*!
\qmlproperty size ShaderEffectSource::textureSize
- This property holds the size of the texture. If it is empty, which is the
- default, the size of the source rectangle is used.
+ This property holds the requested size of the texture. If it is empty,
+ which is the default, the size of the source rectangle is used.
+
+ \note Some platforms have a limit on how small framebuffer objects can be,
+ which means the actual texture size might be larger than the requested
+ size.
*/
QSize QSGShaderEffectSource::textureSize() const
@@ -812,7 +816,7 @@ static void get_wrap_mode(QSGShaderEffectSource::WrapMode mode, QSGTexture::Wrap
QSGNode *QSGShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
- if (!m_sourceItem) {
+ if (!m_sourceItem || m_sourceItem->width() == 0 || m_sourceItem->height() == 0) {
delete oldNode;
return 0;
}
@@ -820,13 +824,22 @@ QSGNode *QSGShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaintNod
QSGShaderEffectTexture *tex = qobject_cast<QSGShaderEffectTexture *>(m_texture);
tex->setLive(m_live);
tex->setItem(QSGItemPrivate::get(m_sourceItem)->itemNode());
- QRectF sourceRect = m_sourceRect.isNull()
+ QRectF sourceRect = m_sourceRect.width() == 0 || m_sourceRect.height() == 0
? QRectF(0, 0, m_sourceItem->width(), m_sourceItem->height())
: m_sourceRect;
tex->setRect(sourceRect);
QSize textureSize = m_textureSize.isEmpty()
? QSize(qCeil(qAbs(sourceRect.width())), qCeil(qAbs(sourceRect.height())))
: m_textureSize;
+ Q_ASSERT(!textureSize.isEmpty());
+ QSGItemPrivate *d = static_cast<QSGItemPrivate *>(QObjectPrivate::get(this));
+ const QSize minTextureSize = d->sceneGraphContext()->minimumFBOSize();
+ // Keep power-of-two by doubling the size.
+ while (textureSize.width() < minTextureSize.width())
+ textureSize.rwidth() *= 2;
+ while (textureSize.height() < minTextureSize.height())
+ textureSize.rheight() *= 2;
+
tex->setSize(textureSize);
tex->setRecursive(m_recursive);
tex->setFormat(GLenum(m_format));
diff --git a/src/declarative/items/qsgtext.cpp b/src/declarative/items/qsgtext.cpp
index cc6a4b406d..bac0be969b 100644
--- a/src/declarative/items/qsgtext.cpp
+++ b/src/declarative/items/qsgtext.cpp
@@ -91,6 +91,7 @@ private:
static QSet<QUrl> errors;
};
+DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
DEFINE_BOOL_CONFIG_OPTION(enableImageCache, QML_ENABLE_TEXT_IMAGE_CACHE);
QString QSGTextPrivate::elideChar = QString(0x2026);
@@ -106,7 +107,12 @@ QSGTextPrivate::QSGTextPrivate()
richText(false), singleline(false), cacheAllTextAsImage(true), internalWidthUpdate(false),
requireImplicitWidth(false), truncated(false), hAlignImplicit(true), rightToLeftText(false),
layoutTextElided(false), richTextAsImage(false), textureImageCacheDirty(false), naturalWidth(0),
- doc(0), layoutThread(0), nodeType(NodeIsNull)
+ doc(0), nodeType(NodeIsNull)
+
+#if defined(Q_OS_MAC)
+ , layoutThread(0)
+#endif
+
{
cacheAllTextAsImage = enableImageCache();
}
@@ -290,7 +296,9 @@ void QSGTextPrivate::updateSize()
int dy = q->height();
QSize size(0, 0);
+#if defined(Q_OS_MAC)
layoutThread = QThread::currentThread();
+#endif
//setup instance of QTextLayout for all cases other than richtext
if (!richText) {
@@ -312,6 +320,8 @@ void QSGTextPrivate::updateSize()
QTextOption option;
option.setAlignment((Qt::Alignment)int(horizontalAlignment | vAlign));
option.setWrapMode(QTextOption::WrapMode(wrapMode));
+ if (!cacheAllTextAsImage && !richTextAsImage && !qmlDisableDistanceField())
+ option.setUseDesignMetrics(true);
doc->setDefaultTextOption(option);
if (requireImplicitWidth && q->widthValid()) {
doc->setTextWidth(-1);
@@ -375,6 +385,8 @@ QRect QSGTextPrivate::setupTextLayout()
QTextOption textOption = layout.textOption();
textOption.setAlignment(Qt::Alignment(q->effectiveHAlign()));
textOption.setWrapMode(QTextOption::WrapMode(wrapMode));
+ if (!cacheAllTextAsImage && !richTextAsImage && !qmlDisableDistanceField())
+ textOption.setUseDesignMetrics(true);
layout.setTextOption(textOption);
bool elideText = false;
@@ -574,7 +586,7 @@ void QSGTextPrivate::invalidateImageCache()
{
Q_Q(QSGText);
- if(richTextAsImage || cacheAllTextAsImage || (!QSGDistanceFieldGlyphCache::distanceFieldEnabled() && style != QSGText::Normal)){//If actually using the image cache
+ if(richTextAsImage || cacheAllTextAsImage || (qmlDisableDistanceField() && style != QSGText::Normal)){//If actually using the image cache
if (imageCacheDirty)
return;
@@ -694,6 +706,49 @@ QPixmap QSGTextPrivate::drawOutline(const QPixmap &source, const QPixmap &styleS
return img;
}
+/*!
+ \qmlclass Text QSGText
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-visual-elements
+ \brief The Text item allows you to add formatted text to a scene.
+ \inherits Item
+
+ Text items can display both plain and rich text. For example, red text with
+ a specific font and size can be defined like this:
+
+ \qml
+ Text {
+ text: "Hello World!"
+ font.family: "Helvetica"
+ font.pointSize: 24
+ color: "red"
+ }
+ \endqml
+
+ Rich text is defined using HTML-style markup:
+
+ \qml
+ Text {
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+ \endqml
+
+ \image declarative-text.png
+
+ If height and width are not explicitly set, Text will attempt to determine how
+ much room is needed and set it accordingly. Unless \l wrapMode is set, it will always
+ prefer width to height (all text will be placed on a single line).
+
+ The \l elide property can alternatively be used to fit a single line of
+ plain text to a set width.
+
+ Note that the \l{Supported HTML Subset} is limited. Also, if the text contains
+ HTML img tags that load remote images, the text is reloaded.
+
+ Text provides read-only text. For editable text, see \l TextEdit.
+
+ \sa {declarative/text/fonts}{Fonts example}
+*/
QSGText::QSGText(QSGItem *parent)
: QSGImplicitSizeItem(*(new QSGTextPrivate), parent)
{
@@ -705,6 +760,149 @@ QSGText::~QSGText()
{
}
+/*!
+ \qmlproperty bool QtQuick2::Text::clip
+ This property holds whether the text is clipped.
+
+ Note that if the text does not fit in the bounding rectangle it will be abruptly chopped.
+
+ If you want to display potentially long text in a limited space, you probably want to use \c elide instead.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::Text::smooth
+
+ This property holds whether the text is smoothly scaled or transformed.
+
+ Smooth filtering gives better visual quality, but is slower. If
+ the item is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the item is stationary on
+ the screen. A common pattern when animating an item is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Text::onLinkActivated(string link)
+
+ This handler is called when the user clicks on a link embedded in the text.
+ The link must be in rich text or HTML format and the
+ \a link string provides access to the particular link.
+
+ \snippet doc/src/snippets/declarative/text/onLinkActivated.qml 0
+
+ The example code will display the text
+ "The main website is at \l{http://qt.nokia.com}{Nokia Qt DF}."
+
+ Clicking on the highlighted link will output
+ \tt{http://qt.nokia.com link activated} to the console.
+*/
+
+/*!
+ \qmlproperty string QtQuick2::Text::font.family
+
+ Sets the family name of the font.
+
+ The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
+ If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
+ If the family isn't available a family will be set using the font matching algorithm.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::Text::font.bold
+
+ Sets whether the font weight is bold.
+*/
+
+/*!
+ \qmlproperty enumeration QtQuick2::Text::font.weight
+
+ Sets the font's weight.
+
+ The weight can be one of:
+ \list
+ \o Font.Light
+ \o Font.Normal - the default
+ \o Font.DemiBold
+ \o Font.Bold
+ \o Font.Black
+ \endlist
+
+ \qml
+ Text { text: "Hello"; font.weight: Font.DemiBold }
+ \endqml
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::Text::font.italic
+
+ Sets whether the font has an italic style.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::Text::font.underline
+
+ Sets whether the text is underlined.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::Text::font.strikeout
+
+ Sets whether the font has a strikeout style.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Text::font.pointSize
+
+ Sets the font size in points. The point size must be greater than zero.
+*/
+
+/*!
+ \qmlproperty int QtQuick2::Text::font.pixelSize
+
+ Sets the font size in pixels.
+
+ Using this function makes the font device dependent.
+ Use \c pointSize to set the size of the font in a device independent manner.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Text::font.letterSpacing
+
+ Sets the letter spacing for the font.
+
+ Letter spacing changes the default spacing between individual letters in the font.
+ A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Text::font.wordSpacing
+
+ Sets the word spacing for the font.
+
+ Word spacing changes the default spacing between individual words.
+ A positive value increases the word spacing by a corresponding amount of pixels,
+ while a negative value decreases the inter-word spacing accordingly.
+*/
+
+/*!
+ \qmlproperty enumeration QtQuick2::Text::font.capitalization
+
+ Sets the capitalization for the text.
+
+ \list
+ \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
+ \o Font.AllUppercase - This alters the text to be rendered in all uppercase type.
+ \o Font.AllLowercase - This alters the text to be rendered in all lowercase type.
+ \o Font.SmallCaps - This alters the text to be rendered in small-caps type.
+ \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
+ \endlist
+
+ \qml
+ Text { text: "Hello"; font.capitalization: Font.AllLowercase }
+ \endqml
+*/
QFont QSGText::font() const
{
Q_D(const QSGText);
@@ -720,8 +918,6 @@ void QSGText::setFont(const QFont &font)
d->sourceFont = font;
QFont oldFont = d->font;
d->font = font;
- if (QSGDistanceFieldGlyphCache::distanceFieldEnabled())
- d->font.setHintingPreference(QFont::PreferNoHinting);
if (d->font.pointSizeF() != -1) {
// 0.5pt resolution
@@ -735,6 +931,14 @@ void QSGText::setFont(const QFont &font)
emit fontChanged(d->sourceFont);
}
+/*!
+ \qmlproperty string QtQuick2::Text::text
+
+ The text to display. Text supports both plain and rich text strings.
+
+ The item will try to automatically determine whether the text should
+ be treated as rich text. This determination is made using Qt::mightBeRichText().
+*/
QString QSGText::text() const
{
Q_D(const QSGText);
@@ -764,6 +968,27 @@ void QSGText::setText(const QString &n)
emit textChanged(d->text);
}
+/*!
+ \qmlproperty color QtQuick2::Text::color
+
+ The text color.
+
+ An example of green text defined using hexadecimal notation:
+ \qml
+ Text {
+ color: "#00FF00"
+ text: "green text"
+ }
+ \endqml
+
+ An example of steel blue text defined using an SVG color name:
+ \qml
+ Text {
+ color: "steelblue"
+ text: "blue text"
+ }
+ \endqml
+*/
QColor QSGText::color() const
{
Q_D(const QSGText);
@@ -780,7 +1005,30 @@ void QSGText::setColor(const QColor &color)
d->invalidateImageCache();
emit colorChanged(d->color);
}
+/*!
+ \qmlproperty enumeration QtQuick2::Text::style
+
+ Set an additional text style.
+
+ Supported text styles are:
+ \list
+ \o Text.Normal - the default
+ \o Text.Outline
+ \o Text.Raised
+ \o Text.Sunken
+ \endlist
+
+ \qml
+ Row {
+ Text { font.pointSize: 24; text: "Normal" }
+ Text { font.pointSize: 24; text: "Raised"; style: Text.Raised; styleColor: "#AAAAAA" }
+ Text { font.pointSize: 24; text: "Outline";style: Text.Outline; styleColor: "red" }
+ Text { font.pointSize: 24; text: "Sunken"; style: Text.Sunken; styleColor: "#AAAAAA" }
+ }
+ \endqml
+ \image declarative-textstyle.png
+*/
QSGText::TextStyle QSGText::style() const
{
Q_D(const QSGText);
@@ -801,6 +1049,21 @@ void QSGText::setStyle(QSGText::TextStyle style)
emit styleChanged(d->style);
}
+/*!
+ \qmlproperty color QtQuick2::Text::styleColor
+
+ Defines the secondary color used by text styles.
+
+ \c styleColor is used as the outline color for outlined text, and as the
+ shadow color for raised or sunken text. If no style has been set, it is not
+ used at all.
+
+ \qml
+ Text { font.pointSize: 18; text: "hello"; style: Text.Raised; styleColor: "gray" }
+ \endqml
+
+ \sa style
+ */
QColor QSGText::styleColor() const
{
Q_D(const QSGText);
@@ -818,6 +1081,30 @@ void QSGText::setStyleColor(const QColor &color)
emit styleColorChanged(d->styleColor);
}
+/*!
+ \qmlproperty enumeration QtQuick2::Text::horizontalAlignment
+ \qmlproperty enumeration QtQuick2::Text::verticalAlignment
+ \qmlproperty enumeration QtQuick2::Text::effectiveHorizontalAlignment
+
+ Sets the horizontal and vertical alignment of the text within the Text items
+ width and height. By default, the text is vertically aligned to the top. Horizontal
+ alignment follows the natural alignment of the text, for example text that is read
+ from left to right will be aligned to the left.
+
+ The valid values for \c horizontalAlignment are \c Text.AlignLeft, \c Text.AlignRight, \c Text.AlignHCenter and
+ \c Text.AlignJustify. The valid values for \c verticalAlignment are \c Text.AlignTop, \c Text.AlignBottom
+ and \c Text.AlignVCenter.
+
+ Note that for a single line of text, the size of the text is the area of the text. In this common case,
+ all alignments are equivalent. If you want the text to be, say, centered in its parent, then you will
+ need to either modify the Item::anchors, or set horizontalAlignment to Text.AlignHCenter and bind the width to
+ that of the parent.
+
+ When using the attached property LayoutMirroring::enabled to mirror application
+ layouts, the horizontal alignment of text will also be mirrored. However, the property
+ \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
+ of Text, use the read-only property \c effectiveHorizontalAlignment.
+*/
QSGText::HAlignment QSGText::hAlign() const
{
Q_D(const QSGText);
@@ -917,6 +1204,19 @@ void QSGText::setVAlign(VAlignment align)
emit verticalAlignmentChanged(align);
}
+/*!
+ \qmlproperty enumeration QtQuick2::Text::wrapMode
+
+ Set this property to wrap the text to the Text item's width. The text will only
+ wrap if an explicit width has been set. wrapMode can be one of:
+
+ \list
+ \o Text.NoWrap (default) - no wrapping will be performed. If the text contains insufficient newlines, then \l paintedWidth will exceed a set width.
+ \o Text.WordWrap - wrapping is done on word boundaries only. If a word is too long, \l paintedWidth will exceed a set width.
+ \o Text.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word.
+ \o Text.Wrap - if possible, wrapping occurs at a word boundary; otherwise it will occur at the appropriate point on the line, even in the middle of a word.
+ \endlist
+*/
QSGText::WrapMode QSGText::wrapMode() const
{
Q_D(const QSGText);
@@ -935,18 +1235,48 @@ void QSGText::setWrapMode(WrapMode mode)
emit wrapModeChanged();
}
+/*!
+ \qmlproperty int QtQuick2::Text::lineCount
+
+ Returns the number of lines visible in the text item.
+
+ This property is not supported for rich text.
+
+ \sa maximumLineCount
+*/
int QSGText::lineCount() const
{
Q_D(const QSGText);
return d->lineCount;
}
+/*!
+ \qmlproperty bool QtQuick2::Text::truncated
+
+ Returns true if the text has been truncated due to \l maximumLineCount
+ or \l elide.
+
+ This property is not supported for rich text.
+
+ \sa maximumLineCount, elide
+*/
bool QSGText::truncated() const
{
Q_D(const QSGText);
return d->truncated;
}
+/*!
+ \qmlproperty int QtQuick2::Text::maximumLineCount
+
+ Set this property to limit the number of lines that the text item will show.
+ If elide is set to Text.ElideRight, the text will be elided appropriately.
+ By default, this is the value of the largest possible integer.
+
+ This property is not supported for rich text.
+
+ \sa lineCount, elide
+*/
int QSGText::maximumLineCount() const
{
Q_D(const QSGText);
@@ -976,6 +1306,61 @@ void QSGText::resetMaximumLineCount()
}
}
+/*!
+ \qmlproperty enumeration QtQuick2::Text::textFormat
+
+ The way the text property should be displayed.
+
+ Supported text formats are:
+
+ \list
+ \o Text.AutoText (default)
+ \o Text.PlainText
+ \o Text.RichText
+ \o Text.StyledText
+ \endlist
+
+ If the text format is \c Text.AutoText the text element
+ will automatically determine whether the text should be treated as
+ rich text. This determination is made using Qt::mightBeRichText().
+
+ Text.StyledText is an optimized format supporting some basic text
+ styling markup, in the style of html 3.2:
+
+ \code
+ <font size="4" color="#ff0000">font size and color</font>
+ <b>bold</b>
+ <i>italic</i>
+ <br>
+ &gt; &lt; &amp;
+ \endcode
+
+ \c Text.StyledText parser is strict, requiring tags to be correctly nested.
+
+ \table
+ \row
+ \o
+ \qml
+Column {
+ Text {
+ font.pointSize: 24
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+ Text {
+ font.pointSize: 24
+ textFormat: Text.RichText
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+ Text {
+ font.pointSize: 24
+ textFormat: Text.PlainText
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+}
+ \endqml
+ \o \image declarative-textformat.png
+ \endtable
+*/
QSGText::TextFormat QSGText::textFormat() const
{
Q_D(const QSGText);
@@ -1002,6 +1387,31 @@ void QSGText::setTextFormat(TextFormat format)
emit textFormatChanged(d->format);
}
+/*!
+ \qmlproperty enumeration QtQuick2::Text::elide
+
+ Set this property to elide parts of the text fit to the Text item's width.
+ The text will only elide if an explicit width has been set.
+
+ This property cannot be used with rich text.
+
+ Eliding can be:
+ \list
+ \o Text.ElideNone - the default
+ \o Text.ElideLeft
+ \o Text.ElideMiddle
+ \o Text.ElideRight
+ \endlist
+
+ If this property is set to Text.ElideRight, it can be used with multiline
+ text. The text will only elide if maximumLineCount has been set.
+
+ If the text is a multi-length string, and the mode is not \c Text.ElideNone,
+ the first string that fits will be used, otherwise the last will be elided.
+
+ Multi-length strings are ordered from longest to shortest, separated by the
+ Unicode "String Terminator" character \c U009C (write this in QML with \c{"\u009C"} or \c{"\x9C"}).
+*/
QSGText::TextElideMode QSGText::elideMode() const
{
Q_D(const QSGText);
@@ -1079,11 +1489,13 @@ QSGNode *QSGText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
QRectF bounds = boundingRect();
// We need to make sure the layout is done in the current thread
+#if defined(Q_OS_MAC)
if (d->layoutThread != QThread::currentThread())
d->updateLayout();
+#endif
// XXX todo - some styled text can be done by the QSGTextNode
- if (d->richTextAsImage || d->cacheAllTextAsImage || (!QSGDistanceFieldGlyphCache::distanceFieldEnabled() && d->style != Normal)) {
+ if (d->richTextAsImage || d->cacheAllTextAsImage || (qmlDisableDistanceField() && d->style != Normal)) {
bool wasDirty = d->textureImageCacheDirty;
d->textureImageCacheDirty = false;
@@ -1156,18 +1568,39 @@ bool QSGText::event(QEvent *e)
}
}
+/*!
+ \qmlproperty real QtQuick2::Text::paintedWidth
+
+ Returns the width of the text, including width past the width
+ which is covered due to insufficient wrapping if WrapMode is set.
+*/
qreal QSGText::paintedWidth() const
{
Q_D(const QSGText);
return d->paintedSize.width();
}
+/*!
+ \qmlproperty real QtQuick2::Text::paintedHeight
+
+ Returns the height of the text, including height past the height
+ which is covered due to there being more text than fits in the set height.
+*/
qreal QSGText::paintedHeight() const
{
Q_D(const QSGText);
return d->paintedSize.height();
}
+/*!
+ \qmlproperty real QtQuick2::Text::lineHeight
+
+ Sets the line height for the text.
+ The value can be in pixels or a multiplier depending on lineHeightMode.
+
+ The default value is a multiplier of 1.0.
+ The line height must be a positive value.
+*/
qreal QSGText::lineHeight() const
{
Q_D(const QSGText);
@@ -1186,6 +1619,18 @@ void QSGText::setLineHeight(qreal lineHeight)
emit lineHeightChanged(lineHeight);
}
+/*!
+ \qmlproperty enumeration QtQuick2::Text::lineHeightMode
+
+ This property determines how the line height is specified.
+ The possible values are:
+
+ \list
+ \o Text.ProportionalHeight (default) - this sets the spacing proportional to the
+ line (as a multiplier). For example, set to 2 for double spacing.
+ \o Text.FixedHeight - this sets the line height to a fixed line height (in pixels).
+ \endlist
+*/
QSGText::LineHeightMode QSGText::lineHeightMode() const
{
Q_D(const QSGText);
diff --git a/src/declarative/items/qsgtext_p_p.h b/src/declarative/items/qsgtext_p_p.h
index 050e3984ab..40c986142c 100644
--- a/src/declarative/items/qsgtext_p_p.h
+++ b/src/declarative/items/qsgtext_p_p.h
@@ -134,7 +134,6 @@ public:
QPixmap textLayoutImage(bool drawStyle);
void drawTextLayout(QPainter *p, const QPointF &pos, bool drawStyle);
QTextLayout layout;
- QThread *layoutThread;
static QPixmap drawOutline(const QPixmap &source, const QPixmap &styleSource);
static QPixmap drawOutline(const QPixmap &source, const QPixmap &styleSource, int yOffset);
@@ -146,9 +145,13 @@ public:
enum NodeType {
NodeIsNull,
NodeIsTexture,
- NodeIsText,
+ NodeIsText
};
NodeType nodeType;
+
+#if defined(Q_OS_MAC)
+ QThread *layoutThread;
+#endif
};
QT_END_NAMESPACE
diff --git a/src/declarative/items/qsgtextedit.cpp b/src/declarative/items/qsgtextedit.cpp
index 4ba5bec5e4..1c0ed62f0d 100644
--- a/src/declarative/items/qsgtextedit.cpp
+++ b/src/declarative/items/qsgtextedit.cpp
@@ -43,6 +43,8 @@
#include "qsgtextedit_p_p.h"
#include "qsgevents_p_p.h"
#include "qsgcanvas.h"
+#include "qsgtextnode_p.h"
+#include "qsgsimplerectnode.h"
#include <QtDeclarative/qdeclarativeinfo.h>
#include <QtWidgets/qapplication.h>
@@ -55,13 +57,68 @@
#include <private/qtextcontrol_p.h>
#include <private/qtextengine_p.h>
#include <private/qwidget_p.h>
+#include <private/qsgdistancefieldglyphcache_p.h>
+#include <private/qsgtexture_p.h>
+#include <private/qsgadaptationlayer_p.h>
QT_BEGIN_NAMESPACE
+DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
+
QWidgetPrivate *qt_widget_private(QWidget *widget);
+/*!
+ \qmlclass TextEdit QSGTextEdit
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-visual-elements
+ \brief The TextEdit item displays multiple lines of editable formatted text.
+ \inherits Item
+
+ The TextEdit item displays a block of editable, formatted text.
+
+ It can display both plain and rich text. For example:
+
+ \qml
+TextEdit {
+ width: 240
+ text: "<b>Hello</b> <i>World!</i>"
+ font.family: "Helvetica"
+ font.pointSize: 20
+ color: "blue"
+ focus: true
+}
+ \endqml
+
+ \image declarative-textedit.gif
+
+ Setting \l {Item::focus}{focus} to \c true enables the TextEdit item to receive keyboard focus.
+
+ Note that the TextEdit does not implement scrolling, following the cursor, or other behaviors specific
+ to a look-and-feel. For example, to add flickable scrolling that follows the cursor:
+ \snippet snippets/declarative/texteditor.qml 0
+
+ A particular look-and-feel might use smooth scrolling (eg. using SmoothedFollow), might have a visible
+ scrollbar, or a scrollbar that fades in to show location, etc.
+
+ Clipboard support is provided by the cut(), copy(), and paste() functions, and the selection can
+ be handled in a traditional "mouse" mechanism by setting selectByMouse, or handled completely
+ from QML by manipulating selectionStart and selectionEnd, or using selectAll() or selectWord().
+
+ You can translate between cursor positions (characters from the start of the document) and pixel
+ points using positionAt() and positionToRectangle().
+
+ \sa Text, TextInput, {declarative/text/textselection}{Text Selection example}
+*/
+
+/*!
+ \qmlsignal QtQuick2::TextEdit::onLinkActivated(string link)
+
+ This handler is called when the user clicks on a link embedded in the text.
+ The link must be in rich text or HTML format and the
+ \a link string provides access to the particular link.
+*/
QSGTextEdit::QSGTextEdit(QSGItem *parent)
-: QSGImplicitSizePaintedItem(*(new QSGTextEditPrivate), parent)
+: QSGImplicitSizeItem(*(new QSGTextEditPrivate), parent)
{
Q_D(QSGTextEdit);
d->init();
@@ -79,6 +136,119 @@ QString QSGTextEdit::text() const
return d->document->toPlainText();
}
+/*!
+ \qmlproperty string QtQuick2::TextEdit::font.family
+
+ Sets the family name of the font.
+
+ The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
+ If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
+ If the family isn't available a family will be set using the font matching algorithm.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::TextEdit::font.bold
+
+ Sets whether the font weight is bold.
+*/
+
+/*!
+ \qmlproperty enumeration QtQuick2::TextEdit::font.weight
+
+ Sets the font's weight.
+
+ The weight can be one of:
+ \list
+ \o Font.Light
+ \o Font.Normal - the default
+ \o Font.DemiBold
+ \o Font.Bold
+ \o Font.Black
+ \endlist
+
+ \qml
+ TextEdit { text: "Hello"; font.weight: Font.DemiBold }
+ \endqml
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::TextEdit::font.italic
+
+ Sets whether the font has an italic style.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::TextEdit::font.underline
+
+ Sets whether the text is underlined.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::TextEdit::font.strikeout
+
+ Sets whether the font has a strikeout style.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::TextEdit::font.pointSize
+
+ Sets the font size in points. The point size must be greater than zero.
+*/
+
+/*!
+ \qmlproperty int QtQuick2::TextEdit::font.pixelSize
+
+ Sets the font size in pixels.
+
+ Using this function makes the font device dependent. Use
+ \l{TextEdit::font.pointSize} to set the size of the font in a
+ device independent manner.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::TextEdit::font.letterSpacing
+
+ Sets the letter spacing for the font.
+
+ Letter spacing changes the default spacing between individual letters in the font.
+ A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::TextEdit::font.wordSpacing
+
+ Sets the word spacing for the font.
+
+ Word spacing changes the default spacing between individual words.
+ A positive value increases the word spacing by a corresponding amount of pixels,
+ while a negative value decreases the inter-word spacing accordingly.
+*/
+
+/*!
+ \qmlproperty enumeration QtQuick2::TextEdit::font.capitalization
+
+ Sets the capitalization for the text.
+
+ \list
+ \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
+ \o Font.AllUppercase - This alters the text to be rendered in all uppercase type.
+ \o Font.AllLowercase - This alters the text to be rendered in all lowercase type.
+ \o Font.SmallCaps - This alters the text to be rendered in small-caps type.
+ \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
+ \endlist
+
+ \qml
+ TextEdit { text: "Hello"; font.capitalization: Font.AllLowercase }
+ \endqml
+*/
+
+/*!
+ \qmlproperty string QtQuick2::TextEdit::text
+
+ The text to display. If the text format is AutoText the text edit will
+ automatically determine whether the text should be treated as
+ rich text. This determination is made using Qt::mightBeRichText().
+*/
void QSGTextEdit::setText(const QString &text)
{
Q_D(QSGTextEdit);
@@ -92,12 +262,52 @@ void QSGTextEdit::setText(const QString &text)
#else
d->control->setPlainText(text);
#endif
+ d->isComplexRichText = QSGTextNode::isComplexRichText(d->document);
} else {
d->control->setPlainText(text);
}
q_textChanged();
}
+/*!
+ \qmlproperty enumeration QtQuick2::TextEdit::textFormat
+
+ The way the text property should be displayed.
+
+ \list
+ \o TextEdit.AutoText
+ \o TextEdit.PlainText
+ \o TextEdit.RichText
+ \endlist
+
+ The default is TextEdit.AutoText. If the text format is TextEdit.AutoText the text edit
+ will automatically determine whether the text should be treated as
+ rich text. This determination is made using Qt::mightBeRichText().
+
+ \table
+ \row
+ \o
+ \qml
+Column {
+ TextEdit {
+ font.pointSize: 24
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+ TextEdit {
+ font.pointSize: 24
+ textFormat: TextEdit.RichText
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+ TextEdit {
+ font.pointSize: 24
+ textFormat: TextEdit.PlainText
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+}
+ \endqml
+ \o \image declarative-textformat.png
+ \endtable
+*/
QSGTextEdit::TextFormat QSGTextEdit::textFormat() const
{
Q_D(const QSGTextEdit);
@@ -122,6 +332,7 @@ void QSGTextEdit::setTextFormat(TextFormat format)
d->control->setPlainText(d->text);
#endif
updateSize();
+ d->isComplexRichText = QSGTextNode::isComplexRichText(d->document);
}
d->format = format;
d->control->setAcceptRichText(d->format != PlainText);
@@ -156,11 +367,26 @@ void QSGTextEdit::setFont(const QFont &font)
moveCursorDelegate();
}
updateSize();
- update();
+ updateDocument();
}
emit fontChanged(d->sourceFont);
}
+/*!
+ \qmlproperty color QtQuick2::TextEdit::color
+
+ The text color.
+
+ \qml
+ // green text using hexadecimal notation
+ TextEdit { color: "#00FF00" }
+ \endqml
+
+ \qml
+ // steelblue text using SVG color name
+ TextEdit { color: "steelblue" }
+ \endqml
+*/
QColor QSGTextEdit::color() const
{
Q_D(const QSGTextEdit);
@@ -177,10 +403,15 @@ void QSGTextEdit::setColor(const QColor &color)
QPalette pal = d->control->palette();
pal.setColor(QPalette::Text, color);
d->control->setPalette(pal);
- update();
+ updateDocument();
emit colorChanged(d->color);
}
+/*!
+ \qmlproperty color QtQuick2::TextEdit::selectionColor
+
+ The text highlight color, used behind selections.
+*/
QColor QSGTextEdit::selectionColor() const
{
Q_D(const QSGTextEdit);
@@ -197,10 +428,15 @@ void QSGTextEdit::setSelectionColor(const QColor &color)
QPalette pal = d->control->palette();
pal.setColor(QPalette::Highlight, color);
d->control->setPalette(pal);
- update();
+ updateDocument();
emit selectionColorChanged(d->selectionColor);
}
+/*!
+ \qmlproperty color QtQuick2::TextEdit::selectedTextColor
+
+ The selected text color, used in selections.
+*/
QColor QSGTextEdit::selectedTextColor() const
{
Q_D(const QSGTextEdit);
@@ -217,10 +453,40 @@ void QSGTextEdit::setSelectedTextColor(const QColor &color)
QPalette pal = d->control->palette();
pal.setColor(QPalette::HighlightedText, color);
d->control->setPalette(pal);
- update();
+ updateDocument();
emit selectedTextColorChanged(d->selectedTextColor);
}
+/*!
+ \qmlproperty enumeration QtQuick2::TextEdit::horizontalAlignment
+ \qmlproperty enumeration QtQuick2::TextEdit::verticalAlignment
+ \qmlproperty enumeration QtQuick2::TextEdit::effectiveHorizontalAlignment
+
+ Sets the horizontal and vertical alignment of the text within the TextEdit item's
+ width and height. By default, the text alignment follows the natural alignment
+ of the text, for example text that is read from left to right will be aligned to
+ the left.
+
+ Valid values for \c horizontalAlignment are:
+ \list
+ \o TextEdit.AlignLeft (default)
+ \o TextEdit.AlignRight
+ \o TextEdit.AlignHCenter
+ \o TextEdit.AlignJustify
+ \endlist
+
+ Valid values for \c verticalAlignment are:
+ \list
+ \o TextEdit.AlignTop (default)
+ \o TextEdit.AlignBottom
+ \o TextEdit.AlignVCenter
+ \endlist
+
+ When using the attached property LayoutMirroring::enabled to mirror application
+ layouts, the horizontal alignment of text will also be mirrored. However, the property
+ \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
+ of TextEdit, use the read-only property \c effectiveHorizontalAlignment.
+*/
QSGTextEdit::HAlignment QSGTextEdit::hAlign() const
{
Q_D(const QSGTextEdit);
@@ -320,7 +586,21 @@ void QSGTextEdit::setVAlign(QSGTextEdit::VAlignment alignment)
moveCursorDelegate();
emit verticalAlignmentChanged(d->vAlign);
}
+/*!
+ \qmlproperty enumeration QtQuick2::TextEdit::wrapMode
+
+ Set this property to wrap the text to the TextEdit item's width.
+ The text will only wrap if an explicit width has been set.
+
+ \list
+ \o TextEdit.NoWrap - no wrapping will be performed. If the text contains insufficient newlines, then implicitWidth will exceed a set width.
+ \o TextEdit.WordWrap - wrapping is done on word boundaries only. If a word is too long, implicitWidth will exceed a set width.
+ \o TextEdit.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word.
+ \o TextEdit.Wrap - if possible, wrapping occurs at a word boundary; otherwise it will occur at the appropriate point on the line, even in the middle of a word.
+ \endlist
+ The default is TextEdit.NoWrap. If you set a width, consider using TextEdit.Wrap.
+*/
QSGTextEdit::WrapMode QSGTextEdit::wrapMode() const
{
Q_D(const QSGTextEdit);
@@ -338,24 +618,48 @@ void QSGTextEdit::setWrapMode(WrapMode mode)
emit wrapModeChanged();
}
+/*!
+ \qmlproperty int QtQuick2::TextEdit::lineCount
+
+ Returns the total number of lines in the textEdit item.
+*/
int QSGTextEdit::lineCount() const
{
Q_D(const QSGTextEdit);
return d->lineCount;
}
+/*!
+ \qmlproperty real QtQuick2::TextEdit::paintedWidth
+
+ Returns the width of the text, including the width past the width
+ which is covered due to insufficient wrapping if \l wrapMode is set.
+*/
qreal QSGTextEdit::paintedWidth() const
{
Q_D(const QSGTextEdit);
return d->paintedSize.width();
}
+/*!
+ \qmlproperty real QtQuick2::TextEdit::paintedHeight
+
+ Returns the height of the text, including the height past the height
+ that is covered if the text does not fit within the set height.
+*/
qreal QSGTextEdit::paintedHeight() const
{
Q_D(const QSGTextEdit);
return d->paintedSize.height();
}
+/*!
+ \qmlmethod rectangle QtQuick2::TextEdit::positionToRectangle(position)
+
+ Returns the rectangle at the given \a position in the text. The x, y,
+ and height properties correspond to the cursor that would describe
+ that position.
+*/
QRectF QSGTextEdit::positionToRectangle(int pos) const
{
Q_D(const QSGTextEdit);
@@ -365,6 +669,14 @@ QRectF QSGTextEdit::positionToRectangle(int pos) const
}
+/*!
+ \qmlmethod int QtQuick2::TextEdit::positionAt(int x, int y)
+
+ Returns the text position closest to pixel position (\a x, \a y).
+
+ Position 0 is before the first character, position 1 is after the first character
+ but before the second, and so on until position \l {text}.length, which is after all characters.
+*/
int QSGTextEdit::positionAt(int x, int y) const
{
Q_D(const QSGTextEdit);
@@ -388,6 +700,43 @@ int QSGTextEdit::positionAt(int x, int y) const
return r;
}
+/*!
+ \qmlmethod void QtQuick2::TextEdit::moveCursorSelection(int position, SelectionMode mode = TextEdit.SelectCharacters)
+
+ Moves the cursor to \a position and updates the selection according to the optional \a mode
+ parameter. (To only move the cursor, set the \l cursorPosition property.)
+
+ When this method is called it additionally sets either the
+ selectionStart or the selectionEnd (whichever was at the previous cursor position)
+ to the specified position. This allows you to easily extend and contract the selected
+ text range.
+
+ The selection mode specifies whether the selection is updated on a per character or a per word
+ basis. If not specified the selection mode will default to TextEdit.SelectCharacters.
+
+ \list
+ \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
+ the previous cursor position) to the specified position.
+ \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all
+ words between the specified postion and the previous cursor position. Words partially in the
+ range are included.
+ \endlist
+
+ For example, take this sequence of calls:
+
+ \code
+ cursorPosition = 5
+ moveCursorSelection(9, TextEdit.SelectCharacters)
+ moveCursorSelection(7, TextEdit.SelectCharacters)
+ \endcode
+
+ This moves the cursor to position 5, extend the selection end from 5 to 9
+ and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
+ selected (the 6th and 7th characters).
+
+ The same sequence with TextEdit.SelectWords will extend the selection start to a word boundary
+ before or on position 5 and extend the selection end to a word boundary on or past position 9.
+*/
void QSGTextEdit::moveCursorSelection(int pos)
{
//Note that this is the same as setCursorPosition but with the KeepAnchor flag set
@@ -448,6 +797,13 @@ void QSGTextEdit::moveCursorSelection(int pos, SelectionMode mode)
d->control->setTextCursor(cursor);
}
+/*!
+ \qmlproperty bool QtQuick2::TextEdit::cursorVisible
+ If true the text edit shows a cursor.
+
+ This property is set and unset when the text edit gets active focus, but it can also
+ be set directly (useful, for example, if a KeyProxy might forward keys to it).
+*/
bool QSGTextEdit::isCursorVisible() const
{
Q_D(const QSGTextEdit);
@@ -467,6 +823,10 @@ void QSGTextEdit::setCursorVisible(bool on)
emit cursorVisibleChanged(d->cursorVisible);
}
+/*!
+ \qmlproperty int QtQuick2::TextEdit::cursorPosition
+ The position of the cursor in the TextEdit.
+*/
int QSGTextEdit::cursorPosition() const
{
Q_D(const QSGTextEdit);
@@ -485,6 +845,19 @@ void QSGTextEdit::setCursorPosition(int pos)
d->control->setTextCursor(cursor);
}
+/*!
+ \qmlproperty Component QtQuick2::TextEdit::cursorDelegate
+ The delegate for the cursor in the TextEdit.
+
+ If you set a cursorDelegate for a TextEdit, this delegate will be used for
+ drawing the cursor instead of the standard cursor. An instance of the
+ delegate will be created and managed by the text edit when a cursor is
+ needed, and the x and y properties of delegate instance will be set so as
+ to be one pixel before the top left of the current character.
+
+ Note that the root item of the delegate component must be a QDeclarativeItem or
+ QDeclarativeItem derived item.
+*/
QDeclarativeComponent* QSGTextEdit::cursorDelegate() const
{
Q_D(const QSGTextEdit);
@@ -497,7 +870,7 @@ void QSGTextEdit::setCursorDelegate(QDeclarativeComponent* c)
if(d->cursorComponent){
if(d->cursor){
d->control->setCursorWidth(-1);
- update(cursorRectangle());
+ updateCursor();
delete d->cursor;
d->cursor = 0;
}
@@ -522,7 +895,7 @@ void QSGTextEdit::loadCursorDelegate()
d->cursor = qobject_cast<QSGItem*>(d->cursorComponent->create(qmlContext(this)));
if(d->cursor){
d->control->setCursorWidth(0);
- update(cursorRectangle());
+ updateCursor();
QDeclarative_setParent_noEvent(d->cursor, this);
d->cursor->setParentItem(this);
d->cursor->setHeight(QFontMetrics(d->font).height());
@@ -532,24 +905,64 @@ void QSGTextEdit::loadCursorDelegate()
}
}
+/*!
+ \qmlproperty int QtQuick2::TextEdit::selectionStart
+
+ The cursor position before the first character in the current selection.
+
+ This property is read-only. To change the selection, use select(start,end),
+ selectAll(), or selectWord().
+
+ \sa selectionEnd, cursorPosition, selectedText
+*/
int QSGTextEdit::selectionStart() const
{
Q_D(const QSGTextEdit);
return d->control->textCursor().selectionStart();
}
+/*!
+ \qmlproperty int QtQuick2::TextEdit::selectionEnd
+
+ The cursor position after the last character in the current selection.
+
+ This property is read-only. To change the selection, use select(start,end),
+ selectAll(), or selectWord().
+
+ \sa selectionStart, cursorPosition, selectedText
+*/
int QSGTextEdit::selectionEnd() const
{
Q_D(const QSGTextEdit);
return d->control->textCursor().selectionEnd();
}
+/*!
+ \qmlproperty string QtQuick2::TextEdit::selectedText
+
+ This read-only property provides the text currently selected in the
+ text edit.
+
+ It is equivalent to the following snippet, but is faster and easier
+ to use.
+ \code
+ //myTextEdit is the id of the TextEdit
+ myTextEdit.text.toString().substring(myTextEdit.selectionStart,
+ myTextEdit.selectionEnd);
+ \endcode
+*/
QString QSGTextEdit::selectedText() const
{
Q_D(const QSGTextEdit);
return d->control->textCursor().selectedText();
}
+/*!
+ \qmlproperty bool QtQuick2::TextEdit::activeFocusOnPress
+
+ Whether the TextEdit should gain active focus on a mouse press. By default this is
+ set to true.
+*/
bool QSGTextEdit::focusOnPress() const
{
Q_D(const QSGTextEdit);
@@ -565,6 +978,12 @@ void QSGTextEdit::setFocusOnPress(bool on)
emit activeFocusOnPressChanged(d->focusOnPress);
}
+/*!
+ \qmlproperty bool QtQuick2::TextEdit::persistentSelection
+
+ Whether the TextEdit should keep the selection visible when it loses active focus to another
+ item in the scene. By default this is set to true;
+*/
bool QSGTextEdit::persistentSelection() const
{
Q_D(const QSGTextEdit);
@@ -580,6 +999,11 @@ void QSGTextEdit::setPersistentSelection(bool on)
emit persistentSelectionChanged(d->persistentSelection);
}
+/*
+ \qmlproperty real QtQuick2::TextEdit::textMargin
+
+ The margin, in pixels, around the text in the TextEdit.
+*/
qreal QSGTextEdit::textMargin() const
{
Q_D(const QSGTextEdit);
@@ -601,21 +1025,40 @@ void QSGTextEdit::geometryChanged(const QRectF &newGeometry,
{
if (newGeometry.width() != oldGeometry.width())
updateSize();
- QSGPaintedItem::geometryChanged(newGeometry, oldGeometry);
+ QSGImplicitSizeItem::geometryChanged(newGeometry, oldGeometry);
}
+/*!
+ Ensures any delayed caching or data loading the class
+ needs to performed is complete.
+*/
void QSGTextEdit::componentComplete()
{
Q_D(QSGTextEdit);
- QSGPaintedItem::componentComplete();
+ QSGImplicitSizeItem::componentComplete();
+
+ if (d->richText) {
+ d->isComplexRichText = QSGTextNode::isComplexRichText(d->document);
+ }
+
if (d->dirty) {
d->determineHorizontalAlignment();
d->updateDefaultTextOption();
updateSize();
d->dirty = false;
}
+
}
+/*!
+ \qmlproperty bool QtQuick2::TextEdit::selectByMouse
+ Defaults to false.
+
+ If true, the user can use the mouse to select text in some
+ platform-specific way. Note that for some platforms this may
+ not be an appropriate interaction (eg. may conflict with how
+ the text needs to behave inside a Flickable.
+*/
bool QSGTextEdit::selectByMouse() const
{
Q_D(const QSGTextEdit);
@@ -636,6 +1079,18 @@ void QSGTextEdit::setSelectByMouse(bool on)
}
}
+/*!
+ \qmlproperty enum QtQuick2::TextEdit::mouseSelectionMode
+
+ Specifies how text should be selected using a mouse.
+
+ \list
+ \o TextEdit.SelectCharacters - The selection is updated with individual characters. (Default)
+ \o TextEdit.SelectWords - The selection is updated with whole words.
+ \endlist
+
+ This property only applies when \l selectByMouse is true.
+*/
QSGTextEdit::SelectionMode QSGTextEdit::mouseSelectionMode() const
{
Q_D(const QSGTextEdit);
@@ -652,6 +1107,14 @@ void QSGTextEdit::setMouseSelectionMode(SelectionMode mode)
}
}
+/*!
+ \qmlproperty bool QtQuick2::TextEdit::readOnly
+
+ Whether the user can interact with the TextEdit item. If this
+ property is set to true the text cannot be edited by user interaction.
+
+ By default this property is false.
+*/
void QSGTextEdit::setReadOnly(bool r)
{
Q_D(QSGTextEdit);
@@ -677,18 +1140,32 @@ bool QSGTextEdit::isReadOnly() const
return !(d->control->textInteractionFlags() & Qt::TextEditable);
}
+/*!
+ Sets how the text edit should interact with user input to the given
+ \a flags.
+*/
void QSGTextEdit::setTextInteractionFlags(Qt::TextInteractionFlags flags)
{
Q_D(QSGTextEdit);
d->control->setTextInteractionFlags(flags);
}
+/*!
+ Returns the flags specifying how the text edit should interact
+ with user input.
+*/
Qt::TextInteractionFlags QSGTextEdit::textInteractionFlags() const
{
Q_D(const QSGTextEdit);
return d->control->textInteractionFlags();
}
+/*!
+ \qmlproperty rectangle QtQuick2::TextEdit::cursorRectangle
+
+ The rectangle where the text cursor is rendered
+ within the text edit. Read-only.
+*/
QRect QSGTextEdit::cursorRectangle() const
{
Q_D(const QSGTextEdit);
@@ -702,7 +1179,7 @@ bool QSGTextEdit::event(QEvent *event)
d->control->processEvent(event, QPointF(0, -d->yoff));
return event->isAccepted();
}
- return QSGPaintedItem::event(event);
+ return QSGImplicitSizeItem::event(event);
}
/*!
@@ -714,7 +1191,7 @@ void QSGTextEdit::keyPressEvent(QKeyEvent *event)
Q_D(QSGTextEdit);
d->control->processEvent(event, QPointF(0, -d->yoff));
if (!event->isAccepted())
- QSGPaintedItem::keyPressEvent(event);
+ QSGImplicitSizeItem::keyPressEvent(event);
}
/*!
@@ -726,9 +1203,14 @@ void QSGTextEdit::keyReleaseEvent(QKeyEvent *event)
Q_D(QSGTextEdit);
d->control->processEvent(event, QPointF(0, -d->yoff));
if (!event->isAccepted())
- QSGPaintedItem::keyReleaseEvent(event);
+ QSGImplicitSizeItem::keyReleaseEvent(event);
}
+/*!
+ \qmlmethod void QtQuick2::TextEdit::deselect()
+
+ Removes active text selection.
+*/
void QSGTextEdit::deselect()
{
Q_D(QSGTextEdit);
@@ -737,12 +1219,22 @@ void QSGTextEdit::deselect()
d->control->setTextCursor(c);
}
+/*!
+ \qmlmethod void QtQuick2::TextEdit::selectAll()
+
+ Causes all text to be selected.
+*/
void QSGTextEdit::selectAll()
{
Q_D(QSGTextEdit);
d->control->selectAll();
}
+/*!
+ \qmlmethod void QtQuick2::TextEdit::selectWord()
+
+ Causes the word closest to the current cursor position to be selected.
+*/
void QSGTextEdit::selectWord()
{
Q_D(QSGTextEdit);
@@ -751,6 +1243,19 @@ void QSGTextEdit::selectWord()
d->control->setTextCursor(c);
}
+/*!
+ \qmlmethod void QtQuick2::TextEdit::select(int start, int end)
+
+ Causes the text from \a start to \a end to be selected.
+
+ If either start or end is out of range, the selection is not changed.
+
+ After calling this, selectionStart will become the lesser
+ and selectionEnd will become the greater (regardless of the order passed
+ to this method).
+
+ \sa selectionStart, selectionEnd
+*/
void QSGTextEdit::select(int start, int end)
{
Q_D(QSGTextEdit);
@@ -767,6 +1272,12 @@ void QSGTextEdit::select(int start, int end)
updateSelectionMarkers();
}
+/*!
+ \qmlmethod void QtQuick2::TextEdit::isRightToLeft(int start, int end)
+
+ Returns true if the natural reading direction of the editor text
+ found between positions \a start and \a end is right to left.
+*/
bool QSGTextEdit::isRightToLeft(int start, int end)
{
Q_D(QSGTextEdit);
@@ -779,18 +1290,33 @@ bool QSGTextEdit::isRightToLeft(int start, int end)
}
#ifndef QT_NO_CLIPBOARD
+/*!
+ \qmlmethod QtQuick2::TextEdit::cut()
+
+ Moves the currently selected text to the system clipboard.
+*/
void QSGTextEdit::cut()
{
Q_D(QSGTextEdit);
d->control->cut();
}
+/*!
+ \qmlmethod QtQuick2::TextEdit::copy()
+
+ Copies the currently selected text to the system clipboard.
+*/
void QSGTextEdit::copy()
{
Q_D(QSGTextEdit);
d->control->copy();
}
+/*!
+ \qmlmethod QtQuick2::TextEdit::paste()
+
+ Replaces the currently selected text by the contents of the system clipboard.
+*/
void QSGTextEdit::paste()
{
Q_D(QSGTextEdit);
@@ -821,7 +1347,7 @@ void QSGTextEdit::mousePressEvent(QGraphicsSceneMouseEvent *event)
}
d->control->processEvent(event, QPointF(0, -d->yoff));
if (!event->isAccepted())
- QSGPaintedItem::mousePressEvent(event);
+ QSGImplicitSizeItem::mousePressEvent(event);
}
/*!
@@ -844,7 +1370,7 @@ void QSGTextEdit::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
d->clickCausedFocus = false;
if (!event->isAccepted())
- QSGPaintedItem::mouseReleaseEvent(event);
+ QSGImplicitSizeItem::mouseReleaseEvent(event);
}
/*!
@@ -856,7 +1382,7 @@ void QSGTextEdit::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
Q_D(QSGTextEdit);
d->control->processEvent(event, QPointF(0, -d->yoff));
if (!event->isAccepted())
- QSGPaintedItem::mouseDoubleClickEvent(event);
+ QSGImplicitSizeItem::mouseDoubleClickEvent(event);
}
/*!
@@ -868,7 +1394,7 @@ void QSGTextEdit::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
Q_D(QSGTextEdit);
d->control->processEvent(event, QPointF(0, -d->yoff));
if (!event->isAccepted())
- QSGPaintedItem::mouseMoveEvent(event);
+ QSGImplicitSizeItem::mouseMoveEvent(event);
}
/*!
@@ -903,49 +1429,162 @@ QVariant QSGTextEdit::inputMethodQuery(Qt::InputMethodQuery property) const
return d->control->inputMethodQuery(property);
}
-/*!
-Draws the contents of the text edit using the given \a painter within
-the given \a bounds.
-*/
-void QSGTextEdit::paint(QPainter *painter)
+void QSGTextEdit::updateImageCache(const QRectF &)
{
- // XXX todo
- QRect bounds(0, 0, width(), height());
Q_D(QSGTextEdit);
- painter->setRenderHint(QPainter::TextAntialiasing, true);
- painter->translate(0,d->yoff);
+ // Do we really need the image cache?
+ if (!d->richText || !d->isComplexRichText) {
+ if (!d->pixmapCache.isNull())
+ d->pixmapCache = QPixmap();
+ return;
+ }
+
+ if (width() != d->pixmapCache.width() || height() != d->pixmapCache.height())
+ d->pixmapCache = QPixmap(width(), height());
+
+ if (d->pixmapCache.isNull())
+ return;
+
+ // ### Use supplied rect, clear area and update only this part (for cursor updates)
+ QRectF bounds = QRectF(0, 0, width(), height());
+ d->pixmapCache.fill(Qt::transparent);
+ {
+ QPainter painter(&d->pixmapCache);
- d->control->drawContents(painter, bounds.translated(0,-d->yoff));
+ painter.setRenderHint(QPainter::TextAntialiasing);
+ painter.translate(0, d->yoff);
+
+ d->control->drawContents(&painter, bounds);
+ }
- painter->translate(0,-d->yoff);
}
-void QSGTextEdit::updateImgCache(const QRectF &rf)
+QSGNode *QSGTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData)
{
- Q_D(const QSGTextEdit);
- QRect r;
- if (!rf.isValid()) {
- r = QRect(0,0,INT_MAX,INT_MAX);
- } else {
- r = rf.toRect();
- if (r.height() > INT_MAX/2) {
- // Take care of overflow when translating "everything"
- r.setTop(r.y() + d->yoff);
- r.setBottom(INT_MAX/2);
+ Q_UNUSED(updatePaintNodeData);
+ Q_D(QSGTextEdit);
+
+ QSGNode *currentNode = oldNode;
+ if (d->richText && d->isComplexRichText) {
+ QSGImageNode *node = 0;
+ if (oldNode == 0 || d->nodeType != QSGTextEditPrivate::NodeIsTexture) {
+ delete oldNode;
+ node = QSGItemPrivate::get(this)->sceneGraphContext()->createImageNode();
+ d->texture = new QSGPlainTexture();
+ d->nodeType = QSGTextEditPrivate::NodeIsTexture;
+ currentNode = node;
+ } else {
+ node = static_cast<QSGImageNode *>(oldNode);
+ }
+
+ qobject_cast<QSGPlainTexture *>(d->texture)->setImage(d->pixmapCache.toImage());
+ node->setTexture(0);
+ node->setTexture(d->texture);
+
+ node->setTargetRect(QRectF(0, 0, d->pixmapCache.width(), d->pixmapCache.height()));
+ node->setSourceRect(QRectF(0, 0, 1, 1));
+ node->setHorizontalWrapMode(QSGTexture::ClampToEdge);
+ node->setVerticalWrapMode(QSGTexture::ClampToEdge);
+ node->setFiltering(QSGTexture::Linear); // Nonsmooth text just ugly, so don't do that..
+ node->update();
+
+ } else if (oldNode == 0 || d->documentDirty) {
+ d->documentDirty = false;
+
+#if defined(Q_WS_MAC)
+ // Make sure document is relayouted in the paint node on Mac
+ // to avoid crashes due to the font engines created in the
+ // shaping process
+ d->document->markContentsDirty(0, d->document->characterCount());
+#endif
+
+ QSGTextNode *node = 0;
+ if (oldNode == 0 || d->nodeType != QSGTextEditPrivate::NodeIsText) {
+ delete oldNode;
+ node = new QSGTextNode(QSGItemPrivate::get(this)->sceneGraphContext());
+ d->nodeType = QSGTextEditPrivate::NodeIsText;
+ currentNode = node;
} else {
- r = r.translated(0,d->yoff);
+ node = static_cast<QSGTextNode *>(oldNode);
}
+
+ node->deleteContent();
+ node->setMatrix(QMatrix4x4());
+
+ QRectF bounds = boundingRect();
+
+ QColor selectionColor = d->control->palette().color(QPalette::Highlight);
+ QColor selectedTextColor = d->control->palette().color(QPalette::HighlightedText);
+ node->addTextDocument(bounds.topLeft(), d->document, d->color, QSGText::Normal, QColor(),
+ selectionColor, selectedTextColor, selectionStart(),
+ selectionEnd());
+
+#if defined(Q_WS_MAC)
+ // We also need to make sure the document layout is redone when
+ // control is returned to the main thread, as all the font engines
+ // are now owned by the rendering thread
+ d->document->markContentsDirty(0, d->document->characterCount());
+#endif
}
- update(r);
+
+ if (d->nodeType == QSGTextEditPrivate::NodeIsText && d->cursorComponent == 0 && !isReadOnly()) {
+ QSGTextNode *node = static_cast<QSGTextNode *>(currentNode);
+
+ QColor color = (!d->cursorVisible || !d->control->cursorOn())
+ ? QColor(0, 0, 0, 0)
+ : d->color;
+
+ if (node->cursorNode() == 0) {
+ node->setCursor(cursorRectangle(), color);
+ } else {
+ node->cursorNode()->setRect(cursorRectangle());
+ node->cursorNode()->setColor(color);
+ }
+
+ }
+
+ return currentNode;
}
+/*!
+ \qmlproperty bool QtQuick2::TextEdit::smooth
+
+ This property holds whether the text is smoothly scaled or transformed.
+
+ Smooth filtering gives better visual quality, but is slower. If
+ the item is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the item is stationary on
+ the screen. A common pattern when animating an item is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::TextEdit::canPaste
+
+ Returns true if the TextEdit is writable and the content of the clipboard is
+ suitable for pasting into the TextEdit.
+*/
bool QSGTextEdit::canPaste() const
{
Q_D(const QSGTextEdit);
return d->canPaste;
}
+/*!
+ \qmlproperty bool QtQuick2::TextEdit::inputMethodComposing
+
+
+ This property holds whether the TextEdit has partial text input from an
+ input method.
+
+ While it is composing an input method may rely on mouse or key events from
+ the TextEdit to edit or commit the partial text. This property can be used
+ to determine when to disable events handlers that may interfere with the
+ correct operation of an input method.
+*/
bool QSGTextEdit::isInputMethodComposing() const
{
Q_D(const QSGTextEdit);
@@ -961,12 +1600,22 @@ void QSGTextEditPrivate::init()
q->setSmooth(smooth);
q->setAcceptedMouseButtons(Qt::LeftButton);
q->setFlag(QSGItem::ItemAcceptsInputMethod);
+ q->setFlag(QSGItem::ItemHasContents);
control = new QTextControl(q);
control->setIgnoreUnusedNavigationEvents(true);
control->setTextInteractionFlags(Qt::LinksAccessibleByMouse | Qt::TextSelectableByKeyboard | Qt::TextEditable);
control->setDragEnabled(false);
+ // By default, QTextControl will issue both a updateCursorRequest() and an updateRequest()
+ // when the cursor needs to be repainted. We need the signals to be separate to be able to
+ // distinguish the cursor updates so that we can avoid updating the whole subtree when the
+ // cursor blinks.
+ if (!QObject::disconnect(control, SIGNAL(updateCursorRequest(QRectF)),
+ control, SIGNAL(updateRequest(QRectF)))) {
+ qWarning("QSGTextEditPrivate::init: Failed to disconnect updateCursorRequest and updateRequest");
+ }
+
// QTextControl follows the default text color
// defined by the platform, declarative text
// should be black by default
@@ -976,8 +1625,8 @@ void QSGTextEditPrivate::init()
control->setPalette(pal);
}
- QObject::connect(control, SIGNAL(updateRequest(QRectF)), q, SLOT(updateImgCache(QRectF)));
-
+ QObject::connect(control, SIGNAL(updateRequest(QRectF)), q, SLOT(updateDocument()));
+ QObject::connect(control, SIGNAL(updateCursorRequest()), q, SLOT(updateCursor()));
QObject::connect(control, SIGNAL(textChanged()), q, SLOT(q_textChanged()));
QObject::connect(control, SIGNAL(selectionChanged()), q, SIGNAL(selectionChanged()));
QObject::connect(control, SIGNAL(selectionChanged()), q, SLOT(updateSelectionMarkers()));
@@ -1056,7 +1705,7 @@ void QSGTextEdit::updateSelectionMarkers()
QRectF QSGTextEdit::boundingRect() const
{
Q_D(const QSGTextEdit);
- QRectF r = QSGPaintedItem::boundingRect();
+ QRectF r = QSGImplicitSizeItem::boundingRect();
int cursorWidth = 1;
if(d->cursor)
cursorWidth = d->cursor->width();
@@ -1121,7 +1770,7 @@ void QSGTextEdit::updateSize()
} else {
nyoff = 0;
}
- if (nyoff != d->yoff)
+ if (nyoff != d->yoff)
d->yoff = nyoff;
setBaselineOffset(fm.ascent() + d->yoff + d->textMargin);
@@ -1138,12 +1787,31 @@ void QSGTextEdit::updateSize()
setImplicitHeight(newHeight);
d->paintedSize = QSize(newWidth, newHeight);
- setContentsSize(d->paintedSize);
emit paintedSizeChanged();
} else {
d->dirty = true;
}
- update();
+ updateDocument();
+}
+
+void QSGTextEdit::updateDocument()
+{
+ Q_D(QSGTextEdit);
+ d->documentDirty = true;
+
+ if (isComponentComplete()) {
+ updateImageCache();
+ update();
+ }
+}
+
+void QSGTextEdit::updateCursor()
+{
+ Q_D(QSGTextEdit);
+ if (isComponentComplete()) {
+ updateImageCache(d->control->cursorRect());
+ update();
+ }
}
void QSGTextEdit::updateTotalLines()
@@ -1184,12 +1852,59 @@ void QSGTextEditPrivate::updateDefaultTextOption()
QTextOption::WrapMode oldWrapMode = opt.wrapMode();
opt.setWrapMode(QTextOption::WrapMode(wrapMode));
- if (oldWrapMode == opt.wrapMode() && oldAlignment == opt.alignment())
+ bool oldUseDesignMetrics = opt.useDesignMetrics();
+ bool useDesignMetrics = !qmlDisableDistanceField();
+ opt.setUseDesignMetrics(useDesignMetrics);
+
+ if (oldWrapMode == opt.wrapMode()
+ && oldAlignment == opt.alignment()
+ && oldUseDesignMetrics == useDesignMetrics) {
return;
+ }
document->setDefaultTextOption(opt);
}
+
+/*!
+ \qmlmethod void QtQuick2::TextEdit::openSoftwareInputPanel()
+
+ Opens software input panels like virtual keyboards for typing, useful for
+ customizing when you want the input keyboard to be shown and hidden in
+ your application.
+
+ By default the opening of input panels follows the platform style. On Symbian^1 and
+ Symbian^3 -based devices the panels are opened by clicking TextEdit. On other platforms
+ the panels are automatically opened when TextEdit element gains active focus. Input panels are
+ always closed if no editor has active focus.
+
+ You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
+ and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
+ the behavior you want.
+
+ Only relevant on platforms, which provide virtual keyboards.
+
+ \code
+ import QtQuick 1.0
+ TextEdit {
+ id: textEdit
+ text: "Hello world!"
+ activeFocusOnPress: false
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ if (!textEdit.activeFocus) {
+ textEdit.forceActiveFocus();
+ textEdit.openSoftwareInputPanel();
+ } else {
+ textEdit.focus = false;
+ }
+ }
+ onPressAndHold: textEdit.closeSoftwareInputPanel();
+ }
+ }
+ \endcode
+*/
void QSGTextEdit::openSoftwareInputPanel()
{
if (qApp) {
@@ -1200,6 +1915,45 @@ void QSGTextEdit::openSoftwareInputPanel()
}
}
+/*!
+ \qmlmethod void QtQuick2::TextEdit::closeSoftwareInputPanel()
+
+ Closes a software input panel like a virtual keyboard shown on the screen, useful
+ for customizing when you want the input keyboard to be shown and hidden in
+ your application.
+
+ By default the opening of input panels follows the platform style. On Symbian^1 and
+ Symbian^3 -based devices the panels are opened by clicking TextEdit. On other platforms
+ the panels are automatically opened when TextEdit element gains active focus. Input panels are
+ always closed if no editor has active focus.
+
+ You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
+ and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
+ the behavior you want.
+
+ Only relevant on platforms, which provide virtual keyboards.
+
+ \code
+ import QtQuick 1.0
+ TextEdit {
+ id: textEdit
+ text: "Hello world!"
+ activeFocusOnPress: false
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ if (!textEdit.activeFocus) {
+ textEdit.forceActiveFocus();
+ textEdit.openSoftwareInputPanel();
+ } else {
+ textEdit.focus = false;
+ }
+ }
+ onPressAndHold: textEdit.closeSoftwareInputPanel();
+ }
+ }
+ \endcode
+*/
void QSGTextEdit::closeSoftwareInputPanel()
{
if (qApp) {
@@ -1218,7 +1972,7 @@ void QSGTextEdit::focusInEvent(QFocusEvent *event)
openSoftwareInputPanel();
}
}
- QSGPaintedItem::focusInEvent(event);
+ QSGImplicitSizeItem::focusInEvent(event);
}
void QSGTextEdit::q_canPasteChanged()
diff --git a/src/declarative/items/qsgtextedit_p.h b/src/declarative/items/qsgtextedit_p.h
index 115b25040d..fa61f03f7f 100644
--- a/src/declarative/items/qsgtextedit_p.h
+++ b/src/declarative/items/qsgtextedit_p.h
@@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
class QSGTextEditPrivate;
-class Q_AUTOTEST_EXPORT QSGTextEdit : public QSGImplicitSizePaintedItem
+class Q_AUTOTEST_EXPORT QSGTextEdit : public QSGImplicitSizeItem
{
Q_OBJECT
Q_ENUMS(VAlignment)
@@ -260,16 +260,18 @@ public Q_SLOTS:
#endif
private Q_SLOTS:
- void updateImgCache(const QRectF &rect);
void q_textChanged();
void updateSelectionMarkers();
void moveCursorDelegate();
void loadCursorDelegate();
void q_canPasteChanged();
+ void updateDocument();
+ void updateCursor();
private:
void updateSize();
void updateTotalLines();
+ void updateImageCache(const QRectF &rect = QRectF());
protected:
virtual void geometryChanged(const QRectF &newGeometry,
@@ -288,7 +290,8 @@ protected:
void inputMethodEvent(QInputMethodEvent *e);
virtual void itemChange(ItemChange, const ItemChangeData &);
- void paint(QPainter *);
+ QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData);
+
private:
Q_DISABLE_COPY(QSGTextEdit)
Q_DECLARE_PRIVATE(QSGTextEdit)
diff --git a/src/declarative/items/qsgtextedit_p_p.h b/src/declarative/items/qsgtextedit_p_p.h
index c080857e46..e4f74c0ef5 100644
--- a/src/declarative/items/qsgtextedit_p_p.h
+++ b/src/declarative/items/qsgtextedit_p_p.h
@@ -63,21 +63,21 @@ QT_BEGIN_NAMESPACE
class QTextLayout;
class QTextDocument;
class QTextControl;
-class QSGTextEditPrivate : public QSGImplicitSizePaintedItemPrivate
+class QSGTextEditPrivate : public QSGImplicitSizeItemPrivate
{
Q_DECLARE_PUBLIC(QSGTextEdit)
public:
QSGTextEditPrivate()
: color("black"), hAlign(QSGTextEdit::AlignLeft), vAlign(QSGTextEdit::AlignTop),
- imgDirty(true), dirty(false), richText(false), cursorVisible(false), focusOnPress(true),
+ documentDirty(true), dirty(false), richText(false), cursorVisible(false), focusOnPress(true),
showInputPanelOnFocus(true), clickCausedFocus(false), persistentSelection(true),
requireImplicitWidth(false), selectByMouse(false), canPaste(false),
- hAlignImplicit(true), rightToLeftText(false),
+ hAlignImplicit(true), rightToLeftText(false), isComplexRichText(false),
textMargin(0.0), lastSelectionStart(0), lastSelectionEnd(0), cursorComponent(0), cursor(0),
format(QSGTextEdit::AutoText), document(0), wrapMode(QSGTextEdit::NoWrap),
mouseSelectionMode(QSGTextEdit::SelectCharacters),
- yoff(0)
+ yoff(0), nodeType(NodeIsNull), texture(0)
{
#ifdef Q_OS_SYMBIAN
if (QSysInfo::symbianVersion() == QSysInfo::SV_SF_1 || QSysInfo::symbianVersion() == QSysInfo::SV_SF_3) {
@@ -104,12 +104,10 @@ public:
QColor selectedTextColor;
QString style;
QColor styleColor;
- QPixmap imgCache;
- QPixmap imgStyleCache;
QSGTextEdit::HAlignment hAlign;
QSGTextEdit::VAlignment vAlign;
- bool imgDirty : 1;
+ bool documentDirty : 1;
bool dirty : 1;
bool richText : 1;
bool cursorVisible : 1;
@@ -122,6 +120,7 @@ public:
bool canPaste:1;
bool hAlignImplicit:1;
bool rightToLeftText:1;
+ bool isComplexRichText:1;
qreal textMargin;
int lastSelectionStart;
@@ -136,6 +135,15 @@ public:
int lineCount;
int yoff;
QSize paintedSize;
+
+ enum NodeType {
+ NodeIsNull,
+ NodeIsTexture,
+ NodeIsText
+ };
+ NodeType nodeType;
+ QSGTexture *texture;
+ QPixmap pixmapCache;
};
QT_END_NAMESPACE
diff --git a/src/declarative/items/qsgtextinput.cpp b/src/declarative/items/qsgtextinput.cpp
index 405540d419..d30faadb34 100644
--- a/src/declarative/items/qsgtextinput.cpp
+++ b/src/declarative/items/qsgtextinput.cpp
@@ -45,19 +45,43 @@
#include <private/qdeclarativeglobal_p.h>
#include <private/qwidget_p.h>
+#include <private/qsgdistancefieldglyphcache_p.h>
#include <QtDeclarative/qdeclarativeinfo.h>
#include <QtWidgets/qgraphicssceneevent.h>
#include <QtWidgets/qinputcontext.h>
#include <QTextBoundaryFinder>
#include <qstyle.h>
+#include <qsgtextnode_p.h>
+#include <qsgsimplerectnode.h>
QT_BEGIN_NAMESPACE
+DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
+
QWidgetPrivate *qt_widget_private(QWidget *widget);
+/*!
+ \qmlclass TextInput QSGTextInput
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-visual-elements
+ \brief The TextInput item displays an editable line of text.
+ \inherits Item
+
+ The TextInput element displays a single line of editable plain text.
+
+ TextInput is used to accept a line of text input. Input constraints
+ can be placed on a TextInput item (for example, through a \l validator or \l inputMask),
+ and setting \l echoMode to an appropriate value enables TextInput to be used for
+ a password input field.
+
+ On Mac OS X, the Up/Down key bindings for Home/End are explicitly disabled.
+ If you want such bindings (on any platform), you will need to construct them in QML.
+
+ \sa TextEdit, Text, {declarative/text/textselection}{Text Selection example}
+*/
QSGTextInput::QSGTextInput(QSGItem* parent)
-: QSGImplicitSizePaintedItem(*(new QSGTextInputPrivate), parent)
+: QSGImplicitSizeItem(*(new QSGTextInputPrivate), parent)
{
Q_D(QSGTextInput);
d->init();
@@ -67,6 +91,11 @@ QSGTextInput::~QSGTextInput()
{
}
+/*!
+ \qmlproperty string QtQuick2::TextInput::text
+
+ The text in the TextInput.
+*/
QString QSGTextInput::text() const
{
Q_D(const QSGTextInput);
@@ -81,6 +110,111 @@ void QSGTextInput::setText(const QString &s)
d->control->setText(s);
}
+/*!
+ \qmlproperty string QtQuick2::TextInput::font.family
+
+ Sets the family name of the font.
+
+ The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
+ If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
+ If the family isn't available a family will be set using the font matching algorithm.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::TextInput::font.bold
+
+ Sets whether the font weight is bold.
+*/
+
+/*!
+ \qmlproperty enumeration QtQuick2::TextInput::font.weight
+
+ Sets the font's weight.
+
+ The weight can be one of:
+ \list
+ \o Font.Light
+ \o Font.Normal - the default
+ \o Font.DemiBold
+ \o Font.Bold
+ \o Font.Black
+ \endlist
+
+ \qml
+ TextInput { text: "Hello"; font.weight: Font.DemiBold }
+ \endqml
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::TextInput::font.italic
+
+ Sets whether the font has an italic style.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::TextInput::font.underline
+
+ Sets whether the text is underlined.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::TextInput::font.strikeout
+
+ Sets whether the font has a strikeout style.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::TextInput::font.pointSize
+
+ Sets the font size in points. The point size must be greater than zero.
+*/
+
+/*!
+ \qmlproperty int QtQuick2::TextInput::font.pixelSize
+
+ Sets the font size in pixels.
+
+ Using this function makes the font device dependent.
+ Use \c pointSize to set the size of the font in a device independent manner.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::TextInput::font.letterSpacing
+
+ Sets the letter spacing for the font.
+
+ Letter spacing changes the default spacing between individual letters in the font.
+ A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::TextInput::font.wordSpacing
+
+ Sets the word spacing for the font.
+
+ Word spacing changes the default spacing between individual words.
+ A positive value increases the word spacing by a corresponding amount of pixels,
+ while a negative value decreases the inter-word spacing accordingly.
+*/
+
+/*!
+ \qmlproperty enumeration QtQuick2::TextInput::font.capitalization
+
+ Sets the capitalization for the text.
+
+ \list
+ \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
+ \o Font.AllUppercase - This alters the text to be rendered in all uppercase type.
+ \o Font.AllLowercase - This alters the text to be rendered in all lowercase type.
+ \o Font.SmallCaps - This alters the text to be rendered in small-caps type.
+ \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
+ \endlist
+
+ \qml
+ TextInput { text: "Hello"; font.capitalization: Font.AllLowercase }
+ \endqml
+*/
+
QFont QSGTextInput::font() const
{
Q_D(const QSGTextInput);
@@ -112,6 +246,11 @@ void QSGTextInput::setFont(const QFont &font)
emit fontChanged(d->sourceFont);
}
+/*!
+ \qmlproperty color QtQuick2::TextInput::color
+
+ The text color.
+*/
QColor QSGTextInput::color() const
{
Q_D(const QSGTextInput);
@@ -128,6 +267,12 @@ void QSGTextInput::setColor(const QColor &c)
}
}
+
+/*!
+ \qmlproperty color QtQuick2::TextInput::selectionColor
+
+ The text highlight color, used behind selections.
+*/
QColor QSGTextInput::selectionColor() const
{
Q_D(const QSGTextInput);
@@ -144,11 +289,15 @@ void QSGTextInput::setSelectionColor(const QColor &color)
QPalette p = d->control->palette();
p.setColor(QPalette::Highlight, d->selectionColor);
d->control->setPalette(p);
- if (d->control->hasSelectedText())
+ if (d->control->hasSelectedText())
update();
emit selectionColorChanged(color);
}
+/*!
+ \qmlproperty color QtQuick2::TextInput::selectedTextColor
+ The highlighted text color, used in selections.
+*/
QColor QSGTextInput::selectedTextColor() const
{
Q_D(const QSGTextInput);
@@ -165,11 +314,34 @@ void QSGTextInput::setSelectedTextColor(const QColor &color)
QPalette p = d->control->palette();
p.setColor(QPalette::HighlightedText, d->selectedTextColor);
d->control->setPalette(p);
- if (d->control->hasSelectedText())
+ if (d->control->hasSelectedText())
update();
emit selectedTextColorChanged(color);
}
+/*!
+ \qmlproperty enumeration QtQuick2::TextInput::horizontalAlignment
+ \qmlproperty enumeration QtQuick2::TextInput::effectiveHorizontalAlignment
+
+ Sets the horizontal alignment of the text within the TextInput item's
+ width and height. By default, the text alignment follows the natural alignment
+ of the text, for example text that is read from left to right will be aligned to
+ the left.
+
+ TextInput does not have vertical alignment, as the natural height is
+ exactly the height of the single line of text. If you set the height
+ manually to something larger, TextInput will always be top aligned
+ vertically. You can use anchors to align it however you want within
+ another item.
+
+ The valid values for \c horizontalAlignment are \c TextInput.AlignLeft, \c TextInput.AlignRight and
+ \c TextInput.AlignHCenter.
+
+ When using the attached property LayoutMirroring::enabled to mirror application
+ layouts, the horizontal alignment of text will also be mirrored. However, the property
+ \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
+ of TextInput, use the read-only property \c effectiveHorizontalAlignment.
+*/
QSGTextInput::HAlignment QSGTextInput::hAlign() const
{
Q_D(const QSGTextInput);
@@ -250,6 +422,15 @@ void QSGTextInputPrivate::mirrorChange()
}
}
+/*!
+ \qmlproperty bool QtQuick2::TextInput::readOnly
+
+ Sets whether user input can modify the contents of the TextInput.
+
+ If readOnly is set to true, then user input will not affect the text
+ property. Any bindings or attempts to set the text property will still
+ work.
+*/
bool QSGTextInput::isReadOnly() const
{
Q_D(const QSGTextInput);
@@ -270,6 +451,14 @@ void QSGTextInput::setReadOnly(bool ro)
emit readOnlyChanged(ro);
}
+/*!
+ \qmlproperty int QtQuick2::TextInput::maximumLength
+ The maximum permitted length of the text in the TextInput.
+
+ If the text is too long, it is truncated at the limit.
+
+ By default, this property contains a value of 32767.
+*/
int QSGTextInput::maxLength() const
{
Q_D(const QSGTextInput);
@@ -287,6 +476,32 @@ void QSGTextInput::setMaxLength(int ml)
emit maximumLengthChanged(ml);
}
+/*!
+ \qmlproperty bool QtQuick2::TextInput::cursorVisible
+ Set to true when the TextInput shows a cursor.
+
+ This property is set and unset when the TextInput gets active focus, so that other
+ properties can be bound to whether the cursor is currently showing. As it
+ gets set and unset automatically, when you set the value yourself you must
+ keep in mind that your value may be overwritten.
+
+ It can be set directly in script, for example if a KeyProxy might
+ forward keys to it and you desire it to look active when this happens
+ (but without actually giving it active focus).
+
+ It should not be set directly on the element, like in the below QML,
+ as the specified value will be overridden an lost on focus changes.
+
+ \code
+ TextInput {
+ text: "Text"
+ cursorVisible: false
+ }
+ \endcode
+
+ In the above snippet the cursor will still become visible when the
+ TextInput gains active focus.
+*/
bool QSGTextInput::isCursorVisible() const
{
Q_D(const QSGTextInput);
@@ -308,6 +523,10 @@ void QSGTextInput::setCursorVisible(bool on)
emit cursorVisibleChanged(d->cursorVisible);
}
+/*!
+ \qmlproperty int QtQuick2::TextInput::cursorPosition
+ The position of the cursor in the TextInput.
+*/
int QSGTextInput::cursorPosition() const
{
Q_D(const QSGTextInput);
@@ -321,6 +540,10 @@ void QSGTextInput::setCursorPosition(int cp)
d->control->moveCursor(cp);
}
+/*!
+ Returns a Rect which encompasses the cursor, but which may be larger than is
+ required. Ignores custom cursor delegates.
+*/
QRect QSGTextInput::cursorRectangle() const
{
Q_D(const QSGTextInput);
@@ -331,19 +554,49 @@ QRect QSGTextInput::cursorRectangle() const
r.adjust(5 - d->hscroll, 0, -4 - d->hscroll, -1);
return r;
}
+/*!
+ \qmlproperty int QtQuick2::TextInput::selectionStart
+
+ The cursor position before the first character in the current selection.
+
+ This property is read-only. To change the selection, use select(start,end),
+ selectAll(), or selectWord().
+ \sa selectionEnd, cursorPosition, selectedText
+*/
int QSGTextInput::selectionStart() const
{
Q_D(const QSGTextInput);
return d->lastSelectionStart;
}
+/*!
+ \qmlproperty int QtQuick2::TextInput::selectionEnd
+ The cursor position after the last character in the current selection.
+
+ This property is read-only. To change the selection, use select(start,end),
+ selectAll(), or selectWord().
+
+ \sa selectionStart, cursorPosition, selectedText
+*/
int QSGTextInput::selectionEnd() const
{
Q_D(const QSGTextInput);
return d->lastSelectionEnd;
}
+/*!
+ \qmlmethod void QtQuick2::TextInput::select(int start, int end)
+
+ Causes the text from \a start to \a end to be selected.
+
+ If either start or end is out of range, the selection is not changed.
+
+ After calling this, selectionStart will become the lesser
+ and selectionEnd will become the greater (regardless of the order passed
+ to this method).
+ \sa selectionStart, selectionEnd
+*/
void QSGTextInput::select(int start, int end)
{
Q_D(QSGTextInput);
@@ -352,12 +605,32 @@ void QSGTextInput::select(int start, int end)
d->control->setSelection(start, end-start);
}
+/*!
+ \qmlproperty string QtQuick2::TextInput::selectedText
+
+ This read-only property provides the text currently selected in the
+ text input.
+
+ It is equivalent to the following snippet, but is faster and easier
+ to use.
+
+ \js
+ myTextInput.text.toString().substring(myTextInput.selectionStart,
+ myTextInput.selectionEnd);
+ \endjs
+*/
QString QSGTextInput::selectedText() const
{
Q_D(const QSGTextInput);
return d->control->selectedText();
}
+/*!
+ \qmlproperty bool QtQuick2::TextInput::activeFocusOnPress
+
+ Whether the TextInput should gain active focus on a mouse press. By default this is
+ set to true.
+*/
bool QSGTextInput::focusOnPress() const
{
Q_D(const QSGTextInput);
@@ -374,7 +647,12 @@ void QSGTextInput::setFocusOnPress(bool b)
emit activeFocusOnPressChanged(d->focusOnPress);
}
+/*!
+ \qmlproperty bool QtQuick2::TextInput::autoScroll
+ Whether the TextInput should scroll when the text is longer than the width. By default this is
+ set to true.
+*/
bool QSGTextInput::autoScroll() const
{
Q_D(const QSGTextInput);
@@ -395,6 +673,114 @@ void QSGTextInput::setAutoScroll(bool b)
}
#ifndef QT_NO_VALIDATOR
+
+/*!
+ \qmlclass IntValidator QIntValidator
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-visual-elements
+
+ This element provides a validator for integer values.
+
+ IntValidator uses the \l {QLocale::setDefault()}{default locale} to interpret the number and
+ will accept locale specific digits, group separators, and positive and negative signs. In
+ addition, IntValidator is always guaranteed to accept a number formatted according to the "C"
+ locale.
+*/
+/*!
+ \qmlproperty int QtQuick2::IntValidator::top
+
+ This property holds the validator's highest acceptable value.
+ By default, this property's value is derived from the highest signed integer available (typically 2147483647).
+*/
+/*!
+ \qmlproperty int QtQuick2::IntValidator::bottom
+
+ This property holds the validator's lowest acceptable value.
+ By default, this property's value is derived from the lowest signed integer available (typically -2147483647).
+*/
+
+/*!
+ \qmlclass DoubleValidator QDoubleValidator
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-visual-elements
+
+ This element provides a validator for non-integer numbers.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::DoubleValidator::top
+
+ This property holds the validator's maximum acceptable value.
+ By default, this property contains a value of infinity.
+*/
+/*!
+ \qmlproperty real QtQuick2::DoubleValidator::bottom
+
+ This property holds the validator's minimum acceptable value.
+ By default, this property contains a value of -infinity.
+*/
+/*!
+ \qmlproperty int QtQuick2::DoubleValidator::decimals
+
+ This property holds the validator's maximum number of digits after the decimal point.
+ By default, this property contains a value of 1000.
+*/
+/*!
+ \qmlproperty enumeration QtQuick2::DoubleValidator::notation
+ This property holds the notation of how a string can describe a number.
+
+ The possible values for this property are:
+
+ \list
+ \o DoubleValidator.StandardNotation
+ \o DoubleValidator.ScientificNotation (default)
+ \endlist
+
+ If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2).
+*/
+
+/*!
+ \qmlclass RegExpValidator QRegExpValidator
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-visual-elements
+
+ This element provides a validator, which counts as valid any string which
+ matches a specified regular expression.
+*/
+/*!
+ \qmlproperty regExp QtQuick2::RegExpValidator::regExp
+
+ This property holds the regular expression used for validation.
+
+ Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression
+ matching "a".
+
+ By default, this property contains a regular expression with the pattern .* that matches any string.
+*/
+
+/*!
+ \qmlproperty Validator QtQuick2::TextInput::validator
+
+ Allows you to set a validator on the TextInput. When a validator is set
+ the TextInput will only accept input which leaves the text property in
+ an acceptable or intermediate state. The accepted signal will only be sent
+ if the text is in an acceptable state when enter is pressed.
+
+ Currently supported validators are IntValidator, DoubleValidator and
+ RegExpValidator. An example of using validators is shown below, which allows
+ input of integers between 11 and 31 into the text input:
+
+ \code
+ import QtQuick 1.0
+ TextInput{
+ validator: IntValidator{bottom: 11; top: 31;}
+ focus: true
+ }
+ \endcode
+
+ \sa acceptableInput, inputMask
+*/
+
QValidator* QSGTextInput::validator() const
{
Q_D(const QSGTextInput);
@@ -418,6 +804,15 @@ void QSGTextInput::setValidator(QValidator* v)
}
#endif // QT_NO_VALIDATOR
+/*!
+ \qmlproperty string QtQuick2::TextInput::inputMask
+
+ Allows you to set an input mask on the TextInput, restricting the allowable
+ text inputs. See QLineEdit::inputMask for further details, as the exact
+ same mask strings are used by TextInput.
+
+ \sa acceptableInput, validator
+*/
QString QSGTextInput::inputMask() const
{
Q_D(const QSGTextInput);
@@ -434,12 +829,29 @@ void QSGTextInput::setInputMask(const QString &im)
emit inputMaskChanged(d->control->inputMask());
}
+/*!
+ \qmlproperty bool QtQuick2::TextInput::acceptableInput
+
+ This property is always true unless a validator or input mask has been set.
+ If a validator or input mask has been set, this property will only be true
+ if the current text is acceptable to the validator or input mask as a final
+ string (not as an intermediate string).
+*/
bool QSGTextInput::hasAcceptableInput() const
{
Q_D(const QSGTextInput);
return d->control->hasAcceptableInput();
}
+/*!
+ \qmlsignal QtQuick2::TextInput::onAccepted()
+
+ This handler is called when the Return or Enter key is pressed.
+ Note that if there is a \l validator or \l inputMask set on the text
+ input, the handler will only be emitted if the input is in an acceptable
+ state.
+*/
+
void QSGTextInputPrivate::updateInputMethodHints()
{
Q_Q(QSGTextInput);
@@ -453,7 +865,18 @@ void QSGTextInputPrivate::updateInputMethodHints()
hints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
q->setInputMethodHints(hints);
}
-
+/*!
+ \qmlproperty enumeration QtQuick2::TextInput::echoMode
+
+ Specifies how the text should be displayed in the TextInput.
+ \list
+ \o TextInput.Normal - Displays the text as it is. (Default)
+ \o TextInput.Password - Displays asterixes instead of characters.
+ \o TextInput.NoEcho - Displays nothing.
+ \o TextInput.PasswordEchoOnEdit - Displays characters as they are entered
+ while editing, otherwise displays asterisks.
+ \endlist
+*/
QSGTextInput::EchoMode QSGTextInput::echoMode() const
{
Q_D(const QSGTextInput);
@@ -486,6 +909,19 @@ void QSGTextInput::setIMHints(Qt::InputMethodHints hints)
d->updateInputMethodHints();
}
+/*!
+ \qmlproperty Component QtQuick2::TextInput::cursorDelegate
+ The delegate for the cursor in the TextInput.
+
+ If you set a cursorDelegate for a TextInput, this delegate will be used for
+ drawing the cursor instead of the standard cursor. An instance of the
+ delegate will be created and managed by the TextInput when a cursor is
+ needed, and the x property of delegate instance will be set so as
+ to be one pixel before the top left of the current character.
+
+ Note that the root item of the delegate component must be a QDeclarativeItem or
+ QDeclarativeItem derived item.
+*/
QDeclarativeComponent* QSGTextInput::cursorDelegate() const
{
Q_D(const QSGTextInput);
@@ -547,6 +983,15 @@ void QSGTextInput::createCursor()
d->cursorItem->setHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
}
+/*!
+ \qmlmethod rect QtQuick2::TextInput::positionToRectangle(int pos)
+
+ This function takes a character position and returns the rectangle that the
+ cursor would occupy, if it was placed at that character position.
+
+ This is similar to setting the cursorPosition, and then querying the cursor
+ rectangle, but the cursorPosition is not changed.
+*/
QRectF QSGTextInput::positionToRectangle(int pos) const
{
Q_D(const QSGTextInput);
@@ -558,6 +1003,24 @@ QRectF QSGTextInput::positionToRectangle(int pos) const
cursorRectangle().height());
}
+/*!
+ \qmlmethod int QtQuick2::TextInput::positionAt(int x, CursorPosition position = CursorBetweenCharacters)
+
+ This function returns the character position at
+ x pixels from the left of the textInput. Position 0 is before the
+ first character, position 1 is after the first character but before the second,
+ and so on until position text.length, which is after all characters.
+
+ This means that for all x values before the first character this function returns 0,
+ and for all x values after the last character this function returns text.length.
+
+ The cursor position type specifies how the cursor position should be resolved.
+
+ \list
+ \o TextInput.CursorBetweenCharacters - Returns the position between characters that is nearest x.
+ \o TextInput.CursorOnCharacter - Returns the position before the character that is nearest x.
+ \endlist
+*/
int QSGTextInput::positionAt(int x) const
{
return positionAt(x, CursorBetweenCharacters);
@@ -597,7 +1060,7 @@ void QSGTextInput::keyPressEvent(QKeyEvent* ev)
d->control->processKeyEvent(ev);
}
if (!ev->isAccepted())
- QSGPaintedItem::keyPressEvent(ev);
+ QSGImplicitSizeItem::keyPressEvent(ev);
}
void QSGTextInput::inputMethodEvent(QInputMethodEvent *ev)
@@ -610,7 +1073,7 @@ void QSGTextInput::inputMethodEvent(QInputMethodEvent *ev)
d->control->processInputMethodEvent(ev);
}
if (!ev->isAccepted())
- QSGPaintedItem::inputMethodEvent(ev);
+ QSGImplicitSizeItem::inputMethodEvent(ev);
if (wasComposing != (d->control->preeditAreaText().length() > 0))
emit inputMethodComposingChanged();
@@ -626,7 +1089,7 @@ void QSGTextInput::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
d->control->selectWordAtPos(cursor);
event->setAccepted(true);
} else {
- QSGPaintedItem::mouseDoubleClickEvent(event);
+ QSGImplicitSizeItem::mouseDoubleClickEvent(event);
}
}
@@ -671,7 +1134,7 @@ void QSGTextInput::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
moveCursorSelection(d->xToPos(event->pos().x()), d->mouseSelectionMode);
event->setAccepted(true);
} else {
- QSGPaintedItem::mouseMoveEvent(event);
+ QSGImplicitSizeItem::mouseMoveEvent(event);
}
}
@@ -696,7 +1159,7 @@ void QSGTextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
d->clickCausedFocus = false;
d->control->processEvent(event);
if (!event->isAccepted())
- QSGPaintedItem::mouseReleaseEvent(event);
+ QSGImplicitSizeItem::mouseReleaseEvent(event);
}
bool QSGTextInputPrivate::sendMouseEventToInputContext(
@@ -762,7 +1225,7 @@ bool QSGTextInput::event(QEvent* ev)
handled = d->control->processEvent(ev);
}
if(!handled)
- handled = QSGPaintedItem::event(ev);
+ handled = QSGImplicitSizeItem::event(ev);
return handled;
}
@@ -773,7 +1236,7 @@ void QSGTextInput::geometryChanged(const QRectF &newGeometry,
updateSize();
updateCursorRectangle();
}
- QSGPaintedItem::geometryChanged(newGeometry, oldGeometry);
+ QSGImplicitSizeItem::geometryChanged(newGeometry, oldGeometry);
}
int QSGTextInputPrivate::calculateTextWidth()
@@ -827,25 +1290,73 @@ void QSGTextInputPrivate::updateHorizontalScroll()
}
}
-void QSGTextInput::paint(QPainter *p)
+QSGNode *QSGTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
{
- // XXX todo
- QRect r = boundingRect().toRect();
-
+ Q_UNUSED(data);
Q_D(QSGTextInput);
- p->setRenderHint(QPainter::TextAntialiasing, true);
- p->save();
- p->setPen(QPen(d->color));
- int flags = QLineControl::DrawText;
- if(!isReadOnly() && d->cursorVisible && !d->cursorItem)
- flags |= QLineControl::DrawCursor;
- if (d->control->hasSelectedText())
- flags |= QLineControl::DrawSelections;
- QFontMetrics fm = QFontMetrics(d->font);
- // the y offset is there to keep the baseline constant in case we have script changes in the text.
- QPoint offset(-d->hscroll, fm.ascent() - d->control->ascent());
- d->control->draw(p, offset, r, flags);
- p->restore();
+
+ QSGTextNode *node = static_cast<QSGTextNode *>(oldNode);
+ if (node == 0)
+ node = new QSGTextNode(QSGItemPrivate::get(this)->sceneGraphContext());
+ d->textNode = node;
+
+ if (!d->textLayoutDirty) {
+ QSGSimpleRectNode *cursorNode = node->cursorNode();
+ if (cursorNode != 0 && !isReadOnly()) {
+ QFontMetrics fm = QFontMetrics(d->font);
+ // the y offset is there to keep the baseline constant in case we have script changes in the text.
+ QPoint offset(-d->hscroll, fm.ascent() - d->control->ascent());
+ offset.rx() += d->control->cursorToX();
+
+ QRect br(boundingRect().toRect());
+ cursorNode->setRect(QRectF(offset, QSizeF(d->control->cursorWidth(), br.height())));
+
+ if (!d->cursorVisible
+ || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) {
+ d->hideCursor();
+ } else {
+ d->showCursor();
+ }
+ }
+ } else {
+ node->deleteContent();
+ node->setMatrix(QMatrix4x4());
+
+ QPoint offset = QPoint(0,0);
+ QFontMetrics fm = QFontMetrics(d->font);
+ QRect br(boundingRect().toRect());
+ if (d->autoScroll) {
+ // the y offset is there to keep the baseline constant in case we have script changes in the text.
+ offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
+ } else {
+ offset = QPoint(d->hscroll, 0);
+ }
+
+ QTextLayout *textLayout = d->control->textLayout();
+ if (!textLayout->text().isEmpty()) {
+ node->addTextLayout(offset, textLayout, d->color,
+ QSGText::Normal, QColor(),
+ d->selectionColor, d->selectedTextColor,
+ d->control->selectionStart(),
+ d->control->selectionEnd() - 1); // selectionEnd() returns first char after
+ // selection
+ }
+
+ if (!isReadOnly() && d->cursorItem == 0) {
+ offset.rx() += d->control->cursorToX();
+ node->setCursor(QRectF(offset, QSizeF(d->control->cursorWidth(), br.height())), d->color);
+ if (!d->cursorVisible
+ || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) {
+ d->hideCursor();
+ } else {
+ d->showCursor();
+ }
+ }
+
+ d->textLayoutDirty = false;
+ }
+
+ return node;
}
QVariant QSGTextInput::inputMethodQuery(Qt::InputMethodQuery property) const
@@ -879,18 +1390,34 @@ QVariant QSGTextInput::inputMethodQuery(Qt::InputMethodQuery property) const
}
}
+/*!
+ \qmlmethod void QtQuick2::TextInput::deselect()
+
+ Removes active text selection.
+*/
void QSGTextInput::deselect()
{
Q_D(QSGTextInput);
d->control->deselect();
}
+/*!
+ \qmlmethod void QtQuick2::TextInput::selectAll()
+
+ Causes all text to be selected.
+*/
void QSGTextInput::selectAll()
{
Q_D(QSGTextInput);
d->control->setSelection(0, d->control->text().length());
}
+/*!
+ \qmlmethod void QtQuick2::TextInput::isRightToLeft(int start, int end)
+
+ Returns true if the natural reading direction of the editor text
+ found between positions \a start and \a end is right to left.
+*/
bool QSGTextInput::isRightToLeft(int start, int end)
{
Q_D(QSGTextInput);
@@ -903,6 +1430,11 @@ bool QSGTextInput::isRightToLeft(int start, int end)
}
#ifndef QT_NO_CLIPBOARD
+/*!
+ \qmlmethod QtQuick2::TextInput::cut()
+
+ Moves the currently selected text to the system clipboard.
+*/
void QSGTextInput::cut()
{
Q_D(QSGTextInput);
@@ -910,12 +1442,22 @@ void QSGTextInput::cut()
d->control->del();
}
+/*!
+ \qmlmethod QtQuick2::TextInput::copy()
+
+ Copies the currently selected text to the system clipboard.
+*/
void QSGTextInput::copy()
{
Q_D(QSGTextInput);
d->control->copy();
}
+/*!
+ \qmlmethod QtQuick2::TextInput::paste()
+
+ Replaces the currently selected text by the contents of the system clipboard.
+*/
void QSGTextInput::paste()
{
Q_D(QSGTextInput);
@@ -924,12 +1466,41 @@ void QSGTextInput::paste()
}
#endif // QT_NO_CLIPBOARD
+/*!
+ \qmlmethod void QtQuick2::TextInput::selectWord()
+
+ Causes the word closest to the current cursor position to be selected.
+*/
void QSGTextInput::selectWord()
{
Q_D(QSGTextInput);
d->control->selectWordAtPos(d->control->cursor());
}
+/*!
+ \qmlproperty bool QtQuick2::TextInput::smooth
+
+ This property holds whether the text is smoothly scaled or transformed.
+
+ Smooth filtering gives better visual quality, but is slower. If
+ the item is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the item is stationary on
+ the screen. A common pattern when animating an item is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+*/
+
+/*!
+ \qmlproperty string QtQuick2::TextInput::passwordCharacter
+
+ This is the character displayed when echoMode is set to Password or
+ PasswordEchoOnEdit. By default it is an asterisk.
+
+ If this property is set to a string with more than one character,
+ the first character is used. If the string is empty, the value
+ is ignored and the property is not set.
+*/
QString QSGTextInput::passwordCharacter() const
{
Q_D(const QSGTextInput);
@@ -949,12 +1520,32 @@ void QSGTextInput::setPasswordCharacter(const QString &str)
emit passwordCharacterChanged();
}
+/*!
+ \qmlproperty string QtQuick2::TextInput::displayText
+
+ This is the text displayed in the TextInput.
+
+ If \l echoMode is set to TextInput::Normal, this holds the
+ same value as the TextInput::text property. Otherwise,
+ this property holds the text visible to the user, while
+ the \l text property holds the actual entered text.
+*/
QString QSGTextInput::displayText() const
{
Q_D(const QSGTextInput);
return d->control->displayText();
}
+/*!
+ \qmlproperty bool QtQuick2::TextInput::selectByMouse
+
+ Defaults to false.
+
+ If true, the user can use the mouse to select text in some
+ platform-specific way. Note that for some platforms this may
+ not be an appropriate interaction (eg. may conflict with how
+ the text needs to behave inside a Flickable.
+*/
bool QSGTextInput::selectByMouse() const
{
Q_D(const QSGTextInput);
@@ -970,6 +1561,19 @@ void QSGTextInput::setSelectByMouse(bool on)
}
}
+/*!
+ \qmlproperty enum QtQuick2::TextInput::mouseSelectionMode
+
+ Specifies how text should be selected using a mouse.
+
+ \list
+ \o TextInput.SelectCharacters - The selection is updated with individual characters. (Default)
+ \o TextInput.SelectWords - The selection is updated with whole words.
+ \endlist
+
+ This property only applies when \l selectByMouse is true.
+*/
+
QSGTextInput::SelectionMode QSGTextInput::mouseSelectionMode() const
{
Q_D(const QSGTextInput);
@@ -985,6 +1589,12 @@ void QSGTextInput::setMouseSelectionMode(SelectionMode mode)
}
}
+/*!
+ \qmlproperty bool QtQuick2::TextInput::canPaste
+
+ Returns true if the TextInput is writable and the content of the clipboard is
+ suitable for pasting into the TextEdit.
+*/
bool QSGTextInput::canPaste() const
{
Q_D(const QSGTextInput);
@@ -997,6 +1607,43 @@ void QSGTextInput::moveCursorSelection(int position)
d->control->moveCursor(position, true);
}
+/*!
+ \qmlmethod void QtQuick2::TextInput::moveCursorSelection(int position, SelectionMode mode = TextInput.SelectCharacters)
+
+ Moves the cursor to \a position and updates the selection according to the optional \a mode
+ parameter. (To only move the cursor, set the \l cursorPosition property.)
+
+ When this method is called it additionally sets either the
+ selectionStart or the selectionEnd (whichever was at the previous cursor position)
+ to the specified position. This allows you to easily extend and contract the selected
+ text range.
+
+ The selection mode specifies whether the selection is updated on a per character or a per word
+ basis. If not specified the selection mode will default to TextInput.SelectCharacters.
+
+ \list
+ \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
+ the previous cursor position) to the specified position.
+ \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all
+ words between the specified postion and the previous cursor position. Words partially in the
+ range are included.
+ \endlist
+
+ For example, take this sequence of calls:
+
+ \code
+ cursorPosition = 5
+ moveCursorSelection(9, TextInput.SelectCharacters)
+ moveCursorSelection(7, TextInput.SelectCharacters)
+ \endcode
+
+ This moves the cursor to position 5, extend the selection end from 5 to 9
+ and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
+ selected (the 6th and 7th characters).
+
+ The same sequence with TextInput.SelectWords will extend the selection start to a word boundary
+ before or on position 5 and extend the selection end to a word boundary on or past position 9.
+*/
void QSGTextInput::moveCursorSelection(int pos, SelectionMode mode)
{
Q_D(QSGTextInput);
@@ -1054,6 +1701,45 @@ void QSGTextInput::moveCursorSelection(int pos, SelectionMode mode)
}
}
+/*!
+ \qmlmethod void QtQuick2::TextInput::openSoftwareInputPanel()
+
+ Opens software input panels like virtual keyboards for typing, useful for
+ customizing when you want the input keyboard to be shown and hidden in
+ your application.
+
+ By default the opening of input panels follows the platform style. On Symbian^1 and
+ Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
+ the panels are automatically opened when TextInput element gains active focus. Input panels are
+ always closed if no editor has active focus.
+
+ . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
+ and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
+ the behavior you want.
+
+ Only relevant on platforms, which provide virtual keyboards.
+
+ \qml
+ import QtQuick 1.0
+ TextInput {
+ id: textInput
+ text: "Hello world!"
+ activeFocusOnPress: false
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ if (!textInput.activeFocus) {
+ textInput.forceActiveFocus()
+ textInput.openSoftwareInputPanel();
+ } else {
+ textInput.focus = false;
+ }
+ }
+ onPressAndHold: textInput.closeSoftwareInputPanel();
+ }
+ }
+ \endqml
+*/
void QSGTextInput::openSoftwareInputPanel()
{
if (qApp) {
@@ -1064,6 +1750,45 @@ void QSGTextInput::openSoftwareInputPanel()
}
}
+/*!
+ \qmlmethod void QtQuick2::TextInput::closeSoftwareInputPanel()
+
+ Closes a software input panel like a virtual keyboard shown on the screen, useful
+ for customizing when you want the input keyboard to be shown and hidden in
+ your application.
+
+ By default the opening of input panels follows the platform style. On Symbian^1 and
+ Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
+ the panels are automatically opened when TextInput element gains active focus. Input panels are
+ always closed if no editor has active focus.
+
+ . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
+ and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
+ the behavior you want.
+
+ Only relevant on platforms, which provide virtual keyboards.
+
+ \qml
+ import QtQuick 1.0
+ TextInput {
+ id: textInput
+ text: "Hello world!"
+ activeFocusOnPress: false
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ if (!textInput.activeFocus) {
+ textInput.forceActiveFocus();
+ textInput.openSoftwareInputPanel();
+ } else {
+ textInput.focus = false;
+ }
+ }
+ onPressAndHold: textInput.closeSoftwareInputPanel();
+ }
+ }
+ \endqml
+*/
void QSGTextInput::closeSoftwareInputPanel()
{
if (qApp) {
@@ -1082,7 +1807,7 @@ void QSGTextInput::focusInEvent(QFocusEvent *event)
openSoftwareInputPanel();
}
}
- QSGPaintedItem::focusInEvent(event);
+ QSGImplicitSizeItem::focusInEvent(event);
}
void QSGTextInput::itemChange(ItemChange change, const ItemChangeData &value)
@@ -1100,6 +1825,18 @@ void QSGTextInput::itemChange(ItemChange change, const ItemChangeData &value)
QSGItem::itemChange(change, value);
}
+/*!
+ \qmlproperty bool QtQuick2::TextInput::inputMethodComposing
+
+
+ This property holds whether the TextInput has partial text input from an
+ input method.
+
+ While it is composing an input method may rely on mouse or key events from
+ the TextInput to edit or commit the partial text. This property can be
+ used to determine when to disable events handlers that may interfere with
+ the correct operation of an input method.
+*/
bool QSGTextInput::isInputMethodComposing() const
{
Q_D(const QSGTextInput);
@@ -1109,12 +1846,16 @@ bool QSGTextInput::isInputMethodComposing() const
void QSGTextInputPrivate::init()
{
Q_Q(QSGTextInput);
+#if defined(Q_WS_MAC)
+ control->setThreadChecks(true);
+#endif
control->setParent(q);//Now mandatory due to accessibility changes
control->setCursorWidth(1);
control->setPasswordCharacter(QLatin1Char('*'));
q->setSmooth(smooth);
q->setAcceptedMouseButtons(Qt::LeftButton);
q->setFlag(QSGItem::ItemAcceptsInputMethod);
+ q->setFlag(QSGItem::ItemHasContents);
q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
q, SLOT(cursorPosChanged()));
q->connect(control, SIGNAL(selectionChanged()),
@@ -1144,6 +1885,12 @@ void QSGTextInputPrivate::init()
selectedTextColor = p.color(QPalette::HighlightedText);
selectionColor = p.color(QPalette::Highlight);
determineHorizontalAlignment();
+
+ if (!qmlDisableDistanceField()) {
+ QTextOption option = control->textLayout()->textOption();
+ option.setUseDesignMetrics(true);
+ control->textLayout()->setTextOption(option);
+ }
}
void QSGTextInput::cursorPosChanged()
@@ -1214,19 +1961,35 @@ void QSGTextInput::q_textChanged()
}
}
+void QSGTextInputPrivate::showCursor()
+{
+ if (textNode != 0 && textNode->cursorNode() != 0)
+ textNode->cursorNode()->setColor(color);
+}
+
+void QSGTextInputPrivate::hideCursor()
+{
+ if (textNode != 0 && textNode->cursorNode() != 0)
+ textNode->cursorNode()->setColor(QColor(0, 0, 0, 0));
+}
+
void QSGTextInput::updateRect(const QRect &r)
{
Q_D(QSGTextInput);
- if(r == QRect())
- update();
- else
- update(QRect(r.x() - d->hscroll, r.y(), r.width(), r.height()));
+ if (!isComponentComplete())
+ return;
+
+ if (r.isEmpty()) {
+ d->textLayoutDirty = true;
+ }
+
+ update();
}
QRectF QSGTextInput::boundingRect() const
{
Q_D(const QSGTextInput);
- QRectF r = QSGPaintedItem::boundingRect();
+ QRectF r = QSGImplicitSizeItem::boundingRect();
int cursorWidth = d->cursorItem ? d->cursorItem->width() : d->control->cursorWidth();
@@ -1243,7 +2006,6 @@ void QSGTextInput::updateSize(bool needsRedraw)
int h = height();
setImplicitHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
setImplicitWidth(d->calculateTextWidth());
- setContentsSize(boundingRect().size().toSize());
if(w==width() && h==height() && needsRedraw)
update();
}
diff --git a/src/declarative/items/qsgtextinput_p.h b/src/declarative/items/qsgtextinput_p.h
index 770afa8283..f5ac50e8e1 100644
--- a/src/declarative/items/qsgtextinput_p.h
+++ b/src/declarative/items/qsgtextinput_p.h
@@ -54,7 +54,7 @@ QT_MODULE(Declarative)
class QSGTextInputPrivate;
class QValidator;
-class Q_AUTOTEST_EXPORT QSGTextInput : public QSGImplicitSizePaintedItem
+class Q_AUTOTEST_EXPORT QSGTextInput : public QSGImplicitSizeItem
{
Q_OBJECT
Q_ENUMS(HAlignment)
@@ -204,7 +204,6 @@ public:
bool hasAcceptableInput() const;
- void paint(QPainter *p);
QVariant inputMethodQuery(Qt::InputMethodQuery property) const;
QRectF boundingRect() const;
@@ -261,6 +260,7 @@ protected:
bool event(QEvent *e);
void focusInEvent(QFocusEvent *event);
virtual void itemChange(ItemChange, const ItemChangeData &);
+ QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data);
public Q_SLOTS:
void selectAll();
diff --git a/src/declarative/items/qsgtextinput_p_p.h b/src/declarative/items/qsgtextinput_p_p.h
index f25722972b..0d1f21b54c 100644
--- a/src/declarative/items/qsgtextinput_p_p.h
+++ b/src/declarative/items/qsgtextinput_p_p.h
@@ -65,18 +65,35 @@
QT_BEGIN_NAMESPACE
-class Q_AUTOTEST_EXPORT QSGTextInputPrivate : public QSGImplicitSizePaintedItemPrivate
+class QSGTextNode;
+
+class Q_AUTOTEST_EXPORT QSGTextInputPrivate : public QSGImplicitSizeItemPrivate
{
Q_DECLARE_PUBLIC(QSGTextInput)
public:
- QSGTextInputPrivate() : control(new QLineControl(QString())),
- color((QRgb)0), style(QSGText::Normal),
- styleColor((QRgb)0), hAlign(QSGTextInput::AlignLeft),
- mouseSelectionMode(QSGTextInput::SelectCharacters), inputMethodHints(Qt::ImhNone),
- hscroll(0), oldScroll(0), oldValidity(false), focused(false), focusOnPress(true),
- showInputPanelOnFocus(true), clickCausedFocus(false), cursorVisible(false),
- autoScroll(true), selectByMouse(false), canPaste(false), hAlignImplicit(true),
- selectPressed(false)
+ QSGTextInputPrivate()
+ : control(new QLineControl(QString()))
+ , color((QRgb)0)
+ , style(QSGText::Normal)
+ , styleColor((QRgb)0)
+ , hAlign(QSGTextInput::AlignLeft)
+ , mouseSelectionMode(QSGTextInput::SelectCharacters)
+ , inputMethodHints(Qt::ImhNone)
+ , textNode(0)
+ , hscroll(0)
+ , oldScroll(0)
+ , oldValidity(false)
+ , focused(false)
+ , focusOnPress(true)
+ , showInputPanelOnFocus(true)
+ , clickCausedFocus(false)
+ , cursorVisible(false)
+ , autoScroll(true)
+ , selectByMouse(false)
+ , canPaste(false)
+ , hAlignImplicit(true)
+ , selectPressed(false)
+ , textLayoutDirty(true)
{
#ifdef Q_OS_SYMBIAN
if (QSysInfo::symbianVersion() == QSysInfo::SV_SF_1 || QSysInfo::symbianVersion() == QSysInfo::SV_SF_3) {
@@ -106,6 +123,8 @@ public:
int calculateTextWidth();
bool sendMouseEventToInputContext(QGraphicsSceneMouseEvent *event, QEvent::Type eventType);
void updateInputMethodHints();
+ void hideCursor();
+ void showCursor();
QLineControl* control;
@@ -122,6 +141,7 @@ public:
QPointer<QDeclarativeComponent> cursorComponent;
QPointer<QSGItem> cursorItem;
QPointF pressPos;
+ QSGTextNode *textNode;
int lastSelectionStart;
int lastSelectionEnd;
@@ -141,6 +161,7 @@ public:
bool canPaste:1;
bool hAlignImplicit:1;
bool selectPressed:1;
+ bool textLayoutDirty:1;
static inline QSGTextInputPrivate *get(QSGTextInput *t) {
return t->d_func();
diff --git a/src/declarative/items/qsgtextnode.cpp b/src/declarative/items/qsgtextnode.cpp
index 03a558fe3d..1ae457b6fa 100644
--- a/src/declarative/items/qsgtextnode.cpp
+++ b/src/declarative/items/qsgtextnode.cpp
@@ -47,6 +47,7 @@
#include <private/qsgcontext_p.h>
+#include <QtCore/qpoint.h>
#include <qmath.h>
#include <qtextdocument.h>
#include <qtextlayout.h>
@@ -57,6 +58,7 @@
#include <private/qfont_p.h>
#include <private/qfontengine_p.h>
#include <private/qrawfont_p.h>
+#include <qhash.h>
QT_BEGIN_NAMESPACE
@@ -64,7 +66,7 @@ QT_BEGIN_NAMESPACE
Creates an empty QSGTextNode
*/
QSGTextNode::QSGTextNode(QSGContext *context)
-: m_context(context)
+ : m_context(context), m_cursorNode(0)
{
#if defined(QML_RUNTIME_TESTING)
description = QLatin1String("text");
@@ -119,131 +121,682 @@ void QSGTextNode::setStyleColor(const QColor &styleColor)
}
#endif
-void QSGTextNode::addTextDecorations(Decoration decorations, const QPointF &position,
- const QColor &color, qreal width, qreal lineThickness,
- qreal underlinePos, qreal ascent)
+QSGGlyphNode *QSGTextNode::addGlyphs(const QPointF &position, const QGlyphRun &glyphs, const QColor &color,
+ QSGText::TextStyle style, const QColor &styleColor,
+ QSGNode *parentNode)
{
- QRectF line(position.x(), position.y() - lineThickness / 2.0, width, lineThickness);
+ QSGGlyphNode *node = m_context->createGlyphNode();
+ node->setGlyphs(position + QPointF(0, glyphs.rawFont().ascent()), glyphs);
+ node->setStyle(style);
+ node->setStyleColor(styleColor);
+ node->setColor(color);
+ node->update();
- if (decorations & Underline) {
- int underlinePosition = qCeil(underlinePos);
- QRectF underline(line);
- underline.translate(0.0, underlinePosition);
- appendChildNode(new QSGSimpleRectNode(underline, color));
- }
+ /* We flag the geometry as static, but we never call markVertexDataDirty
+ or markIndexDataDirty on them. This is because all text nodes are
+ discarded when a change occurs. If we start appending/removing from
+ existing geometry, then we also need to start marking the geometry as
+ dirty.
+ */
+ node->geometry()->setIndexDataPattern(QSGGeometry::StaticPattern);
+ node->geometry()->setVertexDataPattern(QSGGeometry::StaticPattern);
- if (decorations & Overline) {
- QRectF overline(line);
- overline.translate(0.0, -ascent);
- appendChildNode(new QSGSimpleRectNode(overline, color));
- }
+ if (parentNode == 0)
+ parentNode = this;
+ parentNode->appendChildNode(node);
- if (decorations & StrikeOut) {
- QRectF strikeOut(line);
- strikeOut.translate(0.0, ascent / -3.0);
- appendChildNode(new QSGSimpleRectNode(strikeOut, color));
- }
+ return node;
}
-QSGGlyphNode *QSGTextNode::addGlyphs(const QPointF &position, const QGlyphRun &glyphs, const QColor &color,
- QSGText::TextStyle style, const QColor &styleColor, QSGGlyphNode *prevNode)
+void QSGTextNode::setCursor(const QRectF &rect, const QColor &color)
{
- QSGGlyphNode *node = prevNode;
+ if (m_cursorNode != 0)
+ delete m_cursorNode;
+
+ m_cursorNode = new QSGSimpleRectNode(rect, color);
+ appendChildNode(m_cursorNode);
+}
+
+namespace {
+
+ struct BinaryTreeNode {
+ enum SelectionState {
+ Unselected,
+ Selected
+ };
+
+ BinaryTreeNode()
+ : selectionState(Unselected)
+ , clipNode(0)
+ , decorations(QSGTextNode::NoDecoration)
+ , leftChildIndex(-1)
+ , rightChildIndex(-1)
+ {
+
+ }
+
+ BinaryTreeNode(const QGlyphRun &g, SelectionState selState, const QRectF &brect,
+ const QSGTextNode::Decorations &decs, const QColor &c,
+ const QPointF &pos)
+ : glyphRun(g)
+ , boundingRect(brect)
+ , selectionState(selState)
+ , clipNode(0)
+ , decorations(decs)
+ , color(c)
+ , position(pos)
+ , leftChildIndex(-1)
+ , rightChildIndex(-1)
+ {
+ }
+
+ QGlyphRun glyphRun;
+ QRectF boundingRect;
+ SelectionState selectionState;
+ QSGClipNode *clipNode;
+ QSGTextNode::Decorations decorations;
+ QColor color;
+ QPointF position;
+
+ int leftChildIndex;
+ int rightChildIndex;
+
+ static void insert(QVarLengthArray<BinaryTreeNode> *binaryTree,
+ const QGlyphRun &glyphRun,
+ SelectionState selectionState,
+ const QColor &textColor,
+ const QPointF &position)
+ {
+ int newIndex = binaryTree->size();
+ QRectF searchRect = glyphRun.boundingRect();
+
+ if (qFuzzyIsNull(searchRect.width()) || qFuzzyIsNull(searchRect.height()))
+ return;
+
+ QSGTextNode::Decorations decorations = QSGTextNode::NoDecoration;
+ decorations |= (glyphRun.underline() ? QSGTextNode::Underline : QSGTextNode::NoDecoration);
+ decorations |= (glyphRun.overline() ? QSGTextNode::Overline : QSGTextNode::NoDecoration);
+ decorations |= (glyphRun.strikeOut() ? QSGTextNode::StrikeOut : QSGTextNode::NoDecoration);
+
+ binaryTree->append(BinaryTreeNode(glyphRun, selectionState, searchRect, decorations,
+ textColor, position));
+ if (newIndex == 0)
+ return;
+
+ int searchIndex = 0;
+ forever {
+ BinaryTreeNode *node = binaryTree->data() + searchIndex;
+ if (searchRect.left() < node->boundingRect.left()) {
+ if (node->leftChildIndex < 0) {
+ node->leftChildIndex = newIndex;
+ break;
+ } else {
+ searchIndex = node->leftChildIndex;
+ }
+ } else {
+ if (node->rightChildIndex < 0) {
+ node->rightChildIndex = newIndex;
+ break;
+ } else {
+ searchIndex = node->rightChildIndex;
+ }
+ }
+ }
+ }
+
+ static void inOrder(const QVarLengthArray<BinaryTreeNode> &binaryTree,
+ QVarLengthArray<int> *sortedIndexes,
+ int currentIndex = 0)
+ {
+ Q_ASSERT(currentIndex < binaryTree.size());
- if (!node)
- node = m_context->createGlyphNode();
+ const BinaryTreeNode *node = binaryTree.data() + currentIndex;
+ if (node->leftChildIndex >= 0)
+ inOrder(binaryTree, sortedIndexes, node->leftChildIndex);
- node->setGlyphs(position, glyphs);
+ sortedIndexes->append(currentIndex);
- if (node != prevNode) {
- if (QSGDistanceFieldGlyphCache::distanceFieldEnabled()) {
- QSGDistanceFieldGlyphNode *dfNode = static_cast<QSGDistanceFieldGlyphNode *>(node);
- dfNode->setStyle(style);
- dfNode->setStyleColor(styleColor);
+ if (node->rightChildIndex >= 0)
+ inOrder(binaryTree, sortedIndexes, node->rightChildIndex);
+ }
+ };
+
+ // Engine that takes glyph runs as input, and produces a set of glyph nodes, clip nodes,
+ // and rectangle nodes to represent the text, decorations and selection. Will try to minimize
+ // number of nodes, and join decorations in neighbouring items
+ class SelectionEngine
+ {
+ public:
+ SelectionEngine() : m_hasSelection(false) {}
+
+ QTextLine currentLine() const { return m_currentLine; }
+
+ void setCurrentLine(const QTextLine &currentLine)
+ {
+ if (m_currentLine.isValid())
+ processCurrentLine();
+
+ m_currentLine = currentLine;
+ }
+
+ void addSelectedGlyphs(const QGlyphRun &glyphRun);
+ void addUnselectedGlyphs(const QGlyphRun &glyphRun);
+
+ void addToSceneGraph(QSGTextNode *parent,
+ QSGText::TextStyle style = QSGText::Normal,
+ const QColor &styleColor = QColor());
+
+ void setSelectionColor(const QColor &selectionColor)
+ {
+ m_selectionColor = selectionColor;
+ }
+
+ void setSelectedTextColor(const QColor &selectedTextColor)
+ {
+ m_selectedTextColor = selectedTextColor;
+ }
+
+ void setTextColor(const QColor &textColor)
+ {
+ m_textColor = textColor;
+ }
+
+ void setPosition(const QPointF &position)
+ {
+ m_position = position;
+ }
+
+ private:
+ struct TextDecoration
+ {
+ TextDecoration() : selectionState(BinaryTreeNode::Unselected) {}
+ TextDecoration(const BinaryTreeNode::SelectionState &s,
+ const QRectF &r,
+ const QColor &c)
+ : selectionState(s)
+ , rect(r)
+ , color(c)
+ {
+ }
+
+ BinaryTreeNode::SelectionState selectionState;
+ QRectF rect;
+ QColor color;
+ };
+
+ void processCurrentLine();
+ void addTextDecorations(const QVarLengthArray<TextDecoration> &textDecorations,
+ qreal offset, qreal thickness);
+
+ QColor m_selectionColor;
+ QColor m_textColor;
+ QColor m_selectedTextColor;
+ QPointF m_position;
+
+ QTextLine m_currentLine;
+ bool m_hasSelection;
+
+ QList<QRectF> m_selectionRects;
+ QVarLengthArray<BinaryTreeNode> m_currentLineTree;
+
+ QList<TextDecoration> m_lines;
+ QVector<BinaryTreeNode> m_processedNodes;
+ };
+
+ void SelectionEngine::addTextDecorations(const QVarLengthArray<TextDecoration> &textDecorations,
+ qreal offset, qreal thickness)
+ {
+ for (int i=0; i<textDecorations.size(); ++i) {
+ TextDecoration textDecoration = textDecorations.at(i);
+
+ {
+ QRectF &rect = textDecoration.rect;
+ rect.setY(qRound(rect.y() + m_currentLine.ascent() + offset));
+ rect.setHeight(thickness);
+ }
+
+ m_lines.append(textDecoration);
}
- node->setColor(color);
}
- node->update();
+ void SelectionEngine::processCurrentLine()
+ {
+ // No glyphs, do nothing
+ if (m_currentLineTree.isEmpty())
+ return;
+
+ // 1. Go through current line and get correct decoration position for each node based on
+ // neighbouring decorations. Add decoration to global list
+ // 2. Create clip nodes for all selected text. Try to merge as many as possible within
+ // the line.
+ // 3. Add QRects to a list of selection rects.
+ // 4. Add all nodes to a global processed list
+ QVarLengthArray<int> sortedIndexes; // Indexes in tree sorted by x position
+ BinaryTreeNode::inOrder(m_currentLineTree, &sortedIndexes);
+
+ Q_ASSERT(sortedIndexes.size() == m_currentLineTree.size());
+
+ BinaryTreeNode::SelectionState currentSelectionState = BinaryTreeNode::Unselected;
+ QRectF currentRect;
+
+ QSGTextNode::Decorations currentDecorations = QSGTextNode::NoDecoration;
+ qreal underlineOffset = 0.0;
+ qreal underlineThickness = 0.0;
+
+ qreal overlineOffset = 0.0;
+ qreal overlineThickness = 0.0;
+
+ qreal strikeOutOffset = 0.0;
+ qreal strikeOutThickness = 0.0;
+
+ QRectF decorationRect = currentRect;
+
+ QColor lastColor;
+
+ QVarLengthArray<TextDecoration> pendingUnderlines;
+ QVarLengthArray<TextDecoration> pendingOverlines;
+ QVarLengthArray<TextDecoration> pendingStrikeOuts;
+ if (!sortedIndexes.isEmpty()) {
+ QSGClipNode *currentClipNode = m_hasSelection ? new QSGClipNode : 0;
+ bool currentClipNodeUsed = false;
+ for (int i=0; i<=sortedIndexes.size(); ++i) {
+ BinaryTreeNode *node = 0;
+ if (i < sortedIndexes.size()) {
+ int sortedIndex = sortedIndexes.at(i);
+ Q_ASSERT(sortedIndex < m_currentLineTree.size());
+
+ node = m_currentLineTree.data() + sortedIndex;
+ }
+
+ if (i == 0)
+ currentSelectionState = node->selectionState;
+
+ // Update decorations
+ if (currentDecorations != QSGTextNode::NoDecoration) {
+ decorationRect.setY(m_position.y() + m_currentLine.y());
+ decorationRect.setHeight(m_currentLine.height());
+
+ if (node != 0)
+ decorationRect.setRight(node->boundingRect.left());
+
+ TextDecoration textDecoration(currentSelectionState, decorationRect, lastColor);
+ if (currentDecorations & QSGTextNode::Underline)
+ pendingUnderlines.append(textDecoration);
+
+ if (currentDecorations & QSGTextNode::Overline)
+ pendingOverlines.append(textDecoration);
+
+ if (currentDecorations & QSGTextNode::StrikeOut)
+ pendingStrikeOuts.append(textDecoration);
+ }
+
+ // If we've reached an unselected node from a selected node, we add the
+ // selection rect to the graph, and we add decoration every time the
+ // selection state changes, because that means the text color changes
+ if (node == 0 || node->selectionState != currentSelectionState) {
+ if (node != 0)
+ currentRect.setRight(node->boundingRect.left());
+ currentRect.setY(m_position.y() + m_currentLine.y());
+ currentRect.setHeight(m_currentLine.height());
+
+ // Draw selection all the way up to the left edge of the unselected item
+ if (currentSelectionState == BinaryTreeNode::Selected)
+ m_selectionRects.append(currentRect);
+
+ if (currentClipNode != 0) {
+ if (!currentClipNodeUsed) {
+ delete currentClipNode;
+ } else {
+ currentClipNode->setIsRectangular(true);
+ currentClipNode->setClipRect(currentRect);
+ }
+ }
+
+ if (node != 0 && m_hasSelection)
+ currentClipNode = new QSGClipNode;
+ else
+ currentClipNode = 0;
+ currentClipNodeUsed = false;
+
+ if (node != 0) {
+ currentSelectionState = node->selectionState;
+ currentRect = node->boundingRect;
+
+ // Make sure currentRect is valid, otherwise the unite won't work
+ if (currentRect.isNull())
+ currentRect.setSize(QSizeF(1, 1));
+ }
+ } else {
+ if (currentRect.isNull())
+ currentRect = node->boundingRect;
+ else
+ currentRect = currentRect.united(node->boundingRect);
+ }
+
+ if (node != 0) {
+ node->clipNode = currentClipNode;
+ currentClipNodeUsed = true;
+
+ decorationRect = node->boundingRect;
+
+ // If previous item(s) had underline and current does not, then we add the
+ // pending lines to the lists and likewise for overlines and strikeouts
+ if (!pendingUnderlines.isEmpty()
+ && !(node->decorations & QSGTextNode::Underline)) {
+ addTextDecorations(pendingUnderlines, underlineOffset, underlineThickness);
+
+ pendingUnderlines.clear();
+
+ underlineOffset = 0.0;
+ underlineThickness = 0.0;
+ }
+
+ // ### Add pending when overlineOffset/thickness changes to minimize number of
+ // nodes
+ if (!pendingOverlines.isEmpty()) {
+ addTextDecorations(pendingOverlines, overlineOffset, overlineThickness);
+
+ pendingOverlines.clear();
+
+ overlineOffset = 0.0;
+ overlineThickness = 0.0;
+ }
+
+ // ### Add pending when overlineOffset/thickness changes to minimize number of
+ // nodes
+ if (!pendingStrikeOuts.isEmpty()) {
+ addTextDecorations(pendingStrikeOuts, strikeOutOffset, strikeOutThickness);
+
+ pendingStrikeOuts.clear();
+
+ strikeOutOffset = 0.0;
+ strikeOutThickness = 0.0;
+ }
+
+ // Merge current values with previous. Prefer greatest thickness
+ QRawFont rawFont = node->glyphRun.rawFont();
+ if (node->decorations & QSGTextNode::Underline) {
+ if (rawFont.lineThickness() > underlineThickness) {
+ underlineThickness = rawFont.lineThickness();
+ underlineOffset = rawFont.underlinePosition();
+ }
+ }
- // A new node, add it to the graph.
- if (node != prevNode) {
- appendChildNode(node);
-
- /* We flag the geometry as static, but we never call markVertexDataDirty
- or markIndexDataDirty on them. This is because all text nodes are
- discarded when a change occurs. If we start appending/removing from
- existing geometry, then we also need to start marking the geometry as
- dirty.
- */
- node->geometry()->setIndexDataPattern(QSGGeometry::StaticPattern);
- node->geometry()->setVertexDataPattern(QSGGeometry::StaticPattern);
+ if (node->decorations & QSGTextNode::Overline) {
+ overlineOffset = -rawFont.ascent();
+ overlineThickness = rawFont.lineThickness();
+ }
+
+ if (node->decorations & QSGTextNode::StrikeOut) {
+ strikeOutThickness = rawFont.lineThickness();
+ strikeOutOffset = rawFont.ascent() / -3.0;
+ }
+
+ currentDecorations = node->decorations;
+ lastColor = node->color;
+ m_processedNodes.append(*node);
+ }
+ }
+
+ // If there are pending decorations, we need to add them
+ if (!pendingUnderlines.isEmpty())
+ addTextDecorations(pendingUnderlines, underlineOffset, underlineThickness);
+
+ if (!pendingOverlines.isEmpty())
+ addTextDecorations(pendingOverlines, overlineOffset, overlineThickness);
+
+ if (!pendingStrikeOuts.isEmpty())
+ addTextDecorations(pendingStrikeOuts, strikeOutOffset, strikeOutThickness);
+ }
+
+ m_currentLineTree.clear();
+ m_currentLine = QTextLine();
+ m_hasSelection = false;
}
- return node;
+ void SelectionEngine::addUnselectedGlyphs(const QGlyphRun &glyphRun)
+ {
+ BinaryTreeNode::insert(&m_currentLineTree, glyphRun, BinaryTreeNode::Unselected,
+ m_textColor, m_position);
+ }
+
+ void SelectionEngine::addSelectedGlyphs(const QGlyphRun &glyphRun)
+ {
+ int currentSize = m_currentLineTree.size();
+ BinaryTreeNode::insert(&m_currentLineTree, glyphRun, BinaryTreeNode::Selected,
+ m_textColor, m_position);
+ m_hasSelection = m_hasSelection || m_currentLineTree.size() > currentSize;
+ }
+
+ void SelectionEngine::addToSceneGraph(QSGTextNode *parentNode,
+ QSGText::TextStyle style,
+ const QColor &styleColor)
+ {
+ if (m_currentLine.isValid())
+ processCurrentLine();
+
+ // First, prepend all selection rectangles to the tree
+ for (int i=0; i<m_selectionRects.size(); ++i) {
+ const QRectF &rect = m_selectionRects.at(i);
+
+ parentNode->appendChildNode(new QSGSimpleRectNode(rect, m_selectionColor));
+ }
+
+ // Then, go through all the nodes for all lines and combine all QGlyphRuns with a common
+ // font, selection state and clip node.
+ typedef QPair<QFontEngine *, QPair<QSGClipNode *, QPair<QRgb, int> > > KeyType;
+ QHash<KeyType, BinaryTreeNode *> map;
+ for (int i=0; i<m_processedNodes.size(); ++i) {
+ BinaryTreeNode *node = m_processedNodes.data() + i;
+
+ QGlyphRun glyphRun = node->glyphRun;
+ QRawFont rawFont = glyphRun.rawFont();
+ QRawFontPrivate *rawFontD = QRawFontPrivate::get(rawFont);
+
+ QFontEngine *fontEngine = rawFontD->fontEngine;
+
+ KeyType key(qMakePair(fontEngine,
+ qMakePair(node->clipNode,
+ qMakePair(node->color.rgba(), int(node->selectionState)))));
+
+ BinaryTreeNode *otherNode = map.value(key, 0);
+ if (otherNode != 0) {
+ QGlyphRun &otherGlyphRun = otherNode->glyphRun;
+
+ QVector<quint32> otherGlyphIndexes = otherGlyphRun.glyphIndexes();
+ QVector<QPointF> otherGlyphPositions = otherGlyphRun.positions();
+
+ otherGlyphIndexes += glyphRun.glyphIndexes();
+
+ QVector<QPointF> glyphPositions = glyphRun.positions();
+ for (int j=0; j<glyphPositions.size(); ++j) {
+ otherGlyphPositions += glyphPositions.at(j) + (node->position - otherNode->position);
+ }
+
+ otherGlyphRun.setGlyphIndexes(otherGlyphIndexes);
+ otherGlyphRun.setPositions(otherGlyphPositions);
+
+ } else {
+ map.insert(key, node);
+ }
+ }
+
+ // ...and add clip nodes and glyphs to tree.
+ QHash<KeyType, BinaryTreeNode *>::const_iterator it = map.constBegin();
+ while (it != map.constEnd()) {
+
+ BinaryTreeNode *node = it.value();
+
+ QSGClipNode *clipNode = node->clipNode;
+ if (clipNode != 0 && clipNode->parent() == 0 )
+ parentNode->appendChildNode(clipNode);
+
+ QColor color = node->selectionState == BinaryTreeNode::Selected
+ ? m_selectedTextColor
+ : node->color;
+
+ parentNode->addGlyphs(node->position, node->glyphRun, color, style, styleColor, clipNode);
+
+ ++it;
+ }
+
+ // Finally, add decorations for each node to the tree.
+ for (int i=0; i<m_lines.size(); ++i) {
+ const TextDecoration &textDecoration = m_lines.at(i);
+
+ QColor color = textDecoration.selectionState == BinaryTreeNode::Selected
+ ? m_selectedTextColor
+ : textDecoration.color;
+
+ parentNode->appendChildNode(new QSGSimpleRectNode(textDecoration.rect, color));
+ }
+ }
}
-void QSGTextNode::addTextDocument(const QPointF &position, QTextDocument *textDocument, const QColor &color,
- QSGText::TextStyle style, const QColor &styleColor)
+void QSGTextNode::addTextDocument(const QPointF &, QTextDocument *textDocument,
+ const QColor &textColor,
+ QSGText::TextStyle style, const QColor &styleColor,
+ const QColor &selectionColor, const QColor &selectedTextColor,
+ int selectionStart, int selectionEnd)
{
- Q_UNUSED(position)
QTextFrame *textFrame = textDocument->rootFrame();
- QPointF p = textDocument->documentLayout()->frameBoundingRect(textFrame).topLeft();
+ QPointF position = textDocument->documentLayout()->frameBoundingRect(textFrame).topLeft();
+
+ SelectionEngine engine;
+ engine.setTextColor(textColor);
+ engine.setSelectedTextColor(selectedTextColor);
+ engine.setSelectionColor(selectionColor);
+
+ bool hasSelection = selectionStart >= 0 && selectionEnd >= 0 && selectionStart != selectionEnd;
QTextFrame::iterator it = textFrame->begin();
while (!it.atEnd()) {
- addTextBlock(p, textDocument, it.currentBlock(), color, style, styleColor);
+ Q_ASSERT(!engine.currentLine().isValid());
+
+ QTextBlock block = it.currentBlock();
+
+ QTextBlock::iterator blockIterator = block.begin();
+ while (!blockIterator.atEnd()) {
+ QTextFragment fragment = blockIterator.fragment();
+ if (fragment.text().isEmpty())
+ continue;
+
+ QPointF blockPosition = textDocument->documentLayout()->blockBoundingRect(block).topLeft();
+ engine.setPosition(position + blockPosition);
+
+ QTextCharFormat charFormat = fragment.charFormat();
+ if (!textColor.isValid())
+ engine.setTextColor(charFormat.foreground().color());
+
+ int fragmentEnd = fragment.position() + fragment.length();
+ int textPos = fragment.position();
+ while (textPos < fragmentEnd) {
+ int blockRelativePosition = textPos - block.position();
+ QTextLine line = block.layout()->lineForTextPosition(blockRelativePosition);
+ Q_ASSERT(line.textLength() > 0);
+ if (!engine.currentLine().isValid() || line.lineNumber() != engine.currentLine().lineNumber())
+ engine.setCurrentLine(line);
+
+ int lineEnd = line.textStart() + block.position() + line.textLength();
+
+ int len = qMin(lineEnd - textPos, fragmentEnd - textPos);
+ Q_ASSERT(len > 0);
+
+ int currentStepEnd = textPos + len;
+
+ if (!hasSelection || selectionStart > currentStepEnd || selectionEnd < textPos) {
+ QList<QGlyphRun> glyphRuns = fragment.glyphRuns(blockRelativePosition, len);
+ for (int j=0; j<glyphRuns.size(); ++j)
+ engine.addUnselectedGlyphs(glyphRuns.at(j));
+ } else {
+ if (textPos < selectionStart) {
+ int unselectedPartLength = qMin(selectionStart - textPos, len);
+ QList<QGlyphRun> glyphRuns = fragment.glyphRuns(blockRelativePosition,
+ unselectedPartLength);
+ for (int j=0; j<glyphRuns.size(); ++j)
+ engine.addUnselectedGlyphs(glyphRuns.at(j));
+ }
+
+ if (selectionStart < currentStepEnd && selectionEnd > textPos) {
+ int currentSelectionStart = qMax(selectionStart, textPos);
+ int currentSelectionLength = qMin(selectionEnd - currentSelectionStart,
+ currentStepEnd - currentSelectionStart);
+ int selectionRelativeBlockPosition = currentSelectionStart - block.position();
+
+ QList<QGlyphRun> glyphRuns = fragment.glyphRuns(selectionRelativeBlockPosition,
+ currentSelectionLength);
+ for (int j=0; j<glyphRuns.size(); ++j)
+ engine.addSelectedGlyphs(glyphRuns.at(j));
+ }
+
+ if (selectionEnd >= textPos && selectionEnd < currentStepEnd) {
+ QList<QGlyphRun> glyphRuns = fragment.glyphRuns(selectionEnd - block.position(),
+ currentStepEnd - selectionEnd);
+ for (int j=0; j<glyphRuns.size(); ++j)
+ engine.addUnselectedGlyphs(glyphRuns.at(j));
+ }
+ }
+
+ textPos = currentStepEnd;
+ }
+
+ ++blockIterator;
+ }
+
+ engine.setCurrentLine(QTextLine()); // Reset current line because the text layout changed
++it;
}
+
+ engine.addToSceneGraph(this, style, styleColor);
}
void QSGTextNode::addTextLayout(const QPointF &position, QTextLayout *textLayout, const QColor &color,
- QSGText::TextStyle style, const QColor &styleColor)
+ QSGText::TextStyle style, const QColor &styleColor,
+ const QColor &selectionColor, const QColor &selectedTextColor,
+ int selectionStart, int selectionEnd)
{
- QList<QGlyphRun> glyphsList(textLayout->glyphRuns());
-
- QSGGlyphNode *prevNode = 0;
-
- QFont font = textLayout->font();
- qreal underlinePosition, ascent, lineThickness;
- int decorations = NoDecoration;
- decorations |= (font.underline() ? Underline : 0);
- decorations |= (font.overline() ? Overline : 0);
- decorations |= (font.strikeOut() ? StrikeOut : 0);
-
- underlinePosition = ascent = lineThickness = 0;
- for (int i=0; i<glyphsList.size(); ++i) {
- QGlyphRun glyphs = glyphsList.at(i);
- QRawFont rawfont = glyphs.rawFont();
- prevNode = addGlyphs(position + QPointF(0, rawfont.ascent()), glyphs, color, style, styleColor);
-
- if (decorations) {
- qreal rawAscent = rawfont.ascent();
- if (decorations & Underline) {
- ascent = qMax(ascent, rawAscent);
- qreal pos = rawfont.underlinePosition();
- if (pos > underlinePosition) {
- underlinePosition = pos;
- // take line thickness from the rawfont with maximum underline
- // position in this case
- lineThickness = rawfont.lineThickness();
- }
- } else {
- // otherwise it's strike out or overline, we take line thickness
- // from the rawfont with maximum ascent
- if (rawAscent > ascent) {
- ascent = rawAscent;
- lineThickness = rawfont.lineThickness();
- }
+ SelectionEngine engine;
+ engine.setTextColor(color);
+ engine.setSelectedTextColor(selectedTextColor);
+ engine.setSelectionColor(selectionColor);
+ engine.setPosition(position);
+
+ for (int i=0; i<textLayout->lineCount(); ++i) {
+ QTextLine line = textLayout->lineAt(i);
+
+ engine.setCurrentLine(line);
+
+ int lineEnd = line.textStart() + line.textLength();
+ if (selectionStart > lineEnd || selectionEnd < line.textStart()) {
+ QList<QGlyphRun> glyphRuns = line.glyphRuns();
+ for (int j=0; j<glyphRuns.size(); ++j)
+ engine.addUnselectedGlyphs(glyphRuns.at(j));
+ } else {
+ if (line.textStart() < selectionStart) {
+ QList<QGlyphRun> glyphRuns = line.glyphRuns(line.textStart(),
+ qMin(selectionStart - line.textStart(),
+ line.textLength()));
+
+ for (int j=0; j<glyphRuns.size(); ++j)
+ engine.addUnselectedGlyphs(glyphRuns.at(j));
+ }
+
+ if (lineEnd >= selectionStart && selectionStart >= line.textStart()) {
+ QList<QGlyphRun> glyphRuns = line.glyphRuns(selectionStart, selectionEnd - selectionStart + 1);
+
+ for (int j=0; j<glyphRuns.size(); ++j)
+ engine.addSelectedGlyphs(glyphRuns.at(j));
+ }
+
+ if (selectionEnd >= line.textStart() && selectionEnd < lineEnd) {
+ QList<QGlyphRun> glyphRuns = line.glyphRuns(selectionEnd + 1, lineEnd - selectionEnd);
+ for (int j=0; j<glyphRuns.size(); ++j)
+ engine.addUnselectedGlyphs(glyphRuns.at(j));
}
}
}
- if (decorations) {
- addTextDecorations(Decoration(decorations), position + QPointF(0, ascent), color,
- textLayout->boundingRect().width(),
- lineThickness, underlinePosition, ascent);
- }
+ engine.addToSceneGraph(this, style, styleColor);
}
@@ -383,49 +936,11 @@ bool QSGTextNode::isComplexRichText(QTextDocument *doc)
return reader.hasError();
}
-void QSGTextNode::addTextBlock(const QPointF &position, QTextDocument *textDocument, const QTextBlock &block,
- const QColor &overrideColor, QSGText::TextStyle style, const QColor &styleColor)
-{
- if (!block.isValid())
- return;
-
- QPointF blockPosition = textDocument->documentLayout()->blockBoundingRect(block).topLeft();
-
- QTextBlock::iterator it = block.begin();
- while (!it.atEnd()) {
- QTextFragment fragment = it.fragment();
- if (!fragment.text().isEmpty()) {
- QTextCharFormat charFormat = fragment.charFormat();
- QColor color = overrideColor.isValid()
- ? overrideColor
- : charFormat.foreground().color();
-
- QList<QGlyphRun> glyphsList = fragment.glyphRuns();
- for (int i=0; i<glyphsList.size(); ++i) {
- QGlyphRun glyphs = glyphsList.at(i);
- QRawFont font = glyphs.rawFont();
- QSGGlyphNode *glyphNode = addGlyphs(position + blockPosition + QPointF(0, font.ascent()),
- glyphs, color, style, styleColor);
- int decorations = (glyphs.overline() ? Overline : 0) |
- (glyphs.strikeOut() ? StrikeOut : 0) |
- (glyphs.underline() ? Underline : 0);
- if (decorations) {
- QPointF baseLine = glyphNode->baseLine();
- qreal width = glyphNode->boundingRect().width();
- addTextDecorations(Decoration(decorations), baseLine, color, width,
- font.lineThickness(), font.underlinePosition(), font.ascent());
- }
- }
- }
-
- ++it;
- }
-}
-
void QSGTextNode::deleteContent()
{
- while (firstChild() > 0)
+ while (firstChild() != 0)
delete firstChild();
+ m_cursorNode = 0;
}
#if 0
diff --git a/src/declarative/items/qsgtextnode_p.h b/src/declarative/items/qsgtextnode_p.h
index 7ff31998c6..4c5199aefa 100644
--- a/src/declarative/items/qsgtextnode_p.h
+++ b/src/declarative/items/qsgtextnode_p.h
@@ -54,10 +54,20 @@ class QColor;
class QTextDocument;
class QSGContext;
class QRawFont;
+class QSGSimpleRectNode;
+class QSGClipNode;
class QSGTextNode : public QSGTransformNode
{
public:
+ enum Decoration {
+ NoDecoration = 0x0,
+ Underline = 0x1,
+ Overline = 0x2,
+ StrikeOut = 0x4
+ };
+ Q_DECLARE_FLAGS(Decorations, Decoration)
+
QSGTextNode(QSGContext *);
~QSGTextNode();
@@ -65,26 +75,24 @@ public:
void deleteContent();
void addTextLayout(const QPointF &position, QTextLayout *textLayout, const QColor &color = QColor(),
- QSGText::TextStyle style = QSGText::Normal, const QColor &styleColor = QColor());
+ QSGText::TextStyle style = QSGText::Normal, const QColor &styleColor = QColor(),
+ const QColor &selectionColor = QColor(), const QColor &selectedTextColor = QColor(),
+ int selectionStart = -1, int selectionEnd = -1);
void addTextDocument(const QPointF &position, QTextDocument *textDocument, const QColor &color = QColor(),
- QSGText::TextStyle style = QSGText::Normal, const QColor &styleColor = QColor());
+ QSGText::TextStyle style = QSGText::Normal, const QColor &styleColor = QColor(),
+ const QColor &selectionColor = QColor(), const QColor &selectedTextColor = QColor(),
+ int selectionStart = -1, int selectionEnd = -1);
-private:
- enum Decoration {
- NoDecoration = 0x0,
- Underline = 0x1,
- Overline = 0x2,
- StrikeOut = 0x4
- };
+ void setCursor(const QRectF &rect, const QColor &color);
+ QSGSimpleRectNode *cursorNode() const { return m_cursorNode; }
- void addTextBlock(const QPointF &position, QTextDocument *textDocument, const QTextBlock &block,
- const QColor &overrideColor, QSGText::TextStyle style = QSGText::Normal, const QColor &styleColor = QColor());
QSGGlyphNode *addGlyphs(const QPointF &position, const QGlyphRun &glyphs, const QColor &color,
- QSGText::TextStyle style = QSGText::Normal, const QColor &styleColor = QColor(),
- QSGGlyphNode *node = 0);
- void addTextDecorations(Decoration decorations, const QPointF &position, const QColor &color,
- qreal width, qreal lineThickness, qreal underlinePosition, qreal ascent);
+ QSGText::TextStyle style = QSGText::Normal, const QColor &styleColor = QColor(),
+ QSGNode *parentNode = 0);
+
+private:
QSGContext *m_context;
+ QSGSimpleRectNode *m_cursorNode;
};
QT_END_NAMESPACE
diff --git a/src/declarative/items/qsgtranslate.cpp b/src/declarative/items/qsgtranslate.cpp
index fc2e7b3cc2..1de5c6c3ea 100644
--- a/src/declarative/items/qsgtranslate.cpp
+++ b/src/declarative/items/qsgtranslate.cpp
@@ -56,15 +56,29 @@ public:
qreal y;
};
+/*!
+ Constructs an empty QSGTranslate object with the given \a parent.
+*/
QSGTranslate::QSGTranslate(QObject *parent)
: QSGTransform(*new QSGTranslatePrivate, parent)
{
}
+/*!
+ Destroys the graphics scale.
+*/
QSGTranslate::~QSGTranslate()
{
}
+/*!
+ \property QSGTranslate::x
+ \brief the horizontal translation.
+
+ The translation can be any real number; the default value is 0.0.
+
+ \sa y
+*/
qreal QSGTranslate::x() const
{
Q_D(const QSGTranslate);
@@ -81,6 +95,14 @@ void QSGTranslate::setX(qreal x)
emit xChanged();
}
+/*!
+ \property QSGTranslate::y
+ \brief the vertical translation.
+
+ The translation can be any real number; the default value is 0.0.
+
+ \sa x
+*/
qreal QSGTranslate::y() const
{
Q_D(const QSGTranslate);
diff --git a/src/declarative/items/qsgvisualitemmodel.cpp b/src/declarative/items/qsgvisualitemmodel.cpp
index 7e45aeb629..5dfe01dd2b 100644
--- a/src/declarative/items/qsgvisualitemmodel.cpp
+++ b/src/declarative/items/qsgvisualitemmodel.cpp
@@ -57,6 +57,7 @@
#include <private/qdeclarativeglobal_p.h>
#include <private/qlistmodelinterface_p.h>
#include <private/qmetaobjectbuilder_p.h>
+#include <private/qdeclarativeproperty_p.h>
#include <private/qobject_p.h>
#include <QtCore/qhash.h>
@@ -122,11 +123,56 @@ public:
QList<Item> children;
};
+
+/*!
+ \qmlclass VisualItemModel QSGVisualItemModel
+ \inqmlmodule QtQuick 2
+ \ingroup qml-working-with-data
+ \brief The VisualItemModel allows items to be provided to a view.
+
+ A VisualItemModel contains the visual items to be used in a view.
+ When a VisualItemModel is used in a view, the view does not require
+ a delegate since the VisualItemModel already contains the visual
+ delegate (items).
+
+ An item can determine its index within the
+ model via the \l{VisualItemModel::index}{index} attached property.
+
+ The example below places three colored rectangles in a ListView.
+ \code
+ import QtQuick 1.0
+
+ Rectangle {
+ VisualItemModel {
+ id: itemModel
+ Rectangle { height: 30; width: 80; color: "red" }
+ Rectangle { height: 30; width: 80; color: "green" }
+ Rectangle { height: 30; width: 80; color: "blue" }
+ }
+
+ ListView {
+ anchors.fill: parent
+ model: itemModel
+ }
+ }
+ \endcode
+
+ \image visualitemmodel.png
+
+ \sa {declarative/modelviews/visualitemmodel}{VisualItemModel example}
+*/
QSGVisualItemModel::QSGVisualItemModel(QObject *parent)
: QSGVisualModel(*(new QSGVisualItemModelPrivate), parent)
{
}
+/*!
+ \qmlattachedproperty int QtQuick2::VisualItemModel::index
+ This attached property holds the index of this delegate's item within the model.
+
+ It is attached to each instance of the delegate.
+*/
+
QDeclarativeListProperty<QSGItem> QSGVisualItemModel::children()
{
Q_D(QSGVisualItemModel);
@@ -134,6 +180,11 @@ QDeclarativeListProperty<QSGItem> QSGVisualItemModel::children()
d->children_count, d->children_at);
}
+/*!
+ \qmlproperty int QtQuick2::VisualItemModel::count
+
+ The number of items in the model. This property is readonly.
+*/
int QSGVisualItemModel::count() const
{
Q_D(const QSGVisualItemModel);
@@ -198,20 +249,53 @@ QSGVisualItemModelAttached *QSGVisualItemModel::qmlAttachedProperties(QObject *o
//============================================================================
-class VDMDelegateDataType : public QDeclarativeOpenMetaObjectType
+class VDMDelegateDataType : public QDeclarativeRefCount
{
public:
- VDMDelegateDataType(const QMetaObject *base, QDeclarativeEngine *engine) : QDeclarativeOpenMetaObjectType(base, engine) {}
+ VDMDelegateDataType()
+ : metaObject(0)
+ , propertyCache(0)
+ , propertyOffset(0)
+ , signalOffset(0)
+ , shared(true)
+ {
+ }
+
+ VDMDelegateDataType(const VDMDelegateDataType &type)
+ : metaObject(0)
+ , propertyCache(0)
+ , propertyOffset(type.propertyOffset)
+ , signalOffset(type.signalOffset)
+ , shared(false)
+ , builder(type.metaObject, QMetaObjectBuilder::Properties
+ | QMetaObjectBuilder::Signals
+ | QMetaObjectBuilder::SuperClass
+ | QMetaObjectBuilder::ClassName)
+ {
+ builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
+ }
- void propertyCreated(int, QMetaPropertyBuilder &prop) {
- prop.setWritable(false);
+ ~VDMDelegateDataType()
+ {
+ if (propertyCache)
+ propertyCache->release();
+ qFree(metaObject);
}
+
+ QMetaObject *metaObject;
+ QDeclarativePropertyCache *propertyCache;
+ int propertyOffset;
+ int signalOffset;
+ bool shared : 1;
+ QMetaObjectBuilder builder;
};
class QSGVisualDataModelParts;
class QSGVisualDataModelData;
+class QSGVisualDataModelDataMetaObject;
class QSGVisualDataModelPrivate : public QObjectPrivate
{
+ Q_DECLARE_PUBLIC(QSGVisualDataModel)
public:
QSGVisualDataModelPrivate(QDeclarativeContext *);
@@ -228,55 +312,30 @@ public:
QDeclarativeGuard<QDeclarativeContext> m_context;
QList<int> m_roles;
QHash<QByteArray,int> m_roleNames;
- void ensureRoles() {
- if (m_roleNames.isEmpty()) {
- if (m_listModelInterface) {
- m_roles = m_listModelInterface->roles();
- for (int ii = 0; ii < m_roles.count(); ++ii)
- m_roleNames.insert(m_listModelInterface->toString(m_roles.at(ii)).toUtf8(), m_roles.at(ii));
- } else if (m_abstractItemModel) {
- for (QHash<int,QByteArray>::const_iterator it = m_abstractItemModel->roleNames().begin();
- it != m_abstractItemModel->roleNames().end(); ++it) {
- m_roles.append(it.key());
- m_roleNames.insert(*it, it.key());
- }
- if (m_roles.count())
- m_roleNames.insert("hasModelChildren", -1);
- } else if (m_listAccessor) {
- m_roleNames.insert("modelData", 0);
- if (m_listAccessor->type() == QDeclarativeListAccessor::Instance) {
- if (QObject *object = m_listAccessor->at(0).value<QObject*>()) {
- int count = object->metaObject()->propertyCount();
- for (int ii = 1; ii < count; ++ii) {
- const QMetaProperty &prop = object->metaObject()->property(ii);
- m_roleNames.insert(prop.name(), 0);
- }
- }
- }
- }
- }
+
+ void addProperty(int role, int propertyId, const char *propertyName, const char *propertyType, bool isModelData = false);
+ template <typename T> void setModelDataType()
+ {
+ createModelData = &T::create;
+ m_delegateDataType->builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
+ m_delegateDataType->builder.setClassName(T::staticMetaObject.className());
+ m_delegateDataType->builder.setSuperClass(&T::staticMetaObject);
+ m_delegateDataType->propertyOffset = T::staticMetaObject.propertyCount();
+ m_delegateDataType->signalOffset = T::staticMetaObject.methodCount();
}
+ QSGVisualDataModelData *createMetaObject(int index, QSGVisualDataModel *model);
- QHash<int,int> m_roleToPropId;
- int m_modelDataPropId;
- void createMetaData() {
- if (!m_metaDataCreated) {
- ensureRoles();
- if (m_roleNames.count()) {
- QHash<QByteArray, int>::const_iterator it = m_roleNames.begin();
- while (it != m_roleNames.end()) {
- int propId = m_delegateDataType->createProperty(it.key()) - m_delegateDataType->propertyOffset();
- m_roleToPropId.insert(*it, propId);
- ++it;
- }
- // Add modelData property
- if (m_roles.count() == 1 && !m_roleNames.contains("modelData"))
- m_modelDataPropId = m_delegateDataType->createProperty("modelData") - m_delegateDataType->propertyOffset();
- m_metaDataCreated = true;
- }
- }
+ static QSGVisualDataModelData *initializeModelData(int index, QSGVisualDataModel *model) {
+ return get(model)->createMetaObject(index, model);
}
+ typedef QSGVisualDataModelData *(*CreateModelData)(int index, QSGVisualDataModel *model);
+
+ struct PropertyData {
+ int role;
+ bool isModelData : 1;
+ };
+
struct ObjectRef {
ObjectRef(QObject *object=0) : obj(object), ref(1) {}
QObject *obj;
@@ -338,11 +397,12 @@ public:
friend class QSGVisualItemParts;
VDMDelegateDataType *m_delegateDataType;
+ CreateModelData createModelData;
+
friend class QSGVisualDataModelData;
- bool m_metaDataCreated : 1;
- bool m_metaDataCacheable : 1;
bool m_delegateValidated : 1;
bool m_completePending : 1;
+ bool m_objectList : 1;
QSGVisualDataModelData *data(QObject *item);
@@ -352,164 +412,315 @@ public:
QModelIndex m_root;
QList<QByteArray> watchedRoles;
QList<int> watchedRoleIds;
-};
-
-class QSGVisualDataModelDataMetaObject : public QDeclarativeOpenMetaObject
-{
-public:
- QSGVisualDataModelDataMetaObject(QObject *parent, QDeclarativeOpenMetaObjectType *type)
- : QDeclarativeOpenMetaObject(parent, type) {}
- virtual QVariant initialValue(int);
- virtual int createProperty(const char *, const char *);
-
-private:
- friend class QSGVisualDataModelData;
+ QVector<PropertyData> m_propertyData;
};
class QSGVisualDataModelData : public QObject
{
-Q_OBJECT
+ Q_OBJECT
+ Q_PROPERTY(int index READ index NOTIFY indexChanged)
public:
QSGVisualDataModelData(int index, QSGVisualDataModel *model);
~QSGVisualDataModelData();
- Q_PROPERTY(int index READ index NOTIFY indexChanged)
int index() const;
void setIndex(int index);
- int propForRole(int) const;
- int modelDataPropertyId() const {
- QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(m_model);
- return model->m_modelDataPropId;
- }
-
- void setValue(int, const QVariant &);
- bool hasValue(int id) const {
- return m_meta->hasValue(id);
- }
-
- void ensureProperties();
-
Q_SIGNALS:
void indexChanged();
-private:
- friend class QSGVisualDataModelDataMetaObject;
+public:
int m_index;
QDeclarativeGuard<QSGVisualDataModel> m_model;
- QSGVisualDataModelDataMetaObject *m_meta;
};
-int QSGVisualDataModelData::propForRole(int id) const
+class QSGVisualDataModelDataMetaObject : public QAbstractDynamicMetaObject
{
- QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(m_model);
- QHash<int,int>::const_iterator it = model->m_roleToPropId.find(id);
- if (it != model->m_roleToPropId.end())
- return *it;
+public:
+ QSGVisualDataModelDataMetaObject(QSGVisualDataModelData *data, VDMDelegateDataType *type)
+ : m_data(data)
+ , m_type(type)
+ {
+ QObjectPrivate *op = QObjectPrivate::get(m_data);
+ *static_cast<QMetaObject *>(this) = *type->metaObject;
+ op->metaObject = this;
+ m_type->addref();
+ }
- return -1;
-}
+ ~QSGVisualDataModelDataMetaObject() { m_type->release(); }
-void QSGVisualDataModelData::setValue(int id, const QVariant &val)
-{
- m_meta->setValue(id, val);
-}
+ QSGVisualDataModelData *m_data;
+ VDMDelegateDataType *m_type;
+};
-int QSGVisualDataModelDataMetaObject::createProperty(const char *name, const char *type)
+class QSGVDMAbstractItemModelDataMetaObject : public QSGVisualDataModelDataMetaObject
{
- QSGVisualDataModelData *data =
- static_cast<QSGVisualDataModelData *>(object());
+public:
+ QSGVDMAbstractItemModelDataMetaObject(QSGVisualDataModelData *object, VDMDelegateDataType *type)
+ : QSGVisualDataModelDataMetaObject(object, type) {}
+
+ int metaCall(QMetaObject::Call call, int id, void **arguments)
+ {
+ if (call == QMetaObject::ReadProperty && id >= m_type->propertyOffset) {
+ QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(m_data->m_model);
+ if (m_data->m_index == -1 || !model->m_abstractItemModel)
+ return -1;
+ *static_cast<QVariant *>(arguments[0]) = model->m_abstractItemModel->index(
+ m_data->m_index, 0, model->m_root).data(model->m_propertyData.at(id - m_type->propertyOffset).role);
+ return -1;
+ } else {
+ return m_data->qt_metacall(call, id, arguments);
+ }
+ }
+};
- if (!data->m_model)
- return -1;
+class QSGVDMAbstractItemModelData : public QSGVisualDataModelData
+{
+ Q_OBJECT
+ Q_PROPERTY(bool hasModelChildren READ hasModelChildren CONSTANT)
+public:
+ bool hasModelChildren() const
+ {
+ QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(m_model);
+ return model->m_abstractItemModel->hasChildren(model->m_abstractItemModel->index(m_index, 0, model->m_root));
+ }
- QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(data->m_model);
- if (data->m_index < 0 || data->m_index >= model->modelCount())
- return -1;
+ static QSGVisualDataModelData *create(int index, QSGVisualDataModel *model) {
+ return new QSGVDMAbstractItemModelData(index, model); }
+private:
+ QSGVDMAbstractItemModelData(int index, QSGVisualDataModel *model)
+ : QSGVisualDataModelData(index, model)
+ {
+ new QSGVDMAbstractItemModelDataMetaObject(
+ this, QSGVisualDataModelPrivate::get(m_model)->m_delegateDataType);
+ }
+};
- if ((!model->m_listModelInterface || !model->m_abstractItemModel) && model->m_listAccessor) {
- if (model->m_listAccessor->type() == QDeclarativeListAccessor::ListProperty) {
- model->ensureRoles();
- if (qstrcmp(name,"modelData") == 0)
- return QDeclarativeOpenMetaObject::createProperty(name, type);
+class QSGVDMListModelInterfaceDataMetaObject : public QSGVisualDataModelDataMetaObject
+{
+public:
+ QSGVDMListModelInterfaceDataMetaObject(QSGVisualDataModelData *object, VDMDelegateDataType *type)
+ : QSGVisualDataModelDataMetaObject(object, type) {}
+
+ int metaCall(QMetaObject::Call call, int id, void **arguments)
+ {
+ if (call == QMetaObject::ReadProperty && id >= m_type->propertyOffset) {
+ QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(m_data->m_model);
+ if (m_data->m_index == -1 || !model->m_listModelInterface)
+ return -1;
+ *static_cast<QVariant *>(arguments[0]) = model->m_listModelInterface->data(
+ m_data->m_index, model->m_propertyData.at(id - m_type->propertyOffset).role);
+ return -1;
+ } else {
+ return m_data->qt_metacall(call, id, arguments);
}
}
- return -1;
-}
+};
-QVariant QSGVisualDataModelDataMetaObject::initialValue(int propId)
+class QSGVDMListModelInterfaceData : public QSGVisualDataModelData
{
- QSGVisualDataModelData *data =
- static_cast<QSGVisualDataModelData *>(object());
+public:
+ static QSGVisualDataModelData *create(int index, QSGVisualDataModel *model) {
+ return new QSGVDMListModelInterfaceData(index, model); }
+private:
+ QSGVDMListModelInterfaceData(int index, QSGVisualDataModel *model)
+ : QSGVisualDataModelData(index, model)
+ {
+ new QSGVDMListModelInterfaceDataMetaObject(
+ this, QSGVisualDataModelPrivate::get(m_model)->m_delegateDataType);
+ }
+};
- Q_ASSERT(data->m_model);
- QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(data->m_model);
+class QSGVDMListAccessorData : public QSGVisualDataModelData
+{
+ Q_OBJECT
+ Q_PROPERTY(QVariant modelData READ modelData CONSTANT)
+public:
+ QVariant modelData() const {
+ return QSGVisualDataModelPrivate::get(m_model)->m_listAccessor->at(m_index); }
- QByteArray propName = name(propId);
- if ((!model->m_listModelInterface || !model->m_abstractItemModel) && model->m_listAccessor) {
- if (propName == "modelData") {
- if (model->m_listAccessor->type() == QDeclarativeListAccessor::Instance) {
- QObject *object = model->m_listAccessor->at(0).value<QObject*>();
- return object->metaObject()->property(1).read(object); // the first property after objectName
- }
- return model->m_listAccessor->at(data->m_index);
+ static QSGVisualDataModelData *create(int index, QSGVisualDataModel *model) {
+ return new QSGVDMListAccessorData(index, model); }
+private:
+ QSGVDMListAccessorData(int index, QSGVisualDataModel *model)
+ : QSGVisualDataModelData(index, model)
+ {
+ }
+};
+
+class QSGVDMObjectDataMetaObject : public QSGVisualDataModelDataMetaObject
+{
+public:
+ QSGVDMObjectDataMetaObject(QSGVisualDataModelData *data, VDMDelegateDataType *type)
+ : QSGVisualDataModelDataMetaObject(data, type)
+ , m_object(QSGVisualDataModelPrivate::get(data->m_model)->m_listAccessor->at(data->m_index).value<QObject *>())
+ {}
+
+ int metaCall(QMetaObject::Call call, int id, void **arguments)
+ {
+ if (id >= m_type->propertyOffset
+ && (call == QMetaObject::ReadProperty
+ || call == QMetaObject::WriteProperty
+ || call == QMetaObject::ResetProperty)) {
+ if (m_object)
+ QMetaObject::metacall(m_object, call, id - m_type->propertyOffset + 1, arguments);
+ return -1;
+ } else if (id >= m_type->signalOffset && call == QMetaObject::InvokeMetaMethod) {
+ QMetaObject::activate(m_data, this, id, 0);
+ return -1;
} else {
- // return any property of a single object instance.
- QObject *object = model->m_listAccessor->at(data->m_index).value<QObject*>();
- return object->property(propName);
+ return m_data->qt_metacall(call, id, arguments);
}
- } else if (model->m_listModelInterface) {
- model->ensureRoles();
- QHash<QByteArray,int>::const_iterator it = model->m_roleNames.find(propName);
- if (it != model->m_roleNames.end()) {
- QVariant value = model->m_listModelInterface->data(data->m_index, *it);
- return value;
- } else if (model->m_roles.count() == 1 && propName == "modelData") {
- //for compatibility with other lists, assign modelData if there is only a single role
- QVariant value = model->m_listModelInterface->data(data->m_index, model->m_roles.first());
- return value;
+ }
+
+ int createProperty(const char *name, const char *)
+ {
+ if (!m_object)
+ return -1;
+ const QMetaObject *metaObject = m_object->metaObject();
+
+ const int previousPropertyCount = propertyCount() - propertyOffset();
+ int propertyIndex = metaObject->indexOfProperty(name);
+ if (propertyIndex == -1)
+ return -1;
+ if (previousPropertyCount + 1 == metaObject->propertyCount())
+ return propertyIndex + m_type->propertyOffset - 1;
+
+ if (m_type->shared) {
+ VDMDelegateDataType *type = m_type;
+ m_type = new VDMDelegateDataType(*m_type);
+ type->release();
}
- } else if (model->m_abstractItemModel) {
- model->ensureRoles();
- QModelIndex index = model->m_abstractItemModel->index(data->m_index, 0, model->m_root);
- if (propName == "hasModelChildren") {
- return model->m_abstractItemModel->hasChildren(index);
- } else {
- QHash<QByteArray,int>::const_iterator it = model->m_roleNames.find(propName);
- if (it != model->m_roleNames.end()) {
- return model->m_abstractItemModel->data(index, *it);
- } else if (model->m_roles.count() == 1 && propName == "modelData") {
- //for compatibility with other lists, assign modelData if there is only a single role
- return model->m_abstractItemModel->data(index, model->m_roles.first());
+
+ const int previousMethodCount = methodCount();
+ int notifierId = previousMethodCount;
+ for (int propertyId = previousPropertyCount; propertyId < metaObject->propertyCount() - 1; ++propertyId) {
+ QMetaProperty property = metaObject->property(propertyId + 1);
+ QMetaPropertyBuilder propertyBuilder;
+ if (property.hasNotifySignal()) {
+ m_type->builder.addSignal("__" + QByteArray::number(propertyId) + "()");
+ propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName(), notifierId);
+ ++notifierId;
+ } else {
+ propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName());
+ }
+ propertyBuilder.setWritable(property.isWritable());
+ propertyBuilder.setResettable(property.isResettable());
+ propertyBuilder.setConstant(property.isConstant());
+ }
+
+ if (m_type->metaObject)
+ qFree(m_type->metaObject);
+ m_type->metaObject = m_type->builder.toMetaObject();
+ *static_cast<QMetaObject *>(this) = *m_type->metaObject;
+
+ notifierId = previousMethodCount;
+ for (int i = previousPropertyCount; i < metaObject->propertyCount(); ++i) {
+ QMetaProperty property = metaObject->property(i);
+ if (property.hasNotifySignal()) {
+ QDeclarativePropertyPrivate::connect(
+ m_object, property.notifySignalIndex(), m_data, notifierId);
+ ++notifierId;
}
}
+ return propertyIndex + m_type->propertyOffset - 1;
+ }
+
+ QDeclarativeGuard<QObject> m_object;
+};
+
+class QSGVDMObjectData : public QSGVisualDataModelData
+{
+ Q_OBJECT
+ Q_PROPERTY(QObject *modelData READ modelData CONSTANT)
+public:
+ QObject *modelData() const { return m_metaObject->m_object; }
+
+ static QSGVisualDataModelData *create(int index, QSGVisualDataModel *model) {
+ return new QSGVDMObjectData(index, model); }
+
+private:
+ QSGVDMObjectData(int index, QSGVisualDataModel *model)
+ : QSGVisualDataModelData(index, model)
+ , m_metaObject(new QSGVDMObjectDataMetaObject(this, QSGVisualDataModelPrivate::get(m_model)->m_delegateDataType))
+ {
}
- Q_ASSERT(!"Can never be reached");
- return QVariant();
+
+ QSGVDMObjectDataMetaObject *m_metaObject;
+};
+
+void QSGVisualDataModelPrivate::addProperty(
+ int role, int propertyId, const char *propertyName, const char *propertyType, bool isModelData)
+{
+ PropertyData propertyData;
+ propertyData.role = role;
+ propertyData.isModelData = isModelData;
+ m_delegateDataType->builder.addSignal("__" + QByteArray::number(propertyId) + "()");
+ QMetaPropertyBuilder property = m_delegateDataType->builder.addProperty(
+ propertyName, propertyType, propertyId);
+ property.setWritable(false);
+
+ m_propertyData.append(propertyData);
}
-QSGVisualDataModelData::QSGVisualDataModelData(int index,
- QSGVisualDataModel *model)
-: m_index(index), m_model(model),
-m_meta(new QSGVisualDataModelDataMetaObject(this, QSGVisualDataModelPrivate::get(model)->m_delegateDataType))
+QSGVisualDataModelData *QSGVisualDataModelPrivate::createMetaObject(int index, QSGVisualDataModel *model)
{
- ensureProperties();
+ Q_ASSERT(!m_delegateDataType);
+
+ m_objectList = false;
+ m_propertyData.clear();
+ if (m_listAccessor
+ && m_listAccessor->type() != QDeclarativeListAccessor::ListProperty
+ && m_listAccessor->type() != QDeclarativeListAccessor::Instance) {
+ createModelData = &QSGVDMListAccessorData::create;
+ return QSGVDMListAccessorData::create(index, model);
+ }
+
+ m_delegateDataType = new VDMDelegateDataType;
+ if (m_listModelInterface) {
+ setModelDataType<QSGVDMListModelInterfaceData>();
+ QList<int> roles = m_listModelInterface->roles();
+ for (int propertyId = 0; propertyId < roles.count(); ++propertyId) {
+ const int role = roles.at(propertyId);
+ const QByteArray propertyName = m_listModelInterface->toString(role).toUtf8();
+ addProperty(role, propertyId, propertyName, "QVariant");
+ m_roleNames.insert(propertyName, role);
+ }
+ if (m_propertyData.count() == 1)
+ addProperty(roles.first(), 1, "modelData", "QVariant", true);
+ } else if (m_abstractItemModel) {
+ setModelDataType<QSGVDMAbstractItemModelData>();
+ QHash<int, QByteArray> roleNames = m_abstractItemModel->roleNames();
+ for (QHash<int, QByteArray>::const_iterator it = roleNames.begin(); it != roleNames.end(); ++it) {
+ addProperty(it.key(), m_propertyData.count(), it.value(), "QVariant");
+ m_roleNames.insert(it.value(), it.key());
+ }
+ if (m_propertyData.count() == 1)
+ addProperty(roleNames.begin().key(), 1, "modelData", "QVariant", true);
+ } else if (m_listAccessor) {
+ setModelDataType<QSGVDMObjectData>();
+ m_objectList = true;
+ } else {
+ Q_ASSERT(!"No model set on VisualDataModel");
+ return 0;
+ }
+ m_delegateDataType->metaObject = m_delegateDataType->builder.toMetaObject();
+ if (!m_objectList) {
+ m_delegateDataType->propertyCache = new QDeclarativePropertyCache(
+ m_context ? m_context->engine() : qmlEngine(q_func()), m_delegateDataType->metaObject);
+ }
+ return createModelData(index, model);
}
-QSGVisualDataModelData::~QSGVisualDataModelData()
+QSGVisualDataModelData::QSGVisualDataModelData(int index, QSGVisualDataModel *model)
+ : m_index(index)
+ , m_model(model)
{
}
-void QSGVisualDataModelData::ensureProperties()
+QSGVisualDataModelData::~QSGVisualDataModelData()
{
- QSGVisualDataModelPrivate *modelPriv = QSGVisualDataModelPrivate::get(m_model);
- if (modelPriv->m_metaDataCacheable) {
- if (!modelPriv->m_metaDataCreated)
- modelPriv->createMetaData();
- if (modelPriv->m_metaDataCreated)
- m_meta->setCached(true);
- }
}
int QSGVisualDataModelData::index() const
@@ -571,8 +782,8 @@ QSGVisualDataModelParts::QSGVisualDataModelParts(QSGVisualDataModel *parent)
QSGVisualDataModelPrivate::QSGVisualDataModelPrivate(QDeclarativeContext *ctxt)
: m_listModelInterface(0), m_abstractItemModel(0), m_visualItemModel(0), m_delegate(0)
-, m_context(ctxt), m_modelDataPropId(-1), m_parts(0), m_delegateDataType(0), m_metaDataCreated(false)
-, m_metaDataCacheable(false), m_delegateValidated(false), m_completePending(false), m_listAccessor(0)
+, m_context(ctxt), m_parts(0), m_delegateDataType(0), createModelData(&initializeModelData)
+, m_delegateValidated(false), m_completePending(false), m_objectList(false), m_listAccessor(0)
{
}
@@ -586,6 +797,26 @@ QSGVisualDataModelData *QSGVisualDataModelPrivate::data(QObject *item)
//---------------------------------------------------------------------------
+/*!
+ \qmlclass VisualDataModel QSGVisualDataModel
+ \inqmlmodule QtQuick 2
+ \ingroup qml-working-with-data
+ \brief The VisualDataModel encapsulates a model and delegate
+
+ A VisualDataModel encapsulates a model and the delegate that will
+ be instantiated for items in the model.
+
+ It is usually not necessary to create VisualDataModel elements.
+ However, it can be useful for manipulating and accessing the \l modelIndex
+ when a QAbstractItemModel subclass is used as the
+ model. Also, VisualDataModel is used together with \l Package to
+ provide delegates to multiple views.
+
+ The example below illustrates using a VisualDataModel with a ListView.
+
+ \snippet doc/src/snippets/declarative/visualdatamodel.qml 0
+*/
+
QSGVisualDataModel::QSGVisualDataModel()
: QSGVisualModel(*(new QSGVisualDataModelPrivate(0)))
{
@@ -605,6 +836,20 @@ QSGVisualDataModel::~QSGVisualDataModel()
d->m_delegateDataType->release();
}
+/*!
+ \qmlproperty model QtQuick2::VisualDataModel::model
+ This property holds the model providing data for the VisualDataModel.
+
+ The model provides a set of data that is used to create the items
+ for a view. For large or dynamic datasets the model is usually
+ provided by a C++ model object. The C++ model object must be a \l
+ {QAbstractItemModel} subclass or a simple list.
+
+ Models can also be created directly in QML, using a \l{ListModel} or
+ \l{XmlListModel}.
+
+ \sa {qmlmodels}{Data Models}
+*/
QVariant QSGVisualDataModel::model() const
{
Q_D(const QSGVisualDataModel);
@@ -658,9 +903,8 @@ void QSGVisualDataModel::setModel(const QVariant &model)
d->m_roleNames.clear();
if (d->m_delegateDataType)
d->m_delegateDataType->release();
- d->m_metaDataCreated = 0;
- d->m_metaDataCacheable = false;
- d->m_delegateDataType = new VDMDelegateDataType(&QSGVisualDataModelData::staticMetaObject, d->m_context?d->m_context->engine():qmlEngine(this));
+ d->m_delegateDataType = 0;
+ d->createModelData = &QSGVisualDataModelPrivate::initializeModelData;
QObject *object = qvariant_cast<QObject *>(model);
if (object && (d->m_listModelInterface = qobject_cast<QListModelInterface *>(object))) {
@@ -672,7 +916,6 @@ void QSGVisualDataModel::setModel(const QVariant &model)
this, SLOT(_q_itemsRemoved(int,int)));
QObject::connect(d->m_listModelInterface, SIGNAL(itemsMoved(int,int,int)),
this, SLOT(_q_itemsMoved(int,int,int)));
- d->m_metaDataCacheable = true;
if (d->m_delegate && d->m_listModelInterface->count())
emit itemsInserted(0, d->m_listModelInterface->count());
return;
@@ -687,7 +930,6 @@ void QSGVisualDataModel::setModel(const QVariant &model)
this, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
QObject::connect(d->m_abstractItemModel, SIGNAL(modelReset()), this, SLOT(_q_modelReset()));
QObject::connect(d->m_abstractItemModel, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged()));
- d->m_metaDataCacheable = true;
if (d->m_abstractItemModel->canFetchMore(d->m_root))
d->m_abstractItemModel->fetchMore(d->m_root);
return;
@@ -710,13 +952,19 @@ void QSGVisualDataModel::setModel(const QVariant &model)
d->m_listAccessor = new QDeclarativeListAccessor;
d->m_listAccessor->setList(model, d->m_context?d->m_context->engine():qmlEngine(this));
if (d->m_listAccessor->type() != QDeclarativeListAccessor::ListProperty)
- d->m_metaDataCacheable = true;
if (d->m_delegate && d->modelCount()) {
emit itemsInserted(0, d->modelCount());
emit countChanged();
}
}
+/*!
+ \qmlproperty Component QtQuick2::VisualDataModel::delegate
+
+ The delegate provides a template defining each item instantiated by a view.
+ The index is exposed as an accessible \c index property. Properties of the
+ model are also available depending upon the type of \l {qmlmodels}{Data Model}.
+*/
QDeclarativeComponent *QSGVisualDataModel::delegate() const
{
Q_D(const QSGVisualDataModel);
@@ -741,6 +989,35 @@ void QSGVisualDataModel::setDelegate(QDeclarativeComponent *delegate)
}
}
+/*!
+ \qmlproperty QModelIndex QtQuick2::VisualDataModel::rootIndex
+
+ QAbstractItemModel provides a hierarchical tree of data, whereas
+ QML only operates on list data. \c rootIndex allows the children of
+ any node in a QAbstractItemModel to be provided by this model.
+
+ This property only affects models of type QAbstractItemModel that
+ are hierarchical (e.g, a tree model).
+
+ For example, here is a simple interactive file system browser.
+ When a directory name is clicked, the view's \c rootIndex is set to the
+ QModelIndex node of the clicked directory, thus updating the view to show
+ the new directory's contents.
+
+ \c main.cpp:
+ \snippet doc/src/snippets/declarative/visualdatamodel_rootindex/main.cpp 0
+
+ \c view.qml:
+ \snippet doc/src/snippets/declarative/visualdatamodel_rootindex/view.qml 0
+
+ If the \l model is a QAbstractItemModel subclass, the delegate can also
+ reference a \c hasModelChildren property (optionally qualified by a
+ \e model. prefix) that indicates whether the delegate's model item has
+ any child nodes.
+
+
+ \sa modelIndex(), parentModelIndex()
+*/
QVariant QSGVisualDataModel::rootIndex() const
{
Q_D(const QSGVisualDataModel);
@@ -767,6 +1044,18 @@ void QSGVisualDataModel::setRootIndex(const QVariant &root)
}
}
+/*!
+ \qmlmethod QModelIndex QtQuick2::VisualDataModel::modelIndex(int index)
+
+ QAbstractItemModel provides a hierarchical tree of data, whereas
+ QML only operates on list data. This function assists in using
+ tree models in QML.
+
+ Returns a QModelIndex for the specified index.
+ This value can be assigned to rootIndex.
+
+ \sa rootIndex
+*/
QVariant QSGVisualDataModel::modelIndex(int idx) const
{
Q_D(const QSGVisualDataModel);
@@ -775,6 +1064,18 @@ QVariant QSGVisualDataModel::modelIndex(int idx) const
return QVariant::fromValue(QModelIndex());
}
+/*!
+ \qmlmethod QModelIndex QtQuick2::VisualDataModel::parentModelIndex()
+
+ QAbstractItemModel provides a hierarchical tree of data, whereas
+ QML only operates on list data. This function assists in using
+ tree models in QML.
+
+ Returns a QModelIndex for the parent of the current rootIndex.
+ This value can be assigned to rootIndex.
+
+ \sa rootIndex
+*/
QVariant QSGVisualDataModel::parentModelIndex() const
{
Q_D(const QSGVisualDataModel);
@@ -783,6 +1084,33 @@ QVariant QSGVisualDataModel::parentModelIndex() const
return QVariant::fromValue(QModelIndex());
}
+/*!
+ \qmlproperty object QtQuick2::VisualDataModel::parts
+
+ The \a parts property selects a VisualDataModel which creates
+ delegates from the part named. This is used in conjunction with
+ the \l Package element.
+
+ For example, the code below selects a model which creates
+ delegates named \e list from a \l Package:
+
+ \code
+ VisualDataModel {
+ id: visualModel
+ delegate: Package {
+ Item { Package.name: "list" }
+ }
+ model: myModel
+ }
+
+ ListView {
+ width: 200; height:200
+ model: visualModel.parts.list
+ }
+ \endcode
+
+ \sa Package
+*/
QString QSGVisualDataModel::part() const
{
Q_D(const QSGVisualDataModel);
@@ -881,12 +1209,11 @@ QSGItem *QSGVisualDataModel::item(int index, const QByteArray &viewId, bool comp
QDeclarativeContext *ccontext = d->m_context;
if (!ccontext) ccontext = qmlContext(this);
QDeclarativeContext *ctxt = new QDeclarativeContext(ccontext);
- QSGVisualDataModelData *data = new QSGVisualDataModelData(index, this);
- if ((!d->m_listModelInterface || !d->m_abstractItemModel) && d->m_listAccessor
- && d->m_listAccessor->type() == QDeclarativeListAccessor::ListProperty) {
- ctxt->setContextObject(d->m_listAccessor->at(index).value<QObject*>());
- ctxt = new QDeclarativeContext(ctxt, ctxt);
+ if (d->m_objectList) {
+ ctxt->setContextObject(d->m_listAccessor->at(index).value<QObject *>());
+ ctxt = new QDeclarativeContext(ctxt);
}
+ QSGVisualDataModelData *data = d->createModelData(index, this);
ctxt->setContextProperty(QLatin1String("model"), data);
ctxt->setContextObject(data);
d->m_completePending = false;
@@ -975,7 +1302,7 @@ QString QSGVisualDataModel::stringValue(int index, const QString &name)
if (QObject *nobj = d->m_cache.item(index))
data = d->data(nobj);
if (!data) {
- data = new QSGVisualDataModelData(index, this);
+ data = d->createModelData(index, this);
tempData = true;
}
@@ -1031,6 +1358,21 @@ void QSGVisualDataModel::_q_itemsChanged(int index, int count,
}
}
+ QVector<int> signalIndexes;
+ for (int i = 0; i < roles.count(); ++i) {
+ const int role = roles.at(i);
+ if (!changed && d->watchedRoleIds.contains(role))
+ changed = true;
+ for (int propertyId = 0; propertyId < d->m_propertyData.count(); ++propertyId) {
+ if (d->m_propertyData.at(propertyId).role == role)
+ signalIndexes.append(propertyId + d->m_delegateDataType->signalOffset);
+ }
+ }
+ if (roles.isEmpty()) {
+ for (int propertyId = 0; propertyId < d->m_propertyData.count(); ++propertyId)
+ signalIndexes.append(propertyId + d->m_delegateDataType->signalOffset);
+ }
+
for (QHash<int,QSGVisualDataModelPrivate::ObjectRef>::ConstIterator iter = d->m_cache.begin();
iter != d->m_cache.end(); ++iter) {
const int idx = iter.key();
@@ -1038,41 +1380,8 @@ void QSGVisualDataModel::_q_itemsChanged(int index, int count,
if (idx >= index && idx < index+count) {
QSGVisualDataModelPrivate::ObjectRef objRef = *iter;
QSGVisualDataModelData *data = d->data(objRef.obj);
- for (int roleIdx = 0; roleIdx < roles.count(); ++roleIdx) {
- int role = roles.at(roleIdx);
- if (!changed && !d->watchedRoleIds.isEmpty() && d->watchedRoleIds.contains(role))
- changed = true;
- int propId = data->propForRole(role);
- if (propId != -1) {
- if (data->hasValue(propId)) {
- if (d->m_listModelInterface) {
- data->setValue(propId, d->m_listModelInterface->data(idx, role));
- } else if (d->m_abstractItemModel) {
- QModelIndex index = d->m_abstractItemModel->index(idx, 0, d->m_root);
- data->setValue(propId, d->m_abstractItemModel->data(index, role));
- }
- }
- } else {
- QString roleName;
- if (d->m_listModelInterface)
- roleName = d->m_listModelInterface->toString(role);
- else if (d->m_abstractItemModel)
- roleName = QString::fromUtf8(d->m_abstractItemModel->roleNames().value(role));
- qmlInfo(this) << "Changing role not present in item: " << roleName;
- }
- }
- if (d->m_modelDataPropId != -1) {
- // Handle the modelData role we add if there is just one role.
- if (data->hasValue(d->m_modelDataPropId)) {
- int role = d->m_roles.at(0);
- if (d->m_listModelInterface) {
- data->setValue(d->m_modelDataPropId, d->m_listModelInterface->data(idx, role));
- } else if (d->m_abstractItemModel) {
- QModelIndex index = d->m_abstractItemModel->index(idx, 0, d->m_root);
- data->setValue(d->m_modelDataPropId, d->m_abstractItemModel->data(index, role));
- }
- }
- }
+ for (int i = 0; i < signalIndexes.count(); ++i)
+ QMetaObject::activate(data, signalIndexes.at(i), 0);
}
}
if (changed)
diff --git a/src/declarative/particles/defaultshaders/coloredfragment.shader b/src/declarative/particles/defaultshaders/coloredfragment.shader
new file mode 100644
index 0000000000..4ae2643598
--- /dev/null
+++ b/src/declarative/particles/defaultshaders/coloredfragment.shader
@@ -0,0 +1,9 @@
+uniform sampler2D texture;
+uniform lowp float qt_Opacity;
+
+varying lowp vec4 fColor;
+
+void main() {
+ gl_FragColor = (texture2D(texture, gl_PointCoord)) * fColor * qt_Opacity;
+}
+
diff --git a/src/declarative/particles/defaultshaders/trailsvertex.shader b/src/declarative/particles/defaultshaders/coloredvertex.shader
index 7bc1d66b71..5b8339276c 100644
--- a/src/declarative/particles/defaultshaders/trailsvertex.shader
+++ b/src/declarative/particles/defaultshaders/coloredvertex.shader
@@ -1,18 +1,15 @@
attribute highp vec2 vPos;
-attribute highp vec2 vTex;
attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize
attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration
attribute lowp vec4 vColor;
-uniform highp mat4 matrix;
+uniform highp mat4 qt_Matrix;
uniform highp float timestamp;
-uniform lowp float opacity;
+uniform highp float entry;
-varying highp vec2 fTex;
varying lowp vec4 fColor;
-void main() {
- fTex = vTex;
+void main() {
highp float size = vData.z;
highp float endSize = vData.w;
@@ -23,15 +20,25 @@ void main() {
if (t < 0. || t > 1.)
currentSize = 0.;
+ lowp float fFade = 1.;
+
+ if (entry == 1.){
+ highp float fadeIn = min(t * 10., 1.);
+ highp float fadeOut = 1. - max(0., min((t - 0.75) * 4., 1.));
+ fFade = fadeIn * fadeOut;
+ }else if(entry == 2.){
+ highp float sizeIn = min(t * 10., 1.);
+ highp float sizeOut = 1. - max(0., min((t - 0.75) * 4., 1.));
+ currentSize = currentSize * sizeIn * sizeOut;
+ }
+
+ gl_PointSize = currentSize;
+
highp vec2 pos = vPos
- - currentSize / 2. + currentSize * vTex // adjust size
+ vVec.xy * t * vData.y // apply speed vector..
+ 0.5 * vVec.zw * pow(t * vData.y, 2.);
- gl_Position = matrix * vec4(pos.x, pos.y, 0, 1);
-
- highp float fadeIn = min(t * 10., 1.);
- highp float fadeOut = 1. - max(0., min((t - 0.75) * 4., 1.));
+ gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);
- fColor = vColor * fadeIn * fadeOut * opacity;
+ fColor = vColor * (fFade);
}
diff --git a/src/declarative/particles/defaultshaders/ctfragment.shader b/src/declarative/particles/defaultshaders/ctfragment.shader
deleted file mode 100644
index a17f5841ca..0000000000
--- a/src/declarative/particles/defaultshaders/ctfragment.shader
+++ /dev/null
@@ -1,11 +0,0 @@
-uniform sampler2D texture;
-uniform sampler2D colortable;
-uniform sampler2D opacitytable;
-
-varying highp vec2 fTex;
-varying lowp vec4 fColor;
-varying lowp float tt;
-
-void main() {
- gl_FragColor = (texture2D(texture, fTex).w) * fColor * texture2D(colortable, vec2(tt, 0.5)) *( texture2D(opacitytable, vec2(tt, 0.5)).w);
-}
diff --git a/src/declarative/particles/defaultshaders/ctvertex.shader b/src/declarative/particles/defaultshaders/ctvertex.shader
deleted file mode 100644
index b20676cc49..0000000000
--- a/src/declarative/particles/defaultshaders/ctvertex.shader
+++ /dev/null
@@ -1,38 +0,0 @@
-attribute highp vec2 vPos;
-attribute highp vec2 vTex;
-attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize
-attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration
-attribute lowp vec4 vColor;
-
-uniform highp mat4 matrix;
-uniform highp float timestamp;
-uniform sampler2D sizetable;
-uniform sampler2D opacitytable;
-
-varying highp vec2 fTex;
-varying lowp vec4 fColor;
-varying lowp float tt;
-
-void main() {
- fTex = vTex;
- highp float size = vData.z;
- highp float endSize = vData.w;
-
- highp float t = (timestamp - vData.x) / vData.y;
-
- highp float currentSize = mix(size, endSize, t * t) * texture2D(sizetable, vec2(t,0.5)).w;
-
- if (t < 0. || t > 1.)
- currentSize = 0.;
-
- highp vec2 pos = vPos
- - currentSize / 2. + currentSize * vTex // adjust size
- + vVec.xy * t * vData.y // apply speed vector..
- + 0.5 * vVec.zw * pow(t * vData.y, 2.);
-
- gl_Position = matrix * vec4(pos.x, pos.y, 0, 1);
-
- fColor = vColor;
- tt = t;
-
-}
diff --git a/src/declarative/particles/defaultshaders/deformablefragment.shader b/src/declarative/particles/defaultshaders/deformablefragment.shader
index 494053e319..1ac25ba208 100644
--- a/src/declarative/particles/defaultshaders/deformablefragment.shader
+++ b/src/declarative/particles/defaultshaders/deformablefragment.shader
@@ -1,8 +1,9 @@
uniform sampler2D texture;
+uniform lowp float qt_Opacity;
varying highp vec2 fTex;
-varying lowp float fFade;
+varying lowp vec4 fColor;
void main() {
- gl_FragColor = (texture2D(texture, fTex)) * fFade;
+ gl_FragColor = (texture2D(texture, fTex)) * fColor * qt_Opacity;
}
diff --git a/src/declarative/particles/defaultshaders/deformablevertex.shader b/src/declarative/particles/defaultshaders/deformablevertex.shader
index 01570950b1..ab6acde36d 100644
--- a/src/declarative/particles/defaultshaders/deformablevertex.shader
+++ b/src/declarative/particles/defaultshaders/deformablevertex.shader
@@ -4,13 +4,14 @@ attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize
attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration
attribute highp vec4 vDeformVec; //x,y x unit vector; z,w = y unit vector
attribute highp vec3 vRotation; //x = radians of rotation, y=rotation speed, z= bool autoRotate
+attribute lowp vec4 vColor;
-uniform highp mat4 matrix;
+uniform highp mat4 qt_Matrix;
uniform highp float timestamp;
-uniform lowp float opacity;
+uniform highp float entry;
varying highp vec2 fTex;
-varying lowp float fFade;
+varying lowp vec4 fColor;
void main() {
fTex = vTex;
@@ -21,37 +22,44 @@ void main() {
highp float currentSize = mix(size, endSize, t * t);
- highp vec2 pos;
- if (t < 0. || t > 1.){
+ if (t < 0. || t > 1.)
currentSize = 0.;
- pos = vPos;
- }else{
- highp float rotation = vRotation.x + vRotation.y * t * vData.y;
- if(vRotation.z == 1.0){
- highp vec2 curVel = vVec.zw * t * vData.y + vVec.xy;
- rotation += atan(curVel.y, curVel.x);
- }
- highp vec2 trigCalcs = vec2(cos(rotation), sin(rotation));
- highp vec2 xDeform = vDeformVec.xy * currentSize * (vTex.x-0.5);
- highp vec2 yDeform = vDeformVec.zw * currentSize * (vTex.y-0.5);
- highp vec2 xRotatedDeform;
- xRotatedDeform.x = trigCalcs.x*xDeform.x - trigCalcs.y*xDeform.y;
- xRotatedDeform.y = trigCalcs.y*xDeform.x + trigCalcs.x*xDeform.y;
- highp vec2 yRotatedDeform;
- yRotatedDeform.x = trigCalcs.x*yDeform.x - trigCalcs.y*yDeform.y;
- yRotatedDeform.y = trigCalcs.y*yDeform.x + trigCalcs.x*yDeform.y;
- pos = vPos
- + xRotatedDeform
- + yRotatedDeform
- //- vec2(1,1) * currentSize * 0.5 // 'center'
- + vVec.xy * t * vData.y // apply speed
- + 0.5 * vVec.zw * pow(t * vData.y, 2.); // apply acceleration
+
+ lowp float fFade = 1.;
+
+ if (entry == 1.){
+ highp float fadeIn = min(t * 10., 1.);
+ highp float fadeOut = 1. - max(0., min((t - 0.75) * 4., 1.));
+ fFade = fadeIn * fadeOut;
+ }else if(entry == 2.){
+ highp float sizeIn = min(t * 10., 1.);
+ highp float sizeOut = 1. - max(0., min((t - 0.75) * 4., 1.));
+ currentSize = currentSize * sizeIn * sizeOut;
}
- gl_Position = matrix * vec4(pos.x, pos.y, 0, 1);
+ highp vec2 pos;
+ highp float rotation = vRotation.x + vRotation.y * t * vData.y;
+ if(vRotation.z == 1.0){
+ highp vec2 curVel = vVec.zw * t * vData.y + vVec.xy;
+ rotation += atan(curVel.y, curVel.x);
+ }
+ highp vec2 trigCalcs = vec2(cos(rotation), sin(rotation));
+ highp vec2 xDeform = vDeformVec.xy * currentSize * (vTex.x-0.5);
+ highp vec2 yDeform = vDeformVec.zw * currentSize * (vTex.y-0.5);
+ highp vec2 xRotatedDeform;
+ xRotatedDeform.x = trigCalcs.x*xDeform.x - trigCalcs.y*xDeform.y;
+ xRotatedDeform.y = trigCalcs.y*xDeform.x + trigCalcs.x*xDeform.y;
+ highp vec2 yRotatedDeform;
+ yRotatedDeform.x = trigCalcs.x*yDeform.x - trigCalcs.y*yDeform.y;
+ yRotatedDeform.y = trigCalcs.y*yDeform.x + trigCalcs.x*yDeform.y;
+ pos = vPos
+ + xRotatedDeform
+ + yRotatedDeform
+ //- vec2(1,1) * currentSize * 0.5 // 'center'
+ + vVec.xy * t * vData.y // apply speed
+ + 0.5 * vVec.zw * pow(t * vData.y, 2.); // apply acceleration
- highp float fadeIn = min(t * 10., 1.);
- highp float fadeOut = 1. - max(0., min((t - 0.75) * 4., 1.));
+ gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);
- fFade = fadeIn * fadeOut * opacity;
+ fColor = vColor * fFade;
}
diff --git a/src/declarative/particles/defaultshaders/imagefragment.shader b/src/declarative/particles/defaultshaders/imagefragment.shader
new file mode 100644
index 0000000000..c2341fe6ff
--- /dev/null
+++ b/src/declarative/particles/defaultshaders/imagefragment.shader
@@ -0,0 +1,45 @@
+uniform sampler2D texture;
+uniform lowp float qt_Opacity;
+
+#ifdef SPRITE
+varying highp vec4 fTexS;
+#else
+#ifdef DEFORM //First non-pointsprite
+varying highp vec2 fTex;
+#endif
+#endif
+#ifdef COLOR
+varying lowp vec4 fColor;
+#else
+varying lowp float fFade;
+#endif
+#ifdef TABLE
+varying lowp vec2 tt;
+uniform sampler2D colortable;
+#endif
+
+void main() {
+#ifdef SPRITE
+ gl_FragColor = mix(texture2D(texture, fTexS.xy), texture2D(texture, fTexS.zw), tt.y)
+ * fColor
+ * texture2D(colortable, tt)
+ * qt_Opacity;
+#else
+#ifdef TABLE
+ gl_FragColor = texture2D(texture, fTex)
+ * fColor
+ * texture2D(colortable, tt)
+ * qt_Opacity;
+#else
+#ifdef DEFORM
+ gl_FragColor = (texture2D(texture, fTex)) * fColor * qt_Opacity;
+#else
+#ifdef COLOR
+ gl_FragColor = (texture2D(texture, gl_PointCoord)) * fColor * qt_Opacity;
+#else
+ gl_FragColor = texture2D(texture, gl_PointCoord) * (fFade * qt_Opacity);
+#endif //COLOR
+#endif //DEFORM
+#endif //TABLE
+#endif //SPRITE
+}
diff --git a/src/declarative/particles/defaultshaders/ultravertex.shader b/src/declarative/particles/defaultshaders/imagevertex.shader
index 65a1a3077a..e1033c9165 100644
--- a/src/declarative/particles/defaultshaders/ultravertex.shader
+++ b/src/declarative/particles/defaultshaders/imagevertex.shader
@@ -1,76 +1,97 @@
attribute highp vec2 vPos;
-attribute highp vec2 vTex;
attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize
attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration
+uniform highp float entry;
+#ifdef COLOR
attribute lowp vec4 vColor;
+#endif
+#ifdef DEFORM
+attribute highp vec2 vTex;
attribute highp vec4 vDeformVec; //x,y x unit vector; z,w = y unit vector
attribute highp vec3 vRotation; //x = radians of rotation, y=rotation speed, z= bool autoRotate
+#endif
+#ifdef SPRITE
attribute highp vec4 vAnimData;// idx, duration, frameCount (this anim), timestamp (this anim)
-
-uniform highp mat4 matrix;
-uniform highp float timestamp;
uniform highp float framecount; //maximum of all anims
uniform highp float animcount;
-uniform sampler2D sizetable;
+#endif
-varying lowp float tt;
-varying highp vec2 fTexA;
-varying highp vec2 fTexB;
-varying lowp float progress;
+uniform highp mat4 qt_Matrix;
+uniform highp float timestamp;
+#ifdef TABLE
+varying lowp vec2 tt;//y is progress if Sprite mode
+uniform highp float sizetable[64];
+uniform highp float opacitytable[64];
+#endif
+#ifdef SPRITE
+varying highp vec4 fTexS;
+#else
+#ifdef DEFORM
+varying highp vec2 fTex;
+#endif
+#endif
+#ifdef COLOR
varying lowp vec4 fColor;
+#else
+varying lowp float fFade;
+#endif
void main() {
- highp float size = vData.z;
- highp float endSize = vData.w;
highp float t = (timestamp - vData.x) / vData.y;
-
+ if (t < 0. || t > 1.){
+#ifdef DEFORM //Not point sprites
+ gl_Position = qt_Matrix * vec4(vPos.x, vPos.y, 0., 1.);
+#else
+ gl_PointSize = 0.;
+#endif
+ return;
+ }
+#ifdef SPRITE
//Calculate frame location in texture
highp float frameIndex = mod((((timestamp - vAnimData.w)*1000.)/vAnimData.y),vAnimData.z);
- progress = mod((timestamp - vAnimData.w)*1000., vAnimData.y) / vAnimData.y;
+ tt.y = mod((timestamp - vAnimData.w)*1000., vAnimData.y) / vAnimData.y;
frameIndex = floor(frameIndex);
- highp vec2 frameTex = vTex;
- if(vTex.x == 0.)
- frameTex.x = (frameIndex/framecount);
- else
- frameTex.x = 1. * ((frameIndex + 1.)/framecount);
-
- if(vTex.y == 0.)
- frameTex.y = (vAnimData.x/animcount);
- else
- frameTex.y = 1. * ((vAnimData.x + 1.)/animcount);
+ fTexS.xy = vec2(((frameIndex + vTex.x) / framecount), ((vAnimData.x + vTex.y) / animcount));
- fTexA = frameTex;
//Next frame is also passed, for interpolation
//### Should the next anim be precalculated to allow for interpolation there?
if(frameIndex != vAnimData.z - 1.)//Can't do it for the last frame though, this anim may not loop
frameIndex = mod(frameIndex+1., vAnimData.z);
-
- if(vTex.x == 0.)
- frameTex.x = (frameIndex/framecount);
- else
- frameTex.x = 1. * ((frameIndex + 1.)/framecount);
-
- if(vTex.y == 0.)
- frameTex.y = (vAnimData.x/animcount);
- else
- frameTex.y = 1. * ((vAnimData.x + 1.)/animcount);
- fTexB = frameTex;
-
- highp float currentSize = mix(size, endSize, t * t) * texture2D(sizetable, vec2(t,0.5)).w;
-
- if (t < 0. || t > 1.)
- currentSize = 0.;
+ fTexS.zw = vec2(((frameIndex + vTex.x) / framecount), ((vAnimData.x + vTex.y) / animcount));
+#else
+#ifdef DEFORM
+ fTex = vTex;
+#endif
+#endif
+ highp float currentSize = mix(vData.z, vData.w, t * t);
+ lowp float fade = 1.;
+ highp float fadeIn = min(t * 10., 1.);
+ highp float fadeOut = 1. - clamp((t - 0.75) * 4.,0., 1.);
+
+#ifdef TABLE
+ currentSize = currentSize * sizetable[int(floor(t*64.))];
+ fade = fade * opacitytable[int(floor(t*64.))];
+#endif
+ if (entry == 1.)
+ fade = fadeIn * fadeOut;
+ else if(entry == 2.)
+ currentSize = currentSize * fadeIn * fadeOut;
highp vec2 pos;
+#ifdef DEFORM
highp float rotation = vRotation.x + vRotation.y * t * vData.y;
if(vRotation.z == 1.0){
highp vec2 curVel = vVec.zw * t * vData.y + vVec.xy;
rotation += atan(curVel.y, curVel.x);
}
highp vec2 trigCalcs = vec2(cos(rotation), sin(rotation));
+ highp vec4 deform = vDeformVec * currentSize * (vTex.xxyy - 0.5);
+ highp vec4 rotatedDeform = deform.xxzz * trigCalcs.xyxy;
+ rotatedDeform = rotatedDeform + (deform.yyww * trigCalcs.yxyx * vec4(-1.,1.,-1.,1.));
+ /* The readable version:
highp vec2 xDeform = vDeformVec.xy * currentSize * (vTex.x-0.5);
highp vec2 yDeform = vDeformVec.zw * currentSize * (vTex.y-0.5);
highp vec2 xRotatedDeform;
@@ -79,16 +100,26 @@ void main() {
highp vec2 yRotatedDeform;
yRotatedDeform.x = trigCalcs.x*yDeform.x - trigCalcs.y*yDeform.y;
yRotatedDeform.y = trigCalcs.y*yDeform.x + trigCalcs.x*yDeform.y;
+ */
pos = vPos
- + xRotatedDeform
- + yRotatedDeform
- //- vec2(1,1) * currentSize * 0.5 // 'center'
+ + rotatedDeform.xy
+ + rotatedDeform.zw
+ vVec.xy * t * vData.y // apply speed
+ 0.5 * vVec.zw * pow(t * vData.y, 2.); // apply acceleration
-
- gl_Position = matrix * vec4(pos.x, pos.y, 0, 1);
-
- fColor = vColor;
- tt = t;
-
+#else
+ pos = vPos
+ + vVec.xy * t * vData.y // apply speed vector..
+ + 0.5 * vVec.zw * pow(t * vData.y, 2.);
+ gl_PointSize = currentSize;
+#endif
+ gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);
+
+#ifdef COLOR
+ fColor = vColor * fade;
+#else
+ fFade = fade;
+#endif
+#ifdef TABLE
+ tt.x = t;
+#endif
}
diff --git a/src/declarative/particles/defaultshaders/simplefragment.shader b/src/declarative/particles/defaultshaders/simplefragment.shader
index 494053e319..9b445da52f 100644
--- a/src/declarative/particles/defaultshaders/simplefragment.shader
+++ b/src/declarative/particles/defaultshaders/simplefragment.shader
@@ -1,8 +1,8 @@
uniform sampler2D texture;
+uniform lowp float qt_Opacity;
-varying highp vec2 fTex;
varying lowp float fFade;
void main() {
- gl_FragColor = (texture2D(texture, fTex)) * fFade;
+ gl_FragColor = texture2D(texture, gl_PointCoord) * (fFade * qt_Opacity);
}
diff --git a/src/declarative/particles/defaultshaders/simplevertex.shader b/src/declarative/particles/defaultshaders/simplevertex.shader
index f185ef0700..c287e159a5 100644
--- a/src/declarative/particles/defaultshaders/simplevertex.shader
+++ b/src/declarative/particles/defaultshaders/simplevertex.shader
@@ -1,36 +1,39 @@
attribute highp vec2 vPos;
-attribute highp vec2 vTex;
attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize
attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration
-uniform highp mat4 matrix;
+uniform highp mat4 qt_Matrix;
uniform highp float timestamp;
-uniform lowp float opacity;
+uniform highp float entry;
-varying highp vec2 fTex;
varying lowp float fFade;
void main() {
- fTex = vTex;
- highp float size = vData.z;
- highp float endSize = vData.w;
-
highp float t = (timestamp - vData.x) / vData.y;
- highp float currentSize = mix(size, endSize, t * t);
+ highp float currentSize = mix(vData.z, vData.w, t * t);
if (t < 0. || t > 1.)
currentSize = 0.;
+ fFade = 1.;
+
+ if (entry == 1.){
+ highp float fadeIn = min(t * 10., 1.);
+ highp float fadeOut = 1. - max(0., min((t - 0.75) * 4., 1.));
+ fFade = fadeIn * fadeOut;
+ }else if(entry == 2.){
+ highp float sizeIn = min(t * 10., 1.);
+ highp float sizeOut = 1. - max(0., min((t - 0.75) * 4., 1.));
+ currentSize = currentSize * sizeIn * sizeOut;
+ }
+
+ gl_PointSize = currentSize;
+
highp vec2 pos = vPos
- - currentSize / 2. + currentSize * vTex // adjust size
+ vVec.xy * t * vData.y // apply speed vector..
+ 0.5 * vVec.zw * pow(t * vData.y, 2.);
- gl_Position = matrix * vec4(pos.x, pos.y, 0, 1);
-
- highp float fadeIn = min(t * 10., 1.);
- highp float fadeOut = 1. - max(0., min((t - 0.75) * 4., 1.));
+ gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);
- fFade = fadeIn * fadeOut * opacity;
}
diff --git a/src/declarative/particles/defaultshaders/spritefragment.shader b/src/declarative/particles/defaultshaders/spritefragment.shader
index 4d89d69c6a..86002f03fb 100644
--- a/src/declarative/particles/defaultshaders/spritefragment.shader
+++ b/src/declarative/particles/defaultshaders/spritefragment.shader
@@ -1,10 +1,17 @@
uniform sampler2D texture;
+uniform sampler2D colortable;
+uniform sampler2D opacitytable;
+uniform lowp float qt_Opacity;
varying highp vec2 fTexA;
varying highp vec2 fTexB;
varying lowp float progress;
varying lowp vec4 fColor;
+varying lowp float tt;
void main() {
- gl_FragColor = mix(texture2D(texture, fTexA), texture2D(texture, fTexB), progress) * fColor.w;
+ gl_FragColor = mix(texture2D(texture, fTexA), texture2D(texture, fTexB), progress)
+ * fColor
+ * texture2D(colortable, vec2(tt, 0.5))
+ * (texture2D(opacitytable, vec2(tt, 0.5)).w * qt_Opacity);
}
diff --git a/src/declarative/particles/defaultshaders/spritevertex.shader b/src/declarative/particles/defaultshaders/spritevertex.shader
index 78b8e36b3b..96ce3454b8 100644
--- a/src/declarative/particles/defaultshaders/spritevertex.shader
+++ b/src/declarative/particles/defaultshaders/spritevertex.shader
@@ -1,26 +1,41 @@
attribute highp vec2 vPos;
-attribute highp vec2 vTex;
attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize
attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration
+#ifdef COLOR
+attribute lowp vec4 vColor;
+#endif
+#ifdef DEFORM
+attribute highp vec2 vTex;
+attribute highp vec4 vDeformVec; //x,y x unit vector; z,w = y unit vector
+attribute highp vec3 vRotation; //x = radians of rotation, y=rotation speed, z= bool autoRotate
+#endif
+#ifdef SPRITE
attribute highp vec4 vAnimData;// idx, duration, frameCount (this anim), timestamp (this anim)
-
-uniform highp mat4 matrix;
-uniform highp float timestamp;
-uniform lowp float opacity;
uniform highp float framecount; //maximum of all anims
uniform highp float animcount;
-
+#endif
+
+uniform highp mat4 qt_Matrix;
+uniform highp float timestamp;
+#ifdef TABLE
+varying lowp float tt;
+#endif
+#ifdef SPRITE
+varying lowp float progress;
varying highp vec2 fTexA;
varying highp vec2 fTexB;
-varying lowp float progress;
+#elseif DEFORM
+varying highp vec2 fTex;
+#endif
+#ifdef COLOR
varying lowp vec4 fColor;
+#endif
-void main() {
- highp float size = vData.z;
- highp float endSize = vData.w;
- highp float t = (timestamp - vData.x) / vData.y;
+void main() {
+ highp float t = (timestamp - vData.x) / vData.y;
+#ifdef SPRITE
//Calculate frame location in texture
highp float frameIndex = mod((((timestamp - vAnimData.w)*1000.)/vAnimData.y),vAnimData.z);
progress = mod((timestamp - vAnimData.w)*1000., vAnimData.y) / vAnimData.y;
@@ -53,25 +68,46 @@ void main() {
else
frameTex.y = 1. * ((vAnimData.x + 1.)/animcount);
fTexB = frameTex;
+#endif
- //Applying Size here seems to screw with RockingAffector?
- highp float currentSize = mix(size, endSize, t * t);
+ highp float currentSize = mix(vData.z, vData.w, t * t);
if (t < 0. || t > 1.)
currentSize = 0.;
- //If affector is mananging pos, they don't set speed?
- highp vec2 pos = vPos
- - currentSize / 2. + currentSize * vTex // adjust size
- + vVec.xy * t * vData.y // apply speed vector..
- + 0.5 * vVec.zw * pow(t * vData.y, 2.);
-
- gl_Position = matrix * vec4(pos.x, pos.y, 0, 1);
-
- // calculate opacity
- highp float fadeIn = min(t * 10., 1.);
- highp float fadeOut = 1. - max(0., min((t - 0.75) * 4., 1.));
-
- lowp vec4 white = vec4(1.);
- fColor = white * fadeIn * fadeOut * opacity;
+ highp vec2 pos;
+#ifdef DEFORM
+ highp float rotation = vRotation.x + vRotation.y * t * vData.y;
+ if(vRotation.z == 1.0){
+ highp vec2 curVel = vVec.zw * t * vData.y + vVec.xy;
+ rotation += atan(curVel.y, curVel.x);
+ }
+ highp vec2 trigCalcs = vec2(cos(rotation), sin(rotation));
+ highp vec2 xDeform = vDeformVec.xy * currentSize * (vTex.x-0.5);
+ highp vec2 yDeform = vDeformVec.zw * currentSize * (vTex.y-0.5);
+ highp vec2 xRotatedDeform;
+ xRotatedDeform.x = trigCalcs.x*xDeform.x - trigCalcs.y*xDeform.y;
+ xRotatedDeform.y = trigCalcs.y*xDeform.x + trigCalcs.x*xDeform.y;
+ highp vec2 yRotatedDeform;
+ yRotatedDeform.x = trigCalcs.x*yDeform.x - trigCalcs.y*yDeform.y;
+ yRotatedDeform.y = trigCalcs.y*yDeform.x + trigCalcs.x*yDeform.y;
+ pos = vPos
+ + xRotatedDeform
+ + yRotatedDeform
+ //- vec2(1,1) * currentSize * 0.5 // 'center'
+ + vVec.xy * t * vData.y // apply speed
+ + 0.5 * vVec.zw * pow(t * vData.y, 2.); // apply acceleration
+#else
+ pos = vPos
+ + vVec.xy * t * vData.y // apply speed vector..
+ + 0.5 * vVec.zw * pow(t * vData.y, 2.);
+#endif
+ gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);
+
+#ifdef COLOR
+ fColor = vColor;
+#endif
+#ifdef TABLE
+ tt = t;
+#endif
}
diff --git a/src/declarative/particles/defaultshaders/superfragment.shader b/src/declarative/particles/defaultshaders/superfragment.shader
deleted file mode 100644
index a17f5841ca..0000000000
--- a/src/declarative/particles/defaultshaders/superfragment.shader
+++ /dev/null
@@ -1,11 +0,0 @@
-uniform sampler2D texture;
-uniform sampler2D colortable;
-uniform sampler2D opacitytable;
-
-varying highp vec2 fTex;
-varying lowp vec4 fColor;
-varying lowp float tt;
-
-void main() {
- gl_FragColor = (texture2D(texture, fTex).w) * fColor * texture2D(colortable, vec2(tt, 0.5)) *( texture2D(opacitytable, vec2(tt, 0.5)).w);
-}
diff --git a/src/declarative/particles/defaultshaders/tabledfragment.shader b/src/declarative/particles/defaultshaders/tabledfragment.shader
new file mode 100644
index 0000000000..e92d8050eb
--- /dev/null
+++ b/src/declarative/particles/defaultshaders/tabledfragment.shader
@@ -0,0 +1,23 @@
+uniform sampler2D texture;
+uniform sampler2D colortable;
+uniform sampler2D opacitytable;
+uniform sampler2D sizetable;
+uniform lowp float qt_Opacity;
+
+varying highp vec2 fTex;
+varying lowp vec4 fColor;
+varying lowp float tt;
+
+void main() {
+ highp vec2 tex = (((fTex - 0.5) / texture2D(sizetable, vec2(tt, 0.5)).w) + 0.5);
+ lowp vec4 color;
+ if(tex.x < 1.0 && tex.x > 0.0 && tex.y < 1.0 && tex.y > 0.0){//No CLAMP_TO_BORDER in ES2, so have to do it ourselves
+ color = texture2D(texture, tex);
+ }else{
+ color = vec4(0.,0.,0.,0.);
+ }
+ gl_FragColor = color
+ * fColor
+ * texture2D(colortable, vec2(tt, 0.5))
+ * (texture2D(opacitytable, vec2(tt, 0.5)).w * qt_Opacity);
+}
diff --git a/src/declarative/particles/defaultshaders/supervertex.shader b/src/declarative/particles/defaultshaders/tabledvertex.shader
index 432a23ce05..ef3c35da82 100644
--- a/src/declarative/particles/defaultshaders/supervertex.shader
+++ b/src/declarative/particles/defaultshaders/tabledvertex.shader
@@ -6,14 +6,14 @@ attribute lowp vec4 vColor;
attribute highp vec4 vDeformVec; //x,y x unit vector; z,w = y unit vector
attribute highp vec3 vRotation; //x = radians of rotation, y=rotation speed, z= bool autoRotate
-uniform highp mat4 matrix;
+uniform highp mat4 qt_Matrix;
uniform highp float timestamp;
-uniform sampler2D sizetable;
-uniform sampler2D opacitytable;
+varying lowp float tt;
varying highp vec2 fTex;
+varying lowp float progress;
varying lowp vec4 fColor;
-varying lowp float tt;
+
void main() {
fTex = vTex;
@@ -22,8 +22,7 @@ void main() {
highp float t = (timestamp - vData.x) / vData.y;
- highp float currentSize = mix(size, endSize, t * t) * texture2D(sizetable, vec2(t,0.5)).w;
-
+ highp float currentSize = mix(size, endSize, t * t);
if (t < 0. || t > 1.)
currentSize = 0.;
@@ -49,7 +48,7 @@ void main() {
+ vVec.xy * t * vData.y // apply speed
+ 0.5 * vVec.zw * pow(t * vData.y, 2.); // apply acceleration
- gl_Position = matrix * vec4(pos.x, pos.y, 0, 1);
+ gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);
fColor = vColor;
tt = t;
diff --git a/src/declarative/particles/defaultshaders/trailsfragment.shader b/src/declarative/particles/defaultshaders/trailsfragment.shader
deleted file mode 100644
index d3db87fa30..0000000000
--- a/src/declarative/particles/defaultshaders/trailsfragment.shader
+++ /dev/null
@@ -1,8 +0,0 @@
-uniform sampler2D texture;
-
-varying highp vec2 fTex;
-varying lowp vec4 fColor;
-
-void main() {
- gl_FragColor = (texture2D(texture, fTex).w) * fColor;
-}
diff --git a/src/declarative/particles/defaultshaders/ultrafragment.shader b/src/declarative/particles/defaultshaders/ultrafragment.shader
deleted file mode 100644
index 0627d0f1e8..0000000000
--- a/src/declarative/particles/defaultshaders/ultrafragment.shader
+++ /dev/null
@@ -1,16 +0,0 @@
-uniform sampler2D texture;
-uniform sampler2D colortable;
-uniform sampler2D opacitytable;
-
-varying highp vec2 fTexA;
-varying highp vec2 fTexB;
-varying lowp float progress;
-varying lowp vec4 fColor;
-varying lowp float tt;
-
-void main() {
- gl_FragColor = mix(texture2D(texture, fTexA), texture2D(texture, fTexB), progress)
- * fColor
- * texture2D(colortable, vec2(tt, 0.5))
- *( texture2D(opacitytable, vec2(tt, 0.5)).w);
-}
diff --git a/src/declarative/particles/particles.pri b/src/declarative/particles/particles.pri
index 582e1d3f8c..9f63cd81b9 100644
--- a/src/declarative/particles/particles.pri
+++ b/src/declarative/particles/particles.pri
@@ -4,7 +4,6 @@ HEADERS += \
$$PWD/qsgangleddirection_p.h \
$$PWD/qsgcustomparticle_p.h \
$$PWD/qsgellipseextruder_p.h \
- $$PWD/qsgemitter_p.h \
$$PWD/qsgfollowemitter_p.h \
$$PWD/qsgfriction_p.h \
$$PWD/qsggravity_p.h \
@@ -29,15 +28,12 @@ HEADERS += \
$$PWD/qsgwander_p.h \
$$PWD/qsgtargetaffector_p.h \
$$PWD/qsgcumulativedirection_p.h \
- $$PWD/qsgcustomemitter_p.h \
- $$PWD/qsgcustomaffector_p.h \
$$PWD/qsgv8particledata_p.h
SOURCES += \
$$PWD/qsgangleddirection.cpp \
$$PWD/qsgcustomparticle.cpp \
$$PWD/qsgellipseextruder.cpp \
- $$PWD/qsgemitter.cpp \
$$PWD/qsgfollowemitter.cpp \
$$PWD/qsgfriction.cpp \
$$PWD/qsggravity.cpp \
@@ -62,8 +58,6 @@ SOURCES += \
$$PWD/qsgwander.cpp \
$$PWD/qsgtargetaffector.cpp \
$$PWD/qsgcumulativedirection.cpp \
- $$PWD/qsgcustomemitter.cpp \
- $$PWD/qsgcustomaffector.cpp \
$$PWD/qsgv8particledata.cpp
RESOURCES += \
diff --git a/src/declarative/particles/particles.qrc b/src/declarative/particles/particles.qrc
index 85931ec9ce..5403f55266 100644
--- a/src/declarative/particles/particles.qrc
+++ b/src/declarative/particles/particles.qrc
@@ -1,22 +1,10 @@
<RCC>
<qresource prefix="/">
- <file>defaultshaders/spritefragment.shader</file>
- <file>defaultshaders/spritevertex.shader</file>
- <file>defaultshaders/ctfragment.shader</file>
- <file>defaultshaders/ctvertex.shader</file>
- <file>defaultshaders/trailsfragment.shader</file>
- <file>defaultshaders/trailsvertex.shader</file>
+ <file>defaultshaders/imagefragment.shader</file>
+ <file>defaultshaders/imagevertex.shader</file>
<file>defaultshaders/spriteimagefragment.shader</file>
<file>defaultshaders/spriteimagevertex.shader</file>
<file>defaultshaders/identitytable.png</file>
<file>defaultshaders/defaultFadeInOut.png</file>
- <file>defaultshaders/deformablefragment.shader</file>
- <file>defaultshaders/deformablevertex.shader</file>
- <file>defaultshaders/ultravertex.shader</file>
- <file>defaultshaders/ultrafragment.shader</file>
- <file>defaultshaders/supervertex.shader</file>
- <file>defaultshaders/superfragment.shader</file>
- <file>defaultshaders/simplevertex.shader</file>
- <file>defaultshaders/simplefragment.shader</file>
</qresource>
</RCC>
diff --git a/src/declarative/particles/qsgangleddirection.cpp b/src/declarative/particles/qsgangleddirection.cpp
index ffd434f980..ab39b8a575 100644
--- a/src/declarative/particles/qsgangleddirection.cpp
+++ b/src/declarative/particles/qsgangleddirection.cpp
@@ -46,7 +46,6 @@ const qreal CONV = 0.017453292519943295;
/*!
\qmlclass AngledDirection QSGAngledDirection
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits StochasticDirection
\brief The AngledDirection element allows you to specify a direction that varies in angle
diff --git a/src/declarative/particles/qsgcumulativedirection.cpp b/src/declarative/particles/qsgcumulativedirection.cpp
index 5ffdef6327..1d7523972b 100644
--- a/src/declarative/particles/qsgcumulativedirection.cpp
+++ b/src/declarative/particles/qsgcumulativedirection.cpp
@@ -45,7 +45,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass CumulativeDirection QSGCumulativeDirection
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits StochasticDirection
\brief The CumulativeDirection element allows you to specify a direction made of other directions
diff --git a/src/declarative/particles/qsgcustomaffector.cpp b/src/declarative/particles/qsgcustomaffector.cpp
deleted file mode 100644
index 9832399661..0000000000
--- a/src/declarative/particles/qsgcustomaffector.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qsgcustomaffector_p.h"
-QT_BEGIN_NAMESPACE
-/*!
- \qmlclass CustomAffector QSGCustomAffector
- \inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
- \inherits Affector
- \brief The Custom affector allows you to modify affected particles
-
-*/
-
-//TODO: Document particle 'type'
-/*!
- \qmlsignal Timer::affecting(particle, dt)
-
- This handler is called when a particle is selected to be affected.
-
- dt is the time since the last time it was affected. Use dt to normalize
- trajectory manipulations to real time.
-*/
-QSGCustomAffector::QSGCustomAffector(QSGItem *parent) :
- QSGParticleAffector(parent)
-{
-}
-
-
-bool QSGCustomAffector::affectParticle(QSGParticleData *d, qreal dt)
-{
- emit affectParticle(d->v8Value(), dt);
- return true;//TODO: Work it out (best added alongside autoTimeScaling)
-}
-QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgcustomemitter.cpp b/src/declarative/particles/qsgcustomemitter.cpp
deleted file mode 100644
index 0500e0c75e..0000000000
--- a/src/declarative/particles/qsgcustomemitter.cpp
+++ /dev/null
@@ -1,189 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qsgcustomemitter_p.h"
-#include "qsgparticlesystem_p.h"
-QT_BEGIN_NAMESPACE
-/*!
- \qmlclass CustomEmitter QSGCustomEmitter
- \inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
- \inherits Emitter
- \brief The Custom emitter allows you to modify particles as they are emitted
-
-*/
-
-//TODO: Document particle 'type'
-/*!
- \qmlsignal CustomEmitter::emitting(particle)
-
- This handler is called when a particle is emitted. You can modify particle
- attributes from within the handler.
-*/
-
-QSGCustomEmitter::QSGCustomEmitter(QSGItem* parent)
- : QSGParticleEmitter(parent)
- , m_particle_count(0)
- , m_reset_last(true)
- , m_last_timestamp(0)
- , m_last_emission(0)
-{
-}
-
-void QSGCustomEmitter::reset()
-{
- m_reset_last = true;
-}
-
-void QSGCustomEmitter::emitWindow(int timeStamp)
-{
- if (m_system == 0)
- return;
- if ((!m_emitting || !m_particlesPerSecond)&& !m_burstLeft && m_burstQueue.isEmpty()){
- m_reset_last = true;
- return;
- }
-
- if (m_reset_last) {
- m_last_emitter = m_last_last_emitter = QPointF(x(), y());
- m_last_timestamp = timeStamp/1000.;
- m_last_emission = m_last_timestamp;
- m_reset_last = false;
- }
-
- if (m_burstLeft){
- m_burstLeft -= timeStamp - m_last_timestamp * 1000.;
- if (m_burstLeft < 0){
- if (!m_emitting)
- timeStamp += m_burstLeft;
- m_burstLeft = 0;
- }
- }
-
- qreal time = timeStamp / 1000.;
-
- qreal particleRatio = 1. / m_particlesPerSecond;
- qreal pt = m_last_emission;
-
- qreal opt = pt; // original particle time
- qreal dt = time - m_last_timestamp; // timestamp delta...
- if (!dt)
- dt = 0.000001;
-
- // emitter difference since last...
- qreal dex = (x() - m_last_emitter.x());
- qreal dey = (y() - m_last_emitter.y());
-
- qreal sizeAtEnd = m_particleEndSize >= 0 ? m_particleEndSize : m_particleSize;
- qreal emitter_x_offset = m_last_emitter.x() - x();
- qreal emitter_y_offset = m_last_emitter.y() - y();
- if (!m_burstQueue.isEmpty() && !m_burstLeft && !m_emitting)//'outside time' emissions only
- pt = time;
- while (pt < time || !m_burstQueue.isEmpty()) {
- //int pos = m_last_particle % m_particle_count;
- QSGParticleData* datum = m_system->newDatum(m_system->m_groupIds[m_particle]);
- if (datum){//actually emit(otherwise we've been asked to skip this one)
- datum->e = this;//###useful?
- qreal t = 1 - (pt - opt) / dt;
-
-
- // Particle timestamp
- datum->t = pt;
- datum->lifeSpan = //TODO:Promote to base class?
- (m_particleDuration
- + ((rand() % ((m_particleDurationVariation*2) + 1)) - m_particleDurationVariation))
- / 1000.0;
-
- // Particle position
- QRectF boundsRect;
- if (!m_burstQueue.isEmpty()){
- boundsRect = QRectF(m_burstQueue.first().second.x() - x(), m_burstQueue.first().second.y() - y(),
- width(), height());
- } else {
- boundsRect = QRectF(emitter_x_offset + dex * (pt - opt) / dt, emitter_y_offset + dey * (pt - opt) / dt
- , width(), height());
- }
- QPointF newPos = effectiveExtruder()->extrude(boundsRect);
- datum->x = newPos.x();
- datum->y = newPos.y();
-
- // Particle speed
- const QPointF &speed = m_speed->sample(newPos);
- datum->vx = speed.x();
- datum->vy = speed.y();
-
- // Particle acceleration
- const QPointF &accel = m_acceleration->sample(newPos);
- datum->ax = accel.x();
- datum->ay = accel.y();
-
- // Particle size
- float sizeVariation = -m_particleSizeVariation
- + rand() / float(RAND_MAX) * m_particleSizeVariation * 2;
-
- float size = qMax((qreal)0.0 , m_particleSize + sizeVariation);
- float endSize = qMax((qreal)0.0 , sizeAtEnd + sizeVariation);
-
- datum->size = size;
- datum->endSize = endSize;
-
- emitParticle(datum->v8Value());//A chance for arbitrary JS changes
-
- m_system->emitParticle(datum);
- }
- if (m_burstQueue.isEmpty()){
- pt += particleRatio;
- }else{
- m_burstQueue.first().first--;
- if (m_burstQueue.first().first <= 0)
- m_burstQueue.pop_front();
- }
- }
- m_last_emission = pt;
-
- m_last_last_last_emitter = m_last_last_emitter;
- m_last_last_emitter = m_last_emitter;
- m_last_emitter = QPointF(x(), y());
- m_last_timestamp = time;
-}
-
-
-QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgcustomemitter_p.h b/src/declarative/particles/qsgcustomemitter_p.h
deleted file mode 100644
index 4d22490fb6..0000000000
--- a/src/declarative/particles/qsgcustomemitter_p.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSGCUSTOMEMITTER_H
-#define QSGCUSTOMEMITTER_H
-#include "qsgparticleemitter_p.h"
-#include <private/qv8engine_p.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QSGCustomEmitter : public QSGParticleEmitter
-{
- Q_OBJECT
-public:
- explicit QSGCustomEmitter(QSGItem* parent=0);
- virtual ~QSGCustomEmitter(){}
- virtual void emitWindow(int timeStamp);
- virtual void reset();
-Q_SIGNALS:
- void emitParticle(QDeclarativeV8Handle particle);
-private:
- int m_particle_count;
- bool m_reset_last;
- qreal m_last_timestamp;
- qreal m_last_emission;
-
- QPointF m_last_emitter;
- QPointF m_last_last_emitter;
- QPointF m_last_last_last_emitter;
-};
-
-QT_END_NAMESPACE
-QT_END_HEADER
-#endif // QSGCUSTOMEMITTER_H
diff --git a/src/declarative/particles/qsgcustomparticle.cpp b/src/declarative/particles/qsgcustomparticle.cpp
index 53cb131bc5..db544d20e8 100644
--- a/src/declarative/particles/qsgcustomparticle.cpp
+++ b/src/declarative/particles/qsgcustomparticle.cpp
@@ -122,7 +122,6 @@ struct PlainVertices {
/*!
\qmlclass CustomParticle QSGCustomParticle
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits ParticlePainter
\brief The CustomParticle element allows you to specify your own shader to paint particles.
@@ -420,10 +419,12 @@ void QSGCustomParticle::prepareNextFrame(){
QSGShaderEffectNode* QSGCustomParticle::buildCustomNodes()
{
+#ifdef QT_OPENGL_ES_2
if (m_count * 4 > 0xffff) {
- printf("CustomParticle: Too many particles... \n");//####Why is this here?
+ printf("CustomParticle: Too many particles... \n");
return 0;
}
+#endif
if (m_count <= 0) {
printf("CustomParticle: Too few particles... \n");
diff --git a/src/declarative/particles/qsgellipseextruder.cpp b/src/declarative/particles/qsgellipseextruder.cpp
index 59e8803b28..29fa3c8841 100644
--- a/src/declarative/particles/qsgellipseextruder.cpp
+++ b/src/declarative/particles/qsgellipseextruder.cpp
@@ -45,7 +45,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass EllipseShape QSGEllipseExtruder
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits Shape
\brief The EllipseShape represents an ellipse to other particle system elements
diff --git a/src/declarative/particles/qsgemitter.cpp b/src/declarative/particles/qsgemitter.cpp
deleted file mode 100644
index 10d59dfaf8..0000000000
--- a/src/declarative/particles/qsgemitter.cpp
+++ /dev/null
@@ -1,262 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qsgemitter_p.h"
-#include "qsgparticlesystem_p.h"
-QT_BEGIN_NAMESPACE
-
-/*!
- \qmlclass Emitter QSGBasicEmitter
- \inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
- \brief The Emitter element allows you to emit logical particles.
-
- This element emits logical particles into the ParticleSystem, with the
- given starting attributes.
-
- Note that logical particles are not
- automatically rendered, you will need to have one or more
- ParticlePainter elements visualizing them.
-
- Note that the given starting attributes can be modified at any point
- in the particle's lifetime by any Affector element in the same
- ParticleSystem. This includes attributes like lifespan.
-*/
-
-QSGBasicEmitter::QSGBasicEmitter(QSGItem* parent)
- : QSGParticleEmitter(parent)
- , m_speed_from_movement(0)
- , m_particle_count(0)
- , m_reset_last(true)
- , m_last_timestamp(0)
- , m_last_emission(0)
-{
-// setFlag(ItemHasContents);
-}
-
-/*!
- \qmlproperty ParticleSystem QtQuick.Particles2::Emitter::system
-
- This is the Particle system that the Emitter will emit into.
- This can be omitted if the Emitter is a direct child of the ParticleSystem
-*/
-/*!
- \qmlproperty string QtQuick.Particles2::Emitter::particle
-*/
-/*!
- \qmlproperty Shape QtQuick.Particles2::Emitter::shape
-*/
-/*!
- \qmlproperty bool QtQuick.Particles2::Emitter::emitting
-*/
-/*!
- \qmlproperty real QtQuick.Particles2::Emitter::emitRate
-*/
-/*!
- \qmlproperty int QtQuick.Particles2::Emitter::lifeSpan
-*/
-/*!
- \qmlproperty int QtQuick.Particles2::Emitter::lifeSpanVariation
-*/
-/*!
- \qmlproperty int QtQuick.Particles2::Emitter::emitCap
-*/
-/*!
- \qmlproperty real QtQuick.Particles2::Emitter::size
-*/
-/*!
- \qmlproperty real QtQuick.Particles2::Emitter::endSize
-*/
-/*!
- \qmlproperty real QtQuick.Particles2::Emitter::sizeVariation
-*/
-/*!
- \qmlproperty StochasticDirection QtQuick.Particles2::Emitter::speed
-*/
-/*!
- \qmlproperty StochasticDirection QtQuick.Particles2::Emitter::acceleration
-*/
-/*!
- \qmlproperty qreal QtQuick.Particles2::Emitter::speedFromMovement
-*/
-
-void QSGBasicEmitter::setSpeedFromMovement(qreal t)
-{
- if (t == m_speed_from_movement)
- return;
- m_speed_from_movement = t;
- emit speedFromMovementChanged();
-}
-
-void QSGBasicEmitter::reset()
-{
- m_reset_last = true;
-}
-
-void QSGBasicEmitter::emitWindow(int timeStamp)
-{
- if (m_system == 0)
- return;
- if ((!m_emitting || !m_particlesPerSecond)&& !m_burstLeft && m_burstQueue.isEmpty()){
- m_reset_last = true;
- return;
- }
-
- if (m_reset_last) {
- m_last_emitter = m_last_last_emitter = QPointF(x(), y());
- m_last_timestamp = timeStamp/1000.;
- m_last_emission = m_last_timestamp;
- m_reset_last = false;
- }
-
- if (m_burstLeft){
- m_burstLeft -= timeStamp - m_last_timestamp * 1000.;
- if (m_burstLeft < 0){
- if (!m_emitting)
- timeStamp += m_burstLeft;
- m_burstLeft = 0;
- }
- }
-
- qreal time = timeStamp / 1000.;
-
- qreal particleRatio = 1. / m_particlesPerSecond;
- qreal pt = m_last_emission;
-
- qreal opt = pt; // original particle time
- qreal dt = time - m_last_timestamp; // timestamp delta...
- if (!dt)
- dt = 0.000001;
-
- // emitter difference since last...
- qreal dex = (x() - m_last_emitter.x());
- qreal dey = (y() - m_last_emitter.y());
-
- qreal ax = (m_last_last_emitter.x() + m_last_emitter.x()) / 2;
- qreal bx = m_last_emitter.x();
- qreal cx = (x() + m_last_emitter.x()) / 2;
- qreal ay = (m_last_last_emitter.y() + m_last_emitter.y()) / 2;
- qreal by = m_last_emitter.y();
- qreal cy = (y() + m_last_emitter.y()) / 2;
-
- qreal sizeAtEnd = m_particleEndSize >= 0 ? m_particleEndSize : m_particleSize;
- qreal emitter_x_offset = m_last_emitter.x() - x();
- qreal emitter_y_offset = m_last_emitter.y() - y();
- if (!m_burstQueue.isEmpty() && !m_burstLeft && !m_emitting)//'outside time' emissions only
- pt = time;
- while (pt < time || !m_burstQueue.isEmpty()) {
- //int pos = m_last_particle % m_particle_count;
- QSGParticleData* datum = m_system->newDatum(m_system->m_groupIds[m_particle]);
- if (datum){//actually emit(otherwise we've been asked to skip this one)
- datum->e = this;//###useful?
- qreal t = 1 - (pt - opt) / dt;
- qreal vx =
- - 2 * ax * (1 - t)
- + 2 * bx * (1 - 2 * t)
- + 2 * cx * t;
- qreal vy =
- - 2 * ay * (1 - t)
- + 2 * by * (1 - 2 * t)
- + 2 * cy * t;
-
-
- // Particle timestamp
- datum->t = pt;
- datum->lifeSpan = //TODO:Promote to base class?
- (m_particleDuration
- + ((rand() % ((m_particleDurationVariation*2) + 1)) - m_particleDurationVariation))
- / 1000.0;
-
- // Particle position
- QRectF boundsRect;
- if (!m_burstQueue.isEmpty()){
- boundsRect = QRectF(m_burstQueue.first().second.x() - x(), m_burstQueue.first().second.y() - y(),
- width(), height());
- } else {
- boundsRect = QRectF(emitter_x_offset + dex * (pt - opt) / dt, emitter_y_offset + dey * (pt - opt) / dt
- , width(), height());
- }
- QPointF newPos = effectiveExtruder()->extrude(boundsRect);
- datum->x = newPos.x();
- datum->y = newPos.y();
-
- // Particle speed
- const QPointF &speed = m_speed->sample(newPos);
- datum->vx = speed.x()
- + m_speed_from_movement * vx;
- datum->vy = speed.y()
- + m_speed_from_movement * vy;
-
- // Particle acceleration
- const QPointF &accel = m_acceleration->sample(newPos);
- datum->ax = accel.x();
- datum->ay = accel.y();
-
- // Particle size
- float sizeVariation = -m_particleSizeVariation
- + rand() / float(RAND_MAX) * m_particleSizeVariation * 2;
-
- float size = qMax((qreal)0.0 , m_particleSize + sizeVariation);
- float endSize = qMax((qreal)0.0 , sizeAtEnd + sizeVariation);
-
- datum->size = size;// * float(m_emitting);
- datum->endSize = endSize;// * float(m_emitting);
-
- m_system->emitParticle(datum);
- }
- if (m_burstQueue.isEmpty()){
- pt += particleRatio;
- }else{
- m_burstQueue.first().first--;
- if (m_burstQueue.first().first <= 0)
- m_burstQueue.pop_front();
- }
- }
- m_last_emission = pt;
-
- m_last_last_last_emitter = m_last_last_emitter;
- m_last_last_emitter = m_last_emitter;
- m_last_emitter = QPointF(x(), y());
- m_last_timestamp = time;
-}
-
-
-QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgemitter_p.h b/src/declarative/particles/qsgemitter_p.h
deleted file mode 100644
index f61da15012..0000000000
--- a/src/declarative/particles/qsgemitter_p.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef TRAILSEMITTER_H
-#define TRAILSEMITTER_H
-
-#include <QtCore>//FIXME
-#include <QtGui>
-
-#include "qsgparticleemitter_p.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-
-class QSGGeometryNode;
-
-class QSGBasicEmitter : public QSGParticleEmitter
-{
- Q_OBJECT
-
- Q_PROPERTY(qreal speedFromMovement READ speedFromMovement WRITE setSpeedFromMovement NOTIFY speedFromMovementChanged)
-
-public:
- explicit QSGBasicEmitter(QSGItem* parent=0);
- virtual ~QSGBasicEmitter(){}
- virtual void emitWindow(int timeStamp);
-
-
- qreal speedFromMovement() const { return m_speed_from_movement; }
- void setSpeedFromMovement(qreal s);
-
- qreal renderOpacity() const { return m_render_opacity; }
-
-signals:
-
- void speedFromMovementChanged();
-
-public slots:
-public:
- virtual void reset();
-protected:
-
-private:
-
- qreal m_speed_from_movement;
-
- // derived values...
- int m_particle_count;
- bool m_reset_last;
- qreal m_last_timestamp;
- qreal m_last_emission;
-
- QPointF m_last_emitter;
- QPointF m_last_last_emitter;
- QPointF m_last_last_last_emitter;
-
- qreal m_render_opacity;
-};
-
-QT_END_NAMESPACE
-QT_END_HEADER
-#endif // TRAILSEMITTER_H
diff --git a/src/declarative/particles/qsgfollowemitter.cpp b/src/declarative/particles/qsgfollowemitter.cpp
index 0d4e7f73fd..68f0f6bf75 100644
--- a/src/declarative/particles/qsgfollowemitter.cpp
+++ b/src/declarative/particles/qsgfollowemitter.cpp
@@ -45,21 +45,13 @@
QT_BEGIN_NAMESPACE
/*!
- \qmlclass Emitter QSGBasicEmitter
+ \qmlclass FollowEmitter QSGFollowEmitter
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
- \brief The Emitter element allows you to emit logical particles.
+ \inherits QSGParticleEmitter
+ \brief The FollowEmitter element allows you to emit logical particles from other logical particles.
This element emits logical particles into the ParticleSystem, with the
- given starting attributes.
-
- Note that logical particles are not
- automatically rendered, you will need to have one or more
- ParticlePainter elements visualizing them.
-
- Note that the given starting attributes can be modified at any point
- in the particle's lifetime by any Affector element in the same
- ParticleSystem. This includes attributes like lifespan.
+ starting positions based on those of other logical particles.
*/
QSGFollowEmitter::QSGFollowEmitter(QSGItem *parent) :
QSGParticleEmitter(parent)
@@ -80,24 +72,17 @@ QSGFollowEmitter::QSGFollowEmitter(QSGItem *parent) :
this, SLOT(recalcParticlesPerSecond()));
}
-
-/*!
- \qmlproperty ParticleSystem QtQuick.Particles2::FollowEmitter::system
-
- This is the Particle system that the FollowEmitter will emit into.
- This can be omitted if the FollowEmitter is a direct child of the ParticleSystem
-*/
-/*!
- \qmlproperty string QtQuick.Particles2::FollowEmitter::particle
-*/
/*!
\qmlproperty string QtQuick.Particles2::FollowEmitter::follow
+
+ The type of logical particle which this is emitting from.
*/
-/*!
- \qmlproperty Shape QtQuick.Particles2::FollowEmitter::shape
-*/
+
/*!
\qmlproperty Shape QtQuick.Particles2::FollowEmitter::emitShape
+
+ As the area of a FollowEmitter is the area it follows, a separate shape can be provided
+ to be the shape it emits out of.
*/
/*!
\qmlproperty real QtQuick.Particles2::FollowEmitter::emitWidth
@@ -106,39 +91,24 @@ QSGFollowEmitter::QSGFollowEmitter(QSGItem *parent) :
\qmlproperty real QtQuick.Particles2::FollowEmitter::emitHeight
*/
/*!
- \qmlproperty bool QtQuick.Particles2::FollowEmitter::emitting
-*/
-/*!
\qmlproperty real QtQuick.Particles2::FollowEmitter::emitRatePerParticle
*/
/*!
- \qmlproperty int QtQuick.Particles2::FollowEmitter::lifeSpan
-*/
-/*!
- \qmlproperty int QtQuick.Particles2::FollowEmitter::lifeSpanVariation
-*/
-/*!
- \qmlproperty int QtQuick.Particles2::FollowEmitter::emitCap
-*/
-/*!
- \qmlproperty real QtQuick.Particles2::FollowEmitter::size
-*/
-/*!
- \qmlproperty real QtQuick.Particles2::FollowEmitter::endSize
-*/
-/*!
- \qmlproperty real QtQuick.Particles2::FollowEmitter::sizeVariation
-*/
-/*!
- \qmlproperty StochasticDirection QtQuick.Particles2::FollowEmitter::speed
-*/
-/*!
- \qmlproperty StochasticDirection QtQuick.Particles2::FollowEmitter::acceleration
-*/
-/*!
- \qmlproperty qreal QtQuick.Particles2::FollowEmitter::speedFromMovement
+ \qmlsignal QtQuick.Particles2::FollowEmitter::emitFollowParticle(particle, followed)
+
+ This handler is called when a particle is emitted. You can modify particle
+ attributes from within the handler. followed is the particle that this is being
+ emitted off of.
+
+ If you use this signal handler, emitParticle will not be emitted.
*/
+bool QSGFollowEmitter::isEmitFollowConnected()
+{
+ static int idx = QObjectPrivate::get(this)->signalIndex("emitFollowParticle(QDeclarativeV8Handle,QDeclarativeV8Handle)");
+ return QObjectPrivate::get(this)->isSignalConnected(idx);
+}
+
void QSGFollowEmitter::recalcParticlesPerSecond(){
if (!m_system)
return;
@@ -178,6 +148,7 @@ void QSGFollowEmitter::emitWindow(int timeStamp)
}
}
+ //TODO: Implement startTime and speedFromMovement
qreal time = timeStamp / 1000.;
qreal particleRatio = 1. / m_particlesPerParticlePerSecond;
qreal pt;
@@ -202,7 +173,7 @@ void QSGFollowEmitter::emitWindow(int timeStamp)
continue;
}
while (pt < time || !m_burstQueue.isEmpty()){
- QSGParticleData* datum = m_system->newDatum(gId2);
+ QSGParticleData* datum = m_system->newDatum(gId2, !m_overwrite);
if (datum){//else, skip this emission
datum->e = this;//###useful?
@@ -236,8 +207,10 @@ void QSGFollowEmitter::emitWindow(int timeStamp)
// Particle speed
const QPointF &speed = m_speed->sample(newPos);
- datum->vx = speed.x();
+ datum->vx = speed.x()
+ + m_speed_from_movement * d->vx;
datum->vy = speed.y();
+ + m_speed_from_movement * d->vy;
// Particle acceleration
const QPointF &accel = m_acceleration->sample(newPos);
@@ -254,6 +227,11 @@ void QSGFollowEmitter::emitWindow(int timeStamp)
datum->size = size * float(m_emitting);
datum->endSize = endSize * float(m_emitting);
+ if (isEmitFollowConnected())
+ emitFollowParticle(datum->v8Value(), d->v8Value());//A chance for many arbitrary JS changes
+ else if (isEmitConnected())
+ emitParticle(datum->v8Value());//A chance for arbitrary JS changes
+
m_system->emitParticle(datum);
}
if (!m_burstQueue.isEmpty()){
diff --git a/src/declarative/particles/qsgfollowemitter_p.h b/src/declarative/particles/qsgfollowemitter_p.h
index 3fd5f1c2f8..d26435df6a 100644
--- a/src/declarative/particles/qsgfollowemitter_p.h
+++ b/src/declarative/particles/qsgfollowemitter_p.h
@@ -95,6 +95,7 @@ public:
}
signals:
+ void emitFollowParticle(QDeclarativeV8Handle particle, QDeclarativeV8Handle followed);
void particlesPerParticlePerSecondChanged(int arg);
@@ -161,6 +162,7 @@ private:
int m_followCount;
QSGParticleExtruder* m_emissionExtruder;
QSGParticleExtruder* m_defaultEmissionExtruder;
+ bool isEmitFollowConnected();
};
QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgfriction.cpp b/src/declarative/particles/qsgfriction.cpp
index e6a43013e8..6baeaf6c3b 100644
--- a/src/declarative/particles/qsgfriction.cpp
+++ b/src/declarative/particles/qsgfriction.cpp
@@ -44,7 +44,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass Friction QSGFrictionAffector
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits Affector
\brief The Friction affector slows down movement proportional to the particle's current speed.
diff --git a/src/declarative/particles/qsggravity.cpp b/src/declarative/particles/qsggravity.cpp
index 1639588917..1de2a0e014 100644
--- a/src/declarative/particles/qsggravity.cpp
+++ b/src/declarative/particles/qsggravity.cpp
@@ -46,7 +46,6 @@ const qreal CONV = 0.017453292520444443;
/*!
\qmlclass Gravity QSGGravityAffector
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits Affector
\brief The Gravity element allows you to set a constant accleration in an angle
diff --git a/src/declarative/particles/qsgimageparticle.cpp b/src/declarative/particles/qsgimageparticle.cpp
index cf1f48e036..57461a414b 100644
--- a/src/declarative/particles/qsgimageparticle.cpp
+++ b/src/declarative/particles/qsgimageparticle.cpp
@@ -54,238 +54,395 @@
QT_BEGIN_NAMESPACE
+//###Switch to define later, for now user-friendly (no compilation) debugging is worth it
+DEFINE_BOOL_CONFIG_OPTION(qmlParticlesDebug, QML_PARTICLES_DEBUG)
+
+#ifdef Q_WS_MAC
+#define SHADER_DEFINES "#version 120\n"
+#else
+#define SHADER_DEFINES ""
+#endif
+
+//TODO: Make it larger on desktop? Requires fixing up shader code with the same define
+#define UNIFORM_ARRAY_SIZE 64
+
const float CONV = 0.017453292519943295;
-class UltraMaterial : public QSGMaterial
+class ImageMaterialData
{
-public:
- UltraMaterial(bool withSprites=false)
- : texture(0)
- , colortable(0)
- , sizetable(0)
- , opacitytable(0)
- , timestamp(0)
- , framecount(1)
- , animcount(1)
- , usesSprites(withSprites)
- {
- setFlag(Blending, true);
- }
+ public:
+ ImageMaterialData()
+ : texture(0), colorTable(0)
+ {}
- ~UltraMaterial()
- {
+ ~ImageMaterialData(){
delete texture;
- delete colortable;
- delete sizetable;
- delete opacitytable;
- }
-
- virtual QSGMaterialType *type() const { static QSGMaterialType type; return &type; }
- virtual QSGMaterialShader *createShader() const;
- virtual int compare(const QSGMaterial *other) const
- {
- return this - static_cast<const UltraMaterial *>(other);
+ delete colorTable;
}
QSGTexture *texture;
- QSGTexture *colortable;
- QSGTexture *sizetable;
- QSGTexture *opacitytable;
+ QSGTexture *colorTable;
+ float sizeTable[UNIFORM_ARRAY_SIZE];
+ float opacityTable[UNIFORM_ARRAY_SIZE];
qreal timestamp;
- int framecount;
- int animcount;
- bool usesSprites;
+ qreal entry;
+ qreal framecount;
+ qreal animcount;
};
-class UltraMaterialData : public QSGMaterialShader
+
+//TODO: Move shaders inline once they've stablilized
+class TabledMaterialData : public ImageMaterialData {};
+class TabledMaterial : public QSGSimpleMaterialShader<TabledMaterialData>
{
+ QSG_DECLARE_SIMPLE_SHADER(TabledMaterial, TabledMaterialData)
+
public:
- UltraMaterialData(const char *vertexFile = 0, const char *fragmentFile = 0)
+ TabledMaterial()
{
- QFile vf(vertexFile ? vertexFile : ":defaultshaders/ultravertex.shader");
+ QFile vf(":defaultshaders/imagevertex.shader");
vf.open(QFile::ReadOnly);
- m_vertex_code = vf.readAll();
+ m_vertex_code = QByteArray(SHADER_DEFINES)
+ + QByteArray("#define TABLE\n#define DEFORM\n#define COLOR\n")
+ + vf.readAll();
- QFile ff(fragmentFile ? fragmentFile : ":defaultshaders/ultrafragment.shader");
+ QFile ff(":defaultshaders/imagefragment.shader");
ff.open(QFile::ReadOnly);
- m_fragment_code = ff.readAll();
+ m_fragment_code = QByteArray(SHADER_DEFINES)
+ + QByteArray("#define TABLE\n#define DEFORM\n#define COLOR\n")
+ + ff.readAll();
Q_ASSERT(!m_vertex_code.isNull());
Q_ASSERT(!m_fragment_code.isNull());
}
- void deactivate() {
- QSGMaterialShader::deactivate();
+ const char *vertexShader() const { return m_vertex_code.constData(); }
+ const char *fragmentShader() const { return m_fragment_code.constData(); }
- for (int i=0; i<8; ++i) {
- program()->setAttributeArray(i, GL_FLOAT, chunkOfBytes, 1, 0);
- }
+ QList<QByteArray> attributes() const {
+ return QList<QByteArray>() << "vPos" << "vTex" << "vData" << "vVec"
+ << "vColor" << "vDeformVec" << "vRotation";
+ };
+
+ void initialize() {
+ QSGSimpleMaterialShader<TabledMaterialData>::initialize();
+ program()->bind();
+ program()->setUniformValue("texture", 0);
+ program()->setUniformValue("colortable", 1);
+ glFuncs = QGLContext::currentContext()->functions();
+ m_timestamp_id = program()->uniformLocation("timestamp");
+ m_entry_id = program()->uniformLocation("entry");
+ m_sizetable_id = program()->uniformLocation("sizetable");
+ m_opacitytable_id = program()->uniformLocation("opacitytable");
+ }
+
+ void updateState(const TabledMaterialData* d, const TabledMaterialData*) {
+ glFuncs->glActiveTexture(GL_TEXTURE1);
+ d->colorTable->bind();
+
+ glFuncs->glActiveTexture(GL_TEXTURE0);
+ d->texture->bind();
+
+ program()->setUniformValue(m_timestamp_id, (float) d->timestamp);
+ program()->setUniformValue("framecount", (float) 1);
+ program()->setUniformValue("animcount", (float) 1);
+ program()->setUniformValue(m_entry_id, (float) d->entry);
+ program()->setUniformValueArray(m_sizetable_id, (float*) d->sizeTable, UNIFORM_ARRAY_SIZE, 1);
+ program()->setUniformValueArray(m_opacitytable_id, (float*) d->opacityTable, UNIFORM_ARRAY_SIZE, 1);
}
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *)
+ int m_entry_id;
+ int m_timestamp_id;
+ int m_sizetable_id;
+ int m_opacitytable_id;
+ QByteArray m_vertex_code;
+ QByteArray m_fragment_code;
+ QGLFunctions* glFuncs;
+};
+
+class DeformableMaterialData : public ImageMaterialData {};
+class DeformableMaterial : public QSGSimpleMaterialShader<DeformableMaterialData>
+{
+ QSG_DECLARE_SIMPLE_SHADER(DeformableMaterial, DeformableMaterialData)
+
+public:
+ DeformableMaterial()
{
- UltraMaterial *m = static_cast<UltraMaterial *>(newEffect);
- state.context()->functions()->glActiveTexture(GL_TEXTURE1);
- m->colortable->bind();
+ QFile vf(":defaultshaders/imagevertex.shader");
+ vf.open(QFile::ReadOnly);
+ m_vertex_code = QByteArray(SHADER_DEFINES)
+ + QByteArray("#define DEFORM\n#define COLOR\n")
+ + vf.readAll();
+
+ QFile ff(":defaultshaders/imagefragment.shader");
+ ff.open(QFile::ReadOnly);
+ m_fragment_code = QByteArray(SHADER_DEFINES)
+ + QByteArray("#define DEFORM\n#define COLOR\n")
+ + ff.readAll();
+
+ Q_ASSERT(!m_vertex_code.isNull());
+ Q_ASSERT(!m_fragment_code.isNull());
+ }
- state.context()->functions()->glActiveTexture(GL_TEXTURE2);
- m->sizetable->bind();
+ const char *vertexShader() const { return m_vertex_code.constData(); }
+ const char *fragmentShader() const { return m_fragment_code.constData(); }
- state.context()->functions()->glActiveTexture(GL_TEXTURE3);
- m->opacitytable->bind();
+ QList<QByteArray> attributes() const {
+ return QList<QByteArray>() << "vPos" << "vTex" << "vData" << "vVec"
+ << "vColor" << "vDeformVec" << "vRotation";
+ };
- // make sure we end by setting GL_TEXTURE0 as active texture
- state.context()->functions()->glActiveTexture(GL_TEXTURE0);
- m->texture->bind();
+ void initialize() {
+ QSGSimpleMaterialShader<DeformableMaterialData>::initialize();
+ program()->bind();
+ program()->setUniformValue("texture", 0);
+ glFuncs = QGLContext::currentContext()->functions();
+ m_timestamp_id = program()->uniformLocation("timestamp");
+ m_entry_id = program()->uniformLocation("entry");
+ }
+
+ void updateState(const DeformableMaterialData* d, const DeformableMaterialData*) {
+ glFuncs->glActiveTexture(GL_TEXTURE0);
+ d->texture->bind();
+
+ program()->setUniformValue(m_timestamp_id, (float) d->timestamp);
+ program()->setUniformValue(m_entry_id, (float) d->entry);
+ }
+
+ int m_entry_id;
+ int m_timestamp_id;
+ QByteArray m_vertex_code;
+ QByteArray m_fragment_code;
+ QGLFunctions* glFuncs;
+};
+
+class SpriteMaterialData : public ImageMaterialData {};
+class SpriteMaterial : public QSGSimpleMaterialShader<SpriteMaterialData>
+{
+ QSG_DECLARE_SIMPLE_SHADER(SpriteMaterial, SpriteMaterialData)
+
+public:
+ SpriteMaterial()
+ {
+ QFile vf(":defaultshaders/imagevertex.shader");
+ vf.open(QFile::ReadOnly);
+ m_vertex_code = QByteArray(SHADER_DEFINES)
+ + QByteArray("#define SPRITE\n#define TABLE\n#define DEFORM\n#define COLOR\n")
+ + vf.readAll();
- program()->setUniformValue(m_opacity_id, state.opacity());
- program()->setUniformValue(m_timestamp_id, (float) m->timestamp);
- program()->setUniformValue(m_framecount_id, (float) m->framecount);
- program()->setUniformValue(m_animcount_id, (float) m->animcount);
+ QFile ff(":defaultshaders/imagefragment.shader");
+ ff.open(QFile::ReadOnly);
+ m_fragment_code = QByteArray(SHADER_DEFINES)
+ + QByteArray("#define SPRITE\n#define TABLE\n#define DEFORM\n#define COLOR\n")
+ + ff.readAll();
- if (state.isMatrixDirty())
- program()->setUniformValue(m_matrix_id, state.combinedMatrix());
+ Q_ASSERT(!m_vertex_code.isNull());
+ Q_ASSERT(!m_fragment_code.isNull());
}
- virtual void initialize() {
+ const char *vertexShader() const { return m_vertex_code.constData(); }
+ const char *fragmentShader() const { return m_fragment_code.constData(); }
+
+ QList<QByteArray> attributes() const {
+ return QList<QByteArray>() << "vPos" << "vTex" << "vData" << "vVec"
+ << "vColor" << "vDeformVec" << "vRotation" << "vAnimData";
+ };
+
+ void initialize() {
+ QSGSimpleMaterialShader<SpriteMaterialData>::initialize();
program()->bind();
program()->setUniformValue("texture", 0);
program()->setUniformValue("colortable", 1);
- program()->setUniformValue("sizetable", 2);
- program()->setUniformValue("opacitytable", 3);
- m_matrix_id = program()->uniformLocation("matrix");
- m_opacity_id = program()->uniformLocation("opacity");
+ glFuncs = QGLContext::currentContext()->functions();
m_timestamp_id = program()->uniformLocation("timestamp");
m_framecount_id = program()->uniformLocation("framecount");
m_animcount_id = program()->uniformLocation("animcount");
+ m_entry_id = program()->uniformLocation("entry");
+ m_sizetable_id = program()->uniformLocation("sizetable");
+ m_opacitytable_id = program()->uniformLocation("sizetable");
}
- virtual const char *vertexShader() const { return m_vertex_code.constData(); }
- virtual const char *fragmentShader() const { return m_fragment_code.constData(); }
-
- virtual char const *const *attributeNames() const {
- static const char *attr[] = {
- "vPos",
- "vTex",
- "vData",
- "vVec",
- "vColor",
- "vDeformVec",
- "vRotation",
- "vAnimData",
- 0
- };
- return attr;
- }
+ void updateState(const SpriteMaterialData* d, const SpriteMaterialData*) {
+ glFuncs->glActiveTexture(GL_TEXTURE1);
+ d->colorTable->bind();
- virtual bool isColorTable() const { return false; }
+ // make sure we end by setting GL_TEXTURE0 as active texture
+ glFuncs->glActiveTexture(GL_TEXTURE0);
+ d->texture->bind();
+
+ program()->setUniformValue(m_timestamp_id, (float) d->timestamp);
+ program()->setUniformValue(m_framecount_id, (float) d->framecount);
+ program()->setUniformValue(m_animcount_id, (float) d->animcount);
+ program()->setUniformValue(m_entry_id, (float) d->entry);
+ program()->setUniformValueArray(m_sizetable_id, (float*) d->sizeTable, 64, 1);
+ program()->setUniformValueArray(m_opacitytable_id, (float*) d->opacityTable, UNIFORM_ARRAY_SIZE, 1);
+ }
- int m_matrix_id;
- int m_opacity_id;
int m_timestamp_id;
int m_framecount_id;
int m_animcount_id;
-
+ int m_entry_id;
+ int m_sizetable_id;
+ int m_opacitytable_id;
QByteArray m_vertex_code;
QByteArray m_fragment_code;
-
- static float chunkOfBytes[1024];
+ QGLFunctions* glFuncs;
};
-float UltraMaterialData::chunkOfBytes[1024];
-QSGMaterialShader *UltraMaterial::createShader() const
+class ColoredMaterialData : public ImageMaterialData {};
+class ColoredMaterial : public QSGSimpleMaterialShader<ColoredMaterialData>
{
- if (usesSprites)//TODO: Perhaps just swap the shaders, and don't mind the extra vector?
- return new UltraMaterialData;
- else
- return new UltraMaterialData;
-}
+ QSG_DECLARE_SIMPLE_SHADER(ColoredMaterial, ColoredMaterialData)
+
+public:
+ ColoredMaterial()
+ {
+ QFile vf(":defaultshaders/imagevertex.shader");
+ vf.open(QFile::ReadOnly);
+ m_vertex_code = QByteArray(SHADER_DEFINES)
+ + QByteArray("#define COLOR\n")
+ + vf.readAll();
+ QFile ff(":defaultshaders/imagefragment.shader");
+ ff.open(QFile::ReadOnly);
+ m_fragment_code = QByteArray(SHADER_DEFINES)
+ + QByteArray("#define COLOR\n")
+ + ff.readAll();
-class SimpleMaterial : public UltraMaterial
-{
- virtual QSGMaterialShader *createShader() const;
- virtual QSGMaterialType *type() const { static QSGMaterialType type; return &type; }
+ Q_ASSERT(!m_vertex_code.isNull());
+ Q_ASSERT(!m_fragment_code.isNull());
+ }
+
+ const char *vertexShader() const { return m_vertex_code.constData(); }
+ const char *fragmentShader() const { return m_fragment_code.constData(); }
+
+ void activate() {
+ QSGSimpleMaterialShader<ColoredMaterialData>::activate();
+#ifndef QT_OPENGL_ES_2
+ glEnable(GL_POINT_SPRITE);
+ glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
+#endif
+ }
+
+ void deactivate() {
+ QSGSimpleMaterialShader<ColoredMaterialData>::deactivate();
+#ifndef QT_OPENGL_ES_2
+ glDisable(GL_POINT_SPRITE);
+ glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
+#endif
+ }
+
+ QList<QByteArray> attributes() const {
+ return QList<QByteArray>() << "vPos" << "vData" << "vVec" << "vColor";
+ }
+
+ void initialize() {
+ QSGSimpleMaterialShader<ColoredMaterialData>::initialize();
+ program()->bind();
+ program()->setUniformValue("texture", 0);
+ glFuncs = QGLContext::currentContext()->functions();
+ m_timestamp_id = program()->uniformLocation("timestamp");
+ m_entry_id = program()->uniformLocation("entry");
+ }
+
+ void updateState(const ColoredMaterialData* d, const ColoredMaterialData*) {
+ glFuncs->glActiveTexture(GL_TEXTURE0);
+ d->texture->bind();
+
+ program()->setUniformValue(m_timestamp_id, (float) d->timestamp);
+ program()->setUniformValue(m_entry_id, (float) d->entry);
+ }
+
+ int m_timestamp_id;
+ int m_entry_id;
+ QByteArray m_vertex_code;
+ QByteArray m_fragment_code;
+ QGLFunctions* glFuncs;
};
-class SimpleMaterialData : public QSGMaterialShader
+class SimpleMaterialData : public ImageMaterialData {};
+class SimpleMaterial : public QSGSimpleMaterialShader<SimpleMaterialData>
{
+ QSG_DECLARE_SIMPLE_SHADER(SimpleMaterial, SimpleMaterialData)
+
public:
- SimpleMaterialData(const char *vertexFile = 0, const char *fragmentFile = 0)
+ SimpleMaterial()
{
- QFile vf(vertexFile ? vertexFile : ":defaultshaders/simplevertex.shader");
+ QFile vf(":defaultshaders/imagevertex.shader");
vf.open(QFile::ReadOnly);
- m_vertex_code = vf.readAll();
+ m_vertex_code = QByteArray(SHADER_DEFINES)
+ + vf.readAll();
- QFile ff(fragmentFile ? fragmentFile : ":defaultshaders/simplefragment.shader");
+ QFile ff(":defaultshaders/imagefragment.shader");
ff.open(QFile::ReadOnly);
- m_fragment_code = ff.readAll();
+ m_fragment_code = QByteArray(SHADER_DEFINES)
+ + ff.readAll();
Q_ASSERT(!m_vertex_code.isNull());
Q_ASSERT(!m_fragment_code.isNull());
}
- void deactivate() {
- QSGMaterialShader::deactivate();
+ const char *vertexShader() const { return m_vertex_code.constData(); }
+ const char *fragmentShader() const { return m_fragment_code.constData(); }
- for (int i=0; i<8; ++i) {
- program()->setAttributeArray(i, GL_FLOAT, chunkOfBytes, 1, 0);
- }
+ void activate() {
+ QSGSimpleMaterialShader<SimpleMaterialData>::activate();
+#ifndef QT_OPENGL_ES_2
+ glEnable(GL_POINT_SPRITE);
+ glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
+#endif
}
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *)
- {
- UltraMaterial *m = static_cast<UltraMaterial *>(newEffect);
- state.context()->functions()->glActiveTexture(GL_TEXTURE0);
- m->texture->bind();
-
- program()->setUniformValue(m_opacity_id, state.opacity());
- program()->setUniformValue(m_timestamp_id, (float) m->timestamp);
+ void deactivate() {
+ QSGSimpleMaterialShader<SimpleMaterialData>::deactivate();
+#ifndef QT_OPENGL_ES_2
+ glDisable(GL_POINT_SPRITE);
+ glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
+#endif
+ }
- if (state.isMatrixDirty())
- program()->setUniformValue(m_matrix_id, state.combinedMatrix());
+ QList<QByteArray> attributes() const {
+ return QList<QByteArray>() << "vPos" << "vData" << "vVec";
}
- virtual void initialize() {
- m_matrix_id = program()->uniformLocation("matrix");
- m_opacity_id = program()->uniformLocation("opacity");
+ void initialize() {
+ QSGSimpleMaterialShader<SimpleMaterialData>::initialize();
+ program()->bind();
+ program()->setUniformValue("texture", 0);
+ glFuncs = QGLContext::currentContext()->functions();
m_timestamp_id = program()->uniformLocation("timestamp");
+ m_entry_id = program()->uniformLocation("entry");
}
- virtual const char *vertexShader() const { return m_vertex_code.constData(); }
- virtual const char *fragmentShader() const { return m_fragment_code.constData(); }
-
- virtual char const *const *attributeNames() const {
- static const char *attr[] = {
- "vPos",
- "vTex",
- "vData",
- "vVec",
- 0
- };
- return attr;
- }
+ void updateState(const SimpleMaterialData* d, const SimpleMaterialData*) {
+ glFuncs->glActiveTexture(GL_TEXTURE0);
+ d->texture->bind();
- virtual bool isColorTable() const { return false; }
+ program()->setUniformValue(m_timestamp_id, (float) d->timestamp);
+ program()->setUniformValue(m_entry_id, (float) d->entry);
+ }
- int m_matrix_id;
- int m_opacity_id;
int m_timestamp_id;
-
+ int m_entry_id;
QByteArray m_vertex_code;
QByteArray m_fragment_code;
-
- static float chunkOfBytes[1024];
+ QGLFunctions* glFuncs;
};
-float SimpleMaterialData::chunkOfBytes[1024];
-QSGMaterialShader *SimpleMaterial::createShader() const {
- return new SimpleMaterialData;
+void fillUniformArrayFromImage(float* array, const QImage& img, int size)
+{
+ if (img.isNull()){
+ for (int i=0; i<size; i++)
+ array[i] = 1;
+ return;
+ }
+ QImage scaled = img.scaled(size,1);
+ for (int i=0; i<size; i++)
+ array[i] = qAlpha(scaled.pixel(i,0))/255.0;
}
/*!
\qmlclass ImageParticle QSGImageParticle
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits ParticlePainter
\brief The ImageParticle element visualizes logical particles using an image
@@ -303,6 +460,8 @@ QSGMaterialShader *SimpleMaterial::createShader() const {
*/
/*!
\qmlproperty url QtQuick.Particles2::ImageParticle::sizeTable
+
+ Note that currently sizeTable is ignored for sprite particles.
*/
/*!
\qmlproperty url QtQuick.Particles2::ImageParticle::opacityTable
@@ -352,6 +511,21 @@ QSGMaterialShader *SimpleMaterial::createShader() const {
/*!
\qmlproperty list<Sprite> QtQuick.Particles2::ImageParticle::sprites
*/
+/*!
+ \qmlproperty EntryEffect QtQuick.Particles2::ImageParticle::entryEffect
+
+ This property provides basic and cheap entrance and exit effects for the particles.
+ For fine-grained control, see sizeTable and opacityTable.
+
+ Acceptable values are
+ \list
+ \o None: Particles just appear and disappear.
+ \o Fade: Particles fade in from 0. opacity at the start of their life, and fade out to 0. at the end.
+ \o Scale: Particles scale in from 0 size at the start of their life, and scale back to 0 at the end.
+ \endlist
+
+ Default value is Fade.
+*/
QSGImageParticle::QSGImageParticle(QSGItem* parent)
@@ -376,8 +550,16 @@ QSGImageParticle::QSGImageParticle(QSGItem* parent)
, m_bloat(false)
, perfLevel(Unknown)
, m_lastLevel(Unknown)
+ , m_debugMode(false)
+ , m_entryEffect(Fade)
{
setFlag(ItemHasContents);
+ m_debugMode = qmlParticlesDebug();
+}
+
+QSGImageParticle::~QSGImageParticle()
+{
+ delete m_material;
}
QDeclarativeListProperty<QSGSprite> QSGImageParticle::sprites()
@@ -572,6 +754,16 @@ void QSGImageParticle::setBloat(bool arg)
reset();
}
+void QSGImageParticle::setEntryEffect(EntryEffect arg)
+{
+ if (m_entryEffect != arg) {
+ m_entryEffect = arg;
+ if (m_material)
+ getState<ImageMaterialData>(m_material)->entry = (qreal) m_entryEffect;
+ emit entryEffectChanged(arg);
+ }
+}
+
void QSGImageParticle::reset()
{
QSGParticlePainter::reset();
@@ -592,19 +784,49 @@ void QSGImageParticle::createEngine()
static QSGGeometry::Attribute SimpleParticle_Attributes[] = {
{ 0, 2, GL_FLOAT }, // Position
- { 1, 2, GL_FLOAT }, // TexCoord
- { 2, 4, GL_FLOAT }, // Data
- { 3, 4, GL_FLOAT } // Vectors
+ { 1, 4, GL_FLOAT }, // Data
+ { 2, 4, GL_FLOAT } // Vectors
};
static QSGGeometry::AttributeSet SimpleParticle_AttributeSet =
{
- 4, // Attribute Count
- (2 + 2 + 4 + 4 ) * sizeof(float),
+ 3, // Attribute Count
+ ( 2 + 4 + 4 ) * sizeof(float),
SimpleParticle_Attributes
};
-static QSGGeometry::Attribute UltraParticle_Attributes[] = {
+static QSGGeometry::Attribute ColoredParticle_Attributes[] = {
+ { 0, 2, GL_FLOAT }, // Position
+ { 1, 4, GL_FLOAT }, // Data
+ { 2, 4, GL_FLOAT }, // Vectors
+ { 3, 4, GL_UNSIGNED_BYTE }, // Colors
+};
+
+static QSGGeometry::AttributeSet ColoredParticle_AttributeSet =
+{
+ 4, // Attribute Count
+ ( 2 + 4 + 4 ) * sizeof(float) + 4 * sizeof(uchar),
+ ColoredParticle_Attributes
+};
+
+static QSGGeometry::Attribute DeformableParticle_Attributes[] = {
+ { 0, 2, GL_FLOAT }, // Position
+ { 1, 2, GL_FLOAT }, // TexCoord
+ { 2, 4, GL_FLOAT }, // Data
+ { 3, 4, GL_FLOAT }, // Vectors
+ { 4, 4, GL_UNSIGNED_BYTE }, // Colors
+ { 5, 4, GL_FLOAT }, // DeformationVectors
+ { 6, 3, GL_FLOAT }, // Rotation
+};
+
+static QSGGeometry::AttributeSet DeformableParticle_AttributeSet =
+{
+ 7, // Attribute Count
+ (2 + 2 + 4 + 4 + 4 + 3) * sizeof(float) + 4 * sizeof(uchar),
+ DeformableParticle_Attributes
+};
+
+static QSGGeometry::Attribute SpriteParticle_Attributes[] = {
{ 0, 2, GL_FLOAT }, // Position
{ 1, 2, GL_FLOAT }, // TexCoord
{ 2, 4, GL_FLOAT }, // Data
@@ -615,159 +837,100 @@ static QSGGeometry::Attribute UltraParticle_Attributes[] = {
{ 7, 4, GL_FLOAT } // Anim Data
};
-static QSGGeometry::AttributeSet UltraParticle_AttributeSet =
+static QSGGeometry::AttributeSet SpriteParticle_AttributeSet =
{
8, // Attribute Count
(2 + 2 + 4 + 4 + 4 + 4 + 3) * sizeof(float) + 4 * sizeof(uchar),
- UltraParticle_Attributes
+ SpriteParticle_Attributes
};
-QSGGeometryNode* QSGImageParticle::buildSimpleParticleNodes()
-{
- perfLevel = Simple;//TODO: Intermediate levels
- QImage image = QImage(m_image_name.toLocalFile());
- if (image.isNull()) {
- printf("UltraParticle: loading image failed... '%s'\n", qPrintable(m_image_name.toLocalFile()));
- return 0;
- }
-
- if (m_material) {
- delete m_material;
- m_material = 0;
- }
-
- m_material = new SimpleMaterial();
- m_material->texture = sceneGraphEngine()->createTextureFromImage(image);
- m_material->texture->setFiltering(QSGTexture::Linear);
- m_material->framecount = 1;
-
- foreach (const QString &str, m_particles){
- int gIdx = m_system->m_groupIds[str];
- int count = m_system->m_groupData[gIdx]->size();
-
- QSGGeometryNode* node = new QSGGeometryNode();
- m_nodes.insert(gIdx, node);
- node->setMaterial(m_material);
-
- int vCount = count * 4;
- int iCount = count * 6;
-
- QSGGeometry *g = new QSGGeometry(SimpleParticle_AttributeSet, vCount, iCount);
- node->setGeometry(g);
- g->setDrawingMode(GL_TRIANGLES);
-
- SimpleVertex *vertices = (SimpleVertex *) g->vertexData();
- for (int p=0; p < count; ++p){
- commit(gIdx, p);
- vertices[0].tx = 0;
- vertices[0].ty = 0;
-
- vertices[1].tx = 1;
- vertices[1].ty = 0;
-
- vertices[2].tx = 0;
- vertices[2].ty = 1;
-
- vertices[3].tx = 1;
- vertices[3].ty = 1;
-
- vertices += 4;
- }
-
- quint16 *indices = g->indexDataAsUShort();
- for (int i=0; i < count; ++i) {
- int o = i * 4;
- indices[0] = o;
- indices[1] = o + 1;
- indices[2] = o + 2;
- indices[3] = o + 1;
- indices[4] = o + 3;
- indices[5] = o + 2;
- indices += 6;
- }
- }
-
- foreach (QSGGeometryNode* node, m_nodes){
- if (node == *(m_nodes.begin()))
- continue;
- (*(m_nodes.begin()))->appendChildNode(node);
- }
-
- return *(m_nodes.begin());
-}
-
QSGGeometryNode* QSGImageParticle::buildParticleNodes()
{
+#ifdef QT_OPENGL_ES_2
if (m_count * 4 > 0xffff) {
- printf("UltraParticle: Too many particles... \n");//### Why is this here?
+ printf("ImageParticle: Too many particles - maximum 16,000 per ImageParticle.\n");//ES 2 vertex count limit is ushort
return 0;
}
+#endif
if (count() <= 0)
return 0;
- if (!m_sprites.count() && !m_bloat
- && m_colortable_name.isEmpty()
- && m_sizetable_name.isEmpty()
- && m_opacitytable_name.isEmpty()
- && !m_autoRotation
- && !m_rotation && !m_rotationVariation
- && !m_rotationSpeed && !m_rotationSpeedVariation
- && !m_alphaVariation && m_alpha == 1.0
- && !m_redVariation && !m_blueVariation && !m_greenVariation
- && !m_color.isValid()
- )
- return buildSimpleParticleNodes();
- perfLevel = Sprites;//TODO: intermediate levels
- if (!m_color.isValid())//But we're in colored level (or higher)
- m_color = QColor(Qt::white);
+ if (m_sprites.count() || m_bloat) {
+ perfLevel = Sprites;
+ } else if (!m_colortable_name.isEmpty() || !m_sizetable_name.isEmpty()
+ || !m_opacitytable_name.isEmpty()) {
+ perfLevel = Tabled;
+ } else if (m_autoRotation || m_rotation || m_rotationVariation
+ || m_rotationSpeed || m_rotationSpeedVariation) {
+ perfLevel = Deformable;
+ } else if (m_alphaVariation || m_alpha != 1.0 || m_color.isValid()
+ || m_redVariation || m_blueVariation || m_greenVariation) {
+ perfLevel = Colored;
+ } else {
+ perfLevel = Simple;
+ }
+
+ if (perfLevel >= Colored && !m_color.isValid())
+ m_color = QColor(Qt::white);//Hidden default, but different from unset
QImage image;
- if (m_sprites.count()){
+ if (perfLevel >= Sprites){
if (!m_spriteEngine) {
- qWarning() << "UltraParticle: No sprite engine...";
+ qWarning() << "ImageParticle: No sprite engine...";
return 0;
}
image = m_spriteEngine->assembledImage();
if (image.isNull())//Warning is printed in engine
return 0;
- }else{
+ } else {
image = QImage(m_image_name.toLocalFile());
if (image.isNull()) {
- printf("UltraParticle: loading image failed... '%s'\n", qPrintable(m_image_name.toLocalFile()));
+ printf("ImageParticle: loading image failed '%s'\n", qPrintable(m_image_name.toLocalFile()));
return 0;
}
}
+
if (m_material) {
delete m_material;
m_material = 0;
}
- QImage colortable(m_colortable_name.toLocalFile());
- QImage sizetable(m_sizetable_name.toLocalFile());
- QImage opacitytable(m_opacitytable_name.toLocalFile());
- m_material = new UltraMaterial();
- if (colortable.isNull())
- colortable = QImage(":defaultshaders/identitytable.png");
- if (sizetable.isNull())
- sizetable = QImage(":defaultshaders/identitytable.png");
- if (opacitytable.isNull())
- opacitytable = QImage(":defaultshaders/defaultFadeInOut.png");
- Q_ASSERT(!colortable.isNull());
- Q_ASSERT(!sizetable.isNull());
- Q_ASSERT(!opacitytable.isNull());
- m_material->colortable = sceneGraphEngine()->createTextureFromImage(colortable);
- m_material->sizetable = sceneGraphEngine()->createTextureFromImage(sizetable);
- m_material->opacitytable = sceneGraphEngine()->createTextureFromImage(opacitytable);
-
- m_material->texture = sceneGraphEngine()->createTextureFromImage(image);
- m_material->texture->setFiltering(QSGTexture::Linear);
-
- m_material->framecount = 1;
- if (m_spriteEngine){
- m_material->framecount = m_spriteEngine->maxFrames();
+ //Setup material
+ QImage colortable;
+ QImage sizetable;
+ QImage opacitytable;
+ switch (perfLevel) {//Fallthrough intended
+ case Sprites:
+ m_material = SpriteMaterial::createMaterial();
+ getState<ImageMaterialData>(m_material)->framecount = m_spriteEngine->maxFrames();
m_spriteEngine->setCount(m_count);
+ case Tabled:
+ if (!m_material)
+ m_material = TabledMaterial::createMaterial();
+ colortable = QImage(m_colortable_name.toLocalFile());
+ sizetable = QImage(m_sizetable_name.toLocalFile());
+ opacitytable = QImage(m_opacitytable_name.toLocalFile());
+ if (colortable.isNull())
+ colortable = QImage(":defaultshaders/identitytable.png");
+ Q_ASSERT(!colortable.isNull());
+ getState<ImageMaterialData>(m_material)->colorTable = sceneGraphEngine()->createTextureFromImage(colortable);
+ fillUniformArrayFromImage(getState<ImageMaterialData>(m_material)->sizeTable, sizetable, UNIFORM_ARRAY_SIZE);
+ fillUniformArrayFromImage(getState<ImageMaterialData>(m_material)->opacityTable, opacitytable, UNIFORM_ARRAY_SIZE);
+ case Deformable:
+ if (!m_material)
+ m_material = DeformableMaterial::createMaterial();
+ case Colored:
+ if (!m_material)
+ m_material = ColoredMaterial::createMaterial();
+ default://Also Simple
+ if (!m_material)
+ m_material = SimpleMaterial::createMaterial();
+ getState<ImageMaterialData>(m_material)->texture = sceneGraphEngine()->createTextureFromImage(image);
+ getState<ImageMaterialData>(m_material)->texture->setFiltering(QSGTexture::Linear);
+ getState<ImageMaterialData>(m_material)->entry = (qreal) m_entryEffect;
+ m_material->setFlag(QSGMaterial::Blending);
}
foreach (const QString &str, m_particles){
@@ -784,39 +947,51 @@ QSGGeometryNode* QSGImageParticle::buildParticleNodes()
int vCount = count * 4;
int iCount = count * 6;
- QSGGeometry *g = new QSGGeometry(UltraParticle_AttributeSet, vCount, iCount);
- node->setGeometry(g);
- g->setDrawingMode(GL_TRIANGLES);
-
- UltraVertex *vertices = (UltraVertex *) g->vertexData();
- for (int p=0; p < count; ++p) {
- commit(gIdx, p);//commit sets geometry for the node
-
- vertices[0].tx = 0;
- vertices[0].ty = 0;
-
- vertices[1].tx = 1;
- vertices[1].ty = 0;
-
- vertices[2].tx = 0;
- vertices[2].ty = 1;
-
- vertices[3].tx = 1;
- vertices[3].ty = 1;
-
- vertices += 4;
- }
+ QSGGeometry *g;
+ if (perfLevel == Sprites)
+ g = new QSGGeometry(SpriteParticle_AttributeSet, vCount, iCount);
+ else if (perfLevel == Tabled)
+ g = new QSGGeometry(DeformableParticle_AttributeSet, vCount, iCount);
+ else if (perfLevel == Deformable)
+ g = new QSGGeometry(DeformableParticle_AttributeSet, vCount, iCount);
+ else if (perfLevel == Colored)
+ g = new QSGGeometry(ColoredParticle_AttributeSet, count, 0);
+ else //Simple
+ g = new QSGGeometry(SimpleParticle_AttributeSet, count, 0);
- quint16 *indices = g->indexDataAsUShort();
- for (int i=0; i < count; ++i) {
- int o = i * 4;
- indices[0] = o;
- indices[1] = o + 1;
- indices[2] = o + 2;
- indices[3] = o + 1;
- indices[4] = o + 3;
- indices[5] = o + 2;
- indices += 6;
+ node->setGeometry(g);
+ if (perfLevel <= Colored){
+ g->setDrawingMode(GL_POINTS);
+ if (m_debugMode){
+ GLfloat pointSizeRange[2];
+ glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, pointSizeRange);
+ qDebug() << "Using point sprites, GL_ALIASED_POINT_SIZE_RANGE " <<pointSizeRange[0] << ":" << pointSizeRange[1];
+ }
+ }else
+ g->setDrawingMode(GL_TRIANGLES);
+
+ for (int p=0; p < count; ++p)
+ commit(gIdx, p);//commit sets geometry for the node, has its own perfLevel switch
+
+ if (perfLevel == Sprites)
+ initTexCoords<SpriteVertex>((SpriteVertex*)g->vertexData(), vCount);
+ else if (perfLevel == Tabled)
+ initTexCoords<DeformableVertex>((DeformableVertex*)g->vertexData(), vCount);
+ else if (perfLevel == Deformable)
+ initTexCoords<DeformableVertex>((DeformableVertex*)g->vertexData(), vCount);
+
+ if (perfLevel > Colored){
+ quint16 *indices = g->indexDataAsUShort();
+ for (int i=0; i < count; ++i) {
+ int o = i * 4;
+ indices[0] = o;
+ indices[1] = o + 1;
+ indices[2] = o + 2;
+ indices[3] = o + 1;
+ indices[4] = o + 3;
+ indices[5] = o + 2;
+ indices += 6;
+ }
}
}
@@ -867,26 +1042,34 @@ void QSGImageParticle::prepareNextFrame()
m_rootNode = buildParticleNodes();
if (m_rootNode == 0)
return;
- //qDebug() << "Feature level: " << perfLevel;
+ if(m_debugMode){
+ qDebug() << "QSGImageParticle Feature level: " << perfLevel;
+ qDebug() << "QSGImageParticle Nodes: ";
+ int count = 0;
+ foreach(int i, m_nodes.keys()){
+ qDebug() << "Group " << i << " (" << m_system->m_groupData[i]->size() << " particles)";
+ count += m_system->m_groupData[i]->size();
+ }
+ qDebug() << "Total count: " << count;
+ }
}
qint64 timeStamp = m_system->systemSync(this);
qreal time = timeStamp / 1000.;
- m_material->timestamp = time;
-
- //Advance State
- if (m_spriteEngine){//perfLevel == Sprites?//TODO: use signals?
- m_material->animcount = m_spriteEngine->spriteCount();
+ switch (perfLevel){//Fall-through intended
+ case Sprites:
+ //Advance State
+ getState<ImageMaterialData>(m_material)->animcount = m_spriteEngine->spriteCount();
m_spriteEngine->updateSprites(timeStamp);
foreach (const QString &str, m_particles){
int gIdx = m_system->m_groupIds[str];
int count = m_system->m_groupData[gIdx]->size();
- UltraVertices *particles = (UltraVertices *) m_nodes[gIdx]->geometry()->vertexData();
+ Vertices<SpriteVertex>* particles = (Vertices<SpriteVertex> *) m_nodes[gIdx]->geometry()->vertexData();
for (int i=0; i < count; i++){
int spriteIdx = m_idxStarts[gIdx] + i;
- UltraVertices &p = particles[i];
+ Vertices<SpriteVertex> &p = particles[i];
int curIdx = m_spriteEngine->spriteState(spriteIdx);
if (curIdx != p.v1.animIdx){
p.v1.animIdx = p.v2.animIdx = p.v3.animIdx = p.v4.animIdx = curIdx;
@@ -896,9 +1079,15 @@ void QSGImageParticle::prepareNextFrame()
}
}
}
- }else{
- m_material->animcount = 1;
+ case Tabled:
+ case Deformable:
+ case Colored:
+ case Simple:
+ default: //Also Simple
+ getState<ImageMaterialData>(m_material)->timestamp = time;
+ break;
}
+
}
void QSGImageParticle::reloadColor(const Color4ub &c, QSGParticleData* d)
@@ -967,47 +1156,91 @@ void QSGImageParticle::commit(int gIdx, int pIdx)
if (!node)
return;
QSGParticleData* datum = m_system->m_groupData[gIdx]->data[pIdx];
-
node->setFlag(QSGNode::OwnsGeometry, false);
- UltraVertex *ultraVertices = (UltraVertex *) node->geometry()->vertexData();
+ SpriteVertex *spriteVertices = (SpriteVertex *) node->geometry()->vertexData();
+ DeformableVertex *deformableVertices = (DeformableVertex *) node->geometry()->vertexData();
+ ColoredVertex *coloredVertices = (ColoredVertex *) node->geometry()->vertexData();
SimpleVertex *simpleVertices = (SimpleVertex *) node->geometry()->vertexData();
- switch (perfLevel){
+ switch (perfLevel){//No automatic fall through intended on this one
case Sprites:
- ultraVertices += pIdx*4;
+ spriteVertices += pIdx*4;
for (int i=0; i<4; i++){
- ultraVertices[i].x = datum->x - m_systemOffset.x();
- ultraVertices[i].y = datum->y - m_systemOffset.y();
- ultraVertices[i].t = datum->t;
- ultraVertices[i].lifeSpan = datum->lifeSpan;
- ultraVertices[i].size = datum->size;
- ultraVertices[i].endSize = datum->endSize;
- ultraVertices[i].vx = datum->vx;
- ultraVertices[i].vy = datum->vy;
- ultraVertices[i].ax = datum->ax;
- ultraVertices[i].ay = datum->ay;
- ultraVertices[i].xx = datum->xx;
- ultraVertices[i].xy = datum->xy;
- ultraVertices[i].yx = datum->yx;
- ultraVertices[i].yy = datum->yy;
- ultraVertices[i].rotation = datum->rotation;
- ultraVertices[i].rotationSpeed = datum->rotationSpeed;
- ultraVertices[i].autoRotate = datum->autoRotate;
- ultraVertices[i].animIdx = datum->animIdx;
- ultraVertices[i].frameDuration = datum->frameDuration;
- ultraVertices[i].frameCount = datum->frameCount;
- ultraVertices[i].animT = datum->animT;
- ultraVertices[i].color.r = datum->color.r;
- ultraVertices[i].color.g = datum->color.g;
- ultraVertices[i].color.b = datum->color.b;
- ultraVertices[i].color.a = datum->color.a;
+ spriteVertices[i].x = datum->x - m_systemOffset.x();
+ spriteVertices[i].y = datum->y - m_systemOffset.y();
+ spriteVertices[i].t = datum->t;
+ spriteVertices[i].lifeSpan = datum->lifeSpan;
+ spriteVertices[i].size = datum->size;
+ spriteVertices[i].endSize = datum->endSize;
+ spriteVertices[i].vx = datum->vx;
+ spriteVertices[i].vy = datum->vy;
+ spriteVertices[i].ax = datum->ax;
+ spriteVertices[i].ay = datum->ay;
+ spriteVertices[i].xx = datum->xx;
+ spriteVertices[i].xy = datum->xy;
+ spriteVertices[i].yx = datum->yx;
+ spriteVertices[i].yy = datum->yy;
+ spriteVertices[i].rotation = datum->rotation;
+ spriteVertices[i].rotationSpeed = datum->rotationSpeed;
+ spriteVertices[i].autoRotate = datum->autoRotate;
+ spriteVertices[i].animIdx = datum->animIdx;
+ spriteVertices[i].frameDuration = datum->frameDuration;
+ spriteVertices[i].frameCount = datum->frameCount;
+ spriteVertices[i].animT = datum->animT;
+ spriteVertices[i].color.r = datum->color.r;
+ spriteVertices[i].color.g = datum->color.g;
+ spriteVertices[i].color.b = datum->color.b;
+ spriteVertices[i].color.a = datum->color.a;
}
break;
- case Tabled://TODO: Us
+ case Tabled: //Fall through until it has its own vertex class
case Deformable:
+ deformableVertices += pIdx*4;
+ for (int i=0; i<4; i++){
+ deformableVertices[i].x = datum->x - m_systemOffset.x();
+ deformableVertices[i].y = datum->y - m_systemOffset.y();
+ deformableVertices[i].t = datum->t;
+ deformableVertices[i].lifeSpan = datum->lifeSpan;
+ deformableVertices[i].size = datum->size;
+ deformableVertices[i].endSize = datum->endSize;
+ deformableVertices[i].vx = datum->vx;
+ deformableVertices[i].vy = datum->vy;
+ deformableVertices[i].ax = datum->ax;
+ deformableVertices[i].ay = datum->ay;
+ deformableVertices[i].xx = datum->xx;
+ deformableVertices[i].xy = datum->xy;
+ deformableVertices[i].yx = datum->yx;
+ deformableVertices[i].yy = datum->yy;
+ deformableVertices[i].rotation = datum->rotation;
+ deformableVertices[i].rotationSpeed = datum->rotationSpeed;
+ deformableVertices[i].autoRotate = datum->autoRotate;
+ deformableVertices[i].color.r = datum->color.r;
+ deformableVertices[i].color.g = datum->color.g;
+ deformableVertices[i].color.b = datum->color.b;
+ deformableVertices[i].color.a = datum->color.a;
+ }
+ break;
case Colored:
+ coloredVertices += pIdx*1;
+ for (int i=0; i<1; i++){
+ coloredVertices[i].x = datum->x - m_systemOffset.x();
+ coloredVertices[i].y = datum->y - m_systemOffset.y();
+ coloredVertices[i].t = datum->t;
+ coloredVertices[i].lifeSpan = datum->lifeSpan;
+ coloredVertices[i].size = datum->size;
+ coloredVertices[i].endSize = datum->endSize;
+ coloredVertices[i].vx = datum->vx;
+ coloredVertices[i].vy = datum->vy;
+ coloredVertices[i].ax = datum->ax;
+ coloredVertices[i].ay = datum->ay;
+ coloredVertices[i].color.r = datum->color.r;
+ coloredVertices[i].color.g = datum->color.g;
+ coloredVertices[i].color.b = datum->color.b;
+ coloredVertices[i].color.a = datum->color.a;
+ }
+ break;
case Simple:
- simpleVertices += pIdx*4;
- for (int i=0; i<4; i++){
+ simpleVertices += pIdx*1;
+ for (int i=0; i<1; i++){
simpleVertices[i].x = datum->x - m_systemOffset.x();
simpleVertices[i].y = datum->y - m_systemOffset.y();
simpleVertices[i].t = datum->t;
diff --git a/src/declarative/particles/qsgimageparticle_p.h b/src/declarative/particles/qsgimageparticle_p.h
index 1ac840ca9f..eb890e285c 100644
--- a/src/declarative/particles/qsgimageparticle_p.h
+++ b/src/declarative/particles/qsgimageparticle_p.h
@@ -44,6 +44,7 @@
#include "qsgparticlepainter_p.h"
#include "qsgstochasticdirection_p.h"
#include <QDeclarativeListProperty>
+#include <qsgsimplematerial.h>
QT_BEGIN_HEADER
@@ -51,7 +52,7 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
-class UltraMaterial;
+class ImageMaterialData;
class QSGGeometryNode;
class QSGSprite;
@@ -60,8 +61,6 @@ class QSGSpriteEngine;
struct SimpleVertex {
float x;
float y;
- float tx;
- float ty;
float t;
float lifeSpan;
float size;
@@ -72,14 +71,44 @@ struct SimpleVertex {
float ay;
};
-struct SimpleVertices {
- SimpleVertex v1;
- SimpleVertex v2;
- SimpleVertex v3;
- SimpleVertex v4;
+struct ColoredVertex {
+ float x;
+ float y;
+ float t;
+ float lifeSpan;
+ float size;
+ float endSize;
+ float vx;
+ float vy;
+ float ax;
+ float ay;
+ Color4ub color;
+};
+
+struct DeformableVertex {
+ float x;
+ float y;
+ float tx;
+ float ty;
+ float t;
+ float lifeSpan;
+ float size;
+ float endSize;
+ float vx;
+ float vy;
+ float ax;
+ float ay;
+ Color4ub color;
+ float xx;
+ float xy;
+ float yx;
+ float yy;
+ float rotation;
+ float rotationSpeed;
+ float autoRotate;//Assumed that GPUs prefer floats to bools
};
-struct UltraVertex {
+struct SpriteVertex {
float x;
float y;
float tx;
@@ -99,25 +128,19 @@ struct UltraVertex {
float yy;
float rotation;
float rotationSpeed;
- float autoRotate;//Assume that GPUs prefer floats to bools
+ float autoRotate;//Assumed that GPUs prefer floats to bools
float animIdx;
float frameDuration;
float frameCount;
float animT;
};
-struct UltraVertices {
- UltraVertex v1;
- UltraVertex v2;
- UltraVertex v3;
- UltraVertex v4;
-};
-
-struct IntermediateVertices {
- UltraVertex* v1;
- UltraVertex* v2;
- UltraVertex* v3;
- UltraVertex* v4;
+template <typename Vertex>
+struct Vertices {
+ Vertex v1;
+ Vertex v2;
+ Vertex v3;
+ Vertex v4;
};
class QSGImageParticle : public QSGParticlePainter
@@ -153,15 +176,24 @@ class QSGImageParticle : public QSGParticlePainter
//yVector is the same, but top-left to bottom-left. The particle is always a parallelogram.
Q_PROPERTY(QSGStochasticDirection* yVector READ yVector WRITE setYVector NOTIFY yVectorChanged)
Q_PROPERTY(QDeclarativeListProperty<QSGSprite> sprites READ sprites)
+
+ Q_PROPERTY(EntryEffect entryEffect READ entryEffect WRITE setEntryEffect NOTIFY entryEffectChanged)
Q_PROPERTY(bool bloat READ bloat WRITE setBloat NOTIFY bloatChanged)//Just a debugging property to bypass optimizations
+ Q_ENUMS(EntryEffect)
public:
explicit QSGImageParticle(QSGItem *parent = 0);
- virtual ~QSGImageParticle(){}
+ virtual ~QSGImageParticle();
QDeclarativeListProperty<QSGSprite> sprites();
QSGSpriteEngine* spriteEngine() {return m_spriteEngine;}
+ enum EntryEffect {
+ None = 0,
+ Fade = 1,
+ Scale = 2
+ };
+
enum PerformanceLevel{//TODO: Expose?
Unknown = 0,
Simple,
@@ -217,6 +249,8 @@ public:
bool bloat() const { return m_bloat; }
+ EntryEffect entryEffect() const { return m_entryEffect; }
+
signals:
void imageChanged();
@@ -254,6 +288,8 @@ signals:
void bloatChanged(bool arg);
+ void entryEffectChanged(EntryEffect arg);
+
public slots:
void reloadColor(const Color4ub &c, QSGParticleData* d);
void setAlphaVariation(qreal arg);
@@ -282,6 +318,8 @@ public slots:
void setBloat(bool arg);
+ void setEntryEffect(EntryEffect arg);
+
protected:
void reset();
virtual void initialize(int gIdx, int pIdx);
@@ -290,7 +328,6 @@ protected:
QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
void prepareNextFrame();
QSGGeometryNode* buildParticleNodes();
- QSGGeometryNode* buildSimpleParticleNodes();
private slots:
void createEngine(); //### method invoked by sprite list changing (in engine.h) - pretty nasty
@@ -312,7 +349,7 @@ private:
QHash<int, QSGGeometryNode *> m_nodes;
QHash<int, int> m_idxStarts;//TODO: Proper resizing will lead to needing a spriteEngine per particle - do this after sprite engine gains transparent sharing?
int m_lastIdxStart;
- UltraMaterial *m_material;
+ QSGMaterial *m_material;
// derived values...
@@ -337,6 +374,33 @@ private:
PerformanceLevel perfLevel;
PerformanceLevel m_lastLevel;
+ bool m_debugMode;
+
+ template<class Vertex>
+ void initTexCoords(Vertex* v, int count){
+ Vertex* end = v + count;
+ while (v < end){
+ v[0].tx = 0;
+ v[0].ty = 0;
+
+ v[1].tx = 1;
+ v[1].ty = 0;
+
+ v[2].tx = 0;
+ v[2].ty = 1;
+
+ v[3].tx = 1;
+ v[3].ty = 1;
+
+ v += 4;
+ }
+ }
+
+ template<class MaterialData>
+ MaterialData* getState(QSGMaterial* m){
+ return static_cast<QSGSimpleMaterial<MaterialData> *>(m)->state();
+ }
+ EntryEffect m_entryEffect;
};
QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgitemparticle.cpp b/src/declarative/particles/qsgitemparticle.cpp
index 19d921a10d..65407fabf8 100644
--- a/src/declarative/particles/qsgitemparticle.cpp
+++ b/src/declarative/particles/qsgitemparticle.cpp
@@ -51,7 +51,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass ItemParticle QSGItemParticle
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits ParticlePainter
\brief The ItemParticle element allows you to specify your own delegate to paint particles.
diff --git a/src/declarative/particles/qsgkill.cpp b/src/declarative/particles/qsgkill.cpp
index 9d4bc940bd..dfd26e3f39 100644
--- a/src/declarative/particles/qsgkill.cpp
+++ b/src/declarative/particles/qsgkill.cpp
@@ -45,7 +45,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass Kill QSGKillAffector
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits Affector
\brief The Kill affector allows you to expire affected particles
diff --git a/src/declarative/particles/qsglineextruder.cpp b/src/declarative/particles/qsglineextruder.cpp
index a08d052c20..6581cf23ee 100644
--- a/src/declarative/particles/qsglineextruder.cpp
+++ b/src/declarative/particles/qsglineextruder.cpp
@@ -44,7 +44,6 @@
/*!
\qmlclass LineShape QSGLineExtruder
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits Shape
\brief The LineShape represents a line to Affectors and Emitter
diff --git a/src/declarative/particles/qsgmaskextruder.cpp b/src/declarative/particles/qsgmaskextruder.cpp
index e76280378b..4f8b89a639 100644
--- a/src/declarative/particles/qsgmaskextruder.cpp
+++ b/src/declarative/particles/qsgmaskextruder.cpp
@@ -46,7 +46,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass MaskShape QSGMaskExtruder
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits Shape
\brief The MaskShape element allows you to represent an image as a shape to affectors and emitters.
diff --git a/src/declarative/particles/qsgmodelparticle.cpp b/src/declarative/particles/qsgmodelparticle.cpp
index 19815aa8f4..2646864283 100644
--- a/src/declarative/particles/qsgmodelparticle.cpp
+++ b/src/declarative/particles/qsgmodelparticle.cpp
@@ -49,7 +49,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass ModelParticle QSGModelParticle
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits ParticlePainter
\brief The ModelParticle element allows you to specify a model and delegate pair to paint particles.
diff --git a/src/declarative/particles/qsgparticleaffector.cpp b/src/declarative/particles/qsgparticleaffector.cpp
index bf268efc9d..4cb3e49403 100644
--- a/src/declarative/particles/qsgparticleaffector.cpp
+++ b/src/declarative/particles/qsgparticleaffector.cpp
@@ -45,7 +45,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass Affector QSGParticleAffector
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\brief Affector elements can alter the attributes of logical particles at any point in their lifetime.
The base Affector does not alter any attributes, but can be used to emit a signal
@@ -95,11 +94,24 @@ QT_BEGIN_NAMESPACE
/*!
\qmlproperty bool QtQuick.Particles2::Affector::signal
If this is set to true, then an affected(x,y) signal will be emitted each
- time this affector affects a particle.
+ time this affector would affect a particle.
+
+ For Affector only, this will happen irrespective of whether any changes
+ are made to the particle, for other Affectors the signal will only fire
+ if the particle is actually affected.
Default value is false.
*/
+//TODO: Document particle 'type'
+/*!
+ \qmlsignal QtQuick.Particles2::Affector::affectParticle(particle, dt)
+
+ This handler is called when a particle is selected to be affected.
+
+ dt is the time since the last time it was affected. Use dt to normalize
+ trajectory manipulations to real time.
+*/
QSGParticleAffector::QSGParticleAffector(QSGItem *parent) :
QSGItem(parent), m_needsReset(false), m_system(0), m_active(true)
, m_updateIntSet(false), m_shape(new QSGParticleExtruder(this)), m_signal(false)
@@ -112,6 +124,12 @@ QSGParticleAffector::QSGParticleAffector(QSGItem *parent) :
this, SLOT(updateOffsets()));//TODO: in componentComplete and all relevant signals
}
+bool QSGParticleAffector::isAffectConnected()
+{
+ static int idx = QObjectPrivate::get(this)->signalIndex("affectParticle(QDeclarativeV8Handle, qreal)");
+ return QObjectPrivate::get(this)->isSignalConnected(idx);
+}
+
void QSGParticleAffector::componentComplete()
{
if (!m_system && qobject_cast<QSGParticleSystem*>(parentItem()))
@@ -162,8 +180,10 @@ void QSGParticleAffector::affectSystem(qreal dt)
bool QSGParticleAffector::affectParticle(QSGParticleData *d, qreal dt)
{
- Q_UNUSED(d);
- Q_UNUSED(dt);
+ if (isAffectConnected()){
+ emit affectParticle(d->v8Value(), dt);
+ return true;
+ }
return m_signal;//If signalling, then we always 'null affect' it.
}
diff --git a/src/declarative/particles/qsgparticleaffector_p.h b/src/declarative/particles/qsgparticleaffector_p.h
index 4479f5d131..dd279c07b9 100644
--- a/src/declarative/particles/qsgparticleaffector_p.h
+++ b/src/declarative/particles/qsgparticleaffector_p.h
@@ -103,6 +103,7 @@ public:
}
signals:
+ void affectParticle(QDeclarativeV8Handle particle, qreal dt);
void systemChanged(QSGParticleSystem* arg);
@@ -189,6 +190,7 @@ protected:
bool m_active;
virtual void componentComplete();
QPointF m_offset;
+ bool isAffectConnected();
private:
QSet<int> m_groups;
QSet<QPair<int, int> > m_onceOffed;
diff --git a/src/declarative/particles/qsgparticleemitter.cpp b/src/declarative/particles/qsgparticleemitter.cpp
index dfd1618088..bf4f5701e5 100644
--- a/src/declarative/particles/qsgparticleemitter.cpp
+++ b/src/declarative/particles/qsgparticleemitter.cpp
@@ -41,7 +41,153 @@
#include "qsgparticleemitter_p.h"
QT_BEGIN_NAMESPACE
-//Not visible from QML, so not documented. Document subclasses.
+
+
+/*!
+ \qmlclass Emitter QSGParticleEmitter
+ \inqmlmodule QtQuick.Particles 2
+ \brief The Emitter element allows you to emit logical particles.
+
+ This element emits logical particles into the ParticleSystem, with the
+ given starting attributes.
+
+ Note that logical particles are not
+ automatically rendered, you will need to have one or more
+ ParticlePainter elements visualizing them.
+
+ Note that the given starting attributes can be modified at any point
+ in the particle's lifetime by any Affector element in the same
+ ParticleSystem. This includes attributes like lifespan.
+*/
+
+
+/*!
+ \qmlproperty ParticleSystem QtQuick.Particles2::Emitter::system
+
+ This is the Particle system that the Emitter will emit into.
+ This can be omitted if the Emitter is a direct child of the ParticleSystem
+*/
+/*!
+ \qmlproperty string QtQuick.Particles2::Emitter::particle
+
+ This is the type of logical particle which it will emit.
+
+ Default value is "" (empty string).
+*/
+/*!
+ \qmlproperty Shape QtQuick.Particles2::Emitter::shape
+
+ This shape is applied to the bounding box of the emitter. Particles are then emitting
+ from inside the area of the shape.
+
+*/
+/*!
+ \qmlproperty bool QtQuick.Particles2::Emitter::emitting
+
+ If set to false, the emitter will cease emissions until it is set to true.
+
+ Default value is true.
+*/
+/*!
+ \qmlproperty real QtQuick.Particles2::Emitter::emitRate
+
+ Number of particles emitted per second.
+
+ Default value is 10 particles per second.
+*/
+/*!
+ \qmlproperty int QtQuick.Particles2::Emitter::lifeSpan
+
+ The time in milliseconds each emitted particle should last for.
+
+ Default value is 1000 (one second).
+*/
+/*!
+ \qmlproperty int QtQuick.Particles2::Emitter::lifeSpanVariation
+
+ Particle lifespans will vary by up to this much in either direction.
+
+ Default value is 0.
+*/
+
+/*!
+ \qmlproperty int QtQuick.Particles2::Emitter::emitCap
+
+ The maximum number of particles at a time that this emitter will have alive.
+
+ This can be set as a performance optimization (when using burst and pulse) or
+ to stagger emissions. The default value is emitRate * lifeSpan in seconds, which
+ is the number of particles that would be alive at any one time given the default settings.
+*/
+/*!
+ \qmlproperty bool QtQuick.Particles2::Emitter::noCap
+
+ If set to true, the emitCap will be ignored and this emitter will never skip emitting
+ a particle based on how many it has alive.
+
+ Default value is false.
+*/
+/*!
+ \qmlproperty int QtQuick.Particles2::Emitter::startTime
+
+ If this value is set when the emitter is loaded, then it will emit particles from the
+ past, up to startTime milliseconds ago. These will simulate as if they were emitted then,
+ but will not have any affectors applied to them. Affectors will take effect from the present time.
+*/
+/*!
+ \qmlproperty real QtQuick.Particles2::Emitter::size
+
+ The size in pixels of the particles at the start of their life.
+
+ Default value is 16.
+*/
+/*!
+ \qmlproperty real QtQuick.Particles2::Emitter::endSize
+
+ The size in pixels of the particles at the end of their life. Size will
+ be linearly interpolated during the life of the particle from this value and
+ size. If endSize is -1, then the size of the particle will remain constant at
+ the starting size.
+
+ Default value is -1.
+*/
+/*!
+ \qmlproperty real QtQuick.Particles2::Emitter::sizeVariation
+
+ The size of a particle can vary by this much up or down from size/endSize. The same
+ random addition is made to both size and endSize for a single particle.
+
+ Default value is 0.
+*/
+/*!
+ \qmlproperty StochasticDirection QtQuick.Particles2::Emitter::speed
+
+ The starting speed of the particles emitted.
+*/
+/*!
+ \qmlproperty StochasticDirection QtQuick.Particles2::Emitter::acceleration
+
+ The starting acceleraton of the particles emitted.
+*/
+/*!
+ \qmlproperty qreal QtQuick.Particles2::Emitter::speedFromMovement
+
+ If this value is non-zero, then any movement of the emitter will provide additional
+ starting velocity to the particles based on the movement. The additional vector will be the
+ same angle as the emitter's movement, with a magnitude that is the magnitude of the emitters
+ movement multiplied by speedFromMovement.
+
+ Default value is 0.
+*/
+//TODO: Document particle 'type'
+/*!
+ \qmlsignal QtQuick.Particles2::Emitter::emitParticle(particle)
+
+ This handler is called when a particle is emitted. You can modify particle
+ attributes from within the handler.
+*/
+
+
QSGParticleEmitter::QSGParticleEmitter(QSGItem *parent) :
QSGItem(parent)
, m_particlesPerSecond(10)
@@ -58,6 +204,13 @@ QSGParticleEmitter::QSGParticleEmitter(QSGItem *parent) :
, m_particleSizeVariation(0)
, m_maxParticleCount(-1)
, m_burstLeft(0)
+ , m_speed_from_movement(0)
+ , m_particle_count(0)
+ , m_reset_last(true)
+ , m_last_timestamp(-1)
+ , m_last_emission(0)
+ , m_startTime(0)
+ , m_overwrite(false)
{
//TODO: Reset speed/acc back to null vector? Or allow null pointer?
@@ -75,6 +228,12 @@ QSGParticleEmitter::~QSGParticleEmitter()
delete m_defaultExtruder;
}
+bool QSGParticleEmitter::isEmitConnected()
+{
+ static int idx = QObjectPrivate::get(this)->signalIndex("emitParticle(QDeclarativeV8Handle)");
+ return QObjectPrivate::get(this)->isSignalConnected(idx);
+}
+
void QSGParticleEmitter::componentComplete()
{
if (!m_system && qobject_cast<QSGParticleSystem*>(parentItem()))
@@ -83,11 +242,6 @@ void QSGParticleEmitter::componentComplete()
qWarning() << "Emitter created without a particle system specified";//TODO: useful QML warnings, like line number?
QSGItem::componentComplete();
}
-void QSGParticleEmitter::emitWindow(int timeStamp)
-{
- Q_UNUSED(timeStamp);
-}
-
void QSGParticleEmitter::setEmitting(bool arg)
{
@@ -155,4 +309,145 @@ int QSGParticleEmitter::particleCount() const
return m_particlesPerSecond*((m_particleDuration+m_particleDurationVariation)/1000.0);
}
+void QSGParticleEmitter::setSpeedFromMovement(qreal t)
+{
+ if (t == m_speed_from_movement)
+ return;
+ m_speed_from_movement = t;
+ emit speedFromMovementChanged();
+}
+
+void QSGParticleEmitter::emitWindow(int timeStamp)
+{
+ if (m_system == 0)
+ return;
+ if ((!m_emitting || !m_particlesPerSecond)&& !m_burstLeft && m_burstQueue.isEmpty()){
+ m_reset_last = true;
+ return;
+ }
+
+ if (m_reset_last) {
+ m_last_emitter = m_last_last_emitter = QPointF(x(), y());
+ if (m_last_timestamp == -1)
+ m_last_timestamp = timeStamp/1000. - m_startTime;
+ else
+ m_last_timestamp = timeStamp/1000.;
+ m_last_emission = m_last_timestamp;
+ m_reset_last = false;
+ }
+
+ if (m_burstLeft){
+ m_burstLeft -= timeStamp - m_last_timestamp * 1000.;
+ if (m_burstLeft < 0){
+ if (!m_emitting)
+ timeStamp += m_burstLeft;
+ m_burstLeft = 0;
+ }
+ }
+
+ qreal time = timeStamp / 1000.;
+
+ qreal particleRatio = 1. / m_particlesPerSecond;
+ qreal pt = m_last_emission;
+
+ qreal opt = pt; // original particle time
+ qreal dt = time - m_last_timestamp; // timestamp delta...
+ if (!dt)
+ dt = 0.000001;
+
+ // emitter difference since last...
+ qreal dex = (x() - m_last_emitter.x());
+ qreal dey = (y() - m_last_emitter.y());
+
+ qreal ax = (m_last_last_emitter.x() + m_last_emitter.x()) / 2;
+ qreal bx = m_last_emitter.x();
+ qreal cx = (x() + m_last_emitter.x()) / 2;
+ qreal ay = (m_last_last_emitter.y() + m_last_emitter.y()) / 2;
+ qreal by = m_last_emitter.y();
+ qreal cy = (y() + m_last_emitter.y()) / 2;
+
+ qreal sizeAtEnd = m_particleEndSize >= 0 ? m_particleEndSize : m_particleSize;
+ qreal emitter_x_offset = m_last_emitter.x() - x();
+ qreal emitter_y_offset = m_last_emitter.y() - y();
+ if (!m_burstQueue.isEmpty() && !m_burstLeft && !m_emitting)//'outside time' emissions only
+ pt = time;
+ while (pt < time || !m_burstQueue.isEmpty()) {
+ //int pos = m_last_particle % m_particle_count;
+ QSGParticleData* datum = m_system->newDatum(m_system->m_groupIds[m_particle], !m_overwrite);
+ if (datum){//actually emit(otherwise we've been asked to skip this one)
+ datum->e = this;//###useful?
+ qreal t = 1 - (pt - opt) / dt;
+ qreal vx =
+ - 2 * ax * (1 - t)
+ + 2 * bx * (1 - 2 * t)
+ + 2 * cx * t;
+ qreal vy =
+ - 2 * ay * (1 - t)
+ + 2 * by * (1 - 2 * t)
+ + 2 * cy * t;
+
+
+ // Particle timestamp
+ datum->t = pt;
+ datum->lifeSpan = //TODO:Promote to base class?
+ (m_particleDuration
+ + ((rand() % ((m_particleDurationVariation*2) + 1)) - m_particleDurationVariation))
+ / 1000.0;
+
+ // Particle position
+ QRectF boundsRect;
+ if (!m_burstQueue.isEmpty()){
+ boundsRect = QRectF(m_burstQueue.first().second.x() - x(), m_burstQueue.first().second.y() - y(),
+ width(), height());
+ } else {
+ boundsRect = QRectF(emitter_x_offset + dex * (pt - opt) / dt, emitter_y_offset + dey * (pt - opt) / dt
+ , width(), height());
+ }
+ QPointF newPos = effectiveExtruder()->extrude(boundsRect);
+ datum->x = newPos.x();
+ datum->y = newPos.y();
+
+ // Particle speed
+ const QPointF &speed = m_speed->sample(newPos);
+ datum->vx = speed.x()
+ + m_speed_from_movement * vx;
+ datum->vy = speed.y()
+ + m_speed_from_movement * vy;
+
+ // Particle acceleration
+ const QPointF &accel = m_acceleration->sample(newPos);
+ datum->ax = accel.x();
+ datum->ay = accel.y();
+
+ // Particle size
+ float sizeVariation = -m_particleSizeVariation
+ + rand() / float(RAND_MAX) * m_particleSizeVariation * 2;
+
+ float size = qMax((qreal)0.0 , m_particleSize + sizeVariation);
+ float endSize = qMax((qreal)0.0 , sizeAtEnd + sizeVariation);
+
+ datum->size = size;// * float(m_emitting);
+ datum->endSize = endSize;// * float(m_emitting);
+
+ if (isEmitConnected())
+ emitParticle(datum->v8Value());//A chance for arbitrary JS changes
+ m_system->emitParticle(datum);
+ }
+ if (m_burstQueue.isEmpty()){
+ pt += particleRatio;
+ }else{
+ m_burstQueue.first().first--;
+ if (m_burstQueue.first().first <= 0)
+ m_burstQueue.pop_front();
+ }
+ }
+ m_last_emission = pt;
+
+ m_last_last_last_emitter = m_last_last_emitter;
+ m_last_last_emitter = m_last_emitter;
+ m_last_emitter = QPointF(x(), y());
+ m_last_timestamp = time;
+}
+
+
QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgparticleemitter_p.h b/src/declarative/particles/qsgparticleemitter_p.h
index 9cf130d40d..2c75fbfe22 100644
--- a/src/declarative/particles/qsgparticleemitter_p.h
+++ b/src/declarative/particles/qsgparticleemitter_p.h
@@ -64,6 +64,8 @@ class QSGParticleEmitter : public QSGItem
Q_PROPERTY(QString particle READ particle WRITE setParticle NOTIFY particleChanged)
Q_PROPERTY(QSGParticleExtruder* shape READ extruder WRITE setExtruder NOTIFY extruderChanged)
Q_PROPERTY(bool emitting READ emitting WRITE setEmitting NOTIFY emittingChanged)
+ Q_PROPERTY(int startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged)
+ Q_PROPERTY(bool noCap READ overwrite WRITE setOverWrite NOTIFY overwriteChanged)
Q_PROPERTY(qreal emitRate READ particlesPerSecond WRITE setParticlesPerSecond NOTIFY particlesPerSecondChanged)
Q_PROPERTY(int lifeSpan READ particleDuration WRITE setParticleDuration NOTIFY particleDurationChanged)
@@ -76,6 +78,8 @@ class QSGParticleEmitter : public QSGItem
Q_PROPERTY(QSGStochasticDirection *speed READ speed WRITE setSpeed NOTIFY speedChanged)
Q_PROPERTY(QSGStochasticDirection *acceleration READ acceleration WRITE setAcceleration NOTIFY accelerationChanged)
+ Q_PROPERTY(qreal speedFromMovement READ speedFromMovement WRITE setSpeedFromMovement NOTIFY speedFromMovementChanged)
+
public:
explicit QSGParticleEmitter(QSGItem *parent = 0);
virtual ~QSGParticleEmitter();
@@ -111,8 +115,11 @@ public:
return m_particleDurationVariation;
}
+ qreal speedFromMovement() const { return m_speed_from_movement; }
+ void setSpeedFromMovement(qreal s);
virtual void componentComplete();
signals:
+ void emitParticle(QDeclarativeV8Handle particle);
void particlesPerSecondChanged(qreal);
void particleDurationChanged(int);
void emittingChanged(bool);
@@ -138,6 +145,12 @@ signals:
void maxParticleCountChanged(int arg);
void particleCountChanged();
+ void speedFromMovementChanged();
+
+ void startTimeChanged(int arg);
+
+ void overwriteChanged(bool arg);
+
public slots:
void pulse(qreal seconds);
void burst(int num);
@@ -235,6 +248,22 @@ public slots:
void setMaxParticleCount(int arg);
+ void setStartTime(int arg)
+ {
+ if (m_startTime != arg) {
+ m_startTime = arg;
+ emit startTimeChanged(arg);
+ }
+ }
+
+ void setOverWrite(bool arg)
+{
+ if (m_overwrite != arg) {
+ m_overwrite = arg;
+emit overwriteChanged(arg);
+}
+}
+
public:
int particleCount() const;
@@ -274,6 +303,16 @@ public:
return m_maxParticleCount;
}
+ int startTime() const
+ {
+ return m_startTime;
+ }
+
+ bool overwrite() const
+ {
+ return m_overwrite;
+ }
+
protected:
qreal m_particlesPerSecond;
int m_particleDuration;
@@ -290,11 +329,30 @@ protected:
qreal m_particleEndSize;
qreal m_particleSizeVariation;
+ qreal m_speedFromMovement;
+ int m_startTime;
+ bool m_overwrite;
+
int m_burstLeft;//TODO: Rename to pulse
QList<QPair<int, QPointF > > m_burstQueue;
int m_maxParticleCount;
+
+ //Used in default implementation, but might be useful
+ qreal m_speed_from_movement;
+
+ int m_particle_count;
+ bool m_reset_last;
+ qreal m_last_timestamp;
+ qreal m_last_emission;
+
+ QPointF m_last_emitter;
+ QPointF m_last_last_emitter;
+ QPointF m_last_last_last_emitter;
+
+ bool isEmitConnected();
private:
QSGStochasticDirection m_nullVector;
+
};
QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgparticleextruder.cpp b/src/declarative/particles/qsgparticleextruder.cpp
index b51ab8b467..a390bb92ac 100644
--- a/src/declarative/particles/qsgparticleextruder.cpp
+++ b/src/declarative/particles/qsgparticleextruder.cpp
@@ -46,7 +46,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass Shape QSGParticleExtruder
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\brief The Shape element allows you to specify an area for affectors and emitter.
The base class is just a rectangle.
diff --git a/src/declarative/particles/qsgparticlepainter.cpp b/src/declarative/particles/qsgparticlepainter.cpp
index 4d795999a0..97333ff20b 100644
--- a/src/declarative/particles/qsgparticlepainter.cpp
+++ b/src/declarative/particles/qsgparticlepainter.cpp
@@ -45,7 +45,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass ParticlePainter QSGParticlePainter
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits ParticlePainter
\brief ParticlePainter elements allow you to specify how to paint particles.
diff --git a/src/declarative/particles/qsgparticlesmodule.cpp b/src/declarative/particles/qsgparticlesmodule.cpp
index 1bb06eae35..e6076b925f 100644
--- a/src/declarative/particles/qsgparticlesmodule.cpp
+++ b/src/declarative/particles/qsgparticlesmodule.cpp
@@ -42,7 +42,6 @@
#include "qsgangleddirection_p.h"
#include "qsgcustomparticle_p.h"
#include "qsgellipseextruder_p.h"
-#include "qsgemitter_p.h"
#include "qsgfollowemitter_p.h"
#include "qsgfriction_p.h"
#include "qsggravity_p.h"
@@ -67,20 +66,12 @@
#include "qsgwander_p.h"
#include "qsgtargetaffector_p.h"
#include "qsgcumulativedirection_p.h"
-#include "qsgcustomemitter_p.h"
-#include "qsgcustomaffector_p.h"
QT_BEGIN_NAMESPACE
void QSGParticlesModule::defineModule()
{
const char* uri = "QtQuick.Particles";
- //Debugging only exposition
- qmlRegisterType<QSGParticlePainter>(uri, 2, 0, "ParticlePainter");
- qmlRegisterType<QSGParticleEmitter>(uri, 2, 0, "ParticleEmitter");
- qmlRegisterType<QSGParticleExtruder>(uri, 2, 0, "ParticleExtruder");
- qmlRegisterType<QSGStochasticDirection>(uri, 2, 0, "NullVector");
- //Probably should be nocreate types
qmlRegisterType<QSGParticleSystem>(uri, 2, 0, "ParticleSystem");
@@ -89,8 +80,7 @@ void QSGParticlesModule::defineModule()
qmlRegisterType<QSGItemParticle>(uri, 2, 0, "ItemParticle");
qmlRegisterType<QSGModelParticle>(uri, 2, 0, "ModelParticle");
- qmlRegisterType<QSGBasicEmitter>(uri, 2, 0, "Emitter");//TODO: Rename BasicEmitter?
- qmlRegisterType<QSGCustomEmitter>(uri, 2, 0, "CustomEmitter");
+ qmlRegisterType<QSGParticleEmitter>(uri, 2, 0, "Emitter");
qmlRegisterType<QSGFollowEmitter>(uri, 2, 0, "FollowEmitter");
qmlRegisterType<QSGEllipseExtruder>(uri, 2, 0, "EllipseShape");
@@ -103,7 +93,6 @@ void QSGParticlesModule::defineModule()
qmlRegisterType<QSGCumulativeDirection>(uri, 2, 0, "CumulativeDirection");
qmlRegisterType<QSGParticleAffector>(uri, 2, 0, "Affector");//useful for the triggered signal
- qmlRegisterType<QSGCustomAffector>(uri, 2, 0, "CustomAffector");
qmlRegisterType<QSGWanderAffector>(uri, 2, 0, "Wander");
qmlRegisterType<QSGFrictionAffector>(uri, 2, 0, "Friction");
qmlRegisterType<QSGPointAttractorAffector>(uri, 2, 0, "PointAttractor");
@@ -112,6 +101,11 @@ void QSGParticlesModule::defineModule()
qmlRegisterType<QSGSpriteGoalAffector>(uri, 2, 0, "SpriteGoal");
qmlRegisterType<QSGTurbulenceAffector>(uri, 2, 0 , "Turbulence");
qmlRegisterType<QSGTargetAffector>(uri, 2, 0 , "Target");
+
+ //Exposed just for completeness
+ qmlRegisterType<QSGParticlePainter>(uri, 2, 0, "ParticlePainter");
+ qmlRegisterType<QSGParticleExtruder>(uri, 2, 0, "ParticleExtruder");
+ qmlRegisterType<QSGStochasticDirection>(uri, 2, 0, "NullVector");
}
QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgparticlesystem.cpp b/src/declarative/particles/qsgparticlesystem.cpp
index f48156315c..efd6c22bd9 100644
--- a/src/declarative/particles/qsgparticlesystem.cpp
+++ b/src/declarative/particles/qsgparticlesystem.cpp
@@ -57,7 +57,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass ParticleSystem QSGParticleSystem
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\brief The ParticleSystem brings together ParticlePainter, Emitter and Affector elements.
*/
@@ -478,7 +477,7 @@ float QSGParticleData::curSize()
{
if (!system || !lifeSpan)
return 0.0f;
- return size + (endSize - size) * (lifeLeft() / lifeSpan);
+ return size + (endSize - size) * (1 - (lifeLeft() / lifeSpan));
}
float QSGParticleData::lifeLeft()
diff --git a/src/declarative/particles/qsgpointattractor.cpp b/src/declarative/particles/qsgpointattractor.cpp
index cc4cac66a4..1a3c3c25c5 100644
--- a/src/declarative/particles/qsgpointattractor.cpp
+++ b/src/declarative/particles/qsgpointattractor.cpp
@@ -46,7 +46,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass PointAttractor QSGPointAttractorAffector
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits Affector
\brief The PointAttractor allows you to attract particles towards a specific point.
diff --git a/src/declarative/particles/qsgpointattractor_p.h b/src/declarative/particles/qsgpointattractor_p.h
index 932a3081d6..95716483ed 100644
--- a/src/declarative/particles/qsgpointattractor_p.h
+++ b/src/declarative/particles/qsgpointattractor_p.h
@@ -55,7 +55,7 @@ class QSGPointAttractorAffector : public QSGParticleAffector
//Like Gravitational singularity, but linear to distance instead of quadratic
//And affects ds/dt, not da/dt
Q_PROPERTY(qreal strength READ strength WRITE setStrength NOTIFY strengthChanged)
- Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
+ Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)//TODO: Change to pointX, pointY
Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
Q_PROPERTY(PhysicsAffects physics READ physics WRITE setPhysics NOTIFY physicsChanged)
Q_PROPERTY(Proportion proportionalToDistance READ proportionalToDistance WRITE setProportionalToDistance NOTIFY proportionalToDistanceChanged)
diff --git a/src/declarative/particles/qsgpointdirection.cpp b/src/declarative/particles/qsgpointdirection.cpp
index 0448ac9a7e..7cc0823eec 100644
--- a/src/declarative/particles/qsgpointdirection.cpp
+++ b/src/declarative/particles/qsgpointdirection.cpp
@@ -46,7 +46,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass PointDirection QSGPointDirection
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits StochasticDirection
\brief The PointDirection element allows you to specify a direction that varies in x and y components
diff --git a/src/declarative/particles/qsgspritegoal.cpp b/src/declarative/particles/qsgspritegoal.cpp
index 79fcf8188c..1837167813 100644
--- a/src/declarative/particles/qsgspritegoal.cpp
+++ b/src/declarative/particles/qsgspritegoal.cpp
@@ -50,7 +50,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass SpriteGoal QSGSpriteGoalAffector
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits Affector
\brief The SpriteGoal Affector allows you to change the state of a sprite or group of a particle.
diff --git a/src/declarative/particles/qsgstochasticdirection.cpp b/src/declarative/particles/qsgstochasticdirection.cpp
index f44b941578..cdbc9f15ad 100644
--- a/src/declarative/particles/qsgstochasticdirection.cpp
+++ b/src/declarative/particles/qsgstochasticdirection.cpp
@@ -45,7 +45,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass StochasticDirection QSGStochasticDirection
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\brief The StochasticDirection elements allow you to specify a vector space.
*/
diff --git a/src/declarative/particles/qsgtargeteddirection.cpp b/src/declarative/particles/qsgtargeteddirection.cpp
index 3e5d3e1628..696cdfa915 100644
--- a/src/declarative/particles/qsgtargeteddirection.cpp
+++ b/src/declarative/particles/qsgtargeteddirection.cpp
@@ -48,7 +48,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass TargetedDirection QSGTargetedDirection
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits StochasticDirection
\brief The TargetedDirection element allows you to specify a direction towards the target point
diff --git a/src/declarative/particles/qsgturbulence.cpp b/src/declarative/particles/qsgturbulence.cpp
index e9812d7825..003f3c12b6 100644
--- a/src/declarative/particles/qsgturbulence.cpp
+++ b/src/declarative/particles/qsgturbulence.cpp
@@ -49,7 +49,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass Turbulence QSGTurbulenceAffector
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits Affector
\brief The TurbulenceAffector is a bit of a hack and probably shouldn't be used yet.
diff --git a/src/declarative/particles/qsgwander.cpp b/src/declarative/particles/qsgwander.cpp
index 2d04d62eba..a4a4d2c9c5 100644
--- a/src/declarative/particles/qsgwander.cpp
+++ b/src/declarative/particles/qsgwander.cpp
@@ -45,7 +45,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass Wander QSGWanderAffector
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits Affector
\brief The Wander affector allows particles to randomly vary their trajectory.
diff --git a/src/declarative/qml/qdeclarative.h b/src/declarative/qml/qdeclarative.h
index 4c962f890e..311ecd31ca 100644
--- a/src/declarative/qml/qdeclarative.h
+++ b/src/declarative/qml/qdeclarative.h
@@ -550,6 +550,17 @@ inline int qmlRegisterModuleApi(const char *uri, int versionMajor, int versionMi
return QDeclarativePrivate::qmlregister(QDeclarativePrivate::ModuleApiRegistration, &api);
}
+// Enable debugging before any QDeclarativeEngine is created
+struct Q_DECLARATIVE_EXPORT QDeclarativeDebuggingEnabler
+{
+ QDeclarativeDebuggingEnabler();
+};
+
+// Execute code in constructor before first QDeclarativeEngine is instantiated
+#if defined(QT_DECLARATIVE_DEBUG)
+static QDeclarativeDebuggingEnabler qmlEnableDebuggingHelper;
+#endif
+
QT_END_NAMESPACE
QML_DECLARE_TYPE(QObject)
diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp
index 5e1d3f60a9..7cc8422ddd 100644
--- a/src/declarative/qml/qdeclarativecompiler.cpp
+++ b/src/declarative/qml/qdeclarativecompiler.cpp
@@ -312,6 +312,13 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop,
if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: 3D vector expected"));
}
break;
+ case QVariant::Vector4D:
+ {
+ bool ok;
+ QDeclarativeStringConverters::vector4DFromString(string, &ok);
+ if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: 4D vector expected"));
+ }
+ break;
default:
{
int t = prop.userType();
@@ -467,7 +474,7 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop,
instr.storeDateTime.propertyIndex = prop.propertyIndex();
instr.storeDateTime.date = dateTime.date().toJulianDay();
Q_ASSERT(sizeof(instr.storeDateTime.time) == sizeof(QTime));
- ::memcmp(&instr.storeDateTime.time, &time, sizeof(QTime));
+ ::memcpy(&instr.storeDateTime.time, &time, sizeof(QTime));
}
break;
#endif // QT_NO_DATESTRING
@@ -554,6 +561,18 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop,
instr.storeVector3D.vector.zp = vector.z();
}
break;
+ case QVariant::Vector4D:
+ {
+ bool ok;
+ QVector4D vector = QDeclarativeStringConverters::vector4DFromString(string, &ok);
+ instr.setType(QDeclarativeInstruction::StoreVector4D);
+ instr.storeVector4D.propertyIndex = prop.propertyIndex();
+ instr.storeVector4D.vector.xp = vector.x();
+ instr.storeVector4D.vector.yp = vector.y();
+ instr.storeVector4D.vector.zp = vector.z();
+ instr.storeVector4D.vector.wp = vector.w();
+ }
+ break;
default:
{
int t = prop.userType();
@@ -856,6 +875,9 @@ bool QDeclarativeCompiler::buildObject(QDeclarativeParser::Object *obj, const Bi
int ids = compileState.ids.count();
COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
canDefer = ids == compileState.ids.count();
+ } else if (isSignalPropertyName(prop->name) &&
+ (cp->flags() & QDeclarativeCustomParser::AcceptsSignalHandlers)) {
+ COMPILE_CHECK(buildSignal(prop,obj,objCtxt));
} else {
customProps << QDeclarativeCustomParserNodePrivate::fromProperty(prop);
}
@@ -2378,25 +2400,27 @@ bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj)
}
for (int ii = 0; ii < obj->dynamicSignals.count(); ++ii) {
- QByteArray name = obj->dynamicSignals.at(ii).name;
+ const QDeclarativeParser::Object::DynamicSignal &currSig = obj->dynamicSignals.at(ii);
+ QByteArray name = currSig.name;
if (methodNames.contains(name))
- COMPILE_EXCEPTION(obj, tr("Duplicate signal name"));
+ COMPILE_EXCEPTION(&currSig, tr("Duplicate signal name"));
QString nameStr = QString::fromUtf8(name);
if (nameStr.at(0).isUpper())
- COMPILE_EXCEPTION(obj, tr("Signal names cannot begin with an upper case letter"));
+ COMPILE_EXCEPTION(&currSig, tr("Signal names cannot begin with an upper case letter"));
if (enginePrivate->v8engine()->illegalNames().contains(nameStr))
- COMPILE_EXCEPTION(obj, tr("Illegal signal name"));
+ COMPILE_EXCEPTION(&currSig, tr("Illegal signal name"));
methodNames.insert(name);
}
for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) {
- QByteArray name = obj->dynamicSlots.at(ii).name;
+ const QDeclarativeParser::Object::DynamicSlot &currSlot = obj->dynamicSlots.at(ii);
+ QByteArray name = currSlot.name;
if (methodNames.contains(name))
- COMPILE_EXCEPTION(obj, tr("Duplicate method name"));
+ COMPILE_EXCEPTION(&currSlot, tr("Duplicate method name"));
QString nameStr = QString::fromUtf8(name);
if (nameStr.at(0).isUpper())
- COMPILE_EXCEPTION(obj, tr("Method names cannot begin with an upper case letter"));
+ COMPILE_EXCEPTION(&currSlot, tr("Method names cannot begin with an upper case letter"));
if (enginePrivate->v8engine()->illegalNames().contains(nameStr))
- COMPILE_EXCEPTION(obj, tr("Illegal method name"));
+ COMPILE_EXCEPTION(&currSlot, tr("Illegal method name"));
methodNames.insert(name);
}
@@ -2747,6 +2771,7 @@ bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder,
int propIdx = -1;
int flags = 0;
bool writable = false;
+ bool resettable = false;
if (alias.count() == 2 || alias.count() == 3) {
propIdx = indexOfProperty(idObject, alias.at(1).toUtf8());
@@ -2761,6 +2786,7 @@ bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder,
COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location"));
writable = aliasProperty.isWritable();
+ resettable = aliasProperty.isResettable();
if (alias.count() == 3) {
QDeclarativeValueType *valueType = enginePrivate->valueTypes[aliasProperty.type()];
@@ -2805,6 +2831,7 @@ bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder,
QMetaPropertyBuilder propBuilder =
builder.addProperty(prop.name, typeName.constData(), builder.methodCount() - 1);
propBuilder.setWritable(writable);
+ propBuilder.setResettable(resettable);
return true;
}
diff --git a/src/declarative/qml/qdeclarativecustomparser_p.h b/src/declarative/qml/qdeclarativecustomparser_p.h
index ab66b9fcdc..31452836bd 100644
--- a/src/declarative/qml/qdeclarativecustomparser_p.h
+++ b/src/declarative/qml/qdeclarativecustomparser_p.h
@@ -116,7 +116,8 @@ class Q_DECLARATIVE_EXPORT QDeclarativeCustomParser
public:
enum Flag {
NoFlag = 0x00000000,
- AcceptsAttachedProperties = 0x00000001
+ AcceptsAttachedProperties = 0x00000001,
+ AcceptsSignalHandlers = 0x00000002
};
Q_DECLARE_FLAGS(Flags, Flag)
diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp
index 4781264bde..1906612e8a 100644
--- a/src/declarative/qml/qdeclarativeengine.cpp
+++ b/src/declarative/qml/qdeclarativeengine.cpp
@@ -67,7 +67,7 @@
#include "private/qdeclarativenotifier_p.h"
#include "private/qdeclarativedebugtrace_p.h"
#include "private/qdeclarativeapplication_p.h"
-#include "private/qjsdebugservice_p.h"
+#include "private/qv8debugservice_p.h"
#include <QtCore/qmetaobject.h>
#include <QNetworkReply>
@@ -175,12 +175,6 @@ void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
\endcode
*/
-struct StaticQtMetaObject : public QObject
-{
- static const QMetaObject *get()
- { return &static_cast<StaticQtMetaObject*> (0)->staticQtMetaObject; }
-};
-
static bool qt_QmlQtModule_registered = false;
bool QDeclarativeEnginePrivate::qml_debugging_enabled = false;
@@ -457,7 +451,7 @@ void QDeclarativeEnginePrivate::init()
QDeclarativeEngineDebugServer::isDebuggingEnabled()) {
isDebugging = true;
QDeclarativeEngineDebugServer::instance()->addEngine(q);
- QJSDebugService::instance()->addEngine(q);
+ QV8DebugService::instance()->addEngine(q);
}
}
@@ -992,6 +986,17 @@ QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
return qmlAttachedPropertiesObjectById(*idCache, object, create);
}
+QDeclarativeDebuggingEnabler::QDeclarativeDebuggingEnabler()
+{
+#ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL
+ if (!QDeclarativeEnginePrivate::qml_debugging_enabled) {
+ qWarning("Qml debugging is enabled. Only use this in a safe environment!");
+ }
+ QDeclarativeEnginePrivate::qml_debugging_enabled = true;
+#endif
+}
+
+
class QDeclarativeDataExtended {
public:
QDeclarativeDataExtended();
diff --git a/src/declarative/qml/qdeclarativeinstruction.cpp b/src/declarative/qml/qdeclarativeinstruction.cpp
index f99351bde5..f5bd6e915a 100644
--- a/src/declarative/qml/qdeclarativeinstruction.cpp
+++ b/src/declarative/qml/qdeclarativeinstruction.cpp
@@ -132,6 +132,9 @@ void QDeclarativeCompiledData::dump(QDeclarativeInstruction *instr, int idx)
case QDeclarativeInstruction::StoreVector3D:
qWarning().nospace() << idx << "\t\t" << "STORE_VECTOR3D\t\t" << instr->storeVector3D.propertyIndex << "\t" << instr->storeVector3D.vector.xp << "\t" << instr->storeVector3D.vector.yp << "\t" << instr->storeVector3D.vector.zp;
break;
+ case QDeclarativeInstruction::StoreVector4D:
+ qWarning().nospace() << idx << "\t\t" << "STORE_VECTOR4D\t\t" << instr->storeVector4D.propertyIndex << "\t" << instr->storeVector4D.vector.xp << "\t" << instr->storeVector4D.vector.yp << "\t" << instr->storeVector4D.vector.zp << "\t" << instr->storeVector4D.vector.wp;
+ break;
case QDeclarativeInstruction::StoreVariant:
qWarning().nospace() << idx << "\t\t" << "STORE_VARIANT\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value);
break;
diff --git a/src/declarative/qml/qdeclarativeinstruction_p.h b/src/declarative/qml/qdeclarativeinstruction_p.h
index a48c44c32e..f98002766a 100644
--- a/src/declarative/qml/qdeclarativeinstruction_p.h
+++ b/src/declarative/qml/qdeclarativeinstruction_p.h
@@ -88,6 +88,7 @@ QT_BEGIN_NAMESPACE
F(StoreRect, storeRect) \
F(StoreRectF, storeRectF) \
F(StoreVector3D, storeVector3D) \
+ F(StoreVector4D, storeVector4D) \
F(StoreObject, storeObject) \
F(AssignCustomType, assignCustomType) \
F(AssignSignalObject, assignSignalObject) \
@@ -405,6 +406,16 @@ union QDeclarativeInstruction
float zp;
} vector;
};
+ struct instr_storeVector4D {
+ QML_INSTR_HEADER
+ int propertyIndex;
+ struct QVector4D {
+ float xp;
+ float yp;
+ float zp;
+ float wp;
+ } vector;
+ };
instr_common common;
instr_init init;
@@ -440,6 +451,7 @@ union QDeclarativeInstruction
instr_storeRect storeRect;
instr_storeRectF storeRectF;
instr_storeVector3D storeVector3D;
+ instr_storeVector4D storeVector4D;
instr_storeObject storeObject;
instr_assignCustomType assignCustomType;
instr_storeSignal storeSignal;
diff --git a/src/declarative/qml/qdeclarativeparser.cpp b/src/declarative/qml/qdeclarativeparser.cpp
index 0447ea3227..a405022a71 100644
--- a/src/declarative/qml/qdeclarativeparser.cpp
+++ b/src/declarative/qml/qdeclarativeparser.cpp
@@ -191,7 +191,7 @@ QDeclarativeParser::Object::DynamicSignal::DynamicSignal()
QDeclarativeParser::Object::DynamicSignal::DynamicSignal(const DynamicSignal &o)
: name(o.name), parameterTypes(o.parameterTypes),
- parameterNames(o.parameterNames)
+ parameterNames(o.parameterNames), location(o.location)
{
}
diff --git a/src/declarative/qml/qdeclarativeparser_p.h b/src/declarative/qml/qdeclarativeparser_p.h
index 59c41ef8de..7080a8daee 100644
--- a/src/declarative/qml/qdeclarativeparser_p.h
+++ b/src/declarative/qml/qdeclarativeparser_p.h
@@ -212,6 +212,7 @@ namespace QDeclarativeParser
QByteArray name;
QList<QByteArray> parameterTypes;
QList<QByteArray> parameterNames;
+ LocationSpan location;
};
struct DynamicSlot {
DynamicSlot();
diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp
index 98c758267d..3406109a28 100644
--- a/src/declarative/qml/qdeclarativeproperty.cpp
+++ b/src/declarative/qml/qdeclarativeproperty.cpp
@@ -399,7 +399,7 @@ const char *QDeclarativeProperty::propertyTypeName() const
return 0;
if (d->isValueType()) {
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(d->engine);
+ QDeclarativeEnginePrivate *ep = d->engine?QDeclarativeEnginePrivate::get(d->engine):0;
QDeclarativeValueType *valueType = 0;
if (ep) valueType = ep->valueTypes[d->core.propType];
else valueType = QDeclarativeValueTypeFactory::valueType(d->core.propType);
@@ -987,7 +987,7 @@ QVariant QDeclarativePropertyPrivate::readValueProperty()
{
if (isValueType()) {
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
+ QDeclarativeEnginePrivate *ep = engine?QDeclarativeEnginePrivate::get(engine):0;
QDeclarativeValueType *valueType = 0;
if (ep) valueType = ep->valueTypes[core.propType];
else valueType = QDeclarativeValueTypeFactory::valueType(core.propType);
@@ -1072,7 +1072,7 @@ bool QDeclarativePropertyPrivate::writeValueProperty(const QVariant &value, Writ
bool rv = false;
if (isValueType()) {
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
+ QDeclarativeEnginePrivate *ep = engine?QDeclarativeEnginePrivate::get(engine):0;
QDeclarativeValueType *writeBack = 0;
if (ep) {
diff --git a/src/declarative/qml/qdeclarativescriptparser.cpp b/src/declarative/qml/qdeclarativescriptparser.cpp
index 3f843295d7..dcd12e287a 100644
--- a/src/declarative/qml/qdeclarativescriptparser.cpp
+++ b/src/declarative/qml/qdeclarativescriptparser.cpp
@@ -528,6 +528,7 @@ bool ProcessAST::visit(AST::UiPublicMember *node)
p = p->finish();
}
+ signal.location = location(node->typeToken, node->semicolonToken);
_stateStack.top().object->dynamicSignals << signal;
} else {
const QString memberType = node->memberType->asString();
diff --git a/src/declarative/qml/qdeclarativestringconverters.cpp b/src/declarative/qml/qdeclarativestringconverters.cpp
index d7cfe2eca3..b949adf5ec 100644
--- a/src/declarative/qml/qdeclarativestringconverters.cpp
+++ b/src/declarative/qml/qdeclarativestringconverters.cpp
@@ -43,6 +43,7 @@
#include <QtGui/qcolor.h>
#include <QtGui/qvector3d.h>
+#include <QtGui/qvector4d.h>
#include <QtCore/qpoint.h>
#include <QtCore/qrect.h>
#include <QtCore/qsize.h>
@@ -93,6 +94,8 @@ QVariant QDeclarativeStringConverters::variantFromString(const QString &s)
if (ok) return QVariant(sz);
QVector3D v = vector3DFromString(s, &ok);
if (ok) return QVariant::fromValue(v);
+ QVector4D v4 = vector4DFromString(s, &ok);
+ if (ok) return QVariant::fromValue(v4);
return QVariant(s);
}
@@ -128,6 +131,8 @@ QVariant QDeclarativeStringConverters::variantFromString(const QString &s, int p
return QVariant::fromValue(rectFFromString(s, ok).toRect());
case QMetaType::QVector3D:
return QVariant::fromValue(vector3DFromString(s, ok));
+ case QMetaType::QVector4D:
+ return QVariant::fromValue(vector4DFromString(s, ok));
default:
if (ok) *ok = false;
return QVariant();
@@ -275,4 +280,32 @@ QVector3D QDeclarativeStringConverters::vector3DFromString(const QString &s, boo
return QVector3D(xCoord, yCoord, zCoord);
}
+//expects input of "x,y,z,w"
+QVector4D QDeclarativeStringConverters::vector4DFromString(const QString &s, bool *ok)
+{
+ if (s.count(QLatin1Char(',')) != 3) {
+ if (ok)
+ *ok = false;
+ return QVector4D();
+ }
+
+ bool xGood, yGood, zGood, wGood;
+ int index = s.indexOf(QLatin1Char(','));
+ int index2 = s.indexOf(QLatin1Char(','), index+1);
+ int index3 = s.indexOf(QLatin1Char(','), index2+1);
+ qreal xCoord = s.left(index).toDouble(&xGood);
+ qreal yCoord = s.mid(index+1, index2-index-1).toDouble(&yGood);
+ qreal zCoord = s.mid(index2+1, index3-index2-1).toDouble(&zGood);
+ qreal wCoord = s.mid(index3+1).toDouble(&wGood);
+ if (!xGood || !yGood || !zGood || !wGood) {
+ if (ok)
+ *ok = false;
+ return QVector4D();
+ }
+
+ if (ok)
+ *ok = true;
+ return QVector4D(xCoord, yCoord, zCoord, wCoord);
+}
+
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativestringconverters_p.h b/src/declarative/qml/qdeclarativestringconverters_p.h
index a8c63595fc..2f93cd72f9 100644
--- a/src/declarative/qml/qdeclarativestringconverters_p.h
+++ b/src/declarative/qml/qdeclarativestringconverters_p.h
@@ -67,6 +67,7 @@ class QRectF;
class QString;
class QByteArray;
class QVector3D;
+class QVector4D;
// XXX - Bauhaus currently uses these methods which is why they're exported
namespace QDeclarativeStringConverters
@@ -84,6 +85,7 @@ namespace QDeclarativeStringConverters
QSizeF Q_DECLARATIVE_PRIVATE_EXPORT sizeFFromString(const QString &, bool *ok = 0);
QRectF Q_DECLARATIVE_PRIVATE_EXPORT rectFFromString(const QString &, bool *ok = 0);
QVector3D Q_DECLARATIVE_PRIVATE_EXPORT vector3DFromString(const QString &, bool *ok = 0);
+ QVector4D Q_DECLARATIVE_PRIVATE_EXPORT vector4DFromString(const QString &, bool *ok = 0);
}
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativevaluetype.cpp b/src/declarative/qml/qdeclarativevaluetype.cpp
index 7f77388516..3e77f4b503 100644
--- a/src/declarative/qml/qdeclarativevaluetype.cpp
+++ b/src/declarative/qml/qdeclarativevaluetype.cpp
@@ -152,6 +152,9 @@ QDeclarativeValueType *QDeclarativeValueTypeFactory::valueType(int t)
case QVariant::Font:
rv = new QDeclarativeFontValueType;
break;
+ case QVariant::Color:
+ rv = new QDeclarativeColorValueType;
+ break;
default:
break;
}
@@ -193,6 +196,16 @@ void QDeclarativePointFValueType::setValue(QVariant value)
point = qvariant_cast<QPointF>(value);
}
+QString QDeclarativePointFValueType::toString() const
+{
+ return QString(QLatin1String("QPointF(%1, %2)")).arg(point.x()).arg(point.y());
+}
+
+bool QDeclarativePointFValueType::isEqual(const QVariant &value) const
+{
+ return (QVariant(point) == value);
+}
+
qreal QDeclarativePointFValueType::x() const
{
return point.x();
@@ -241,6 +254,16 @@ void QDeclarativePointValueType::setValue(QVariant value)
point = qvariant_cast<QPoint>(value);
}
+QString QDeclarativePointValueType::toString() const
+{
+ return QString(QLatin1String("QPoint(%1, %2)")).arg(point.x()).arg(point.y());
+}
+
+bool QDeclarativePointValueType::isEqual(const QVariant &value) const
+{
+ return (QVariant(point) == value);
+}
+
int QDeclarativePointValueType::x() const
{
return point.x();
@@ -289,6 +312,16 @@ void QDeclarativeSizeFValueType::setValue(QVariant value)
size = qvariant_cast<QSizeF>(value);
}
+QString QDeclarativeSizeFValueType::toString() const
+{
+ return QString(QLatin1String("QSizeF(%1, %2)")).arg(size.width()).arg(size.height());
+}
+
+bool QDeclarativeSizeFValueType::isEqual(const QVariant &value) const
+{
+ return (QVariant(size) == value);
+}
+
qreal QDeclarativeSizeFValueType::width() const
{
return size.width();
@@ -337,6 +370,16 @@ void QDeclarativeSizeValueType::setValue(QVariant value)
size = qvariant_cast<QSize>(value);
}
+QString QDeclarativeSizeValueType::toString() const
+{
+ return QString(QLatin1String("QSize(%1, %2)")).arg(size.width()).arg(size.height());
+}
+
+bool QDeclarativeSizeValueType::isEqual(const QVariant &value) const
+{
+ return (QVariant(size) == value);
+}
+
int QDeclarativeSizeValueType::width() const
{
return size.width();
@@ -385,6 +428,16 @@ void QDeclarativeRectFValueType::setValue(QVariant value)
rect = qvariant_cast<QRectF>(value);
}
+QString QDeclarativeRectFValueType::toString() const
+{
+ return QString(QLatin1String("QRectF(%1, %2, %3, %4)")).arg(rect.x()).arg(rect.y()).arg(rect.width()).arg(rect.height());
+}
+
+bool QDeclarativeRectFValueType::isEqual(const QVariant &value) const
+{
+ return (QVariant(rect) == value);
+}
+
qreal QDeclarativeRectFValueType::x() const
{
return rect.x();
@@ -453,6 +506,16 @@ void QDeclarativeRectValueType::setValue(QVariant value)
rect = qvariant_cast<QRect>(value);
}
+QString QDeclarativeRectValueType::toString() const
+{
+ return QString(QLatin1String("QRect(%1, %2, %3, %4)")).arg(rect.x()).arg(rect.y()).arg(rect.width()).arg(rect.height());
+}
+
+bool QDeclarativeRectValueType::isEqual(const QVariant &value) const
+{
+ return (QVariant(rect) == value);
+}
+
int QDeclarativeRectValueType::x() const
{
return rect.x();
@@ -521,6 +584,16 @@ void QDeclarativeVector2DValueType::setValue(QVariant value)
vector = qvariant_cast<QVector2D>(value);
}
+QString QDeclarativeVector2DValueType::toString() const
+{
+ return QString(QLatin1String("QVector2D(%1, %2)")).arg(vector.x()).arg(vector.y());
+}
+
+bool QDeclarativeVector2DValueType::isEqual(const QVariant &value) const
+{
+ return (QVariant(vector) == value);
+}
+
qreal QDeclarativeVector2DValueType::x() const
{
return vector.x();
@@ -569,6 +642,16 @@ void QDeclarativeVector3DValueType::setValue(QVariant value)
vector = qvariant_cast<QVector3D>(value);
}
+QString QDeclarativeVector3DValueType::toString() const
+{
+ return QString(QLatin1String("QVector3D(%1, %2, %3)")).arg(vector.x()).arg(vector.y()).arg(vector.z());
+}
+
+bool QDeclarativeVector3DValueType::isEqual(const QVariant &value) const
+{
+ return (QVariant(vector) == value);
+}
+
qreal QDeclarativeVector3DValueType::x() const
{
return vector.x();
@@ -627,6 +710,16 @@ void QDeclarativeVector4DValueType::setValue(QVariant value)
vector = qvariant_cast<QVector4D>(value);
}
+QString QDeclarativeVector4DValueType::toString() const
+{
+ return QString(QLatin1String("QVector4D(%1, %2, %3, %4)")).arg(vector.x()).arg(vector.y()).arg(vector.z()).arg(vector.w());
+}
+
+bool QDeclarativeVector4DValueType::isEqual(const QVariant &value) const
+{
+ return (QVariant(vector) == value);
+}
+
qreal QDeclarativeVector4DValueType::x() const
{
return vector.x();
@@ -695,6 +788,16 @@ void QDeclarativeQuaternionValueType::setValue(QVariant value)
quaternion = qvariant_cast<QQuaternion>(value);
}
+QString QDeclarativeQuaternionValueType::toString() const
+{
+ return QString(QLatin1String("QQuaternion(%1, %2, %3, %4)")).arg(quaternion.scalar()).arg(quaternion.x()).arg(quaternion.y()).arg(quaternion.z());
+}
+
+bool QDeclarativeQuaternionValueType::isEqual(const QVariant &value) const
+{
+ return (QVariant(quaternion) == value);
+}
+
qreal QDeclarativeQuaternionValueType::scalar() const
{
return quaternion.scalar();
@@ -763,6 +866,20 @@ void QDeclarativeMatrix4x4ValueType::setValue(QVariant value)
matrix = qvariant_cast<QMatrix4x4>(value);
}
+QString QDeclarativeMatrix4x4ValueType::toString() const
+{
+ return QString(QLatin1String("QMatrix4x4(%1, %2, %3, %4, %5, %6, %7, %8, %9, %10, %11, %12, %13, %14, %15, %16)"))
+ .arg(matrix(0, 0)).arg(matrix(0, 1)).arg(matrix(0, 2)).arg(matrix(0, 3))
+ .arg(matrix(1, 0)).arg(matrix(1, 1)).arg(matrix(1, 2)).arg(matrix(1, 3))
+ .arg(matrix(2, 0)).arg(matrix(2, 1)).arg(matrix(2, 2)).arg(matrix(2, 3))
+ .arg(matrix(3, 0)).arg(matrix(3, 1)).arg(matrix(3, 2)).arg(matrix(3, 3));
+}
+
+bool QDeclarativeMatrix4x4ValueType::isEqual(const QVariant &value) const
+{
+ return (QVariant(matrix) == value);
+}
+
QDeclarativeEasingValueType::QDeclarativeEasingValueType(QObject *parent)
: QDeclarativeValueType(parent)
{
@@ -791,6 +908,16 @@ void QDeclarativeEasingValueType::setValue(QVariant value)
easing = qvariant_cast<QEasingCurve>(value);
}
+QString QDeclarativeEasingValueType::toString() const
+{
+ return QString(QLatin1String("QEasingCurve(%1, %2, %3, %4)")).arg(easing.type()).arg(easing.amplitude()).arg(easing.overshoot()).arg(easing.period());
+}
+
+bool QDeclarativeEasingValueType::isEqual(const QVariant &value) const
+{
+ return (QVariant(easing) == value);
+}
+
QDeclarativeEasingValueType::Type QDeclarativeEasingValueType::type() const
{
return (QDeclarativeEasingValueType::Type)easing.type();
@@ -861,6 +988,16 @@ void QDeclarativeFontValueType::setValue(QVariant value)
font = qvariant_cast<QFont>(value);
}
+QString QDeclarativeFontValueType::toString() const
+{
+ return QString(QLatin1String("QFont(%1)")).arg(font.toString());
+}
+
+bool QDeclarativeFontValueType::isEqual(const QVariant &value) const
+{
+ return (QVariant(font) == value);
+}
+
QString QDeclarativeFontValueType::family() const
{
@@ -1009,4 +1146,83 @@ void QDeclarativeFontValueType::setWordSpacing(qreal size)
font.setWordSpacing(size);
}
+QDeclarativeColorValueType::QDeclarativeColorValueType(QObject *parent)
+: QDeclarativeValueType(parent)
+{
+}
+
+void QDeclarativeColorValueType::read(QObject *obj, int idx)
+{
+ void *a[] = { &color, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
+}
+
+void QDeclarativeColorValueType::write(QObject *obj, int idx, QDeclarativePropertyPrivate::WriteFlags flags)
+{
+ int status = -1;
+ void *a[] = { &color, 0, &status, &flags };
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
+}
+
+QVariant QDeclarativeColorValueType::value()
+{
+ return QVariant(color);
+}
+
+void QDeclarativeColorValueType::setValue(QVariant value)
+{
+ color = qvariant_cast<QColor>(value);
+}
+
+QString QDeclarativeColorValueType::toString() const
+{
+ // special case - to maintain behaviour with QtQuick 1.0, we just output normal toString() value.
+ return QVariant(color).toString();
+}
+
+bool QDeclarativeColorValueType::isEqual(const QVariant &value) const
+{
+ return (QVariant(color) == value);
+}
+
+qreal QDeclarativeColorValueType::r() const
+{
+ return color.redF();
+}
+
+qreal QDeclarativeColorValueType::g() const
+{
+ return color.greenF();
+}
+
+qreal QDeclarativeColorValueType::b() const
+{
+ return color.blueF();
+}
+
+qreal QDeclarativeColorValueType::a() const
+{
+ return color.alphaF();
+}
+
+void QDeclarativeColorValueType::setR(qreal r)
+{
+ color.setRedF(r);
+}
+
+void QDeclarativeColorValueType::setG(qreal g)
+{
+ color.setGreenF(g);
+}
+
+void QDeclarativeColorValueType::setB(qreal b)
+{
+ color.setBlueF(b);
+}
+
+void QDeclarativeColorValueType::setA(qreal a)
+{
+ color.setAlphaF(a);
+}
+
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativevaluetype_p.h b/src/declarative/qml/qdeclarativevaluetype_p.h
index 5d103a46de..03cb83fdad 100644
--- a/src/declarative/qml/qdeclarativevaluetype_p.h
+++ b/src/declarative/qml/qdeclarativevaluetype_p.h
@@ -67,6 +67,7 @@
#include <QtGui/qmatrix4x4.h>
#include <QtGui/qquaternion.h>
#include <QtGui/qfont.h>
+#include <QtGui/qcolor.h>
QT_BEGIN_NAMESPACE
@@ -79,6 +80,9 @@ public:
virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags flags) = 0;
virtual QVariant value() = 0;
virtual void setValue(QVariant) = 0;
+
+ virtual QString toString() const = 0;
+ virtual bool isEqual(const QVariant &value) const = 0;
};
class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeValueTypeFactory
@@ -113,6 +117,8 @@ public:
virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
virtual QVariant value();
virtual void setValue(QVariant value);
+ virtual QString toString() const;
+ virtual bool isEqual(const QVariant &value) const;
qreal x() const;
qreal y() const;
@@ -135,6 +141,8 @@ public:
virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
virtual QVariant value();
virtual void setValue(QVariant value);
+ virtual QString toString() const;
+ virtual bool isEqual(const QVariant &value) const;
int x() const;
int y() const;
@@ -157,6 +165,8 @@ public:
virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
virtual QVariant value();
virtual void setValue(QVariant value);
+ virtual QString toString() const;
+ virtual bool isEqual(const QVariant &value) const;
qreal width() const;
qreal height() const;
@@ -179,6 +189,8 @@ public:
virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
virtual QVariant value();
virtual void setValue(QVariant value);
+ virtual QString toString() const;
+ virtual bool isEqual(const QVariant &value) const;
int width() const;
int height() const;
@@ -203,6 +215,8 @@ public:
virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
virtual QVariant value();
virtual void setValue(QVariant value);
+ virtual QString toString() const;
+ virtual bool isEqual(const QVariant &value) const;
qreal x() const;
qreal y() const;
@@ -232,6 +246,8 @@ public:
virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
virtual QVariant value();
virtual void setValue(QVariant value);
+ virtual QString toString() const;
+ virtual bool isEqual(const QVariant &value) const;
int x() const;
int y() const;
@@ -259,6 +275,8 @@ public:
virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
virtual QVariant value();
virtual void setValue(QVariant value);
+ virtual QString toString() const;
+ virtual bool isEqual(const QVariant &value) const;
qreal x() const;
qreal y() const;
@@ -282,6 +300,8 @@ public:
virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
virtual QVariant value();
virtual void setValue(QVariant value);
+ virtual QString toString() const;
+ virtual bool isEqual(const QVariant &value) const;
qreal x() const;
qreal y() const;
@@ -308,6 +328,8 @@ public:
virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
virtual QVariant value();
virtual void setValue(QVariant value);
+ virtual QString toString() const;
+ virtual bool isEqual(const QVariant &value) const;
qreal x() const;
qreal y() const;
@@ -336,6 +358,8 @@ public:
virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
virtual QVariant value();
virtual void setValue(QVariant value);
+ virtual QString toString() const;
+ virtual bool isEqual(const QVariant &value) const;
qreal scalar() const;
qreal x() const;
@@ -376,6 +400,8 @@ public:
virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
virtual QVariant value();
virtual void setValue(QVariant value);
+ virtual QString toString() const;
+ virtual bool isEqual(const QVariant &value) const;
qreal m11() const { return matrix(0, 0); }
qreal m12() const { return matrix(0, 1); }
@@ -457,6 +483,8 @@ public:
virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
virtual QVariant value();
virtual void setValue(QVariant value);
+ virtual QString toString() const;
+ virtual bool isEqual(const QVariant &value) const;
Type type() const;
qreal amplitude() const;
@@ -508,6 +536,8 @@ public:
virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
virtual QVariant value();
virtual void setValue(QVariant value);
+ virtual QString toString() const;
+ virtual bool isEqual(const QVariant &value) const;
QString family() const;
void setFamily(const QString &);
@@ -552,6 +582,36 @@ private:
mutable QDeclarativeNullableValue<int> dpi;
};
+class Q_AUTOTEST_EXPORT QDeclarativeColorValueType : public QDeclarativeValueType
+{
+ Q_PROPERTY(qreal r READ r WRITE setR)
+ Q_PROPERTY(qreal g READ g WRITE setG)
+ Q_PROPERTY(qreal b READ b WRITE setB)
+ Q_PROPERTY(qreal a READ a WRITE setA)
+ Q_OBJECT
+public:
+ QDeclarativeColorValueType(QObject *parent = 0);
+
+ virtual void read(QObject *, int);
+ virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
+ virtual QVariant value();
+ virtual void setValue(QVariant value);
+ virtual QString toString() const;
+ virtual bool isEqual(const QVariant &value) const;
+
+ qreal r() const;
+ qreal g() const;
+ qreal b() const;
+ qreal a() const;
+ void setR(qreal);
+ void setG(qreal);
+ void setB(qreal);
+ void setA(qreal);
+
+private:
+ QColor color;
+};
+
QT_END_NAMESPACE
#endif // QDECLARATIVEVALUETYPE_P_H
diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp
index 45e4745c1a..6708b60834 100644
--- a/src/declarative/qml/qdeclarativevme.cpp
+++ b/src/declarative/qml/qdeclarativevme.cpp
@@ -586,6 +586,16 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEObjectStack &stack,
instr.propertyIndex, a);
QML_END_INSTR(StoreVector3D)
+ QML_BEGIN_INSTR(StoreVector4D)
+ QObject *target = stack.top();
+ CLEAN_PROPERTY(target, instr.propertyIndex);
+
+ QVector4D *v = (QVector4D *)&instr.vector;
+ void *a[] = { v, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.propertyIndex, a);
+ QML_END_INSTR(StoreVector4D)
+
QML_BEGIN_INSTR(StoreObject)
QObject *assignObj = stack.pop();
QObject *target = stack.top();
diff --git a/src/declarative/qml/qdeclarativevmemetaobject.cpp b/src/declarative/qml/qdeclarativevmemetaobject.cpp
index 746c9f650b..bcd46f259e 100644
--- a/src/declarative/qml/qdeclarativevmemetaobject.cpp
+++ b/src/declarative/qml/qdeclarativevmemetaobject.cpp
@@ -458,7 +458,7 @@ int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
}
}
}
- if(c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty) {
+ if (c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty || c == QMetaObject::ResetProperty) {
if (id >= propOffset) {
id -= propOffset;
diff --git a/src/declarative/qml/qdeclarativexmlhttprequest.cpp b/src/declarative/qml/qdeclarativexmlhttprequest.cpp
index abcc283610..0eb923a70c 100644
--- a/src/declarative/qml/qdeclarativexmlhttprequest.cpp
+++ b/src/declarative/qml/qdeclarativexmlhttprequest.cpp
@@ -49,6 +49,7 @@
#include "private/qdeclarativeengine_p.h"
#include "private/qdeclarativeexpression_p.h"
#include "qdeclarativeglobal_p.h"
+#include "qv8domerrors_p.h"
#include <QtCore/qobject.h>
#include <QtDeclarative/qjsvalue.h>
@@ -63,33 +64,6 @@
#ifndef QT_NO_XMLSTREAMREADER
-// From DOM-Level-3-Core spec
-// http://www.w3.org/TR/DOM-Level-3-Core/core.html
-#define INDEX_SIZE_ERR 1
-#define DOMSTRING_SIZE_ERR 2
-#define HIERARCHY_REQUEST_ERR 3
-#define WRONG_DOCUMENT_ERR 4
-#define INVALID_CHARACTER_ERR 5
-#define NO_DATA_ALLOWED_ERR 6
-#define NO_MODIFICATION_ALLOWED_ERR 7
-#define NOT_FOUND_ERR 8
-#define NOT_SUPPORTED_ERR 9
-#define INUSE_ATTRIBUTE_ERR 10
-#define INVALID_STATE_ERR 11
-#define SYNTAX_ERR 12
-#define INVALID_MODIFICATION_ERR 13
-#define NAMESPACE_ERR 14
-#define INVALID_ACCESS_ERR 15
-#define VALIDATION_ERR 16
-#define TYPE_MISMATCH_ERR 17
-
-#define V8THROW_DOM(error, string) { \
- v8::Local<v8::Value> v = v8::Exception::Error(v8::String::New(string)); \
- v->ToObject()->Set(v8::String::New("code"), v8::Integer::New(error)); \
- v8::ThrowException(v); \
- return v8::Handle<v8::Value>(); \
-}
-
#define V8THROW_REFERENCE(string) { \
v8::ThrowException(v8::Exception::ReferenceError(v8::String::New(string))); \
return v8::Handle<v8::Value>(); \
@@ -1518,7 +1492,7 @@ static v8::Handle<v8::Value> qmlxmlhttprequest_open(const v8::Arguments &args)
V8THROW_REFERENCE("Not an XMLHttpRequest object");
if (args.Length() < 2 || args.Length() > 5)
- V8THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
+ V8THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
QV8Engine *engine = r->engine;
@@ -1529,7 +1503,7 @@ static v8::Handle<v8::Value> qmlxmlhttprequest_open(const v8::Arguments &args)
method != QLatin1String("HEAD") &&
method != QLatin1String("POST") &&
method != QLatin1String("DELETE"))
- V8THROW_DOM(SYNTAX_ERR, "Unsupported HTTP method type");
+ V8THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Unsupported HTTP method type");
// Argument 1 - URL
QUrl url = QUrl::fromEncoded(engine->toString(args[1]).toUtf8());
@@ -1539,7 +1513,7 @@ static v8::Handle<v8::Value> qmlxmlhttprequest_open(const v8::Arguments &args)
// Argument 2 - async (optional)
if (args.Length() > 2 && !args[2]->BooleanValue())
- V8THROW_DOM(NOT_SUPPORTED_ERR, "Synchronous XMLHttpRequest calls are not supported");
+ V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Synchronous XMLHttpRequest calls are not supported");
// Argument 3/4 - user/pass (optional)
QString username, password;
@@ -1565,10 +1539,10 @@ static v8::Handle<v8::Value> qmlxmlhttprequest_setRequestHeader(const v8::Argume
V8THROW_REFERENCE("Not an XMLHttpRequest object");
if (args.Length() != 2)
- V8THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
+ V8THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
if (r->readyState() != QDeclarativeXMLHttpRequest::Opened || r->sendFlag())
- V8THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+ V8THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
QV8Engine *engine = r->engine;
@@ -1615,7 +1589,7 @@ static v8::Handle<v8::Value> qmlxmlhttprequest_send(const v8::Arguments &args)
if (r->readyState() != QDeclarativeXMLHttpRequest::Opened ||
r->sendFlag())
- V8THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+ V8THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
QByteArray data;
if (args.Length() > 0)
@@ -1642,12 +1616,12 @@ static v8::Handle<v8::Value> qmlxmlhttprequest_getResponseHeader(const v8::Argum
QV8Engine *engine = r->engine;
if (args.Length() != 1)
- V8THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
+ V8THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
if (r->readyState() != QDeclarativeXMLHttpRequest::Loading &&
r->readyState() != QDeclarativeXMLHttpRequest::Done &&
r->readyState() != QDeclarativeXMLHttpRequest::HeadersReceived)
- V8THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+ V8THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
return engine->toString(r->header(engine->toString(args[0])));
}
@@ -1661,12 +1635,12 @@ static v8::Handle<v8::Value> qmlxmlhttprequest_getAllResponseHeaders(const v8::A
QV8Engine *engine = r->engine;
if (args.Length() != 0)
- V8THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
+ V8THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
if (r->readyState() != QDeclarativeXMLHttpRequest::Loading &&
r->readyState() != QDeclarativeXMLHttpRequest::Done &&
r->readyState() != QDeclarativeXMLHttpRequest::HeadersReceived)
- V8THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+ V8THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
return engine->toString(r->headers());
}
@@ -1691,7 +1665,7 @@ static v8::Handle<v8::Value> qmlxmlhttprequest_status(v8::Local<v8::String> prop
if (r->readyState() == QDeclarativeXMLHttpRequest::Unsent ||
r->readyState() == QDeclarativeXMLHttpRequest::Opened)
- V8THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+ V8THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
if (r->errorFlag())
return v8::Integer::New(0);
@@ -1710,7 +1684,7 @@ static v8::Handle<v8::Value> qmlxmlhttprequest_statusText(v8::Local<v8::String>
if (r->readyState() == QDeclarativeXMLHttpRequest::Unsent ||
r->readyState() == QDeclarativeXMLHttpRequest::Opened)
- V8THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+ V8THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
if (r->errorFlag())
return engine->toString(QString());
@@ -1812,27 +1786,6 @@ void *qt_add_qmlxmlhttprequest(QV8Engine *engine)
xmlhttprequest->Set(v8::String::New("DONE"), v8::Integer::New(4), attributes);
engine->global()->Set(v8::String::New("XMLHttpRequest"), xmlhttprequest->GetFunction());
- // DOM Exception
- v8::Local<v8::Object> domexception = v8::Object::New();
- domexception->Set(v8::String::New("INDEX_SIZE_ERR"), v8::Integer::New(INDEX_SIZE_ERR), attributes);
- domexception->Set(v8::String::New("DOMSTRING_SIZE_ERR"), v8::Integer::New(DOMSTRING_SIZE_ERR), attributes);
- domexception->Set(v8::String::New("HIERARCHY_REQUEST_ERR"), v8::Integer::New(HIERARCHY_REQUEST_ERR), attributes);
- domexception->Set(v8::String::New("WRONG_DOCUMENT_ERR"), v8::Integer::New(WRONG_DOCUMENT_ERR), attributes);
- domexception->Set(v8::String::New("INVALID_CHARACTER_ERR"), v8::Integer::New(INVALID_CHARACTER_ERR), attributes);
- domexception->Set(v8::String::New("NO_DATA_ALLOWED_ERR"), v8::Integer::New(NO_DATA_ALLOWED_ERR), attributes);
- domexception->Set(v8::String::New("NO_MODIFICATION_ALLOWED_ERR"), v8::Integer::New(NO_MODIFICATION_ALLOWED_ERR), attributes);
- domexception->Set(v8::String::New("NOT_FOUND_ERR"), v8::Integer::New(NOT_FOUND_ERR), attributes);
- domexception->Set(v8::String::New("NOT_SUPPORTED_ERR"), v8::Integer::New(NOT_SUPPORTED_ERR), attributes);
- domexception->Set(v8::String::New("INUSE_ATTRIBUTE_ERR"), v8::Integer::New(INUSE_ATTRIBUTE_ERR), attributes);
- domexception->Set(v8::String::New("INVALID_STATE_ERR"), v8::Integer::New(INVALID_STATE_ERR), attributes);
- domexception->Set(v8::String::New("SYNTAX_ERR"), v8::Integer::New(SYNTAX_ERR), attributes);
- domexception->Set(v8::String::New("INVALID_MODIFICATION_ERR"), v8::Integer::New(INVALID_MODIFICATION_ERR), attributes);
- domexception->Set(v8::String::New("NAMESPACE_ERR"), v8::Integer::New(NAMESPACE_ERR), attributes);
- domexception->Set(v8::String::New("INVALID_ACCESS_ERR"), v8::Integer::New(INVALID_ACCESS_ERR), attributes);
- domexception->Set(v8::String::New("VALIDATION_ERR"), v8::Integer::New(VALIDATION_ERR), attributes);
- domexception->Set(v8::String::New("TYPE_MISMATCH_ERR"), v8::Integer::New(TYPE_MISMATCH_ERR), attributes);
- engine->global()->Set(v8::String::New("DOMException"), domexception);
-
QDeclarativeXMLHttpRequestData *data = new QDeclarativeXMLHttpRequestData;
return data;
}
diff --git a/src/declarative/qml/qintrusivelist.cpp b/src/declarative/qml/qintrusivelist.cpp
index a94f5152a3..dabb893e91 100644
--- a/src/declarative/qml/qintrusivelist.cpp
+++ b/src/declarative/qml/qintrusivelist.cpp
@@ -113,6 +113,12 @@ Remove \a object from the list. \a object must not be null.
*/
/*!
+\fn bool QIntrusiveList::contains(N *object) const
+
+Returns true if the list contains \a object; otherwise returns false.
+*/
+
+/*!
\fn N *QIntrusiveList::first() const
Returns the first entry in this list, or null if the list is empty.
diff --git a/src/declarative/qml/qintrusivelist_p.h b/src/declarative/qml/qintrusivelist_p.h
index c1ea80a767..717b11c344 100644
--- a/src/declarative/qml/qintrusivelist_p.h
+++ b/src/declarative/qml/qintrusivelist_p.h
@@ -68,6 +68,7 @@ public:
inline bool isEmpty() const;
inline void insert(N *n);
inline void remove(N *n);
+ inline bool contains(N *) const;
class iterator {
public:
@@ -202,6 +203,18 @@ void QIntrusiveList<N, member>::remove(N *n)
}
template<class N, QIntrusiveListNode N::*member>
+bool QIntrusiveList<N, member>::contains(N *n) const
+{
+ QIntrusiveListNode *nnode = __first;
+ while (nnode) {
+ if (nodeToN(nnode) == n)
+ return true;
+ nnode = nnode->_next;
+ }
+ return false;
+}
+
+template<class N, QIntrusiveListNode N::*member>
N *QIntrusiveList<N, member>::first() const
{
return __first?nodeToN(__first):0;
diff --git a/src/declarative/qml/v8/qhashedstring.cpp b/src/declarative/qml/v8/qhashedstring.cpp
index 4a23e3b7dd..2e2af98ff4 100644
--- a/src/declarative/qml/v8/qhashedstring.cpp
+++ b/src/declarative/qml/v8/qhashedstring.cpp
@@ -7,29 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** 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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
diff --git a/src/declarative/qml/v8/qhashedstring_p.h b/src/declarative/qml/v8/qhashedstring_p.h
index 143bd0b995..e0ca1d466a 100644
--- a/src/declarative/qml/v8/qhashedstring_p.h
+++ b/src/declarative/qml/v8/qhashedstring_p.h
@@ -7,29 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** 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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
diff --git a/src/declarative/qml/v8/qjsconverter_p.h b/src/declarative/qml/v8/qjsconverter_p.h
index 4aec472c7a..c42381bc55 100644
--- a/src/declarative/qml/v8/qjsconverter_p.h
+++ b/src/declarative/qml/v8/qjsconverter_p.h
@@ -28,6 +28,7 @@
#include <QtCore/qglobal.h>
#include <QtCore/qnumeric.h>
#include <QtCore/qstring.h>
+#include <QtCore/qstringlist.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qregexp.h>
#include <QtCore/qdatetime.h>
@@ -70,7 +71,7 @@ public:
return qstr;
}
- static v8::Handle<v8::String> toString(const QString& string)
+ static v8::Local<v8::String> toString(const QString& string)
{
return v8::String::New(reinterpret_cast<const uint16_t*>(string.data()), string.size());
}
diff --git a/src/declarative/qml/v8/qjsengine.cpp b/src/declarative/qml/v8/qjsengine.cpp
index e80fcb4e7e..3db7fc40e0 100644
--- a/src/declarative/qml/v8/qjsengine.cpp
+++ b/src/declarative/qml/v8/qjsengine.cpp
@@ -52,6 +52,97 @@ Q_DECLARE_METATYPE(QJSValue)
Q_DECLARE_METATYPE(QObjectList)
Q_DECLARE_METATYPE(QList<int>)
+/*!
+ \since 5.0
+ \class QJSEngine
+
+ \brief The QJSEngine class provides an environment for evaluating JavaScript code.
+
+ \ingroup qtjavascript
+ \mainclass
+
+ \section1 Evaluating Scripts
+
+ Use evaluate() to evaluate script code.
+
+ \snippet doc/src/snippets/code/src_script_qjsengine.cpp 0
+
+ evaluate() returns a QJSValue that holds the result of the
+ evaluation. The QJSValue class provides functions for converting
+ the result to various C++ types (e.g. QJSValue::toString()
+ and QJSValue::toNumber()).
+
+ The following code snippet shows how a script function can be
+ defined and then invoked from C++ using QJSValue::call():
+
+ \snippet doc/src/snippets/code/src_script_qjsengine.cpp 1
+
+ As can be seen from the above snippets, a script is provided to the
+ engine in the form of a string. One common way of loading scripts is
+ by reading the contents of a file and passing it to evaluate():
+
+ \snippet doc/src/snippets/code/src_script_qjsengine.cpp 2
+
+ Here we pass the name of the file as the second argument to
+ evaluate(). This does not affect evaluation in any way; the second
+ argument is a general-purpose string that is used to identify the
+ script for debugging purposes (for example, our filename will now
+ show up in any uncaughtExceptionBacktrace() involving the script).
+
+ \section1 Engine Configuration
+
+ The globalObject() function returns the \bold {Global Object}
+ associated with the script engine. Properties of the Global Object
+ are accessible from any script code (i.e. they are global
+ variables). Typically, before evaluating "user" scripts, you will
+ want to configure a script engine by adding one or more properties
+ to the Global Object:
+
+ \snippet doc/src/snippets/code/src_script_qjsengine.cpp 3
+
+ Adding custom properties to the scripting environment is one of the
+ standard means of providing a scripting API that is specific to your
+ application. Usually these custom properties are objects created by
+ the newQObject() or newObject() functions.
+
+ \section1 Script Exceptions
+
+ evaluate() can throw a script exception (e.g. due to a syntax
+ error); in that case, the return value is the value that was thrown
+ (typically an \c{Error} object). You can check whether the
+ evaluation caused an exception by calling hasUncaughtException(). In
+ that case, you can call toString() on the error object to obtain an
+ error message. The current uncaught exception is also available
+ through uncaughtException().
+ Calling clearExceptions() will cause any uncaught exceptions to be
+ cleared.
+
+ \snippet doc/src/snippets/code/src_script_qjsengine.cpp 4
+
+ \section1 Script Object Creation
+
+ Use newObject() to create a JavaScript object; this is the
+ C++ equivalent of the script statement \c{new Object()}. You can use
+ the object-specific functionality in QJSValue to manipulate the
+ script object (e.g. QJSValue::setProperty()). Similarly, use
+ newArray() to create a JavaScript array object. Use newDate() to
+ create a \c{Date} object, and newRegExp() to create a \c{RegExp}
+ object.
+
+ \section1 QObject Integration
+
+ Use newQObject() to wrap a QObject (or subclass)
+ pointer. newQObject() returns a proxy script object; properties,
+ children, and signals and slots of the QObject are available as
+ properties of the proxy object. No binding code is needed because it
+ is done dynamically using the Qt meta object system.
+
+ \snippet doc/src/snippets/code/src_script_qjsengine.cpp 5
+
+ \sa QJSValue, {Making Applications Scriptable}
+
+*/
+
QT_BEGIN_NAMESPACE
@@ -102,6 +193,11 @@ QJSEngine::~QJSEngine()
}
/*!
+ \fn QV8Engine *QJSEngine::handle() const
+ \internal
+*/
+
+/*!
Returns true if the last script evaluation resulted in an uncaught
exception; otherwise returns false.
@@ -201,6 +297,11 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
return QJSValuePrivate::get(d->evaluate(program, fileName, lineNumber));
}
+/*!
+ Returns a QJSValue of the primitive type Null.
+
+ \sa nullValue()
+*/
QJSValue QJSEngine::nullValue()
{
Q_D(QJSEngine);
@@ -209,6 +310,11 @@ QJSValue QJSEngine::nullValue()
return QJSValuePrivate::get(new QJSValuePrivate(d, v8::Null()));
}
+/*!
+ Returns a QJSValue of the primitive type Undefined.
+
+ \sa nullValue()
+*/
QJSValue QJSEngine::undefinedValue()
{
Q_D(QJSEngine);
@@ -217,6 +323,14 @@ QJSValue QJSEngine::undefinedValue()
return QJSValuePrivate::get(new QJSValuePrivate(d, v8::Undefined()));
}
+/*!
+ Creates a JavaScript object of class Object.
+
+ The prototype of the created object will be the Object
+ prototype object.
+
+ \sa newArray(), QJSValue::setProperty()
+*/
QJSValue QJSEngine::newObject()
{
Q_D(QJSEngine);
@@ -225,6 +339,11 @@ QJSValue QJSEngine::newObject()
return QJSValuePrivate::get(new QJSValuePrivate(d, v8::Object::New()));
}
+/*!
+ Creates a JavaScript object of class Array with the given \a length.
+
+ \sa newObject()
+*/
QJSValue QJSEngine::newArray(uint length)
{
Q_D(QJSEngine);
@@ -234,13 +353,12 @@ QJSValue QJSEngine::newArray(uint length)
}
/*!
- Creates a QtScript object that wraps the given QObject \a
+ Creates a JavaScript object that wraps the given QObject \a
object, using the given \a ownership. The given \a options control
various aspects of the interaction with the resulting script object.
Signals and slots, properties and children of \a object are
- available as properties of the created QJSValue. For more
- information, see the \l{QtScript} documentation.
+ available as properties of the created QJSValue.
If \a object is a null pointer, this function returns nullValue().
@@ -248,8 +366,8 @@ QJSValue QJSEngine::newArray(uint length)
(or its superclass, recursively), the prototype of the new script
object will be set to be that default prototype.
- If the given \a object is deleted outside of QtScript's control, any
- attempt to access the deleted QObject's members through the QtScript
+ If the given \a object is deleted outside of the engine's control, any
+ attempt to access the deleted QObject's members through the JavaScript
wrapper object (either by script code or C++) will result in a
script exception.
@@ -264,7 +382,7 @@ QJSValue QJSEngine::newQObject(QObject *object)
}
/*!
- Creates a QtScript object holding the given variant \a value.
+ Creates a JavaScript object holding the given variant \a value.
If a default prototype has been registered with the meta type id of
\a value, then the prototype of the created object will be that
@@ -282,6 +400,16 @@ QJSValue QJSEngine::newVariant(const QVariant &value)
}
+/*!
+ Returns this engine's Global Object.
+
+ By default, the Global Object contains the built-in objects that are
+ part of \l{ECMA-262}, such as Math, Date and String. Additionally,
+ you can set properties of the Global Object to make your own
+ extensions available to all script code. Non-local variables in
+ script code will be created as properties of the Global Object, as
+ well as local variables in global code.
+*/
QJSValue QJSEngine::globalObject() const
{
Q_D(const QJSEngine);
@@ -290,6 +418,23 @@ QJSValue QJSEngine::globalObject() const
return d->scriptValueFromInternal(d->global());
}
+/*!
+ Converts the given \a value to an object, if such a conversion is
+ possible; otherwise returns an invalid QJSValue. The conversion
+ is performed according to the following table:
+
+ \table
+ \header \o Input Type \o Result
+ \row \o Undefined \o An invalid QJSValue.
+ \row \o Null \o An invalid QJSValue.
+ \row \o Boolean \o A new Boolean object whose internal value is set to the value of the boolean.
+ \row \o Number \o A new Number object whose internal value is set to the value of the number.
+ \row \o String \o A new String object whose internal value is set to the value of the string.
+ \row \o Object \o The result is the object itself (no conversion).
+ \endtable
+
+ \sa newObject()
+*/
QJSValue QJSEngine::toObject(const QJSValue& value)
{
Q_D(QJSEngine);
@@ -299,7 +444,7 @@ QJSValue QJSEngine::toObject(const QJSValue& value)
}
/*!
- Creates a QtScript object of class Date from the given \a value.
+ Creates a JavaScript object of class Date from the given \a value.
\sa QJSValue::toDateTime()
*/
@@ -312,7 +457,7 @@ QJSValue QJSEngine::newDate(const QDateTime &dt)
}
/*!
- Creates a QtScript object of class Date with the given
+ Creates a JavaScript object of class Date with the given
\a value (the number of milliseconds since 01 January 1970,
UTC).
*/
@@ -325,7 +470,7 @@ QJSValue QJSEngine::newDate(double date)
}
/*!
- Creates a QtScript object of class RegExp with the given
+ Creates a JavaScript object of class RegExp with the given
\a regexp.
\sa QJSValue::toRegExp()
@@ -339,7 +484,7 @@ QJSValue QJSEngine::newRegExp(const QRegExp &regexp)
}
/*!
- Creates a QtScript object of class RegExp with the given
+ Creates a JavaScript object of class RegExp with the given
\a pattern and \a flags.
The legal flags are 'g' (global), 'i' (ignore case), and 'm'
@@ -425,6 +570,19 @@ bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
}
}
+/*! \fn QJSValue QJSEngine::toScriptValue(const T &value)
+
+ Creates a QJSValue with the given \a value.
+
+ \sa fromScriptValue()
+*/
+
+/*! \fn T QJSEngine::fromScriptValue(const QJSValue &value)
+
+ Returns the given \a value converted to the template type \c{T}.
+
+ \sa toScriptValue()
+*/
QT_END_NAMESPACE
diff --git a/src/declarative/qml/v8/qjsengine.h b/src/declarative/qml/v8/qjsengine.h
index 5109cefcf4..759363ab84 100644
--- a/src/declarative/qml/v8/qjsengine.h
+++ b/src/declarative/qml/v8/qjsengine.h
@@ -35,7 +35,7 @@ QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
-QT_MODULE(Script)
+QT_MODULE(Declarative)
class QDateTime;
class QV8Engine;
@@ -45,7 +45,7 @@ class QRegExp;
template <typename T>
inline T qjsvalue_cast(const QJSValue &);
-class Q_SCRIPT_EXPORT QJSEngine
+class Q_DECLARATIVE_EXPORT QJSEngine
: public QObject
{
Q_OBJECT
diff --git a/src/declarative/qml/v8/qjsvalue.cpp b/src/declarative/qml/v8/qjsvalue.cpp
index eff7b4321a..bbfae8983c 100644
--- a/src/declarative/qml/v8/qjsvalue.cpp
+++ b/src/declarative/qml/v8/qjsvalue.cpp
@@ -31,23 +31,71 @@
#include <QtCore/qregexp.h>
#include <QtCore/qstring.h>
-QT_BEGIN_NAMESPACE
-
/*!
- Constructs an invalid value.
+ \since 5.0
+ \class QJSValue
+
+ \brief The QJSValue class acts as a container for Qt/JavaScript data types.
+
+ \ingroup qtjavascript
+ \mainclass
+
+ QJSValue supports the types defined in the \l{ECMA-262}
+ standard: The primitive types, which are Undefined, Null, Boolean,
+ Number, and String; and the Object type. Additionally, built-in
+ support is provided for Qt/C++ types such as QVariant and QObject.
+
+ For the object-based types (including Date and RegExp), use the
+ newT() functions in QJSEngine (e.g. QJSEngine::newObject())
+ to create a QJSValue of the desired type. For the primitive types,
+ use one of the QJSValue constructor overloads.
+
+ The methods named isT() (e.g. isBool(), isUndefined()) can be
+ used to test if a value is of a certain type. The methods named
+ toT() (e.g. toBool(), toString()) can be used to convert a
+ QJSValue to another type. You can also use the generic
+ QJSValue_cast() function.
+
+ Object values have zero or more properties which are themselves
+ QJSValues. Use setProperty() to set a property of an object, and
+ call property() to retrieve the value of a property.
+
+ \snippet doc/src/snippets/code/src_script_qjsvalue.cpp 0
+
+ The attributes of a property can be queried by calling the
+ propertyFlags() function.
+
+ If you want to iterate over the properties of a script object, use
+ the QJSValueIterator class.
+
+ Object values have an internal \c{prototype} property, which can be
+ accessed with prototype() and setPrototype().
+
+ Function objects (objects for which isFunction() returns true) can
+ be invoked by calling call(). Constructor functions can be used to
+ construct new objects by calling construct().
+
+ Use equals() or strictlyEquals() to compare a QJSValue to another.
+
+ Note that a QJSValue for which isObject() is true only carries a
+ reference to an actual object; copying the QJSValue will only
+ copy the object reference, not the object itself. If you want to
+ clone an object (i.e. copy an object's properties to another
+ object), you can do so with the help of a \c{for-in} statement in
+ script code, or QJSValueIterator in C++.
+
+ \sa QJSEngine, QJSValueIterator
*/
-QJSValue::QJSValue()
- : d_ptr(InvalidValue())
-{
-}
/*!
- Constructs a new QJSValue with a boolean \a value.
+ \enum QJSValue::SpecialValue
+
+ This enum is used to specify a single-valued type.
+
+ \value UndefinedValue An undefined value.
+
+ \value NullValue A null value.
*/
-QJSValue::QJSValue(bool value)
- : d_ptr(new QJSValuePrivate(value))
-{
-}
/*!
\enum QJSValue::PropertyFlag
@@ -59,17 +107,25 @@ QJSValue::QJSValue(bool value)
\value Undeletable Attempts by Qt Script code to \c{delete} the property will be ignored.
\value SkipInEnumeration The property is not to be enumerated by a \c{for-in} enumeration.
+*/
- \value PropertyGetter The property is defined by a function which will be called to get the property value.
-
- \value PropertySetter The property is defined by a function which will be called to set the property value.
-
- \omitvalue QObjectMember This flag is used to indicate that an existing property is a QObject member (a property or method).
+QT_BEGIN_NAMESPACE
- \value KeepExistingFlags This value is used to indicate to setProperty() that the property's flags should be left unchanged. If the property doesn't exist, the default flags (0) will be used.
+/*!
+ Constructs an invalid value.
+*/
+QJSValue::QJSValue()
+ : d_ptr(InvalidValue())
+{
+}
- \omitvalue UserRange Flags in this range are not used by Qt Script, and can be used for custom purposes.
+/*!
+ Constructs a new QJSValue with a boolean \a value.
*/
+QJSValue::QJSValue(bool value)
+ : d_ptr(new QJSValuePrivate(value))
+{
+}
/*!
Constructs a new QJSValue with a number \a value.
@@ -120,8 +176,6 @@ QJSValue::QJSValue(const QLatin1String &value)
}
/*!
- \fn QJSValue::QJSValue(const QLatin1String &value)
-
Constructs a new QJSValue with a string \a value.
*/
#ifndef QT_NO_CAST_FROM_ASCII
@@ -383,8 +437,6 @@ bool QJSValue::isUndefined() const
/*!
Returns true if this QJSValue is an object of the Error class;
otherwise returns false.
-
- \sa QScriptContext::throwError()
*/
bool QJSValue::isError() const
{
@@ -654,7 +706,7 @@ QVariant QJSValue::toVariant() const
QJSEngine::hasUncaughtException() to determine if an exception
occurred.
- \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 2
+ \snippet doc/src/snippets/code/src_script_qjsvalue.cpp 1
\sa construct()
*/
@@ -773,7 +825,7 @@ QJSValue& QJSValue::operator=(const QJSValue& other)
toString()) in an attempt to convert the object to a primitive value
(possibly resulting in an uncaught script exception).
- \sa strictlyEquals(), lessThan()
+ \sa strictlyEquals()
*/
bool QJSValue::equals(const QJSValue& other) const
{
@@ -830,9 +882,7 @@ bool QJSValue::instanceOf(const QJSValue &other) const
}
/*!
- Returns the value of this QJSValue's property with the given \a name,
- using the given \a mode to resolve the property.
-
+ Returns the value of this QJSValue's property with the given \a name.
If no such property exists, an invalid QJSValue is returned.
If the property is implemented using a getter function (i.e. has the
@@ -854,8 +904,7 @@ QJSValue QJSValue::property(const QString& name) const
/*!
\overload
- Returns the property at the given \a arrayIndex, using the given \a
- mode to resolve the property.
+ Returns the property at the given \a arrayIndex.
This function is provided for convenience and performance when
working with array objects.
@@ -878,8 +927,7 @@ QJSValue QJSValue::property(quint32 arrayIndex) const
If this QJSValue is not an object, this function does nothing.
If this QJSValue does not already have a property with name \a name,
- a new property is created; the given \a flags then specify how this
- property may be accessed by script code.
+ a new property is created.
If \a value is invalid, the property is removed.
@@ -922,8 +970,7 @@ void QJSValue::setProperty(quint32 arrayIndex, const QJSValue& value)
}
/*!
- Returns the flags of the property with the given \a name, using the
- given \a mode to resolve the property.
+ Returns the flags of the property with the given \a name.
\sa property()
*/
diff --git a/src/declarative/qml/v8/qjsvalue.h b/src/declarative/qml/v8/qjsvalue.h
index 07276bc694..8b78addd00 100644
--- a/src/declarative/qml/v8/qjsvalue.h
+++ b/src/declarative/qml/v8/qjsvalue.h
@@ -34,7 +34,7 @@ QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
-QT_MODULE(Script)
+QT_MODULE(Declarative)
class QJSValue;
class QJSEngine;
@@ -50,7 +50,7 @@ class QJSValuePrivate;
struct QScriptValuePrivatePointerDeleter;
template <class T> class QScriptPassPointer;
-class Q_SCRIPT_EXPORT QJSValue
+class Q_DECLARATIVE_EXPORT QJSValue
{
public:
enum PropertyFlag {
diff --git a/src/declarative/qml/v8/qjsvalue_impl_p.h b/src/declarative/qml/v8/qjsvalue_impl_p.h
index adff6ce945..b0ad7669d7 100644
--- a/src/declarative/qml/v8/qjsvalue_impl_p.h
+++ b/src/declarative/qml/v8/qjsvalue_impl_p.h
@@ -42,6 +42,29 @@
QT_BEGIN_NAMESPACE
+// This template is used indirectly by the Q_GLOBAL_STATIC macro below
+template<>
+class QGlobalStaticDeleter<QJSValuePrivate>
+{
+public:
+ QGlobalStatic<QJSValuePrivate> &globalStatic;
+ QGlobalStaticDeleter(QGlobalStatic<QJSValuePrivate> &_globalStatic)
+ : globalStatic(_globalStatic)
+ {
+ globalStatic.pointer->ref.ref();
+ }
+
+ inline ~QGlobalStaticDeleter()
+ {
+ if (!globalStatic.pointer->ref.deref()) { // Logic copy & paste from SharedDataPointer
+ delete globalStatic.pointer;
+ }
+ globalStatic.pointer = 0;
+ globalStatic.destroyed = true;
+ }
+};
+
+Q_GLOBAL_STATIC(QJSValuePrivate, InvalidValue)
QJSValuePrivate* QJSValuePrivate::get(const QJSValue& q) { Q_ASSERT(q.d_ptr.data()); return q.d_ptr.data(); }
@@ -803,6 +826,8 @@ inline QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::property(const QStri
{
if (!name.length())
return InvalidValue();
+ if (!isObject())
+ return InvalidValue();
v8::HandleScope handleScope;
return property(QJSConverter::toString(name));
@@ -1013,12 +1038,14 @@ bool QJSValuePrivate::assignEngine(QV8Engine* engine)
/*!
\internal
- reinitialize this value to an invalid value.
+ Invalidates this value.
+
+ Does not remove the value from the engine's list of
+ registered values; that's the responsibility of the caller.
*/
-void QJSValuePrivate::reinitialize()
+void QJSValuePrivate::invalidate()
{
if (isJSBased()) {
- m_engine->unregisterValue(this);
m_value.Dispose();
m_value.Clear();
} else if (isStringBased()) {
@@ -1028,26 +1055,6 @@ void QJSValuePrivate::reinitialize()
m_state = Invalid;
}
-/*!
- \internal
- reinitialize this value to an JSValue.
-*/
-void QJSValuePrivate::reinitialize(QV8Engine* engine, v8::Handle<v8::Value> value)
-{
- Q_ASSERT_X(this != InvalidValue(), Q_FUNC_INFO, "static invalid can't be reinitialized to a different value");
- if (isJSBased()) {
- m_value.Dispose();
- // avoid double registration
- m_engine->unregisterValue(this);
- } else if (isStringBased()) {
- delete u.m_string;
- }
- m_engine = engine;
- m_state = JSValue;
- m_value = v8::Persistent<v8::Value>::New(value);
- m_engine->registerValue(this);
-}
-
QV8Engine* QJSValuePrivate::engine() const
{
return m_engine;
diff --git a/src/declarative/qml/v8/qjsvalue_p.h b/src/declarative/qml/v8/qjsvalue_p.h
index 7b2a001f97..09cd38b0bf 100644
--- a/src/declarative/qml/v8/qjsvalue_p.h
+++ b/src/declarative/qml/v8/qjsvalue_p.h
@@ -43,19 +43,20 @@
#include <QtCore/qvarlengtharray.h>
#include <qdebug.h>
-#include "qscripttools_p.h"
+#include <private/qintrusivelist_p.h>
#include "qscriptshareddata_p.h"
#include "qjsvalue.h"
QT_BEGIN_NAMESPACE
+class QV8Engine;
+
/*!
\internal
\class QJSValuePrivate
*/
class QJSValuePrivate
: public QSharedData
- , public QScriptLinkedNode
{
public:
inline QJSValuePrivate();
@@ -79,8 +80,7 @@ public:
inline QJSValuePrivate(QV8Engine *engine, const QString& value);
inline QJSValuePrivate(QV8Engine *engine, QJSValue::SpecialValue value);
inline QJSValuePrivate(QV8Engine *engine, v8::Handle<v8::Value>);
- inline void reinitialize();
- inline void reinitialize(QV8Engine *engine, v8::Handle<v8::Value> value);
+ inline void invalidate();
inline bool toBool() const;
inline double toNumber() const;
@@ -147,6 +147,7 @@ public:
inline operator v8::Handle<v8::Object>() const;
inline v8::Handle<v8::Value> asV8Value(QV8Engine *engine);
private:
+ QIntrusiveListNode m_node;
QV8Engine *m_engine;
// Please, update class documentation when you change the enum.
@@ -182,32 +183,10 @@ private:
inline bool isNumberBased() const;
inline bool isStringBased() const;
inline bool prepareArgumentsForCall(v8::Handle<v8::Value> argv[], const QJSValueList& arguments) const;
-};
-// This template is used indirectly by the Q_GLOBAL_STATIC macro below
-template<>
-class QGlobalStaticDeleter<QJSValuePrivate>
-{
-public:
- QGlobalStatic<QJSValuePrivate> &globalStatic;
- QGlobalStaticDeleter(QGlobalStatic<QJSValuePrivate> &_globalStatic)
- : globalStatic(_globalStatic)
- {
- globalStatic.pointer->ref.ref();
- }
-
- inline ~QGlobalStaticDeleter()
- {
- if (!globalStatic.pointer->ref.deref()) { // Logic copy & paste from SharedDataPointer
- delete globalStatic.pointer;
- }
- globalStatic.pointer = 0;
- globalStatic.destroyed = true;
- }
+ friend class QV8Engine;
};
-Q_GLOBAL_STATIC(QJSValuePrivate, InvalidValue)
-
QT_END_NAMESPACE
#endif
diff --git a/src/declarative/qml/v8/qjsvalueiterator.cpp b/src/declarative/qml/v8/qjsvalueiterator.cpp
index ca9123f0c0..76a43c9475 100644
--- a/src/declarative/qml/v8/qjsvalueiterator.cpp
+++ b/src/declarative/qml/v8/qjsvalueiterator.cpp
@@ -22,6 +22,7 @@
****************************************************************************/
#include "qjsvalueiterator.h"
+#include "qjsvalueiterator_p.h"
#include "qscriptisolate_p.h"
#include "qjsvalue_p.h"
@@ -35,7 +36,7 @@ QT_BEGIN_NAMESPACE
\brief The QJSValueIterator class provides a Java-style iterator for QJSValue.
- \ingroup script
+ \ingroup qtjavascript
The QJSValueIterator constructor takes a QJSValue as
@@ -43,169 +44,28 @@ QT_BEGIN_NAMESPACE
beginning of the sequence of properties. Here's how to iterate over
all the properties of a QJSValue:
- \snippet doc/src/snippets/code/src_script_QJSValueIterator.cpp 0
+ \snippet doc/src/snippets/code/src_script_qjsvalueiterator.cpp 0
- The next() advances the iterator. The name(), value() and flags()
- functions return the name, value and flags of the last item that was
+ The next() advances the iterator. The name() and value()
+ functions return the name and value of the last item that was
jumped over.
- If you want to remove properties as you iterate over the
- QJSValue, use remove(). If you want to modify the value of a
- property, use setValue().
-
Note that QJSValueIterator only iterates over the QJSValue's
own properties; i.e. it does not follow the prototype chain. You can
use a loop like this to follow the prototype chain:
- \snippet doc/src/snippets/code/src_script_QJSValueIterator.cpp 1
+ \snippet doc/src/snippets/code/src_script_qjsvalueiterator.cpp 1
Note that QJSValueIterator will not automatically skip over
properties that have the QJSValue::SkipInEnumeration flag set;
that flag only affects iteration in script code. If you want, you
can skip over such properties with code like the following:
- \snippet doc/src/snippets/code/src_script_QJSValueIterator.cpp 2
+ \snippet doc/src/snippets/code/src_script_qjsvalueiterator.cpp 2
\sa QJSValue::property()
*/
-using v8::Persistent;
-using v8::Local;
-using v8::Array;
-using v8::String;
-using v8::Handle;
-using v8::Object;
-using v8::Value;
-
-// FIXME (Qt5) This class should be refactored. It should use the common Iterator interface.
-// FIXME it could be faster!
-class QJSValueIteratorPrivate {
-public:
- inline QJSValueIteratorPrivate(const QJSValuePrivate* value);
- inline ~QJSValueIteratorPrivate();
-
- inline bool hasNext() const;
- inline bool next();
-
- inline QString name() const;
-
- inline QScriptPassPointer<QJSValuePrivate> value() const;
-
- inline bool isValid() const;
- inline QV8Engine* engine() const;
-private:
- Q_DISABLE_COPY(QJSValueIteratorPrivate)
- //void dump(QString) const;
-
- QScriptSharedDataPointer<QJSValuePrivate> m_object;
- QList<v8::Persistent<v8::String> > m_names;
- QMutableListIterator<v8::Persistent<v8::String> > m_iterator;
-};
-
-inline QJSValueIteratorPrivate::QJSValueIteratorPrivate(const QJSValuePrivate* value)
- : m_object(const_cast<QJSValuePrivate*>(value))
- , m_iterator(m_names)
-{
- Q_ASSERT(value);
- QV8Engine *engine = m_object->engine();
- QScriptIsolate api(engine);
- if (!m_object->isObject())
- m_object = 0;
- else {
- v8::HandleScope scope;
- Handle<Value> tmp = *value;
- Handle<Object> obj = Handle<Object>::Cast(tmp);
- Local<Array> names;
-
- // FIXME we need newer V8!
- //names = obj->GetOwnPropertyNames();
- names = engine->getOwnPropertyNames(obj);
-
- // it is suboptimal, it would be better to write iterator instead
- uint32_t count = names->Length();
- Local<String> name;
- m_names.reserve(count); // The count is the maximal count of values.
- for (uint32_t i = count - 1; i < count; --i) {
- name = names->Get(i)->ToString();
- m_names.append(v8::Persistent<v8::String>::New(name));
- }
-
- // Reinitialize the iterator.
- m_iterator = m_names;
- }
-}
-
-inline QJSValueIteratorPrivate::~QJSValueIteratorPrivate()
-{
- QMutableListIterator<v8::Persistent<v8::String> > it = m_names;
- //FIXME: we need register this QJSVAlueIterator
- if (engine()) {
- while (it.hasNext()) {
- it.next().Dispose();
- }
- } else {
- // FIXME leak ?
- }
-}
-
-inline bool QJSValueIteratorPrivate::hasNext() const
-{
- //dump("hasNext()");
- return isValid()
- ? m_iterator.hasNext() : false;
-}
-
-inline bool QJSValueIteratorPrivate::next()
-{
- //dump("next();");
- if (m_iterator.hasNext()) {
- m_iterator.next();
- return true;
- }
- return false;
-}
-
-inline QString QJSValueIteratorPrivate::name() const
-{
- //dump("name");
- if (!isValid())
- return QString();
-
- return QJSConverter::toString(m_iterator.value());
-}
-
-inline QScriptPassPointer<QJSValuePrivate> QJSValueIteratorPrivate::value() const
-{
- //dump("value()");
- if (!isValid())
- return InvalidValue();
-
- return m_object->property(m_iterator.value());
-}
-
-inline bool QJSValueIteratorPrivate::isValid() const
-{
- bool result = m_object ? m_object->isValid() : false;
- // We know that if this object is still valid then it is an object
- // if this assumption is not correct then some other logic in this class
- // have to be changed too.
- Q_ASSERT(!result || m_object->isObject());
- return result;
-}
-
-inline QV8Engine* QJSValueIteratorPrivate::engine() const
-{
- return m_object ? m_object->engine() : 0;
-}
-
-//void QJSValueIteratorPrivate::dump(QString fname) const
-//{
-// qDebug() << " *** " << fname << " ***";
-// foreach (Persistent<String> name, m_names) {
-// qDebug() << " - " << QJSConverter::toString(name);
-// }
-//}
-
/*!
Constructs an iterator for traversing \a object. The iterator is
set to be at the front of the sequence of properties (before the
@@ -226,7 +86,7 @@ QJSValueIterator::~QJSValueIterator()
(i.e. the iterator is \e not at the back of the property sequence);
otherwise returns false.
- \sa next(), hasPrevious()
+ \sa next()
*/
bool QJSValueIterator::hasNext() const
{
@@ -237,11 +97,14 @@ bool QJSValueIterator::hasNext() const
/*!
Advances the iterator by one position.
+ Returns true if there is at least one item ahead of the iterator
+ (i.e. the iterator is \e not at the back of the property sequence);
+ otherwise returns false.
Calling this function on an iterator located at the back of the
container leads to undefined results.
- \sa hasNext(), previous(), name()
+ \sa hasNext(), name()
*/
bool QJSValueIterator::next()
{
@@ -252,9 +115,9 @@ bool QJSValueIterator::next()
/*!
Returns the name of the last property that was jumped over using
- next() or previous().
+ next().
- \sa value(), flags()
+ \sa value()
*/
QString QJSValueIterator::name() const
{
@@ -266,9 +129,9 @@ QString QJSValueIterator::name() const
/*!
Returns the value of the last property that was jumped over using
- next() or previous().
+ next().
- \sa setValue(), name()
+ \sa name()
*/
QJSValue QJSValueIterator::value() const
{
diff --git a/src/declarative/qml/v8/qjsvalueiterator.h b/src/declarative/qml/v8/qjsvalueiterator.h
index 1ec4d4b63b..575421d33e 100644
--- a/src/declarative/qml/v8/qjsvalueiterator.h
+++ b/src/declarative/qml/v8/qjsvalueiterator.h
@@ -31,12 +31,12 @@ QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
-QT_MODULE(Script)
+QT_MODULE(Declarative)
class QString;
class QJSValueIteratorPrivate;
-class Q_SCRIPT_EXPORT QJSValueIterator
+class Q_DECLARATIVE_EXPORT QJSValueIterator
{
public:
QJSValueIterator(const QJSValue &value);
diff --git a/src/declarative/qml/v8/qjsvalueiterator_impl_p.h b/src/declarative/qml/v8/qjsvalueiterator_impl_p.h
new file mode 100644
index 0000000000..68075e55f3
--- /dev/null
+++ b/src/declarative/qml/v8/qjsvalueiterator_impl_p.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QJSVALUEITERATOR_IMPL_P_H
+#define QJSVALUEITERATOR_IMPL_P_H
+
+#include <qjsvalueiterator_p.h>
+#include <qv8engine_p.h>
+#include <qjsconverter_p.h>
+
+inline QJSValueIteratorPrivate::QJSValueIteratorPrivate(const QJSValuePrivate* value)
+ : m_object(const_cast<QJSValuePrivate*>(value))
+ , m_index(0)
+ , m_count(0)
+{
+ Q_ASSERT(value);
+ QV8Engine *engine = m_object->engine();
+ if (!m_object->isObject())
+ m_object = 0;
+ else {
+ QScriptIsolate api(engine, QScriptIsolate::NotNullEngine);
+ v8::HandleScope scope;
+
+ v8::Handle<v8::Value> tmp = *value;
+ v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(tmp);
+ v8::Local<v8::Array> names;
+
+ // FIXME we need newer V8!
+ //names = obj->GetOwnPropertyNames();
+ names = engine->getOwnPropertyNames(obj);
+ m_names = v8::Persistent<v8::Array>::New(names);
+ m_count = names->Length();
+
+ engine->registerValueIterator(this);
+ }
+}
+
+inline QJSValueIteratorPrivate::~QJSValueIteratorPrivate()
+{
+ if (isValid()) {
+ engine()->unregisterValueIterator(this);
+ m_names.Dispose();
+ }
+}
+
+inline void QJSValueIteratorPrivate::invalidate()
+{
+ m_names.Dispose();
+ m_object.reset();
+ m_index = 0;
+ m_count = 0;
+}
+
+inline bool QJSValueIteratorPrivate::hasNext() const
+{
+ return isValid() ? m_index < m_count : false;
+}
+
+inline bool QJSValueIteratorPrivate::next()
+{
+ if (hasNext()) {
+ ++m_index;
+ return true;
+ }
+ return false;
+}
+
+inline QString QJSValueIteratorPrivate::name() const
+{
+ if (!isValid())
+ return QString();
+
+ v8::HandleScope handleScope;
+ return QJSConverter::toString(m_names->Get(m_index - 1)->ToString());
+}
+
+inline QScriptPassPointer<QJSValuePrivate> QJSValueIteratorPrivate::value() const
+{
+ if (!isValid())
+ return InvalidValue();
+
+ v8::HandleScope handleScope;
+ return m_object->property(m_names->Get(m_index - 1)->ToString());
+}
+
+inline bool QJSValueIteratorPrivate::isValid() const
+{
+ bool result = m_object ? m_object->isValid() : false;
+ // We know that if this object is still valid then it is an object
+ // if this assumption is not correct then some other logic in this class
+ // have to be changed too.
+ Q_ASSERT(!result || m_object->isObject());
+ return result;
+}
+
+inline QV8Engine* QJSValueIteratorPrivate::engine() const
+{
+ return m_object ? m_object->engine() : 0;
+}
+
+#endif // QJSVALUEITERATOR_IMPL_P_H
diff --git a/src/declarative/qml/v8/qjsvalueiterator_p.h b/src/declarative/qml/v8/qjsvalueiterator_p.h
new file mode 100644
index 0000000000..6113d3dd4f
--- /dev/null
+++ b/src/declarative/qml/v8/qjsvalueiterator_p.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QJSVALUEITERATOR_P_H
+#define QJSVALUEITERATOR_P_H
+
+#include <private/qintrusivelist_p.h>
+#include "qjsvalue_p.h"
+
+#include <private/qv8_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QV8Engine;
+
+class QJSValueIteratorPrivate
+{
+public:
+ inline QJSValueIteratorPrivate(const QJSValuePrivate* value);
+ inline ~QJSValueIteratorPrivate();
+
+ inline bool hasNext() const;
+ inline bool next();
+
+ inline QString name() const;
+
+ inline QScriptPassPointer<QJSValuePrivate> value() const;
+
+ inline bool isValid() const;
+ inline QV8Engine* engine() const;
+
+ inline void invalidate();
+private:
+ Q_DISABLE_COPY(QJSValueIteratorPrivate)
+
+ QIntrusiveListNode m_node;
+ QScriptSharedDataPointer<QJSValuePrivate> m_object;
+ v8::Persistent<v8::Array> m_names;
+ uint32_t m_index;
+ uint32_t m_count;
+
+ friend class QV8Engine;
+};
+
+
+QT_END_NAMESPACE
+
+#endif // QJSVALUEITERATOR_P_H
diff --git a/src/declarative/qml/v8/qscript_impl_p.h b/src/declarative/qml/v8/qscript_impl_p.h
index e66b561efe..d197d9fd6b 100644
--- a/src/declarative/qml/v8/qscript_impl_p.h
+++ b/src/declarative/qml/v8/qscript_impl_p.h
@@ -37,5 +37,6 @@
#include "qv8engine_impl_p.h"
#include "qjsvalue_impl_p.h"
+#include "qjsvalueiterator_impl_p.h"
#endif //QSCRIPT_IMPL_P_H
diff --git a/src/declarative/qml/v8/qscriptoriginalglobalobject_p.h b/src/declarative/qml/v8/qscriptoriginalglobalobject_p.h
index c46d0e37a0..c0a761f518 100644
--- a/src/declarative/qml/v8/qscriptoriginalglobalobject_p.h
+++ b/src/declarative/qml/v8/qscriptoriginalglobalobject_p.h
@@ -49,7 +49,7 @@ class QV8Engine;
class QScriptOriginalGlobalObject
{
public:
- inline QScriptOriginalGlobalObject(const QV8Engine *engine, v8::Handle<v8::Context> context);
+ inline QScriptOriginalGlobalObject(v8::Handle<v8::Context> context);
inline void destroy();
inline QJSValue::PropertyFlags getPropertyFlags(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property);
@@ -63,7 +63,7 @@ private:
v8::Persistent<v8::Object> m_globalObject;
};
-QScriptOriginalGlobalObject::QScriptOriginalGlobalObject(const QV8Engine *engine, v8::Handle<v8::Context> context)
+QScriptOriginalGlobalObject::QScriptOriginalGlobalObject(v8::Handle<v8::Context> context)
{
// Please notice that engine is not fully initialized at this point.
diff --git a/src/declarative/qml/v8/qscripttools_p.h b/src/declarative/qml/v8/qscripttools_p.h
index f74fbab83f..c8dace0b9f 100644
--- a/src/declarative/qml/v8/qscripttools_p.h
+++ b/src/declarative/qml/v8/qscripttools_p.h
@@ -36,180 +36,32 @@
#ifndef QSCRIPTTOOLS_P_H
#define QSCRIPTTOOLS_P_H
-#include <qdebug.h>
+#include <private/qintrusivelist_p.h>
QT_BEGIN_NAMESPACE
-template<class T>
-class QScriptBagContainer;
-
-/*!
- \internal
- \interface
- Helper class for a container. The purpuse of it is to add two pointer properties to a class
- inheriting this class without bloating an interface.
-
- This class exist only as a memory storage implementation. The only way to use it is to inherit it.
-*/
-class QScriptLinkedNode
+template<class N, QIntrusiveListNode N::*member>
+class QScriptIntrusiveList : public QIntrusiveList<N, member>
{
-protected:
- QScriptLinkedNode()
- : m_next(0)
- , m_prev(0)
- {}
-
- ~QScriptLinkedNode()
- {
- Q_ASSERT_X(!isUsed(), Q_FUNC_INFO, "Destorying QScriptLinkedNode instance that still is in a container");
- }
-
-private:
- bool isUsed() const
- {
- return m_next || m_prev;
- }
-
-#if defined(Q_NO_TEMPLATE_FRIENDS)
public:
-#else
- template<class T>
- friend class QScriptBagContainer;
-#endif
- QScriptLinkedNode *m_next;
- QScriptLinkedNode *m_prev;
+ inline void insert(N *n);
+ inline void remove(N *n);
};
-/*!
- \internal
- The QScriptBagContainer is a simple, low level, set like container for a pointer type castable to
- QScriptLinkedNode*.
- Algorithms complexity:
- put: O(1)
- get: O(1)
- forEach: O(n)
- \note This container doesn't take ownership of pointed values.
- \attention All values have to be unique.
-*/
-template<class T>
-class QScriptBagContainer
+template<class N, QIntrusiveListNode N::*member>
+void QScriptIntrusiveList<N, member>::insert(N *n)
{
-public:
- QScriptBagContainer()
- : m_first(0)
- {}
-
- /*!
- \internal
- Add a this \a value to this container
- */
- void insert(T* value)
- {
- //dump(Q_FUNC_INFO, value);
- Q_ASSERT_X(!contains(value), Q_FUNC_INFO, "Can't insert a value which is in the bag already");
- QScriptLinkedNode* v = static_cast<QScriptLinkedNode*>(value);
- Q_ASSERT(v);
- Q_ASSERT_X(!v->m_next && !v->m_prev, Q_FUNC_INFO, "Can't insert a value which is in an another bag");
-
- if (m_first)
- m_first->m_prev = v;
-
- v->m_next = m_first;
- v->m_prev = 0;
- m_first = v;
- }
-
- /*!
- \internal
- Remove this \a value from this container
- */
- void remove(T* value)
- {
- //dump(Q_FUNC_INFO, value);
- QScriptLinkedNode* v = static_cast<QScriptLinkedNode*>(value);
- Q_ASSERT(v);
+ Q_ASSERT_X(!contains(n), Q_FUNC_INFO, "Can't insert a value which is in the list already");
+ Q_ASSERT_X(!(n->*member).isInList(), Q_FUNC_INFO, "Can't insert a value which is in another list");
+ QIntrusiveList<N, member>::insert(n);
+}
- if (!v->m_next && !v->m_prev && m_first != v) {
- // ignore that value as it is not registered at all
- // FIXME: That may be optimized out if unregister call is removed from ~QtDataBase
- return;
- }
-
- Q_ASSERT_X(contains(value), Q_FUNC_INFO, "Can't remove a value which is not in the bag");
- Q_ASSERT(v->m_prev || (m_first == v && !v->m_prev));
-
- if (v->m_next)
- v->m_next->m_prev= v->m_prev;
-
- if (v->m_prev)
- v->m_prev->m_next = v->m_next;
- else
- m_first = v->m_next;
- // reset removed value
- v->m_next = v->m_prev = 0;
- }
-
- /*!
- \internal
- Call \a fun for each element in this container. Fun should accept T* as a parameter.
- \note In general it is not allowed to change this container by calling put() or get() unless
- given value is the same as currently procceded by forEach.
- */
- template<class Functor>
- void forEach(Functor fun)
- {
- //dump(Q_FUNC_INFO);
- QScriptLinkedNode *i = m_first;
- QScriptLinkedNode *tmp;
- while (i) {
- tmp = i;
- i = i->m_next;
- fun(static_cast<T*>(tmp));
- }
- }
-
- /*!
- \internal
- Clear this container.
- */
- void clear()
- {
- m_first = 0;
- }
-
- /*!
- \internal
- Returns true if this container is empty; false otherwise.
- */
- bool isEmpty() const
- {
- return !m_first;
- }
-
-// void dump(const char* msg, T* obj = 0) const
-// {
-// qDebug() << msg << obj;
-// qDebug() << m_first;
-// QScriptLinkedNode *i = m_first;
-// while (i) {
-// qDebug() <<" - " << i << "(" << i->m_prev << ", " << i->m_next <<")";
-// i = i->m_next;
-// }
-// }
-
-private:
- bool contains(T *value) const
- {
- QScriptLinkedNode *i = m_first;
- while (i) {
- if (static_cast<T*>(i) == value)
- return true;
- i = i->m_next;
- }
- return false;
- }
- QScriptLinkedNode *m_first;
-};
+template<class N, QIntrusiveListNode N::*member>
+void QScriptIntrusiveList<N, member>::remove(N *n)
+{
+ Q_ASSERT_X(contains(n), Q_FUNC_INFO, "Can't remove a value which is not in the list");
+ QIntrusiveList<N, member>::remove(n);
+}
QT_END_NAMESPACE
diff --git a/src/declarative/qml/v8/qv8_p.h b/src/declarative/qml/v8/qv8_p.h
index 6aeb6f6458..8df007e804 100644
--- a/src/declarative/qml/v8/qv8_p.h
+++ b/src/declarative/qml/v8/qv8_p.h
@@ -1 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
#include "../../../3rdparty/v8/include/v8.h"
diff --git a/src/declarative/qml/v8/qv8bindings.cpp b/src/declarative/qml/v8/qv8bindings.cpp
index c45274a97f..3c98af2951 100644
--- a/src/declarative/qml/v8/qv8bindings.cpp
+++ b/src/declarative/qml/v8/qv8bindings.cpp
@@ -7,29 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** 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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
diff --git a/src/declarative/qml/v8/qv8bindings_p.h b/src/declarative/qml/v8/qv8bindings_p.h
index f8a9407ed8..b387a50df3 100644
--- a/src/declarative/qml/v8/qv8bindings_p.h
+++ b/src/declarative/qml/v8/qv8bindings_p.h
@@ -7,29 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** 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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
diff --git a/src/declarative/qml/v8/qv8contextwrapper.cpp b/src/declarative/qml/v8/qv8contextwrapper.cpp
index 4984102ba2..f41c994a0d 100644
--- a/src/declarative/qml/v8/qv8contextwrapper.cpp
+++ b/src/declarative/qml/v8/qv8contextwrapper.cpp
@@ -7,29 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** 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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
diff --git a/src/declarative/qml/v8/qv8debug_p.h b/src/declarative/qml/v8/qv8debug_p.h
new file mode 100644
index 0000000000..51208aac8e
--- /dev/null
+++ b/src/declarative/qml/v8/qv8debug_p.h
@@ -0,0 +1 @@
+#include "../../../3rdparty/v8/include/v8-debug.h"
diff --git a/src/declarative/qml/v8/qv8domerrors.cpp b/src/declarative/qml/v8/qv8domerrors.cpp
new file mode 100644
index 0000000000..e739e4a7bd
--- /dev/null
+++ b/src/declarative/qml/v8/qv8domerrors.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv8domerrors_p.h"
+#include "qv8engine_p.h"
+
+QT_BEGIN_NAMESPACE
+
+void qt_add_domexceptions(QV8Engine *engine)
+{
+ // DOM Exception
+ v8::PropertyAttribute attributes = (v8::PropertyAttribute)(v8::ReadOnly | v8::DontEnum | v8::DontDelete);
+
+ v8::Local<v8::Object> domexception = v8::Object::New();
+ domexception->Set(v8::String::New("INDEX_SIZE_ERR"), v8::Integer::New(DOMEXCEPTION_INDEX_SIZE_ERR), attributes);
+ domexception->Set(v8::String::New("DOMSTRING_SIZE_ERR"), v8::Integer::New(DOMEXCEPTION_DOMSTRING_SIZE_ERR), attributes);
+ domexception->Set(v8::String::New("HIERARCHY_REQUEST_ERR"), v8::Integer::New(DOMEXCEPTION_HIERARCHY_REQUEST_ERR), attributes);
+ domexception->Set(v8::String::New("WRONG_DOCUMENT_ERR"), v8::Integer::New(DOMEXCEPTION_WRONG_DOCUMENT_ERR), attributes);
+ domexception->Set(v8::String::New("INVALID_CHARACTER_ERR"), v8::Integer::New(DOMEXCEPTION_INVALID_CHARACTER_ERR), attributes);
+ domexception->Set(v8::String::New("NO_DATA_ALLOWED_ERR"), v8::Integer::New(DOMEXCEPTION_NO_DATA_ALLOWED_ERR), attributes);
+ domexception->Set(v8::String::New("NO_MODIFICATION_ALLOWED_ERR"), v8::Integer::New(DOMEXCEPTION_NO_MODIFICATION_ALLOWED_ERR), attributes);
+ domexception->Set(v8::String::New("NOT_FOUND_ERR"), v8::Integer::New(DOMEXCEPTION_NOT_FOUND_ERR), attributes);
+ domexception->Set(v8::String::New("NOT_SUPPORTED_ERR"), v8::Integer::New(DOMEXCEPTION_NOT_SUPPORTED_ERR), attributes);
+ domexception->Set(v8::String::New("INUSE_ATTRIBUTE_ERR"), v8::Integer::New(DOMEXCEPTION_INUSE_ATTRIBUTE_ERR), attributes);
+ domexception->Set(v8::String::New("INVALID_STATE_ERR"), v8::Integer::New(DOMEXCEPTION_INVALID_STATE_ERR), attributes);
+ domexception->Set(v8::String::New("SYNTAX_ERR"), v8::Integer::New(DOMEXCEPTION_SYNTAX_ERR), attributes);
+ domexception->Set(v8::String::New("INVALID_MODIFICATION_ERR"), v8::Integer::New(DOMEXCEPTION_INVALID_MODIFICATION_ERR), attributes);
+ domexception->Set(v8::String::New("NAMESPACE_ERR"), v8::Integer::New(DOMEXCEPTION_NAMESPACE_ERR), attributes);
+ domexception->Set(v8::String::New("INVALID_ACCESS_ERR"), v8::Integer::New(DOMEXCEPTION_INVALID_ACCESS_ERR), attributes);
+ domexception->Set(v8::String::New("VALIDATION_ERR"), v8::Integer::New(DOMEXCEPTION_VALIDATION_ERR), attributes);
+ domexception->Set(v8::String::New("TYPE_MISMATCH_ERR"), v8::Integer::New(DOMEXCEPTION_TYPE_MISMATCH_ERR), attributes);
+ engine->global()->Set(v8::String::New("DOMException"), domexception);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgcustomaffector_p.h b/src/declarative/qml/v8/qv8domerrors_p.h
index b4d0ca7417..ef8ab28c12 100644
--- a/src/declarative/particles/qsgcustomaffector_p.h
+++ b/src/declarative/qml/v8/qv8domerrors_p.h
@@ -4,7 +4,7 @@
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the Declarative module of the Qt Toolkit.
+** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
@@ -39,31 +39,56 @@
**
****************************************************************************/
-#ifndef CUSTOMAFFECTOR_H
-#define CUSTOMAFFECTOR_H
-#include "qsgparticleaffector_p.h"
+#ifndef QV8DOMERRORS_P_H
+#define QV8DOMERRORS_P_H
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+#include <QtCore/qglobal.h>
-class QSGCustomAffector : public QSGParticleAffector
-{
- Q_OBJECT
-public:
- explicit QSGCustomAffector(QSGItem *parent = 0);
-protected:
- virtual bool affectParticle(QSGParticleData *d, qreal dt);
-signals:
- void affectParticle(QDeclarativeV8Handle particle, qreal dt);
+QT_BEGIN_HEADER
-public slots:
+QT_BEGIN_NAMESPACE
+// From DOM-Level-3-Core spec
+// http://www.w3.org/TR/DOM-Level-3-Core/core.html
+#define DOMEXCEPTION_INDEX_SIZE_ERR 1
+#define DOMEXCEPTION_DOMSTRING_SIZE_ERR 2
+#define DOMEXCEPTION_HIERARCHY_REQUEST_ERR 3
+#define DOMEXCEPTION_WRONG_DOCUMENT_ERR 4
+#define DOMEXCEPTION_INVALID_CHARACTER_ERR 5
+#define DOMEXCEPTION_NO_DATA_ALLOWED_ERR 6
+#define DOMEXCEPTION_NO_MODIFICATION_ALLOWED_ERR 7
+#define DOMEXCEPTION_NOT_FOUND_ERR 8
+#define DOMEXCEPTION_NOT_SUPPORTED_ERR 9
+#define DOMEXCEPTION_INUSE_ATTRIBUTE_ERR 10
+#define DOMEXCEPTION_INVALID_STATE_ERR 11
+#define DOMEXCEPTION_SYNTAX_ERR 12
+#define DOMEXCEPTION_INVALID_MODIFICATION_ERR 13
+#define DOMEXCEPTION_NAMESPACE_ERR 14
+#define DOMEXCEPTION_INVALID_ACCESS_ERR 15
+#define DOMEXCEPTION_VALIDATION_ERR 16
+#define DOMEXCEPTION_TYPE_MISMATCH_ERR 17
-};
+#define V8THROW_DOM(error, string) { \
+ v8::Local<v8::Value> v = v8::Exception::Error(v8::String::New(string)); \
+ v->ToObject()->Set(v8::String::New("code"), v8::Integer::New(error)); \
+ v8::ThrowException(v); \
+ return v8::Handle<v8::Value>(); \
+}
+class QV8Engine;
+void qt_add_domexceptions(QV8Engine *engine);
QT_END_NAMESPACE
+
QT_END_HEADER
-#endif // CUSTOMAFFECTOR_H
+
+#endif // QV8DOMERRORS_P_H
diff --git a/src/declarative/qml/v8/qv8engine.cpp b/src/declarative/qml/v8/qv8engine.cpp
index acbfb92b15..4f5caa13f4 100644
--- a/src/declarative/qml/v8/qv8engine.cpp
+++ b/src/declarative/qml/v8/qv8engine.cpp
@@ -7,29 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** 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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
@@ -42,6 +42,7 @@
#include "qv8engine_p.h"
#include "qv8contextwrapper_p.h"
+#include "qv8valuetypewrapper_p.h"
#include "qv8include_p.h"
#include "../../../3rdparty/javascriptcore/DateMath.h"
@@ -63,6 +64,7 @@
#include <private/qdeclarativesqldatabase_p.h>
#include "qscript_impl_p.h"
+#include "qv8domerrors_p.h"
Q_DECLARE_METATYPE(QJSValue)
Q_DECLARE_METATYPE(QList<int>)
@@ -87,10 +89,20 @@ static bool ObjectComparisonCallback(v8::Local<v8::Object> lhs, v8::Local<v8::Ob
QV8ObjectResource::ResourceType rhst = rhsr->resourceType();
switch (lhst) {
+ case QV8ObjectResource::ValueTypeType:
+ if (rhst == QV8ObjectResource::ValueTypeType) {
+ return lhsr->engine->valueTypeWrapper()->isEqual(lhsr, lhsr->engine->valueTypeWrapper()->toVariant(rhsr));
+ } else if (rhst == QV8ObjectResource::VariantType) {
+ return lhsr->engine->valueTypeWrapper()->isEqual(lhsr, lhsr->engine->variantWrapper()->toVariant(rhsr));
+ }
+ break;
case QV8ObjectResource::VariantType:
- if (rhst == QV8ObjectResource::VariantType)
+ if (rhst == QV8ObjectResource::VariantType) {
return lhsr->engine->variantWrapper()->toVariant(lhsr) ==
lhsr->engine->variantWrapper()->toVariant(rhsr);
+ } else if (rhst == QV8ObjectResource::ValueTypeType) {
+ return rhsr->engine->valueTypeWrapper()->isEqual(rhsr, rhsr->engine->variantWrapper()->toVariant(lhsr));
+ }
break;
default:
break;
@@ -105,7 +117,7 @@ QV8Engine::QV8Engine(QJSEngine* qq, QJSEngine::ContextOwnership ownership)
, m_engine(0)
, m_ownsV8Context(ownership == QJSEngine::CreateNewContext)
, m_context((ownership == QJSEngine::CreateNewContext) ? v8::Context::New() : v8::Persistent<v8::Context>::New(v8::Context::GetCurrent()))
- , m_originalGlobalObject(this, m_context)
+ , m_originalGlobalObject(m_context)
, m_xmlHttpRequestData(0)
, m_sqlDatabaseData(0)
, m_listModelData(0)
@@ -265,55 +277,6 @@ static v8::Handle<v8::Object> objectFromVariantMap(QV8Engine *engine, const QVar
Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax);
-// Converts a QRegExp to a JS RegExp.
-// The conversion is not 100% exact since ECMA regexp and QRegExp
-// have different semantics/flags, but we try to do our best.
-static v8::Handle<v8::RegExp> regexpFromQRegExp(QV8Engine *engine, const QRegExp &re)
-{
- // Convert the pattern to a ECMAScript pattern.
- QString pattern = qt_regexp_toCanonical(re.pattern(), re.patternSyntax());
- if (re.isMinimal()) {
- QString ecmaPattern;
- int len = pattern.length();
- ecmaPattern.reserve(len);
- int i = 0;
- const QChar *wc = pattern.unicode();
- bool inBracket = false;
- while (i < len) {
- QChar c = wc[i++];
- ecmaPattern += c;
- switch (c.unicode()) {
- case '?':
- case '+':
- case '*':
- case '}':
- if (!inBracket)
- ecmaPattern += QLatin1Char('?');
- break;
- case '\\':
- if (i < len)
- ecmaPattern += wc[i++];
- break;
- case '[':
- inBracket = true;
- break;
- case ']':
- inBracket = false;
- break;
- default:
- break;
- }
- }
- pattern = ecmaPattern;
- }
-
- int flags = v8::RegExp::kNone;
- if (re.caseSensitivity() == Qt::CaseInsensitive)
- flags |= v8::RegExp::kIgnoreCase;
-
- return v8::RegExp::New(engine->toString(pattern), static_cast<v8::RegExp::Flags>(flags));
-}
-
v8::Handle<v8::Value> QV8Engine::fromVariant(const QVariant &variant)
{
int type = variant.userType();
@@ -356,7 +319,7 @@ v8::Handle<v8::Value> QV8Engine::fromVariant(const QVariant &variant)
case QMetaType::QTime:
return v8::Date::New(qtDateTimeToJsDate(QDateTime(QDate(1970,1,1), *reinterpret_cast<const QTime *>(ptr))));
case QMetaType::QRegExp:
- return regexpFromQRegExp(this, *reinterpret_cast<const QRegExp *>(ptr));
+ return QJSConverter::toRegExp(*reinterpret_cast<const QRegExp *>(ptr));
case QMetaType::QObjectStar:
case QMetaType::QWidgetStar:
return newQObject(*reinterpret_cast<QObject* const *>(ptr));
@@ -464,13 +427,13 @@ QVariant QV8Engine::toBasicVariant(v8::Handle<v8::Value> value)
{
if (value->IsNull() || value->IsUndefined())
return QVariant();
- else if (value->IsBoolean())
+ if (value->IsBoolean())
return value->ToBoolean()->Value();
- else if (value->IsInt32())
+ if (value->IsInt32())
return value->ToInt32()->Value();
- else if (value->IsNumber())
+ if (value->IsNumber())
return value->ToNumber()->Value();
- else if (value->IsString())
+ if (value->IsString())
return m_stringWrapper.toString(value->ToString());
if (value->IsDate())
return qtDateTimeFromJsDate(v8::Handle<v8::Date>::Cast(value)->NumberValue());
@@ -480,17 +443,9 @@ QVariant QV8Engine::toBasicVariant(v8::Handle<v8::Value> value)
if (value->IsRegExp()) {
v8::Context::Scope scope(context());
- v8::Handle<v8::RegExp> jsRegExp = v8::Handle<v8::RegExp>::Cast(value);
- // Copied from QtScript
- // Converts a JS RegExp to a QRegExp.
- // The conversion is not 100% exact since ECMA regexp and QRegExp
- // have different semantics/flags, but we try to do our best.
- QString pattern = toString(jsRegExp->GetSource());
- Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive;
- if (jsRegExp->GetFlags() & v8::RegExp::kIgnoreCase)
- caseSensitivity = Qt::CaseInsensitive;
- return QRegExp(pattern, caseSensitivity, QRegExp::RegExp2);
- } else if (value->IsArray()) {
+ return QJSConverter::toRegExp(v8::Handle<v8::RegExp>::Cast(value));
+ }
+ if (value->IsArray()) {
v8::Context::Scope scope(context());
QVariantList rv;
@@ -500,7 +455,8 @@ QVariant QV8Engine::toBasicVariant(v8::Handle<v8::Value> value)
rv << toVariant(array->Get(ii), -1);
return rv;
- } else if (!value->IsFunction()) {
+ }
+ if (!value->IsFunction()) {
v8::Context::Scope scope(context());
v8::Handle<v8::Object> object = value->ToObject();
v8::Local<v8::Array> properties = object->GetPropertyNames();
@@ -522,6 +478,7 @@ QVariant QV8Engine::toBasicVariant(v8::Handle<v8::Value> value)
#include <QtGui/qvector3d.h>
+#include <QtGui/qvector4d.h>
struct StaticQtMetaObject : public QObject
{
@@ -556,6 +513,7 @@ void QV8Engine::initializeGlobal(v8::Handle<v8::Object> global)
qt->Set(v8::String::New("point"), V8FUNCTION(point, this));
qt->Set(v8::String::New("size"), V8FUNCTION(size, this));
qt->Set(v8::String::New("vector3d"), V8FUNCTION(vector3d, this));
+ qt->Set(v8::String::New("vector4d"), V8FUNCTION(vector4d, this));
qt->Set(v8::String::New("formatDate"), V8FUNCTION(formatDate, this));
qt->Set(v8::String::New("formatTime"), V8FUNCTION(formatTime, this));
@@ -594,6 +552,7 @@ void QV8Engine::initializeGlobal(v8::Handle<v8::Object> global)
v8::Local<v8::Object> stringPrototype = v8::Local<v8::Object>::Cast(string->Get(v8::String::New("prototype")));
stringPrototype->Set(v8::String::New("arg"), V8FUNCTION(stringArg, this));
+ qt_add_domexceptions(this);
m_xmlHttpRequestData = qt_add_qmlxmlhttprequest(this);
m_sqlDatabaseData = qt_add_qmlsqldatabase(this);
@@ -891,6 +850,23 @@ v8::Handle<v8::Value> QV8Engine::vector3d(const v8::Arguments &args)
}
/*!
+\qmlmethod Qt::vector4d(real x, real y, real z, real w)
+Returns a Vector4D with the specified \c x, \c y, \c z and \c w.
+*/
+v8::Handle<v8::Value> QV8Engine::vector4d(const v8::Arguments &args)
+{
+ if (args.Length() != 4)
+ V8THROW_ERROR("Qt.vector4d(): Invalid arguments");
+
+ double x = args[0]->NumberValue();
+ double y = args[1]->NumberValue();
+ double z = args[2]->NumberValue();
+ double w = args[3]->NumberValue();
+
+ return V8ENGINE()->fromVariant(QVariant::fromValue(QVector4D(x, y, z, w)));
+}
+
+/*!
\qmlmethod color Qt::lighter(color baseColor, real factor)
Returns a color lighter than \c baseColor by the \c factor provided.
@@ -2131,14 +2107,14 @@ bool QV8Engine::metaTypeFromJS(v8::Handle<v8::Value> value, int type, void *data
}
#endif
- // Try to use magic.
+ // Try to use magic; for compatibility with qscriptvalue_cast.
QByteArray name = QMetaType::typeName(type);
if (convertToNativeQObject(value, name, reinterpret_cast<void* *>(data)))
return true;
if (isVariant(value) && name.endsWith('*')) {
int valueType = QMetaType::type(name.left(name.size()-1));
- QVariant var = variantValue(value);
+ QVariant &var = variantValue(value);
if (valueType == var.userType()) {
// We have T t, T* is requested, so return &t.
*reinterpret_cast<void* *>(data) = var.data();
@@ -2201,9 +2177,9 @@ QVariant QV8Engine::variantFromJS(v8::Handle<v8::Value> value)
return QVariant();
if (value->IsBoolean())
return value->ToBoolean()->Value();
- else if (value->IsInt32())
+ if (value->IsInt32())
return value->ToInt32()->Value();
- else if (value->IsNumber())
+ if (value->IsNumber())
return value->ToNumber()->Value();
if (value->IsString())
return QJSConverter::toString(value->ToString());
@@ -2259,10 +2235,9 @@ QObject *QV8Engine::qtObjectFromJS(v8::Handle<v8::Value> value)
}
-QVariant QV8Engine::variantValue(v8::Handle<v8::Value> value)
+QVariant &QV8Engine::variantValue(v8::Handle<v8::Value> value)
{
- Q_ASSERT(isVariant(value));
- return QV8Engine::toVariant(value, -1 /*whateever magic hint is*/);
+ return variantWrapper()->variantValue(value);
}
// Creates a QVariant wrapper object.
diff --git a/src/declarative/qml/v8/qv8engine_impl_p.h b/src/declarative/qml/v8/qv8engine_impl_p.h
index 5c56efdf39..53ce2a5acd 100644
--- a/src/declarative/qml/v8/qv8engine_impl_p.h
+++ b/src/declarative/qml/v8/qv8engine_impl_p.h
@@ -38,6 +38,7 @@
#include "qv8engine_p.h"
#include "qjsvalue_p.h"
#include "qjsconverter_p.h"
+#include "qjsvalueiterator_p.h"
QT_BEGIN_NAMESPACE
@@ -80,6 +81,10 @@ public:
{
value->reinitialize();
}
+ void operator () (QJSValueIteratorPrivate *iterator) const
+ {
+ iterator->invalidate();
+ }
};
inline void QV8Engine::registerValue(QJSValuePrivate *data)
@@ -94,9 +99,28 @@ inline void QV8Engine::unregisterValue(QJSValuePrivate *data)
inline void QV8Engine::invalidateAllValues()
{
- QtScriptBagCleaner invalidator;
- m_values.forEach(invalidator);
- m_values.clear();
+ ValueList::iterator it;
+ for (it = m_values.begin(); it != m_values.end(); it = it.erase())
+ (*it)->invalidate();
+ Q_ASSERT(m_values.isEmpty());
+}
+
+inline void QV8Engine::registerValueIterator(QJSValueIteratorPrivate *data)
+{
+ m_valueIterators.insert(data);
+}
+
+inline void QV8Engine::unregisterValueIterator(QJSValueIteratorPrivate *data)
+{
+ m_valueIterators.remove(data);
+}
+
+inline void QV8Engine::invalidateAllIterators()
+{
+ ValueIteratorList::iterator it;
+ for (it = m_valueIterators.begin(); it != m_valueIterators.end(); it = it.erase())
+ (*it)->invalidate();
+ Q_ASSERT(m_valueIterators.isEmpty());
}
/*!
diff --git a/src/declarative/qml/v8/qv8engine_p.h b/src/declarative/qml/v8/qv8engine_p.h
index b95e55002b..43ef9821ac 100644
--- a/src/declarative/qml/v8/qv8engine_p.h
+++ b/src/declarative/qml/v8/qv8engine_p.h
@@ -7,29 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** 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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
@@ -63,6 +63,8 @@
#include <private/qv8_p.h>
#include <qjsengine.h>
#include <qjsvalue.h>
+#include "qjsvalue_p.h"
+#include "qjsvalueiterator_p.h"
#include "qscriptoriginalglobalobject_p.h"
#include "qscripttools_p.h"
@@ -125,6 +127,7 @@ private:
return rv; \
} \
+
class QV8Engine;
class QV8ObjectResource : public v8::Object::ExternalResource
{
@@ -214,6 +217,7 @@ class QDeclarativeEngine;
class QDeclarativeValueType;
class QNetworkAccessManager;
class QDeclarativeContextData;
+
class Q_DECLARATIVE_EXPORT QV8Engine
{
public:
@@ -260,11 +264,16 @@ public:
inline void unregisterValue(QJSValuePrivate *data);
inline void invalidateAllValues();
+ inline void registerValueIterator(QJSValueIteratorPrivate *data);
+ inline void unregisterValueIterator(QJSValueIteratorPrivate *data);
+ inline void invalidateAllIterators();
+
QV8ContextWrapper *contextWrapper() { return &m_contextWrapper; }
QV8QObjectWrapper *qobjectWrapper() { return &m_qobjectWrapper; }
QV8TypeWrapper *typeWrapper() { return &m_typeWrapper; }
QV8ListWrapper *listWrapper() { return &m_listWrapper; }
QV8VariantWrapper *variantWrapper() { return &m_variantWrapper; }
+ QV8ValueTypeWrapper *valueTypeWrapper() { return &m_valueTypeWrapper; }
void *xmlHttpRequestData() { return m_xmlHttpRequestData; }
void *sqlDatabaseData() { return m_sqlDatabaseData; }
@@ -378,7 +387,7 @@ public:
const QByteArray &targetType,
void **result);
- QVariant variantValue(v8::Handle<v8::Value> value);
+ QVariant &variantValue(v8::Handle<v8::Value> value);
QJSValue scriptValueFromInternal(v8::Handle<v8::Value>) const;
@@ -427,6 +436,7 @@ protected:
static v8::Handle<v8::Value> point(const v8::Arguments &args);
static v8::Handle<v8::Value> size(const v8::Arguments &args);
static v8::Handle<v8::Value> vector3d(const v8::Arguments &args);
+ static v8::Handle<v8::Value> vector4d(const v8::Arguments &args);
static v8::Handle<v8::Value> lighter(const v8::Arguments &args);
static v8::Handle<v8::Value> darker(const v8::Arguments &args);
static v8::Handle<v8::Value> tint(const v8::Arguments &args);
@@ -452,10 +462,15 @@ protected:
double qtDateTimeToJsDate(const QDateTime &dt);
QDateTime qtDateTimeFromJsDate(double jsDate);
+
private:
- QScriptBagContainer<QJSValuePrivate> m_values;
+ typedef QScriptIntrusiveList<QJSValuePrivate, &QJSValuePrivate::m_node> ValueList;
+ ValueList m_values;
+ typedef QScriptIntrusiveList<QJSValueIteratorPrivate, &QJSValueIteratorPrivate::m_node> ValueIteratorList;
+ ValueIteratorList m_valueIterators;
Q_DISABLE_COPY(QV8Engine)
+ friend class QV8DebugService;
};
// Allocate a new Persistent handle. *ALL* persistent handles in QML must be allocated
diff --git a/src/declarative/qml/v8/qv8include.cpp b/src/declarative/qml/v8/qv8include.cpp
index 71937d0aad..1d68e8e4be 100644
--- a/src/declarative/qml/v8/qv8include.cpp
+++ b/src/declarative/qml/v8/qv8include.cpp
@@ -7,29 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** 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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
diff --git a/src/declarative/qml/v8/qv8listwrapper.cpp b/src/declarative/qml/v8/qv8listwrapper.cpp
index 5f2d9fb91e..777ce78686 100644
--- a/src/declarative/qml/v8/qv8listwrapper.cpp
+++ b/src/declarative/qml/v8/qv8listwrapper.cpp
@@ -7,29 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** 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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
@@ -135,7 +135,7 @@ v8::Handle<v8::Value> QV8ListWrapper::Getter(v8::Local<v8::String> property,
{
Q_UNUSED(property);
Q_UNUSED(info);
- return v8::Undefined();
+ return v8::Handle<v8::Value>();
}
v8::Handle<v8::Value> QV8ListWrapper::Setter(v8::Local<v8::String> property,
diff --git a/src/declarative/qml/v8/qv8listwrapper_p.h b/src/declarative/qml/v8/qv8listwrapper_p.h
index 82fdaa7271..8cbc7db0b8 100644
--- a/src/declarative/qml/v8/qv8listwrapper_p.h
+++ b/src/declarative/qml/v8/qv8listwrapper_p.h
@@ -7,29 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** 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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
diff --git a/src/declarative/qml/v8/qv8qobjectwrapper.cpp b/src/declarative/qml/v8/qv8qobjectwrapper.cpp
index f97f427ede..c7ed0116e1 100644
--- a/src/declarative/qml/v8/qv8qobjectwrapper.cpp
+++ b/src/declarative/qml/v8/qv8qobjectwrapper.cpp
@@ -7,29 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** 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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
@@ -336,7 +336,8 @@ static v8::Handle<v8::Value> LoadProperty(QV8Engine *engine, QObject *object,
void *args[] = { &handle, 0 };
QMetaObject::metacall(object, QMetaObject::ReadProperty, property.coreIndex, args);
return handle.toHandle();
- } else if (QDeclarativeValueTypeFactory::isValueType((uint)property.propType)) {
+ } else if (QDeclarativeValueTypeFactory::isValueType((uint)property.propType)
+ && engine->engine()) {
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine->engine());
QDeclarativeValueType *valueType = ep->valueTypes[property.propType];
if (valueType)
@@ -381,7 +382,8 @@ static v8::Handle<v8::Value> LoadPropertyDirect(QV8Engine *engine, QObject *obje
void *args[] = { &handle, 0 };
object->qt_metacall(QMetaObject::ReadProperty, property.coreIndex, args);
return handle.toHandle();
- } else if (QDeclarativeValueTypeFactory::isValueType((uint)property.propType)) {
+ } else if (QDeclarativeValueTypeFactory::isValueType((uint)property.propType)
+ && engine->engine()) {
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine->engine());
QDeclarativeValueType *valueType = ep->valueTypes[property.propType];
if (valueType)
@@ -600,7 +602,7 @@ v8::Handle<v8::Value> QV8QObjectWrapper::Getter(v8::Local<v8::String> property,
QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
if (resource->object.isNull())
- return v8::Undefined();
+ return v8::Handle<v8::Value>();
QObject *object = resource->object;
@@ -628,7 +630,7 @@ v8::Handle<v8::Value> QV8QObjectWrapper::Getter(v8::Local<v8::String> property,
}
}
- return v8::Undefined();
+ return v8::Handle<v8::Value>();
}
v8::Handle<v8::Value> QV8QObjectWrapper::Setter(v8::Local<v8::String> property,
diff --git a/src/declarative/qml/v8/qv8qobjectwrapper_p.h b/src/declarative/qml/v8/qv8qobjectwrapper_p.h
index dd787cc476..d0a489bed8 100644
--- a/src/declarative/qml/v8/qv8qobjectwrapper_p.h
+++ b/src/declarative/qml/v8/qv8qobjectwrapper_p.h
@@ -7,29 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** 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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
diff --git a/src/declarative/qml/v8/qv8stringwrapper.cpp b/src/declarative/qml/v8/qv8stringwrapper.cpp
index 883c4826c5..1fea98fdc0 100644
--- a/src/declarative/qml/v8/qv8stringwrapper.cpp
+++ b/src/declarative/qml/v8/qv8stringwrapper.cpp
@@ -7,29 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** 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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qv8stringwrapper_p.h"
+#include "qjsconverter_p.h"
QT_BEGIN_NAMESPACE
@@ -73,7 +74,7 @@ void QV8StringWrapper::destroy()
v8::Local<v8::String> QV8StringWrapper::toString(const QString &qstr)
{
// return v8::String::NewExternal(new QV8StringResource(qstr));
- return v8::String::New((uint16_t*)qstr.constData(), qstr.length());
+ return QJSConverter::toString(qstr);
}
QString QV8StringWrapper::toString(v8::Handle<v8::String> jsstr)
@@ -84,10 +85,7 @@ QString QV8StringWrapper::toString(v8::Handle<v8::String> jsstr)
QV8StringResource *r = (QV8StringResource *)jsstr->GetExternalStringResource();
return r->str;
} else {
- QString qstr;
- qstr.resize(jsstr->Length());
- jsstr->Write((uint16_t*)qstr.data());
- return qstr;
+ return QJSConverter::toString(jsstr);
}
}
diff --git a/src/declarative/qml/v8/qv8stringwrapper_p.h b/src/declarative/qml/v8/qv8stringwrapper_p.h
index 36c9e24c06..beef80ff10 100644
--- a/src/declarative/qml/v8/qv8stringwrapper_p.h
+++ b/src/declarative/qml/v8/qv8stringwrapper_p.h
@@ -7,29 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** 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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
diff --git a/src/declarative/qml/v8/qv8typewrapper.cpp b/src/declarative/qml/v8/qv8typewrapper.cpp
index fe30670fc2..c51a2eeb7f 100644
--- a/src/declarative/qml/v8/qv8typewrapper.cpp
+++ b/src/declarative/qml/v8/qv8typewrapper.cpp
@@ -7,29 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** 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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
@@ -150,7 +150,7 @@ v8::Handle<v8::Value> QV8TypeWrapper::Getter(v8::Local<v8::String> property,
}
}
- // Fall through to undefined
+ // Fall through to return empty handle
} else if (resource->object) {
QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(), object);
@@ -158,10 +158,10 @@ v8::Handle<v8::Value> QV8TypeWrapper::Getter(v8::Local<v8::String> property,
return v8engine->qobjectWrapper()->getProperty(ao, propertystring,
QV8QObjectWrapper::IgnoreRevision);
- // Fall through to undefined
+ // Fall through to return empty handle
}
- // Fall through to undefined
+ // Fall through to return empty handle
} else if (resource->typeNamespace) {
@@ -185,21 +185,19 @@ v8::Handle<v8::Value> QV8TypeWrapper::Getter(v8::Local<v8::String> property,
if (moduleApi->qobjectApi) {
v8::Handle<v8::Value> rv = v8engine->qobjectWrapper()->getProperty(moduleApi->qobjectApi, propertystring, QV8QObjectWrapper::IgnoreRevision);
- if (rv.IsEmpty())
- return v8::Undefined();
- else
- return rv;
+ return rv;
} else {
- return v8::Undefined();
+ return v8::Handle<v8::Value>();
}
}
- // Fall through to undefined
+ // Fall through to return empty handle
} else {
Q_ASSERT(!"Unreachable");
}
- return v8::Undefined();
+
+ return v8::Handle<v8::Value>();
}
v8::Handle<v8::Value> QV8TypeWrapper::Setter(v8::Local<v8::String> property,
diff --git a/src/declarative/qml/v8/qv8valuetypewrapper.cpp b/src/declarative/qml/v8/qv8valuetypewrapper.cpp
index f3100cf7b5..e459fee71f 100644
--- a/src/declarative/qml/v8/qv8valuetypewrapper.cpp
+++ b/src/declarative/qml/v8/qv8valuetypewrapper.cpp
@@ -7,29 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** 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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
@@ -103,15 +103,21 @@ QV8ValueTypeWrapper::~QV8ValueTypeWrapper()
void QV8ValueTypeWrapper::destroy()
{
+ qPersistentDispose(m_toString);
qPersistentDispose(m_constructor);
}
void QV8ValueTypeWrapper::init(QV8Engine *engine)
{
m_engine = engine;
+ m_toString = qPersistentNew<v8::Function>(v8::FunctionTemplate::New(ToString)->GetFunction());
v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
ft->InstanceTemplate()->SetNamedPropertyHandler(Getter, Setter);
ft->InstanceTemplate()->SetHasExternalResource(true);
+ ft->InstanceTemplate()->MarkAsUseUserObjectComparison();
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("toString"), ToStringGetter, 0,
+ m_toString, v8::DEFAULT,
+ v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
m_constructor = qPersistentNew<v8::Function>(ft->GetFunction());
}
@@ -166,26 +172,85 @@ QVariant QV8ValueTypeWrapper::toVariant(QV8ObjectResource *r)
}
}
+bool QV8ValueTypeWrapper::isEqual(QV8ObjectResource *r, const QVariant& value)
+{
+ Q_ASSERT(r->resourceType() == QV8ObjectResource::ValueTypeType);
+ QV8ValueTypeResource *resource = static_cast<QV8ValueTypeResource *>(r);
+
+ if (resource->objectType == QV8ValueTypeResource::Reference) {
+ QV8ValueTypeReferenceResource *reference = static_cast<QV8ValueTypeReferenceResource *>(resource);
+ if (reference->object) {
+ reference->type->read(reference->object, reference->property);
+ return reference->type->isEqual(value);
+ } else {
+ return false;
+ }
+ } else {
+ Q_ASSERT(resource->objectType == QV8ValueTypeResource::Copy);
+ QV8ValueTypeCopyResource *copy = static_cast<QV8ValueTypeCopyResource *>(resource);
+ return (value == copy->value);
+ }
+}
+
+v8::Handle<v8::Value> QV8ValueTypeWrapper::ToStringGetter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info)
+{
+ Q_UNUSED(property);
+ return info.Data();
+}
+
+v8::Handle<v8::Value> QV8ValueTypeWrapper::ToString(const v8::Arguments &args)
+{
+ QV8ValueTypeResource *resource = v8_resource_cast<QV8ValueTypeResource>(args.This());
+ if (resource) {
+ if (resource->objectType == QV8ValueTypeResource::Reference) {
+ QV8ValueTypeReferenceResource *reference = static_cast<QV8ValueTypeReferenceResource *>(resource);
+ if (reference->object) {
+ reference->type->read(reference->object, reference->property);
+ return resource->engine->toString(resource->type->toString());
+ } else {
+ return v8::Undefined();
+ }
+ } else {
+ Q_ASSERT(resource->objectType == QV8ValueTypeResource::Copy);
+ QV8ValueTypeCopyResource *copy = static_cast<QV8ValueTypeCopyResource *>(resource);
+ QString result = copy->value.toString();
+ if (result.isEmpty() && !copy->value.canConvert(QVariant::String)) {
+ result = QString::fromLatin1("QVariant(%0)").arg(QString::fromLatin1(copy->value.typeName()));
+ }
+ return resource->engine->toString(result);
+ }
+ } else {
+ return v8::Undefined();
+ }
+}
+
v8::Handle<v8::Value> QV8ValueTypeWrapper::Getter(v8::Local<v8::String> property,
const v8::AccessorInfo &info)
{
QV8ValueTypeResource *r = v8_resource_cast<QV8ValueTypeResource>(info.This());
- if (!r) return v8::Undefined();
+ if (!r) return v8::Handle<v8::Value>();
// XXX This is horribly inefficient. Sadly people seem to have taken a liking to
// value type properties, so we should probably try and optimize it a little.
// We should probably just replace all value properties with dedicated accessors.
QByteArray propName = r->engine->toString(property).toUtf8();
+ if (propName == QByteArray("toString")) {
+ return r->engine->valueTypeWrapper()->m_toString;
+ }
+
int index = r->type->metaObject()->indexOfProperty(propName.constData());
if (index == -1)
- return v8::Undefined();
+ return v8::Handle<v8::Value>();
+
if (r->objectType == QV8ValueTypeResource::Reference) {
QV8ValueTypeReferenceResource *reference = static_cast<QV8ValueTypeReferenceResource *>(r);
if (!reference->object)
- return v8::Undefined();
+ return v8::Handle<v8::Value>();
+
r->type->read(reference->object, reference->property);
} else {
diff --git a/src/declarative/qml/v8/qv8valuetypewrapper_p.h b/src/declarative/qml/v8/qv8valuetypewrapper_p.h
index d08d89392c..2582560c0f 100644
--- a/src/declarative/qml/v8/qv8valuetypewrapper_p.h
+++ b/src/declarative/qml/v8/qv8valuetypewrapper_p.h
@@ -77,7 +77,12 @@ public:
QVariant toVariant(v8::Handle<v8::Object>);
QVariant toVariant(QV8ObjectResource *);
+ static bool isEqual(QV8ObjectResource *, const QVariant& value);
+
private:
+ static v8::Handle<v8::Value> ToStringGetter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> ToString(const v8::Arguments &args);
static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property,
const v8::AccessorInfo &info);
static v8::Handle<v8::Value> Setter(v8::Local<v8::String> property,
@@ -86,6 +91,7 @@ private:
QV8Engine *m_engine;
v8::Persistent<v8::Function> m_constructor;
+ v8::Persistent<v8::Function> m_toString;
};
QT_END_NAMESPACE
diff --git a/src/declarative/qml/v8/qv8variantwrapper.cpp b/src/declarative/qml/v8/qv8variantwrapper.cpp
index d4097d7f74..de4f0ce2d7 100644
--- a/src/declarative/qml/v8/qv8variantwrapper.cpp
+++ b/src/declarative/qml/v8/qv8variantwrapper.cpp
@@ -7,29 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** 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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
@@ -159,17 +159,24 @@ QVariant QV8VariantWrapper::toVariant(QV8ObjectResource *r)
return static_cast<QV8VariantResource *>(r)->data;
}
-v8::Handle<v8::Value> QV8VariantWrapper::Getter(v8::Local<v8::String> property,
+QVariant &QV8VariantWrapper::variantValue(v8::Handle<v8::Value> value)
+{
+ Q_ASSERT(isVariant(value));
+ QV8VariantResource *r = v8_resource_cast<QV8VariantResource>(value->ToObject());
+ return static_cast<QV8VariantResource *>(r)->data;
+}
+
+v8::Handle<v8::Value> QV8VariantWrapper::Getter(v8::Local<v8::String> property,
const v8::AccessorInfo &info)
{
- return v8::Undefined();
+ return v8::Handle<v8::Value>();
}
v8::Handle<v8::Value> QV8VariantWrapper::Setter(v8::Local<v8::String> property,
v8::Local<v8::Value> value,
const v8::AccessorInfo &info)
{
- return v8::Undefined();
+ return value;
}
v8::Handle<v8::Value> QV8VariantWrapper::PreserveGetter(v8::Local<v8::String> property,
diff --git a/src/declarative/qml/v8/qv8variantwrapper_p.h b/src/declarative/qml/v8/qv8variantwrapper_p.h
index de74bc9e12..7e9924b3c0 100644
--- a/src/declarative/qml/v8/qv8variantwrapper_p.h
+++ b/src/declarative/qml/v8/qv8variantwrapper_p.h
@@ -74,6 +74,7 @@ public:
bool isVariant(v8::Handle<v8::Value>);
QVariant toVariant(v8::Handle<v8::Object>);
QVariant toVariant(QV8ObjectResource *);
+ QVariant &variantValue(v8::Handle<v8::Value>);
private:
static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property,
diff --git a/src/declarative/qml/v8/qv8worker.cpp b/src/declarative/qml/v8/qv8worker.cpp
index 0d396d3304..d6998849e2 100644
--- a/src/declarative/qml/v8/qv8worker.cpp
+++ b/src/declarative/qml/v8/qv8worker.cpp
@@ -7,29 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** 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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
diff --git a/src/declarative/qml/v8/qv8worker_p.h b/src/declarative/qml/v8/qv8worker_p.h
index 086e18e7e0..20a295a51c 100644
--- a/src/declarative/qml/v8/qv8worker_p.h
+++ b/src/declarative/qml/v8/qv8worker_p.h
@@ -7,29 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** 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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
diff --git a/src/declarative/qml/v8/script.pri b/src/declarative/qml/v8/script.pri
index 04a23d1f2b..7454d2004c 100644
--- a/src/declarative/qml/v8/script.pri
+++ b/src/declarative/qml/v8/script.pri
@@ -17,4 +17,6 @@ HEADERS += \
$$PWD/qscriptshareddata_p.h \
$$PWD/qscripttools_p.h \
$$PWD/qscript_impl_p.h \
- $$PWD/qscriptoriginalglobalobject_p.h
+ $$PWD/qscriptoriginalglobalobject_p.h \
+ $$PWD/qjsvalueiterator_p.h \
+ $$PWD/qjsvalueiterator_impl_p.h
diff --git a/src/declarative/qml/v8/v8.pri b/src/declarative/qml/v8/v8.pri
index 97b3d679df..9349742c78 100644
--- a/src/declarative/qml/v8/v8.pri
+++ b/src/declarative/qml/v8/v8.pri
@@ -5,6 +5,7 @@ include(script.pri)
HEADERS += \
$$PWD/qv8_p.h \
+ $$PWD/qv8debug_p.h \
$$PWD/qv8stringwrapper_p.h \
$$PWD/qv8engine_p.h \
$$PWD/qhashedstring_p.h \
@@ -18,7 +19,8 @@ HEADERS += \
$$PWD/qv8worker_p.h \
$$PWD/qv8bindings_p.h \
$$PWD/../../../3rdparty/javascriptcore/DateMath.h \
- $$PWD/qv8engine_impl_p.h
+ $$PWD/qv8engine_impl_p.h \
+ $$PWD/qv8domerrors_p.h
SOURCES += \
$$PWD/qv8stringwrapper.cpp \
@@ -34,3 +36,4 @@ SOURCES += \
$$PWD/qv8worker.cpp \
$$PWD/qv8bindings.cpp \
$$PWD/../../../3rdparty/javascriptcore/DateMath.cpp \
+ $$PWD/qv8domerrors.cpp
diff --git a/src/declarative/scenegraph/coreapi/qsgnode.cpp b/src/declarative/scenegraph/coreapi/qsgnode.cpp
index 70ca1fbf9c..95afbb51ab 100644
--- a/src/declarative/scenegraph/coreapi/qsgnode.cpp
+++ b/src/declarative/scenegraph/coreapi/qsgnode.cpp
@@ -84,13 +84,13 @@ static void qt_print_node_count()
QSGNode::QSGNode()
: m_parent(0)
, m_type(BasicNodeType)
- , m_subtreeGeometryCount(0)
- , m_nodeFlags(OwnedByParent)
- , m_flags(0)
, m_firstChild(0)
, m_lastChild(0)
, m_nextSibling(0)
, m_previousSibling(0)
+ , m_subtreeGeometryCount(0)
+ , m_nodeFlags(OwnedByParent)
+ , m_flags(0)
{
init();
}
@@ -98,13 +98,13 @@ QSGNode::QSGNode()
QSGNode::QSGNode(NodeType type)
: m_parent(0)
, m_type(type)
- , m_subtreeGeometryCount(type == GeometryNodeType ? 1 : 0)
- , m_nodeFlags(OwnedByParent)
- , m_flags(0)
, m_firstChild(0)
, m_lastChild(0)
, m_nextSibling(0)
, m_previousSibling(0)
+ , m_subtreeGeometryCount(type == GeometryNodeType ? 1 : 0)
+ , m_nodeFlags(OwnedByParent)
+ , m_flags(0)
{
init();
}
@@ -126,7 +126,7 @@ QSGNode::~QSGNode()
#ifndef QT_NO_DEBUG
--qt_node_count;
if (qt_node_count < 0)
- qDebug("Material destroyed after qt_print_node_count() was called.");
+ qDebug("Node destroyed after qt_print_node_count() was called.");
#endif
destroy();
}
diff --git a/src/declarative/scenegraph/coreapi/qsgrenderer.cpp b/src/declarative/scenegraph/coreapi/qsgrenderer.cpp
index 5a137adfe5..c92d943708 100644
--- a/src/declarative/scenegraph/coreapi/qsgrenderer.cpp
+++ b/src/declarative/scenegraph/coreapi/qsgrenderer.cpp
@@ -410,17 +410,32 @@ QSGRenderer::ClipType QSGRenderer::updateStencilClip(const QSGClipNode *clip)
m *= *clip->matrix();
// TODO: Check for multisampling and pixel grid alignment.
- bool canUseScissor = clip->isRectangular()
- && qFuzzyIsNull(m(0, 1)) && qFuzzyIsNull(m(0, 2))
- && qFuzzyIsNull(m(1, 0)) && qFuzzyIsNull(m(1, 2));
+ bool isRectangleWithNoPerspective = clip->isRectangular()
+ && qFuzzyIsNull(m(3, 0)) && qFuzzyIsNull(m(3, 1));
+ bool noRotate = qFuzzyIsNull(m(0, 1)) && qFuzzyIsNull(m(1, 0));
+ bool isRotate90 = qFuzzyIsNull(m(0, 0)) && qFuzzyIsNull(m(1, 1));
- if (canUseScissor) {
+ if (isRectangleWithNoPerspective && (noRotate || isRotate90)) {
QRectF bbox = clip->clipRect();
qreal invW = 1 / m(3, 3);
- qreal fx1 = (bbox.left() * m(0, 0) + m(0, 3)) * invW;
- qreal fy1 = (bbox.bottom() * m(1, 1) + m(1, 3)) * invW;
- qreal fx2 = (bbox.right() * m(0, 0) + m(0, 3)) * invW;
- qreal fy2 = (bbox.top() * m(1, 1) + m(1, 3)) * invW;
+ qreal fx1, fy1, fx2, fy2;
+ if (noRotate) {
+ fx1 = (bbox.left() * m(0, 0) + m(0, 3)) * invW;
+ fy1 = (bbox.bottom() * m(1, 1) + m(1, 3)) * invW;
+ fx2 = (bbox.right() * m(0, 0) + m(0, 3)) * invW;
+ fy2 = (bbox.top() * m(1, 1) + m(1, 3)) * invW;
+ } else {
+ Q_ASSERT(isRotate90);
+ fx1 = (bbox.bottom() * m(0, 1) + m(0, 3)) * invW;
+ fy1 = (bbox.left() * m(1, 0) + m(1, 3)) * invW;
+ fx2 = (bbox.top() * m(0, 1) + m(0, 3)) * invW;
+ fy2 = (bbox.right() * m(1, 0) + m(1, 3)) * invW;
+ }
+
+ if (fx1 > fx2)
+ qSwap(fx1, fx2);
+ if (fy1 > fy2)
+ qSwap(fy1, fy2);
GLint ix1 = qRound((fx1 + 1) * m_device_rect.width() * qreal(0.5));
GLint iy1 = qRound((fy1 + 1) * m_device_rect.height() * qreal(0.5));
@@ -435,7 +450,6 @@ QSGRenderer::ClipType QSGRenderer::updateStencilClip(const QSGClipNode *clip)
clipRect &= QRect(ix1, iy1, ix2 - ix1, iy2 - iy1);
}
- clipRect = clipRect.normalized();
glScissor(clipRect.x(), clipRect.y(), clipRect.width(), clipRect.height());
} else {
if (!stencilEnabled) {
diff --git a/src/declarative/scenegraph/qsgadaptationlayer_p.h b/src/declarative/scenegraph/qsgadaptationlayer_p.h
index 81b17a9000..f2c0cbe9ef 100644
--- a/src/declarative/scenegraph/qsgadaptationlayer_p.h
+++ b/src/declarative/scenegraph/qsgadaptationlayer_p.h
@@ -44,7 +44,7 @@
#include "qsgnode.h"
#include "qsgtexture.h"
-
+#include <private/qsgtext_p.h>
#include <QtCore/qobject.h>
#include <QtCore/qrect.h>
#include <QtGui/qcolor.h>
@@ -52,6 +52,8 @@
#include <QtGui/qglyphrun.h>
#include <QtCore/qurl.h>
+#include <private/qsgtext_p.h>
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
@@ -100,11 +102,14 @@ public:
enum AntialiasingMode
{
GrayAntialiasing,
- SubPixelAntialiasing
+ LowQualitySubPixelAntialiasing,
+ HighQualitySubPixelAntialiasing
};
virtual void setGlyphs(const QPointF &position, const QGlyphRun &glyphs) = 0;
virtual void setColor(const QColor &color) = 0;
+ virtual void setStyle(QSGText::TextStyle style) = 0;
+ virtual void setStyleColor(const QColor &color) = 0;
virtual QPointF baseLine() const = 0;
virtual QRectF boundingRect() const { return m_bounding_rect; }
diff --git a/src/declarative/scenegraph/qsgcontext.cpp b/src/declarative/scenegraph/qsgcontext.cpp
index c5e4a7de24..2a9e007264 100644
--- a/src/declarative/scenegraph/qsgcontext.cpp
+++ b/src/declarative/scenegraph/qsgcontext.cpp
@@ -62,6 +62,7 @@
DEFINE_BOOL_CONFIG_OPTION(qmlFlashMode, QML_FLASH_MODE)
DEFINE_BOOL_CONFIG_OPTION(qmlTranslucentMode, QML_TRANSLUCENT_MODE)
+DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
/*
Comments about this class from Gunnar:
@@ -90,12 +91,14 @@ public:
: rootNode(0)
, renderer(0)
, gl(0)
+ , distanceFieldCacheManager(0)
, flashMode(qmlFlashMode())
+ , distanceFieldDisabled(qmlDisableDistanceField())
{
renderAlpha = qmlTranslucentMode() ? 0.5 : 1;
}
- ~QSGContextPrivate()
+ ~QSGContextPrivate()
{
}
@@ -108,11 +111,14 @@ public:
QHash<QSGMaterialType *, QSGMaterialShader *> materials;
+ QSGDistanceFieldGlyphCacheManager *distanceFieldCacheManager;
+
QMutex textureMutex;
QList<QSGTexture *> texturesToClean;
bool flashMode;
float renderAlpha;
+ bool distanceFieldDisabled;
};
@@ -142,6 +148,7 @@ QSGContext::~QSGContext()
delete d->rootNode;
cleanupTextures();
qDeleteAll(d->materials.values());
+ delete d->distanceFieldCacheManager;
}
/*!
@@ -286,20 +293,28 @@ QSGImageNode *QSGContext::createImageNode()
*/
QSGGlyphNode *QSGContext::createGlyphNode()
{
+ Q_D(QSGContext);
+
// ### Do something with these before final release...
static bool doSubpixel = qApp->arguments().contains(QLatin1String("--text-subpixel-antialiasing"));
+ static bool doLowQualSubpixel = qApp->arguments().contains(QLatin1String("--text-subpixel-antialiasing-lowq"));
static bool doGray = qApp->arguments().contains(QLatin1String("--text-gray-antialiasing"));
- if (QSGDistanceFieldGlyphCache::distanceFieldEnabled()) {
- QSGGlyphNode *node = new QSGDistanceFieldGlyphNode;
-
- if (doSubpixel)
- node->setPreferredAntialiasingMode(QSGGlyphNode::SubPixelAntialiasing);
- else if (doGray)
- node->setPreferredAntialiasingMode(QSGGlyphNode::GrayAntialiasing);
- return node;
- } else {
+ if (d->distanceFieldDisabled) {
return new QSGDefaultGlyphNode;
+ } else {
+ if (!d->distanceFieldCacheManager) {
+ d->distanceFieldCacheManager = new QSGDistanceFieldGlyphCacheManager(d->gl);
+ if (doSubpixel)
+ d->distanceFieldCacheManager->setDefaultAntialiasingMode(QSGGlyphNode::HighQualitySubPixelAntialiasing);
+ else if (doLowQualSubpixel)
+ d->distanceFieldCacheManager->setDefaultAntialiasingMode(QSGGlyphNode::LowQualitySubPixelAntialiasing);
+ else if (doGray)
+ d->distanceFieldCacheManager->setDefaultAntialiasingMode(QSGGlyphNode::GrayAntialiasing);
+ }
+
+ QSGGlyphNode *node = new QSGDistanceFieldGlyphNode(d->distanceFieldCacheManager);
+ return node;
}
}
@@ -383,6 +398,21 @@ QSGTexture *QSGContext::createTexture(const QImage &image) const
/*!
+ Returns the minimum supported framebuffer object size.
+ */
+
+QSize QSGContext::minimumFBOSize() const
+{
+#ifdef Q_WS_MAC
+ return QSize(33, 33);
+#else
+ return QSize(1, 1);
+#endif
+}
+
+
+
+/*!
Returns a material shader for the given material.
*/
@@ -449,6 +479,24 @@ qreal QSGContext::renderAlpha() const
}
+/*!
+ Sets whether or not the scene graph should use the distance field technique to render text
+ */
+void QSGContext::setDistanceFieldEnabled(bool enabled)
+{
+ d_func()->distanceFieldDisabled = !enabled;
+}
+
+
+/*!
+ Returns true if the scene graph uses the distance field technique to render text
+ */
+bool QSGContext::isDistanceFieldEnabled() const
+{
+ return !d_func()->distanceFieldDisabled;
+}
+
+
/*!
Creates a new animation driver.
diff --git a/src/declarative/scenegraph/qsgcontext_p.h b/src/declarative/scenegraph/qsgcontext_p.h
index cc2be930f4..29a5aac4b9 100644
--- a/src/declarative/scenegraph/qsgcontext_p.h
+++ b/src/declarative/scenegraph/qsgcontext_p.h
@@ -102,6 +102,7 @@ public:
QSize *size,
const QSize &requestSize);
virtual QSGTexture *createTexture(const QImage &image = QImage()) const;
+ virtual QSize minimumFBOSize() const;
static QSGContext *createDefaultContext();
@@ -114,6 +115,9 @@ public:
void setRenderAlpha(qreal renderAlpha);
qreal renderAlpha() const;
+ void setDistanceFieldEnabled(bool enabled);
+ bool isDistanceFieldEnabled() const;
+
virtual QAnimationDriver *createAnimationDriver(QObject *parent);
signals:
diff --git a/src/declarative/scenegraph/qsgdefaultglyphnode_p.h b/src/declarative/scenegraph/qsgdefaultglyphnode_p.h
index 16e267b605..993eabcd3c 100644
--- a/src/declarative/scenegraph/qsgdefaultglyphnode_p.h
+++ b/src/declarative/scenegraph/qsgdefaultglyphnode_p.h
@@ -64,6 +64,8 @@ public:
virtual void setColor(const QColor &color);
virtual void setPreferredAntialiasingMode(AntialiasingMode) { }
+ virtual void setStyle(QSGText::TextStyle) { }
+ virtual void setStyleColor(const QColor &) { }
virtual void update() { }
diff --git a/src/declarative/scenegraph/qsgdistancefieldglyphcache.cpp b/src/declarative/scenegraph/qsgdistancefieldglyphcache.cpp
index 2cd3db4074..ff4913a7b5 100644
--- a/src/declarative/scenegraph/qsgdistancefieldglyphcache.cpp
+++ b/src/declarative/scenegraph/qsgdistancefieldglyphcache.cpp
@@ -86,6 +86,21 @@ static inline int qt_next_power_of_two(int v)
return v;
}
+static float defaultThresholdFunc(float glyphScale)
+{
+ static float base = qgetenv("QT_DF_BASE").isEmpty() ? 0.5f : qgetenv("QT_DF_BASE").toFloat();
+ static float baseDev = qgetenv("QT_DF_BASEDEVIATION").isEmpty() ? 0.065f : qgetenv("QT_DF_BASEDEVIATION").toFloat();
+ static float devScaleMin = qgetenv("QT_DF_SCALEFORMAXDEV").isEmpty() ? 0.15f : qgetenv("QT_DF_SCALEFORMAXDEV").toFloat();
+ static float devScaleMax = qgetenv("QT_DF_SCALEFORNODEV").isEmpty() ? 0.3f : qgetenv("QT_DF_SCALEFORNODEV").toFloat();
+ return base - ((qBound(devScaleMin, glyphScale, devScaleMax) - devScaleMin) / (devScaleMax - devScaleMin) * -baseDev + baseDev);
+}
+
+static float defaultAntialiasingSpreadFunc(float glyphScale)
+{
+ static float range = qgetenv("QT_DF_RANGE").isEmpty() ? 0.06f : qgetenv("QT_DF_RANGE").toFloat();
+ return range / glyphScale;
+}
+
namespace
{
enum FillHDir
@@ -782,46 +797,17 @@ static bool fontHasNarrowOutlines(const QRawFont &f)
return minHThick == 1 || minVThick == 1;
}
-DEFINE_BOOL_CONFIG_OPTION(disableDistanceField, QML_DISABLE_DISTANCEFIELD)
-
-QHash<QPair<const QGLContext *, QFontEngine *>, QSGDistanceFieldGlyphCache *> QSGDistanceFieldGlyphCache::m_caches;
-QHash<QFontEngine *, QGLContextGroupResource<QSGDistanceFieldGlyphCache::DistanceFieldTextureData> > QSGDistanceFieldGlyphCache::m_textures_data;
-
-QSGDistanceFieldGlyphCache *QSGDistanceFieldGlyphCache::get(const QGLContext *ctx, const QRawFont &font)
-{
- QRawFontPrivate *fontD = QRawFontPrivate::get(font);
- QPair<const QGLContext *, QFontEngine *> key(ctx, fontD->fontEngine);
- QHash<QPair<const QGLContext *, QFontEngine *>, QSGDistanceFieldGlyphCache *>::iterator atlas = m_caches.find(key);
- if (atlas == m_caches.end())
- atlas = m_caches.insert(key, new QSGDistanceFieldGlyphCache(ctx, font));
-
- return atlas.value();
-}
-
-QSGDistanceFieldGlyphCache::DistanceFieldTextureData *QSGDistanceFieldGlyphCache::textureData()
-{
- return m_textures_data[QRawFontPrivate::get(m_font)->fontEngine].value(ctx);
-}
-
-QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(const QGLContext *c, const QRawFont &font)
- : QObject()
+QSGDistanceFieldGlyphCacheManager::QSGDistanceFieldGlyphCacheManager(const QGLContext *c)
+ : ctx(c)
+ , m_threshold_func(defaultThresholdFunc)
+ , m_antialiasingSpread_func(defaultAntialiasingSpreadFunc)
, m_maxTextureSize(0)
- , ctx(c)
- , m_blitProgram(0)
{
- Q_ASSERT(font.isValid());
- m_font = font;
-
- m_textureData = textureData();
-
- QRawFontPrivate *fontD = QRawFontPrivate::get(m_font);
- m_glyphCount = fontD->fontEngine->glyphCount();
-
- m_textureData->doubleGlyphResolution = fontHasNarrowOutlines(font) && m_glyphCount < QT_DISTANCEFIELD_HIGHGLYPHCOUNT;
-
- m_referenceFont = m_font;
- m_referenceFont.setPixelSize(QT_DISTANCEFIELD_BASEFONTSIZE);
- Q_ASSERT(m_referenceFont.isValid());
+#ifndef QT_OPENGL_ES
+ m_defaultAntialiasingMode = QSGGlyphNode::HighQualitySubPixelAntialiasing;
+#else
+ m_defaultAntialiasingMode = QSGGlyphNode::GrayAntialiasing;
+#endif
m_vertexCoordinateArray[0] = -1.0f;
m_vertexCoordinateArray[1] = -1.0f;
@@ -841,24 +827,88 @@ QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(const QGLContext *c, cons
m_textureCoordinateArray[6] = 0.0f;
m_textureCoordinateArray[7] = 1.0f;
- connect(QGLSignalProxy::instance(), SIGNAL(aboutToDestroyContext(const QGLContext*)),
- this, SLOT(onContextDestroyed(const QGLContext*)));
+ m_blitProgram = new QGLShaderProgram;
+ {
+ QString source;
+ source.append(QLatin1String(qglslMainWithTexCoordsVertexShader));
+ source.append(QLatin1String(qglslUntransformedPositionVertexShader));
+
+ QGLShader *vertexShader = new QGLShader(QGLShader::Vertex, m_blitProgram);
+ vertexShader->compileSourceCode(source);
+
+ m_blitProgram->addShader(vertexShader);
+ }
+ {
+ QString source;
+ source.append(QLatin1String(qglslMainFragmentShader));
+ source.append(QLatin1String(qglslImageSrcFragmentShader));
+
+ QGLShader *fragmentShader = new QGLShader(QGLShader::Fragment, m_blitProgram);
+ fragmentShader->compileSourceCode(source);
+
+ m_blitProgram->addShader(fragmentShader);
+ }
+ m_blitProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
+ m_blitProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
+ m_blitProgram->link();
}
-QSGDistanceFieldGlyphCache::~QSGDistanceFieldGlyphCache()
+QSGDistanceFieldGlyphCacheManager::~QSGDistanceFieldGlyphCacheManager()
{
delete m_blitProgram;
+ qDeleteAll(m_caches.values());
}
-void QSGDistanceFieldGlyphCache::onContextDestroyed(const QGLContext *context)
+QSGDistanceFieldGlyphCache *QSGDistanceFieldGlyphCacheManager::cache(const QRawFont &font)
{
- if (context != ctx)
- return;
+ QRawFontPrivate *fontD = QRawFontPrivate::get(font);
+ QHash<QFontEngine *, QSGDistanceFieldGlyphCache *>::iterator cache = m_caches.find(fontD->fontEngine);
+ if (cache == m_caches.end())
+ cache = m_caches.insert(fontD->fontEngine, new QSGDistanceFieldGlyphCache(this, ctx, font));
+ return cache.value();
+}
+
+int QSGDistanceFieldGlyphCacheManager::maxTextureSize() const
+{
+ if (!m_maxTextureSize)
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize);
+ return m_maxTextureSize;
+}
+
+
+QHash<QString, QGLContextGroupResource<QSGDistanceFieldGlyphCache::DistanceFieldTextureData> > QSGDistanceFieldGlyphCache::m_textures_data;
+
+QSGDistanceFieldGlyphCache::DistanceFieldTextureData *QSGDistanceFieldGlyphCache::textureData()
+{
+ QString key = QString::fromLatin1("%1_%2_%3_%4")
+ .arg(m_font.familyName())
+ .arg(m_font.styleName())
+ .arg(m_font.weight())
+ .arg(m_font.style());
+ return m_textures_data[key].value(ctx);
+}
+
+QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, const QGLContext *c, const QRawFont &font)
+ : m_manager(man)
+ , ctx(c)
+{
+ Q_ASSERT(font.isValid());
+ m_font = font;
+
+ m_textureData = textureData();
QRawFontPrivate *fontD = QRawFontPrivate::get(m_font);
- QPair<const QGLContext *, QFontEngine *> key(context, fontD->fontEngine);
- m_caches.remove(key);
- deleteLater();
+ m_glyphCount = fontD->fontEngine->glyphCount();
+
+ m_textureData->doubleGlyphResolution = fontHasNarrowOutlines(font) && m_glyphCount < QT_DISTANCEFIELD_HIGHGLYPHCOUNT;
+
+ m_referenceFont = m_font;
+ m_referenceFont.setPixelSize(QT_DISTANCEFIELD_BASEFONTSIZE);
+ Q_ASSERT(m_referenceFont.isValid());
+}
+
+QSGDistanceFieldGlyphCache::~QSGDistanceFieldGlyphCache()
+{
}
GLuint QSGDistanceFieldGlyphCache::texture()
@@ -871,13 +921,6 @@ QSize QSGDistanceFieldGlyphCache::textureSize() const
return m_textureData->size;
}
-int QSGDistanceFieldGlyphCache::maxTextureSize() const
-{
- if (!m_maxTextureSize)
- glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize);
- return m_maxTextureSize;
-}
-
QSGDistanceFieldGlyphCache::Metrics QSGDistanceFieldGlyphCache::glyphMetrics(glyph_t glyph)
{
QHash<glyph_t, Metrics>::iterator metric = m_metrics.find(glyph);
@@ -970,7 +1013,7 @@ void QSGDistanceFieldGlyphCache::populate(int count, const glyph_t *glyphs)
if (!cacheIsFull()) {
m_textureData->currX += QT_DISTANCEFIELD_TILESIZE;
- if (m_textureData->currX >= maxTextureSize()) {
+ if (m_textureData->currX >= m_manager->maxTextureSize()) {
m_textureData->currX = 0;
m_textureData->currY += QT_DISTANCEFIELD_TILESIZE;
}
@@ -986,7 +1029,7 @@ void QSGDistanceFieldGlyphCache::populate(int count, const glyph_t *glyphs)
}
}
- if (c.y < maxTextureSize()) {
+ if (c.y < m_manager->maxTextureSize()) {
m_textureData->texCoords.insert(glyphIndex, c);
m_textureData->pendingGlyphs.add(glyphIndex);
}
@@ -1010,10 +1053,7 @@ void QSGDistanceFieldGlyphCache::createTexture(int width, int height)
glGenTextures(1, &m_textureData->texture);
glBindTexture(GL_TEXTURE_2D, m_textureData->texture);
- QVarLengthArray<uchar> data(width * height);
- for (int i = 0; i < data.size(); ++i)
- data[i] = 0;
- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &data[0]);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -1090,45 +1130,14 @@ void QSGDistanceFieldGlyphCache::resizeTexture(int width, int height)
glViewport(0, 0, oldWidth, oldHeight);
- if (m_blitProgram == 0) {
- m_blitProgram = new QGLShaderProgram;
+ ctx->functions()->glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, m_manager->blitVertexArray());
+ ctx->functions()->glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, m_manager->blitTextureArray());
- {
- QString source;
- source.append(QLatin1String(qglslMainWithTexCoordsVertexShader));
- source.append(QLatin1String(qglslUntransformedPositionVertexShader));
-
- QGLShader *vertexShader = new QGLShader(QGLShader::Vertex, m_blitProgram);
- vertexShader->compileSourceCode(source);
-
- m_blitProgram->addShader(vertexShader);
- }
-
- {
- QString source;
- source.append(QLatin1String(qglslMainFragmentShader));
- source.append(QLatin1String(qglslImageSrcFragmentShader));
-
- QGLShader *fragmentShader = new QGLShader(QGLShader::Fragment, m_blitProgram);
- fragmentShader->compileSourceCode(source);
-
- m_blitProgram->addShader(fragmentShader);
- }
-
- m_blitProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
- m_blitProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
-
- m_blitProgram->link();
- }
-
- ctx->functions()->glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, m_vertexCoordinateArray);
- ctx->functions()->glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, m_textureCoordinateArray);
-
- m_blitProgram->bind();
- m_blitProgram->enableAttributeArray(int(QT_VERTEX_COORDS_ATTR));
- m_blitProgram->enableAttributeArray(int(QT_TEXTURE_COORDS_ATTR));
- m_blitProgram->disableAttributeArray(int(QT_OPACITY_ATTR));
- m_blitProgram->setUniformValue("imageTexture", GLuint(0));
+ m_manager->blitProgram()->bind();
+ m_manager->blitProgram()->enableAttributeArray(int(QT_VERTEX_COORDS_ATTR));
+ m_manager->blitProgram()->enableAttributeArray(int(QT_TEXTURE_COORDS_ATTR));
+ m_manager->blitProgram()->disableAttributeArray(int(QT_OPACITY_ATTR));
+ m_manager->blitProgram()->setUniformValue("imageTexture", GLuint(0));
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
@@ -1160,9 +1169,9 @@ void QSGDistanceFieldGlyphCache::updateCache()
if (m_textureData->pendingGlyphs.isEmpty())
return;
- int requiredWidth = maxTextureSize();
+ int requiredWidth = m_manager->maxTextureSize();
int rows = 128 / (requiredWidth / QT_DISTANCEFIELD_TILESIZE); // Enough rows to fill the latin1 set by default..
- int requiredHeight = qMin(maxTextureSize(), qMax(m_textureData->currY + QT_DISTANCEFIELD_TILESIZE, QT_DISTANCEFIELD_TILESIZE * rows));
+ int requiredHeight = qMin(m_manager->maxTextureSize(), qMax(m_textureData->currY + QT_DISTANCEFIELD_TILESIZE, QT_DISTANCEFIELD_TILESIZE * rows));
resizeTexture((requiredWidth), (requiredHeight));
glBindTexture(GL_TEXTURE_2D, m_textureData->texture);
@@ -1170,6 +1179,12 @@ void QSGDistanceFieldGlyphCache::updateCache()
// ### Remove before final release
static bool cacheDistanceFields = QApplication::arguments().contains("--cache-distance-fields");
+// #define QSGDISTANCEFIELDS_TIME_CREATION
+#ifdef QSGDISTANCEFIELDS_TIME_CREATION
+ QTime time;
+ time.start();
+#endif
+
QString tmpPath = QString::fromLatin1("%1/.qt/").arg(QDir::tempPath());
QString keyBase = QString::fromLatin1("%1%2%3_%4_%5_%6.fontblob")
.arg(tmpPath)
@@ -1218,6 +1233,13 @@ void QSGDistanceFieldGlyphCache::updateCache()
file.write((const char *) glyph.constBits(), glyph.width() * glyph.height());
}
}
+
+#ifdef QSGDISTANCEFIELDS_TIME_CREATION
+ static int totalTime;
+ totalTime += time.elapsed();
+ printf("time: %d\n", totalTime);
+#endif
+
m_textureData->pendingGlyphs.reset();
}
@@ -1226,11 +1248,6 @@ bool QSGDistanceFieldGlyphCache::useWorkaroundBrokenFBOReadback() const
return ctx->d_ptr->workaround_brokenFBOReadBack;
}
-bool QSGDistanceFieldGlyphCache::distanceFieldEnabled()
-{
- return !disableDistanceField();
-}
-
int QSGDistanceFieldGlyphCache::glyphCount() const
{
return m_glyphCount;
diff --git a/src/declarative/scenegraph/qsgdistancefieldglyphcache_p.h b/src/declarative/scenegraph/qsgdistancefieldglyphcache_p.h
index bcfb44a706..c4dd97bab5 100644
--- a/src/declarative/scenegraph/qsgdistancefieldglyphcache_p.h
+++ b/src/declarative/scenegraph/qsgdistancefieldglyphcache_p.h
@@ -48,18 +48,59 @@
#include <private/qfont_p.h>
#include <private/qfontengine_p.h>
#include <QtGui/private/qdatabuffer_p.h>
+#include <private/qsgadaptationlayer_p.h>
QT_BEGIN_NAMESPACE
+typedef float (*ThresholdFunc)(float glyphScale);
+typedef float (*AntialiasingSpreadFunc)(float glyphScale);
+
class QGLShaderProgram;
+class QSGDistanceFieldGlyphCache;
-class Q_DECLARATIVE_EXPORT QSGDistanceFieldGlyphCache : public QObject
+class Q_DECLARATIVE_EXPORT QSGDistanceFieldGlyphCacheManager
{
- Q_OBJECT
public:
- ~QSGDistanceFieldGlyphCache();
+ QSGDistanceFieldGlyphCacheManager(const QGLContext *c);
+ ~QSGDistanceFieldGlyphCacheManager();
+
+ QSGDistanceFieldGlyphCache *cache(const QRawFont &font);
+
+ QSGGlyphNode::AntialiasingMode defaultAntialiasingMode() const { return m_defaultAntialiasingMode; }
+ void setDefaultAntialiasingMode(QSGGlyphNode::AntialiasingMode mode) { m_defaultAntialiasingMode = mode; }
+
+ ThresholdFunc thresholdFunc() const { return m_threshold_func; }
+ void setThresholdFunc(ThresholdFunc func) { m_threshold_func = func; }
+
+ AntialiasingSpreadFunc antialiasingSpreadFunc() const { return m_antialiasingSpread_func; }
+ void setAntialiasingSpreadFunc(AntialiasingSpreadFunc func) { m_antialiasingSpread_func = func; }
+
+ QGLShaderProgram *blitProgram() { return m_blitProgram; }
+ const GLfloat *blitVertexArray() const { return &m_vertexCoordinateArray[0]; }
+ const GLfloat *blitTextureArray() const { return &m_textureCoordinateArray[0]; }
+
+ int maxTextureSize() const;
+
+private:
+ QHash<QFontEngine *, QSGDistanceFieldGlyphCache *> m_caches;
+
+ const QGLContext *ctx;
+
+ QSGGlyphNode::AntialiasingMode m_defaultAntialiasingMode;
+ ThresholdFunc m_threshold_func;
+ AntialiasingSpreadFunc m_antialiasingSpread_func;
+
+ mutable int m_maxTextureSize;
- static QSGDistanceFieldGlyphCache *get(const QGLContext *ctx, const QRawFont &font);
+ QGLShaderProgram *m_blitProgram;
+ GLfloat m_vertexCoordinateArray[8];
+ GLfloat m_textureCoordinateArray[8];
+};
+
+class Q_DECLARATIVE_EXPORT QSGDistanceFieldGlyphCache
+{
+public:
+ ~QSGDistanceFieldGlyphCache();
struct Metrics {
qreal width;
@@ -85,9 +126,10 @@ public:
};
TexCoord glyphTexCoord(glyph_t glyph);
+ const QSGDistanceFieldGlyphCacheManager *manager() const { return m_manager; }
+
GLuint texture();
QSize textureSize() const;
- int maxTextureSize() const;
qreal fontScale() const;
int distanceFieldRadius() const;
QImage renderDistanceFieldGlyph(glyph_t glyph) const;
@@ -98,29 +140,23 @@ public:
void derefGlyphs(int count, const glyph_t *glyphs);
void updateCache();
- bool cacheIsFull() const { return m_textureData->currY >= maxTextureSize(); }
+ bool cacheIsFull() const { return m_textureData->currY >= m_manager->maxTextureSize(); }
bool useWorkaroundBrokenFBOReadback() const;
- static bool distanceFieldEnabled();
-
-private Q_SLOTS:
- void onContextDestroyed(const QGLContext *context);
-
private:
- QSGDistanceFieldGlyphCache(const QGLContext *c, const QRawFont &font);
+ QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, const QGLContext *c, const QRawFont &font);
void createTexture(int width, int height);
void resizeTexture(int width, int height);
- static QHash<QPair<const QGLContext *, QFontEngine *>, QSGDistanceFieldGlyphCache *> m_caches;
+ QSGDistanceFieldGlyphCacheManager *m_manager;
QRawFont m_font;
QRawFont m_referenceFont;
int m_glyphCount;
QHash<glyph_t, Metrics> m_metrics;
- mutable int m_maxTextureSize;
struct DistanceFieldTextureData {
GLuint texture;
@@ -146,13 +182,11 @@ private:
};
DistanceFieldTextureData *textureData();
DistanceFieldTextureData *m_textureData;
- static QHash<QFontEngine *, QGLContextGroupResource<DistanceFieldTextureData> > m_textures_data;
+ static QHash<QString, QGLContextGroupResource<DistanceFieldTextureData> > m_textures_data;
const QGLContext *ctx;
- QGLShaderProgram *m_blitProgram;
- GLfloat m_vertexCoordinateArray[8];
- GLfloat m_textureCoordinateArray[8];
+ friend class QSGDistanceFieldGlyphCacheManager;
};
QT_END_NAMESPACE
diff --git a/src/declarative/scenegraph/qsgdistancefieldglyphnode.cpp b/src/declarative/scenegraph/qsgdistancefieldglyphnode.cpp
index 26326d0c75..cb3dab959c 100644
--- a/src/declarative/scenegraph/qsgdistancefieldglyphnode.cpp
+++ b/src/declarative/scenegraph/qsgdistancefieldglyphnode.cpp
@@ -46,8 +46,9 @@
QT_BEGIN_NAMESPACE
-QSGDistanceFieldGlyphNode::QSGDistanceFieldGlyphNode()
+QSGDistanceFieldGlyphNode::QSGDistanceFieldGlyphNode(QSGDistanceFieldGlyphCacheManager *cacheManager)
: m_material(0)
+ , m_glyph_cacheManager(cacheManager)
, m_glyph_cache(0)
, m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 0)
, m_style(QSGText::Normal)
@@ -58,10 +59,7 @@ QSGDistanceFieldGlyphNode::QSGDistanceFieldGlyphNode()
{
m_geometry.setDrawingMode(GL_TRIANGLES);
setGeometry(&m_geometry);
-
-#ifndef QT_OPENGL_ES
- setPreferredAntialiasingMode(QSGGlyphNode::SubPixelAntialiasing);
-#endif
+ setPreferredAntialiasingMode(cacheManager->defaultAntialiasingMode());
}
QSGDistanceFieldGlyphNode::~QSGDistanceFieldGlyphNode()
@@ -169,6 +167,7 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
QPointF margins(2, 2);
QPointF texMargins = margins / m_glyph_cache->fontScale();
+ QVector<QPointF> glyphPositions = m_glyphs.positions();
for (int i = 0; i < glyphIndexes.size(); ++i) {
quint32 glyphIndex = glyphIndexes.at(i);
QSGDistanceFieldGlyphCache::Metrics metrics = m_glyph_cache->glyphMetrics(glyphIndex);
@@ -185,9 +184,9 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
c.height += texMargins.y() * 2;
}
- QPointF glyphPosition = m_glyphs.positions().at(i) + m_position;
- qreal x = glyphPosition.x() + metrics.baselineX;
- qreal y = glyphPosition.y() - metrics.baselineY;
+ const QPointF &glyphPosition = glyphPositions.at(i);
+ qreal x = glyphPosition.x() + metrics.baselineX + m_position.x();
+ qreal y = glyphPosition.y() - metrics.baselineY + m_position.y();
boundingRect |= QRectF(x, y, metrics.width, metrics.height);
@@ -245,7 +244,7 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
void QSGDistanceFieldGlyphNode::updateFont()
{
- m_glyph_cache = QSGDistanceFieldGlyphCache::get(QGLContext::currentContext(), m_glyphs.rawFont());
+ m_glyph_cache = m_glyph_cacheManager->cache(m_glyphs.rawFont());
m_dirtyFont = false;
}
@@ -254,10 +253,18 @@ void QSGDistanceFieldGlyphNode::updateMaterial()
delete m_material;
if (m_style == QSGText::Normal) {
- if (m_antialiasingMode == SubPixelAntialiasing)
- m_material = new QSGSubPixelDistanceFieldTextMaterial;
- else
+ switch (m_antialiasingMode) {
+ case HighQualitySubPixelAntialiasing:
+ m_material = new QSGHiQSubPixelDistanceFieldTextMaterial;
+ break;
+ case LowQualitySubPixelAntialiasing:
+ m_material = new QSGLoQSubPixelDistanceFieldTextMaterial;
+ break;
+ case GrayAntialiasing:
+ default:
m_material = new QSGDistanceFieldTextMaterial;
+ break;
+ }
} else {
QSGDistanceFieldStyledTextMaterial *material;
if (m_style == QSGText::Outline) {
diff --git a/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.cpp b/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.cpp
index 18de955b29..c81113f4dc 100644
--- a/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.cpp
+++ b/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.cpp
@@ -60,10 +60,10 @@ protected:
virtual const char *vertexShader() const;
virtual const char *fragmentShader() const;
- virtual void updateAlphaRange();
+ void updateAlphaRange(ThresholdFunc thresholdFunc, AntialiasingSpreadFunc spreadFunc);
- qreal m_fontScale;
- qreal m_matrixScale;
+ float m_fontScale;
+ float m_matrixScale;
int m_matrix_id;
int m_textureScale_id;
@@ -110,11 +110,14 @@ QSGDistanceFieldTextMaterialShader::QSGDistanceFieldTextMaterialShader()
{
}
-void QSGDistanceFieldTextMaterialShader::updateAlphaRange()
+void QSGDistanceFieldTextMaterialShader::updateAlphaRange(ThresholdFunc thresholdFunc, AntialiasingSpreadFunc spreadFunc)
{
- qreal combinedScale = m_fontScale * m_matrixScale;
- qreal alphaMin = qMax(0.0, 0.5 - 0.07 / combinedScale);
- qreal alphaMax = qMin(0.5 + 0.07 / combinedScale, 1.0);
+ float combinedScale = m_fontScale * m_matrixScale;
+ float base = thresholdFunc(combinedScale);
+ float range = spreadFunc(combinedScale);
+
+ float alphaMin = qMax(0.0f, base - range);
+ float alphaMax = qMin(base + range, 1.0f);
program()->setUniformValue(m_alphaMin_id, GLfloat(alphaMin));
program()->setUniformValue(m_alphaMax_id, GLfloat(alphaMax));
}
@@ -156,11 +159,13 @@ void QSGDistanceFieldTextMaterialShader::updateState(const RenderState &state, Q
}
if (state.isMatrixDirty()) {
program()->setUniformValue(m_matrix_id, state.combinedMatrix());
- m_matrixScale = qSqrt(state.modelViewMatrix().determinant());
+ m_matrixScale = qSqrt(qAbs(state.modelViewMatrix().determinant()));
updateRange = true;
}
- if (updateRange)
- updateAlphaRange();
+ if (updateRange) {
+ updateAlphaRange(material->glyphCache()->manager()->thresholdFunc(),
+ material->glyphCache()->manager()->antialiasingSpreadFunc());
+ }
Q_ASSERT(material->glyphCache());
@@ -494,7 +499,7 @@ QSGMaterialShader *QSGDistanceFieldShiftedStyleTextMaterial::createShader() cons
}
-class QSGSubPixelDistanceFieldTextMaterialShader : public QSGDistanceFieldTextMaterialShader
+class QSGHiQSubPixelDistanceFieldTextMaterialShader : public QSGDistanceFieldTextMaterialShader
{
public:
virtual void initialize();
@@ -506,14 +511,12 @@ protected:
virtual const char *vertexShader() const;
virtual const char *fragmentShader() const;
- void updateAlphaRange();
-
private:
int m_fontScale_id;
int m_vecDelta_id;
};
-const char *QSGSubPixelDistanceFieldTextMaterialShader::vertexShader() const {
+const char *QSGHiQSubPixelDistanceFieldTextMaterialShader::vertexShader() const {
return
"uniform highp mat4 matrix; \n"
"uniform highp vec2 textureScale; \n"
@@ -545,7 +548,7 @@ const char *QSGSubPixelDistanceFieldTextMaterialShader::vertexShader() const {
"}";
}
-const char *QSGSubPixelDistanceFieldTextMaterialShader::fragmentShader() const {
+const char *QSGHiQSubPixelDistanceFieldTextMaterialShader::fragmentShader() const {
return
"varying highp vec2 sampleCoord; \n"
"varying highp vec3 sampleFarLeft; \n"
@@ -579,7 +582,7 @@ const char *QSGSubPixelDistanceFieldTextMaterialShader::fragmentShader() const {
"}";
}
-//const char *QSGSubPixelDistanceFieldTextMaterialShader::fragmentShader() const {
+//const char *QSGHiQSubPixelDistanceFieldTextMaterialShader::fragmentShader() const {
// return
// "#extension GL_OES_standard_derivatives: enable \n"
// "varying highp vec2 sampleCoord; \n"
@@ -601,35 +604,26 @@ const char *QSGSubPixelDistanceFieldTextMaterialShader::fragmentShader() const {
// "}";
//}
-void QSGSubPixelDistanceFieldTextMaterialShader::initialize()
+void QSGHiQSubPixelDistanceFieldTextMaterialShader::initialize()
{
QSGDistanceFieldTextMaterialShader::initialize();
m_fontScale_id = program()->uniformLocation("fontScale");
m_vecDelta_id = program()->uniformLocation("vecDelta");
}
-void QSGSubPixelDistanceFieldTextMaterialShader::activate()
+void QSGHiQSubPixelDistanceFieldTextMaterialShader::activate()
{
QSGDistanceFieldTextMaterialShader::activate();
glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR);
}
-void QSGSubPixelDistanceFieldTextMaterialShader::deactivate()
+void QSGHiQSubPixelDistanceFieldTextMaterialShader::deactivate()
{
QSGDistanceFieldTextMaterialShader::deactivate();
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
-void QSGSubPixelDistanceFieldTextMaterialShader::updateAlphaRange()
-{
- qreal combinedScale = m_fontScale * m_matrixScale;
- qreal alphaMin = qMax(0.0, 0.5 - 0.05 / combinedScale);
- qreal alphaMax = qMin(0.5 + 0.05 / combinedScale, 1.0);
- program()->setUniformValue(m_alphaMin_id, GLfloat(alphaMin));
- program()->setUniformValue(m_alphaMax_id, GLfloat(alphaMax));
-}
-
-void QSGSubPixelDistanceFieldTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
+void QSGHiQSubPixelDistanceFieldTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
{
Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type());
QSGDistanceFieldTextMaterial *material = static_cast<QSGDistanceFieldTextMaterial *>(newEffect);
@@ -652,16 +646,77 @@ void QSGSubPixelDistanceFieldTextMaterialShader::updateState(const RenderState &
QSGDistanceFieldTextMaterialShader::updateState(state, newEffect, oldEffect);
}
-QSGMaterialType *QSGSubPixelDistanceFieldTextMaterial::type() const
+QSGMaterialType *QSGHiQSubPixelDistanceFieldTextMaterial::type() const
{
static QSGMaterialType type;
return &type;
}
-QSGMaterialShader *QSGSubPixelDistanceFieldTextMaterial::createShader() const
+QSGMaterialShader *QSGHiQSubPixelDistanceFieldTextMaterial::createShader() const
+{
+ return new QSGHiQSubPixelDistanceFieldTextMaterialShader;
+}
+
+
+class QSGLoQSubPixelDistanceFieldTextMaterialShader : public QSGHiQSubPixelDistanceFieldTextMaterialShader
+{
+protected:
+ virtual const char *vertexShader() const;
+ virtual const char *fragmentShader() const;
+};
+
+const char *QSGLoQSubPixelDistanceFieldTextMaterialShader::vertexShader() const {
+ return
+ "uniform highp mat4 matrix; \n"
+ "uniform highp vec2 textureScale; \n"
+ "uniform highp float fontScale; \n"
+ "uniform highp vec4 vecDelta; \n"
+ "attribute highp vec4 vCoord; \n"
+ "attribute highp vec2 tCoord; \n"
+ "varying highp vec3 sampleNearLeft; \n"
+ "varying highp vec3 sampleNearRight; \n"
+ "void main() { \n"
+ " highp vec2 sampleCoord = tCoord * textureScale; \n"
+ " gl_Position = matrix * vCoord; \n"
+ // Calculate neighbour pixel position in item space.
+ " highp vec3 wDelta = gl_Position.w * vecDelta.xyw; \n"
+ " highp vec3 nearLeft = vCoord.xyw - 0.25 * wDelta; \n"
+ " highp vec3 nearRight = vCoord.xyw + 0.25 * wDelta; \n"
+ // Calculate neighbour texture coordinate.
+ " highp vec2 scale = textureScale / fontScale; \n"
+ " highp vec2 base = sampleCoord - scale * vCoord.xy; \n"
+ " sampleNearLeft = vec3(base * nearLeft.z + scale * nearLeft.xy, nearLeft.z); \n"
+ " sampleNearRight = vec3(base * nearRight.z + scale * nearRight.xy, nearRight.z); \n"
+ "}";
+}
+
+const char *QSGLoQSubPixelDistanceFieldTextMaterialShader::fragmentShader() const {
+ return
+ "varying highp vec3 sampleNearLeft; \n"
+ "varying highp vec3 sampleNearRight; \n"
+ "uniform sampler2D texture; \n"
+ "uniform lowp vec4 color; \n"
+ "uniform highp float alphaMin; \n"
+ "uniform highp float alphaMax; \n"
+ "void main() { \n"
+ " highp vec2 n; \n"
+ " n.x = texture2DProj(texture, sampleNearLeft).a; \n"
+ " n.y = texture2DProj(texture, sampleNearRight).a; \n"
+ " n = smoothstep(alphaMin, alphaMax, n); \n"
+ " highp float c = 0.5 * (n.x + n.y); \n"
+ " gl_FragColor = vec4(n.x, c, n.y, c) * color.w; \n"
+ "}";
+}
+
+QSGMaterialType *QSGLoQSubPixelDistanceFieldTextMaterial::type() const
{
- return new QSGSubPixelDistanceFieldTextMaterialShader;
+ static QSGMaterialType type;
+ return &type;
}
+QSGMaterialShader *QSGLoQSubPixelDistanceFieldTextMaterial::createShader() const
+{
+ return new QSGLoQSubPixelDistanceFieldTextMaterialShader;
+}
QT_END_NAMESPACE
diff --git a/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.h b/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.h
index 926a84383c..a5bdf36d16 100644
--- a/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.h
+++ b/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.h
@@ -53,11 +53,12 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
class QSGDistanceFieldGlyphCache;
+class QSGDistanceFieldGlyphCacheManager;
class QSGDistanceFieldTextMaterial;
class QSGDistanceFieldGlyphNode: public QSGGlyphNode
{
public:
- QSGDistanceFieldGlyphNode();
+ QSGDistanceFieldGlyphNode(QSGDistanceFieldGlyphCacheManager *cacheManager);
~QSGDistanceFieldGlyphNode();
virtual QPointF baseLine() const { return m_baseLine; }
@@ -66,8 +67,8 @@ public:
virtual void setPreferredAntialiasingMode(AntialiasingMode mode);
- void setStyle(QSGText::TextStyle style);
- void setStyleColor(const QColor &color);
+ virtual void setStyle(QSGText::TextStyle style);
+ virtual void setStyleColor(const QColor &color);
virtual void update();
@@ -81,6 +82,7 @@ private:
QSGDistanceFieldTextMaterial *m_material;
QPointF m_position;
QGlyphRun m_glyphs;
+ QSGDistanceFieldGlyphCacheManager *m_glyph_cacheManager;
QSGDistanceFieldGlyphCache *m_glyph_cache;
QSGGeometry m_geometry;
QSGText::TextStyle m_style;
diff --git a/src/declarative/scenegraph/qsgdistancefieldglyphnode_p_p.h b/src/declarative/scenegraph/qsgdistancefieldglyphnode_p_p.h
index c120ffe466..8733edf203 100644
--- a/src/declarative/scenegraph/qsgdistancefieldglyphnode_p_p.h
+++ b/src/declarative/scenegraph/qsgdistancefieldglyphnode_p_p.h
@@ -116,7 +116,14 @@ protected:
QPointF m_shift;
};
-class QSGSubPixelDistanceFieldTextMaterial : public QSGDistanceFieldTextMaterial
+class QSGHiQSubPixelDistanceFieldTextMaterial : public QSGDistanceFieldTextMaterial
+{
+public:
+ virtual QSGMaterialType *type() const;
+ virtual QSGMaterialShader *createShader() const;
+};
+
+class QSGLoQSubPixelDistanceFieldTextMaterial : public QSGDistanceFieldTextMaterial
{
public:
virtual QSGMaterialType *type() const;
diff --git a/src/declarative/scenegraph/util/qsgflatcolormaterial.h b/src/declarative/scenegraph/util/qsgflatcolormaterial.h
index bb2a65bedf..ffff7941a3 100644
--- a/src/declarative/scenegraph/util/qsgflatcolormaterial.h
+++ b/src/declarative/scenegraph/util/qsgflatcolormaterial.h
@@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
-class Q_AUTOTEST_EXPORT QSGFlatColorMaterial : public QSGMaterial
+class Q_DECLARATIVE_EXPORT QSGFlatColorMaterial : public QSGMaterial
{
public:
QSGFlatColorMaterial();
diff --git a/src/declarative/util/qdeclarativeanimation.cpp b/src/declarative/util/qdeclarativeanimation.cpp
index 977f7fa0d9..11e1c7cc0a 100644
--- a/src/declarative/util/qdeclarativeanimation.cpp
+++ b/src/declarative/util/qdeclarativeanimation.cpp
@@ -74,8 +74,8 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass Animation QDeclarativeAbstractAnimation
+ \inqmlmodule QtQuick 2
\ingroup qml-animation-transition
- \since 4.7
\brief The Animation element is the base of all QML animations.
The Animation element cannot be used directly in a QML file. It exists
@@ -99,7 +99,7 @@ QDeclarativeAbstractAnimation::QDeclarativeAbstractAnimation(QDeclarativeAbstrac
}
/*!
- \qmlproperty bool Animation::running
+ \qmlproperty bool QtQuick2::Animation::running
This property holds whether the animation is currently running.
The \c running property can be set to declaratively control whether or not
@@ -236,7 +236,7 @@ void QDeclarativeAbstractAnimation::setRunning(bool r)
}
/*!
- \qmlproperty bool Animation::paused
+ \qmlproperty bool QtQuick2::Animation::paused
This property holds whether the animation is currently paused.
The \c paused property can be set to declaratively control whether or not
@@ -303,7 +303,7 @@ void QDeclarativeAbstractAnimation::componentFinalized()
}
/*!
- \qmlproperty bool Animation::alwaysRunToEnd
+ \qmlproperty bool QtQuick2::Animation::alwaysRunToEnd
This property holds whether the animation should run to completion when it is stopped.
If this true the animation will complete its current iteration when it
@@ -335,7 +335,7 @@ void QDeclarativeAbstractAnimation::setAlwaysRunToEnd(bool f)
}
/*!
- \qmlproperty int Animation::loops
+ \qmlproperty int QtQuick2::Animation::loops
This property holds the number of times the animation should play.
By default, \c loops is 1: the animation will play through once and then stop.
@@ -412,7 +412,7 @@ void QDeclarativeAbstractAnimation::setGroup(QDeclarativeAnimationGroup *g)
}
/*!
- \qmlmethod Animation::start()
+ \qmlmethod QtQuick2::Animation::start()
\brief Starts the animation.
If the animation is already running, calling this method has no effect. The
@@ -424,7 +424,7 @@ void QDeclarativeAbstractAnimation::start()
}
/*!
- \qmlmethod Animation::pause()
+ \qmlmethod QtQuick2::Animation::pause()
\brief Pauses the animation.
If the animation is already paused, calling this method has no effect. The
@@ -436,7 +436,7 @@ void QDeclarativeAbstractAnimation::pause()
}
/*!
- \qmlmethod Animation::resume()
+ \qmlmethod QtQuick2::Animation::resume()
\brief Resumes a paused animation.
If the animation is not paused, calling this method has no effect. The
@@ -448,7 +448,7 @@ void QDeclarativeAbstractAnimation::resume()
}
/*!
- \qmlmethod Animation::stop()
+ \qmlmethod QtQuick2::Animation::stop()
\brief Stops the animation.
If the animation is not running, calling this method has no effect. The
@@ -473,7 +473,7 @@ void QDeclarativeAbstractAnimation::stop()
}
/*!
- \qmlmethod Animation::restart()
+ \qmlmethod QtQuick2::Animation::restart()
\brief Restarts the animation.
This is a convenience method, and is equivalent to calling \c stop() and
@@ -486,7 +486,7 @@ void QDeclarativeAbstractAnimation::restart()
}
/*!
- \qmlmethod Animation::complete()
+ \qmlmethod QtQuick2::Animation::complete()
\brief Stops the animation, jumping to the final property values.
If the animation is not running, calling this method has no effect. The
@@ -562,8 +562,8 @@ void QDeclarativeAbstractAnimation::timelineComplete()
/*!
\qmlclass PauseAnimation QDeclarativePauseAnimation
+ \inqmlmodule QtQuick 2
\ingroup qml-animation-transition
- \since 4.7
\inherits Animation
\brief The PauseAnimation element provides a pause for an animation.
@@ -600,7 +600,7 @@ void QDeclarativePauseAnimationPrivate::init()
}
/*!
- \qmlproperty int PauseAnimation::duration
+ \qmlproperty int QtQuick2::PauseAnimation::duration
This property holds the duration of the pause in milliseconds
The default value is 250.
@@ -633,8 +633,8 @@ QAbstractAnimation *QDeclarativePauseAnimation::qtAnimation()
/*!
\qmlclass ColorAnimation QDeclarativeColorAnimation
+ \inqmlmodule QtQuick 2
\ingroup qml-animation-transition
- \since 4.7
\inherits PropertyAnimation
\brief The ColorAnimation element animates changes in color values.
@@ -674,7 +674,7 @@ QDeclarativeColorAnimation::~QDeclarativeColorAnimation()
}
/*!
- \qmlproperty color ColorAnimation::from
+ \qmlproperty color QtQuick2::ColorAnimation::from
This property holds the color value at which the animation should begin.
For example, the following animation is not applied until a color value
@@ -711,7 +711,7 @@ void QDeclarativeColorAnimation::setFrom(const QColor &f)
}
/*!
- \qmlproperty color ColorAnimation::to
+ \qmlproperty color QtQuick2::ColorAnimation::to
This property holds the color value at which the animation should end.
@@ -737,8 +737,8 @@ void QDeclarativeColorAnimation::setTo(const QColor &t)
/*!
\qmlclass ScriptAction QDeclarativeScriptAction
+ \inqmlmodule QtQuick 2
\ingroup qml-animation-transition
- \since 4.7
\inherits Animation
\brief The ScriptAction element allows scripts to be run during an animation.
@@ -782,7 +782,7 @@ void QDeclarativeScriptActionPrivate::init()
}
/*!
- \qmlproperty script ScriptAction::script
+ \qmlproperty script QtQuick2::ScriptAction::script
This property holds the script to run.
*/
QDeclarativeScriptString QDeclarativeScriptAction::script() const
@@ -798,7 +798,7 @@ void QDeclarativeScriptAction::setScript(const QDeclarativeScriptString &script)
}
/*!
- \qmlproperty string ScriptAction::scriptName
+ \qmlproperty string QtQuick2::ScriptAction::scriptName
This property holds the the name of the StateChangeScript to run.
This property is only valid when ScriptAction is used as part of a transition.
@@ -871,8 +871,8 @@ QAbstractAnimation *QDeclarativeScriptAction::qtAnimation()
/*!
\qmlclass PropertyAction QDeclarativePropertyAction
+ \inqmlmodule QtQuick 2
\ingroup qml-animation-transition
- \since 4.7
\inherits Animation
\brief The PropertyAction element allows immediate property changes during animation.
@@ -958,10 +958,10 @@ void QDeclarativePropertyAction::setProperty(const QString &n)
}
/*!
- \qmlproperty Object PropertyAction::target
- \qmlproperty list<Object> PropertyAction::targets
- \qmlproperty string PropertyAction::property
- \qmlproperty string PropertyAction::properties
+ \qmlproperty Object QtQuick2::PropertyAction::target
+ \qmlproperty list<Object> QtQuick2::PropertyAction::targets
+ \qmlproperty string QtQuick2::PropertyAction::property
+ \qmlproperty string QtQuick2::PropertyAction::properties
These properties determine the items and their properties that are
affected by this action.
@@ -994,7 +994,7 @@ QDeclarativeListProperty<QObject> QDeclarativePropertyAction::targets()
}
/*!
- \qmlproperty list<Object> PropertyAction::exclude
+ \qmlproperty list<Object> QtQuick2::PropertyAction::exclude
This property holds the objects that should not be affected by this action.
\sa targets
@@ -1006,7 +1006,7 @@ QDeclarativeListProperty<QObject> QDeclarativePropertyAction::exclude()
}
/*!
- \qmlproperty any PropertyAction::value
+ \qmlproperty any QtQuick2::PropertyAction::value
This property holds the value to be set on the property.
If the PropertyAction is defined within a \l Transition or \l Behavior,
@@ -1132,8 +1132,8 @@ void QDeclarativePropertyAction::transition(QDeclarativeStateActions &actions,
/*!
\qmlclass NumberAnimation QDeclarativeNumberAnimation
+ \inqmlmodule QtQuick 2
\ingroup qml-animation-transition
- \since 4.7
\inherits PropertyAnimation
\brief The NumberAnimation element animates changes in qreal-type values.
@@ -1181,7 +1181,7 @@ void QDeclarativeNumberAnimation::init()
}
/*!
- \qmlproperty real NumberAnimation::from
+ \qmlproperty real QtQuick2::NumberAnimation::from
This property holds the starting value for the animation.
For example, the following animation is not applied until the \c x value
@@ -1219,7 +1219,7 @@ void QDeclarativeNumberAnimation::setFrom(qreal f)
}
/*!
- \qmlproperty real NumberAnimation::to
+ \qmlproperty real QtQuick2::NumberAnimation::to
This property holds the end value for the animation.
If the NumberAnimation is defined within a \l Transition or \l Behavior,
@@ -1244,8 +1244,8 @@ void QDeclarativeNumberAnimation::setTo(qreal t)
/*!
\qmlclass Vector3dAnimation QDeclarativeVector3dAnimation
+ \inqmlmodule QtQuick 2
\ingroup qml-animation-transition
- \since 4.7
\inherits PropertyAnimation
\brief The Vector3dAnimation element animates changes in QVector3d values.
@@ -1273,7 +1273,7 @@ QDeclarativeVector3dAnimation::~QDeclarativeVector3dAnimation()
}
/*!
- \qmlproperty real Vector3dAnimation::from
+ \qmlproperty real QtQuick2::Vector3dAnimation::from
This property holds the starting value for the animation.
If the Vector3dAnimation is defined within a \l Transition or \l Behavior,
@@ -1295,7 +1295,7 @@ void QDeclarativeVector3dAnimation::setFrom(QVector3D f)
}
/*!
- \qmlproperty real Vector3dAnimation::to
+ \qmlproperty real QtQuick2::Vector3dAnimation::to
This property holds the end value for the animation.
If the Vector3dAnimation is defined within a \l Transition or \l Behavior,
@@ -1320,8 +1320,8 @@ void QDeclarativeVector3dAnimation::setTo(QVector3D t)
/*!
\qmlclass RotationAnimation QDeclarativeRotationAnimation
+ \inqmlmodule QtQuick 2
\ingroup qml-animation-transition
- \since 4.7
\inherits PropertyAnimation
\brief The RotationAnimation element animates changes in rotation values.
@@ -1409,7 +1409,7 @@ QDeclarativeRotationAnimation::~QDeclarativeRotationAnimation()
}
/*!
- \qmlproperty real RotationAnimation::from
+ \qmlproperty real QtQuick2::RotationAnimation::from
This property holds the starting value for the animation.
For example, the following animation is not applied until the \c angle value
@@ -1446,7 +1446,7 @@ void QDeclarativeRotationAnimation::setFrom(qreal f)
}
/*!
- \qmlproperty real RotationAnimation::to
+ \qmlproperty real QtQuick2::RotationAnimation::to
This property holds the end value for the animation..
If the RotationAnimation is defined within a \l Transition or \l Behavior,
@@ -1468,7 +1468,7 @@ void QDeclarativeRotationAnimation::setTo(qreal t)
}
/*!
- \qmlproperty enumeration RotationAnimation::direction
+ \qmlproperty enumeration QtQuick2::RotationAnimation::direction
This property holds the direction of the rotation.
Possible values are:
@@ -1564,8 +1564,8 @@ QDeclarativeListProperty<QDeclarativeAbstractAnimation> QDeclarativeAnimationGro
/*!
\qmlclass SequentialAnimation QDeclarativeSequentialAnimation
+ \inqmlmodule QtQuick 2
\ingroup qml-animation-transition
- \since 4.7
\inherits Animation
\brief The SequentialAnimation element allows animations to be run sequentially.
@@ -1638,8 +1638,8 @@ void QDeclarativeSequentialAnimation::transition(QDeclarativeStateActions &actio
/*!
\qmlclass ParallelAnimation QDeclarativeParallelAnimation
+ \inqmlmodule QtQuick 2
\ingroup qml-animation-transition
- \since 4.7
\inherits Animation
\brief The ParallelAnimation element allows animations to be run in parallel.
@@ -1752,8 +1752,8 @@ void QDeclarativePropertyAnimationPrivate::convertVariant(QVariant &variant, int
/*!
\qmlclass PropertyAnimation QDeclarativePropertyAnimation
+ \inqmlmodule QtQuick 2
\ingroup qml-animation-transition
- \since 4.7
\inherits Animation
\brief The PropertyAnimation element animates changes in property values.
@@ -1838,7 +1838,7 @@ void QDeclarativePropertyAnimationPrivate::init()
}
/*!
- \qmlproperty int PropertyAnimation::duration
+ \qmlproperty int QtQuick2::PropertyAnimation::duration
This property holds the duration of the animation, in milliseconds.
The default value is 250.
@@ -1864,7 +1864,7 @@ void QDeclarativePropertyAnimation::setDuration(int duration)
}
/*!
- \qmlproperty real PropertyAnimation::from
+ \qmlproperty real QtQuick2::PropertyAnimation::from
This property holds the starting value for the animation.
If the PropertyAnimation is defined within a \l Transition or \l Behavior,
@@ -1891,7 +1891,7 @@ void QDeclarativePropertyAnimation::setFrom(const QVariant &f)
}
/*!
- \qmlproperty real PropertyAnimation::to
+ \qmlproperty real QtQuick2::PropertyAnimation::to
This property holds the end value for the animation.
If the PropertyAnimation is defined within a \l Transition or \l Behavior,
@@ -1918,10 +1918,10 @@ void QDeclarativePropertyAnimation::setTo(const QVariant &t)
}
/*!
- \qmlproperty enumeration PropertyAnimation::easing.type
- \qmlproperty real PropertyAnimation::easing.amplitude
- \qmlproperty real PropertyAnimation::easing.overshoot
- \qmlproperty real PropertyAnimation::easing.period
+ \qmlproperty enumeration QtQuick2::PropertyAnimation::easing.type
+ \qmlproperty real QtQuick2::PropertyAnimation::easing.amplitude
+ \qmlproperty real QtQuick2::PropertyAnimation::easing.overshoot
+ \qmlproperty real QtQuick2::PropertyAnimation::easing.period
\brief the easing curve used for the animation.
To specify an easing curve you need to specify at least the type. For some curves you can also specify
@@ -2179,10 +2179,10 @@ void QDeclarativePropertyAnimation::setProperties(const QString &prop)
}
/*!
- \qmlproperty string PropertyAnimation::properties
- \qmlproperty list<Object> PropertyAnimation::targets
- \qmlproperty string PropertyAnimation::property
- \qmlproperty Object PropertyAnimation::target
+ \qmlproperty string QtQuick2::PropertyAnimation::properties
+ \qmlproperty list<Object> QtQuick2::PropertyAnimation::targets
+ \qmlproperty string QtQuick2::PropertyAnimation::property
+ \qmlproperty Object QtQuick2::PropertyAnimation::target
These properties are used as a set to determine which properties should be animated.
The singular and plural forms are functionally identical, e.g.
@@ -2275,7 +2275,7 @@ QDeclarativeListProperty<QObject> QDeclarativePropertyAnimation::targets()
}
/*!
- \qmlproperty list<Object> PropertyAnimation::exclude
+ \qmlproperty list<Object> QtQuick2::PropertyAnimation::exclude
This property holds the items not to be affected by this animation.
\sa PropertyAnimation::targets
*/
diff --git a/src/declarative/util/qdeclarativebehavior.cpp b/src/declarative/util/qdeclarativebehavior.cpp
index 8587ccb4fb..84636e4701 100644
--- a/src/declarative/util/qdeclarativebehavior.cpp
+++ b/src/declarative/util/qdeclarativebehavior.cpp
@@ -72,8 +72,8 @@ public:
/*!
\qmlclass Behavior QDeclarativeBehavior
+ \inqmlmodule QtQuick 2
\ingroup qml-animation-transition
- \since 4.7
\brief The Behavior element allows you to specify a default animation for a property change.
A Behavior defines the default animation to be applied whenever a
@@ -108,7 +108,7 @@ QDeclarativeBehavior::~QDeclarativeBehavior()
}
/*!
- \qmlproperty Animation Behavior::animation
+ \qmlproperty Animation QtQuick2::Behavior::animation
\default
This property holds the animation to run when the behavior is triggered.
@@ -149,7 +149,7 @@ void QDeclarativeBehavior::qtAnimationStateChanged(QAbstractAnimation::State new
/*!
- \qmlproperty bool Behavior::enabled
+ \qmlproperty bool QtQuick2::Behavior::enabled
This property holds whether the behavior will be triggered when the tracked
property changes value.
diff --git a/src/declarative/util/qdeclarativebind.cpp b/src/declarative/util/qdeclarativebind.cpp
index fa463ebef8..ba120b959a 100644
--- a/src/declarative/util/qdeclarativebind.cpp
+++ b/src/declarative/util/qdeclarativebind.cpp
@@ -44,6 +44,7 @@
#include "private/qdeclarativenullablevalue_p_p.h"
#include "private/qdeclarativeproperty_p.h"
#include "private/qdeclarativebinding_p.h"
+#include "private/qdeclarativeguard_p.h"
#include <qdeclarativeengine.h>
#include <qdeclarativecontext.h>
@@ -67,7 +68,7 @@ public:
QDeclarativeNullableValue<bool> when;
bool componentComplete;
- QObject *obj;
+ QDeclarativeGuard<QObject> obj;
QString propName;
QDeclarativeNullableValue<QVariant> value;
QDeclarativeProperty prop;
@@ -77,8 +78,8 @@ public:
/*!
\qmlclass Binding QDeclarativeBind
+ \inqmlmodule QtQuick 2
\ingroup qml-working-with-data
- \since 4.7
\brief The Binding element allows arbitrary property bindings to be created.
\section1 Binding to an inaccessible property
@@ -151,7 +152,7 @@ QDeclarativeBind::~QDeclarativeBind()
}
/*!
- \qmlproperty bool Binding::when
+ \qmlproperty bool QtQuick2::Binding::when
This property holds when the binding is active.
This should be set to an expression that evaluates to true when you want the binding to be active.
@@ -183,7 +184,7 @@ void QDeclarativeBind::setWhen(bool v)
}
/*!
- \qmlproperty Object Binding::target
+ \qmlproperty Object QtQuick2::Binding::target
The object to be updated.
*/
@@ -196,9 +197,12 @@ QObject *QDeclarativeBind::object()
void QDeclarativeBind::setObject(QObject *obj)
{
Q_D(QDeclarativeBind);
- if (d->obj && d->obj != obj) {
- qmlInfo(this) << tr("Cannot change the object assigned to a Binding.");
- return;
+ if (d->obj && d->when.isValid() && d->when) {
+ /* if we switch the object at runtime, we need to restore the
+ previous binding on the old object before continuing */
+ d->when = false;
+ eval();
+ d->when = true;
}
d->obj = obj;
if (d->componentComplete)
@@ -207,7 +211,7 @@ void QDeclarativeBind::setObject(QObject *obj)
}
/*!
- \qmlproperty string Binding::property
+ \qmlproperty string QtQuick2::Binding::property
The property to be updated.
*/
@@ -220,9 +224,12 @@ QString QDeclarativeBind::property() const
void QDeclarativeBind::setProperty(const QString &p)
{
Q_D(QDeclarativeBind);
- if (!d->propName.isEmpty() && d->propName != p) {
- qmlInfo(this) << tr("Cannot change the property assigned to a Binding.");
- return;
+ if (!d->propName.isEmpty() && d->when.isValid() && d->when) {
+ /* if we switch the property name at runtime, we need to restore the
+ previous binding on the old object before continuing */
+ d->when = false;
+ eval();
+ d->when = true;
}
d->propName = p;
if (d->componentComplete)
@@ -231,7 +238,7 @@ void QDeclarativeBind::setProperty(const QString &p)
}
/*!
- \qmlproperty any Binding::value
+ \qmlproperty any QtQuick2::Binding::value
The value to be set on the target object and property. This can be a
constant (which isn't very useful), or a bound expression.
diff --git a/src/declarative/util/qdeclarativechangeset.cpp b/src/declarative/util/qdeclarativechangeset.cpp
index 737031be05..a10693f525 100644
--- a/src/declarative/util/qdeclarativechangeset.cpp
+++ b/src/declarative/util/qdeclarativechangeset.cpp
@@ -41,379 +41,383 @@
#include "qdeclarativechangeset_p.h"
-void QDeclarativeChangeSet::insertInsert(int start, int end)
+QDeclarativeChangeSet::QDeclarativeChangeSet()
+ : m_moveCounter(0)
{
- const int count = end - start;
-
- // Moved signals.
- QVector<Move>::iterator move = m_moves.begin();
- for (; move != m_moves.end() && start >= move->maximum(); ++move) {}
- for (; move != m_moves.end() && end >= move->minimum(); ++move) {
- if (start <= move->tstart) {
- move->tstart += count;
- move->tend += count;
- } else if (start < move->tend) {
- int relativeStart = start - move->tstart;
-
- move = m_moves.insert(move, Move(
- move->fstart + count, move->fstart + count + relativeStart, move->tstart));
- ++move;
- move->fstart += relativeStart;
- move->tstart += count + relativeStart;
- move->tend += count;
-
- start -= relativeStart;
- end -= relativeStart;
- } else {
- start -= move->count();
- end -= move->count();
- }
+}
- if (start <= move->fstart) {
- move->fstart += count;
- move->fend += count;
- } else if (start < move->tstart) {
- start += move->count();
- end += move->count();
- }
+QDeclarativeChangeSet::QDeclarativeChangeSet(const QDeclarativeChangeSet &changeSet)
+ : m_removes(changeSet.m_removes)
+ , m_inserts(changeSet.m_inserts)
+ , m_changes(changeSet.m_changes)
+ , m_moveCounter(changeSet.m_moveCounter)
+{
+}
- }
- for (; move != m_moves.end(); ++move) {
- move->fstart += count;
- move->fend += count;
- move->tstart += count;
- move->tend += count;
- }
+QDeclarativeChangeSet::~QDeclarativeChangeSet()
+{
+}
- // Inserted signals.
- QVector<Insert>::iterator insert = m_inserts.begin();
- for (; insert != m_inserts.end(); ++insert) {
- if (start < insert->start) {
- insert = m_inserts.insert(insert, Insert(start, end));
- break;
- } else if (start <= insert->end) {
- insert->end += count;
- break;
- }
- }
- if (insert == m_inserts.end()) {
- m_inserts.append(Insert(start, end));
- } else for (++insert; insert != m_inserts.end(); ++insert) {
- insert->start += count;
- insert->end += count;
- }
+QDeclarativeChangeSet &QDeclarativeChangeSet::operator =(const QDeclarativeChangeSet &changeSet)
+{
+ m_removes = changeSet.m_removes;
+ m_inserts = changeSet.m_inserts;
+ m_changes = changeSet.m_changes;
+ m_moveCounter = changeSet.m_moveCounter;
+ return *this;
+}
+void QDeclarativeChangeSet::insert(int index, int count)
+{
+ applyInsertions(QVector<Insert>() << Insert(index, count));
+}
- // Changed signals.
- QVector<Change>::iterator change = m_changes.begin();
- for (; change != m_changes.end() && start != change->start && start < change->end; ++change) {
- if (start > change->start) {
- int relativeStart = start - change->start;
- change = m_changes.insert(change, Change(change->start, change->start + relativeStart));
- ++change;
- change->start += count + relativeStart;
- change->end += count - relativeStart;
- break;
- }
- }
- for (; change != m_changes.end(); ++change) {
- change->start += count;
- change->end += count;
- }
+void QDeclarativeChangeSet::remove(int index, int count)
+{
+ QVector<Insert> i;
+ applyRemovals(QVector<Remove>() << Remove(index, count), i);
}
-void QDeclarativeChangeSet::insertRemove(int start, int end)
+void QDeclarativeChangeSet::move(int from, int to, int count)
{
- // Changed Signals.
- QVector<Change>::iterator change = m_changes.begin();
- for (; change != m_changes.end() && start >= change->end; ++change) {}
- for (; change != m_changes.end() && end < change->start; ++change) {
- const int removeCount = qMin(change->end, end) - qMax(change->start, start);
- change->end -= removeCount;
- if (change->start == change->end) {
- change = m_changes.erase(change);
- } else if (start < change->start) {
- change->start = start;
- }
- }
- const int count = end - start;
- for (; change != m_changes.end(); ++change) {
- change->start -= count;
- change->end -= count;
- }
+ apply(QVector<Remove>() << Remove(from, count, -2), QVector<Insert>() << Insert(to, count, -2));
+}
- QVector<Remove> removeChanges;
-
- // Moved signals.
- QVector<Move>::iterator move = m_moves.begin();
- for (; move != m_moves.end() && start >= move->maximum(); ++move) {}
- for (; move != m_moves.end() && end >= move->minimum(); ++move) {
- if (move->fstart < move->tstart) {
- if (start < move->fstart) {
- const int difference = move->fstart - start;
- move->fend -= difference;
- move->fstart = start;
- move->tstart -= difference;
- move->tend -= difference;
-
- removeChanges.append(Remove(start, start + difference));
- end -= difference;
- }
- if (end < move->tstart) {
- move->tstart -= end - start;
- move->tend -= end - start;
- } else if (start < move->tend) {
- const int difference = qMin(move->tend, end) - move->tstart;
- removeChanges.append(Remove(
- move->fstart , move->fstart + difference));
- end -= difference;
-
- move->fend -= difference;
- move->tstart -= end - start;
- move->tend -= end - start + difference;
- }
- start += move->count();
- end += move->count();
- } else {
- if (start < move->tend) {
- const int offset = qMax(0, start - move->tstart);
- const int difference = qMin(move->tend, end) - qMax(move->tstart, start);
-
- removeChanges.append(Remove(
- move->fstart + offset, move->fstart + offset + difference));
- start -= offset;
- end -= offset + difference;
-
- move->fend -= difference;
- move->tstart = start;
- move->tend = start + move->fend - move->fstart;
- } else {
- start -= move->count();
- end -= move->count();
- }
+void QDeclarativeChangeSet::change(int index, int count)
+{
+ applyChanges(QVector<Change>() << Change(index, count));
+}
+
+void QDeclarativeChangeSet::apply(const QDeclarativeChangeSet &changeSet)
+{
+ apply(changeSet.m_removes, changeSet.m_inserts, changeSet.m_changes);
+}
+
+void QDeclarativeChangeSet::apply(const QVector<Remove> &removals)
+{
+ QVector<Remove> r = removals;
+ QVector<Insert> i;
+ applyRemovals(r, i);
+}
+
+void QDeclarativeChangeSet::apply(const QVector<Insert> &insertions)
+{
+ QVector<Insert> i = insertions;
+ applyInsertions(i);
+}
- move->fstart -= end - start;
- move->fend -= end - start;
-
- if (start > move->fstart) {
- const int offset = start - move->fstart;
- const int difference = qMin(move->fend, end) - start;
- removeChanges.append(Remove(
- move->fstart + end - start + offset + difference ,
- move->fend + end - start + offset));
- end -= offset;
- move->fstart += offset;
- move->fend += offset;
+void QDeclarativeChangeSet::apply(const QVector<Change> &changes)
+{
+ QVector<Change> c = changes;
+ applyChanges(c);
+}
+
+void QDeclarativeChangeSet::apply(const QVector<Remove> &removals, const QVector<Insert> &insertions, const QVector<Change> &changes)
+{
+ QVector<Remove> r = removals;
+ QVector<Insert> i = insertions;
+ QVector<Change> c = changes;
+ applyRemovals(r, i);
+ applyInsertions(i);
+ applyChanges(c);
+}
+
+void QDeclarativeChangeSet::applyRemovals(QVector<Remove> &removals, QVector<Insert> &insertions)
+{
+ int removeCount = 0;
+ int insertCount = 0;
+ QVector<Insert>::iterator insert = m_inserts.begin();
+ QVector<Change>::iterator change = m_changes.begin();
+ QVector<Remove>::iterator rit = removals.begin();
+ for (; rit != removals.end(); ++rit) {
+ int index = rit->index + removeCount;
+ int count = rit->count;
+
+ QVector<Insert>::iterator iit = insertions.begin();
+ for (; rit->moveId != -1 && iit != insertions.end() && iit->moveId != rit->moveId; ++iit) {}
+ for (; change != m_changes.end() && change->end() < rit->index; ++change) {}
+ for (; change != m_changes.end() && change->index > rit->end(); ++change) {
+ change->count -= qMin(change->end(), rit->end()) - qMax(change->index, rit->index);
+ if (change->count == 0) {
+ change = m_changes.erase(change);
+ } else if (rit->index < change->index) {
+ change->index = rit->index;
}
}
-
- if (move->tstart == move->tend || move->fstart == move->tstart) {
- move = m_moves.erase(move);
- --move;
+ for (; insert != m_inserts.end() && insert->end() <= index; ++insert) {
+ insertCount += insert->count;
+ insert->index -= removeCount;
}
- }
- for (; move != m_moves.end(); ++move) {
- move->fstart -= count;
- move->fend -= count;
- move->tstart -= count;
- move->tend -= count;
- }
+ for (; insert != m_inserts.end() && insert->index < index + count; ++insert) {
+ const int offset = insert->index - index;
+ const int difference = qMin(insert->end(), index + count) - qMax(insert->index, index);
+ const int moveId = rit->moveId != -1 ? m_moveCounter++ : -1;
+ if (insert->moveId != -1) {
+ QVector<Remove>::iterator remove = m_removes.begin();
+ for (; remove != m_removes.end() && remove->moveId != insert->moveId; ++remove) {}
+ Q_ASSERT(remove != m_removes.end());
+ const int offset = index - insert->index;
+ if (rit->moveId != -1 && offset < 0) {
+ const int moveId = m_moveCounter++;
+ iit = insertions.insert(iit, Insert(iit->index, -offset, moveId));
+ ++iit;
+ iit->index += -offset;
+ iit->count -= -offset;
+ rit = removals.insert(rit, Remove(rit->index, -offset, moveId));
+ ++rit;
+ rit->count -= -offset;
+ }
+
+ if (offset > 0) {
+ const int moveId = m_moveCounter++;
+ insert = m_inserts.insert(insert, Insert(insert->index, offset, moveId));
+ ++insert;
+ insert->index += offset;
+ insert->count -= offset;
+ remove = m_removes.insert(remove, Remove(remove->index, offset, moveId));
+ ++remove;
+ remove->count -= offset;
+ rit->index -= offset;
+ index += offset;
+ count -= offset;
+ }
- if (start != end)
- removeChanges.append(Remove(start, end));
+ if (remove->count == difference) {
+ remove->moveId = moveId;
+ } else {
+ remove = m_removes.insert(remove, Remove(remove->index, difference, moveId));
+ ++remove;
+ remove->count -= difference;
+ }
+ } else if (rit->moveId != -1 && offset > 0) {
+ const int moveId = m_moveCounter++;
+ iit = insertions.insert(iit, Insert(iit->index, offset, moveId));
+ ++iit;
+ iit->index += offset;
+ iit->count -= offset;
+ rit = removals.insert(rit, Remove(rit->index, offset, moveId));
+ ++rit;
+ rit->count -= offset;
+ index += offset;
+ count -= offset;
+ }
- foreach (const Remove &r, removeChanges) {
- int start = r.start;
- int end = r.end;
+ if (rit->moveId != -1 && difference > 0) {
+ iit = insertions.insert(iit, Insert(iit->index, difference, moveId));
+ ++iit;
+ iit->index += difference;
+ iit->count -= difference;
+ }
- QVector<Insert>::iterator insert = m_inserts.end() - 1;
- for (const int count = end - start; insert != m_inserts.begin() - 1 && insert->start >= end; --insert) {
- insert->start -= count;
- insert->end -= count;
- }
- for (; insert != m_inserts.begin() - 1 && insert->end > start; --insert) {
- const int removeCount = qMin(insert->end, end) - qMax(insert->start, start);
- insert->end -= removeCount;
- if (insert->start == insert->end) {
+ insert->count -= difference;
+ rit->count -= difference;
+ if (insert->count == 0) {
insert = m_inserts.erase(insert);
- } else if (start < insert->start) {
- insert->end -= insert->start - start;
- insert->start = start;
+ --insert;
+ } else if (index <= insert->index) {
+ insert->index = rit->index;
} else {
- start -= insert->count();
- end -= insert->count();
+ rit->index -= insert->count;
}
- end -= removeCount;
- if (start == end)
- return;
- }
- // Adjust the index to compensate for any inserts prior to the remove position..
- for (; insert != m_inserts.begin() - 1; --insert) {
- start -= insert->count();
- end -= insert->count();
+ index += difference;
+ count -= difference;
+ removeCount += difference;
}
+ rit->index -= insertCount;
+ removeCount += rit->count;
+
+ if (rit->count == 0) {
+ if (rit->moveId != -1 && iit->count == 0)
+ insertions.erase(iit);
+ rit = removals.erase(rit);
+ --rit;
+ } else if (rit->moveId != -1) {
+ const int moveId = m_moveCounter++;
+ rit->moveId = moveId;
+ iit->moveId = moveId;
+ }
+ }
+ for (; change != m_changes.end(); ++change)
+ change->index -= removeCount;
+ for (; insert != m_inserts.end(); ++insert)
+ insert->index -= removeCount;
+
+ removeCount = 0;
+ QVector<Remove>::iterator remove = m_removes.begin();
+ for (rit = removals.begin(); rit != removals.end(); ++rit) {
+ QVector<Insert>::iterator iit = insertions.begin();
+ int index = rit->index + removeCount;
+ for (; rit->moveId != -1 && iit != insertions.end() && iit->moveId != rit->moveId; ++iit) {}
+ for (; remove != m_removes.end() && index > remove->index; ++remove)
+ remove->index -= removeCount;
+ while (remove != m_removes.end() && index + rit->count > remove->index) {
+ int count = 0;
+ const int offset = remove->index - index - removeCount;
+ QVector<Remove>::iterator rend = remove;
+ for (; rend != m_removes.end()
+ && rit->moveId == -1
+ && rend->moveId == -1
+ && rit->index + rit->count > rend->index; ++rend) {
+ count += rend->count;
+ }
+ if (remove != rend) {
+ const int difference = rend == m_removes.end() || rit->index + rit->count < rend->index - removeCount
+ ? rit->count
+ : offset;
+ count += difference;
+
+ index += difference;
+ rit->count -= difference;
+ removeCount += difference;
+
+ remove->index = rit->index;
+ remove->count = count;
+ remove = m_removes.erase(++remove, rend);
+ } else if (rit->moveId != -1) {
+ if (offset > 0) {
+ const int moveId = m_moveCounter++;
+ iit = insertions.insert(iit, Insert(iit->index, offset, moveId));
+ ++iit;
+ iit->index += offset;
+ iit->count -= offset;
+ remove = m_removes.insert(remove, Remove(rit->index, offset, moveId));
+ ++remove;
+ rit->count -= offset;
+ }
+ remove->index = rit->index;
+ index += offset;
+ removeCount += offset;
- // Removed signals.
- QVector<Remove>::iterator remove = m_removes.begin();
- for (; remove != m_removes.end(); ++remove) {
- if (end < remove->start) {
- remove = m_removes.insert(remove, Remove(start, end));
- break;
- } else if (start <= remove->start) {
- remove->end += end - remove->start;
- remove->start = start;
-
- QVector<Remove>::iterator rbegin = remove;
- QVector<Remove>::iterator rend = ++rbegin;
- for (; rend != m_removes.end() && rend->start <= remove->end; ++rend)
- remove->end += rend->count();
- if (rbegin != rend) {
- remove = m_removes.erase(rbegin, rend);
+ ++remove;
+ } else {
+ if (offset > 0) {
+ remove = m_removes.insert(remove, Remove(rit->index, offset));
+ ++remove;
+ rit->count -= offset;
}
- break;
+ remove->index = rit->index;
+ index += offset;
+ removeCount += offset;
+
+ ++remove;
}
+ index += count;
+ rit->count -= count;
}
- if (remove != m_removes.end()) {
- const int count = end - start;
- for (++remove; remove != m_removes.end(); ++remove) {
- remove->start -= count;
- remove->end -= count;
- }
- } else {
- m_removes.append(Remove(start, end));
+
+ if (rit->count > 0) {
+ remove = m_removes.insert(remove, *rit);
+ ++remove;
}
+ removeCount += rit->count;
}
+ for (; remove != m_removes.end(); ++remove)
+ remove->index -= removeCount;
}
-void QDeclarativeChangeSet::insertMove(int start, int end, int to)
+void QDeclarativeChangeSet::applyInsertions(QVector<Insert> &insertions)
{
- QVector<Insert> insertChanges;
- QVector<Move> moveChanges;
-
- int fStart = start;
- int fTo = to;
- int fEnd = end;
- int &bStart = fTo;
- int bEnd = to + end - start;
-
- if (start > to) {
- qSwap(fStart, bStart);
- qSwap(fEnd, bEnd);
- }
-
- // Inserted signals.
+ int insertCount = 0;
QVector<Insert>::iterator insert = m_inserts.begin();
- if (start < to) {
- for (; insert != m_inserts.end() && fStart >= insert->end; ++insert) {}
- for (; insert != m_inserts.end() && fEnd > insert->start; ++insert) {
- const int removeCount = qMin(insert->end, fEnd) - qMax(insert->start, fStart);
- const int relativeStart = fStart - insert->start;
- const int relativeEnd = qMax(0, fEnd - insert->end);
-
- insert->end -= removeCount;
- if (insert->start == insert->end) {
- insert = m_inserts.erase(insert);
- --insert;
- }
-
- if (relativeStart < 0) {
- moveChanges.append(Move(fStart, fStart - relativeStart, fTo + relativeEnd));
- fTo -= relativeStart;
- }
-
- fTo += removeCount;
- insertChanges.append(Insert(bEnd - removeCount, bEnd));
+ QVector<Change>::iterator change = m_changes.begin();
+ for (QVector<Insert>::iterator iit = insertions.begin(); iit != insertions.end(); ++iit) {
+ int index = iit->index - insertCount;
+ int count = iit->count;
+ for (; change != m_changes.end() && change->index >= index; ++change)
+ change->index += insertCount;
+ if (change != m_changes.end() && change->index < index + count) {
+ int offset = index - change->index;
+ change = m_changes.insert(change, Change(change->index + insertCount, offset));
+ ++change;
+ change->index += count + offset;
+ change->count -= offset;
}
- } else {
- for (; insert != m_inserts.end() && bStart >= insert->end; ++insert) {}
- for (; insert != m_inserts.end() && bEnd > insert->start; ++insert) {
- const int removeCount = qMin(insert->end, bEnd) - qMax(insert->start, bStart);
- const int relativeStart = bStart - insert->start;
-
- insert->start += removeCount;
- if (insert->start == insert->end) {
- insert->start = fStart;
- insert->end = insert->start + removeCount;
+ for (; insert != m_inserts.end() && iit->index > insert->index + insert->count; ++insert)
+ insert->index += insertCount;
+ if (insert == m_inserts.end()) {
+ insert = m_inserts.insert(insert, *iit);
+ ++insert;
+ } else {
+ const int offset = index - insert->index;
+ if (offset < 0 || (offset == 0 && (iit->moveId != -1 || insert->moveId != -1))) {
+ insert = m_inserts.insert(insert, *iit);
+ ++insert;
+ } else if (iit->moveId == -1 && insert->moveId == -1) {
+ insert->index -= iit->count;
+ insert->count += iit->count;
+ } else if (offset < insert->count) {
+ const int moveId = insert->moveId != -1 ? m_moveCounter++ : -1;
+ insert = m_inserts.insert(insert, Insert(insert->index + insertCount, offset, moveId));
+ ++insert;
+ insert->index += offset;
+ insert->count -= offset;
+ insert = m_inserts.insert(insert, *iit);
+ ++insert;
+
+ if (insert->moveId != -1) {
+ QVector<Remove>::iterator remove = m_removes.begin();
+ for (; remove != m_removes.end() && remove->moveId != insert->moveId; ++remove) {}
+ Q_ASSERT(remove != m_removes.end());
+ if (remove->count == offset) {
+ remove->moveId = moveId;
+ } else {
+ remove = m_removes.insert(remove, Remove(remove->index, offset, moveId));
+ ++remove;
+ remove->count -= offset;
+ }
+ }
} else {
- insert = m_inserts.insert(insert, Insert(fStart, fStart + removeCount));
+ ++insert;
+ insert = m_inserts.insert(insert, *iit);
++insert;
}
- if (relativeStart < 0) {
- moveChanges.append(Move(fStart, fStart - relativeStart, fTo + removeCount));
- fStart -= relativeStart;
- fTo -= relativeStart;
- }
- fStart += removeCount;
- fTo += removeCount;
- }
- }
-
- if (fTo != bEnd)
- moveChanges.append(Move(fStart, fStart + bEnd - fTo, fTo));
-
- QVector<Insert>::iterator it = insertChanges.begin();
- for (insert = m_inserts.begin(); it != insertChanges.end() && insert != m_inserts.end();++insert) {
- if (it->start < insert->start) {
- insert = m_inserts.insert(insert, *it);
- ++it;
- } else if (it->start <= insert->end) {
- insert->end += it->count();
- ++it;
- }
- }
- for (; it != insertChanges.end(); ++it)
- m_inserts.append(*it);
-
- // Insert queued moved signals ordered by destination position.
- QVector<Move>::iterator move = m_moves.begin();
- if (start > to) {
- for (QVector<Move>::iterator it = moveChanges.begin(); it != moveChanges.end(); ++it) {
- it->fend += it->tstart - it->fstart;
- it->tend -=it->tstart - it->fstart;
- qSwap(it->fstart, it->tstart);
- for (; move != m_moves.end() && it->to >= qMin(move->fstart, move->tstart); ++move) {}
- move = m_moves.insert(move, *it);
- }
- } else {
- for (QVector<Move>::iterator it = moveChanges.begin(); it != moveChanges.end(); ++it) {
- for (; move != m_moves.end() && it->start >= qMin(move->fstart, move->tstart); ++move) {}
- move = m_moves.insert(move, *it);
+ insertCount += iit->count;
}
}
+ for (; change != m_changes.end(); ++change)
+ change->index += insertCount;
+ for (; insert != m_inserts.end(); ++insert)
+ insert->index += insertCount;
}
-void QDeclarativeChangeSet::insertChange(int start, int end)
+void QDeclarativeChangeSet::applyChanges(QVector<Change> &changes)
{
- QVector<Change> filteredChanges;
-
- // Inserted signals (don't emit change signals on new items).
QVector<Insert>::iterator insert = m_inserts.begin();
- for (; insert != m_inserts.end() && start >= insert->end; ++insert) {}
- for (; insert != m_inserts.end() && end > insert->start; ++insert) {
- if (start < insert->start)
- filteredChanges.append(Change(start, insert->start));
- start = insert->end;
- }
- if (start < end)
- filteredChanges.append(Change(start, end));
-
- // Find the union of the existing and filtered sets of change signals.
QVector<Change>::iterator change = m_changes.begin();
- for (QVector<Change>::iterator it = filteredChanges.begin(); it != filteredChanges.end(); ++it) {
- for (; change != m_changes.end() && change->end < it->start; ++change) {}
- if (change == m_changes.end() || change->start > it->end) {
- change = m_changes.insert(change, *it);
+ for (QVector<Change>::iterator cit = changes.begin(); cit != changes.end(); ++cit) {
+ for (; insert != m_inserts.end() && insert->end() < cit->index; ++insert) {}
+ for (; insert != m_inserts.end() && insert->index < cit->end(); ++insert) {
+ const int offset = insert->index - cit->index;
+ const int count = cit->count + cit->index - insert->index - insert->count;
+ if (offset == 0) {
+ cit->index = insert->index + insert->count;
+ cit->count = count;
+ } else {
+ cit = changes.insert(++cit, Change(insert->index + insert->count, count));
+ --cit;
+ cit->count = offset;
+ }
+ }
+
+ for (; change != m_changes.end() && change->index + change->count < cit->index; ++change) {}
+ if (change == m_changes.end() || change->index > cit->index + cit->count) {
+ if (cit->count > 0) {
+ change = m_changes.insert(change, *cit);
+ ++change;
+ }
} else {
- if (it->start < change->start)
- change->start = it->start;
+ if (cit->index < change->index) {
+ change->count += change->index - cit->index;
+ change->index = cit->index;
+ }
- if (it->end > change->end) {
- change->end = it->end;
+ if (cit->index + cit->count > change->index + change->count) {
+ change->count = cit->index + cit->count - change->index;
QVector<Change>::iterator rbegin = change;
QVector<Change>::iterator rend = ++rbegin;
- for (; rend != m_changes.end() && rend->start <= change->end; ++rend) {
- if (rend->end > change->end)
- change->end = rend->end;
+ for (; rend != m_changes.end() && rend->index <= change->index + change->count; ++rend) {
+ if (rend->index + rend->count > change->index + change->count)
+ change->count = rend->index + rend->count - change->index;
}
if (rbegin != rend) {
change = m_changes.erase(rbegin, rend);
@@ -422,19 +426,29 @@ void QDeclarativeChangeSet::insertChange(int start, int end)
}
}
}
-
}
QDebug operator <<(QDebug debug, const QDeclarativeChangeSet &set)
{
- foreach (const QDeclarativeChangeSet::Remove &remove, set.removes())
- debug.nospace() << "QDeclarativeChangeSet::Remove(" << remove.start << "," << remove.end << ")";
- foreach (const QDeclarativeChangeSet::Insert &insert, set.inserts())
- debug.nospace() << "QDeclarativeChangeSet::Insert(" << insert.start << "," << insert.end << ")";
- foreach (const QDeclarativeChangeSet::Move &move, set.moves())
- debug.nospace() << "QDeclarativeChangeSet::Move(" << move.start << "," << move.end << "," << move.to << ")";
- foreach (const QDeclarativeChangeSet::Change &change, set.changes())
- debug.nospace() << "QDeclarativeChangeSet::Change(" << change.start << "," << change.end << ")";
- return debug;
+ debug.nospace() << "QDeclarativeChangeSet(";
+ foreach (const QDeclarativeChangeSet::Remove &remove, set.removes()) debug << remove;
+ foreach (const QDeclarativeChangeSet::Insert &insert, set.inserts()) debug << insert;
+ foreach (const QDeclarativeChangeSet::Change &change, set.changes()) debug << change;
+ return debug.nospace() << ")";
+}
+
+QDebug operator <<(QDebug debug, const QDeclarativeChangeSet::Remove &remove)
+{
+ return (debug.nospace() << "Remove(" << remove.index << "," << remove.count << "," << remove.moveId << ")").space();
+}
+
+QDebug operator <<(QDebug debug, const QDeclarativeChangeSet::Insert &insert)
+{
+ return (debug.nospace() << "Insert(" << insert.index << "," << insert.count << "," << insert.moveId << ")").space();
+}
+
+QDebug operator <<(QDebug debug, const QDeclarativeChangeSet::Change &change)
+{
+ return (debug.nospace() << "Change(" << change.index << "," << change.count << ")").space();
}
diff --git a/src/declarative/util/qdeclarativechangeset_p.h b/src/declarative/util/qdeclarativechangeset_p.h
index ec3429392b..67533b02d5 100644
--- a/src/declarative/util/qdeclarativechangeset_p.h
+++ b/src/declarative/util/qdeclarativechangeset_p.h
@@ -61,103 +61,104 @@ QT_BEGIN_NAMESPACE
class Q_AUTOTEST_EXPORT QDeclarativeChangeSet
{
public:
- struct Insert
+ struct MoveKey
{
- Insert() {}
- Insert(int start, int end) : start(start), end(end) {}
-
- int count() const { return end - start; }
-
- int start;
- int end;
+ MoveKey() : moveId(-1), offset(0) {}
+ MoveKey(int moveId, int offset) : moveId(moveId), offset(offset) {}
+ int moveId;
+ int offset;
};
- struct Remove
+ struct Change
{
- Remove() {}
- Remove(int start, int end) : start(start), end(end) {}
+ Change() : index(0), count(0), moveId(-1) {}
+ Change(int index, int count) : index(index), count(count), moveId(-1) {}
+ Change(int index, int count, int moveId) : index(index), count(count), moveId(moveId) {}
- int count() const { return end - start; }
+ int index;
+ int count;
+ int moveId;
- int start;
- int end;
+ bool isMove() const { return moveId >= 0; }
+
+ MoveKey moveKey(int index) const { return MoveKey(moveId, index - Change::index); }
+
+ int start() const { return index; }
+ int end() const { return index + count; }
};
- struct Move
+
+ struct Insert : public Change
{
- Move() {}
- Move(int start, int end, int to) : fstart(start), fend(end), tstart(to), tend(to + end - start) {}
-
- int minimum() const { return qMin(fstart, tstart); }
- int maximum() const { return qMax(fend, tend); }
- int count() const { return fend - fstart; }
-
- union {
- int start;
- int fstart;
- };
- union {
- int end;
- int fend;
- };
- union {
- int to;
- int tstart;
- };
- int tend;
+ Insert() {}
+ Insert(int index, int count) : Change(index, count) {}
+ Insert(int index, int count, int moveId) : Change(index, count, moveId) {}
};
- struct Change
+ struct Remove : public Change
{
- Change() {}
- Change(int start, int end) : start(start), end(end) {}
+ Remove() {}
+ Remove(int index, int count) : Change(index, count) {}
+ Remove(int index, int count, int moveId) : Change(index, count, moveId) {}
+ };
- int count() const { return end - start; }
+ QDeclarativeChangeSet();
+ QDeclarativeChangeSet(
+ const QVector<Remove> &removals,
+ const QVector<Insert> &insertions,
+ const QVector<Change> &changes = QVector<Change>());
+ QDeclarativeChangeSet(const QDeclarativeChangeSet &changeSet);
+ ~QDeclarativeChangeSet();
- int start;
- int end;
- };
+ QDeclarativeChangeSet &operator =(const QDeclarativeChangeSet &changeSet);
const QVector<Remove> &removes() const { return m_removes; }
const QVector<Insert> &inserts() const { return m_inserts; }
- const QVector<Move> &moves() const { return m_moves; }
const QVector<Change> &changes() const {return m_changes; }
- void insertInsert(int start, int end);
- void insertRemove(int start, int end);
- void insertMove(int start, int end, int to);
- void insertChange(int start, int end);
+ void insert(int index, int count);
+ void remove(int index, int count);
+ void move(int from, int to, int count);
+ void change(int index, int count);
- void appendInsert(int start, int end) { m_inserts.append(Insert(start, end)); }
- void appendRemove(int start, int end) { m_removes.append(Remove(start, end)); }
- void appendMove(int start, int end, int to) { m_moves.append(Move(start, end, to)); }
- void appendChange(int start, int end) { m_changes.append(Change(start, end)); }
+ void apply(const QDeclarativeChangeSet &changeSet);
+ void apply(const QVector<Remove> &removals);
+ void apply(const QVector<Insert> &insertions);
+ void apply(const QVector<Change> &changes);
+ void apply(
+ const QVector<Remove> &removals,
+ const QVector<Insert> &insertions,
+ const QVector<Change> &changes = QVector<Change>());
- void append(const QVector<Insert> &inserts) { m_inserts += inserts; }
- void append(const QVector<Remove> &removes) { m_removes += removes; }
- void append(const QVector<Move> &moves) { m_moves += moves; }
- void append(const QVector<Change> &changes) { m_changes += changes; }
-
- bool isEmpty() const {
- return m_removes.empty() && m_inserts.empty() && m_moves.empty() && m_changes.empty();
- }
+ bool isEmpty() const { return m_removes.empty() && m_inserts.empty() && m_changes.empty(); }
void clear()
{
m_removes.clear();
m_inserts.clear();
- m_moves.clear();
m_changes.clear();
+ m_moveCounter = 0;
}
private:
+ void applyRemovals(QVector<Remove> &removals, QVector<Insert> &insertions);
+ void applyInsertions(QVector<Insert> &insertions);
+ void applyChanges(QVector<Change> &changes);
+
QVector<Remove> m_removes;
QVector<Insert> m_inserts;
- QVector<Move> m_moves;
QVector<Change> m_changes;
+ int m_moveCounter;
};
+inline uint qHash(const QDeclarativeChangeSet::MoveKey &key) { return qHash(qMakePair(key.moveId, key.offset)); }
+inline bool operator ==(const QDeclarativeChangeSet::MoveKey &l, const QDeclarativeChangeSet::MoveKey &r) {
+ return l.moveId == r.moveId && l.offset == r.offset; }
+
Q_AUTOTEST_EXPORT QDebug operator <<(QDebug debug, const QDeclarativeChangeSet &change);
+Q_AUTOTEST_EXPORT QDebug operator <<(QDebug debug, const QDeclarativeChangeSet::Remove &remove);
+Q_AUTOTEST_EXPORT QDebug operator <<(QDebug debug, const QDeclarativeChangeSet::Insert &insert);
+Q_AUTOTEST_EXPORT QDebug operator <<(QDebug debug, const QDeclarativeChangeSet::Change &change);
QT_END_NAMESPACE
diff --git a/src/declarative/util/qdeclarativeconnections.cpp b/src/declarative/util/qdeclarativeconnections.cpp
index 956533f7ca..6559d4bb20 100644
--- a/src/declarative/util/qdeclarativeconnections.cpp
+++ b/src/declarative/util/qdeclarativeconnections.cpp
@@ -72,8 +72,8 @@ public:
/*!
\qmlclass Connections QDeclarativeConnections
+ \inqmlmodule QtQuick 2
\ingroup qml-utility-elements
- \since 4.7
\brief A Connections element describes generalized connections to signals.
A Connections object creates a connection to a QML signal.
@@ -137,7 +137,7 @@ QDeclarativeConnections::~QDeclarativeConnections()
}
/*!
- \qmlproperty Object Connections::target
+ \qmlproperty Object QtQuick2::Connections::target
This property holds the object that sends the signal.
If this property is not set, the \c target defaults to the parent of the Connection.
@@ -172,7 +172,7 @@ void QDeclarativeConnections::setTarget(QObject *obj)
}
/*!
- \qmlproperty bool Connections::ignoreUnknownSignals
+ \qmlproperty bool QtQuick2::Connections::ignoreUnknownSignals
Normally, a connection to a non-existent signal produces runtime errors.
diff --git a/src/declarative/util/qdeclarativefontloader.cpp b/src/declarative/util/qdeclarativefontloader.cpp
index 4d67736e0c..7a1dec88f0 100644
--- a/src/declarative/util/qdeclarativefontloader.cpp
+++ b/src/declarative/util/qdeclarativefontloader.cpp
@@ -145,8 +145,8 @@ QHash<QUrl, QDeclarativeFontObject*> QDeclarativeFontLoaderPrivate::fonts;
/*!
\qmlclass FontLoader QDeclarativeFontLoader
+ \inqmlmodule QtQuick 2
\ingroup qml-utility-elements
- \since 4.7
\brief The FontLoader element allows fonts to be loaded by name or URL.
The FontLoader element is used to load fonts by name or URL.
@@ -179,7 +179,7 @@ QDeclarativeFontLoader::~QDeclarativeFontLoader()
}
/*!
- \qmlproperty url FontLoader::source
+ \qmlproperty url QtQuick2::FontLoader::source
The url of the font to load.
*/
QUrl QDeclarativeFontLoader::source() const
@@ -253,7 +253,7 @@ void QDeclarativeFontLoader::updateFontInfo(const QString& name, QDeclarativeFon
}
/*!
- \qmlproperty string FontLoader::name
+ \qmlproperty string QtQuick2::FontLoader::name
This property holds the name of the font family.
It is set automatically when a font is loaded using the \c url property.
@@ -294,7 +294,7 @@ void QDeclarativeFontLoader::setName(const QString &name)
}
/*!
- \qmlproperty enumeration FontLoader::status
+ \qmlproperty enumeration QtQuick2::FontLoader::status
This property holds the status of font loading. It can be one of:
\list
diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp
index 035502140b..15d87c828d 100644
--- a/src/declarative/util/qdeclarativelistmodel.cpp
+++ b/src/declarative/util/qdeclarativelistmodel.cpp
@@ -204,8 +204,8 @@ QDeclarativeListModelParser::ListInstruction *QDeclarativeListModelParser::ListM
/*!
\qmlclass ListModel QDeclarativeListModel
+ \inqmlmodule QtQuick 2
\ingroup qml-working-with-data
- \since 4.7
\brief The ListModel element defines a free-form list data source.
The ListModel is a simple container of ListElement definitions, each containing data roles.
@@ -436,7 +436,7 @@ QVariant QDeclarativeListModel::data(int index, int role) const
}
/*!
- \qmlproperty int ListModel::count
+ \qmlproperty int QtQuick2::ListModel::count
The number of data entries in the model.
*/
int QDeclarativeListModel::count() const
@@ -445,7 +445,7 @@ int QDeclarativeListModel::count() const
}
/*!
- \qmlmethod ListModel::clear()
+ \qmlmethod QtQuick2::ListModel::clear()
Deletes all content from the model.
@@ -498,7 +498,7 @@ ModelObject *ModelNode::object(const NestedListModel *model)
}
/*!
- \qmlmethod ListModel::remove(int index)
+ \qmlmethod QtQuick2::ListModel::remove(int index)
Deletes the content at \a index from the model.
@@ -523,7 +523,7 @@ void QDeclarativeListModel::remove(int index)
}
/*!
- \qmlmethod ListModel::insert(int index, jsobject dict)
+ \qmlmethod QtQuick2::ListModel::insert(int index, jsobject dict)
Adds a new item to the list model at position \a index, with the
values in \a dict.
@@ -560,7 +560,7 @@ void QDeclarativeListModel::insert(int index, const QDeclarativeV8Handle &handle
}
/*!
- \qmlmethod ListModel::move(int from, int to, int n)
+ \qmlmethod QtQuick2::ListModel::move(int from, int to, int n)
Moves \a n items \a from one position \a to another.
@@ -604,7 +604,7 @@ void QDeclarativeListModel::move(int from, int to, int n)
}
/*!
- \qmlmethod ListModel::append(jsobject dict)
+ \qmlmethod QtQuick2::ListModel::append(jsobject dict)
Adds a new item to the end of the list model, with the
values in \a dict.
@@ -628,7 +628,7 @@ void QDeclarativeListModel::append(const QDeclarativeV8Handle &handle)
}
/*!
- \qmlmethod object ListModel::get(int index)
+ \qmlmethod object QtQuick2::ListModel::get(int index)
Returns the item at \a index in the list model. This allows the item
data to be accessed or modified from JavaScript:
@@ -665,7 +665,7 @@ QDeclarativeV8Handle QDeclarativeListModel::get(int index) const
}
/*!
- \qmlmethod ListModel::set(int index, jsobject dict)
+ \qmlmethod QtQuick2::ListModel::set(int index, jsobject dict)
Changes the item at \a index in the list model with the
values in \a dict. Properties not appearing in \a dict
@@ -712,7 +712,7 @@ void QDeclarativeListModel::set(int index, const QDeclarativeV8Handle &handle, Q
}
/*!
- \qmlmethod ListModel::setProperty(int index, string property, variant value)
+ \qmlmethod QtQuick2::ListModel::setProperty(int index, string property, variant value)
Changes the \a property of the item at \a index in the list model to \a value.
@@ -746,7 +746,7 @@ void QDeclarativeListModel::setProperty(int index, const QString& property, cons
}
/*!
- \qmlmethod ListModel::sync()
+ \qmlmethod QtQuick2::ListModel::sync()
Writes any unsaved changes to the list model after it has been modified
from a worker script.
@@ -1019,8 +1019,8 @@ bool QDeclarativeListModelParser::definesEmptyList(const QString &s)
/*!
\qmlclass ListElement QDeclarativeListElement
+ \inqmlmodule QtQuick 2
\ingroup qml-working-with-data
- \since 4.7
\brief The ListElement element defines a data item in a ListModel.
List elements are defined inside ListModel definitions, and represent items in a
diff --git a/src/declarative/util/qdeclarativelistmodel_p.h b/src/declarative/util/qdeclarativelistmodel_p.h
index 94a7e65bfb..e7c5632ce3 100644
--- a/src/declarative/util/qdeclarativelistmodel_p.h
+++ b/src/declarative/util/qdeclarativelistmodel_p.h
@@ -125,6 +125,7 @@ Q_OBJECT
class QDeclarativeListModelParser : public QDeclarativeCustomParser
{
public:
+ QDeclarativeListModelParser() : QDeclarativeCustomParser(QDeclarativeCustomParser::AcceptsSignalHandlers) {}
QByteArray compile(const QList<QDeclarativeCustomParserProperty> &);
void setCustomData(QObject *, const QByteArray &);
diff --git a/src/declarative/util/qdeclarativepackage.cpp b/src/declarative/util/qdeclarativepackage.cpp
index 2f96b3c6da..4973ee212a 100644
--- a/src/declarative/util/qdeclarativepackage.cpp
+++ b/src/declarative/util/qdeclarativepackage.cpp
@@ -48,6 +48,7 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass Package QDeclarativePackage
+ \inqmlmodule QtQuick 2
\ingroup qml-working-with-data
\brief Package provides a collection of named items.
@@ -75,7 +76,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \qmlattachedproperty string Package::name
+ \qmlattachedproperty string QtQuick2::Package::name
This attached property holds the name of an item within a Package.
*/
diff --git a/src/declarative/util/qdeclarativepath.cpp b/src/declarative/util/qdeclarativepath.cpp
index 7b5d966719..34752b5242 100644
--- a/src/declarative/util/qdeclarativepath.cpp
+++ b/src/declarative/util/qdeclarativepath.cpp
@@ -53,8 +53,8 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass PathElement QDeclarativePathElement
+ \inqmlmodule QtQuick 2
\ingroup qml-view-elements
- \since 4.7
\brief PathElement is the base path type.
This type is the base for all path types. It cannot
@@ -65,8 +65,8 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass Path QDeclarativePath
+ \inqmlmodule QtQuick 2
\ingroup qml-view-elements
- \since 4.7
\brief A Path object defines a path for use by \l PathView.
A Path is composed of one or more path segments - PathLine, PathQuad,
@@ -90,8 +90,8 @@ QDeclarativePath::~QDeclarativePath()
}
/*!
- \qmlproperty real Path::startX
- \qmlproperty real Path::startY
+ \qmlproperty real QtQuick2::Path::startX
+ \qmlproperty real QtQuick2::Path::startY
These properties hold the starting position of the path.
*/
qreal QDeclarativePath::startX() const
@@ -127,7 +127,7 @@ void QDeclarativePath::setStartY(qreal y)
}
/*!
- \qmlproperty bool Path::closed
+ \qmlproperty bool QtQuick2::Path::closed
This property holds whether the start and end of the path are identical.
*/
bool QDeclarativePath::isClosed() const
@@ -137,7 +137,7 @@ bool QDeclarativePath::isClosed() const
}
/*!
- \qmlproperty list<PathElement> Path::pathElements
+ \qmlproperty list<PathElement> QtQuick2::Path::pathElements
This property holds the objects composing the path.
\default
@@ -502,8 +502,8 @@ void QDeclarativeCurve::setY(qreal y)
/*!
\qmlclass PathAttribute QDeclarativePathAttribute
+ \inqmlmodule QtQuick 2
\ingroup qml-view-elements
- \since 4.7
\brief The PathAttribute allows setting an attribute at a given position in a Path.
The PathAttribute object allows attributes consisting of a name and
@@ -533,7 +533,7 @@ void QDeclarativeCurve::setY(qreal y)
*/
/*!
- \qmlproperty string PathAttribute::name
+ \qmlproperty string QtQuick2::PathAttribute::name
This property holds the name of the attribute to change.
This attribute will be available to the delegate as PathView.<name>
@@ -562,7 +562,7 @@ void QDeclarativePathAttribute::setName(const QString &name)
}
/*!
- \qmlproperty real PathAttribute::value
+ \qmlproperty real QtQuick2::PathAttribute::value
This property holds the value for the attribute.
The value specified can be used to influence the visual appearance
@@ -618,8 +618,8 @@ void QDeclarativePathAttribute::setValue(qreal value)
/*!
\qmlclass PathLine QDeclarativePathLine
+ \inqmlmodule QtQuick 2
\ingroup qml-view-elements
- \since 4.7
\brief The PathLine defines a straight line.
The example below creates a path consisting of a straight line from
@@ -636,8 +636,8 @@ void QDeclarativePathAttribute::setValue(qreal value)
*/
/*!
- \qmlproperty real PathLine::x
- \qmlproperty real PathLine::y
+ \qmlproperty real QtQuick2::PathLine::x
+ \qmlproperty real QtQuick2::PathLine::y
Defines the end point of the line.
*/
@@ -651,8 +651,8 @@ void QDeclarativePathLine::addToPath(QPainterPath &path)
/*!
\qmlclass PathQuad QDeclarativePathQuad
+ \inqmlmodule QtQuick 2
\ingroup qml-view-elements
- \since 4.7
\brief The PathQuad defines a quadratic Bezier curve with a control point.
The following QML produces the path shown below:
@@ -672,15 +672,15 @@ void QDeclarativePathLine::addToPath(QPainterPath &path)
*/
/*!
- \qmlproperty real PathQuad::x
- \qmlproperty real PathQuad::y
+ \qmlproperty real QtQuick2::PathQuad::x
+ \qmlproperty real QtQuick2::PathQuad::y
Defines the end point of the curve.
*/
/*!
- \qmlproperty real PathQuad::controlX
- \qmlproperty real PathQuad::controlY
+ \qmlproperty real QtQuick2::PathQuad::controlX
+ \qmlproperty real QtQuick2::PathQuad::controlY
Defines the position of the control point.
*/
@@ -729,8 +729,8 @@ void QDeclarativePathQuad::addToPath(QPainterPath &path)
/*!
\qmlclass PathCubic QDeclarativePathCubic
+ \inqmlmodule QtQuick 2
\ingroup qml-view-elements
- \since 4.7
\brief The PathCubic defines a cubic Bezier curve with two control points.
The following QML produces the path shown below:
@@ -754,15 +754,15 @@ void QDeclarativePathQuad::addToPath(QPainterPath &path)
*/
/*!
- \qmlproperty real PathCubic::x
- \qmlproperty real PathCubic::y
+ \qmlproperty real QtQuick2::PathCubic::x
+ \qmlproperty real QtQuick2::PathCubic::y
Defines the end point of the curve.
*/
/*!
- \qmlproperty real PathCubic::control1X
- \qmlproperty real PathCubic::control1Y
+ \qmlproperty real QtQuick2::PathCubic::control1X
+ \qmlproperty real QtQuick2::PathCubic::control1Y
Defines the position of the first control point.
*/
@@ -795,8 +795,8 @@ void QDeclarativePathCubic::setControl1Y(qreal y)
}
/*!
- \qmlproperty real PathCubic::control2X
- \qmlproperty real PathCubic::control2Y
+ \qmlproperty real QtQuick2::PathCubic::control2X
+ \qmlproperty real QtQuick2::PathCubic::control2Y
Defines the position of the second control point.
*/
@@ -837,8 +837,8 @@ void QDeclarativePathCubic::addToPath(QPainterPath &path)
/*!
\qmlclass PathPercent QDeclarativePathPercent
+ \inqmlmodule QtQuick 2
\ingroup qml-view-elements
- \since 4.7
\brief The PathPercent manipulates the way a path is interpreted.
PathPercent allows you to manipulate the spacing between items on a
@@ -886,7 +886,7 @@ void QDeclarativePathCubic::addToPath(QPainterPath &path)
*/
/*!
- \qmlproperty real PathPercent::value
+ \qmlproperty real QtQuick2::PathPercent::value
The proporation of items that should be laid out up to this point.
This value should always be higher than the last value specified
diff --git a/src/declarative/util/qdeclarativepropertychanges.cpp b/src/declarative/util/qdeclarativepropertychanges.cpp
index 5cdf785ccd..d03cd3bb1a 100644
--- a/src/declarative/util/qdeclarativepropertychanges.cpp
+++ b/src/declarative/util/qdeclarativepropertychanges.cpp
@@ -65,8 +65,8 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass PropertyChanges QDeclarativePropertyChanges
+ \inqmlmodule QtQuick 2
\ingroup qml-state-elements
- \since 4.7
\brief The PropertyChanges element describes new property bindings or values for a state.
PropertyChanges is used to define the property values or bindings in a
@@ -132,7 +132,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \qmlproperty Object PropertyChanges::target
+ \qmlproperty Object QtQuick2::PropertyChanges::target
This property holds the object which contains the properties to be changed.
*/
@@ -394,7 +394,7 @@ void QDeclarativePropertyChanges::setObject(QObject *o)
}
/*!
- \qmlproperty bool PropertyChanges::restoreEntryValues
+ \qmlproperty bool QtQuick2::PropertyChanges::restoreEntryValues
This property holds whether the previous values should be restored when
leaving the state.
@@ -496,7 +496,7 @@ QDeclarativePropertyChanges::ActionList QDeclarativePropertyChanges::actions()
}
/*!
- \qmlproperty bool PropertyChanges::explicit
+ \qmlproperty bool QtQuick2::PropertyChanges::explicit
If explicit is set to true, any potential bindings will be interpreted as
once-off assignments that occur when the state is entered.
diff --git a/src/declarative/util/qdeclarativepropertymap.cpp b/src/declarative/util/qdeclarativepropertymap.cpp
index 765e237051..c9242672c5 100644
--- a/src/declarative/util/qdeclarativepropertymap.cpp
+++ b/src/declarative/util/qdeclarativepropertymap.cpp
@@ -97,7 +97,6 @@ void QDeclarativePropertyMapMetaObject::propertyCreated(int, QMetaPropertyBuilde
/*!
\class QDeclarativePropertyMap
- \since 4.7
\brief The QDeclarativePropertyMap class allows you to set key-value pairs that can be used in QML bindings.
QDeclarativePropertyMap provides a convenient way to expose domain data to the UI layer.
diff --git a/src/declarative/util/qdeclarativesmoothedanimation.cpp b/src/declarative/util/qdeclarativesmoothedanimation.cpp
index 2200d2c77c..f76531a5f7 100644
--- a/src/declarative/util/qdeclarativesmoothedanimation.cpp
+++ b/src/declarative/util/qdeclarativesmoothedanimation.cpp
@@ -253,8 +253,8 @@ void QSmoothedAnimation::init()
/*!
\qmlclass SmoothedAnimation QDeclarativeSmoothedAnimation
+ \inqmlmodule QtQuick 2
\ingroup qml-animation-transition
- \since 4.7
\inherits NumberAnimation
\brief The SmoothedAnimation element allows a property to smoothly track a value.
@@ -382,7 +382,7 @@ void QDeclarativeSmoothedAnimation::transition(QDeclarativeStateActions &actions
}
/*!
- \qmlproperty enumeration SmoothedAnimation::reversingMode
+ \qmlproperty enumeration QtQuick2::SmoothedAnimation::reversingMode
Sets how the SmoothedAnimation behaves if an animation direction is reversed.
@@ -412,7 +412,7 @@ void QDeclarativeSmoothedAnimation::setReversingMode(ReversingMode m)
}
/*!
- \qmlproperty int SmoothedAnimation::duration
+ \qmlproperty int QtQuick2::SmoothedAnimation::duration
This property holds the animation duration, in msecs, used when tracking the source.
@@ -445,7 +445,7 @@ qreal QDeclarativeSmoothedAnimation::velocity() const
}
/*!
- \qmlproperty real SmoothedAnimation::velocity
+ \qmlproperty real QtQuick2::SmoothedAnimation::velocity
This property holds the average velocity allowed when tracking the 'to' value.
@@ -468,7 +468,7 @@ void QDeclarativeSmoothedAnimation::setVelocity(qreal v)
}
/*!
- \qmlproperty int SmoothedAnimation::maximumEasingTime
+ \qmlproperty int QtQuick2::SmoothedAnimation::maximumEasingTime
This property specifies the maximum time, in msecs, any "eases" during the follow should take.
Setting this property causes the velocity to "level out" after at a time. Setting
diff --git a/src/declarative/util/qdeclarativespringanimation.cpp b/src/declarative/util/qdeclarativespringanimation.cpp
index 2c6058caf6..619811f789 100644
--- a/src/declarative/util/qdeclarativespringanimation.cpp
+++ b/src/declarative/util/qdeclarativespringanimation.cpp
@@ -235,9 +235,9 @@ void QDeclarativeSpringAnimationPrivate::updateMode()
/*!
\qmlclass SpringAnimation QDeclarativeSpringAnimation
+ \inqmlmodule QtQuick 2
\ingroup qml-animation-transition
\inherits NumberAnimation
- \since 4.7
\brief The SpringAnimation element allows a property to track a value in a spring-like motion.
@@ -273,7 +273,7 @@ QDeclarativeSpringAnimation::~QDeclarativeSpringAnimation()
}
/*!
- \qmlproperty real SpringAnimation::velocity
+ \qmlproperty real QtQuick2::SpringAnimation::velocity
This property holds the maximum velocity allowed when tracking the source.
@@ -295,7 +295,7 @@ void QDeclarativeSpringAnimation::setVelocity(qreal velocity)
}
/*!
- \qmlproperty real SpringAnimation::spring
+ \qmlproperty real QtQuick2::SpringAnimation::spring
This property describes how strongly the target is pulled towards the
source. The default value is 0 (that is, the spring-like motion is disabled).
@@ -319,7 +319,7 @@ void QDeclarativeSpringAnimation::setSpring(qreal spring)
}
/*!
- \qmlproperty real SpringAnimation::damping
+ \qmlproperty real QtQuick2::SpringAnimation::damping
This property holds the spring damping value.
This value describes how quickly the spring-like motion comes to rest.
@@ -345,7 +345,7 @@ void QDeclarativeSpringAnimation::setDamping(qreal damping)
/*!
- \qmlproperty real SpringAnimation::epsilon
+ \qmlproperty real QtQuick2::SpringAnimation::epsilon
This property holds the spring epsilon.
The epsilon is the rate and amount of change in the value which is close enough
@@ -367,7 +367,7 @@ void QDeclarativeSpringAnimation::setEpsilon(qreal epsilon)
}
/*!
- \qmlproperty real SpringAnimation::modulus
+ \qmlproperty real QtQuick2::SpringAnimation::modulus
This property holds the modulus value. The default value is 0.
Setting a \a modulus forces the target value to "wrap around" at the modulus.
@@ -391,7 +391,7 @@ void QDeclarativeSpringAnimation::setModulus(qreal modulus)
}
/*!
- \qmlproperty real SpringAnimation::mass
+ \qmlproperty real QtQuick2::SpringAnimation::mass
This property holds the "mass" of the property being moved.
The value is 1.0 by default.
diff --git a/src/declarative/util/qdeclarativestate.cpp b/src/declarative/util/qdeclarativestate.cpp
index 9f56ccb02e..4779208c5f 100644
--- a/src/declarative/util/qdeclarativestate.cpp
+++ b/src/declarative/util/qdeclarativestate.cpp
@@ -130,8 +130,8 @@ QDeclarativeStateOperation::QDeclarativeStateOperation(QObjectPrivate &dd, QObje
/*!
\qmlclass State QDeclarativeState
+ \inqmlmodule QtQuick 2
\ingroup qml-state-elements
- \since 4.7
\brief The State element defines configurations of objects and properties.
A \e state is a set of batched changes from the default configuration.
@@ -176,7 +176,7 @@ QDeclarativeState::~QDeclarativeState()
}
/*!
- \qmlproperty string State::name
+ \qmlproperty string QtQuick2::State::name
This property holds the name of the state.
Each state should have a unique name within its item.
@@ -207,7 +207,7 @@ bool QDeclarativeState::isWhenKnown() const
}
/*!
- \qmlproperty bool State::when
+ \qmlproperty bool QtQuick2::State::when
This property holds when the state should be applied.
This should be set to an expression that evaluates to \c true when you want the state to
@@ -245,7 +245,7 @@ void QDeclarativeState::setWhen(QDeclarativeBinding *when)
}
/*!
- \qmlproperty string State::extend
+ \qmlproperty string QtQuick2::State::extend
This property holds the state that this state extends.
When a state extends another state, it inherits all the changes of that state.
@@ -266,7 +266,7 @@ void QDeclarativeState::setExtends(const QString &extends)
}
/*!
- \qmlproperty list<Change> State::changes
+ \qmlproperty list<Change> QtQuick2::State::changes
This property holds the changes to apply for this state
\default
@@ -315,13 +315,15 @@ void QDeclarativeStatePrivate::complete()
}
reverting.clear();
+ if (group)
+ group->stateAboutToComplete();
emit q->completed();
}
// Generate a list of actions for this state. This includes coelescing state
// actions that this state "extends"
QDeclarativeStateOperation::ActionList
-QDeclarativeStatePrivate::generateActionList(QDeclarativeStateGroup *group) const
+QDeclarativeStatePrivate::generateActionList() const
{
QDeclarativeStateOperation::ActionList applyList;
if (inState)
@@ -331,11 +333,11 @@ QDeclarativeStatePrivate::generateActionList(QDeclarativeStateGroup *group) cons
inState = true;
if (!extends.isEmpty()) {
- QList<QDeclarativeState *> states = group->states();
+ QList<QDeclarativeState *> states = group ? group->states() : QList<QDeclarativeState *>();
for (int ii = 0; ii < states.count(); ++ii)
if (states.at(ii)->name() == extends) {
qmlExecuteDeferred(states.at(ii));
- applyList = static_cast<QDeclarativeStatePrivate*>(states.at(ii)->d_func())->generateActionList(group);
+ applyList = static_cast<QDeclarativeStatePrivate*>(states.at(ii)->d_func())->generateActionList();
}
}
@@ -559,7 +561,7 @@ bool QDeclarativeState::isStateActive() const
return stateGroup() && stateGroup()->state() == name();
}
-void QDeclarativeState::apply(QDeclarativeStateGroup *group, QDeclarativeTransition *trans, QDeclarativeState *revert)
+void QDeclarativeState::apply(QDeclarativeTransition *trans, QDeclarativeState *revert)
{
Q_D(QDeclarativeState);
@@ -579,7 +581,7 @@ void QDeclarativeState::apply(QDeclarativeStateGroup *group, QDeclarativeTransit
}
// List of actions caused by this state
- QDeclarativeStateOperation::ActionList applyList = d->generateActionList(group);
+ QDeclarativeStateOperation::ActionList applyList = d->generateActionList();
// List of actions that need to be reverted to roll back (just) this state
QDeclarativeStatePrivate::SimpleActionList additionalReverts;
diff --git a/src/declarative/util/qdeclarativestate_p.h b/src/declarative/util/qdeclarativestate_p.h
index d24304ccf5..a7aafe32fe 100644
--- a/src/declarative/util/qdeclarativestate_p.h
+++ b/src/declarative/util/qdeclarativestate_p.h
@@ -174,7 +174,7 @@ public:
QDeclarativeState &operator<<(QDeclarativeStateOperation *);
- void apply(QDeclarativeStateGroup *, QDeclarativeTransition *, QDeclarativeState *revert);
+ void apply(QDeclarativeTransition *, QDeclarativeState *revert);
void cancel();
QDeclarativeStateGroup *stateGroup() const;
diff --git a/src/declarative/util/qdeclarativestate_p_p.h b/src/declarative/util/qdeclarativestate_p_p.h
index 195b935cdb..2479413511 100644
--- a/src/declarative/util/qdeclarativestate_p_p.h
+++ b/src/declarative/util/qdeclarativestate_p_p.h
@@ -246,7 +246,7 @@ public:
mutable bool inState;
QDeclarativeStateGroup *group;
- QDeclarativeStateOperation::ActionList generateActionList(QDeclarativeStateGroup *) const;
+ QDeclarativeStateOperation::ActionList generateActionList() const;
void complete();
};
diff --git a/src/declarative/util/qdeclarativestategroup.cpp b/src/declarative/util/qdeclarativestategroup.cpp
index c098a38f9c..4f9593011b 100644
--- a/src/declarative/util/qdeclarativestategroup.cpp
+++ b/src/declarative/util/qdeclarativestategroup.cpp
@@ -93,8 +93,8 @@ public:
/*!
\qmlclass StateGroup QDeclarativeStateGroup
+ \inqmlmodule QtQuick 2
\ingroup qml-state-elements
- \since 4.7
\brief The StateGroup element provides state support for non-Item elements.
Item (and all derived elements) provides built in support for states and transitions
@@ -140,7 +140,7 @@ QList<QDeclarativeState *> QDeclarativeStateGroup::states() const
}
/*!
- \qmlproperty list<State> StateGroup::states
+ \qmlproperty list<State> QtQuick2::StateGroup::states
This property holds a list of states defined by the state group.
\qml
@@ -201,7 +201,7 @@ void QDeclarativeStateGroupPrivate::clear_states(QDeclarativeListProperty<QDecla
}
/*!
- \qmlproperty list<Transition> StateGroup::transitions
+ \qmlproperty list<Transition> QtQuick2::StateGroup::transitions
This property holds a list of transitions defined by the state group.
\qml
@@ -255,7 +255,7 @@ void QDeclarativeStateGroupPrivate::clear_transitions(QDeclarativeListProperty<Q
}
/*!
- \qmlproperty string StateGroup::state
+ \qmlproperty string QtQuick2::StateGroup::state
This property holds the name of the current state of the state group.
@@ -372,6 +372,8 @@ QDeclarativeTransition *QDeclarativeStateGroupPrivate::findTransition(const QStr
for (int ii = 0; !done && ii < transitions.count(); ++ii) {
QDeclarativeTransition *t = transitions.at(ii);
+ if (!t->enabled())
+ continue;
for (int ii = 0; ii < 2; ++ii)
{
if (ii && (!t->reversible() ||
@@ -382,7 +384,11 @@ QDeclarativeTransition *QDeclarativeStateGroupPrivate::findTransition(const QStr
QStringList toState;
fromState = t->fromState().split(QLatin1Char(','));
+ for (int jj = 0; jj < fromState.count(); ++jj)
+ fromState[jj] = fromState.at(jj).trimmed();
toState = t->toState().split(QLatin1Char(','));
+ for (int jj = 0; jj < toState.count(); ++jj)
+ toState[jj] = toState.at(jj).trimmed();
if (ii == 1)
qSwap(fromState, toState);
int tScore = 0;
@@ -468,15 +474,17 @@ void QDeclarativeStateGroupPrivate::setCurrentStateInternal(const QString &state
}
if (oldState == 0 || newState == 0) {
- if (!nullState) { nullState = new QDeclarativeState; QDeclarative_setParent_noEvent(nullState, q); }
+ if (!nullState) {
+ nullState = new QDeclarativeState;
+ QDeclarative_setParent_noEvent(nullState, q);
+ nullState->setStateGroup(q);
+ }
if (!oldState) oldState = nullState;
if (!newState) newState = nullState;
}
- newState->apply(q, transition, oldState);
- applyingState = false;
- if (!transition)
- static_cast<QDeclarativeStatePrivate*>(QObjectPrivate::get(newState))->complete();
+ newState->apply(transition, oldState);
+ applyingState = false; //### consider removing this (don't allow state changes in transition)
}
QDeclarativeState *QDeclarativeStateGroup::findState(const QString &name) const
@@ -497,6 +505,12 @@ void QDeclarativeStateGroup::removeState(QDeclarativeState *state)
d->states.removeOne(state);
}
+void QDeclarativeStateGroup::stateAboutToComplete()
+{
+ Q_D(QDeclarativeStateGroup);
+ d->applyingState = false;
+}
+
QT_END_NAMESPACE
diff --git a/src/declarative/util/qdeclarativestategroup_p.h b/src/declarative/util/qdeclarativestategroup_p.h
index 65d9536236..e539f3fb16 100644
--- a/src/declarative/util/qdeclarativestategroup_p.h
+++ b/src/declarative/util/qdeclarativestategroup_p.h
@@ -74,6 +74,7 @@ public:
QDeclarativeListProperty<QDeclarativeTransition> transitionsProperty();
QDeclarativeState *findState(const QString &name) const;
+ void removeState(QDeclarativeState *state);
virtual void classBegin();
virtual void componentComplete();
@@ -82,8 +83,9 @@ Q_SIGNALS:
private:
friend class QDeclarativeState;
+ friend class QDeclarativeStatePrivate;
bool updateAutoState();
- void removeState(QDeclarativeState *state);
+ void stateAboutToComplete();
};
QT_END_NAMESPACE
diff --git a/src/declarative/util/qdeclarativestateoperations.cpp b/src/declarative/util/qdeclarativestateoperations.cpp
index 33ee99bba5..32f36105fc 100644
--- a/src/declarative/util/qdeclarativestateoperations.cpp
+++ b/src/declarative/util/qdeclarativestateoperations.cpp
@@ -71,6 +71,7 @@ public:
/*!
\qmlclass StateChangeScript QDeclarativeStateChangeScript
+ \inqmlmodule QtQuick 2
\ingroup qml-state-elements
\brief The StateChangeScript element allows you to run a script in a state.
@@ -93,7 +94,7 @@ QDeclarativeStateChangeScript::~QDeclarativeStateChangeScript()
}
/*!
- \qmlproperty script StateChangeScript::script
+ \qmlproperty script QtQuick2::StateChangeScript::script
This property holds the script to run when the state is current.
*/
QDeclarativeScriptString QDeclarativeStateChangeScript::script() const
@@ -109,7 +110,7 @@ void QDeclarativeStateChangeScript::setScript(const QDeclarativeScriptString &s)
}
/*!
- \qmlproperty string StateChangeScript::name
+ \qmlproperty string QtQuick2::StateChangeScript::name
This property holds the name of the script. This name can be used by a
ScriptAction to target a specific script.
diff --git a/src/declarative/util/qdeclarativesystempalette.cpp b/src/declarative/util/qdeclarativesystempalette.cpp
index 3fe2e81df4..7c5a535935 100644
--- a/src/declarative/util/qdeclarativesystempalette.cpp
+++ b/src/declarative/util/qdeclarativesystempalette.cpp
@@ -58,8 +58,8 @@ public:
/*!
\qmlclass SystemPalette QDeclarativeSystemPalette
+ \inqmlmodule QtQuick 2
\ingroup qml-utility-elements
- \since 4.7
\brief The SystemPalette element provides access to the Qt palettes.
The SystemPalette element provides access to the Qt application
@@ -94,7 +94,7 @@ QDeclarativeSystemPalette::~QDeclarativeSystemPalette()
}
/*!
- \qmlproperty color SystemPalette::window
+ \qmlproperty color QtQuick2::SystemPalette::window
The window (general background) color of the current color group.
\sa QPalette::ColorRole
@@ -106,7 +106,7 @@ QColor QDeclarativeSystemPalette::window() const
}
/*!
- \qmlproperty color SystemPalette::windowText
+ \qmlproperty color QtQuick2::SystemPalette::windowText
The window text (general foreground) color of the current color group.
\sa QPalette::ColorRole
@@ -118,7 +118,7 @@ QColor QDeclarativeSystemPalette::windowText() const
}
/*!
- \qmlproperty color SystemPalette::base
+ \qmlproperty color QtQuick2::SystemPalette::base
The base color of the current color group.
\sa QPalette::ColorRole
@@ -130,7 +130,7 @@ QColor QDeclarativeSystemPalette::base() const
}
/*!
- \qmlproperty color SystemPalette::text
+ \qmlproperty color QtQuick2::SystemPalette::text
The text color of the current color group.
\sa QPalette::ColorRole
@@ -142,7 +142,7 @@ QColor QDeclarativeSystemPalette::text() const
}
/*!
- \qmlproperty color SystemPalette::alternateBase
+ \qmlproperty color QtQuick2::SystemPalette::alternateBase
The alternate base color of the current color group.
\sa QPalette::ColorRole
@@ -154,7 +154,7 @@ QColor QDeclarativeSystemPalette::alternateBase() const
}
/*!
- \qmlproperty color SystemPalette::button
+ \qmlproperty color QtQuick2::SystemPalette::button
The button color of the current color group.
\sa QPalette::ColorRole
@@ -166,7 +166,7 @@ QColor QDeclarativeSystemPalette::button() const
}
/*!
- \qmlproperty color SystemPalette::buttonText
+ \qmlproperty color QtQuick2::SystemPalette::buttonText
The button text foreground color of the current color group.
\sa QPalette::ColorRole
@@ -178,7 +178,7 @@ QColor QDeclarativeSystemPalette::buttonText() const
}
/*!
- \qmlproperty color SystemPalette::light
+ \qmlproperty color QtQuick2::SystemPalette::light
The light color of the current color group.
\sa QPalette::ColorRole
@@ -190,7 +190,7 @@ QColor QDeclarativeSystemPalette::light() const
}
/*!
- \qmlproperty color SystemPalette::midlight
+ \qmlproperty color QtQuick2::SystemPalette::midlight
The midlight color of the current color group.
\sa QPalette::ColorRole
@@ -202,7 +202,7 @@ QColor QDeclarativeSystemPalette::midlight() const
}
/*!
- \qmlproperty color SystemPalette::dark
+ \qmlproperty color QtQuick2::SystemPalette::dark
The dark color of the current color group.
\sa QPalette::ColorRole
@@ -214,7 +214,7 @@ QColor QDeclarativeSystemPalette::dark() const
}
/*!
- \qmlproperty color SystemPalette::mid
+ \qmlproperty color QtQuick2::SystemPalette::mid
The mid color of the current color group.
\sa QPalette::ColorRole
@@ -226,7 +226,7 @@ QColor QDeclarativeSystemPalette::mid() const
}
/*!
- \qmlproperty color SystemPalette::shadow
+ \qmlproperty color QtQuick2::SystemPalette::shadow
The shadow color of the current color group.
\sa QPalette::ColorRole
@@ -238,7 +238,7 @@ QColor QDeclarativeSystemPalette::shadow() const
}
/*!
- \qmlproperty color SystemPalette::highlight
+ \qmlproperty color QtQuick2::SystemPalette::highlight
The highlight color of the current color group.
\sa QPalette::ColorRole
@@ -250,7 +250,7 @@ QColor QDeclarativeSystemPalette::highlight() const
}
/*!
- \qmlproperty color SystemPalette::highlightedText
+ \qmlproperty color QtQuick2::SystemPalette::highlightedText
The highlighted text color of the current color group.
\sa QPalette::ColorRole
@@ -262,7 +262,7 @@ QColor QDeclarativeSystemPalette::highlightedText() const
}
/*!
- \qmlproperty enumeration SystemPalette::colorGroup
+ \qmlproperty enumeration QtQuick2::SystemPalette::colorGroup
The color group of the palette. This can be one of:
diff --git a/src/declarative/util/qdeclarativetimer.cpp b/src/declarative/util/qdeclarativetimer.cpp
index de3e6ce44d..de37f60bf5 100644
--- a/src/declarative/util/qdeclarativetimer.cpp
+++ b/src/declarative/util/qdeclarativetimer.cpp
@@ -70,8 +70,8 @@ public:
/*!
\qmlclass Timer QDeclarativeTimer
+ \inqmlmodule QtQuick 2
\ingroup qml-utility-elements
- \since 4.7
\brief The Timer item triggers a handler at a specified interval.
A Timer can be used to trigger an action either once, or repeatedly
@@ -118,7 +118,7 @@ QDeclarativeTimer::QDeclarativeTimer(QObject *parent)
}
/*!
- \qmlproperty int Timer::interval
+ \qmlproperty int QtQuick2::Timer::interval
Sets the \a interval between triggers, in milliseconds.
@@ -141,7 +141,7 @@ int QDeclarativeTimer::interval() const
}
/*!
- \qmlproperty bool Timer::running
+ \qmlproperty bool QtQuick2::Timer::running
If set to true, starts the timer; otherwise stops the timer.
For a non-repeating timer, \a running is set to false after the
@@ -169,7 +169,7 @@ void QDeclarativeTimer::setRunning(bool running)
}
/*!
- \qmlproperty bool Timer::repeat
+ \qmlproperty bool QtQuick2::Timer::repeat
If \a repeat is true the timer is triggered repeatedly at the
specified interval; otherwise, the timer will trigger once at the
@@ -196,7 +196,7 @@ void QDeclarativeTimer::setRepeating(bool repeating)
}
/*!
- \qmlproperty bool Timer::triggeredOnStart
+ \qmlproperty bool QtQuick2::Timer::triggeredOnStart
When a timer is started, the first trigger is usually after the specified
interval has elapsed. It is sometimes desirable to trigger immediately
@@ -229,7 +229,7 @@ void QDeclarativeTimer::setTriggeredOnStart(bool triggeredOnStart)
}
/*!
- \qmlmethod Timer::start()
+ \qmlmethod QtQuick2::Timer::start()
\brief Starts the timer.
If the timer is already running, calling this method has no effect. The
@@ -241,7 +241,7 @@ void QDeclarativeTimer::start()
}
/*!
- \qmlmethod Timer::stop()
+ \qmlmethod QtQuick2::Timer::stop()
\brief Stops the timer.
If the timer is not running, calling this method has no effect. The
@@ -253,7 +253,7 @@ void QDeclarativeTimer::stop()
}
/*!
- \qmlmethod Timer::restart()
+ \qmlmethod QtQuick2::Timer::restart()
\brief Restarts the timer.
If the Timer is not running it will be started, otherwise it will be
@@ -298,7 +298,7 @@ void QDeclarativeTimer::componentComplete()
}
/*!
- \qmlsignal Timer::onTriggered()
+ \qmlsignal QtQuick2::Timer::onTriggered()
This handler is called when the Timer is triggered.
*/
diff --git a/src/declarative/util/qdeclarativetransition.cpp b/src/declarative/util/qdeclarativetransition.cpp
index b63407c66a..df22a57c1d 100644
--- a/src/declarative/util/qdeclarativetransition.cpp
+++ b/src/declarative/util/qdeclarativetransition.cpp
@@ -53,8 +53,8 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass Transition QDeclarativeTransition
+ \inqmlmodule QtQuick 2
\ingroup qml-animation-transition
- \since 4.7
\brief The Transition element defines animated transitions that occur on state changes.
A Transition defines the animations to be applied when a \l State change occurs.
@@ -113,7 +113,7 @@ class QDeclarativeTransitionPrivate : public QObjectPrivate
public:
QDeclarativeTransitionPrivate()
: fromState(QLatin1String("*")), toState(QLatin1String("*")),
- reversed(false), reversible(false), endState(0)
+ reversed(false), reversible(false), enabled(true), manager(0)
{
group.trans = this;
}
@@ -122,12 +122,13 @@ public:
QString toState;
bool reversed;
bool reversible;
+ bool enabled;
ParallelAnimationWrapper group;
- QDeclarativeTransitionManager *endState;
+ QDeclarativeTransitionManager *manager;
void complete()
{
- endState->complete();
+ manager->complete();
}
static void append_animation(QDeclarativeListProperty<QDeclarativeAbstractAnimation> *list, QDeclarativeAbstractAnimation *a);
static int animation_count(QDeclarativeListProperty<QDeclarativeAbstractAnimation> *list);
@@ -202,7 +203,7 @@ void QDeclarativeTransition::setReversed(bool r)
void QDeclarativeTransition::prepare(QDeclarativeStateOperation::ActionList &actions,
QList<QDeclarativeProperty> &after,
- QDeclarativeTransitionManager *endState)
+ QDeclarativeTransitionManager *manager)
{
Q_D(QDeclarativeTransition);
@@ -218,14 +219,14 @@ void QDeclarativeTransition::prepare(QDeclarativeStateOperation::ActionList &act
}
}
- d->endState = endState;
+ d->manager = manager;
d->group.setDirection(d->reversed ? QAbstractAnimation::Backward : QAbstractAnimation::Forward);
d->group.start();
}
/*!
- \qmlproperty string Transition::from
- \qmlproperty string Transition::to
+ \qmlproperty string QtQuick2::Transition::from
+ \qmlproperty string QtQuick2::Transition::to
These properties indicate the state changes that trigger the transition.
@@ -244,6 +245,8 @@ void QDeclarativeTransition::prepare(QDeclarativeStateOperation::ActionList &act
The animation would only be applied when changing from the default state to
the "brighter" state (i.e. when the mouse is pressed, but not on release).
+ Multiple \c to and \from values can be set by using a comma-separated string.
+
\sa reversible
*/
QString QDeclarativeTransition::fromState() const
@@ -263,7 +266,7 @@ void QDeclarativeTransition::setFromState(const QString &f)
}
/*!
- \qmlproperty bool Transition::reversible
+ \qmlproperty bool QtQuick2::Transition::reversible
This property holds whether the transition should be automatically reversed when the conditions that triggered this transition are reversed.
The default value is false.
@@ -319,7 +322,50 @@ void QDeclarativeTransition::setToState(const QString &t)
}
/*!
- \qmlproperty list<Animation> Transition::animations
+ \qmlproperty bool QtQuick2::Transition::enabled
+
+ This property holds whether the Transition will be run when moving
+ from the \c from state to the \c to state.
+
+ By default a Transition is enabled.
+
+ Note that in some circumstances disabling a Transition may cause an
+ alternative Transition to be used in its place. In the following
+ example, the generic Transition will be used to animate the change
+ from \c state1 to \c state2, as the more specific Transition has
+ been disabled.
+
+ \qml
+ Item {
+ states: [
+ State { name: "state1" ... }
+ State { name: "state2" ... }
+ ]
+ transitions: [
+ Transition { from: "state1"; to: "state2"; enabled: false ... }
+ Transition { ... }
+ ]
+ }
+ \endqml
+*/
+
+bool QDeclarativeTransition::enabled() const
+{
+ Q_D(const QDeclarativeTransition);
+ return d->enabled;
+}
+
+void QDeclarativeTransition::setEnabled(bool enabled)
+{
+ Q_D(QDeclarativeTransition);
+ if (d->enabled == enabled)
+ return;
+ d->enabled = enabled;
+ emit enabledChanged();
+}
+
+/*!
+ \qmlproperty list<Animation> QtQuick2::Transition::animations
\default
This property holds a list of the animations to be run for this transition.
diff --git a/src/declarative/util/qdeclarativetransition_p.h b/src/declarative/util/qdeclarativetransition_p.h
index 115b947109..db102582d2 100644
--- a/src/declarative/util/qdeclarativetransition_p.h
+++ b/src/declarative/util/qdeclarativetransition_p.h
@@ -66,6 +66,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeTransition : public QObject
Q_PROPERTY(QString to READ toState WRITE setToState NOTIFY toChanged)
Q_PROPERTY(bool reversible READ reversible WRITE setReversible NOTIFY reversibleChanged)
Q_PROPERTY(QDeclarativeListProperty<QDeclarativeAbstractAnimation> animations READ animations)
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
Q_CLASSINFO("DefaultProperty", "animations")
Q_CLASSINFO("DeferredPropertyNames", "animations")
@@ -82,6 +83,9 @@ public:
bool reversible() const;
void setReversible(bool);
+ bool enabled() const;
+ void setEnabled(bool enabled);
+
QDeclarativeListProperty<QDeclarativeAbstractAnimation> animations();
void prepare(QDeclarativeStateOperation::ActionList &actions,
@@ -95,6 +99,7 @@ Q_SIGNALS:
void fromChanged();
void toChanged();
void reversibleChanged();
+ void enabledChanged();
};
QT_END_NAMESPACE
diff --git a/src/declarative/util/qdeclarativetransitionmanager.cpp b/src/declarative/util/qdeclarativetransitionmanager.cpp
index 6e96ac914c..0b549b7cf7 100644
--- a/src/declarative/util/qdeclarativetransitionmanager.cpp
+++ b/src/declarative/util/qdeclarativetransitionmanager.cpp
@@ -246,7 +246,7 @@ void QDeclarativeTransitionManager::transition(const QList<QDeclarativeAction> &
}
#endif
if (!transition)
- d->applyBindings();
+ complete();
}
void QDeclarativeTransitionManager::cancel()
diff --git a/src/declarative/util/qdeclarativeutilmodule.cpp b/src/declarative/util/qdeclarativeutilmodule.cpp
index 9f3c9b05bf..980a8b1cb9 100644
--- a/src/declarative/util/qdeclarativeutilmodule.cpp
+++ b/src/declarative/util/qdeclarativeutilmodule.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -17,7 +17,7 @@
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.2, included in the file LGPL_EXCEPTION.txt in this package.
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
diff --git a/src/declarative/util/qdeclarativexmllistmodel.cpp b/src/declarative/util/qdeclarativexmllistmodel.cpp
index 5b978f49d8..47ef76213a 100644
--- a/src/declarative/util/qdeclarativexmllistmodel.cpp
+++ b/src/declarative/util/qdeclarativexmllistmodel.cpp
@@ -71,15 +71,15 @@ typedef QPair<int, int> QDeclarativeXmlListRange;
/*!
\qmlclass XmlRole QDeclarativeXmlListModelRole
+ \inqmlmodule QtQuick 2
\ingroup qml-working-with-data
- \since 4.7
\brief The XmlRole element allows you to specify a role for an XmlListModel.
\sa {QtDeclarative}
*/
/*!
- \qmlproperty string XmlRole::name
+ \qmlproperty string QtQuick2::XmlRole::name
The name for the role. This name is used to access the model data for this role.
@@ -106,7 +106,7 @@ typedef QPair<int, int> QDeclarativeXmlListRange;
*/
/*!
- \qmlproperty string XmlRole::query
+ \qmlproperty string QtQuick2::XmlRole::query
The relative XPath expression query for this role. The query must be relative; it cannot start
with a '/'.
@@ -124,7 +124,7 @@ typedef QPair<int, int> QDeclarativeXmlListRange;
*/
/*!
- \qmlproperty bool XmlRole::isKey
+ \qmlproperty bool QtQuick2::XmlRole::isKey
Defines whether this is a key role.
Key roles are used to to determine whether a set of values should
@@ -147,114 +147,217 @@ struct XmlQueryJob
QString prefix;
};
-class QDeclarativeXmlQuery : public QObject
+
+class QDeclarativeXmlQueryEngine;
+class QDeclarativeXmlQueryThreadObject : public QObject
{
Q_OBJECT
public:
- QDeclarativeXmlQuery(QObject *parent=0)
- : QObject(parent), m_queryIds(XMLLISTMODEL_CLEAR_ID + 1) {
- qRegisterMetaType<QDeclarativeXmlQueryResult>("QDeclarativeXmlQueryResult");
- moveToThread(&m_thread);
- m_thread.start(QThread::IdlePriority);
- }
+ QDeclarativeXmlQueryThreadObject(QDeclarativeXmlQueryEngine *);
- ~QDeclarativeXmlQuery() {
- if(m_thread.isRunning()) {
- m_thread.quit();
- m_thread.wait();
- }
- }
-
- void abort(int id) {
- QMutexLocker ml(&m_mutex);
- if (id != -1) {
- m_jobs.remove(id);
- }
- }
-
- int doQuery(QString query, QString namespaces, QByteArray data, QList<QDeclarativeXmlListModelRole *>* roleObjects, QStringList keyRoleResultsCache) {
- {
- QMutexLocker m1(&m_mutex);
- m_queryIds.ref();
- if (m_queryIds <= 0)
- m_queryIds = 1;
- }
-
- XmlQueryJob job;
- job.queryId = m_queryIds;
- job.data = data;
- job.query = QLatin1String("doc($src)") + query;
- job.namespaces = namespaces;
- job.keyRoleResultsCache = keyRoleResultsCache;
-
- for (int i=0; i<roleObjects->count(); i++) {
- if (!roleObjects->at(i)->isValid()) {
- job.roleQueries << QString();
- continue;
- }
- job.roleQueries << roleObjects->at(i)->query();
- job.roleQueryErrorId << static_cast<void*>(roleObjects->at(i));
- if (roleObjects->at(i)->isKey())
- job.keyRoleQueries << job.roleQueries.last();
- }
+ void processJobs();
+ virtual bool event(QEvent *e);
- {
- QMutexLocker ml(&m_mutex);
- m_jobs.insert(m_queryIds, job);
- }
+private:
+ QDeclarativeXmlQueryEngine *m_queryEngine;
+};
- QMetaObject::invokeMethod(this, "processQuery", Qt::QueuedConnection, Q_ARG(int, job.queryId));
- return job.queryId;
- }
-private slots:
- void processQuery(int queryId) {
- XmlQueryJob job;
+class QDeclarativeXmlQueryEngine : public QThread
+{
+ Q_OBJECT
+public:
+ QDeclarativeXmlQueryEngine(QDeclarativeEngine *eng);
+ ~QDeclarativeXmlQueryEngine();
- {
- QMutexLocker ml(&m_mutex);
- if (!m_jobs.contains(queryId))
- return;
- job = m_jobs.value(queryId);
- }
+ int doQuery(QString query, QString namespaces, QByteArray data, QList<QDeclarativeXmlListModelRole *>* roleObjects, QStringList keyRoleResultsCache);
+ void abort(int id);
- QDeclarativeXmlQueryResult result;
- result.queryId = job.queryId;
- doQueryJob(&job, &result);
- doSubQueryJob(&job, &result);
+ void processJobs();
- {
- QMutexLocker ml(&m_mutex);
- if (m_jobs.contains(queryId)) {
- emit queryCompleted(result);
- m_jobs.remove(queryId);
- }
- }
- }
+ static QDeclarativeXmlQueryEngine *instance(QDeclarativeEngine *engine);
-Q_SIGNALS:
+signals:
void queryCompleted(const QDeclarativeXmlQueryResult &);
void error(void*, const QString&);
protected:
-
+ void run();
private:
+ void processQuery(XmlQueryJob *job);
void doQueryJob(XmlQueryJob *job, QDeclarativeXmlQueryResult *currentResult);
void doSubQueryJob(XmlQueryJob *job, QDeclarativeXmlQueryResult *currentResult);
void getValuesOfKeyRoles(const XmlQueryJob& currentJob, QStringList *values, QXmlQuery *query) const;
void addIndexToRangeList(QList<QDeclarativeXmlListRange> *ranges, int index) const;
-private:
QMutex m_mutex;
- QThread m_thread;
- QMap<int, XmlQueryJob> m_jobs;
+ QDeclarativeXmlQueryThreadObject *m_threadObject;
+ QList<XmlQueryJob> m_jobs;
+ QSet<int> m_cancelledJobs;
QAtomicInt m_queryIds;
+
+ QDeclarativeEngine *m_engine;
+ QObject *m_eventLoopQuitHack;
+
+ static QHash<QDeclarativeEngine *,QDeclarativeXmlQueryEngine*> queryEngines;
+ static QMutex queryEnginesMutex;
};
+QHash<QDeclarativeEngine *,QDeclarativeXmlQueryEngine*> QDeclarativeXmlQueryEngine::queryEngines;
+QMutex QDeclarativeXmlQueryEngine::queryEnginesMutex;
+
+
+QDeclarativeXmlQueryThreadObject::QDeclarativeXmlQueryThreadObject(QDeclarativeXmlQueryEngine *e)
+ : m_queryEngine(e)
+{
+}
+
+void QDeclarativeXmlQueryThreadObject::processJobs()
+{
+ QCoreApplication::postEvent(this, new QEvent(QEvent::User));
+}
+
+bool QDeclarativeXmlQueryThreadObject::event(QEvent *e)
+{
+ if (e->type() == QEvent::User) {
+ m_queryEngine->processJobs();
+ return true;
+ } else {
+ return QObject::event(e);
+ }
+}
+
+
+
+QDeclarativeXmlQueryEngine::QDeclarativeXmlQueryEngine(QDeclarativeEngine *eng)
+: QThread(eng), m_threadObject(0), m_queryIds(XMLLISTMODEL_CLEAR_ID + 1), m_engine(eng), m_eventLoopQuitHack(0)
+{
+ qRegisterMetaType<QDeclarativeXmlQueryResult>("QDeclarativeXmlQueryResult");
+
+ m_eventLoopQuitHack = new QObject;
+ m_eventLoopQuitHack->moveToThread(this);
+ connect(m_eventLoopQuitHack, SIGNAL(destroyed(QObject*)), SLOT(quit()), Qt::DirectConnection);
+ start(QThread::IdlePriority);
+}
+
+QDeclarativeXmlQueryEngine::~QDeclarativeXmlQueryEngine()
+{
+ queryEnginesMutex.lock();
+ queryEngines.remove(m_engine);
+ queryEnginesMutex.unlock();
+
+ m_eventLoopQuitHack->deleteLater();
+ wait();
+}
-Q_GLOBAL_STATIC(QDeclarativeXmlQuery, globalXmlQuery)
+int QDeclarativeXmlQueryEngine::doQuery(QString query, QString namespaces, QByteArray data, QList<QDeclarativeXmlListModelRole *>* roleObjects, QStringList keyRoleResultsCache) {
+ {
+ QMutexLocker m1(&m_mutex);
+ m_queryIds.ref();
+ if (m_queryIds <= 0)
+ m_queryIds = 1;
+ }
+
+ XmlQueryJob job;
+ job.queryId = m_queryIds;
+ job.data = data;
+ job.query = QLatin1String("doc($src)") + query;
+ job.namespaces = namespaces;
+ job.keyRoleResultsCache = keyRoleResultsCache;
+
+ for (int i=0; i<roleObjects->count(); i++) {
+ if (!roleObjects->at(i)->isValid()) {
+ job.roleQueries << QString();
+ continue;
+ }
+ job.roleQueries << roleObjects->at(i)->query();
+ job.roleQueryErrorId << static_cast<void*>(roleObjects->at(i));
+ if (roleObjects->at(i)->isKey())
+ job.keyRoleQueries << job.roleQueries.last();
+ }
+
+ {
+ QMutexLocker ml(&m_mutex);
+ m_jobs.append(job);
+ if (m_threadObject)
+ m_threadObject->processJobs();
+ }
+
+ return job.queryId;
+}
+
+void QDeclarativeXmlQueryEngine::abort(int id)
+{
+ QMutexLocker ml(&m_mutex);
+ if (id != -1)
+ m_cancelledJobs.insert(id);
+}
+
+void QDeclarativeXmlQueryEngine::run()
+{
+ m_mutex.lock();
+ m_threadObject = new QDeclarativeXmlQueryThreadObject(this);
+ m_mutex.unlock();
+
+ processJobs();
+ exec();
+
+ delete m_threadObject;
+ m_threadObject = 0;
+}
+
+void QDeclarativeXmlQueryEngine::processJobs()
+{
+ QMutexLocker locker(&m_mutex);
+
+ while (true) {
+ if (m_jobs.isEmpty())
+ return;
+
+ XmlQueryJob currentJob = m_jobs.takeLast();
+ while (m_cancelledJobs.remove(currentJob.queryId)) {
+ if (m_jobs.isEmpty())
+ return;
+ currentJob = m_jobs.takeLast();
+ }
-void QDeclarativeXmlQuery::doQueryJob(XmlQueryJob *currentJob, QDeclarativeXmlQueryResult *currentResult)
+ locker.unlock();
+ processQuery(&currentJob);
+ locker.relock();
+ }
+}
+
+QDeclarativeXmlQueryEngine *QDeclarativeXmlQueryEngine::instance(QDeclarativeEngine *engine)
+{
+ queryEnginesMutex.lock();
+ QDeclarativeXmlQueryEngine *queryEng = queryEngines.value(engine);
+ if (!queryEng) {
+ queryEng = new QDeclarativeXmlQueryEngine(engine);
+ queryEngines.insert(engine, queryEng);
+ }
+ queryEnginesMutex.unlock();
+
+ return queryEng;
+}
+
+void QDeclarativeXmlQueryEngine::processQuery(XmlQueryJob *job)
+{
+ QDeclarativeXmlQueryResult result;
+ result.queryId = job->queryId;
+ doQueryJob(job, &result);
+ doSubQueryJob(job, &result);
+
+ {
+ QMutexLocker ml(&m_mutex);
+ if (m_cancelledJobs.contains(job->queryId)) {
+ m_cancelledJobs.remove(job->queryId);
+ } else {
+ emit queryCompleted(result);
+ }
+ }
+}
+
+void QDeclarativeXmlQueryEngine::doQueryJob(XmlQueryJob *currentJob, QDeclarativeXmlQueryResult *currentResult)
{
Q_ASSERT(currentJob->queryId != -1);
@@ -293,7 +396,7 @@ void QDeclarativeXmlQuery::doQueryJob(XmlQueryJob *currentJob, QDeclarativeXmlQu
currentResult->size = (count > 0 ? count : 0);
}
-void QDeclarativeXmlQuery::getValuesOfKeyRoles(const XmlQueryJob& currentJob, QStringList *values, QXmlQuery *query) const
+void QDeclarativeXmlQueryEngine::getValuesOfKeyRoles(const XmlQueryJob& currentJob, QStringList *values, QXmlQuery *query) const
{
const QStringList &keysQueries = currentJob.keyRoleQueries;
QString keysQuery;
@@ -314,7 +417,7 @@ void QDeclarativeXmlQuery::getValuesOfKeyRoles(const XmlQueryJob& currentJob, QS
}
}
-void QDeclarativeXmlQuery::addIndexToRangeList(QList<QDeclarativeXmlListRange> *ranges, int index) const {
+void QDeclarativeXmlQueryEngine::addIndexToRangeList(QList<QDeclarativeXmlListRange> *ranges, int index) const {
if (ranges->isEmpty())
ranges->append(qMakePair(index, 1));
else if (ranges->last().first + ranges->last().second == index)
@@ -323,7 +426,7 @@ void QDeclarativeXmlQuery::addIndexToRangeList(QList<QDeclarativeXmlListRange> *
ranges->append(qMakePair(index, 1));
}
-void QDeclarativeXmlQuery::doSubQueryJob(XmlQueryJob *currentJob, QDeclarativeXmlQueryResult *currentResult)
+void QDeclarativeXmlQueryEngine::doSubQueryJob(XmlQueryJob *currentJob, QDeclarativeXmlQueryResult *currentResult)
{
Q_ASSERT(currentJob->queryId != -1);
@@ -434,6 +537,15 @@ public:
emit q->statusChanged(status);
}
+ void deleteReply() {
+ Q_Q(QDeclarativeXmlListModel);
+ if (reply) {
+ QObject::disconnect(reply, 0, q, 0);
+ reply->deleteLater();
+ reply = 0;
+ }
+ }
+
bool isComponentComplete;
QUrl src;
QString xml;
@@ -443,6 +555,7 @@ public:
QList<int> roles;
QStringList roleNames;
int highestRole;
+
QNetworkReply *reply;
QDeclarativeXmlListModel::Status status;
QString errorString;
@@ -450,6 +563,7 @@ public:
int queryId;
QStringList keyRoleResultsCache;
QList<QDeclarativeXmlListModelRole *> roleObjects;
+
static void append_role(QDeclarativeListProperty<QDeclarativeXmlListModelRole> *list, QDeclarativeXmlListModelRole *role);
static void clear_role(QDeclarativeListProperty<QDeclarativeXmlListModelRole> *list);
QList<QList<QVariant> > data;
@@ -485,8 +599,8 @@ void QDeclarativeXmlListModelPrivate::clear_role(QDeclarativeListProperty<QDecla
/*!
\qmlclass XmlListModel QDeclarativeXmlListModel
+ \inqmlmodule QtQuick 2
\ingroup qml-working-with-data
- \since 4.7
\brief The XmlListModel element is used to specify a read-only model using XPath expressions.
XmlListModel is used to create a read-only model from XML data. It can be used as a data source
@@ -583,10 +697,6 @@ void QDeclarativeXmlListModelPrivate::clear_role(QDeclarativeListProperty<QDecla
QDeclarativeXmlListModel::QDeclarativeXmlListModel(QObject *parent)
: QListModelInterface(*(new QDeclarativeXmlListModelPrivate), parent)
{
- connect(globalXmlQuery(), SIGNAL(queryCompleted(QDeclarativeXmlQueryResult)),
- this, SLOT(queryCompleted(QDeclarativeXmlQueryResult)));
- connect(globalXmlQuery(), SIGNAL(error(void*,QString)),
- this, SLOT(queryError(void*,QString)));
}
QDeclarativeXmlListModel::~QDeclarativeXmlListModel()
@@ -594,7 +704,7 @@ QDeclarativeXmlListModel::~QDeclarativeXmlListModel()
}
/*!
- \qmlproperty list<XmlRole> XmlListModel::roles
+ \qmlproperty list<XmlRole> QtQuick2::XmlListModel::roles
The roles to make available for this model.
*/
@@ -627,7 +737,7 @@ QVariant QDeclarativeXmlListModel::data(int index, int role) const
}
/*!
- \qmlproperty int XmlListModel::count
+ \qmlproperty int QtQuick2::XmlListModel::count
The number of data entries in the model.
*/
int QDeclarativeXmlListModel::count() const
@@ -652,7 +762,7 @@ QString QDeclarativeXmlListModel::toString(int role) const
}
/*!
- \qmlproperty url XmlListModel::source
+ \qmlproperty url QtQuick2::XmlListModel::source
The location of the XML data source.
If both \c source and \l xml are set, \l xml is used.
@@ -675,7 +785,7 @@ void QDeclarativeXmlListModel::setSource(const QUrl &src)
}
/*!
- \qmlproperty string XmlListModel::xml
+ \qmlproperty string QtQuick2::XmlListModel::xml
This property holds the XML data for this model, if set.
The text is assumed to be UTF-8 encoded.
@@ -699,7 +809,7 @@ void QDeclarativeXmlListModel::setXml(const QString &xml)
}
/*!
- \qmlproperty string XmlListModel::query
+ \qmlproperty string QtQuick2::XmlListModel::query
An absolute XPath query representing the base query for creating model items
from this model's XmlRole objects. The query should start with '/' or '//'.
*/
@@ -725,7 +835,7 @@ void QDeclarativeXmlListModel::setQuery(const QString &query)
}
/*!
- \qmlproperty string XmlListModel::namespaceDeclarations
+ \qmlproperty string QtQuick2::XmlListModel::namespaceDeclarations
The namespace declarations to be used in the XPath queries.
The namespaces should be declared as in XQuery. For example, if a requested document
@@ -759,7 +869,7 @@ void QDeclarativeXmlListModel::setNamespaceDeclarations(const QString &declarati
}
/*!
- \qmlmethod object XmlListModel::get(int index)
+ \qmlmethod object QtQuick2::XmlListModel::get(int index)
Returns the item at \a index in the model.
@@ -799,7 +909,7 @@ QDeclarativeV8Handle QDeclarativeXmlListModel::get(int index) const
}
/*!
- \qmlproperty enumeration XmlListModel::status
+ \qmlproperty enumeration QtQuick2::XmlListModel::status
Specifies the model loading status, which can be one of the following:
\list
@@ -820,7 +930,7 @@ QDeclarativeXmlListModel::Status QDeclarativeXmlListModel::status() const
}
/*!
- \qmlproperty real XmlListModel::progress
+ \qmlproperty real QtQuick2::XmlListModel::progress
This indicates the current progress of the downloading of the XML data
source. This value ranges from 0.0 (no data downloaded) to
@@ -841,7 +951,7 @@ qreal QDeclarativeXmlListModel::progress() const
}
/*!
- \qmlmethod void XmlListModel::errorString()
+ \qmlmethod void QtQuick2::XmlListModel::errorString()
Returns a string description of the last error that occurred
if \l status is XmlListModel::Error.
@@ -856,6 +966,12 @@ void QDeclarativeXmlListModel::classBegin()
{
Q_D(QDeclarativeXmlListModel);
d->isComponentComplete = false;
+
+ QDeclarativeXmlQueryEngine *queryEngine = QDeclarativeXmlQueryEngine::instance(qmlEngine(this));
+ connect(queryEngine, SIGNAL(queryCompleted(QDeclarativeXmlQueryResult)),
+ SLOT(queryCompleted(QDeclarativeXmlQueryResult)));
+ connect(queryEngine, SIGNAL(error(void*,QString)),
+ SLOT(queryError(void*,QString)));
}
void QDeclarativeXmlListModel::componentComplete()
@@ -866,7 +982,7 @@ void QDeclarativeXmlListModel::componentComplete()
}
/*!
- \qmlmethod XmlListModel::reload()
+ \qmlmethod QtQuick2::XmlListModel::reload()
Reloads the model.
@@ -885,7 +1001,7 @@ void QDeclarativeXmlListModel::reload()
if (!d->isComponentComplete)
return;
- globalXmlQuery()->abort(d->queryId);
+ QDeclarativeXmlQueryEngine::instance(qmlEngine(this))->abort(d->queryId);
d->queryId = -1;
if (d->size < 0)
@@ -893,15 +1009,11 @@ void QDeclarativeXmlListModel::reload()
if (d->reply) {
d->reply->abort();
- if (d->reply) {
- // abort will generally have already done this (and more)
- d->reply->deleteLater();
- d->reply = 0;
- }
+ d->deleteReply();
}
if (!d->xml.isEmpty()) {
- d->queryId = globalXmlQuery()->doQuery(d->query, d->namespaces, d->xml.toUtf8(), &d->roleObjects, d->keyRoleResultsCache);
+ d->queryId = QDeclarativeXmlQueryEngine::instance(qmlEngine(this))->doQuery(d->query, d->namespaces, d->xml.toUtf8(), &d->roleObjects, d->keyRoleResultsCache);
d->notifyQueryStarted(false);
} else if (d->src.isEmpty()) {
@@ -931,8 +1043,7 @@ void QDeclarativeXmlListModel::requestFinished()
QVariant redirect = d->reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
if (redirect.isValid()) {
QUrl url = d->reply->url().resolved(redirect.toUrl());
- d->reply->deleteLater();
- d->reply = 0;
+ d->deleteReply();
setSource(url);
return;
}
@@ -941,9 +1052,7 @@ void QDeclarativeXmlListModel::requestFinished()
if (d->reply->error() != QNetworkReply::NoError) {
d->errorString = d->reply->errorString();
- disconnect(d->reply, 0, this, 0);
- d->reply->deleteLater();
- d->reply = 0;
+ d->deleteReply();
int count = this->count();
d->data.clear();
@@ -962,11 +1071,9 @@ void QDeclarativeXmlListModel::requestFinished()
d->queryId = XMLLISTMODEL_CLEAR_ID;
QTimer::singleShot(0, this, SLOT(dataCleared()));
} else {
- d->queryId = globalXmlQuery()->doQuery(d->query, d->namespaces, data, &d->roleObjects, d->keyRoleResultsCache);
+ d->queryId = QDeclarativeXmlQueryEngine::instance(qmlEngine(this))->doQuery(d->query, d->namespaces, data, &d->roleObjects, d->keyRoleResultsCache);
}
- disconnect(d->reply, 0, this, 0);
- d->reply->deleteLater();
- d->reply = 0;
+ d->deleteReply();
d->progress = 1.0;
emit progressChanged(d->progress);
diff --git a/src/declarative/util/qlistmodelinterface.cpp b/src/declarative/util/qlistmodelinterface.cpp
index 17fce99f15..56fc8eeb51 100644
--- a/src/declarative/util/qlistmodelinterface.cpp
+++ b/src/declarative/util/qlistmodelinterface.cpp
@@ -46,7 +46,6 @@ QT_BEGIN_NAMESPACE
/*!
\internal
\class QListModelInterface
- \since 4.7
\brief The QListModelInterface class can be subclassed to provide C++ models to QDeclarativeGraphics Views
This class is comprised primarily of pure virtual functions which
diff --git a/src/declarative/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch b/src/declarative/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch
index 4596202944..1fb3b90733 100644
--- a/src/declarative/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch
+++ b/src/declarative/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch
@@ -1,7 +1,7 @@
From e13ce09287a56c920d5ffdc5d4662d49f1838f16 Mon Sep 17 00:00:00 2001
From: Aaron Kennedy <aaron.kennedy@nokia.com>
Date: Mon, 23 May 2011 15:47:20 +1000
-Subject: [PATCH 1/8] Add hashing and comparison methods to v8::String
+Subject: [PATCH 01/13] Add hashing and comparison methods to v8::String
This allows us to more rapidly search for a v8::String inside
a hash of QStrings.
diff --git a/src/declarative/v8/0002-Add-a-bit-field-3-to-Map.patch b/src/declarative/v8/0002-Add-a-bit-field-3-to-Map.patch
index cb578c0f96..daf8b35570 100644
--- a/src/declarative/v8/0002-Add-a-bit-field-3-to-Map.patch
+++ b/src/declarative/v8/0002-Add-a-bit-field-3-to-Map.patch
@@ -1,7 +1,7 @@
From 7c9cfff80b7864d5687432d424074e51712c4a07 Mon Sep 17 00:00:00 2001
From: Aaron Kennedy <aaron.kennedy@nokia.com>
Date: Mon, 23 May 2011 15:55:26 +1000
-Subject: [PATCH 2/8] Add a bit field 3 to Map
+Subject: [PATCH 02/13] Add a bit field 3 to Map
Bit field 3 will be used to add QML specific map flags.
---
diff --git a/src/declarative/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch b/src/declarative/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch
index daa2250a25..1c81b2af9d 100644
--- a/src/declarative/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch
+++ b/src/declarative/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch
@@ -1,7 +1,7 @@
From ae8688b53d67044f2c9b0cce25fc282b078610c1 Mon Sep 17 00:00:00 2001
From: Aaron Kennedy <aaron.kennedy@nokia.com>
Date: Mon, 23 May 2011 16:21:02 +1000
-Subject: [PATCH 3/8] Add a "fallback" mode for named property interceptors
+Subject: [PATCH 03/13] Add a "fallback" mode for named property interceptors
By default interceptors are called before the normal property
resolution on objects. When an interceptor is installed as a
diff --git a/src/declarative/v8/0004-Generalize-external-object-resources.patch b/src/declarative/v8/0004-Generalize-external-object-resources.patch
index 56e5e371fd..6b85666cf0 100644
--- a/src/declarative/v8/0004-Generalize-external-object-resources.patch
+++ b/src/declarative/v8/0004-Generalize-external-object-resources.patch
@@ -1,7 +1,7 @@
From 4827116b12c50f6662794017c5a662b5dbb2da0b Mon Sep 17 00:00:00 2001
From: Aaron Kennedy <aaron.kennedy@nokia.com>
Date: Mon, 23 May 2011 16:55:35 +1000
-Subject: [PATCH 4/8] Generalize external object resources
+Subject: [PATCH 04/13] Generalize external object resources
V8 was already able to manage and finalize an external string
resource. This change generalizes that mechanism to handle a
diff --git a/src/declarative/v8/0005-Introduce-a-QML-compilation-mode.patch b/src/declarative/v8/0005-Introduce-a-QML-compilation-mode.patch
index 7ec10e9448..2dfd3d9699 100644
--- a/src/declarative/v8/0005-Introduce-a-QML-compilation-mode.patch
+++ b/src/declarative/v8/0005-Introduce-a-QML-compilation-mode.patch
@@ -1,7 +1,7 @@
From fd7d475e298e5b63cd6383c78cc900635c82aa38 Mon Sep 17 00:00:00 2001
From: Aaron Kennedy <aaron.kennedy@nokia.com>
Date: Mon, 23 May 2011 18:26:19 +1000
-Subject: [PATCH 5/8] Introduce a QML compilation mode
+Subject: [PATCH 05/13] Introduce a QML compilation mode
In QML mode, there is a second global object - known as the QML
global object. During property resolution, if a property is not
diff --git a/src/declarative/v8/0006-Allow-access-to-the-calling-script-data.patch b/src/declarative/v8/0006-Allow-access-to-the-calling-script-data.patch
index 7af81c3f69..b9c44654cd 100644
--- a/src/declarative/v8/0006-Allow-access-to-the-calling-script-data.patch
+++ b/src/declarative/v8/0006-Allow-access-to-the-calling-script-data.patch
@@ -1,7 +1,7 @@
From f890f0d1a1e5bd62711815489c87755a4f382436 Mon Sep 17 00:00:00 2001
From: Aaron Kennedy <aaron.kennedy@nokia.com>
Date: Wed, 25 May 2011 10:36:13 +1000
-Subject: [PATCH 6/8] Allow access to the calling script data
+Subject: [PATCH 06/13] Allow access to the calling script data
---
include/v8.h | 1 +
diff --git a/src/declarative/v8/0007-Fix-warnings.patch b/src/declarative/v8/0007-Fix-warnings.patch
index 2efc8331aa..60fb24c138 100644
--- a/src/declarative/v8/0007-Fix-warnings.patch
+++ b/src/declarative/v8/0007-Fix-warnings.patch
@@ -1,7 +1,7 @@
From dac5d9db84cf20564621c679937ca7b9c6a8e880 Mon Sep 17 00:00:00 2001
From: Aaron Kennedy <aaron.kennedy@nokia.com>
Date: Fri, 27 May 2011 13:04:15 +1000
-Subject: [PATCH 7/8] Fix warnings
+Subject: [PATCH 07/13] Fix warnings
---
include/v8.h | 16 ++++++++--------
diff --git a/src/declarative/v8/0008-Add-custom-object-compare-callback.patch b/src/declarative/v8/0008-Add-custom-object-compare-callback.patch
index 659cf4c167..fdb0895f06 100644
--- a/src/declarative/v8/0008-Add-custom-object-compare-callback.patch
+++ b/src/declarative/v8/0008-Add-custom-object-compare-callback.patch
@@ -1,7 +1,7 @@
From bec11b8b7f89d135e7d9a823ac4fe98c70d017cf Mon Sep 17 00:00:00 2001
From: Aaron Kennedy <aaron.kennedy@nokia.com>
Date: Mon, 27 Jun 2011 14:57:28 +1000
-Subject: [PATCH 8/8] Add custom object compare callback
+Subject: [PATCH 08/13] Add custom object compare callback
A global custom object comparison callback can be set with:
V8::SetUserObjectComparisonCallbackFunction()
diff --git a/src/v8/0009-Add-CallAsFunction-method-to-the-Object-class-in-the.patch b/src/declarative/v8/0009-Add-CallAsFunction-method-to-the-Object-class-in-the.patch
index 6cd9294d31..89ec7b96bc 100644
--- a/src/v8/0009-Add-CallAsFunction-method-to-the-Object-class-in-the.patch
+++ b/src/declarative/v8/0009-Add-CallAsFunction-method-to-the-Object-class-in-the.patch
@@ -1,7 +1,7 @@
-From 5719ba59309e85f3ca47da6b64df66e710f3016f Mon Sep 17 00:00:00 2001
-From: "ager@chromium.org" <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
+From 4183b973ed3bd603784c798dfa63ba48f6b68003 Mon Sep 17 00:00:00 2001
+From: ager@chromium.org <ager@chromium.org>
Date: Wed, 4 May 2011 13:03:08 +0000
-Subject: [PATCH] Add CallAsFunction method to the Object class in the API
+Subject: [PATCH 09/13] Add CallAsFunction method to the Object class in the API
Patch by Peter Varga.
@@ -20,10 +20,10 @@ git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@7781 ce2b1a6d-e
5 files changed, 163 insertions(+), 37 deletions(-)
diff --git a/include/v8.h b/include/v8.h
-index 4dcbf28..78ee7e6 100644
+index d5d6972..8a8e1cd 100644
--- a/include/v8.h
+++ b/include/v8.h
-@@ -1606,6 +1606,14 @@ class Object : public Value {
+@@ -1757,6 +1757,14 @@ class Object : public Value {
V8EXPORT ExternalArrayType GetIndexedPropertiesExternalArrayDataType();
V8EXPORT int GetIndexedPropertiesExternalArrayDataLength();
@@ -39,10 +39,10 @@ index 4dcbf28..78ee7e6 100644
static inline Object* Cast(Value* obj);
private:
diff --git a/src/api.cc b/src/api.cc
-index 792e488..c72857d 100644
+index 2436031..e412e51 100644
--- a/src/api.cc
+++ b/src/api.cc
-@@ -3255,6 +3255,37 @@ int v8::Object::GetIndexedPropertiesExternalArrayDataLength() {
+@@ -3259,6 +3259,37 @@ int v8::Object::GetIndexedPropertiesExternalArrayDataLength() {
}
@@ -81,10 +81,10 @@ index 792e488..c72857d 100644
return NewInstance(0, NULL);
}
diff --git a/src/execution.cc b/src/execution.cc
-index eb26438..850dec5 100644
+index 1632076..894d741 100644
--- a/src/execution.cc
+++ b/src/execution.cc
-@@ -234,6 +234,30 @@ Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) {
+@@ -254,6 +254,30 @@ Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) {
}
@@ -116,10 +116,10 @@ index eb26438..850dec5 100644
ASSERT(!object->IsJSFunction());
Isolate* isolate = Isolate::Current();
diff --git a/src/execution.h b/src/execution.h
-index d4b80d2..e89d6ba 100644
+index a476eb4..0a0be51 100644
--- a/src/execution.h
+++ b/src/execution.h
-@@ -138,6 +138,8 @@ class Execution : public AllStatic {
+@@ -144,6 +144,8 @@ class Execution : public AllStatic {
// Get a function delegate (or undefined) for the given non-function
// object. Used for support calling objects as functions.
static Handle<Object> GetFunctionDelegate(Handle<Object> object);
@@ -129,7 +129,7 @@ index d4b80d2..e89d6ba 100644
// Get a function delegate (or undefined) for the given non-function
// object. Used for support calling objects as constructors.
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
-index e2a7fb1..c6affe5 100644
+index d7621d1..693d51e 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -6962,50 +6962,111 @@ THREADED_TEST(CallAsFunction) {
@@ -282,5 +282,5 @@ index e2a7fb1..c6affe5 100644
--
-1.7.5.4
+1.7.2.3
diff --git a/src/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch b/src/declarative/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch
index 7d90f0dfbd..09c2d4af1a 100644
--- a/src/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch
+++ b/src/declarative/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch
@@ -1,7 +1,7 @@
-From fd2cc52576e8c89f3dffc2b4b5a9cc9c48a96f32 Mon Sep 17 00:00:00 2001
-From: "ager@chromium.org" <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
+From 3d6d4249878f7960eac4c9c94e0f2529f9a58c4a Mon Sep 17 00:00:00 2001
+From: ager@chromium.org <ager@chromium.org>
Date: Fri, 6 May 2011 11:07:52 +0000
-Subject: [PATCH] Implement CallAsConstructor method for Object in the API
+Subject: [PATCH 10/13] Implement CallAsConstructor method for Object in the API
Patch by Peter Varga.
@@ -20,10 +20,10 @@ git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@7803 ce2b1a6d-e
5 files changed, 276 insertions(+), 8 deletions(-)
diff --git a/include/v8.h b/include/v8.h
-index 4921823..5fc8059 100644
+index 8a8e1cd..84462b5 100644
--- a/include/v8.h
+++ b/include/v8.h
-@@ -1614,6 +1614,14 @@ class Object : public Value {
+@@ -1765,6 +1765,14 @@ class Object : public Value {
int argc,
Handle<Value> argv[]);
@@ -39,10 +39,10 @@ index 4921823..5fc8059 100644
static inline Object* Cast(Value* obj);
private:
diff --git a/src/api.cc b/src/api.cc
-index c5c66a7..9194641 100644
+index e412e51..1a585d6 100644
--- a/src/api.cc
+++ b/src/api.cc
-@@ -3262,7 +3262,7 @@ Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Object> recv, int argc,
+@@ -3266,7 +3266,7 @@ Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Object> recv, int argc,
return Local<v8::Value>());
LOG_API(isolate, "Object::CallAsFunction");
ENTER_V8(isolate);
@@ -51,7 +51,7 @@ index c5c66a7..9194641 100644
i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
-@@ -3282,7 +3282,44 @@ Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Object> recv, int argc,
+@@ -3286,7 +3286,44 @@ Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Object> recv, int argc,
i::Handle<i::Object> returned =
i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
@@ -98,10 +98,10 @@ index c5c66a7..9194641 100644
diff --git a/src/execution.cc b/src/execution.cc
-index 4ab3e78..db74492 100644
+index 894d741..afb352c 100644
--- a/src/execution.cc
+++ b/src/execution.cc
-@@ -277,6 +277,34 @@ Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) {
+@@ -297,6 +297,34 @@ Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) {
}
@@ -137,10 +137,10 @@ index 4ab3e78..db74492 100644
ExecutionAccess access(isolate_);
return (thread_local_.jslimit_ != kInterruptLimit &&
diff --git a/src/execution.h b/src/execution.h
-index 74189a2..7b6a48c 100644
+index 0a0be51..ec2a195 100644
--- a/src/execution.h
+++ b/src/execution.h
-@@ -146,6 +146,8 @@ class Execution : public AllStatic {
+@@ -150,6 +150,8 @@ class Execution : public AllStatic {
// Get a function delegate (or undefined) for the given non-function
// object. Used for support calling objects as constructors.
static Handle<Object> GetConstructorDelegate(Handle<Object> object);
@@ -150,10 +150,10 @@ index 74189a2..7b6a48c 100644
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
-index 1bcc232..f48d5b4 100644
+index 693d51e..1334f63 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
-@@ -6747,6 +6747,200 @@ THREADED_TEST(Constructor) {
+@@ -6746,6 +6746,200 @@ THREADED_TEST(Constructor) {
CHECK(value->BooleanValue());
}
@@ -354,7 +354,7 @@ index 1bcc232..f48d5b4 100644
THREADED_TEST(FunctionDescriptorException) {
v8::HandleScope handle_scope;
LocalContext context;
-@@ -7029,9 +7223,8 @@ THREADED_TEST(CallAsFunction) {
+@@ -7028,9 +7222,8 @@ THREADED_TEST(CallAsFunction) {
CHECK(value.IsEmpty());
CHECK(try_catch.HasCaught());
String::AsciiValue exception_value1(try_catch.Exception());
@@ -366,7 +366,7 @@ index 1bcc232..f48d5b4 100644
try_catch.Reset();
// Call an object without call-as-function handler through the API
-@@ -7041,7 +7234,7 @@ THREADED_TEST(CallAsFunction) {
+@@ -7040,7 +7233,7 @@ THREADED_TEST(CallAsFunction) {
CHECK(value.IsEmpty());
CHECK(try_catch.HasCaught());
String::AsciiValue exception_value2(try_catch.Exception());
@@ -375,7 +375,7 @@ index 1bcc232..f48d5b4 100644
try_catch.Reset();
}
-@@ -7058,14 +7251,14 @@ THREADED_TEST(CallAsFunction) {
+@@ -7057,14 +7250,14 @@ THREADED_TEST(CallAsFunction) {
value = CompileRun("obj3(22)");
CHECK(try_catch.HasCaught());
String::AsciiValue exception_value1(try_catch.Exception());
@@ -393,5 +393,5 @@ index 1bcc232..f48d5b4 100644
}
}
--
-1.7.5.4
+1.7.2.3
diff --git a/src/v8/0011-QtScript-V8-Add-new-v8-api-to-check-if-a-value-is-an.patch b/src/declarative/v8/0011-QtScript-V8-Add-new-v8-api-to-check-if-a-value-is-an.patch
index 0558ce19f6..f4a15bf97a 100644
--- a/src/v8/0011-QtScript-V8-Add-new-v8-api-to-check-if-a-value-is-an.patch
+++ b/src/declarative/v8/0011-QtScript-V8-Add-new-v8-api-to-check-if-a-value-is-an.patch
@@ -1,7 +1,7 @@
-From 859c452847317efe1131e337fcd51514de616ea2 Mon Sep 17 00:00:00 2001
+From f22d0312faeb93ced8747d9aae8c6d77e11b4aba Mon Sep 17 00:00:00 2001
From: Jedrzej Nowacki <jedrzej.nowacki@nokia.com>
Date: Tue, 7 Dec 2010 11:56:42 +0100
-Subject: [PATCH] QtScript/V8: Add new v8 api to check if a value is an error.
+Subject: [PATCH 11/13] QtScript/V8: Add new v8 api to check if a value is an error.
New function v8::Value::IsError was created.
@@ -14,7 +14,7 @@ research.
3 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/include/v8.h b/include/v8.h
-index 303cb7a..f992cb2 100644
+index 84462b5..08b0ec2 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -937,6 +937,11 @@ class Value : public Data {
@@ -30,7 +30,7 @@ index 303cb7a..f992cb2 100644
V8EXPORT Local<Number> ToNumber() const;
V8EXPORT Local<String> ToString() const;
diff --git a/src/api.cc b/src/api.cc
-index fd4a76b..5ada246 100644
+index 1a585d6..bd435eb 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -2108,6 +2108,12 @@ bool Value::IsRegExp() const {
@@ -59,5 +59,5 @@ index 8cbf378..db90bb9 100644
V(to_string_symbol, "toString") \
V(char_at_symbol, "CharAt") \
--
-1.7.4.15.g7811d
+1.7.2.3
diff --git a/src/declarative/v8/0012-Add-IsCallable-method-for-Object-in-the-API.patch b/src/declarative/v8/0012-Add-IsCallable-method-for-Object-in-the-API.patch
new file mode 100644
index 0000000000..e4c46b0cbf
--- /dev/null
+++ b/src/declarative/v8/0012-Add-IsCallable-method-for-Object-in-the-API.patch
@@ -0,0 +1,116 @@
+From 472c04c9e7a64e8734c76d2cf97a7cc5b773b788 Mon Sep 17 00:00:00 2001
+From: ager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
+Date: Mon, 9 May 2011 15:24:48 +0000
+Subject: [PATCH 12/13] Add IsCallable method for Object in the API
+
+Patch by Peter Varga.
+
+BUG=none
+TEST=cctest/test-api/CallableObject
+
+Review URL: http://codereview.chromium.org/6964005
+
+git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@7828 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
+---
+ include/v8.h | 7 +++++++
+ src/api.cc | 11 +++++++++++
+ test/cctest/test-api.cc | 43 +++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 61 insertions(+), 0 deletions(-)
+
+diff --git a/include/v8.h b/include/v8.h
+index 08b0ec2..4194d4a 100644
+--- a/include/v8.h
++++ b/include/v8.h
+@@ -1763,6 +1763,13 @@ class Object : public Value {
+ V8EXPORT int GetIndexedPropertiesExternalArrayDataLength();
+
+ /**
++ * Checks whether a callback is set by the
++ * ObjectTemplate::SetCallAsFunctionHandler method.
++ * When an Object is callable this method returns true.
++ */
++ V8EXPORT bool IsCallable();
++
++ /**
+ * Call an Object as a function if a callback is set by the
+ * ObjectTemplate::SetCallAsFunctionHandler method.
+ */
+diff --git a/src/api.cc b/src/api.cc
+index bd435eb..a5a637f 100644
+--- a/src/api.cc
++++ b/src/api.cc
+@@ -3265,6 +3265,17 @@ int v8::Object::GetIndexedPropertiesExternalArrayDataLength() {
+ }
+
+
++bool v8::Object::IsCallable() {
++ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
++ ON_BAILOUT(isolate, "v8::Object::IsCallable()", return false);
++ ENTER_V8(isolate);
++ i::HandleScope scope(isolate);
++ i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
++ if (obj->IsJSFunction()) return true;
++ return i::Execution::GetFunctionDelegate(obj)->IsJSFunction();
++}
++
++
+ Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Object> recv, int argc,
+ v8::Handle<v8::Value> argv[]) {
+ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
+index 1334f63..45db5a1 100644
+--- a/test/cctest/test-api.cc
++++ b/test/cctest/test-api.cc
+@@ -7263,6 +7263,49 @@ THREADED_TEST(CallAsFunction) {
+ }
+
+
++// Check whether a non-function object is callable.
++THREADED_TEST(CallableObject) {
++ v8::HandleScope scope;
++ LocalContext context;
++
++ { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
++ instance_template->SetCallAsFunctionHandler(call_as_function);
++ Local<Object> instance = instance_template->NewInstance();
++ v8::TryCatch try_catch;
++
++ CHECK(instance->IsCallable());
++ CHECK(!try_catch.HasCaught());
++ }
++
++ { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
++ Local<Object> instance = instance_template->NewInstance();
++ v8::TryCatch try_catch;
++
++ CHECK(!instance->IsCallable());
++ CHECK(!try_catch.HasCaught());
++ }
++
++ { Local<FunctionTemplate> function_template =
++ FunctionTemplate::New(call_as_function);
++ Local<Function> function = function_template->GetFunction();
++ Local<Object> instance = function;
++ v8::TryCatch try_catch;
++
++ CHECK(instance->IsCallable());
++ CHECK(!try_catch.HasCaught());
++ }
++
++ { Local<FunctionTemplate> function_template = FunctionTemplate::New();
++ Local<Function> function = function_template->GetFunction();
++ Local<Object> instance = function;
++ v8::TryCatch try_catch;
++
++ CHECK(instance->IsCallable());
++ CHECK(!try_catch.HasCaught());
++ }
++}
++
++
+ static int CountHandles() {
+ return v8::HandleScope::NumberOfHandles();
+ }
+--
+1.7.2.3
+
diff --git a/src/declarative/v8/0013-Remove-execute-flag-from-v8-debug.h.patch b/src/declarative/v8/0013-Remove-execute-flag-from-v8-debug.h.patch
new file mode 100644
index 0000000000..0a769921cd
--- /dev/null
+++ b/src/declarative/v8/0013-Remove-execute-flag-from-v8-debug.h.patch
@@ -0,0 +1,15 @@
+From dc2cad4f8fc88c52fcea09b8d0262d35cd32dc44 Mon Sep 17 00:00:00 2001
+From: Aaron Kennedy <aaron.kennedy@nokia.com>
+Date: Thu, 25 Aug 2011 11:09:58 +1000
+Subject: [PATCH 13/13] Remove execute flag from v8-debug.h
+
+---
+ 0 files changed, 0 insertions(+), 0 deletions(-)
+ mode change 100755 => 100644 include/v8-debug.h
+
+diff --git a/include/v8-debug.h b/include/v8-debug.h
+old mode 100755
+new mode 100644
+--
+1.7.2.3
+
diff --git a/src/declarative/v8/v8base.pri b/src/declarative/v8/v8base.pri
index 209e4d5127..9cea5cf575 100644
--- a/src/declarative/v8/v8base.pri
+++ b/src/declarative/v8/v8base.pri
@@ -11,8 +11,9 @@ isEmpty(V8DIR) {
# mksnapshot hangs if gcc 4.5 is used
# for reference look at http://code.google.com/p/v8/issues/detail?id=884
- # FIXME how to find 4.5 series?
- message(because of a bug in gcc / v8 we need to add -fno-strict-aliasing)
- QMAKE_CFLAGS += -fno-strict-aliasing
- QMAKE_CXXFLAGS += -fno-strict-aliasing
+ equals(QT_GCC_MAJOR_VERSION, 4): equals(QT_GCC_MINOR_VERSION, 5) {
+ message(because of a bug in gcc / v8 we need to add -fno-strict-aliasing)
+ QMAKE_CFLAGS += -fno-strict-aliasing
+ QMAKE_CXXFLAGS += -fno-strict-aliasing
+ }
}
diff --git a/src/declarative/v8/wrapcc.pl b/src/declarative/v8/wrapcc.pl
index 463ab059ba..27f5f867b0 100755
--- a/src/declarative/v8/wrapcc.pl
+++ b/src/declarative/v8/wrapcc.pl
@@ -8,29 +8,29 @@
## This file is part of the translations module of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:LGPL$
-## No Commercial Usage
-## This file contains pre-release code and may not be distributed.
-## You may use this file in accordance with the terms and conditions
-## contained in the Technology Preview License Agreement accompanying
-## this package.
-##
## 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 as published by the Free Software
-## Foundation and appearing in the file LICENSE.LGPL included in the
-## packaging of this file. Please review the following information to
-## ensure the GNU Lesser General Public License version 2.1 requirements
-## will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+## This file may be used under the terms of the GNU Lesser General Public
+## License version 2.1 as published by the Free Software Foundation and
+## appearing in the file LICENSE.LGPL included in the packaging of this
+## file. Please review the following information to ensure the GNU Lesser
+## General Public License version 2.1 requirements will be met:
+## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
##
## In addition, as a special exception, Nokia gives you certain additional
-## rights. These rights are described in the Nokia Qt LGPL Exception
+## rights. These rights are described in the Nokia Qt LGPL Exception
## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
##
-## If you have questions regarding the use of this file, please contact
-## Nokia at qt-info@nokia.com.
-##
-##
-##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU General
+## Public License version 3.0 as published by the Free Software Foundation
+## and appearing in the file LICENSE.GPL included in the packaging of this
+## file. Please review the following information to ensure the GNU General
+## Public License version 3.0 requirements will be met:
+## http://www.gnu.org/copyleft/gpl.html.
+##
+## Other Usage
+## Alternatively, this file may be used in accordance with the terms and
+## conditions contained in a signed written agreement between you and Nokia.
##
##
##
diff --git a/src/imports/testlib/SignalSpy.qml b/src/imports/testlib/SignalSpy.qml
index 59d44185a1..91b5f03522 100644
--- a/src/imports/testlib/SignalSpy.qml
+++ b/src/imports/testlib/SignalSpy.qml
@@ -46,6 +46,10 @@ Item {
id: spy
visible: false
+ TestUtil {
+ id: util
+ }
+
// Public API.
property variant target: null
@@ -67,7 +71,7 @@ Item {
i += 50
}
var success = (count >= expected)
- if (!qtest_results.verify(success, "wait for signal " + signalName, QtTest.qtest_caller_file(), QtTest.qtest_caller_line()))
+ if (!qtest_results.verify(success, "wait for signal " + signalName, util.callerFile(), util.callerLine()))
throw new Error("QtQuickTest::fail")
}
diff --git a/src/imports/testlib/TestCase.qml b/src/imports/testlib/TestCase.qml
index 1a222a6138..6da66b20de 100644
--- a/src/imports/testlib/TestCase.qml
+++ b/src/imports/testlib/TestCase.qml
@@ -176,7 +176,7 @@ Item {
|| ((typeExp === "object" || typeExp == "declarativeitem") && typeAct === "string")) {
success = (act == exp)
}
- } else if (typeExp === "string" || typeExp === "boolean" || typeExp === "number" ||
+ } else if (typeExp === "string" || typeExp === "boolean" ||
typeExp === "null" || typeExp === "undefined") {
if (exp instanceof act.constructor || act instanceof exp.constructor) {
// to catch short annotaion VS 'new' annotation of act declaration
@@ -188,7 +188,7 @@ Item {
}
} else if (typeExp === "nan") {
success = isNaN(act);
- } else if (typeExp == "number") {
+ } else if (typeExp === "number") {
// Use act fuzzy compare if the two values are floats
if (Math.abs(act - exp) <= 0.00001) {
success = true
diff --git a/src/imports/testlib/main.cpp b/src/imports/testlib/main.cpp
index db0a029a9a..c12b9423a9 100644
--- a/src/imports/testlib/main.cpp
+++ b/src/imports/testlib/main.cpp
@@ -58,8 +58,8 @@ QML_DECLARE_TYPE(QuickTestEvent)
class QuickTestUtil : public QObject
{
Q_OBJECT
- Q_PROPERTY(bool printAvailableFunctions READ printAvailableFunctions)
- Q_PROPERTY(bool wrapper READ wrapper)
+ Q_PROPERTY(bool printAvailableFunctions READ printAvailableFunctions NOTIFY printAvailableFunctionsChanged)
+ Q_PROPERTY(bool wrapper READ wrapper NOTIFY wrapperChanged)
public:
QuickTestUtil(QObject *parent = 0)
:QObject(parent)
@@ -75,7 +75,9 @@ public:
{
return true;
}
-
+Q_SIGNALS:
+ void printAvailableFunctionsChanged();
+ void wrapperChanged();
public Q_SLOTS:
QDeclarativeV8Handle typeName(const QVariant& v) const
diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp
index 3f0c5325ed..3164d9ec06 100644
--- a/src/qmltest/quicktest.cpp
+++ b/src/qmltest/quicktest.cpp
@@ -110,7 +110,10 @@ static inline QString stripQuotes(const QString &s)
int quick_test_main(int argc, char **argv, const char *name, quick_test_viewport_create createViewport, const char *sourceDir)
{
- QApplication app(argc, argv);
+ QApplication* app = 0;
+ if (!QCoreApplication::instance()) {
+ app = new QApplication(argc, argv);
+ }
// Look for QML-specific command-line options.
// -import dir Specify an import directory.
@@ -143,6 +146,10 @@ int quick_test_main(int argc, char **argv, const char *name, quick_test_viewport
argv[outargc] = 0;
argc = outargc;
+ // Parse the command-line arguments.
+ QuickTestResult::parseArgs(argc, argv);
+ QuickTestResult::setProgramName(name);
+
// Determine where to look for the test data.
if (testPath.isEmpty() && sourceDir)
testPath = QString::fromLocal8Bit(sourceDir);
@@ -167,9 +174,6 @@ int quick_test_main(int argc, char **argv, const char *name, quick_test_viewport
return 1;
}
- // Parse the command-line arguments.
- QuickTestResult::parseArgs(argc, argv);
- QuickTestResult::setProgramName(name);
// Scan through all of the "tst_*.qml" files and run each of them
// in turn with a QDeclarativeView.
@@ -287,6 +291,7 @@ int quick_test_main(int argc, char **argv, const char *name, quick_test_viewport
// Flush the current logging stream.
QuickTestResult::setProgramName(0);
+ delete app;
// Return the number of failures as the exit code.
return QuickTestResult::exitCode();
}
diff --git a/src/qtquick1/graphicsitems/qdeclarativeanimatedimage.cpp b/src/qtquick1/graphicsitems/qdeclarativeanimatedimage.cpp
index b1866e419b..a133bd4e68 100644
--- a/src/qtquick1/graphicsitems/qdeclarativeanimatedimage.cpp
+++ b/src/qtquick1/graphicsitems/qdeclarativeanimatedimage.cpp
@@ -86,7 +86,7 @@ QT_BEGIN_NAMESPACE
\bold Note: Unlike images, animated images are not cached or shared internally.
\clearfloat
- \snippet doc/src/snippets/declarative/animatedimage.qml document
+ \snippet doc/src/snippets/qtquick1/animatedimage.qml document
\sa BorderImage, Image
*/
diff --git a/src/qtquick1/graphicsitems/qdeclarativeborderimage.cpp b/src/qtquick1/graphicsitems/qdeclarativeborderimage.cpp
index 8db733ba2e..1beef966f0 100644
--- a/src/qtquick1/graphicsitems/qdeclarativeborderimage.cpp
+++ b/src/qtquick1/graphicsitems/qdeclarativeborderimage.cpp
@@ -102,7 +102,7 @@ QT_BEGIN_NAMESPACE
used to determine the parts of the image that will lie inside the unscaled corner
areas and the parts that will be stretched horizontally and vertically.
- \snippet doc/src/snippets/declarative/borderimage/normal-image.qml normal image
+ \snippet doc/src/snippets/qtquick1/borderimage/normal-image.qml normal image
\clearfloat
\beginfloatleft
@@ -116,7 +116,7 @@ QT_BEGIN_NAMESPACE
is set to \l{BorderImage::verticalTileMode}{BorderImage.Stretch}, the parts of image
in regions 4 and 6 are stretched vertically.
- \snippet doc/src/snippets/declarative/borderimage/borderimage-scaled.qml scaled border image
+ \snippet doc/src/snippets/qtquick1/borderimage/borderimage-scaled.qml scaled border image
\clearfloat
\beginfloatleft
@@ -130,7 +130,7 @@ QT_BEGIN_NAMESPACE
\l{BorderImage::verticalTileMode}{BorderImage.Repeat}, the parts of image in regions
4 and 6 are tiled so that they fill the space at the left and right of the element.
- \snippet doc/src/snippets/declarative/borderimage/borderimage-tiled.qml tiled border image
+ \snippet doc/src/snippets/qtquick1/borderimage/borderimage-tiled.qml tiled border image
\clearfloat
In some situations, the width of regions 2 and 8 may not be an exact multiple of the width
diff --git a/src/qtquick1/graphicsitems/qdeclarativeflickable.cpp b/src/qtquick1/graphicsitems/qdeclarativeflickable.cpp
index 04e926ac46..f145312334 100644
--- a/src/qtquick1/graphicsitems/qdeclarativeflickable.cpp
+++ b/src/qtquick1/graphicsitems/qdeclarativeflickable.cpp
@@ -462,7 +462,7 @@ void QDeclarative1FlickablePrivate::updateBeginningEnd()
The following example shows a small view onto a large image in which the
user can drag or flick the image in order to view different parts of it.
- \snippet doc/src/snippets/declarative/flickable.qml document
+ \snippet doc/src/snippets/qtquick1/flickable.qml document
\clearfloat
@@ -524,9 +524,9 @@ void QDeclarative1FlickablePrivate::updateBeginningEnd()
These properties are typically used to draw a scrollbar. For example:
- \snippet doc/src/snippets/declarative/flickableScrollbar.qml 0
+ \snippet doc/src/snippets/qtquick1/flickableScrollbar.qml 0
\dots 8
- \snippet doc/src/snippets/declarative/flickableScrollbar.qml 1
+ \snippet doc/src/snippets/qtquick1/flickableScrollbar.qml 1
\sa {declarative/ui-components/scrollbar}{scrollbar example}
*/
@@ -1331,7 +1331,7 @@ void QDeclarative1Flickable::setBoundsBehavior(BoundsBehavior b)
The following snippet shows how these properties are used to display
an image that is larger than the Flickable item itself:
- \snippet doc/src/snippets/declarative/flickable.qml document
+ \snippet doc/src/snippets/qtquick1/flickable.qml document
In some cases, the the content dimensions can be automatically set
using the \l {Item::childrenRect.width}{childrenRect.width}
@@ -1566,6 +1566,7 @@ bool QDeclarative1Flickable::sendMouseEvent(QGraphicsSceneMouseEvent *event)
return stealThisEvent || d->delayedPressEvent || disabledItem;
} else if (d->lastPosTime.isValid()) {
d->lastPosTime.invalidate();
+ returnToBounds();
}
if (mouseEvent.type() == QEvent::GraphicsSceneMouseRelease) {
d->clearDelayedPress();
diff --git a/src/qtquick1/graphicsitems/qdeclarativeflipable.cpp b/src/qtquick1/graphicsitems/qdeclarativeflipable.cpp
index 789cadafb4..e9c23b4dfd 100644
--- a/src/qtquick1/graphicsitems/qdeclarativeflipable.cpp
+++ b/src/qtquick1/graphicsitems/qdeclarativeflipable.cpp
@@ -96,7 +96,7 @@ public:
degrees to produce the flipping effect. When \c flipped is false, the
item reverts to the default state, in which the \c angle value is 0.
- \snippet doc/src/snippets/declarative/flipable/flipable.qml 0
+ \snippet doc/src/snippets/qtquick1/flipable/flipable.qml 0
\image flipable.gif
diff --git a/src/qtquick1/graphicsitems/qdeclarativegridview.cpp b/src/qtquick1/graphicsitems/qdeclarativegridview.cpp
index 63b907b022..f2511a15c9 100644
--- a/src/qtquick1/graphicsitems/qdeclarativegridview.cpp
+++ b/src/qtquick1/graphicsitems/qdeclarativegridview.cpp
@@ -1269,7 +1269,7 @@ void QDeclarative1GridViewPrivate::flick(AxisData &data, qreal minExtent, qreal
The following example shows the definition of a simple list model defined
in a file called \c ContactModel.qml:
- \snippet doc/src/snippets/declarative/gridview/ContactModel.qml 0
+ \snippet doc/src/snippets/qtquick1/gridview/ContactModel.qml 0
\div {class="float-right"}
\inlineimage gridview-simple.png
@@ -1283,9 +1283,9 @@ void QDeclarative1GridViewPrivate::flick(AxisData &data, qreal minExtent, qreal
(containing \l Image and \l Text elements) for its delegate.
\clearfloat
- \snippet doc/src/snippets/declarative/gridview/gridview.qml import
+ \snippet doc/src/snippets/qtquick1/gridview/gridview.qml import
\codeline
- \snippet doc/src/snippets/declarative/gridview/gridview.qml classdocs simple
+ \snippet doc/src/snippets/qtquick1/gridview/gridview.qml classdocs simple
\div {class="float-right"}
\inlineimage gridview-highlight.png
@@ -1298,7 +1298,7 @@ void QDeclarative1GridViewPrivate::flick(AxisData &data, qreal minExtent, qreal
into a separate \c contactDelegate component.
\clearfloat
- \snippet doc/src/snippets/declarative/gridview/gridview.qml classdocs advanced
+ \snippet doc/src/snippets/qtquick1/gridview/gridview.qml classdocs advanced
The currently selected item is highlighted with a blue \l Rectangle using the \l highlight property,
and \c focus is set to \c true to enable keyboard navigation for the grid view.
@@ -1312,7 +1312,7 @@ void QDeclarative1GridViewPrivate::flick(AxisData &data, qreal minExtent, qreal
this attached property directly as \c GridView.isCurrentItem, while the child
\c contactInfo object must refer to this property as \c wrapper.GridView.isCurrentItem.
- \snippet doc/src/snippets/declarative/gridview/gridview.qml isCurrentItem
+ \snippet doc/src/snippets/qtquick1/gridview/gridview.qml isCurrentItem
\note Views do not set the \l{Item::}{clip} property automatically.
If the view is not clipped by another item or the screen, it will be necessary
@@ -1351,7 +1351,7 @@ QDeclarative1GridView::~QDeclarative1GridView()
It is attached to each instance of the delegate.
- \snippet doc/src/snippets/declarative/gridview/gridview.qml isCurrentItem
+ \snippet doc/src/snippets/qtquick1/gridview/gridview.qml isCurrentItem
*/
/*!
@@ -1366,7 +1366,7 @@ QDeclarative1GridView::~QDeclarative1GridView()
The example below ensures that the animation completes before
the item is removed from the grid.
- \snippet doc/src/snippets/declarative/gridview/gridview.qml delayRemove
+ \snippet doc/src/snippets/qtquick1/gridview/gridview.qml delayRemove
*/
/*!
@@ -1640,7 +1640,7 @@ void QDeclarative1GridView::setHighlight(QDeclarativeComponent *highlight)
Here is a highlight with its motion defined by a \l {SpringAnimation} item:
- \snippet doc/src/snippets/declarative/gridview/gridview.qml highlightFollowsCurrentItem
+ \snippet doc/src/snippets/qtquick1/gridview/gridview.qml highlightFollowsCurrentItem
*/
bool QDeclarative1GridView::highlightFollowsCurrentItem() const
{
@@ -2748,7 +2748,7 @@ void QDeclarative1GridView::trackedPositionChanged()
void QDeclarative1GridView::itemsInserted(int modelIndex, int count)
{
Q_D(QDeclarative1GridView);
- if (!isComponentComplete())
+ if (!isComponentComplete() || !d->model || !d->model->isValid())
return;
int index = d->visibleItems.count() ? d->mapFromModel(modelIndex) : 0;
@@ -2879,7 +2879,7 @@ void QDeclarative1GridView::itemsInserted(int modelIndex, int count)
void QDeclarative1GridView::itemsRemoved(int modelIndex, int count)
{
Q_D(QDeclarative1GridView);
- if (!isComponentComplete())
+ if (!isComponentComplete() || !d->model || !d->model->isValid())
return;
d->itemCount -= count;
@@ -2979,7 +2979,7 @@ void QDeclarative1GridView::destroyRemoved()
void QDeclarative1GridView::itemsMoved(int from, int to, int count)
{
Q_D(QDeclarative1GridView);
- if (!isComponentComplete())
+ if (!isComponentComplete() || !d->isValid())
return;
QHash<int,FxGridItem1*> moved;
diff --git a/src/qtquick1/graphicsitems/qdeclarativeimage.cpp b/src/qtquick1/graphicsitems/qdeclarativeimage.cpp
index 4e2cd10218..bc301ddf6c 100644
--- a/src/qtquick1/graphicsitems/qdeclarativeimage.cpp
+++ b/src/qtquick1/graphicsitems/qdeclarativeimage.cpp
@@ -76,7 +76,7 @@ QT_BEGIN_NAMESPACE
The following example shows the simplest usage of the Image element.
- \snippet doc/src/snippets/declarative/image.qml document
+ \snippet doc/src/snippets/qtquick1/image.qml document
\beginfloatleft
\image declarative-qtlogo.png
diff --git a/src/qtquick1/graphicsitems/qdeclarativeitem.cpp b/src/qtquick1/graphicsitems/qdeclarativeitem.cpp
index 20b4c11f5b..b32898fe38 100644
--- a/src/qtquick1/graphicsitems/qdeclarativeitem.cpp
+++ b/src/qtquick1/graphicsitems/qdeclarativeitem.cpp
@@ -201,7 +201,7 @@ QT_BEGIN_NAMESPACE
rotations you must specify the axis to rotate around in addition to the origin point.
The following example shows various 3D-like rotations applied to an \l Image.
- \snippet doc/src/snippets/declarative/rotation.qml 0
+ \snippet doc/src/snippets/qtquick1/rotation.qml 0
\image axisrotation.png
@@ -434,7 +434,7 @@ void QDeclarativeItemKeyFilter::componentComplete()
The following example provides key navigation for a 2x2 grid of items:
- \snippet doc/src/snippets/declarative/keynavigation.qml 0
+ \snippet doc/src/snippets/qtquick1/keynavigation.qml 0
The top-left item initially receives focus by setting \l {Item::}{focus} to
\c true. When an arrow key is pressed, the focus will move to the
@@ -821,7 +821,7 @@ void QDeclarative1KeyNavigationAttached::setFocusNavigation(QDeclarativeItem *cu
from left to right by default, they are now positioned from right to left instead, as demonstrated
by the numbering and opacity of the items:
- \snippet doc/src/snippets/declarative/layoutmirroring.qml 0
+ \snippet doc/src/snippets/qtquick1/layoutmirroring.qml 0
\image layoutmirroring.png
@@ -985,13 +985,13 @@ void QDeclarativeItemPrivate::setLayoutMirror(bool mirror)
be used to test for a certain key; in this case, the left cursor
key:
- \snippet doc/src/snippets/declarative/keys/keys-pressed.qml key item
+ \snippet doc/src/snippets/qtquick1/keys/keys-pressed.qml key item
Some keys may alternatively be handled via specific signal properties,
for example \e onSelectPressed. These handlers automatically set
\e event.accepted to true.
- \snippet doc/src/snippets/declarative/keys/keys-handler.qml key item
+ \snippet doc/src/snippets/qtquick1/keys/keys-handler.qml key item
See \l{Qt::Key}{Qt.Key} for the list of keyboard codes.
diff --git a/src/qtquick1/graphicsitems/qdeclarativelistview.cpp b/src/qtquick1/graphicsitems/qdeclarativelistview.cpp
index c58543c735..5119c0e1fb 100644
--- a/src/qtquick1/graphicsitems/qdeclarativelistview.cpp
+++ b/src/qtquick1/graphicsitems/qdeclarativelistview.cpp
@@ -446,6 +446,7 @@ public:
FxListItem1 *snapItemAt(qreal pos) {
FxListItem1 *snapItem = 0;
+ qreal prevItemSize = 0;
for (int i = 0; i < visibleItems.count(); ++i) {
FxListItem1 *item = visibleItems[i];
if (item->index == -1)
@@ -453,8 +454,9 @@ public:
qreal itemTop = item->position();
if (highlight && itemTop >= pos && item->endPosition() <= pos + highlight->size() - 1)
return item;
- if (itemTop+item->size()/2 >= pos && itemTop-item->size()/2 < pos)
+ if (itemTop+item->size()/2 >= pos && itemTop-prevItemSize/2 < pos)
snapItem = item;
+ prevItemSize = item->size();
}
return snapItem;
}
@@ -1564,13 +1566,13 @@ void QDeclarative1ListViewPrivate::flick(AxisData &data, qreal minExtent, qreal
The following example shows the definition of a simple list model defined
in a file called \c ContactModel.qml:
- \snippet doc/src/snippets/declarative/listview/ContactModel.qml 0
+ \snippet doc/src/snippets/qtquick1/listview/ContactModel.qml 0
Another component can display this model data in a ListView, like this:
- \snippet doc/src/snippets/declarative/listview/listview.qml import
+ \snippet doc/src/snippets/qtquick1/listview/listview.qml import
\codeline
- \snippet doc/src/snippets/declarative/listview/listview.qml classdocs simple
+ \snippet doc/src/snippets/qtquick1/listview/listview.qml classdocs simple
\image listview-simple.png
@@ -1581,7 +1583,7 @@ void QDeclarative1ListViewPrivate::flick(AxisData &data, qreal minExtent, qreal
An improved list view is shown below. The delegate is visually improved and is moved
into a separate \c contactDelegate component.
- \snippet doc/src/snippets/declarative/listview/listview.qml classdocs advanced
+ \snippet doc/src/snippets/qtquick1/listview/listview.qml classdocs advanced
\image listview-highlight.png
The currently selected item is highlighted with a blue \l Rectangle using the \l highlight property,
@@ -1596,7 +1598,7 @@ void QDeclarative1ListViewPrivate::flick(AxisData &data, qreal minExtent, qreal
this attached property directly as \c ListView.isCurrentItem, while the child
\c contactInfo object must refer to this property as \c wrapper.ListView.isCurrentItem.
- \snippet doc/src/snippets/declarative/listview/listview.qml isCurrentItem
+ \snippet doc/src/snippets/qtquick1/listview/listview.qml isCurrentItem
\note Views do not enable \e clip automatically. If the view
is not clipped by another item or the screen, it will be necessary
@@ -1631,7 +1633,7 @@ QDeclarative1ListView::~QDeclarative1ListView()
This property may be used to adjust the appearance of the current item, for example:
- \snippet doc/src/snippets/declarative/listview/listview.qml isCurrentItem
+ \snippet doc/src/snippets/qtquick1/listview/listview.qml isCurrentItem
*/
/*!
@@ -1680,7 +1682,7 @@ QDeclarative1ListView::~QDeclarative1ListView()
The example delegate below ensures that the animation completes before
the item is removed from the list.
- \snippet doc/src/snippets/declarative/listview/listview.qml delayRemove
+ \snippet doc/src/snippets/qtquick1/listview/listview.qml delayRemove
*/
/*!
@@ -1960,7 +1962,7 @@ void QDeclarative1ListView::setHighlight(QDeclarativeComponent *highlight)
Here is a highlight with its motion defined by a \l {SpringAnimation} item:
- \snippet doc/src/snippets/declarative/listview/listview.qml highlightFollowsCurrentItem
+ \snippet doc/src/snippets/qtquick1/listview/listview.qml highlightFollowsCurrentItem
Note that the highlight animation also affects the way that the view
is scrolled. This is because the view moves to maintain the
@@ -3131,7 +3133,6 @@ void QDeclarative1ListView::trackedPositionChanged()
qreal trackedPos = qCeil(d->trackedItem->position());
qreal trackedSize = d->trackedItem->size();
if (d->trackedItem != d->currentItem) {
- trackedPos -= d->currentItem->sectionSize();
trackedSize += d->currentItem->sectionSize();
}
qreal viewPos;
@@ -3195,7 +3196,7 @@ void QDeclarative1ListView::trackedPositionChanged()
void QDeclarative1ListView::itemsInserted(int modelIndex, int count)
{
Q_D(QDeclarative1ListView);
- if (!isComponentComplete())
+ if (!isComponentComplete() || !d->model || !d->model->isValid())
return;
d->updateUnrequestedIndexes();
d->moveReason = QDeclarative1ListViewPrivate::Other;
@@ -3338,7 +3339,7 @@ void QDeclarative1ListView::itemsInserted(int modelIndex, int count)
void QDeclarative1ListView::itemsRemoved(int modelIndex, int count)
{
Q_D(QDeclarative1ListView);
- if (!isComponentComplete())
+ if (!isComponentComplete() || !d->model || !d->model->isValid())
return;
d->moveReason = QDeclarative1ListViewPrivate::Other;
d->updateUnrequestedIndexes();
@@ -3453,7 +3454,7 @@ void QDeclarative1ListView::destroyRemoved()
void QDeclarative1ListView::itemsMoved(int from, int to, int count)
{
Q_D(QDeclarative1ListView);
- if (!isComponentComplete())
+ if (!isComponentComplete() || !d->isValid())
return;
d->updateUnrequestedIndexes();
diff --git a/src/qtquick1/graphicsitems/qdeclarativeloader.cpp b/src/qtquick1/graphicsitems/qdeclarativeloader.cpp
index 7162c31662..3b68ed4a9e 100644
--- a/src/qtquick1/graphicsitems/qdeclarativeloader.cpp
+++ b/src/qtquick1/graphicsitems/qdeclarativeloader.cpp
@@ -138,7 +138,7 @@ void QDeclarative1LoaderPrivate::initResize()
Here is a Loader that loads "Page1.qml" as a component when the
\l MouseArea is clicked:
- \snippet doc/src/snippets/declarative/loader/simple.qml 0
+ \snippet doc/src/snippets/qtquick1/loader/simple.qml 0
The loaded item can be accessed using the \l item property.
@@ -170,8 +170,8 @@ void QDeclarative1LoaderPrivate::initResize()
\o sizeloader.qml
\o sizeitem.qml
\row
- \o \snippet doc/src/snippets/declarative/loader/sizeloader.qml 0
- \o \snippet doc/src/snippets/declarative/loader/sizeitem.qml 0
+ \o \snippet doc/src/snippets/qtquick1/loader/sizeloader.qml 0
+ \o \snippet doc/src/snippets/qtquick1/loader/sizeitem.qml 0
\row
\o The red rectangle will be sized to the size of the root item.
\o The red rectangle will be 50x50, centered in the root item.
@@ -190,8 +190,8 @@ void QDeclarative1LoaderPrivate::initResize()
\o application.qml
\o MyItem.qml
\row
- \o \snippet doc/src/snippets/declarative/loader/connections.qml 0
- \o \snippet doc/src/snippets/declarative/loader/MyItem.qml 0
+ \o \snippet doc/src/snippets/qtquick1/loader/connections.qml 0
+ \o \snippet doc/src/snippets/qtquick1/loader/MyItem.qml 0
\endtable
Alternatively, since \c MyItem.qml is loaded within the scope of the
@@ -217,8 +217,8 @@ void QDeclarative1LoaderPrivate::initResize()
\o application.qml
\o KeyReader.qml
\row
- \o \snippet doc/src/snippets/declarative/loader/focus.qml 0
- \o \snippet doc/src/snippets/declarative/loader/KeyReader.qml 0
+ \o \snippet doc/src/snippets/qtquick1/loader/focus.qml 0
+ \o \snippet doc/src/snippets/qtquick1/loader/KeyReader.qml 0
\endtable
Once \c KeyReader.qml is loaded, it accepts key events and sets
diff --git a/src/qtquick1/graphicsitems/qdeclarativemousearea.cpp b/src/qtquick1/graphicsitems/qdeclarativemousearea.cpp
index 7f43eb1070..94f6b2a798 100644
--- a/src/qtquick1/graphicsitems/qdeclarativemousearea.cpp
+++ b/src/qtquick1/graphicsitems/qdeclarativemousearea.cpp
@@ -226,9 +226,9 @@ QDeclarative1MouseAreaPrivate::~QDeclarative1MouseAreaPrivate()
The following example uses a MouseArea in a \l Rectangle that changes
the \l Rectangle color to red when clicked:
- \snippet doc/src/snippets/declarative/mousearea/mousearea.qml import
+ \snippet doc/src/snippets/qtquick1/mousearea/mousearea.qml import
\codeline
- \snippet doc/src/snippets/declarative/mousearea/mousearea.qml intro
+ \snippet doc/src/snippets/qtquick1/mousearea/mousearea.qml intro
\clearfloat
Many MouseArea signals pass a \l{MouseEvent}{mouse} parameter that contains
@@ -238,7 +238,7 @@ QDeclarative1MouseAreaPrivate::~QDeclarative1MouseAreaPrivate()
Here is an extension of the previous example that produces a different
color when the area is right clicked:
- \snippet doc/src/snippets/declarative/mousearea/mousearea.qml intro-extended
+ \snippet doc/src/snippets/qtquick1/mousearea/mousearea.qml intro-extended
\sa MouseEvent, {declarative/touchinteraction/mousearea}{MouseArea example}
*/
@@ -492,7 +492,7 @@ void QDeclarative1MouseArea::setPreventStealing(bool prevent)
The code below displays "right" when the right mouse buttons is pressed:
- \snippet doc/src/snippets/declarative/mousearea/mousearea.qml mousebuttons
+ \snippet doc/src/snippets/qtquick1/mousearea/mousearea.qml mousebuttons
\sa acceptedButtons
*/
@@ -999,7 +999,7 @@ QDeclarative1Drag *QDeclarative1MouseArea::drag()
The following example displays a \l Rectangle that can be dragged along the X-axis. The opacity
of the rectangle is reduced when it is dragged to the right.
- \snippet doc/src/snippets/declarative/mousearea/mousearea.qml drag
+ \snippet doc/src/snippets/qtquick1/mousearea/mousearea.qml drag
\note Items cannot be dragged if they are anchored for the requested
\c drag.axis. For example, if \c anchors.left or \c anchors.right was set
@@ -1010,7 +1010,7 @@ QDeclarative1Drag *QDeclarative1MouseArea::drag()
If \c drag.filterChildren is set to true, a drag can override descendant MouseAreas. This
enables a parent MouseArea to handle drags, for example, while descendants handle clicks:
- \snippet doc/src/snippets/declarative/mousearea/mouseareadragfilter.qml dragfilter
+ \snippet doc/src/snippets/qtquick1/mousearea/mouseareadragfilter.qml dragfilter
*/
diff --git a/src/qtquick1/graphicsitems/qdeclarativepath.cpp b/src/qtquick1/graphicsitems/qdeclarativepath.cpp
index ecf9e24e2f..5b52af8469 100644
--- a/src/qtquick1/graphicsitems/qdeclarativepath.cpp
+++ b/src/qtquick1/graphicsitems/qdeclarativepath.cpp
@@ -155,7 +155,7 @@ bool QDeclarative1Path::isClosed() const
\i \l PathPercent - a way to spread out items along various segments of the path.
\endlist
- \snippet doc/src/snippets/declarative/pathview/pathattributes.qml 2
+ \snippet doc/src/snippets/qtquick1/pathview/pathattributes.qml 2
*/
QDeclarativeListProperty<QDeclarative1PathElement> QDeclarative1Path::pathElements()
@@ -519,7 +519,7 @@ void QDeclarative1Curve::setY(qreal y)
\row
\o \image declarative-pathattribute.png
\o
- \snippet doc/src/snippets/declarative/pathview/pathattributes.qml 0
+ \snippet doc/src/snippets/qtquick1/pathview/pathattributes.qml 0
(see the PathView documentation for the specification of ContactModel.qml
used for ContactModel above.)
\endtable
diff --git a/src/qtquick1/graphicsitems/qdeclarativepathview.cpp b/src/qtquick1/graphicsitems/qdeclarativepathview.cpp
index 2c0875b4c4..e01cf05f22 100644
--- a/src/qtquick1/graphicsitems/qdeclarativepathview.cpp
+++ b/src/qtquick1/graphicsitems/qdeclarativepathview.cpp
@@ -365,11 +365,11 @@ void QDeclarative1PathViewPrivate::regenerate()
For example, if there is a simple list model defined in a file \c ContactModel.qml like this:
- \snippet doc/src/snippets/declarative/pathview/ContactModel.qml 0
+ \snippet doc/src/snippets/qtquick1/pathview/ContactModel.qml 0
This data can be represented as a PathView, like this:
- \snippet doc/src/snippets/declarative/pathview/pathview.qml 0
+ \snippet doc/src/snippets/qtquick1/pathview/pathview.qml 0
\image pathview.gif
@@ -402,7 +402,7 @@ void QDeclarative1PathViewPrivate::regenerate()
this attached property directly as \c PathView.isCurrentItem, while the child
\c nameText object must refer to this property as \c wrapper.PathView.isCurrentItem.
- \snippet doc/src/snippets/declarative/pathview/pathview.qml 1
+ \snippet doc/src/snippets/qtquick1/pathview/pathview.qml 1
\bold Note that views do not enable \e clip automatically. If the view
is not clipped by another item or the screen, it will be necessary
@@ -464,7 +464,7 @@ QDeclarative1PathView::~QDeclarative1PathView()
This property may be used to adjust the appearance of the current item.
- \snippet doc/src/snippets/declarative/pathview/pathview.qml 1
+ \snippet doc/src/snippets/qtquick1/pathview/pathview.qml 1
*/
/*!
@@ -1002,7 +1002,7 @@ bool QDeclarative1PathView::isFlicking() const
item in the delegate.
Here is an example delegate:
- \snippet doc/src/snippets/declarative/pathview/pathview.qml 1
+ \snippet doc/src/snippets/qtquick1/pathview/pathview.qml 1
*/
QDeclarativeComponent *QDeclarative1PathView::delegate() const
{
@@ -1285,6 +1285,7 @@ bool QDeclarative1PathView::sendMouseEvent(QGraphicsSceneMouseEvent *event)
return d->stealMouse;
} else if (d->lastPosTime.isValid()) {
d->lastPosTime.invalidate();
+ d->fixOffset();
}
if (mouseEvent.type() == QEvent::GraphicsSceneMouseRelease)
d->stealMouse = false;
@@ -1309,6 +1310,22 @@ bool QDeclarative1PathView::sceneEventFilter(QGraphicsItem *i, QEvent *e)
return QDeclarativeItem::sceneEventFilter(i, e);
}
+bool QDeclarative1PathView::sceneEvent(QEvent *event)
+{
+ bool rv = QDeclarativeItem::sceneEvent(event);
+ if (event->type() == QEvent::UngrabMouse) {
+ Q_D(QDeclarative1PathView);
+ if (d->stealMouse) {
+ // if our mouse grab has been removed (probably by another Flickable),
+ // fix our state
+ d->stealMouse = false;
+ setKeepMouseGrab(false);
+ d->lastPosTime.invalidate();
+ }
+ }
+ return rv;
+}
+
bool QDeclarative1PathView::event(QEvent *event)
{
if (event->type() == QEvent::User) {
diff --git a/src/qtquick1/graphicsitems/qdeclarativepathview_p.h b/src/qtquick1/graphicsitems/qdeclarativepathview_p.h
index b4897f9e1d..955951ffd1 100644
--- a/src/qtquick1/graphicsitems/qdeclarativepathview_p.h
+++ b/src/qtquick1/graphicsitems/qdeclarativepathview_p.h
@@ -173,6 +173,7 @@ protected:
void mouseReleaseEvent(QGraphicsSceneMouseEvent *);
bool sendMouseEvent(QGraphicsSceneMouseEvent *event);
bool sceneEventFilter(QGraphicsItem *, QEvent *);
+ bool sceneEvent(QEvent *event);
bool event(QEvent *event);
void componentComplete();
diff --git a/src/qtquick1/graphicsitems/qdeclarativepositioners.cpp b/src/qtquick1/graphicsitems/qdeclarativepositioners.cpp
index 7046945d27..353fbcc418 100644
--- a/src/qtquick1/graphicsitems/qdeclarativepositioners.cpp
+++ b/src/qtquick1/graphicsitems/qdeclarativepositioners.cpp
@@ -349,7 +349,7 @@ void QDeclarative1BasePositioner::finishApplyTransitions()
\image verticalpositioner_example.png
- \snippet doc/src/snippets/declarative/column/vertical-positioner.qml document
+ \snippet doc/src/snippets/qtquick1/column/vertical-positioner.qml document
\section1 Using Transitions
@@ -512,7 +512,7 @@ void QDeclarative1Column::reportConflictingAnchors()
\image horizontalpositioner_example.png
- \snippet doc/src/snippets/declarative/row/row.qml document
+ \snippet doc/src/snippets/qtquick1/row/row.qml document
\section1 Using Transitions
@@ -743,7 +743,7 @@ void QDeclarative1Row::reportConflictingAnchors()
\image gridLayout_example.png
- \snippet doc/src/snippets/declarative/grid/grid.qml document
+ \snippet doc/src/snippets/qtquick1/grid/grid.qml document
\section1 Using Transitions
@@ -1129,7 +1129,7 @@ void QDeclarative1Grid::reportConflictingAnchors()
\image qml-flow-snippet.png
- \snippet doc/src/snippets/declarative/flow.qml flow item
+ \snippet doc/src/snippets/qtquick1/flow.qml flow item
\section1 Using Transitions
diff --git a/src/qtquick1/graphicsitems/qdeclarativerectangle.cpp b/src/qtquick1/graphicsitems/qdeclarativerectangle.cpp
index b67536cc86..088c296a26 100644
--- a/src/qtquick1/graphicsitems/qdeclarativerectangle.cpp
+++ b/src/qtquick1/graphicsitems/qdeclarativerectangle.cpp
@@ -147,7 +147,7 @@ void QDeclarative1GradientStop::updateGradient()
with red, blending to yellow at one third of the height of the rectangle,
and ending with green:
- \snippet doc/src/snippets/declarative/gradient.qml code
+ \snippet doc/src/snippets/qtquick1/gradient.qml code
\clearfloat
\section1 Performance and Limitations
@@ -235,7 +235,7 @@ void QDeclarative1Gradient::doUpdate()
The following example shows the effects of some of the common properties on a
Rectangle item, which in this case is used to create a square:
- \snippet doc/src/snippets/declarative/rectangle/rectangle.qml document
+ \snippet doc/src/snippets/qtquick1/rectangle/rectangle.qml document
\clearfloat
\section1 Performance
@@ -284,7 +284,7 @@ void QDeclarative1Rectangle::doUpdate()
\inlineimage rect-border-width.png
\enddiv
- \snippet doc/src/snippets/declarative/rectangle/rect-border-width.qml 0
+ \snippet doc/src/snippets/qtquick1/rectangle/rect-border-width.qml 0
\clearfloat
Here, the innermost rectangle's border is clipped on the bottom and right edges by its
@@ -308,7 +308,7 @@ QDeclarative1Pen *QDeclarative1Rectangle::border()
\inlineimage declarative-rect_gradient.png
\enddiv
- \snippet doc/src/snippets/declarative/rectangle/rectangle-gradient.qml rectangles
+ \snippet doc/src/snippets/qtquick1/rectangle/rectangle-gradient.qml rectangles
\clearfloat
If both a gradient and a color are specified, the gradient will be used.
@@ -379,7 +379,7 @@ void QDeclarative1Rectangle::setRadius(qreal radius)
The following example shows rectangles with colors specified
using hexadecimal and named color notation:
- \snippet doc/src/snippets/declarative/rectangle/rectangle-colors.qml rectangles
+ \snippet doc/src/snippets/qtquick1/rectangle/rectangle-colors.qml rectangles
\clearfloat
If both a gradient and a color are specified, the gradient will be used.
diff --git a/src/qtquick1/graphicsitems/qdeclarativerepeater.cpp b/src/qtquick1/graphicsitems/qdeclarativerepeater.cpp
index cc080d10d3..ab9beb4d4d 100644
--- a/src/qtquick1/graphicsitems/qdeclarativerepeater.cpp
+++ b/src/qtquick1/graphicsitems/qdeclarativerepeater.cpp
@@ -79,9 +79,9 @@ QDeclarative1RepeaterPrivate::~QDeclarative1RepeaterPrivate()
The following Repeater creates three instances of a \l Rectangle item within
a \l Row:
- \snippet doc/src/snippets/declarative/repeaters/repeater.qml import
+ \snippet doc/src/snippets/qtquick1/repeaters/repeater.qml import
\codeline
- \snippet doc/src/snippets/declarative/repeaters/repeater.qml simple
+ \snippet doc/src/snippets/qtquick1/repeaters/repeater.qml simple
\image repeater-simple.png
@@ -96,7 +96,7 @@ QDeclarative1RepeaterPrivate::~QDeclarative1RepeaterPrivate()
a Repeater to be used inside a layout. For example, the following Repeater's
items are stacked between a red rectangle and a blue rectangle:
- \snippet doc/src/snippets/declarative/repeaters/repeater.qml layout
+ \snippet doc/src/snippets/qtquick1/repeaters/repeater.qml layout
\image repeater.png
@@ -242,7 +242,7 @@ void QDeclarative1Repeater::setModel(const QVariant &model)
\table
\row
- \o \snippet doc/src/snippets/declarative/repeaters/repeater.qml index
+ \o \snippet doc/src/snippets/qtquick1/repeaters/repeater.qml index
\o \image repeater-index.png
\endtable
@@ -253,7 +253,7 @@ void QDeclarative1Repeater::setModel(const QVariant &model)
\table
\row
- \o \snippet doc/src/snippets/declarative/repeaters/repeater.qml modeldata
+ \o \snippet doc/src/snippets/qtquick1/repeaters/repeater.qml modeldata
\o \image repeater-modeldata.png
\endtable
diff --git a/src/qtquick1/graphicsitems/qdeclarativescalegrid.cpp b/src/qtquick1/graphicsitems/qdeclarativescalegrid.cpp
index 83a94ec9de..bcdf92c675 100644
--- a/src/qtquick1/graphicsitems/qdeclarativescalegrid.cpp
+++ b/src/qtquick1/graphicsitems/qdeclarativescalegrid.cpp
@@ -167,6 +167,8 @@ QDeclarative1GridScaledImage::QDeclarative1GridScaledImage(QIODevice *data)
_l = l; _r = r; _t = t; _b = b;
_pix = imgFile;
+ if (_pix.startsWith(QLatin1Char('"')) && _pix.endsWith(QLatin1Char('"')))
+ _pix = _pix.mid(1, _pix.size() - 2); // remove leading/trailing quotes.
}
QDeclarative1BorderImage::TileMode QDeclarative1GridScaledImage::stringToRule(const QString &s)
diff --git a/src/qtquick1/graphicsitems/qdeclarativetext.cpp b/src/qtquick1/graphicsitems/qdeclarativetext.cpp
index 6974f73739..aad4b1e952 100644
--- a/src/qtquick1/graphicsitems/qdeclarativetext.cpp
+++ b/src/qtquick1/graphicsitems/qdeclarativetext.cpp
@@ -749,7 +749,7 @@ QDeclarative1Text::~QDeclarative1Text()
The link must be in rich text or HTML format and the
\a link string provides access to the particular link.
- \snippet doc/src/snippets/declarative/text/onLinkActivated.qml 0
+ \snippet doc/src/snippets/qtquick1/text/onLinkActivated.qml 0
The example code will display the text
"The main website is at \l{http://qt.nokia.com}{Nokia Qt DF}."
diff --git a/src/qtquick1/graphicsitems/qdeclarativevisualitemmodel.cpp b/src/qtquick1/graphicsitems/qdeclarativevisualitemmodel.cpp
index c8627b9d26..5d8a3d4b37 100644
--- a/src/qtquick1/graphicsitems/qdeclarativevisualitemmodel.cpp
+++ b/src/qtquick1/graphicsitems/qdeclarativevisualitemmodel.cpp
@@ -659,7 +659,7 @@ QDeclarative1VisualDataModelData *QDeclarative1VisualDataModelPrivate::data(QObj
The example below illustrates using a VisualDataModel with a ListView.
- \snippet doc/src/snippets/declarative/visualdatamodel.qml 0
+ \snippet doc/src/snippets/qtquick1/visualdatamodel.qml 0
*/
QDeclarative1VisualDataModel::QDeclarative1VisualDataModel()
@@ -852,10 +852,10 @@ void QDeclarative1VisualDataModel::setDelegate(QDeclarativeComponent *delegate)
the new directory's contents.
\c main.cpp:
- \snippet doc/src/snippets/declarative/visualdatamodel_rootindex/main.cpp 0
+ \snippet doc/src/snippets/qtquick1/visualdatamodel_rootindex/main.cpp 0
\c view.qml:
- \snippet doc/src/snippets/declarative/visualdatamodel_rootindex/view.qml 0
+ \snippet doc/src/snippets/qtquick1/visualdatamodel_rootindex/view.qml 0
If the \l model is a QAbstractItemModel subclass, the delegate can also
reference a \c hasModelChildren property (optionally qualified by a
diff --git a/src/qtquick1/util/qdeclarativeanimation.cpp b/src/qtquick1/util/qdeclarativeanimation.cpp
index 89b768b827..8204e33022 100644
--- a/src/qtquick1/util/qdeclarativeanimation.cpp
+++ b/src/qtquick1/util/qdeclarativeanimation.cpp
@@ -642,7 +642,7 @@ QAbstractAnimation *QDeclarative1PauseAnimation::qtAnimation()
as a property value source. It animates the \c color property's value from
its current value to a value of "red", over 1000 milliseconds:
- \snippet doc/src/snippets/declarative/coloranimation.qml 0
+ \snippet doc/src/snippets/qtquick1/coloranimation.qml 0
Like any other animation element, a ColorAnimation can be applied in a
number of ways, including transitions, behaviors and property value
@@ -757,7 +757,7 @@ void QDeclarative1ColorAnimation::setTo(const QColor &t)
When used as part of a Transition, you can also target a specific
StateChangeScript to run using the \c scriptName property.
- \snippet doc/src/snippets/declarative/states/statechangescript.qml state and transition
+ \snippet doc/src/snippets/qtquick1/states/statechangescript.qml state and transition
\sa StateChangeScript
*/
@@ -884,14 +884,14 @@ QAbstractAnimation *QDeclarative1ScriptAction::qtAnimation()
\l {Image::}{smooth} property to \c true, animates the width of the image,
then sets \l {Image::}{smooth} back to \c false:
- \snippet doc/src/snippets/declarative/propertyaction.qml standalone
+ \snippet doc/src/snippets/qtquick1/propertyaction.qml standalone
PropertyAction is also useful for setting the exact point at which a property
change should occur during a \l Transition. For example, if PropertyChanges
was used in a \l State to rotate an item around a particular
\l {Item::}{transformOrigin}, it might be implemented like this:
- \snippet doc/src/snippets/declarative/propertyaction.qml transition
+ \snippet doc/src/snippets/qtquick1/propertyaction.qml transition
However, with this code, the \c transformOrigin is not set until \e after
the animation, as a \l State is taken to define the values at the \e end of
@@ -899,7 +899,7 @@ QAbstractAnimation *QDeclarative1ScriptAction::qtAnimation()
then jump to \c Item.BottomRight. To fix this, insert a PropertyAction
before the RotationAnimation begins:
- \snippet doc/src/snippets/declarative/propertyaction-sequential.qml sequential
+ \snippet doc/src/snippets/qtquick1/propertyaction-sequential.qml sequential
This immediately sets the \c transformOrigin property to the value defined
in the end state of the \l Transition (i.e. the value defined in the
@@ -1144,7 +1144,7 @@ void QDeclarative1PropertyAction::transition(QDeclarative1StateActions &actions,
as a property value source. It animates the \c x value from its current
value to a value of 50, over 1000 milliseconds:
- \snippet doc/src/snippets/declarative/numberanimation.qml 0
+ \snippet doc/src/snippets/qtquick1/numberanimation.qml 0
Like any other animation element, a NumberAnimation can be applied in a
number of ways, including transitions, behaviors and property value
@@ -1339,7 +1339,7 @@ void QDeclarative1Vector3dAnimation::setTo(QVector3D t)
In the following example we use RotationAnimation to animate the rotation
between states via the shortest path:
- \snippet doc/src/snippets/declarative/rotationanimation.qml 0
+ \snippet doc/src/snippets/qtquick1/rotationanimation.qml 0
Notice the RotationAnimation did not need to set a \l target
value. As a convenience, when used in a transition, RotationAnimation will rotate all
@@ -1580,7 +1580,7 @@ QDeclarativeListProperty<QDeclarative1AbstractAnimation> QDeclarative1AnimationG
The following example runs two number animations in a sequence. The \l Rectangle
animates to a \c x position of 50, then to a \c y position of 50.
- \snippet doc/src/snippets/declarative/sequentialanimation.qml 0
+ \snippet doc/src/snippets/qtquick1/sequentialanimation.qml 0
Animations defined within a \l Transition are automatically run in parallel,
so SequentialAnimation can be used to enclose the animations in a \l Transition
@@ -1655,7 +1655,7 @@ void QDeclarative1SequentialAnimation::transition(QDeclarative1StateActions &act
The following animation runs two number animations in parallel. The \l Rectangle
moves to (50,50) by animating its \c x and \c y properties at the same time.
- \snippet doc/src/snippets/declarative/parallelanimation.qml 0
+ \snippet doc/src/snippets/qtquick1/parallelanimation.qml 0
Like any other animation element, a ParallelAnimation can be applied in a
number of ways, including transitions, behaviors and property value
@@ -1772,21 +1772,21 @@ void QDeclarative1PropertyAnimationPrivate::convertVariant(QVariant &variant, in
For example, to animate any objects that have changed their \c x or \c y properties
as a result of a state change, using an \c InOutQuad easing curve:
- \snippet doc/src/snippets/declarative/propertyanimation.qml transition
+ \snippet doc/src/snippets/qtquick1/propertyanimation.qml transition
\o In a \l Behavior
For example, to animate all changes to a rectangle's \c x property:
- \snippet doc/src/snippets/declarative/propertyanimation.qml behavior
+ \snippet doc/src/snippets/qtquick1/propertyanimation.qml behavior
\o As a property value source
For example, to repeatedly animate the rectangle's \c x property:
- \snippet doc/src/snippets/declarative/propertyanimation.qml propertyvaluesource
+ \snippet doc/src/snippets/qtquick1/propertyanimation.qml propertyvaluesource
\o In a signal handler
@@ -1803,7 +1803,7 @@ void QDeclarative1PropertyAnimationPrivate::convertVariant(QVariant &variant, in
For example, to animate \c rect's \c width property over 500ms, from its current width to 30:
- \snippet doc/src/snippets/declarative/propertyanimation.qml standalone
+ \snippet doc/src/snippets/qtquick1/propertyanimation.qml standalone
\endlist
@@ -2460,7 +2460,7 @@ void QDeclarative1PropertyAnimation::transition(QDeclarative1StateActions &actio
the transition, ensures the item animates smoothly as it moves to
its new parent:
- \snippet doc/src/snippets/declarative/parentanimation.qml 0
+ \snippet doc/src/snippets/qtquick1/parentanimation.qml 0
A ParentAnimation can contain any number of animations. These animations will
be run in parallel; to run them sequentially, define them within a
@@ -2818,7 +2818,7 @@ QAbstractAnimation *QDeclarative1ParentAnimation::qtAnimation()
In the following snippet we animate the addition of a right anchor to a \l Rectangle:
- \snippet doc/src/snippets/declarative/anchoranimation.qml 0
+ \snippet doc/src/snippets/qtquick1/anchoranimation.qml 0
For convenience, when an AnchorAnimation is used in a \l Transition, it will
animate any AnchorChanges that have occurred during the state change.
diff --git a/src/qtquick1/util/qdeclarativebehavior.cpp b/src/qtquick1/util/qdeclarativebehavior.cpp
index 02d1b0eed1..0475eea01f 100644
--- a/src/qtquick1/util/qdeclarativebehavior.cpp
+++ b/src/qtquick1/util/qdeclarativebehavior.cpp
@@ -86,7 +86,7 @@ public:
whenever the \l Rectangle's \c width value changes. When the MouseArea
is clicked, the \c width is changed, triggering the behavior's animation:
- \snippet doc/src/snippets/declarative/behavior.qml 0
+ \snippet doc/src/snippets/qtquick1/behavior.qml 0
Note that a property cannot have more than one assigned Behavior. To provide
multiple animations within a Behavior, use ParallelAnimation or
diff --git a/src/qtquick1/util/qdeclarativebind.cpp b/src/qtquick1/util/qdeclarativebind.cpp
index 50514234a3..7afe848448 100644
--- a/src/qtquick1/util/qdeclarativebind.cpp
+++ b/src/qtquick1/util/qdeclarativebind.cpp
@@ -42,6 +42,7 @@
#include "QtQuick1/private/qdeclarativebind_p.h"
#include "QtDeclarative/private/qdeclarativenullablevalue_p_p.h"
+#include "QtDeclarative/private/qdeclarativeguard_p.h"
#include <QtDeclarative/qdeclarativeengine.h>
#include <QtDeclarative/qdeclarativecontext.h>
@@ -65,7 +66,7 @@ public:
bool when : 1;
bool componentComplete : 1;
- QObject *obj;
+ QDeclarativeGuard<QObject> obj;
QString prop;
QDeclarativeNullableValue<QVariant> value;
};
diff --git a/src/qtquick1/util/qdeclarativelistmodel.cpp b/src/qtquick1/util/qdeclarativelistmodel.cpp
index 520d9ac388..d5aa75bec5 100644
--- a/src/qtquick1/util/qdeclarativelistmodel.cpp
+++ b/src/qtquick1/util/qdeclarativelistmodel.cpp
@@ -115,7 +115,7 @@ QDeclarative1ListModelParser::ListInstruction *QDeclarative1ListModelParser::Lis
\inlineimage listmodel.png
\enddiv
- \snippet doc/src/snippets/declarative/listmodel.qml 0
+ \snippet doc/src/snippets/qtquick1/listmodel.qml 0
\clearfloat
Roles (properties) in each element must begin with a lower-case letter and
@@ -125,14 +125,14 @@ QDeclarative1ListModelParser::ListInstruction *QDeclarative1ListModelParser::Lis
Since the example model contains an \c id property, it can be referenced
by views, such as the ListView in this example:
- \snippet doc/src/snippets/declarative/listmodel-simple.qml 0
+ \snippet doc/src/snippets/qtquick1/listmodel-simple.qml 0
\dots 8
- \snippet doc/src/snippets/declarative/listmodel-simple.qml 1
+ \snippet doc/src/snippets/qtquick1/listmodel-simple.qml 1
It is possible for roles to contain list data. In the following example we
create a list of fruit attributes:
- \snippet doc/src/snippets/declarative/listmodel-nested.qml model
+ \snippet doc/src/snippets/qtquick1/listmodel-nested.qml model
The delegate displays all the fruit attributes:
@@ -140,7 +140,7 @@ QDeclarative1ListModelParser::ListInstruction *QDeclarative1ListModelParser::Lis
\inlineimage listmodel-nested.png
\enddiv
- \snippet doc/src/snippets/declarative/listmodel-nested.qml delegate
+ \snippet doc/src/snippets/qtquick1/listmodel-nested.qml delegate
\clearfloat
\section1 Modifying List Models
@@ -148,7 +148,7 @@ QDeclarative1ListModelParser::ListInstruction *QDeclarative1ListModelParser::Lis
The content of a ListModel may be created and modified using the clear(),
append(), set(), insert() and setProperty() methods. For example:
- \snippet doc/src/snippets/declarative/listmodel-modify.qml delegate
+ \snippet doc/src/snippets/qtquick1/listmodel-modify.qml delegate
Note that when creating content dynamically the set of available properties
cannot be changed once set. Whatever properties are first added to the model
@@ -905,12 +905,12 @@ bool QDeclarative1ListModelParser::definesEmptyList(const QString &s)
The following model defines a series of list elements, each of which
contain "name" and "cost" roles and their associated values.
- \snippet doc/src/snippets/declarative/qml-data-models/listelements.qml model
+ \snippet doc/src/snippets/qtquick1/qml-data-models/listelements.qml model
The delegate obtains the name and cost for each element by simply referring
to \c name and \c cost:
- \snippet doc/src/snippets/declarative/qml-data-models/listelements.qml view
+ \snippet doc/src/snippets/qtquick1/qml-data-models/listelements.qml view
\sa ListModel
*/
diff --git a/src/qtquick1/util/qdeclarativepropertychanges.cpp b/src/qtquick1/util/qdeclarativepropertychanges.cpp
index 5882fc5810..776701e58f 100644
--- a/src/qtquick1/util/qdeclarativepropertychanges.cpp
+++ b/src/qtquick1/util/qdeclarativepropertychanges.cpp
@@ -80,9 +80,9 @@ QT_BEGIN_NAMESPACE
properties are to be modified, and define the new property values or
bindings. For example:
- \snippet doc/src/snippets/declarative/propertychanges.qml import
+ \snippet doc/src/snippets/qtquick1/propertychanges.qml import
\codeline
- \snippet doc/src/snippets/declarative/propertychanges.qml 0
+ \snippet doc/src/snippets/qtquick1/propertychanges.qml 0
When the mouse is pressed, the \l Rectangle changes to the \e resized
state. In this state, the PropertyChanges object sets the rectangle's
@@ -116,7 +116,7 @@ QT_BEGIN_NAMESPACE
state, its \c width property is reset, giving the text its natural width
and displaying the whole string on a single line.
- \snippet doc/src/snippets/declarative/propertychanges.qml reset
+ \snippet doc/src/snippets/qtquick1/propertychanges.qml reset
\section2 Immediate property changes in transitions
diff --git a/src/qtquick1/util/qdeclarativesmoothedanimation.cpp b/src/qtquick1/util/qdeclarativesmoothedanimation.cpp
index 0bad1a416b..7e96fe6a1c 100644
--- a/src/qtquick1/util/qdeclarativesmoothedanimation.cpp
+++ b/src/qtquick1/util/qdeclarativesmoothedanimation.cpp
@@ -269,7 +269,7 @@ void QSmoothedAnimation_1::init()
bound to those of the red rectangle. Whenever these values change, the
green rectangle smoothly animates to its new position:
- \snippet doc/src/snippets/declarative/smoothedanimation.qml 0
+ \snippet doc/src/snippets/qtquick1/smoothedanimation.qml 0
A SmoothedAnimation can be configured by setting the \l velocity at which the
animation should occur, or the \l duration that the animation should take.
diff --git a/src/qtquick1/util/qdeclarativespringanimation.cpp b/src/qtquick1/util/qdeclarativespringanimation.cpp
index d6dd68c4c6..155f7bb08f 100644
--- a/src/qtquick1/util/qdeclarativespringanimation.cpp
+++ b/src/qtquick1/util/qdeclarativespringanimation.cpp
@@ -254,7 +254,7 @@ void QDeclarative1SpringAnimationPrivate::updateMode()
on the \c x and \c y values indicates that whenever these values are
changed, a SpringAnimation should be applied.
- \snippet doc/src/snippets/declarative/springanimation.qml 0
+ \snippet doc/src/snippets/qtquick1/springanimation.qml 0
Like any other animation element, a SpringAnimation can be applied in a
number of ways, including transitions, behaviors and property value
diff --git a/src/qtquick1/util/qdeclarativestate.cpp b/src/qtquick1/util/qdeclarativestate.cpp
index 6d96f8d1f7..1be3395c5a 100644
--- a/src/qtquick1/util/qdeclarativestate.cpp
+++ b/src/qtquick1/util/qdeclarativestate.cpp
@@ -151,7 +151,7 @@ QDeclarative1StateOperation::QDeclarative1StateOperation(QObjectPrivate &dd, QOb
between the default state and the "clicked" state, thus toggling the color of the
rectangle between black and red.
- \snippet doc/src/snippets/declarative/state.qml 0
+ \snippet doc/src/snippets/qtquick1/state.qml 0
Notice the default state is referred to using an empty string ("").
@@ -217,7 +217,7 @@ bool QDeclarative1State::isWhenKnown() const
be applied. For example, the following \l Rectangle changes in and out of the "hidden"
state when the \l MouseArea is pressed:
- \snippet doc/src/snippets/declarative/state-when.qml 0
+ \snippet doc/src/snippets/qtquick1/state-when.qml 0
If multiple states in a group have \c when clauses that evaluate to \c true
at the same time, the first matching state will be applied. For example, in
diff --git a/src/qtquick1/util/qdeclarativestategroup.cpp b/src/qtquick1/util/qdeclarativestategroup.cpp
index 60ca08ca17..539fbbadab 100644
--- a/src/qtquick1/util/qdeclarativestategroup.cpp
+++ b/src/qtquick1/util/qdeclarativestategroup.cpp
@@ -385,7 +385,11 @@ QDeclarative1Transition *QDeclarative1StateGroupPrivate::findTransition(const QS
QStringList toState;
fromState = t->fromState().split(QLatin1Char(','));
+ for (int jj = 0; jj < fromState.count(); ++jj)
+ fromState[jj] = fromState.at(jj).trimmed();
toState = t->toState().split(QLatin1Char(','));
+ for (int jj = 0; jj < toState.count(); ++jj)
+ toState[jj] = toState.at(jj).trimmed();
if (ii == 1)
qSwap(fromState, toState);
int tScore = 0;
diff --git a/src/qtquick1/util/qdeclarativestateoperations.cpp b/src/qtquick1/util/qdeclarativestateoperations.cpp
index 37ebe3e248..7d57083c59 100644
--- a/src/qtquick1/util/qdeclarativestateoperations.cpp
+++ b/src/qtquick1/util/qdeclarativestateoperations.cpp
@@ -189,7 +189,7 @@ void QDeclarative1ParentChangePrivate::doChange(QDeclarativeItem *targetParent,
When the \c blueRect is clicked, it changes to the "reparented" state: its parent is changed to \c redRect and it is
positioned at (10, 10) within the red rectangle, as specified in the ParentChange.
- \snippet doc/src/snippets/declarative/parentchange.qml 0
+ \snippet doc/src/snippets/qtquick1/parentchange.qml 0
\image parentchange.png
@@ -703,7 +703,7 @@ QString QDeclarative1StateChangeScript::typeName() const
using AnchorChanges, and the top and bottom anchor margins using
PropertyChanges:
- \snippet doc/src/snippets/declarative/anchorchanges.qml 0
+ \snippet doc/src/snippets/qtquick1/anchorchanges.qml 0
\image anchorchanges.png
diff --git a/src/qtquick1/util/qdeclarativesystempalette.cpp b/src/qtquick1/util/qdeclarativesystempalette.cpp
index 7f0dde3a93..a026c5f805 100644
--- a/src/qtquick1/util/qdeclarativesystempalette.cpp
+++ b/src/qtquick1/util/qdeclarativesystempalette.cpp
@@ -79,7 +79,7 @@ public:
group and uses this to color the window and text items
appropriately:
- \snippet doc/src/snippets/declarative/systempalette.qml 0
+ \snippet doc/src/snippets/qtquick1/systempalette.qml 0
\sa QPalette
*/
diff --git a/src/qtquick1/util/qdeclarativetransition.cpp b/src/qtquick1/util/qdeclarativetransition.cpp
index 8498f6c4e2..235db8b483 100644
--- a/src/qtquick1/util/qdeclarativetransition.cpp
+++ b/src/qtquick1/util/qdeclarativetransition.cpp
@@ -68,7 +68,7 @@ QT_BEGIN_NAMESPACE
changes between the default and the "moved" state, any changes
to the \c x and \c y properties should be animated, using an \c Easing.InOutQuad.
- \snippet doc/src/snippets/declarative/transition.qml 0
+ \snippet doc/src/snippets/qtquick1/transition.qml 0
Notice the example does not require \l{PropertyAnimation::}{to} and
\l{PropertyAnimation::}{from} values for the NumberAnimation. As a convenience,
@@ -85,7 +85,7 @@ QT_BEGIN_NAMESPACE
To define multiple transitions, specify \l Item::transitions as a list:
- \snippet doc/src/snippets/declarative/transitions-list.qml list of transitions
+ \snippet doc/src/snippets/qtquick1/transitions-list.qml list of transitions
If multiple Transitions are specified, only a single (best-matching) Transition will be applied for any particular
state change. In the example above, when changing to \c state1, the first transition will be used, rather
@@ -238,15 +238,17 @@ void QDeclarative1Transition::prepare(QDeclarative1StateOperation::ActionList &a
properties, so the animation is always applied when changing between
the two states (i.e. when the mouse is pressed and released).
- \snippet doc/src/snippets/declarative/transition-from-to.qml 0
+ \snippet doc/src/snippets/qtquick1/transition-from-to.qml 0
If the transition was changed to this:
- \snippet doc/src/snippets/declarative/transition-from-to-modified.qml modified transition
+ \snippet doc/src/snippets/qtquick1/transition-from-to-modified.qml modified transition
The animation would only be applied when changing from the default state to
the "brighter" state (i.e. when the mouse is pressed, but not on release).
+ Multiple \c to and \from values can be set by using a comma-separated string.
+
\sa reversible
*/
QString QDeclarative1Transition::fromState() const
@@ -283,7 +285,7 @@ void QDeclarative1Transition::setFromState(const QString &f)
transition applies a sequential animation when the mouse is pressed,
and reverses the sequence of the animation when the mouse is released:
- \snippet doc/src/snippets/declarative/transition-reversible.qml 0
+ \snippet doc/src/snippets/qtquick1/transition-reversible.qml 0
If the transition did not set the \c to and \c reversible values, then
on the mouse release, the transition would play the PropertyAnimation
@@ -332,7 +334,7 @@ void QDeclarative1Transition::setToState(const QString &t)
The top-level animations are run in parallel. To run them sequentially,
define them within a SequentialAnimation:
- \snippet doc/src/snippets/declarative/transition-reversible.qml sequential animations
+ \snippet doc/src/snippets/qtquick1/transition-reversible.qml sequential animations
*/
QDeclarativeListProperty<QDeclarative1AbstractAnimation> QDeclarative1Transition::animations()
{
diff --git a/src/qtquick1/util/qdeclarativexmllistmodel.cpp b/src/qtquick1/util/qdeclarativexmllistmodel.cpp
index 8beb5d2a94..2450534174 100644
--- a/src/qtquick1/util/qdeclarativexmllistmodel.cpp
+++ b/src/qtquick1/util/qdeclarativexmllistmodel.cpp
@@ -115,13 +115,13 @@ typedef QPair<int, int> QDeclarative1XmlListRange;
For example, if there is an XML document like this:
- \quotefile doc/src/snippets/declarative/xmlrole.xml
+ \quotefile doc/src/snippets/qtquick1/xmlrole.xml
Here are some valid XPath expressions for XmlRole queries on this document:
- \snippet doc/src/snippets/declarative/xmlrole.qml 0
+ \snippet doc/src/snippets/qtquick1/xmlrole.qml 0
\dots 4
- \snippet doc/src/snippets/declarative/xmlrole.qml 1
+ \snippet doc/src/snippets/qtquick1/xmlrole.qml 1
See the \l{http://www.w3.org/TR/xpath20/}{W3C XPath 2.0 specification} for more information.
*/