summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMika Salmela <mika.salmela@digia.com>2013-12-18 11:50:03 +0200
committerMika Salmela <mika.salmela@digia.com>2013-12-18 11:51:20 +0200
commit07aba602fc82ac31684988f8e8e22521d2b3c982 (patch)
tree7ae1da139e8661bf157f996fe71844031d2995f4
parentcf0cf6ca67aec8ae480bb705443ea17f5ab9f9e2 (diff)
parentea0442bc81ae034d22c5742b6075dee993fdd54d (diff)
Merge branch 'develop' into mergebranch
Conflicts: examples/qmlbars/qml/qmlbars/main.qml examples/qmlscatter/qml/qmlscatter/main.qml examples/qmlsurface/qml/qmlsurface/main.qml src/datavisualization/data/qitemmodelbardatamapping.cpp src/datavisualization/data/qitemmodelscatterdatamapping.cpp src/datavisualization/data/qitemmodelsurfacedatamapping.cpp src/datavisualization/engine/drawer.cpp Change-Id: I731ebdb2cc5cee8f2cb32becee96d1fc1b3e5de1
-rw-r--r--.qmake.conf2
-rw-r--r--README29
-rw-r--r--dist/changes-1.0.0 (renamed from dist/changes-0.1.0)0
-rw-r--r--examples/audiolevels/audiolevels.cpp25
-rw-r--r--examples/audiolevels/audiolevelsiodevice.cpp4
-rw-r--r--examples/audiolevels/doc/src/audiolevels.qdoc18
-rw-r--r--examples/audiolevels/main.cpp3
-rw-r--r--examples/bars/doc/src/bars.qdoc54
-rw-r--r--examples/bars/graphmodifier.cpp166
-rw-r--r--examples/bars/graphmodifier.h24
-rw-r--r--examples/bars/main.cpp75
-rw-r--r--examples/custominput/custominput.pro17
-rw-r--r--examples/custominput/custominput.qrc5
-rw-r--r--examples/custominput/custominputhandler.cpp54
-rw-r--r--examples/custominput/custominputhandler.h36
-rw-r--r--examples/custominput/data/data.txt1060
-rw-r--r--examples/custominput/doc/images/custominput-example.pngbin0 -> 108178 bytes
-rw-r--r--examples/custominput/doc/src/custominput.qdoc70
-rw-r--r--examples/custominput/main.cpp84
-rw-r--r--examples/custominput/scatterdatamodifier.cpp172
-rw-r--r--examples/custominput/scatterdatamodifier.h60
-rw-r--r--examples/customproxy/doc/src/customproxy.qdoc6
-rw-r--r--examples/customproxy/main.cpp1
-rw-r--r--examples/customproxy/rainfallgraph.cpp25
-rw-r--r--examples/customproxy/variantbardataproxy.cpp2
-rw-r--r--examples/examples.pri5
-rw-r--r--examples/examples.pro4
-rw-r--r--examples/itemmodel/doc/src/itemmodel.qdoc59
-rw-r--r--examples/itemmodel/main.cpp50
-rw-r--r--examples/qmlbars/doc/images/qmlbars-example.pngbin139958 -> 99784 bytes
-rw-r--r--examples/qmlbars/doc/src/qmlbars.qdoc40
-rw-r--r--examples/qmlbars/main.cpp11
-rw-r--r--examples/qmlbars/qml/qmlbars/axes.qml2
-rw-r--r--examples/qmlbars/qml/qmlbars/data.qml17
-rw-r--r--examples/qmlbars/qml/qmlbars/main.qml338
-rw-r--r--examples/qmlbars/qtquick2applicationviewer/qtquick2applicationviewer.pri10
-rw-r--r--examples/qmlcustominput/doc/images/qmlcustominput-example.pngbin0 -> 116035 bytes
-rw-r--r--examples/qmlcustominput/doc/src/qmlcustominput.qdoc79
-rw-r--r--examples/qmlcustominput/main.cpp55
-rw-r--r--examples/qmlcustominput/qml/qmlcustominput/data.qml1088
-rw-r--r--examples/qmlcustominput/qml/qmlcustominput/main.qml206
-rw-r--r--examples/qmlcustominput/qml/qmlcustominput/newbutton.qml52
-rw-r--r--examples/qmlcustominput/qmlcustominput.desktop11
-rw-r--r--examples/qmlcustominput/qmlcustominput.pro26
-rw-r--r--examples/qmlcustominput/qmlcustominput.qrc7
-rw-r--r--examples/qmlcustominput/qmlcustominput64.pngbin0 -> 3400 bytes
-rw-r--r--examples/qmlcustominput/qmlcustominput80.pngbin0 -> 4945 bytes
-rw-r--r--examples/qmlcustominput/qtquick2applicationviewer/qtquick2applicationviewer.cpp81
-rw-r--r--examples/qmlcustominput/qtquick2applicationviewer/qtquick2applicationviewer.h33
-rw-r--r--examples/qmlcustominput/qtquick2applicationviewer/qtquick2applicationviewer.pri180
-rw-r--r--examples/qmlscatter/doc/images/qmlscatter-example.pngbin84088 -> 60798 bytes
-rw-r--r--examples/qmlscatter/doc/images/qmlscatter-newproject.pngbin72869 -> 37045 bytes
-rw-r--r--examples/qmlscatter/doc/src/qmlscatter.qdoc55
-rw-r--r--examples/qmlscatter/main.cpp11
-rw-r--r--examples/qmlscatter/qml/qmlscatter/data.qml41
-rw-r--r--examples/qmlscatter/qml/qmlscatter/main.qml223
-rw-r--r--examples/qmlscatter/qml/qmlscatter/newbutton.qml23
-rw-r--r--examples/qmlscatter/qtquick2applicationviewer/qtquick2applicationviewer.pri10
-rw-r--r--examples/qmlsurface/doc/images/qmlsurface-example.pngbin254724 -> 168723 bytes
-rw-r--r--examples/qmlsurface/doc/src/qmlsurface.qdoc70
-rw-r--r--examples/qmlsurface/main.cpp10
-rw-r--r--examples/qmlsurface/qml/qmlsurface/data.qml34
-rw-r--r--examples/qmlsurface/qml/qmlsurface/main.qml257
-rw-r--r--examples/qmlsurface/qml/qmlsurface/newbutton.qml23
-rw-r--r--examples/qmlsurface/qtquick2applicationviewer/qtquick2applicationviewer.pri10
-rw-r--r--examples/scatter/doc/src/scatter.qdoc23
-rw-r--r--examples/scatter/main.cpp22
-rw-r--r--examples/scatter/scatterdatamodifier.cpp80
-rw-r--r--examples/scatter/scatterdatamodifier.h6
-rw-r--r--examples/surface/doc/src/surface.qdoc57
-rw-r--r--examples/surface/main.cpp2
-rw-r--r--examples/surface/surfacegraph.cpp168
-rw-r--r--examples/surface/surfacegraph.h31
-rw-r--r--src/datavisualization/axis/q3dabstractaxis.cpp139
-rw-r--r--src/datavisualization/axis/q3dabstractaxis.h33
-rw-r--r--src/datavisualization/axis/q3dabstractaxis_p.h10
-rw-r--r--src/datavisualization/axis/q3dcategoryaxis.cpp24
-rw-r--r--src/datavisualization/axis/q3dcategoryaxis.h9
-rw-r--r--src/datavisualization/axis/q3dvalueaxis.cpp10
-rw-r--r--src/datavisualization/axis/q3dvalueaxis_p.h6
-rw-r--r--src/datavisualization/common.pri3
-rw-r--r--src/datavisualization/data/abstractitemmodelhandler.cpp111
-rw-r--r--src/datavisualization/data/abstractitemmodelhandler_p.h12
-rw-r--r--src/datavisualization/data/baritemmodelhandler.cpp30
-rw-r--r--src/datavisualization/data/baritemmodelhandler_p.h2
-rw-r--r--src/datavisualization/data/barrenderitem.cpp4
-rw-r--r--src/datavisualization/data/barrenderitem_p.h14
-rw-r--r--src/datavisualization/data/data.pri28
-rw-r--r--src/datavisualization/data/qabstract3dseries.cpp667
-rw-r--r--src/datavisualization/data/qabstract3dseries.h141
-rw-r--r--src/datavisualization/data/qabstract3dseries_p.h143
-rw-r--r--src/datavisualization/data/qabstractdatamapping.cpp71
-rw-r--r--src/datavisualization/data/qabstractdataproxy.cpp45
-rw-r--r--src/datavisualization/data/qabstractdataproxy.h14
-rw-r--r--src/datavisualization/data/qabstractdataproxy_p.h11
-rw-r--r--src/datavisualization/data/qbar3dseries.cpp276
-rw-r--r--src/datavisualization/data/qbar3dseries.h65
-rw-r--r--src/datavisualization/data/qbar3dseries_p.h (renamed from src/datavisualization/data/qitemmodelscatterdatamapping_p.h)30
-rw-r--r--src/datavisualization/data/qbardataitem.cpp8
-rw-r--r--src/datavisualization/data/qbardataitem.h10
-rw-r--r--src/datavisualization/data/qbardataproxy.cpp67
-rw-r--r--src/datavisualization/data/qbardataproxy.h35
-rw-r--r--src/datavisualization/data/qbardataproxy_p.h2
-rw-r--r--src/datavisualization/data/qheightmapsurfacedataproxy.cpp140
-rw-r--r--src/datavisualization/data/qheightmapsurfacedataproxy.h21
-rw-r--r--src/datavisualization/data/qitemmodelbardatamapping.cpp407
-rw-r--r--src/datavisualization/data/qitemmodelbardatamapping.h90
-rw-r--r--src/datavisualization/data/qitemmodelbardataproxy.cpp374
-rw-r--r--src/datavisualization/data/qitemmodelbardataproxy.h69
-rw-r--r--src/datavisualization/data/qitemmodelbardataproxy_p.h17
-rw-r--r--src/datavisualization/data/qitemmodelscatterdatamapping.cpp200
-rw-r--r--src/datavisualization/data/qitemmodelscatterdatamapping.h62
-rw-r--r--src/datavisualization/data/qitemmodelscatterdataproxy.cpp146
-rw-r--r--src/datavisualization/data/qitemmodelscatterdataproxy.h36
-rw-r--r--src/datavisualization/data/qitemmodelscatterdataproxy_p.h8
-rw-r--r--src/datavisualization/data/qitemmodelsurfacedatamapping.cpp411
-rw-r--r--src/datavisualization/data/qitemmodelsurfacedatamapping.h90
-rw-r--r--src/datavisualization/data/qitemmodelsurfacedatamapping_p.h63
-rw-r--r--src/datavisualization/data/qitemmodelsurfacedataproxy.cpp378
-rw-r--r--src/datavisualization/data/qitemmodelsurfacedataproxy.h69
-rw-r--r--src/datavisualization/data/qitemmodelsurfacedataproxy_p.h17
-rw-r--r--src/datavisualization/data/qscatter3dseries.cpp302
-rw-r--r--src/datavisualization/data/qscatter3dseries.h70
-rw-r--r--src/datavisualization/data/qscatter3dseries_p.h (renamed from src/datavisualization/data/qitemmodelbardatamapping_p.h)36
-rw-r--r--src/datavisualization/data/qscatterdataitem.cpp12
-rw-r--r--src/datavisualization/data/qscatterdataitem.h4
-rw-r--r--src/datavisualization/data/qscatterdataproxy.cpp120
-rw-r--r--src/datavisualization/data/qscatterdataproxy.h16
-rw-r--r--src/datavisualization/data/qscatterdataproxy_p.h4
-rw-r--r--src/datavisualization/data/qsurface3dseries.cpp381
-rw-r--r--src/datavisualization/data/qsurface3dseries.h86
-rw-r--r--src/datavisualization/data/qsurface3dseries_p.h64
-rw-r--r--src/datavisualization/data/qsurfacedataproxy.cpp288
-rw-r--r--src/datavisualization/data/qsurfacedataproxy.h29
-rw-r--r--src/datavisualization/data/qsurfacedataproxy_p.h11
-rw-r--r--src/datavisualization/data/scatteritemmodelhandler.cpp9
-rw-r--r--src/datavisualization/data/scatteritemmodelhandler_p.h2
-rw-r--r--src/datavisualization/data/scatterrenderitem_p.h7
-rw-r--r--src/datavisualization/data/surfaceitemmodelhandler.cpp30
-rw-r--r--src/datavisualization/data/surfaceitemmodelhandler_p.h2
-rw-r--r--src/datavisualization/datavisualization.pro5
-rw-r--r--src/datavisualization/doc/qtdatavisualization.qdocconf10
-rw-r--r--src/datavisualization/doc/snippets/doc_src_q3dbars_construction.cpp7
-rw-r--r--src/datavisualization/doc/snippets/doc_src_q3dscatter_construction.cpp5
-rw-r--r--src/datavisualization/doc/snippets/doc_src_q3dsurface_construction.cpp5
-rw-r--r--src/datavisualization/doc/snippets/doc_src_q3dtheme.cpp113
-rw-r--r--src/datavisualization/doc/snippets/doc_src_qmldatavisualization.cpp90
-rw-r--r--src/datavisualization/doc/snippets/doc_src_qtdatavisualization.cpp52
-rw-r--r--src/datavisualization/doc/src/qtdatavisualization-index.qdoc12
-rw-r--r--src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc33
-rw-r--r--src/datavisualization/doc/src/qtdatavisualization-qml-bars3d.qdoc60
-rw-r--r--src/datavisualization/doc/src/qtdatavisualization-qml-scatter3d.qdoc41
-rw-r--r--src/datavisualization/doc/src/qtdatavisualization-qml-surface3d.qdoc32
-rw-r--r--src/datavisualization/doc/src/qtdatavisualization.qdoc70
-rw-r--r--src/datavisualization/engine/abstract3dcontroller.cpp539
-rw-r--r--src/datavisualization/engine/abstract3dcontroller_p.h212
-rw-r--r--src/datavisualization/engine/abstract3drenderer.cpp296
-rw-r--r--src/datavisualization/engine/abstract3drenderer_p.h101
-rw-r--r--src/datavisualization/engine/axisrendercache.cpp12
-rw-r--r--src/datavisualization/engine/axisrendercache_p.h12
-rw-r--r--src/datavisualization/engine/bars3dcontroller.cpp446
-rw-r--r--src/datavisualization/engine/bars3dcontroller_p.h38
-rw-r--r--src/datavisualization/engine/bars3drenderer.cpp1842
-rw-r--r--src/datavisualization/engine/bars3drenderer_p.h51
-rw-r--r--src/datavisualization/engine/drawer.cpp99
-rw-r--r--src/datavisualization/engine/drawer_p.h23
-rw-r--r--src/datavisualization/engine/engine.pri4
-rw-r--r--src/datavisualization/engine/engine.qrc28
-rw-r--r--src/datavisualization/engine/meshes/backgroudNegatives.obj33
-rw-r--r--src/datavisualization/engine/meshes/backgroudSmooth.obj36
-rw-r--r--src/datavisualization/engine/meshes/background.obj (renamed from src/datavisualization/engine/meshes/backgroudFlat.obj)0
-rw-r--r--src/datavisualization/engine/meshes/backgroundNegatives.obj22
-rw-r--r--src/datavisualization/engine/meshes/minimalFlat.obj27
-rw-r--r--src/datavisualization/engine/meshes/minimalSmooth.obj27
-rw-r--r--src/datavisualization/engine/meshes/scatterdot.obj28
-rw-r--r--src/datavisualization/engine/meshes/scatterdotFlat.obj28
-rw-r--r--src/datavisualization/engine/q3dbars.cpp396
-rw-r--r--src/datavisualization/engine/q3dbars.h83
-rw-r--r--src/datavisualization/engine/q3dbars_p.h13
-rw-r--r--src/datavisualization/engine/q3dcamera.cpp550
-rw-r--r--src/datavisualization/engine/q3dcamera.h113
-rw-r--r--src/datavisualization/engine/q3dcamera_p.h16
-rw-r--r--src/datavisualization/engine/q3dlight.cpp33
-rw-r--r--src/datavisualization/engine/q3dlight.h2
-rw-r--r--src/datavisualization/engine/q3dobject.h5
-rw-r--r--src/datavisualization/engine/q3dscatter.cpp349
-rw-r--r--src/datavisualization/engine/q3dscatter.h72
-rw-r--r--src/datavisualization/engine/q3dscatter_p.h13
-rw-r--r--src/datavisualization/engine/q3dscene.cpp389
-rw-r--r--src/datavisualization/engine/q3dscene.h36
-rw-r--r--src/datavisualization/engine/q3dscene_p.h35
-rw-r--r--src/datavisualization/engine/q3dsurface.cpp329
-rw-r--r--src/datavisualization/engine/q3dsurface.h70
-rw-r--r--src/datavisualization/engine/q3dsurface_p.h9
-rw-r--r--src/datavisualization/engine/q3dwindow.cpp149
-rw-r--r--src/datavisualization/engine/q3dwindow.h16
-rw-r--r--src/datavisualization/engine/q3dwindow_p.h20
-rw-r--r--src/datavisualization/engine/scatter3dcontroller.cpp297
-rw-r--r--src/datavisualization/engine/scatter3dcontroller_p.h35
-rw-r--r--src/datavisualization/engine/scatter3drenderer.cpp1032
-rw-r--r--src/datavisualization/engine/scatter3drenderer_p.h47
-rw-r--r--src/datavisualization/engine/selectionpointer.cpp53
-rw-r--r--src/datavisualization/engine/selectionpointer_p.h17
-rw-r--r--src/datavisualization/engine/seriesrendercache.cpp174
-rw-r--r--src/datavisualization/engine/seriesrendercache_p.h83
-rw-r--r--src/datavisualization/engine/shaders/ambient.frag32
-rw-r--r--src/datavisualization/engine/shaders/colorOnY.frag8
-rw-r--r--src/datavisualization/engine/shaders/colorOnY_ES2.frag8
-rw-r--r--src/datavisualization/engine/shaders/default.vert2
-rw-r--r--src/datavisualization/engine/shaders/default_ES2.vert26
-rw-r--r--src/datavisualization/engine/shaders/plainColor.frag (renamed from src/datavisualization/engine/shaders/selection.frag)0
-rw-r--r--src/datavisualization/engine/shaders/plainColor.vert (renamed from src/datavisualization/engine/shaders/selection.vert)0
-rw-r--r--src/datavisualization/engine/shaders/point_ES2.vert (renamed from src/datavisualization/engine/shaders/surfaceGrid.vert)4
-rw-r--r--src/datavisualization/engine/shaders/shadowNoTexColorOnY.frag8
-rw-r--r--src/datavisualization/engine/shaders/surface.frag4
-rw-r--r--src/datavisualization/engine/shaders/surfaceFlat.frag2
-rw-r--r--src/datavisualization/engine/shaders/surfaceGrid.frag6
-rw-r--r--src/datavisualization/engine/shaders/surfaceShadowFlat.frag70
-rw-r--r--src/datavisualization/engine/shaders/surfaceShadowFlat.vert (renamed from src/datavisualization/engine/shaders/surface.vert)14
-rw-r--r--src/datavisualization/engine/shaders/surfaceShadowNoTex.frag68
-rw-r--r--src/datavisualization/engine/shaders/surface_ES2.frag4
-rw-r--r--src/datavisualization/engine/shaders/texture.frag35
-rw-r--r--src/datavisualization/engine/shaders/texture.vert26
-rw-r--r--src/datavisualization/engine/shaders/texture_ES2.frag37
-rw-r--r--src/datavisualization/engine/surface3dcontroller.cpp452
-rw-r--r--src/datavisualization/engine/surface3dcontroller_p.h60
-rw-r--r--src/datavisualization/engine/surface3drenderer.cpp936
-rw-r--r--src/datavisualization/engine/surface3drenderer_p.h56
-rw-r--r--src/datavisualization/engine/theme.cpp250
-rw-r--r--src/datavisualization/engine/theme_p.h82
-rw-r--r--src/datavisualization/global/datavisualizationglobal_p.h21
-rw-r--r--src/datavisualization/global/qdatavisualizationenums.h93
-rw-r--r--src/datavisualization/global/qdatavisualizationglobal.h4
-rw-r--r--src/datavisualization/global/qtdatavisualizationenums.qdoc152
-rw-r--r--src/datavisualization/input/q3dinputhandler.cpp22
-rw-r--r--src/datavisualization/input/qabstract3dinputhandler.cpp58
-rw-r--r--src/datavisualization/input/qabstract3dinputhandler.h21
-rw-r--r--src/datavisualization/input/qabstract3dinputhandler_p.h2
-rw-r--r--src/datavisualization/input/qtouch3dinputhandler.cpp26
-rw-r--r--src/datavisualization/input/qtouch3dinputhandler_p.h2
-rw-r--r--src/datavisualization/theme/builtin3dthemes.cpp230
-rw-r--r--src/datavisualization/theme/builtin3dthemes_p.h (renamed from src/datavisualizationqml2/declarativebarsrenderer_p.h)66
-rw-r--r--src/datavisualization/theme/q3dtheme.cpp1064
-rw-r--r--src/datavisualization/theme/q3dtheme.h188
-rw-r--r--src/datavisualization/theme/q3dtheme_p.h136
-rw-r--r--src/datavisualization/theme/theme.pri8
-rw-r--r--src/datavisualization/theme/thememanager.cpp552
-rw-r--r--src/datavisualization/theme/thememanager_p.h81
-rw-r--r--src/datavisualization/utils/camerahelper.cpp50
-rw-r--r--src/datavisualization/utils/camerahelper_p.h3
-rw-r--r--src/datavisualization/utils/objecthelper.cpp3
-rw-r--r--src/datavisualization/utils/shaderhelper.cpp21
-rw-r--r--src/datavisualization/utils/shaderhelper_p.h4
-rw-r--r--src/datavisualization/utils/surfaceobject.cpp481
-rw-r--r--src/datavisualization/utils/surfaceobject_p.h15
-rw-r--r--src/datavisualization/utils/texturehelper.cpp51
-rw-r--r--src/datavisualization/utils/texturehelper_p.h8
-rw-r--r--src/datavisualization/utils/utils.cpp49
-rw-r--r--src/datavisualization/utils/utils_p.h9
-rw-r--r--src/datavisualizationqml2/abstractdeclarative.cpp154
-rw-r--r--src/datavisualizationqml2/abstractdeclarative_p.h55
-rw-r--r--src/datavisualizationqml2/colorgradient.cpp2
-rw-r--r--src/datavisualizationqml2/colorgradient_p.h18
-rw-r--r--src/datavisualizationqml2/datavisualizationqml2.pro19
-rw-r--r--src/datavisualizationqml2/datavisualizationqml2_plugin.cpp28
-rw-r--r--src/datavisualizationqml2/datavisualizationqml2_plugin.h34
-rw-r--r--src/datavisualizationqml2/declarativebars.cpp162
-rw-r--r--src/datavisualizationqml2/declarativebars_p.h62
-rw-r--r--src/datavisualizationqml2/declarativebarsrenderer.cpp87
-rw-r--r--src/datavisualizationqml2/declarativecolor.cpp (renamed from src/datavisualization/data/qabstractdatamapping.h)42
-rw-r--r--src/datavisualizationqml2/declarativecolor_p.h (renamed from src/datavisualization/data/qabstractdatamapping_p.h)23
-rw-r--r--src/datavisualizationqml2/declarativescatter.cpp130
-rw-r--r--src/datavisualizationqml2/declarativescatter_p.h44
-rw-r--r--src/datavisualizationqml2/declarativescatterrenderer.cpp88
-rw-r--r--src/datavisualizationqml2/declarativescatterrenderer_p.h65
-rw-r--r--src/datavisualizationqml2/declarativeseries.cpp346
-rw-r--r--src/datavisualizationqml2/declarativeseries_p.h177
-rw-r--r--src/datavisualizationqml2/declarativesurface.cpp141
-rw-r--r--src/datavisualizationqml2/declarativesurface_p.h48
-rw-r--r--src/datavisualizationqml2/declarativesurfacerenderer.cpp87
-rw-r--r--src/datavisualizationqml2/declarativesurfacerenderer_p.h65
-rw-r--r--src/datavisualizationqml2/declarativetheme.cpp362
-rw-r--r--src/datavisualizationqml2/declarativetheme_p.h118
-rw-r--r--tests/barstest/chart.cpp599
-rw-r--r--tests/barstest/chart.h46
-rw-r--r--tests/barstest/main.cpp92
-rw-r--r--tests/kinectsurface/surfacedata.cpp16
-rw-r--r--tests/kinectsurface/surfacedata.h2
-rw-r--r--tests/minimalbars/minimalbars.pro6
-rw-r--r--tests/minimalscatter/minimalscatter.pro6
-rw-r--r--tests/minimalsurface/minimalsurface.pro6
-rw-r--r--tests/multigraphs/australia.pngbin0 -> 414991 bytes
-rw-r--r--tests/multigraphs/data.cpp330
-rw-r--r--tests/multigraphs/data.h98
-rw-r--r--tests/multigraphs/main.cpp156
-rw-r--r--tests/multigraphs/multigraphs.pro14
-rw-r--r--tests/multigraphs/multigraphs.qrc5
-rw-r--r--tests/qmlcamera/main.cpp11
-rw-r--r--tests/qmlcamera/qml/qmlcamera/Axes.qml2
-rw-r--r--tests/qmlcamera/qml/qmlcamera/Data.qml15
-rw-r--r--tests/qmlcamera/qml/qmlcamera/main.qml61
-rw-r--r--tests/qmldynamicdata/main.cpp55
-rw-r--r--tests/qmldynamicdata/qml/qmldynamicdata/main.qml222
-rw-r--r--tests/qmldynamicdata/qml/qmldynamicdata/newbutton.qml43
-rw-r--r--tests/qmldynamicdata/qmldynamicdata.pro26
-rw-r--r--tests/qmldynamicdata/qmldynamicdata.qrc6
-rw-r--r--tests/qmldynamicdata/qtquick2applicationviewer/qtquick2applicationviewer.cpp81
-rw-r--r--tests/qmldynamicdata/qtquick2applicationviewer/qtquick2applicationviewer.h33
-rw-r--r--tests/qmldynamicdata/qtquick2applicationviewer/qtquick2applicationviewer.pri180
-rw-r--r--tests/scattertest/main.cpp54
-rw-r--r--tests/scattertest/scatterchart.cpp332
-rw-r--r--tests/scattertest/scatterchart.h11
-rw-r--r--tests/spectrum/spectrumapp/main.cpp30
-rw-r--r--tests/spectrum/spectrumapp/spectrumapp.pro1
-rw-r--r--tests/surfacetest/graphmodifier.cpp401
-rw-r--r--tests/surfacetest/graphmodifier.h37
-rw-r--r--tests/surfacetest/main.cpp163
-rw-r--r--tests/tests.pri2
-rw-r--r--tests/tests.pro10
-rwxr-xr-xtools/generate_package_linux.sh4
-rw-r--r--tools/generate_package_win.cmd5
321 files changed, 21893 insertions, 9703 deletions
diff --git a/.qmake.conf b/.qmake.conf
index 213e6914..d8bef836 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -1,2 +1,2 @@
-MODULE_VERSION=0.1.0
+MODULE_VERSION=1.0.0
load(qt_build_config)
diff --git a/README b/README
index 4573323a..998c2f58 100644
--- a/README
+++ b/README
@@ -1,6 +1,6 @@
--------------------------------------------------
-Qt Data Visualization 0.1.0 (Techonology preview)
--------------------------------------------------
+-----------------------------------
+Qt Data Visualization 1.0.0 (alpha)
+-----------------------------------
Qt Data Visualization module provides multiple graph types to visualize data in 3D space
both with C++ and Qt Quick 2.
@@ -8,9 +8,12 @@ both with C++ and Qt Quick 2.
System Requirements
===================
-- Qt 5.1 or newer
+- Qt 5.2 or newer
- OpenGL 2.1 or newer (recommended) or OpenGL ES2 (reduced feature set)
+Platform specific recommendations:
+- Mac: OSX 10.8 recommended
+
Building
========
Configure the project with qmake:
@@ -19,7 +22,7 @@ Configure the project with qmake:
After running qmake, build the project with make:
(Linux) make
(Windows with MinGw) mingw32-make
- (Visual Studio) nmake
+ (Windows with Visual Studio) nmake
(OSX) make
The above generates the default makefiles for your configuration, which is typically
@@ -70,18 +73,16 @@ Please refer to the generated documentation for more information:
Known Issues
============
-The technology preview version is still missing some features entirely, while some
-others may be only partially implemented. Here are some known issues:
-
-- Scatter graphs can only show zero centered axis ranges properly.
-- Value axis range of a bar graph with negative values need to be zero
- centered to display properly.
-- Selection API is missing for surface graphs.
-- Shadows do not work for surface graphs.
-- Mac: Graphs drawn half the size on Retina displays.
- Using multiple graphs in one application crashes on application shutdown
unless the last graph to have active context is deleted last.
- Android doesn't support both widgets and OpenGL simultaneously, so only
the Qt Quick 2 API is usable in practice in Android.
- Shadows are not supported with OpenGL ES2 (including Angle builds in Windows).
- Anti-aliasing doesn't work with OpenGL ES2 (including Angle builds in Windows).
+- Surfaces with non-straight rows and columns do not always render properly.
+- Wrong item can end up selected if you do mouse selection and data removes/inserts
+ simultaneously due to the asynchronous nature of mouse selection handling.
+- Q3DLight class (and Light3D QML item) are currently not usable for anything.
+- Q3DScene::secondarySubviewOnTop property has currently no effect.
+- The color style Q3DTheme::ColorStyleObjectGradient doesn't work for surface graphs.
+- Scatter "point" meshes do not support gradients, they always use the base color.
diff --git a/dist/changes-0.1.0 b/dist/changes-1.0.0
index 854f74e4..854f74e4 100644
--- a/dist/changes-0.1.0
+++ b/dist/changes-1.0.0
diff --git a/examples/audiolevels/audiolevels.cpp b/examples/audiolevels/audiolevels.cpp
index 0922e664..3677c1f1 100644
--- a/examples/audiolevels/audiolevels.cpp
+++ b/examples/audiolevels/audiolevels.cpp
@@ -23,6 +23,8 @@
#include <QtDataVisualization/q3dvalueaxis.h>
#include <QtDataVisualization/q3dscene.h>
#include <QtDataVisualization/q3dcamera.h>
+#include <QtDataVisualization/qbar3dseries.h>
+#include <QtDataVisualization/q3dtheme.h>
#include <QAudioDeviceInfo>
#include <QAudioInput>
@@ -36,18 +38,23 @@ AudioLevels::AudioLevels(Q3DBars *graph, QObject *parent)
m_audioInput(0)
{
// Set up the graph
- m_graph->setBarThickness(0.5);
+ m_graph->setBarThickness(0.5f);
m_graph->setBarSpacing(QSizeF(0.0, 1.0));
- m_graph->setGridVisible(true);
- m_graph->setBackgroundVisible(false);
- m_graph->valueAxis()->setRange(-100.0, 100.0);
+ m_graph->valueAxis()->setRange(-100.0f, 100.0f);
m_graph->valueAxis()->setSegmentCount(20);
m_graph->valueAxis()->setLabelFormat(QStringLiteral("%d%%"));
m_graph->setShadowQuality(QDataVis::ShadowQualityNone);
- m_graph->setSelectionMode(QDataVis::SelectionModeNone);
- m_graph->scene()->activeCamera()->setCameraPosition(-25.0, 10.0, 190.0);
- m_graph->setTheme(QDataVis::ThemeIsabelle);
- m_graph->setBarType(QDataVis::MeshStyleBars);
+ m_graph->setSelectionMode(QDataVis::SelectionNone);
+ m_graph->scene()->activeCamera()->setCameraPosition(-25.0f, 10.0f, 190.0f);
+ m_graph->setTheme(new Q3DTheme(Q3DTheme::ThemeIsabelle));
+ m_graph->theme()->setGridEnabled(true);
+ m_graph->theme()->setBackgroundEnabled(false);
+ QFont font = m_graph->theme()->font();
+ font.setPointSize(10);
+ m_graph->theme()->setFont(font);
+ QBar3DSeries *series = new QBar3DSeries;
+ series->setMesh(QAbstract3DSeries::MeshBar);
+ m_graph->addSeries(series);
//! [0]
QAudioFormat formatAudio;
@@ -67,7 +74,7 @@ AudioLevels::AudioLevels(Q3DBars *graph, QObject *parent)
m_audioInput->setBufferSize(1024);
#endif
- m_device = new AudioLevelsIODevice(m_graph->activeDataProxy(), this);
+ m_device = new AudioLevelsIODevice(m_graph->seriesList().at(0)->dataProxy(), this);
m_device->open(QIODevice::WriteOnly);
m_audioInput->start(m_device);
diff --git a/examples/audiolevels/audiolevelsiodevice.cpp b/examples/audiolevels/audiolevelsiodevice.cpp
index 9fedd804..970677c6 100644
--- a/examples/audiolevels/audiolevelsiodevice.cpp
+++ b/examples/audiolevels/audiolevelsiodevice.cpp
@@ -75,11 +75,11 @@ qint64 AudioLevelsIODevice::writeData(const char *data, qint64 maxSize)
for (int i = newDataSize - 1; i >= newDataStartIndex; i--) {
// Add 0.01 to the value to avoid gaps in the graph (i.e. zero height bars).
// Also, scale to 0...100
- qreal value = qreal(quint8(data[resolution * i]) - 128) / 1.28 + 0.01;
+ float value = float(quint8(data[resolution * i]) - 128) / 1.28f + 0.01f;
(*m_array->at(middleRow))[index].setValue(value);
// Insert a fractional value into front half of the rows.
for (int j = 1; j <= middleRow; j++) {
- qreal fractionalValue = value / qreal(j + 1);
+ float fractionalValue = value / float(j + 1);
(*m_array->at(middleRow - j))[index].setValue(fractionalValue);
}
index++;
diff --git a/examples/audiolevels/doc/src/audiolevels.qdoc b/examples/audiolevels/doc/src/audiolevels.qdoc
index 1aef9174..d52b2e25 100644
--- a/examples/audiolevels/doc/src/audiolevels.qdoc
+++ b/examples/audiolevels/doc/src/audiolevels.qdoc
@@ -30,14 +30,14 @@
\image audiolevels-example.png
- The interesting stuff happens in AudioLevels and AudioLevelsIODevice classes, so we
+ The interesting stuff happens in \c AudioLevels and \c AudioLevelsIODevice classes, so we
concentrate on those and skip explaining the basic Q3DBars functionality - for that see
\l{Bars Example}.
- AudioLevelsIODevice subclasses QIODevice and is given as input device for QAudioInput
+ \c AudioLevelsIODevice subclasses QIODevice and is given as input device for QAudioInput
class, so it receives microphone data.
- In the header file for QAudioInput class we declare necessary members:
+ In the header file for \c AudioLevels class we declare necessary members:
\snippet ../examples/audiolevels/audiolevels.h 0
@@ -45,7 +45,7 @@
\snippet ../examples/audiolevels/audiolevels.cpp 0
- In the header file for AudioLevelsIODevice class we store pointers to the data proxy and
+ In the header file for \c AudioLevelsIODevice class we store pointers to the data proxy and
also the data array we give to the proxy, because we reuse the same array to keep memory
reallocations to the minimum:
@@ -61,11 +61,11 @@
byte from audio input is visualized. This is necessary to make the data readable, as it would
otherwise make the graph scroll too fast.
- In the AudioLevelsIODevice class constructor we initialize the data array:
+ In the \c AudioLevelsIODevice class constructor we initialize the data array:
\snippet ../examples/audiolevels/audiolevelsiodevice.cpp 0
- The AudioLevelsIODevice::writeData function is called whenever there is new audio data
+ The \c AudioLevelsIODevice::writeData function is called whenever there is new audio data
available to be visualized. There we move the old data along the rows and insert new
data in the beginning of the rows:
@@ -75,11 +75,11 @@
the existing data array, as this allows us to avoid any extra memory allocations in our
application code. This also means the data array dimensions do not change, which further
improves efficiency in the bar graph renderer.
- Secondly, since the rows are QVectors of QBarDataItems, which do not allocate any data that needs
- deletion, we can utilize memmove and memcpy functions to quickly move and copy data around.
+ Secondly, since each row is a QVector of bar data items, which do not allocate any data that needs
+ deletion, we can utilize \c memmove and \c memcpy functions to quickly move and copy data around.
\note In the future versions of Qt Data Visualization, QBarDataItem might get extended so that
it does allocate some memory to store other optional bar properties besides the value.
- In use cases where those optional properties are used, using memmove and memcpy would lead to
+ In use cases where those optional properties are used, using \c memmove and \c memcpy would lead to
memory leaks, so use them with care.
*/
diff --git a/examples/audiolevels/main.cpp b/examples/audiolevels/main.cpp
index 524c53b1..36922aa6 100644
--- a/examples/audiolevels/main.cpp
+++ b/examples/audiolevels/main.cpp
@@ -28,7 +28,8 @@ int main(int argc, char *argv[])
QGuiApplication app(argc, argv);
Q3DBars window;
- window.resize(900, 1000);
+ window.setFlags(window.flags() ^ Qt::FramelessWindowHint);
+ window.resize(800, 500);
window.setTitle("Qt Data Visualization - Microphone audio levels visualizer");
window.show();
diff --git a/examples/bars/doc/src/bars.qdoc b/examples/bars/doc/src/bars.qdoc
index e24b4d0f..79cfb270 100644
--- a/examples/bars/doc/src/bars.qdoc
+++ b/examples/bars/doc/src/bars.qdoc
@@ -27,8 +27,8 @@
\list
\li Create an application with Q3DBars and some widgets
- \li Use QBarDataProxy to set data to the graph
- \li Adjust some graph properties using widget controls
+ \li Use QBar3DSeries and QBarDataProxy to set data to the graph
+ \li Adjust some graph and series properties using widget controls
\endlist
It also demonstrates how having negative bar values affects the graph.
@@ -57,7 +57,7 @@
\l {Using widgets to control the graph}
Next, let's create another class to handle the data addition and other interaction with the
- graph. Let's call it GraphModifier (See \l {Setting up the graph} and
+ graph. Let's call it \c GraphModifier (See \l {Setting up the graph} and
\l {Adding data to the graph} for details):
\snippet ../examples/bars/main.cpp 2
@@ -68,7 +68,7 @@
\section1 Setting up the graph
- Let's set up the graph in the constructor of the GraphModifier class we instantiated in the
+ Let's set up the graph in the constructor of the \c GraphModifier class we instantiated in the
application main:
\snippet ../examples/bars/graphmodifier.cpp 0
@@ -84,56 +84,65 @@
\snippet ../examples/bars/graphmodifier.cpp 2
- We're also setting up the axes and adding them to the graph. Notice that we're not setting them
- active yet:
+ We're also setting up the axes and setting them to the graph as active axes:
\snippet ../examples/bars/graphmodifier.cpp 3
- And add the proxy. Note that we're not setting it active yet, but just adding it:
+ Next we create two series for the graph, giving each one a data proxy. Here we also initialize
+ some of the visual properties of the series. Note that the second series is initially not visible:
+
+ \snippet ../examples/bars/graphmodifier.cpp 8
+
+ The series need to be added to the graph to show them:
\snippet ../examples/bars/graphmodifier.cpp 4
+ Finally, we set the camera angle by calling the same method the camera angle change button
+ in the UI uses to cycle through various camera angles:
+
+ \snippet ../examples/bars/graphmodifier.cpp 6
+
+ There you can see that the camera is controlled via the scene object of the graph:
+
+ \snippet ../examples/bars/graphmodifier.cpp 10
+
+ For more information about using scene and cameras, see Q3DScene and Q3DCamera.
+
That concludes setting up the graph.
\section1 Adding data to the graph
At the end of the constructor there's a call:
- \code resetTemperatureData(); \endcode
+ \snippet ../examples/bars/graphmodifier.cpp 9
- The method is used to add data to the proxy:
+ This method is used to add data to the proxies of the two series:
\snippet ../examples/bars/graphmodifier.cpp 5
- Now the data is in the proxy, but not in the graph. We have not set the proxy active yet.
-
- In application main, we called \c {modifier->start()} after constructing all the necessary
- objects. This is what is done in it:
-
- \snippet ../examples/bars/graphmodifier.cpp 6
-
- Finally we set the proxy and the axes active. Now our graph has the data and is ready to be
- used.
+ Now the series have data to show.
\section1 Using widgets to control the graph
There isn't much interaction yet, so let's continue by adding some widgets back in the
- application main. Let's just focus on two:
+ application main. Let's just focus on two as an example:
\snippet ../examples/bars/main.cpp 4
- We can use these to rotate the graph using slider widgets instead of just using the mouse or
+ We can use these slider widgets to rotate the graph instead of just using the mouse or
touch.
Let's add them to the vertical layout we created earlier:
\snippet ../examples/bars/main.cpp 5
- Then we'll connect them to methods in GraphModifier:
+ Then we'll connect them to methods in \c GraphModifier:
\snippet ../examples/bars/main.cpp 6
- Here are the methods in GraphModifier the signals were connected to:
+ Here are the methods in \c GraphModifier the signals were connected to. The camera
+ is controlled via the scene object. This time we specify the actual camera position
+ along the orbit around the center point, instead of specifying a preset camera angle:
\snippet ../examples/bars/graphmodifier.cpp 7
@@ -148,6 +157,7 @@
\li Background visibility
\li Grid visibility
\li Bar shading smoothness
+ \li Visibility of the second bar series
\li Bar style
\li Selection mode
\li Theme
diff --git a/examples/bars/graphmodifier.cpp b/examples/bars/graphmodifier.cpp
index e2ace423..13e4d3e7 100644
--- a/examples/bars/graphmodifier.cpp
+++ b/examples/bars/graphmodifier.cpp
@@ -22,7 +22,10 @@
#include <QtDataVisualization/qbardataproxy.h>
#include <QtDataVisualization/q3dscene.h>
#include <QtDataVisualization/q3dcamera.h>
+#include <QtDataVisualization/qbar3dseries.h>
+#include <QtDataVisualization/q3dtheme.h>
#include <QTime>
+#include <QComboBox>
QT_DATAVISUALIZATION_USE_NAMESPACE
@@ -31,27 +34,29 @@ const QString celsiusString = QString(QChar(0xB0)) + "C";
//! [0]
GraphModifier::GraphModifier(Q3DBars *bargraph)
: m_graph(bargraph),
- m_xRotation(0.0),
- m_yRotation(0.0),
+ m_xRotation(0.0f),
+ m_yRotation(0.0f),
m_fontSize(30),
m_segments(4),
m_subSegments(3),
- m_minval(-20.0),
- m_maxval(20.0),
+ m_minval(-20.0f),
+ m_maxval(20.0f),
//! [1]
m_temperatureAxis(new Q3DValueAxis),
m_yearAxis(new Q3DCategoryAxis),
m_monthAxis(new Q3DCategoryAxis),
- m_temperatureData(new QBarDataProxy),
+ m_primaryData(new QBarDataProxy),
+ m_secondaryData(new QBarDataProxy),
//! [1]
- m_style(QDataVis::MeshStyleBevelBars),
+ m_primaryStyle(QAbstract3DSeries::MeshBevelBar),
+ m_secondaryStyle(QAbstract3DSeries::MeshSphere),
m_smooth(false)
{
//! [2]
- m_graph->setBackgroundVisible(false);
m_graph->setShadowQuality(QDataVis::ShadowQualitySoftMedium);
- m_graph->setFont(QFont("Times New Roman", m_fontSize));
- m_graph->setLabelStyle(QDataVis::LabelStyleFromTheme);
+ m_graph->theme()->setBackgroundEnabled(false);
+ m_graph->theme()->setFont(QFont("Times New Roman", m_fontSize));
+ m_graph->theme()->setLabelBackgroundEnabled(true);
//! [2]
m_months << "January" << "February" << "March" << "April" << "May" << "June" << "July" << "August" << "September" << "October" << "November" << "December";
@@ -67,19 +72,36 @@ GraphModifier::GraphModifier(Q3DBars *bargraph)
m_yearAxis->setTitle("Year");
m_monthAxis->setTitle("Month");
- m_graph->addAxis(m_temperatureAxis);
- m_graph->addAxis(m_yearAxis);
- m_graph->addAxis(m_monthAxis);
+ m_graph->setValueAxis(m_temperatureAxis);
+ m_graph->setRowAxis(m_yearAxis);
+ m_graph->setColumnAxis(m_monthAxis);
//! [3]
- m_temperatureData->setItemLabelFormat(QStringLiteral("@valueTitle for @colLabel @rowLabel: @valueLabel"));
+ //! [8]
+ QBar3DSeries *series = new QBar3DSeries(m_primaryData);
+ series->setItemLabelFormat(QStringLiteral("Oulu - @colLabel @rowLabel: @valueLabel"));
+ series->setMesh(QAbstract3DSeries::MeshBevelBar);
+ series->setMeshSmooth(false);
+
+ QBar3DSeries *series2 = new QBar3DSeries(m_secondaryData);
+ series2->setItemLabelFormat(QStringLiteral("Helsinki - @colLabel @rowLabel: @valueLabel"));
+ series2->setMesh(QAbstract3DSeries::MeshSphere);
+ series2->setMeshSmooth(false);
+ series2->setVisible(false);
+ //! [8]
//! [4]
- m_graph->addDataProxy(m_temperatureData);
+ m_graph->addSeries(series);
+ m_graph->addSeries(series2);
//! [4]
+ //! [6]
changePresetCamera();
+ //! [6]
+
+ //! [9]
resetTemperatureData();
+ //! [9]
}
//! [0]
@@ -88,101 +110,114 @@ GraphModifier::~GraphModifier()
delete m_graph;
}
-void GraphModifier::start()
-{
- //! [6]
- m_graph->setActiveDataProxy(m_temperatureData);
-
- m_graph->setValueAxis(m_temperatureAxis);
- m_graph->setRowAxis(m_yearAxis);
- m_graph->setColumnAxis(m_monthAxis);
- //! [6]
-}
-
void GraphModifier::resetTemperatureData()
{
//! [5]
// Set up data
- static const qreal temp[7][12] = {
- {-6.7, -11.7, -9.7, 3.3, 9.2, 14.0, 16.3, 17.8, 10.2, 2.1, -2.6, -0.3}, // 2006
- {-6.8, -13.3, 0.2, 1.5, 7.9, 13.4, 16.1, 15.5, 8.2, 5.4, -2.6, -0.8}, // 2007
- {-4.2, -4.0, -4.6, 1.9, 7.3, 12.5, 15.0, 12.8, 7.6, 5.1, -0.9, -1.3}, // 2008
- {-7.8, -8.8, -4.2, 0.7, 9.3, 13.2, 15.8, 15.5, 11.2, 0.6, 0.7, -8.4}, // 2009
- {-14.4, -12.1, -7.0, 2.3, 11.0, 12.6, 18.8, 13.8, 9.4, 3.9, -5.6, -13.0}, // 2010
- {-9.0, -15.2, -3.8, 2.6, 8.3, 15.9, 18.6, 14.9, 11.1, 5.3, 1.8, -0.2}, // 2011
- {-8.7, -11.3, -2.3, 0.4, 7.5, 12.2, 16.4, 14.1, 9.2, 3.1, 0.3, -12.1} // 2012
+ static const float tempOulu[7][12] = {
+ {-6.7f, -11.7f, -9.7f, 3.3f, 9.2f, 14.0f, 16.3f, 17.8f, 10.2f, 2.1f, -2.6f, -0.3f}, // 2006
+ {-6.8f, -13.3f, 0.2f, 1.5f, 7.9f, 13.4f, 16.1f, 15.5f, 8.2f, 5.4f, -2.6f, -0.8f}, // 2007
+ {-4.2f, -4.0f, -4.6f, 1.9f, 7.3f, 12.5f, 15.0f, 12.8f, 7.6f, 5.1f, -0.9f, -1.3f}, // 2008
+ {-7.8f, -8.8f, -4.2f, 0.7f, 9.3f, 13.2f, 15.8f, 15.5f, 11.2f, 0.6f, 0.7f, -8.4f}, // 2009
+ {-14.4f, -12.1f, -7.0f, 2.3f, 11.0f, 12.6f, 18.8f, 13.8f, 9.4f, 3.9f, -5.6f, -13.0f}, // 2010
+ {-9.0f, -15.2f, -3.8f, 2.6f, 8.3f, 15.9f, 18.6f, 14.9f, 11.1f, 5.3f, 1.8f, -0.2f}, // 2011
+ {-8.7f, -11.3f, -2.3f, 0.4f, 7.5f, 12.2f, 16.4f, 14.1f, 9.2f, 3.1f, 0.3f, -12.1f} // 2012
+ };
+
+ static const float tempHelsinki[7][12] = {
+ {-3.7f, -7.8f, -5.4f, 3.4f, 10.7f, 15.4f, 18.6f, 18.7f, 14.3f, 8.5f, 2.9f, 4.1f}, // 2006
+ {-1.2f, -7.5f, 3.1f, 5.5f, 10.3f, 15.9f, 17.4f, 17.9f, 11.2f, 7.3f, 1.1f, 0.5f}, // 2007
+ {-0.6f, 1.2f, 0.2f, 6.3f, 10.2f, 13.8f, 18.1f, 15.1f, 10.1f, 9.4f, 2.5f, 0.4f}, // 2008
+ {-2.9f, -3.5f, -0.9f, 4.7f, 10.9f, 14.0f, 17.4f, 16.8f, 13.2f, 4.1f, 2.6f, -2.3f}, // 2009
+ {-10.2f, -8.0f, -1.9f, 6.6f, 11.3f, 14.5f, 21.0f, 18.8f, 12.6f, 6.1f, -0.5f, -7.3f}, // 2010
+ {-4.4f, -9.1f, -2.0f, 5.5f, 9.9f, 15.6f, 20.8f, 17.8f, 13.4f, 8.9f, 3.6f, 1.5f}, // 2011
+ {-3.5f, -3.2f, -0.7f, 4.0f, 11.1f, 13.4f, 17.3f, 15.8f, 13.1f, 6.4f, 4.1f, -5.1f} // 2012
};
- // Create data array
+ // Create data arrays
QBarDataArray *dataSet = new QBarDataArray;
+ QBarDataArray *dataSet2 = new QBarDataArray;
QBarDataRow *dataRow;
+ QBarDataRow *dataRow2;
dataSet->reserve(m_years.size());
for (int year = 0; year < m_years.size(); year++) {
// Create a data row
dataRow = new QBarDataRow(m_months.size());
+ dataRow2 = new QBarDataRow(m_months.size());
for (int month = 0; month < m_months.size(); month++) {
// Add data to the row
- (*dataRow)[month].setValue(temp[year][month]);
+ (*dataRow)[month].setValue(tempOulu[year][month]);
+ (*dataRow2)[month].setValue(tempHelsinki[year][month]);
}
// Add the row to the set
dataSet->append(dataRow);
+ dataSet2->append(dataRow2);
}
// Add data to the graph (the graph assumes ownership of it)
- m_temperatureData->resetArray(dataSet, m_years, m_months);
+ m_primaryData->resetArray(dataSet, m_years, m_months);
+ m_secondaryData->resetArray(dataSet2, m_years, m_months);
//! [5]
}
void GraphModifier::changeStyle(int style)
{
- m_style = QDataVis::MeshStyle(style);
- m_graph->setBarType(m_style, m_smooth);
+ QComboBox *comboBox = qobject_cast<QComboBox *>(sender());
+ if (comboBox) {
+ m_primaryStyle = QAbstract3DSeries::Mesh(comboBox->itemData(style).toInt());
+ if (m_graph->seriesList().size())
+ m_graph->seriesList().at(0)->setMesh(m_primaryStyle);
+ }
}
void GraphModifier::changePresetCamera()
{
- static int preset = QDataVis::CameraPresetFront;
+ //! [10]
+ static int preset = Q3DCamera::CameraPresetFront;
- m_graph->scene()->activeCamera()->setCameraPreset((QDataVis::CameraPreset)preset);
+ m_graph->scene()->activeCamera()->setCameraPreset((Q3DCamera::CameraPreset)preset);
- if (++preset > QDataVis::CameraPresetDirectlyBelow)
- preset = QDataVis::CameraPresetFrontLow;
+ if (++preset > Q3DCamera::CameraPresetDirectlyBelow)
+ preset = Q3DCamera::CameraPresetFrontLow;
+ //! [10]
}
void GraphModifier::changeTheme(int theme)
{
- m_graph->setTheme((QDataVis::Theme)theme);
+ m_graph->setTheme(new Q3DTheme(Q3DTheme::Theme(theme)));
+ emit backgroundEnabledChanged(m_graph->theme()->isBackgroundEnabled());
+ emit gridEnabledChanged(m_graph->theme()->isGridEnabled());
+ emit fontChanged(m_graph->theme()->font());
+ emit fontSizeChanged(m_graph->theme()->font().pointSize());
}
-void GraphModifier::changeLabelStyle()
+void GraphModifier::changeLabelBackground()
{
- static int style = QDataVis::LabelStyleFromTheme;
-
- m_graph->setLabelStyle((QDataVis::LabelStyle)style);
-
- if (++style > QDataVis::LabelStyleTransparent)
- style = QDataVis::LabelStyleOpaque;
+ m_graph->theme()->setLabelBackgroundEnabled(!m_graph->theme()->isLabelBackgroundEnabled());
}
void GraphModifier::changeSelectionMode(int selectionMode)
{
- m_graph->setSelectionMode((QDataVis::SelectionMode)selectionMode);
+ QComboBox *comboBox = qobject_cast<QComboBox *>(sender());
+ if (comboBox) {
+ int flags = comboBox->itemData(selectionMode).toInt();
+ m_graph->setSelectionMode(QDataVis::SelectionFlags(flags));
+ }
}
void GraphModifier::changeFont(const QFont &font)
{
QFont newFont = font;
- newFont.setPointSize(m_fontSize);
- m_graph->setFont(newFont);
+ m_graph->theme()->setFont(newFont);
}
void GraphModifier::changeFontSize(int fontsize)
{
m_fontSize = fontsize;
- QFont font = m_graph->font();
+ QFont font = m_graph->theme()->font();
font.setPointSize(m_fontSize);
- m_graph->setFont(font);
+ m_graph->theme()->setFont(font);
}
void GraphModifier::shadowQualityUpdatedByVisual(QDataVis::ShadowQuality sq)
@@ -215,16 +250,31 @@ void GraphModifier::rotateY(int rotation)
void GraphModifier::setBackgroundEnabled(int enabled)
{
- m_graph->setBackgroundVisible((bool)enabled);
+ m_graph->theme()->setBackgroundEnabled(bool(enabled));
}
void GraphModifier::setGridEnabled(int enabled)
{
- m_graph->setGridVisible((bool)enabled);
+ m_graph->theme()->setGridEnabled(bool(enabled));
}
void GraphModifier::setSmoothBars(int smooth)
{
m_smooth = bool(smooth);
- m_graph->setBarType(m_style, m_smooth);
+ if (m_graph->seriesList().size()) {
+ m_graph->seriesList().at(0)->setMeshSmooth(m_smooth);
+ m_graph->seriesList().at(1)->setMeshSmooth(m_smooth);
+ }
+}
+
+void GraphModifier::setSeriesVisibility(int enabled)
+{
+ m_graph->seriesList().at(1)->setVisible(bool(enabled));
+ if (enabled) {
+ m_graph->setBarThickness(2.0f);
+ m_graph->setBarSpacing(QSizeF(1.0, 3.0));
+ } else {
+ m_graph->setBarThickness(1.0f);
+ m_graph->setBarSpacing(QSizeF(1.0, 1.0));
+ }
}
diff --git a/examples/bars/graphmodifier.h b/examples/bars/graphmodifier.h
index 2e18ffd2..f7c0acaf 100644
--- a/examples/bars/graphmodifier.h
+++ b/examples/bars/graphmodifier.h
@@ -20,6 +20,8 @@
#define GRAPHMODIFIER_H
#include <QtDataVisualization/q3dbars.h>
+#include <QtDataVisualization/qbardataproxy.h>
+#include <QtDataVisualization/qabstract3dseries.h>
#include <QFont>
#include <QDebug>
@@ -37,7 +39,7 @@ public:
void resetTemperatureData();
void changePresetCamera();
- void changeLabelStyle();
+ void changeLabelBackground();
void changeFont(const QFont &font);
void changeFontSize(int fontsize);
void rotateX(int rotation);
@@ -45,7 +47,7 @@ public:
void setBackgroundEnabled(int enabled);
void setGridEnabled(int enabled);
void setSmoothBars(int smooth);
- void start();
+ void setSeriesVisibility(int enabled);
public slots:
void changeStyle(int style);
@@ -56,23 +58,29 @@ public slots:
signals:
void shadowQualityChanged(int quality);
+ void backgroundEnabledChanged(bool enabled);
+ void gridEnabledChanged(bool enabled);
+ void fontChanged(QFont font);
+ void fontSizeChanged(int size);
private:
Q3DBars *m_graph;
- qreal m_xRotation;
- qreal m_yRotation;
+ float m_xRotation;
+ float m_yRotation;
int m_fontSize;
int m_segments;
int m_subSegments;
- qreal m_minval;
- qreal m_maxval;
+ float m_minval;
+ float m_maxval;
QStringList m_months;
QStringList m_years;
Q3DValueAxis *m_temperatureAxis;
Q3DCategoryAxis *m_yearAxis;
Q3DCategoryAxis *m_monthAxis;
- QBarDataProxy *m_temperatureData;
- QDataVis::MeshStyle m_style;
+ QBarDataProxy *m_primaryData;
+ QBarDataProxy *m_secondaryData;
+ QAbstract3DSeries::Mesh m_primaryStyle;
+ QAbstract3DSeries::Mesh m_secondaryStyle;
bool m_smooth;
};
diff --git a/examples/bars/main.cpp b/examples/bars/main.cpp
index 158244b4..21a4e0e6 100644
--- a/examples/bars/main.cpp
+++ b/examples/bars/main.cpp
@@ -52,7 +52,7 @@ int main(int argc, char **argv)
hLayout->addLayout(vLayout);
//! [1]
- widget->setWindowTitle(QStringLiteral("Average temperatures in Oulu, Finland (2006-2012)"));
+ widget->setWindowTitle(QStringLiteral("Average temperatures in Oulu and Helsinki, Finland (2006-2012)"));
QComboBox *themeList = new QComboBox(widget);
themeList->addItem(QStringLiteral("Qt"));
@@ -73,24 +73,51 @@ int main(int argc, char **argv)
smoothCheckBox->setChecked(false);
QComboBox *barStyleList = new QComboBox(widget);
- barStyleList->addItem(QStringLiteral("Bars"));
- barStyleList->addItem(QStringLiteral("Pyramids"));
- barStyleList->addItem(QStringLiteral("Cones"));
- barStyleList->addItem(QStringLiteral("Cylinders"));
- barStyleList->addItem(QStringLiteral("Beveled Bars"));
+ barStyleList->addItem(QStringLiteral("Bar"), int(QAbstract3DSeries::MeshBar));
+ barStyleList->addItem(QStringLiteral("Pyramid"), int(QAbstract3DSeries::MeshPyramid));
+ barStyleList->addItem(QStringLiteral("Cone"), int(QAbstract3DSeries::MeshCone));
+ barStyleList->addItem(QStringLiteral("Cylinder"), int(QAbstract3DSeries::MeshCylinder));
+ barStyleList->addItem(QStringLiteral("Bevel bar"), int(QAbstract3DSeries::MeshBevelBar));
+ barStyleList->addItem(QStringLiteral("Sphere"), int(QAbstract3DSeries::MeshSphere));
barStyleList->setCurrentIndex(4);
QPushButton *cameraButton = new QPushButton(widget);
cameraButton->setText(QStringLiteral("Change camera preset"));
QComboBox *selectionModeList = new QComboBox(widget);
- selectionModeList->addItem(QStringLiteral("None"));
- selectionModeList->addItem(QStringLiteral("Bar"));
- selectionModeList->addItem(QStringLiteral("Bar and Row"));
- selectionModeList->addItem(QStringLiteral("Bar and Column"));
- selectionModeList->addItem(QStringLiteral("Bar, Row and Column"));
- selectionModeList->addItem(QStringLiteral("Slice into Row"));
- selectionModeList->addItem(QStringLiteral("Slice into Column"));
+ selectionModeList->addItem(QStringLiteral("None"),
+ int(QDataVis::SelectionNone));
+ selectionModeList->addItem(QStringLiteral("Bar"),
+ int(QDataVis::SelectionItem));
+ selectionModeList->addItem(QStringLiteral("Row"),
+ int(QDataVis::SelectionRow));
+ selectionModeList->addItem(QStringLiteral("Bar and Row"),
+ int(QDataVis::SelectionItemAndRow));
+ selectionModeList->addItem(QStringLiteral("Column"),
+ int(QDataVis::SelectionColumn));
+ selectionModeList->addItem(QStringLiteral("Bar and Column"),
+ int(QDataVis::SelectionItemAndColumn));
+ selectionModeList->addItem(QStringLiteral("Row and Column"),
+ int(QDataVis::SelectionRowAndColumn));
+ selectionModeList->addItem(QStringLiteral("Bar, Row and Column"),
+ int(QDataVis::SelectionItemRowAndColumn));
+ selectionModeList->addItem(QStringLiteral("Slice into Row"),
+ int(QDataVis::SelectionSlice | QDataVis::SelectionRow));
+ selectionModeList->addItem(QStringLiteral("Slice into Row and Item"),
+ int(QDataVis::SelectionSlice | QDataVis::SelectionItemAndRow));
+ selectionModeList->addItem(QStringLiteral("Slice into Column"),
+ int(QDataVis::SelectionSlice | QDataVis::SelectionColumn));
+ selectionModeList->addItem(QStringLiteral("Slice into Column and Item"),
+ int(QDataVis::SelectionSlice | QDataVis::SelectionItemAndColumn));
+ selectionModeList->addItem(QStringLiteral("Multi: Bar, Row, Col"),
+ int(QDataVis::SelectionItemRowAndColumn
+ | QDataVis::SelectionMultiSeries));
+ selectionModeList->addItem(QStringLiteral("Multi, Slice: Row, Item"),
+ int(QDataVis::SelectionSlice | QDataVis::SelectionItemAndRow
+ | QDataVis::SelectionMultiSeries));
+ selectionModeList->addItem(QStringLiteral("Multi, Slice: Col, Item"),
+ int(QDataVis::SelectionSlice | QDataVis::SelectionItemAndColumn
+ | QDataVis::SelectionMultiSeries));
selectionModeList->setCurrentIndex(1);
QCheckBox *backgroundCheckBox = new QCheckBox(widget);
@@ -101,6 +128,10 @@ int main(int argc, char **argv)
gridCheckBox->setText(QStringLiteral("Show grid"));
gridCheckBox->setChecked(true);
+ QCheckBox *seriesCheckBox = new QCheckBox(widget);
+ seriesCheckBox->setText(QStringLiteral("Show second series"));
+ seriesCheckBox->setChecked(false);
+
//! [4]
QSlider *rotationSliderX = new QSlider(Qt::Horizontal, widget);
rotationSliderX->setTickInterval(30);
@@ -146,7 +177,8 @@ int main(int argc, char **argv)
vLayout->addWidget(cameraButton, 0, Qt::AlignTop);
vLayout->addWidget(backgroundCheckBox);
vLayout->addWidget(gridCheckBox);
- vLayout->addWidget(smoothCheckBox, 0, Qt::AlignTop);
+ vLayout->addWidget(smoothCheckBox);
+ vLayout->addWidget(seriesCheckBox);
vLayout->addWidget(new QLabel(QStringLiteral("Change bar style")));
vLayout->addWidget(barStyleList);
vLayout->addWidget(new QLabel(QStringLiteral("Change selection mode")));
@@ -170,7 +202,7 @@ int main(int argc, char **argv)
//! [6]
QObject::connect(labelButton, &QPushButton::clicked, modifier,
- &GraphModifier::changeLabelStyle);
+ &GraphModifier::changeLabelBackground);
QObject::connect(cameraButton, &QPushButton::clicked, modifier,
&GraphModifier::changePresetCamera);
@@ -180,6 +212,13 @@ int main(int argc, char **argv)
&GraphModifier::setGridEnabled);
QObject::connect(smoothCheckBox, &QCheckBox::stateChanged, modifier,
&GraphModifier::setSmoothBars);
+ QObject::connect(seriesCheckBox, &QCheckBox::stateChanged, modifier,
+ &GraphModifier::setSeriesVisibility);
+
+ QObject::connect(modifier, &GraphModifier::backgroundEnabledChanged,
+ backgroundCheckBox, &QCheckBox::setChecked);
+ QObject::connect(modifier, &GraphModifier::gridEnabledChanged,
+ gridCheckBox, &QCheckBox::setChecked);
QObject::connect(barStyleList, SIGNAL(currentIndexChanged(int)), modifier,
SLOT(changeStyle(int)));
@@ -203,9 +242,13 @@ int main(int argc, char **argv)
QObject::connect(fontList, &QFontComboBox::currentFontChanged, modifier,
&GraphModifier::changeFont);
+ QObject::connect(modifier, &GraphModifier::fontSizeChanged, fontSizeSlider,
+ &QSlider::setValue);
+ QObject::connect(modifier, &GraphModifier::fontChanged, fontList,
+ &QFontComboBox::setCurrentFont);
+
//! [3]
widget->show();
- modifier->start();
return app.exec();
//! [3]
}
diff --git a/examples/custominput/custominput.pro b/examples/custominput/custominput.pro
new file mode 100644
index 00000000..9a94cfcd
--- /dev/null
+++ b/examples/custominput/custominput.pro
@@ -0,0 +1,17 @@
+!include( ../examples.pri ) {
+ error( "Couldn't find the examples.pri file!" )
+}
+
+SOURCES += main.cpp scatterdatamodifier.cpp \
+ custominputhandler.cpp
+HEADERS += scatterdatamodifier.h \
+ custominputhandler.h
+
+QT += widgets
+
+INSTALLS += target
+
+RESOURCES += custominput.qrc
+
+OTHER_FILES += doc/src/* \
+ doc/images/*
diff --git a/examples/custominput/custominput.qrc b/examples/custominput/custominput.qrc
new file mode 100644
index 00000000..8ced2b91
--- /dev/null
+++ b/examples/custominput/custominput.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/data.txt</file>
+ </qresource>
+</RCC>
diff --git a/examples/custominput/custominputhandler.cpp b/examples/custominput/custominputhandler.cpp
new file mode 100644
index 00000000..3b050fda
--- /dev/null
+++ b/examples/custominput/custominputhandler.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#include "custominputhandler.h"
+
+#include <QtDataVisualization/Q3DCamera>
+
+CustomInputHandler::CustomInputHandler(QObject *parent) :
+ QAbstract3DInputHandler(parent)
+{
+}
+
+//! [0]
+void CustomInputHandler::mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos)
+{
+ Q_UNUSED(event)
+ setInputPosition(mousePos);
+}
+//! [0]
+
+//! [1]
+void CustomInputHandler::wheelEvent(QWheelEvent *event)
+{
+ // Adjust zoom level based on what zoom range we're in.
+ int zoomLevel = scene()->activeCamera()->zoomLevel();
+ if (zoomLevel > 100)
+ zoomLevel += event->angleDelta().y() / 12;
+ else if (zoomLevel > 50)
+ zoomLevel += event->angleDelta().y() / 60;
+ else
+ zoomLevel += event->angleDelta().y() / 120;
+ if (zoomLevel > 500)
+ zoomLevel = 500;
+ else if (zoomLevel < 10)
+ zoomLevel = 10;
+
+ scene()->activeCamera()->setZoomLevel(zoomLevel);
+}
+//! [1]
diff --git a/examples/custominput/custominputhandler.h b/examples/custominput/custominputhandler.h
new file mode 100644
index 00000000..1fecb8d8
--- /dev/null
+++ b/examples/custominput/custominputhandler.h
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#ifndef CUSTOMINPUTHANDLER_H
+#define CUSTOMINPUTHANDLER_H
+
+#include <QtDataVisualization/QAbstract3DInputHandler>
+
+using namespace QtDataVisualization;
+
+class CustomInputHandler : public QAbstract3DInputHandler
+{
+ Q_OBJECT
+public:
+ explicit CustomInputHandler(QObject *parent = 0);
+
+ virtual void mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos);
+ virtual void wheelEvent(QWheelEvent *event);
+};
+
+#endif
diff --git a/examples/custominput/data/data.txt b/examples/custominput/data/data.txt
new file mode 100644
index 00000000..d0689b1f
--- /dev/null
+++ b/examples/custominput/data/data.txt
@@ -0,0 +1,1060 @@
+# Each line contains 3 floating point values
+# for x, y and z values in the scatter chart
+-10.0084,5.01799,-5.04425,
+-9.06229,3.07132,-4.54268,
+-8.55132,4.19424,-4.03318,
+-8.03806,4.75162,-3.99583,
+-9.50337,4.90684,-4.21947,
+-9.93819,3.42724,-3.58955,
+-7.84971,3.15272,-4.90367,
+-7.30477,2.91062,-4.11078,
+-7.11201,3.68863,-4.52683,
+-8.83267,2.96504,-3.61108,
+-6.94874,2.49808,-2.92883,
+-9.02606,4.7496,-4.18193,
+-9.5434,3.15534,-3.83789,
+-6.8679,3.66922,-3.58288,
+-8.16487,1.82227,-4.64523,
+-7.42165,3.18192,-4.22791,
+-7.99257,3.06559,-4.33262,
+-8.98851,2.64924,-4.44595,
+-6.36774,3.96697,-4.38998,
+-7.18413,3.32417,-4.04636,
+-7.91649,3.46826,-2.78126,
+-7.49495,3.12306,-3.14539,
+-7.5445,2.85744,-3.68421,
+2.25354,1.36828,-1.32025,
+-2.35524,-0.081203,1.23267,
+2.6517,-1.20549,2.73606,
+-2.55382,3.48814,-0.454971,
+-3.85468,0.263955,0.578276,
+2.85275,1.32315,1.0565,
+-0.404099,-2.36811,-1.60324,
+1.58908,0.363782,-0.554303,
+0.251507,0.124637,-0.752568,
+-2.45626,-0.722719,-1.11764,
+4.15342,1.92247,-0.954975,
+2.05845,0.643191,-0.121564,
+0.253468,0.814651,3.05732,
+1.51724,0.244303,2.25864,
+1.15,-0.487518,0.815931,
+-0.0538979,0.124927,0.251571,
+0.941523,-0.483498,-3.2731,
+3.55074,-1.04714,-0.954301,
+-2.43125,-0.964099,-0.658537,
+4.25459,0.163296,2.05563,
+-0.612031,1.03234,-0.227175,
+7.8338,-0.847922,-0.959189,
+-4.20076,1.44907,0.853836,
+-1.59466,-1.27511,-1.5686,
+-3.3567,-1.96864,1.83224,
+-2.75169,-0.964221,-1.26465,
+-2.45624,0.287046,-4.55032,
+2.73649,-1.48789,-0.653082,
+2.73284,2.2912,-2.4933,
+-0.854321,-2.04288,3.7516,
+-1.35708,-1.84915,2.35985,
+-3.25001,-1.64456,-4.45419,
+-0.356834,-0.569139,-1.75308,
+-0.813569,-0.287899,-0.0535036,
+4.75975,-1.48817,-2.45957,
+4.35294,1.46154,0.814214,
+-3.22467,2.76903,0.510435,
+2.49494,1.9286,0.552287,
+-0.456521,0.688277,-0.82788,
+-2.72568,2.80278,-2.45782,
+-1.65023,1.32005,-2.05754,
+-1.63551,1.88519,-3.65544,
+-1.20008,-0.723785,0.853563,
+1.45448,1.08701,2.17385,
+-3.9042,-1.16916,-0.85395,
+3.15645,0.123932,-0.950988,
+-1.35924,-2.64015,-0.54254,
+-4.15753,1.28294,-4.47502,
+-2.7885,2.48535,-0.159651,
+-3.44364,0.627232,6.11881,
+-1.55639,-0.967484,2.35497,
+-0.752853,1.16736,-0.757871,
+-0.859974,0.640213,-1.75453,
+0.85744,0.480175,2.97204,
+4.0571,3.24083,-0.183622,
+0.658087,0.841418,0.357839,
+-2.13027,0.920836,-2.758,
+-0.65825,0.164257,1.69478,
+-1.88335,-1.4811,-2.15408,
+-1.67331,2.96982,1.85521,
+-0.750937,0.282914,-0.758707,
+2.29891,1.16949,2.65927,
+2.69132,2.92632,-0.206126,
+-1.65771,3.28846,2.50201,
+-0.568799,2.5289,-1.15875,
+-1.85383,0.528953,-2.32418,
+0.159422,-2.36165,-0.569393,
+-3.96506,0.282374,-0.254519,
+0.150933,-3.88058,-0.759422,
+-1.17917,-1.96176,0.95589,
+-0.340817,-3.52333,-1.45715,
+3.21784,-2.56593,2.55468,
+0.609650,-2.44153,1.35813,
+1.4594,-1.96511,0.170228,
+3.55017,-2.16882,1.75539,
+2.89487,-0.727481,-0.39588,
+-1.65151,-0.603877,0.250508,
+-4.35232,-1.32155,-2.31877,
+2.75852,-1.88931,1.77874,
+2.75452,-0.64123,2.45546,
+0.151914,-0.888395,-0.260935,
+0.150593,0.0461652,-0.158206,
+-1.22087,-2.92034,-3.78604,
+-0.761622,0.161856,3.5586,
+-1.88456,-2.48094,0.287091,
+1.25293,2.64374,1.6532,
+-0.657609,1.32547,-0.557301,
+3.85995,2.32568,-1.38265,
+1.65572,-2.28977,0.957488,
+-2.45312,-2.96071,3.45147,
+-1.75259,0.365259,1.60113,
+1.14045,-0.844805,0.359343,
+-1.55951,1.65687,-3.10398,
+0.441652,-1.36623,-1.55494,
+-3.95762,0.288753,3.7791,
+-1.80101,-0.241499,2.29693,
+-0.456931,1.64399,1.35559,
+-0.691421,-0.723378,2.51839,
+-1.20658,-3.04063,-1.552,
+-0.958574,1.48688,0.950152,
+1.76319,-1.36072,2.15866,
+-3.91301,-0.328932,-2.45524,
+2.9553,3.12703,-2.43321,
+3.55939,-1.48028,0.152252,
+-1.41545,3.247,0.779314,
+-3.34482,-0.894538,2.09302,
+1.15338,0.362332,-2.7924,
+0.468852,0.120872,1.35593,
+1.98778,-3.32292,-0.758591,
+0.420718,-0.225014,-2.44806,
+0.550207,1.56432,2.25317,
+4.35156,-0.966178,-0.791032,
+3.35179,-1.04981,-0.854089,
+1.70857,-0.281369,-0.254686,
+-3.05855,-0.443693,1.30251,
+-3.9509,-2.72179,-3.83489,
+2.19632,1.32915,1.15345,
+1.42782,-0.449435,-2.85005,
+-2.19053,0.049866,2.87493,
+2.45196,-2.44705,-2.85302,
+4.35263,0.245956,1.12886,
+1.8167,1.85407,-0.714159,
+1.88577,2.04227,-0.959396,
+1.6522,-2.48289,0.355373,
+-3.39965,0.286834,-1.68171,
+1.85639,1.47419,2.25749,
+-2.5216,-0.88573,-2.69594,
+-0.143043,0.28453,-1.75898,
+-2.52745,-2.76741,-0.257011,
+0.381448,-1.64793,-0.756889,
+2.30469,-1.28844,-2.79271,
+-1.72491,-1.48634,-2.61686,
+0.503342,0.248352,-2.27162,
+0.457491,-1.88183,-0.951124,
+-1.23123,0.963519,2.3569,
+-0.55709,-0.364372,-1.82528,
+2.73963,-0.567024,-0.496936,
+1.17979,2.76252,-2.35641,
+-1.20723,-2.1692,3.14368,
+-0.0504301,1.76714,1.64265,
+1.45714,-0.725448,0.739217,
+0.246123,-3.27811,-0.251218,
+-0.894632,1.08758,-0.17184,
+-2.45217,0.565077,-0.557015,
+2.51301,1.1271,2.25057,
+-1.05099,-2.1688,-1.88996,
+1.26945,-2.1225,-1.55031,
+-4.30129,-0.760298,0.259868,
+-0.157336,-0.237532,-2.69483,
+-2.95778,1.36212,-3.65524,
+2.74003,1.16234,2.05928,
+0.955294,-1.52182,-1.05684,
+-1.87004,2.72729,-0.550608,
+0.459439,2.88101,-4.4135,
+1.35069,1.08445,-0.808625,
+-2.70034,-1.36291,-2.65126,
+0.353099,2.32354,-1.61885,
+-0.453359,1.67524,0.122888,
+3.7506,1.12855,-3.86338,
+0.548626,2.63101,0.552261,
+-0.753935,-3.52241,-3.21122,
+0.258935,-1.32453,2.25745,
+-2.8797,-1.60832,-2.45626,
+0.151838,-0.565264,3.98539,
+2.1508,-1.68734,-1.75076,
+-4.23947,-1.92531,2.35438,
+1.95273,-1.32736,0.313398,
+0.533647,0.646686,0.75712,
+0.856619,-0.843249,-0.577773,
+-2.15649,-1.64285,-2.31055,
+-0.851309,-2.84717,-0.324933,
+-3.17772,-0.324817,-0.858394,
+3.45303,5.29449,0.818094,
+1.42912,0.238088,0.385617,
+0.459586,1.7661,-0.153761,
+0.855577,3.16845,-2.19548,
+2.15181,0.729021,-0.955922,
+-2.40113,0.665756,-0.521366,
+1.45469,-0.462177,-1.95869,
+0.629115,-1.84769,1.86755,
+3.47576,-0.209875,-0.555502,
+0.295075,-0.840772,4.68895,
+-0.253301,-2.49078,2.11749,
+-1.15923,-3.163,-3.05671,
+1.45484,0.963654,-0.734942,
+0.354307,0.520772,-1.32278,
+2.65725,0.284589,-0.856856,
+-1.2596,0.765493,-1.66469,
+-0.656057,-2.16906,3.72144,
+-0.251559,-2.36406,-1.89709,
+0.35608,-0.80463,1.85674,
+0.0508692,0.615674,0.856785,
+-2.50726,2.28743,-2.05697,
+1.65272,1.29604,2.11481,
+-3.2878,-0.244516,0.799732,
+-2.18989,-0.847222,-0.264559,
+0.452832,0.960993,2.53691,
+-2.43913,1.28957,2.75427,
+-1.72889,-3.29414,-2.31426,
+0.952615,-0.0844651,0.346607,
+1.41175,0.889643,0.450356,
+2.13145,1.08697,0.223055,
+-2.16002,-0.225505,-0.602641,
+0.54028,1.24765,-0.456129,
+2.55086,-0.56734,-2.65051,
+-4.53921,-0.483588,-1.25013,
+3.45413,-0.44258,2.29687,
+-0.257456,0.64624,1.65041,
+1.25559,-0.65493,-0.358872,
+1.9599,-1.56965,-4.17044,
+2.75996,-1.98665,3.31794,
+3.05837,1.04847,-0.975536,
+-2.95407,1.40294,-2.25825,
+1.38718,0.360709,-2.98211,
+0.481728,-2.48564,3.25864,
+-1.15089,0.363522,0.458662,
+-2.25551,0.0421839,0.650008,
+-1.85862,-0.969237,4.25313,
+1.55797,0.0465051,-3.85709,
+0.0555338,0.682957,-2.45556,
+-0.186868,-0.482811,1.96957,
+2.197,-1.5248,-4.20912,
+3.40636,6.26268,-2.05757,
+0.780426,2.68048,-0.852693,
+1.65184,1.68951,-0.892089,
+2.11929,-2.44406,1.21168,
+-0.153348,-1.88112,-0.357374,
+-0.359393,1.76654,1.63063,
+-2.15954,0.0819277,0.757621,
+-0.159898,-3.36316,0.359582,
+2.74125,-2.84148,0.355785,
+-1.3558,0.27827,-0.588162,
+-0.354346,-2.56747,-0.984403,
+-2.75082,-3.56807,1.5599,
+-2.54708,-0.686147,2.75649,
+1.35138,0.692978,-2.24969,
+-1.39826,-0.246682,-1.65876,
+-1.46629,-1.44446,4.45293,
+-1.89442,3.64549,2.05732,
+-0.658093,0.0815129,3.95269,
+2.25603,2.96329,-2.35993,
+1.36323,1.64488,-0.0538547,
+1.75659,2.24227,-2.8522,
+-0.0566584,-1.56465,-0.0503143,
+-3.8532,-0.822258,-0.345406,
+0.951328,0.329296,-2.52211,
+-2.48659,0.410856,-3.55401,
+3.72676,2.36324,3.65589,
+0.559972,0.884984,3.15283,
+-1.37624,-1.36007,-2.16578,
+2.05543,0.4472,-0.82911,
+-4.75258,1.8779,-1.75376,
+0.15648,2.64039,-2.21467,
+-2.0593,-2.56775,1.15037,
+-3.70217,2.12375,1.3652,
+1.05566,6.8299,4.02985,
+-0.766882,-0.88359,1.35525,
+0.951335,-1.84689,0.178337,
+0.751608,1.1691,4.25273,
+-1.36367,0.728904,0.655858,
+3.17581,-0.0844758,-1.75811,
+2.85546,-0.683618,0.653701,
+-0.471118,3.04176,-2.35393,
+3.0574,-0.601996,-0.611932,
+-0.854024,-0.44532,0.355575,
+0.504700,-1.92888,6.4818,
+-1.25515,-1.44466,1.90429,
+-1.67201,0.0461708,-0.796655,
+1.45345,-1.66159,-3.48143,
+-2.84514,-1.24586,-3.47945,
+0.287402,-0.688276,-3.75664,
+3.35908,0.687828,-1.94406,
+-2.39167,1.08322,-1.73508,
+1.52152,1.86032,-1.25351,
+1.55931,3.64414,1.35944,
+1.15954,-1.36058,0.758814,
+-1.95325,0.0851092,-0.854106,
+-2.25254,-0.523024,1.05486,
+-2.68036,-1.32901,1.05877,
+-0.485956,-1.52164,2.45303,
+-0.0546215,0.640683,-2.85953,
+4.45295,-0.246051,-0.159626,
+3.4523,1.7215,-1.10587,
+3.35142,-1.72053,-0.252105,
+1.74251,2.76108,2.51524,
+2.15054,-2.88101,-1.7527,
+-3.70517,-0.0470951,0.258921,
+-0.45593,-3.47184,-2.95345,
+3.15988,-2.32107,0.105299,
+0.751449,-2.88762,-3.45245,
+2.9794,0.493172,-0.654683,
+-1.87713,-2.48632,-3.534,
+1.65266,3.16008,2.1579,
+-1.25239,-0.763119,2.15776,
+3.5572,0.282681,2.44174,
+0.251145,0.520256,2.3184,
+-1.78596,-1.36913,-2.50818,
+3.82122,1.04473,0.456159,
+2.45979,-0.722759,-4.05123,
+-0.855594,0.163792,-0.553702,
+0.656895,0.529982,3.35129,
+0.857952,-0.0885677,0.695128,
+-0.143269,1.12972,-3.155,
+-2.95923,0.241767,0.832165,
+0.253329,-0.622952,-0.459799,
+0.151499,2.5297,1.53059,
+0.655464,-1.49902,-1.51071,
+4.7585,1.76425,1.15164,
+-1.75063,-1.44645,-3.65525,
+0.850392,0.0417223,-0.340588,
+-0.557015,-0.282305,-1.85291,
+-4.05639,0.522959,-2.3507,
+-0.358137,-0.967852,0.807832,
+-1.82056,-0.0483894,0.0541359,
+-2.16623,0.129809,-2.52513,
+-1.85591,-1.04417,-1.28501,
+-1.79647,-3.44045,-1.73399,
+2.25342,0.161308,-0.0517495,
+-1.37877,0.243596,-1.52931,
+-0.059299,-0.480825,1.7137,
+-2.54357,0.286685,-2.11495,
+3.92334,-0.442936,-0.852895,
+-0.390023,-1.96437,1.38718,
+1.35263,2.92968,-1.1545,
+-2.25892,-2.27429,-0.451533,
+-0.2215,-0.126727,0.155541,
+0.715932,1.47509,-3.52895,
+-0.382939,3.16461,2.65165,
+-1.14437,-1.44682,0.456601,
+0.251892,-1.0431,4.31548,
+-2.23281,-2.48698,0.46995,
+0.954231,-3.4323,-1.20233,
+2.75569,-1.66383,-1.95486,
+0.750644,-1.84163,-0.159206,
+-0.757387,-1.84192,0.354209,
+-2.85509,-2.12151,-0.954754,
+-0.888427,-2.8403,-0.157387,
+-1.95265,-0.445753,2.17956,
+-1.05845,-2.48694,-1.25315,
+-2.66497,-1.48251,0.873192,
+2.50491,-1.0833,1.99667,
+0.453931,2.52158,0.456875,
+1.55859,-0.161924,0.256619,
+-2.92585,0.368018,0.35908,
+2.95509,-1.56248,-2.74469,
+3.46082,-1.76026,3.05835,
+1.75644,-2.84241,0.507631,
+-0.959006,0.649579,1.10824,
+2.63856,2.0417,0.187281,
+-0.150004,-0.0838836,-0.949314,
+2.26402,-1.28916,2.85284,
+-0.821239,2.68795,-0.317185,
+3.47124,0.840813,-2.65322,
+-0.253209,-0.244177,0.457348,
+2.76181,1.64033,-1.95329,
+1.35105,-2.96027,0.659952,
+-1.45423,-0.24358,0.832696,
+1.45109,1.64958,-3.45448,
+-1.15659,3.08225,1.11445,
+0.806359,1.88298,-2.13001,
+1.15538,3.04545,-0.759437,
+-0.450074,1.36121,-0.155042,
+-2.80924,-1.24207,2.55513,
+4.48859,2.04394,1.25324,
+-0.958741,1.24575,3.65169,
+3.45143,1.3276,2.5144,
+-3.25232,1.12514,-1.21425,
+-2.45327,0.681109,4.35764,
+0.55395,-0.128353,-3.95705,
+-0.352458,3.08882,-0.340631,
+1.35213,-2.92251,-3.31166,
+0.52621,-0.279201,0.959619,
+1.2243,-0.240093,-0.75247,
+-1.29854,2.16477,3.3507,
+-3.35677,2.36713,3.4585,
+0.957717,-0.885793,1.25827,
+0.150983,1.24269,5.39106,
+1.84986,1.56932,-1.05811,
+-1.35563,3.82103,-1.45287,
+1.4544,-2.6453,0.58082,
+2.05908,1.16496,1.44075,
+2.9507,-2.4957,0.153512,
+-1.10289,0.763085,-1.65351,
+-2.50708,-2.467,1.05892,
+3.55284,-1.8509,-2.55732,
+-0.848034,1.24305,-3.7516,
+-1.35051,-2.48178,2.85326,
+-2.18554,1.48771,-0.155205,
+-0.459278,2.68404,2.85727,
+0.854722,1.47322,-3.35951,
+-2.23505,-2.24254,0.353203,
+1.42395,-2.32169,0.558188,
+3.65106,1.12201,-4.58409,
+0.11,-0.68782,1.85804,
+-1.9551,-0.560204,-2.0577,
+1.85964,1.32737,-4.40673,
+-0.616311,0.649737,-0.30189,
+-1.55375,1.52043,-3.75629,
+1.85417,0.486964,0.654806,
+3.35638,2.52599,1.94343,
+0.491389,1.40427,-1.31935,
+-2.72939,0.844341,1.62621,
+-0.525985,1.31415,0.484015,
+2.25998,-1.719,1.25143,
+1.79268,2.46378,-0.951188,
+-3.55105,1.04122,3.9501,
+0.954251,1.28296,2.05486,
+-3.15267,1.96498,-0.361707,
+1.35358,-0.921098,-1.71743,
+-3.16896,-3.08548,0.903411,
+1.25127,-2.44903,2.25616,
+-3.88899,0.761334,-1.05751,
+-1.05163,-3.89783,-0.883668,
+-4.189,1.24176,-2.63816,
+2.45671,-1.84859,0.352808,
+-1.59618,2.16255,4.33699,
+2.10913,-1.88673,-0.952497,
+-1.85571,-0.287392,0.277176,
+0.751967,1.04568,-1.35427,
+2.85792,1.60982,-2.05454,
+-2.13152,-0.260207,-2.15124,
+1.75432,2.28936,0.756254,
+1.95711,-0.681098,-2.38037,
+-0.826273,1.08361,1.6515,
+-1.85118,1.89481,-0.756754,
+-3.0571,2.44795,0.355341,
+-0.455122,-3.58071,-2.85209,
+-0.95805,0.641282,2.15189,
+-1.35515,-0.234803,-0.825819,
+2.12472,-0.0444431,0.651227,
+2.67573,0.223987,2.75712,
+1.65871,-0.163059,1.6513,
+-1.85429,0.68862,1.9576,
+-3.05186,-2.2804,0.100919,
+3.41813,-1.88775,3.67075,
+-0.753778,0.36467,1.55333,
+2.97628,-1.36502,-1.85135,
+0.477128,1.08862,0.858931,
+-1.0531,1.0488,2.15218,
+2.66911,-2.08876,-0.182397,
+5.117,-2.84097,-0.953684,
+0.468302,1.88616,2.05369,
+-3.16099,-2.76085,-2.75679,
+-2.6593,3.52373,-1.24072,
+-4.37957,-0.286903,3.63863,
+-2.85958,-2.56921,-2.85723,
+-0.159735,2.72758,-2.80575,
+-0.951849,-0.607465,1.05633,
+1.93077,2.56422,1.25446,
+-0.859754,0.248106,0.0584456,
+2.4023,2.56659,-1.2588,
+2.35295,-1.08729,2.7851,
+-2.1537,-0.765032,2.83652,
+1.40185,1.29804,2.3588,
+-0.991566,1.72049,4.17146,
+3.76736,-1.48837,2.05329,
+-0.251896,0.765367,-1.4087,
+-1.6228,0.328693,0.0528287,
+2.56735,-3.08103,0.853144,
+0.0531812,-1.96216,1.55734,
+-3.77052,0.8421,-0.258953,
+2.35523,0.676643,-1.55789,
+1.16702,2.64474,-1.45533,
+2.55709,-1.56013,2.05351,
+-2.15518,3.56253,3.257,
+-0.553936,-1.24935,2.65224,
+-0.355931,1.32374,0.859863,
+-1.92974,1.2482,1.15936,
+0.350652,-2.44371,-1.35611,
+2.98996,-1.08527,-4.30641,
+1.82765,-0.440236,1.25528,
+-0.689231,-1.08813,-0.668663,
+-0.326426,-0.881857,-1.45371,
+-1.0655,2.12466,2.34146,
+3.1563,0.523166,-2.8572,
+0.455505,2.48775,-1.33482,
+0.53939,-0.847333,0.732877,
+-0.683025,-0.448889,-1.35747,
+-1.7711,-0.125587,-2.55083,
+-0.512871,0.520964,1.40731,
+4.93857,-1.6805,-0.127298,
+1.46098,-1.64073,1.35833,
+0.0518058,0.285151,-2.2437,
+1.5587,-1.23067,0.458753,
+3.13089,3.64132,1.45181,
+-1.55648,2.167,0.153491,
+3.94451,-2.56372,-1.25276,
+4.15866,0.646921,2.65542,
+-2.88189,0.562407,-1.35379,
+1.31686,1.2808,0.804375,
+-2.36912,-3.08775,1.28335,
+0.575203,-0.36483,-2.43958,
+0.613108,0.526892,2.75368,
+3.96027,-0.525425,-4.25746,
+-0.510821,1.28578,-0.058488,
+-0.254704,-3.847,3.15258,
+-0.925874,-1.72014,-3.15341,
+0.85704,0.84788,-1.75947,
+-3.35712,0.722104,2.15645,
+-1.67305,0.681216,1.65726,
+-3.64682,0.867926,2.63525,
+-0.715921,1.96081,-0.939934,
+-2.45646,1.3249,-2.75733,
+-1.75798,0.725382,-0.851921,
+-2.78528,0.679275,-2.59212,
+-2.24551,-3.4597,-1.85735,
+0.85142,2.28058,-3.75328,
+-3.85054,2.44519,4.35081,
+-3.6553,0.521917,0.293354,
+-4.35959,-0.528198,1.55557,
+1.45186,-0.0891161,-0.468118,
+1.85594,-0.761461,-4.68083,
+0.950642,0.526239,-1.30614,
+-2.50526,-0.885606,-0.362569,
+-2.96569,1.68519,-1.15965,
+-3.212,0.260715,1.18472,
+0.950556,-0.282806,0.776252,
+3.66678,1.08585,-2.15646,
+-0.806289,1.72784,2.85906,
+0.363827,1.76644,0.931866,
+-1.34204,-0.563686,-2.34091,
+-2.81333,0.415358,4.28363,
+1.52053,-0.327359,0.35052,
+-0.633441,-0.240518,4.05745,
+-2.38947,-1.84662,-2.29572,
+-1.95744,-0.863705,1.85889,
+-0.0509082,-0.164164,3.8571,
+0.156438,-2.64188,1.75836,
+-3.85642,1.48025,0.171659,
+0.253545,1.0852,-2.45243,
+-4.11318,4.1655,-0.120976,
+-1.44928,-0.328222,-0.871279,
+-1.90972,-1.8495,-3.16966,
+0.359433,1.3236,-3.95045,
+-2.60974,-1.04138,4.25836,
+-3.16336,-0.961581,-1.65161,
+-0.552909,-1.16942,4.05164,
+-3.10918,-1.2402,-0.555073,
+2.25494,1.24432,3.44063,
+-1.24998,-1.24928,-4.05493,
+3.05441,1.92762,1.43329,
+0.557032,-2.7688,-3.25463,
+-2.05665,1.6357,0.656665,
+-0.459042,0.122664,-0.152961,
+2.17715,2.96833,1.1332,
+0.0536573,-2.08635,-0.736471,
+-3.15658,1.0818,-0.172166,
+-1.95784,0.44402,0.612685,
+0.15168,-0.323951,2.85563,
+0.559356,1.63101,0.558005,
+-2.05643,1.84615,-1.87964,
+-0.254098,0.368208,1.23061,
+4.6438,-0.209283,0.695869,
+-1.95087,-0.859788,0.0539467,
+-0.351737,-1.04291,0.869198,
+0.776319,3.04922,-3.55278,
+-0.158751,1.12538,-2.59681,
+-0.560997,-1.68381,1.56935,
+1.71385,-0.446223,-1.56843,
+4.05142,-1.3243,2.85052,
+1.68685,-1.56305,2.159,
+0.359977,-1.16029,1.25037,
+-2.65045,-1.28532,0.459338,
+5.42068,1.52601,-1.35562,
+1.34386,1.68231,-2.75114,
+1.25123,0.43108,0.383897,
+-0.952936,3.6889,1.75759,
+-3.55855,0.484241,1.15503,
+-1.71394,-2.64568,-3.30684,
+-2.23513,-2.46812,1.05321,
+0.160986,0.442362,-1.05077,
+2.05433,0.473204,0.823968,
+0.482077,0.0477338,4.21712,
+-1.25348,0.767612,0.455813,
+1.61308,2.04125,-2.95433,
+-2.05862,-0.444052,1.35177,
+-3.2582,0.44354,2.15898,
+-1.75935,0.0459283,2.35061,
+-4.15501,0.68674,0.802439,
+-1.66005,1.12067,0.552901,
+-0.150828,3.4151,3.05446,
+-0.274381,0.0405946,-1.45463,
+2.94543,-0.360918,1.45895,
+-1.42494,1.56503,1.31012,
+3.45402,-1.27808,-4.29049,
+-1.14819,0.674339,1.55807,
+-0.356159,1.52295,-0.351445,
+0.387809,0.965119,1.84271,
+2.56165,-1.84639,1.65056,
+-0.619108,2.24004,-2.92134,
+-0.254288,-2.32744,-0.720931,
+3.3508,-2.24501,1.58268,
+1.69434,1.96814,3.97439,
+1.80785,0.685502,-1.55595,
+2.71587,1.76415,-2.98124,
+-2.35151,-0.697338,-3.96269,
+-1.85759,1.96899,-1.25212,
+-4.05922,1.12838,-2.7597,
+-2.85434,-1.36487,0.659987,
+-1.75616,2.12969,-1.35032,
+-2.95985,-0.0854955,3.65545,
+-2.46049,2.45378,4.51969,
+-0.0577358,0.0427911,0.359068,
+-3.25346,0.161829,1.12956,
+3.55498,2.32482,1.33302,
+4.99905,-1.88748,0.450165,
+-2.35406,-1.44715,-0.745307,
+2.44217,-0.642981,0.126924,
+1.73283,1.67362,1.91136,
+1.34239,-0.434386,-0.449795,
+-0.9813,-2.72962,-3.6889,
+1.29807,-0.448566,2.13911,
+0.654017,3.54591,-1.55982,
+-1.55508,-2.64564,0.555,
+1.92722,-0.322513,-2.13691,
+1.35913,-2.84853,-0.470788,
+0.257868,-2.68874,-0.268328,
+-2.05043,-1.68405,-3.05075,
+1.65173,-0.446801,-0.75339,
+-1.25655,0.965275,-4.15374,
+-4.27942,-0.564403,1.45826,
+0.950669,-2.4416,-1.68235,
+-0.0541107,0.882274,3.15308,
+-1.65016,-0.886156,-3.85588,
+0.355613,0.217671,4.25412,
+0.800472,0.847259,3.11114,
+1.8599,-2.16981,-2.22314,
+-2.05061,0.164561,-0.452181,
+0.854144,1.84334,-1.45981,
+1.68547,1.56536,-1.45874,
+1.25244,-0.844991,-2.95475,
+-1.92348,2.32119,-1.80444,
+-0.645646,2.45193,-3.65332,
+4.45803,0.527732,3.02031,
+2.74572,0.287964,-1.80485,
+0.35961,-2.56437,3.97194,
+-0.956828,-1.28915,1.64424,
+0.414971,-0.235061,-2.15757,
+-0.0530542,-1.08464,-4.11853,
+3.17203,-1.21013,-3.85806,
+0.758948,0.124698,-3.10188,
+-1.65404,-1.16204,-1.65357,
+-1.65985,3.84433,4.65101,
+2.83444,-2.69529,-1.65021,
+1.29814,-2.76926,-2.27139,
+0.462382,3.04217,3.45153,
+-3.61944,1.04723,-0.638308,
+2.25235,1.64048,2.95175,
+-3.05826,-0.76526,-2.38243,
+-2.8506,2.12102,-0.659444,
+-0.10046,0.0887098,-1.63621,
+-1.55585,-1.36073,2.2076,
+-0.474968,1.56568,-0.302349,
+0.36584,-2.36102,1.35289,
+0.224784,-0.637694,1.62444,
+-0.658172,1.9689,-3.13712,
+0.646334,-1.04672,2.59285,
+-2.63054,-1.08263,-0.851087,
+1.45804,-2.56159,-2.66388,
+-2.45748,0.0409116,-2.85428,
+-0.0561462,-1.24229,-1.25145,
+-2.95391,-1.80896,-2.05036,
+4.36778,-0.969951,3.53686,
+2.15582,-1.67173,-0.831609,
+-1.27059,-1.14919,1.7569,
+-1.57398,-1.28091,-0.251735,
+2.59506,-2.6408,-0.345589,
+-1.64147,-0.360324,3.1562,
+-0.125427,-0.641484,-3.66095,
+-1.9148,1.8885,2.12972,
+-2.85768,-2.28782,-1.55719,
+-1.37239,-0.485964,-2.22291,
+0.516294,0.281078,0.652612,
+-1.13028,0.246659,-2.25636,
+1.7555,-1.41602,0.348449,
+1.5355,-1.32646,-2.82417,
+-0.95426,2.0824,-0.383507,
+2.75739,0.241779,0.755701,
+0.752655,0.56204,-1.55738,
+1.1271,-3.76145,4.3701,
+0.326656,-1.24467,2.62222,
+-0.259702,2.68152,-3.18542,
+1.88504,-0.760623,4.42592,
+2.51673,4.72252,-1.99239,
+-1.66934,-0.129677,-2.49048,
+-1.25499,2.36151,-2.98447,
+2.65331,0.0443886,0.108819,
+-3.35439,0.0872109,-1.33429,
+3.35597,0.0403626,2.8203,
+4.45191,1.24824,-0.95821,
+-0.171441,-1.52622,-4.68253,
+1.19986,1.72992,-3.29566,
+-0.451339,1.92976,1.21534,
+-0.743119,-0.160688,0.805688,
+2.38678,0.272829,2.75457,
+1.72464,2.08232,-0.950389,
+2.11167,1.56576,1.21969,
+3.05157,-1.56838,-0.450535,
+0.132417,-3.08279,-1.34127,
+1.65441,-0.325204,-0.825145,
+2.05515,-1.8417,1.8561,
+-0.555858,1.52007,-0.80122,
+-2.05026,1.52773,2.33529,
+-2.35231,-3.28716,3.53598,
+-2.25771,2.5667,-1.92243,
+0.386884,-3.28674,3.49336,
+0.957272,-1.68124,-1.89095,
+2.99881,2.24992,-0.0535837,
+3.19604,2.92893,-2.16276,
+2.55903,3.12413,2.95022,
+-0.570758,-2.85326,-0.339255,
+0.356627,0.641074,0.355538,
+-1.15777,-0.162227,-0.455885,
+-2.4871,-0.885492,-0.374875,
+1.55464,-1.48929,-0.593706,
+-0.852655,-2.08736,-1.18281,
+0.504087,-0.879247,1.35148,
+-2.15261,1.04511,-3.25543,
+-0.653745,-1.32873,-3.18964,
+0.35973,-0.844255,-1.72034,
+-2.11112,0.962572,2.59386,
+1.47531,-0.693626,-3.15249,
+-1.35814,0.767202,3.45094,
+-3.05812,-1.26298,1.45287,
+-1.63927,0.893568,-1.94978,
+0.751992,1.68559,2.3618,
+5.8205,-0.769076,-0.958994,
+-2.38512,-0.166005,-1.25855,
+-0.556071,-2.28164,1.57032,
+5.89172,-0.244834,0.553728,
+-0.468648,-0.927756,-0.737048,
+-2.66659,-1.64374,-0.995568,
+0.251499,-1.24569,0.95028,
+0.737721,2.88575,0.448918,
+-0.634421,-1.84377,-2.47094,
+0.556349,2.86774,1.62621,
+-3.29644,3.28642,-3.45459,
+-1.45045,2.52138,2.75329,
+1.87449,-2.68651,3.60371,
+-0.656424,-2.56828,1.35509,
+1.95771,-1.48325,-3.85265,
+3.85074,0.0825779,-1.65283,
+-1.17278,-1.69258,-1.05875,
+1.25754,-0.0439433,1.3571,
+2.91459,2.08715,0.259842,
+0.748196,2.52132,0.659051,
+-1.85745,-1.88355,1.05259,
+1.69311,1.12299,-3.05453,
+-2.86301,0.123274,0.559289,
+-1.43146,1.64425,-1.95053,
+2.35287,0.414621,-0.950807,
+0.952585,-0.280452,-0.844588,
+-1.53836,-1.76396,2.51742,
+-3.05431,2.45,-0.26571,
+-0.637412,1.12028,-0.587387,
+-1.71017,-0.728497,-1.05087,
+0.454027,0.849208,-0.151716,
+-3.54846,0.367137,1.1484,
+0.200816,-2.08832,0.255433,
+-2.15817,0.725338,0.852676,
+-2.45708,-0.725538,-0.859435,
+4.25339,1.84177,-0.555145,
+0.119319,-1.32041,-1.45864,
+-3.65177,0.361323,0.351554,
+0.928598,0.321024,-3.64759,
+-0.250062,1.84912,7.49887,
+3.59593,0.929451,-2.15224,
+0.658599,2.36796,4.11632,
+0.55841,-1.08657,0.258326,
+1.9419,0.0488641,-3.75375,
+0.0589998,0.521351,-3.85723,
+3.45108,0.562199,4.20946,
+-0.255073,2.36504,-3.556,
+1.95848,1.28698,4.25014,
+1.85411,3.12131,0.652769,
+-3.3589,0.801817,-1.5591,
+2.48128,-0.163406,1.25243,
+2.52135,0.960467,1.45432,
+0.827496,-0.163021,-0.558886,
+-3.45032,-0.0831453,0.851212,
+-3.45334,0.855944,1.35596,
+-0.834644,0.245598,-1.23878,
+3.64558,1.16831,-0.18559,
+-1.45919,-3.08196,-0.329805,
+-3.65715,-1.04485,0.159208,
+1.35463,-0.766382,0.558632,
+-2.75899,-1.67431,-1.55069,
+1.67539,2.04337,0.912884,
+3.51677,-3.24285,0.170272,
+-4.25189,0.56589,-4.35936,
+-2.68545,-0.448243,0.540342,
+0.279844,-0.641466,-0.353986,
+-3.27626,-3.52006,1.77644,
+-0.724096,-1.84647,-2.45271,
+-4.18603,0.123376,3.85066,
+-4.05156,0.0499386,-0.332945,
+2.69508,2.32777,1.26256,
+-0.353726,1.07252,-0.738837,
+-0.947178,0.36459,1.55593,
+-0.058346,2.44781,-4.35023,
+1.51586,-0.961109,-3.43483,
+-2.8852,2.08863,-1.75468,
+-0.297867,0.722757,0.91355,
+-1.12917,-1.68328,0.175315,
+-1.24248,-0.323519,-0.854841,
+0.751943,0.564075,3.95073,
+1.15436,2.81813,0.653114,
+-2.55058,-2.56486,0.756618,
+0.959794,0.845224,-0.854001,
+-2.15033,0.248556,-3.16151,
+0.353224,-1.68637,0.457949,
+-0.753237,-2.48313,-0.355373,
+0.296585,2.04822,0.198473,
+-2.4737,0.682952,1.85349,
+1.9027,0.882796,1.45908,
+0.254799,1.92572,-1.70848,
+-0.951602,-0.698987,-2.22682,
+0.262582,-2.44093,1.05636,
+0.385415,-0.685667,-3.35928,
+0.055981,0.523585,-3.36093,
+-0.0518635,-0.889068,-0.840648,
+0.455171,2.84624,-1.98276,
+2.85475,-0.685697,-2.45695,
+-1.05047,-1.92121,0.931666,
+-2.75962,-0.164458,-1.55261,
+1.91811,1.65767,3.15004,
+-2.25653,0.856735,-4.351,
+1.89178,-0.728669,-3.8803,
+-3.25958,-1.16223,-1.85148,
+-1.6291,-2.32967,-0.874786,
+3.17524,0.327351,2.15337,
+-1.05094,-0.560694,-3.4581,
+0.759785,-1.0801,-0.257876,
+-0.4597,-2.2404,2.54341,
+0.242266,0.121832,7.80878,
+-1.6573,1.56049,-1.61749,
+1.39912,-2.84395,-0.25965,
+0.552342,1.36924,2.95278,
+-1.92932,-0.883981,0.0589583,
+-1.9026,0.56297,-0.723523,
+-1.25867,-0.529617,2.3503,
+2.16527,-0.723364,-1.45609,
+-0.984608,-0.720375,-2.05144,
+0.946803,-0.969188,-3.14625,
+2.7986,-2.36069,1.25827,
+3.37979,-1.11699,-3.55116,
+-0.753992,-1.9649,2.98548,
+-0.456321,0.525303,-0.109174,
+0.8642,1.53147,-3.34749,
+-0.450507,-0.443265,-2.8325,
+-3.24876,3.12791,0.576143,
+-3.14755,2.84502,-0.45749,
+0.226819,-1.28172,0.939501,
+-0.650725,-1.40317,-1.35211,
+-0.451625,1.84271,-0.950536,
+-1.36693,0.850218,-1.09799,
+2.35374,-0.28759,1.55815,
+2.60577,-2.46765,1.2633,
+1.21562,-1.72153,-0.4034,
+-2.43216,3.04268,1.90109,
+-1.85365,-0.16523,-2.98947,
+-0.953475,-2.76164,2.53396,
+2.55264,-0.645611,3.25479,
+-0.675476,-0.724382,-1.4566,
+0.801062,0.16778,2.21815,
+0.680443,0.0407888,3.27279,
+-3.75426,-0.247624,0.26307,
+0.427609,-0.322312,0.652005,
+-2.17428,-3.68643,0.256619,
+0.456732,-2.44858,3.13051,
+0.524175,-1.88231,-1.93171,
+7.2311,1.8354,-1.2502,
+2.69502,2.25543,-4.25127,
+0.259357,2.28099,-0.476734,
+-0.327316,-1.24908,0.78628,
+0.190362,-3.26019,0.0545844,
+-1.25409,-0.761609,2.65361,
+2.86816,0.443709,0.556137,
+2.60289,-0.680561,0.248414,
+1.75631,-0.162859,-3.62488,
+-0.559754,-0.16222,2.35858,
+0.157552,-1.72639,-0.48056,
+3.69492,-0.848265,-0.256413,
+-1.4264,-1.48589,-2.724,
+1.15372,-0.27228,-2.75499,
+-1.85159,1.76577,-0.858854,
+0.0580466,-0.41133,1.05649,
+-1.25289,0.528142,-0.386138,
+-0.858101,-0.245127,1.95078,
+-1.95302,-0.0862415,-1.95806,
+-2.79133,-0.527094,-0.356931,
+0.110597,0.167534,4.12784,
+-0.637771,-0.526587,-1.25734,
+-2.311,-0.489068,-2.8594,
+-0.352617,-1.23939,-1.85435,
+1.78814,-0.265883,3.35913,
+2.75557,-2.32271,3.15559,
+2.85426,0.443661,0.921828,
+-2.14262,0.400863,1.11614,
+4.45496,-0.488668,-3.7533,
+0.754719,-1.44165,0.853323,
+-0.856506,1.76559,1.05702,
+-0.418565,-0.921031,-2.43699,
+-1.29292,-0.282271,-1.62927,
+-0.759531,0.566692,-0.750991,
+0.559787,1.72479,-0.26667,
+2.75533,-0.245187,-0.543844,
+-2.27924,-1.04154,-4.05156,
+3.35852,-0.561129,-2.98986,
+2.41843,-0.321119,-1.55651,
+0.85431,-0.883719,-2.17826,
+0.417867,0.242995,-0.456326,
+-4.17449,-0.720086,0.355145,
+-0.577386,0.0440364,-0.950268,
+-2.8156,2.92346,0.958713,
+-1.65138,0.963561,1.25265,
+1.45117,0.845424,0.252789,
+2.27848,-1.76777,0.117707,
+-0.754248,1.08381,-2.15345,
+-3.15415,-0.162292,-1.15347,
+2.55396,-1.68912,1.15698,
+0.159561,1.84202,0.428428,
+-1.58079,2.04207,3.29578,
+-1.05711,-0.843112,-1.98122,
+0.138866,-2.96642,-0.212247,
+2.6778,0.686972,-2.6553,
+-0.498291,-0.362846,-1.0538,
+1.19872,0.0476518,-2.42077,
+-2.3972,1.40393,-0.1943,
+0.85034,-1.24222,1.5646,
+0.142174,0.249903,-2.75252,
+1.15197,1.32746,-1.70104,
+0.359387,-1.65115,-2.75243,
+0.357917,-1.36406,2.55102,
+-1.65268,-0.28339,2.75665,
+-3.82681,-3.28984,2.55128,
+-2.61371,1.08247,-0.457068,
+1.67152,-2.25527,2.45819,
+-0.753832,1.1682,-1.95913,
+-2.05131,3.04537,1.91954,
+-0.695378,2.88924,1.41965,
+3.25767,-2.76934,-0.354127,
+-0.746795,1.36034,1.85953,
+0.859135,1.08222,0.959116,
+1.15898,1.32443,3.41981,
+3.67954,0.447177,-0.414029,
+0.907323,2.12852,1.95837,
+-0.683456,-0.247536,1.05621,
+-1.67809,0.641544,-1.31143,
+-1.30192,-0.677394,-1.95159,
+-0.105665,0.365205,-1.2567,
+1.12189,-1.48969,0.957166,
+1.25554,-1.92186,-0.904086,
+0.117786,2.23836,-0.498009,
+-2.85788,0.643364,0.55867,
+-1.66115,2.56146,-2.28632,
+-3.29334,-0.0894367,-0.656519,
+3.15561,-0.769732,1.15695,
+1.25684,0.64652,-2.6002,
+2.65231,-3.52625,1.55617,
+-1.8573,-1.76276,-1.74075,
+-1.55648,1.2592,2.1585,
+-0.555522,2.88068,-2.85423,
+-3.14249,-0.288592,-3.35534,
+2.45413,0.0854903,-2.20507,
+-2.05464,0.887836,-0.658349,
+1.12708,-0.568106,-3.65865,
+-0.59147,-0.685439,0.301612,
+0.473679,0.886411,-1.65386,
+1.65166,0.166741,0.751119,
+-0.299287,1.72233,0.618559,
+1.15181,-0.488026,0.124448,
+0.0561315,1.04877,2.15922,
+0.154258,-0.64401,-1.31179,
+1.75863,-1.88571,-2.8537,
+3.35024,1.28154,-1.05461,
+-3.71738,-2.88631,-1.05314,
+-1.78258,3.08967,0.150476,
+3.47828,-2.524,-2.45502,
+-0.159138,0.160633,-0.338796,
+-2.15885,-0.82959,1.25022,
+-1.95268,-0.841195,-3.19487,
+-0.281381,-0.887435,-3.55807,
+0.415164,0.326482,-1.55411,
+1.92868,-2.84771,-0.556196,
+1.05804,1.32866,0.66596,
+2.46545,1.00747,2.35957,
+-0.77358,0.284677,-1.38805,
+0.851046,0.960742,-2.70934,
+-0.858208,-0.884015,1.16663,
+1.55291,0.282705,-3.18254,
+1.99034,0.286298,-1.75821,
+0.259097,-2.04379,-0.858936,
+-1.5956,2.04693,-1.35234,
+-0.775432,1.24465,1.95935,
+1.65595,-1.04954,-0.954437,
+-2.35417,-1.76095,-0.248306,
+0.855717,-2.92161,3.4496,
+-0.717941,2.52993,1.25007,
+-3.42927,0.673305,0.995742,
+8.03373,-2.05136,4.02113,
+7.88929,-2.2029,5.0036,
+7.61596,-2.44569,4.54892,
+7.41949,-2.64169,3.82339,
+7.21192,-2.87947,4.89423,
+7.08346,-2.38649,4.19212,
+6.90279,-3.33038,4.9273,
+6.78959,-3.55575,3.55127,
+6.57074,-3.75902,3.32517,
+6.30756,-3.40499,3.78366,
+7.90893,-3.3237,2.48012,
+6.24078,-4.04978,3.47459,
+8.0691,-4.6865,4.08057,
+5.98731,-2.26113,2.82166,
+5.46898,-3.99581,3.25024,
+8.1461,-3.34471,3.42168,
+6.8456,-5.00126,2.36145,
+7.62888,-3.82465,2.7879,
+7.18034,-3.94376,2.74348,
+6.02527,-4.36523,2.56247,
+8.64577,-3.04345,2.62974,
+7.82539,-3.6881,2.96164,
+7.10508,-3.6174,4.22416,
+7.64684,-3.88431,3.9336,
+7.46411,-4.21516,3.32001,
+6.98777,-3.94024,3.14694,
+7.36355,-4.24875,1.72061,
+8.42011,-4.52065,2.62078,
+6.04598,-4.48682,2.74494,
+8.7682,-3.9271,3.82815,
+6.76279,-3.58031,2.92525,
+7.14794,-4.42742,2.62365,
+5.32696,-3.28733,3.34916,
+6.43655,-4.60784,2.41548,
+5.66033,-4.98497,3.72282
diff --git a/examples/custominput/doc/images/custominput-example.png b/examples/custominput/doc/images/custominput-example.png
new file mode 100644
index 00000000..083bac58
--- /dev/null
+++ b/examples/custominput/doc/images/custominput-example.png
Binary files differ
diff --git a/examples/custominput/doc/src/custominput.qdoc b/examples/custominput/doc/src/custominput.qdoc
new file mode 100644
index 00000000..9bb5607f
--- /dev/null
+++ b/examples/custominput/doc/src/custominput.qdoc
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+/*!
+ \example custominput
+ \title Custom Input Example
+ \ingroup qtdatavisualization_examples
+ \brief Implementing custom input handler in a widget application.
+
+ The Custom Input example shows how to customize the 3D graph controls in a widget application using a custom graph input handler to capture and process mouse events.
+ The code in this example shows also how the camera is controlled by using QPropertyAnimation to animate the camera and item selection
+ is done on mouseover rather than clicking any mouse buttons. Also the code shows how to implement similar zoom with mouse wheel functionality as the default
+ input handler implements.
+
+ \image custominput-example.png
+
+ \section1 Replacing default input handling
+
+ The default input handling mechanism is replaced by setting the active input handler of \l Q3DScatter
+ to \c CustomInputHandler that implements the custom behavior.
+
+ \snippet ../examples/custominput/scatterdatamodifier.cpp 0
+
+ \section1 Implementing custom selection handling
+
+ The on mouseover selection handling is implemented in the \c CustomInputHandler that captures the mouse events.
+ It then stores the last known coordinates to the \l QAbstract3DInputHandler::inputPosition property.
+
+ \snippet ../examples/custominput/custominputhandler.cpp 0
+
+ As the selection is one shot, and is cleared each time a 3D frame is rendered, a timer is setup to retrigger selection so that the selection moves to the item
+ currently under the mouse cursor as the camera animates around the graph even when the mouse cursor is not moving.
+
+ \snippet ../examples/custominput/scatterdatamodifier.cpp 1
+
+ \section1 Implementing custom zoom handling
+
+ The camera has a zoom factor that represents amount of zoom in percentages. In this example the zoom range is limited
+ between 10% and 500%. This range is then divided to four subranges where \c angleDelta is scaled to different amount of zoom change
+ based on the current subrange.
+
+ \snippet ../examples/custominput/custominputhandler.cpp 1
+
+ \section1 Implementing custom camera handling
+
+ The camera is animated to constantly rotate around the graph with two animations. The rotation around the graph is done with
+ a simple QPropertyAnimation that just increments during 20 seconds from 0 degrees to 360 degrees and sets the \l Q3DCamera::xRotation property.
+
+ \snippet ../examples/custominput/scatterdatamodifier.cpp 2
+
+ The camera movement up and down is implemented with a QSequentialAnimationGroup that varies the \l Q3DCamera::yRotation property of the camera
+ from 5 degrees to 45 degrees and back with in and out easing.
+
+ \snippet ../examples/custominput/scatterdatamodifier.cpp 3
+*/
diff --git a/examples/custominput/main.cpp b/examples/custominput/main.cpp
new file mode 100644
index 00000000..8b1aa033
--- /dev/null
+++ b/examples/custominput/main.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#include "scatterdatamodifier.h"
+
+#include <QApplication>
+#include <QWidget>
+#include <QHBoxLayout>
+#include <QVBoxLayout>
+#include <QPushButton>
+#include <QCheckBox>
+#include <QComboBox>
+#include <QFontComboBox>
+#include <QLabel>
+#include <QScreen>
+#include <QFontDatabase>
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+ Q3DScatter *graph = new Q3DScatter();
+ QWidget *container = QWidget::createWindowContainer(graph);
+
+ QSize screenSize = graph->screen()->size();
+ container->setMinimumSize(QSize(screenSize.width() / 2, screenSize.height() / 1.5));
+ container->setMaximumSize(screenSize);
+ container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ container->setFocusPolicy(Qt::StrongFocus);
+
+ QWidget *widget = new QWidget;
+ QHBoxLayout *hLayout = new QHBoxLayout(widget);
+ QVBoxLayout *vLayout = new QVBoxLayout();
+ hLayout->addWidget(container, 1);
+ hLayout->addLayout(vLayout);
+
+ widget->setWindowTitle(QStringLiteral("Custom Input Handling"));
+
+ QPushButton *cameraButton = new QPushButton(widget);
+ cameraButton->setText(QStringLiteral("Toggle Camera Animation"));
+
+ QComboBox *shadowQuality = new QComboBox(widget);
+ shadowQuality->addItem(QStringLiteral("None"));
+ shadowQuality->addItem(QStringLiteral("Low"));
+ shadowQuality->addItem(QStringLiteral("Medium"));
+ shadowQuality->addItem(QStringLiteral("High"));
+ shadowQuality->addItem(QStringLiteral("Low Soft"));
+ shadowQuality->addItem(QStringLiteral("Medium Soft"));
+ shadowQuality->addItem(QStringLiteral("High Soft"));
+ shadowQuality->setCurrentIndex(2);
+
+ vLayout->addWidget(cameraButton, 0, Qt::AlignTop);
+ vLayout->addWidget(new QLabel(QStringLiteral("Adjust shadow quality")), 0, Qt::AlignTop);
+ vLayout->addWidget(shadowQuality, 1, Qt::AlignTop);
+
+ ScatterDataModifier *modifier = new ScatterDataModifier(graph);
+
+ QObject::connect(cameraButton, &QPushButton::clicked, modifier,
+ &ScatterDataModifier::toggleCameraAnimation);
+
+ QObject::connect(shadowQuality, SIGNAL(currentIndexChanged(int)), modifier,
+ SLOT(changeShadowQuality(int)));
+
+ QObject::connect(modifier, &ScatterDataModifier::shadowQualityChanged, shadowQuality,
+ &QComboBox::setCurrentIndex);
+
+ widget->show();
+ modifier->start();
+ return app.exec();
+}
diff --git a/examples/custominput/scatterdatamodifier.cpp b/examples/custominput/scatterdatamodifier.cpp
new file mode 100644
index 00000000..aabb1b3a
--- /dev/null
+++ b/examples/custominput/scatterdatamodifier.cpp
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#include "scatterdatamodifier.h"
+
+#include <QtDataVisualization/QScatterDataProxy>
+#include <QtDataVisualization/Q3DValueAxis>
+#include <QtDataVisualization/Q3DScene>
+#include <QtDataVisualization/Q3DCamera>
+#include <QtDataVisualization/QScatter3DSeries>
+#include <QtDataVisualization/Q3DTheme>
+#include <qmath.h>
+
+using namespace QtDataVisualization;
+
+ScatterDataModifier::ScatterDataModifier(Q3DScatter *scatter)
+ : m_graph(scatter),
+ m_inputHandler(new CustomInputHandler())
+{
+ m_graph->setTheme(new Q3DTheme(Q3DTheme::ThemeDigia));
+ m_graph->setShadowQuality(QDataVis::ShadowQualityMedium);
+ m_graph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetFront);
+
+ m_graph->setAxisX(new Q3DValueAxis);
+ m_graph->setAxisY(new Q3DValueAxis);
+ m_graph->setAxisZ(new Q3DValueAxis);
+
+ m_graph->axisX()->setRange(-10.0f, 10.0f);
+ m_graph->axisY()->setRange(-5.0f, 5.0f);
+ m_graph->axisZ()->setRange(-5.0f, 5.0f);
+
+ QScatter3DSeries *series = new QScatter3DSeries;
+ series->setItemLabelFormat("@xLabel, @yLabel, @zLabel");
+ series->setMesh(QAbstract3DSeries::MeshCube);
+ series->setItemSize(0.15f);
+ m_graph->addSeries(series);
+
+ //! [2]
+ m_animationCameraX = new QPropertyAnimation(m_graph->scene()->activeCamera(), "xRotation");
+ m_animationCameraX->setDuration(20000);
+ m_animationCameraX->setStartValue(QVariant::fromValue(0.0f));
+ m_animationCameraX->setEndValue(QVariant::fromValue(360.0f));
+ m_animationCameraX->setLoopCount(-1);
+ //! [2]
+
+ //! [3]
+ QPropertyAnimation *upAnimation = new QPropertyAnimation(m_graph->scene()->activeCamera(), "yRotation");
+ upAnimation->setDuration(9000);
+ upAnimation->setStartValue(QVariant::fromValue(5.0f));
+ upAnimation->setEndValue(QVariant::fromValue(45.0f));
+
+ QPropertyAnimation *downAnimation = new QPropertyAnimation(m_graph->scene()->activeCamera(), "yRotation");
+ downAnimation->setDuration(9000);
+ downAnimation->setStartValue(QVariant::fromValue(45.0f));
+ downAnimation->setEndValue(QVariant::fromValue(5.0f));
+
+ m_animationCameraY = new QSequentialAnimationGroup();
+ m_animationCameraY->setLoopCount(-1);
+ m_animationCameraY->addAnimation(upAnimation);
+ m_animationCameraY->addAnimation(downAnimation);
+ //! [3]
+
+ m_animationCameraX->start();
+ m_animationCameraY->start();
+
+ // Give ownership of the handler to the graph and make it the active handler
+ //! [0]
+ m_graph->setActiveInputHandler(m_inputHandler);
+ //! [0]
+
+ //! [1]
+ m_selectionTimer = new QTimer(this);
+ m_selectionTimer->setInterval(10);
+ m_selectionTimer->setSingleShot(false);
+ QObject::connect(m_selectionTimer, &QTimer::timeout, this,
+ &ScatterDataModifier::triggerSelection);
+ m_selectionTimer->start();
+ //! [1]
+}
+
+ScatterDataModifier::~ScatterDataModifier()
+{
+ delete m_graph;
+}
+
+void ScatterDataModifier::start()
+{
+ addData();
+}
+
+void ScatterDataModifier::addData()
+{
+ QVector<QVector3D> itemList;
+
+ // Read data items from the file to QVector
+ QTextStream stream;
+ QFile dataFile(":/data/data.txt");
+ if (dataFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ stream.setDevice(&dataFile);
+ while (!stream.atEnd()) {
+ QString line = stream.readLine();
+ if (line.startsWith("#")) // Ignore comments
+ continue;
+ QStringList strList = line.split(",", QString::SkipEmptyParts);
+ // Each line has three data items: xPos, yPos and zPos value
+ if (strList.size() < 3) {
+ qWarning() << "Invalid row read from data:" << line;
+ continue;
+ }
+ itemList.append(QVector3D(
+ strList.at(0).trimmed().toFloat(),
+ strList.at(1).trimmed().toFloat(),
+ strList.at(2).trimmed().toFloat()));
+ }
+ } else {
+ qWarning() << "Unable to open data file:" << dataFile.fileName();
+ }
+
+ // Add data from the QVector to datamodel
+ QScatterDataArray *dataArray = new QScatterDataArray;
+ dataArray->resize(itemList.count());
+ QScatterDataItem *ptrToDataArray = &dataArray->first();
+ for (int i = 0; i < itemList.count(); i++) {
+ ptrToDataArray->setPosition(itemList.at(i));
+ ptrToDataArray++;
+ }
+
+ m_graph->seriesList().at(0)->dataProxy()->resetArray(dataArray);
+}
+
+void ScatterDataModifier::toggleCameraAnimation()
+{
+ if (m_animationCameraX->state() != QAbstractAnimation::Paused) {
+ m_animationCameraX->pause();
+ m_animationCameraY->pause();
+ } else {
+ m_animationCameraX->resume();
+ m_animationCameraY->resume();
+ }
+}
+
+void ScatterDataModifier::triggerSelection()
+{
+ m_graph->scene()->setSelectionQueryPosition(m_inputHandler->inputPosition());
+}
+
+void ScatterDataModifier::shadowQualityUpdatedByVisual(QDataVis::ShadowQuality sq)
+{
+ int quality = int(sq);
+ emit shadowQualityChanged(quality); // connected to a checkbox in main.cpp
+}
+
+void ScatterDataModifier::changeShadowQuality(int quality)
+{
+ QDataVis::ShadowQuality sq = QDataVis::ShadowQuality(quality);
+ m_graph->setShadowQuality(sq);
+}
diff --git a/examples/custominput/scatterdatamodifier.h b/examples/custominput/scatterdatamodifier.h
new file mode 100644
index 00000000..fc0bc789
--- /dev/null
+++ b/examples/custominput/scatterdatamodifier.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#ifndef SCATTERDATAMODIFIER_H
+#define SCATTERDATAMODIFIER_H
+
+#include "custominputhandler.h"
+
+#include <QtDataVisualization/q3dscatter.h>
+#include <QtGui/QFont>
+#include <QtCore/QTimer>
+#include <QPropertyAnimation>
+#include <QSequentialAnimationGroup>
+#include <QVector3D>
+
+using namespace QtDataVisualization;
+
+class ScatterDataModifier : public QObject
+{
+ Q_OBJECT
+public:
+ explicit ScatterDataModifier(Q3DScatter *scatter);
+ ~ScatterDataModifier();
+
+ void addData();
+ void toggleCameraAnimation();
+ void start();
+
+public slots:
+ void changeShadowQuality(int quality);
+ void shadowQualityUpdatedByVisual(QDataVis::ShadowQuality shadowQuality);
+ void triggerSelection();
+
+signals:
+ void shadowQualityChanged(int quality);
+
+private:
+ Q3DScatter *m_graph;
+ QPropertyAnimation *m_animationCameraX;
+ QSequentialAnimationGroup *m_animationCameraY;
+ CustomInputHandler *m_inputHandler;
+ QTimer *m_selectionTimer;
+};
+
+#endif
diff --git a/examples/customproxy/doc/src/customproxy.qdoc b/examples/customproxy/doc/src/customproxy.qdoc
index be2e2a96..dacedb80 100644
--- a/examples/customproxy/doc/src/customproxy.qdoc
+++ b/examples/customproxy/doc/src/customproxy.qdoc
@@ -37,7 +37,7 @@
of rainfall in that month.
The custom proxy we provide here is similar to item model based proxies provided by Qt
- Data Visualization in that it requires a mapping object to interpret the data.
+ Data Visualization in that it requires a mapping to interpret the data.
Let's take a closer look at the custom classes:
@@ -96,8 +96,8 @@
The primary way to use a \c VariantBarDataMapping object is to give the mappings already at the
constructor, though they can be set later individually or all together with the \c remap() method.
- A signal is emitted if mapping changes. It is basically a simplified version of
- QItemModelBarDataMapping adapted to work with variant lists instead of item models.
+ A signal is emitted if mapping changes. It is basically a simplified version of the mapping
+ functionality of QItemModelBarDataProxy adapted to work with variant lists instead of item models.
\section1 RainfallGraph
diff --git a/examples/customproxy/main.cpp b/examples/customproxy/main.cpp
index 54ea63e9..58b43873 100644
--- a/examples/customproxy/main.cpp
+++ b/examples/customproxy/main.cpp
@@ -26,6 +26,7 @@ int main(int argc, char **argv)
QGuiApplication app(argc, argv);
Q3DBars *rainfall = new Q3DBars;
+ rainfall->setFlags(rainfall->flags() ^ Qt::FramelessWindowHint);
rainfall->resize(1280, 800);
rainfall->setPosition(QPoint(10, 30));
rainfall->show();
diff --git a/examples/customproxy/rainfallgraph.cpp b/examples/customproxy/rainfallgraph.cpp
index 3a9f820a..ad45d016 100644
--- a/examples/customproxy/rainfallgraph.cpp
+++ b/examples/customproxy/rainfallgraph.cpp
@@ -21,6 +21,8 @@
#include <QtDataVisualization/q3dvalueaxis.h>
#include <QtDataVisualization/q3dscene.h>
#include <QtDataVisualization/q3dcamera.h>
+#include <QtDataVisualization/qbar3dseries.h>
+#include <QtDataVisualization/q3dtheme.h>
#include <QGuiApplication>
#include <QFont>
#include <QDebug>
@@ -39,13 +41,14 @@ RainfallGraph::RainfallGraph(Q3DBars *rainfall)
m_columnCount = m_numericMonths.size();
m_proxy = new VariantBarDataProxy;
- m_graph->setActiveDataProxy(m_proxy);
+ QBar3DSeries *series = new QBar3DSeries(m_proxy);
+ m_graph->addSeries(series);
updateYearsList(2000, 2012);
// Set up bar specifications; make the bars as wide as they are deep,
// and add a small space between the bars
- m_graph->setBarThickness(1.0);
+ m_graph->setBarThickness(1.0f);
m_graph->setBarSpacing(QSizeF(0.2, 0.2));
// Set axis labels and titles
@@ -56,26 +59,26 @@ RainfallGraph::RainfallGraph(Q3DBars *rainfall)
m_graph->valueAxis()->setTitle("rainfall");
m_graph->valueAxis()->setLabelFormat("%d mm");
m_graph->valueAxis()->setSegmentCount(5);
- m_graph->rowAxis()->setCategoryLabels(m_years);
- m_graph->columnAxis()->setCategoryLabels(months);
+ m_graph->rowAxis()->setLabels(m_years);
+ m_graph->columnAxis()->setLabels(months);
// Set bar type to cylinder
- m_graph->setBarType(QDataVis::MeshStyleCylinders, false);
+ series->setMesh(QAbstract3DSeries::MeshCylinder);
// Set shadows to medium
m_graph->setShadowQuality(QDataVis::ShadowQualityMedium);
- // Set font
- m_graph->setFont(QFont("Century Gothic", 30));
-
// Set selection mode to bar and column
- m_graph->setSelectionMode(QDataVis::SelectionModeSliceColumn);
+ m_graph->setSelectionMode(QDataVis::SelectionItemAndColumn | QDataVis::SelectionSlice);
// Set theme
- m_graph->setTheme(QDataVis::ThemeArmyBlue);
+ m_graph->setTheme(new Q3DTheme(Q3DTheme::ThemeArmyBlue));
+
+ // Set font to theme
+ m_graph->theme()->setFont(QFont("Century Gothic", 30));
// Set camera position and zoom
- m_graph->scene()->activeCamera()->setCameraPreset(QDataVis::CameraPresetIsometricRightHigh);
+ m_graph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetIsometricRightHigh);
m_graph->scene()->activeCamera()->setZoomLevel(75);
// Set window title
diff --git a/examples/customproxy/variantbardataproxy.cpp b/examples/customproxy/variantbardataproxy.cpp
index 887115b8..2997810f 100644
--- a/examples/customproxy/variantbardataproxy.cpp
+++ b/examples/customproxy/variantbardataproxy.cpp
@@ -118,7 +118,7 @@ void VariantBarDataProxy::resolveDataSet()
const QStringList &columnList = m_mapping->columnCategories();
// Sort values into rows and columns
- typedef QHash<QString, qreal> ColumnValueMap;
+ typedef QHash<QString, float> ColumnValueMap;
QHash <QString, ColumnValueMap> itemValueMap;
foreach (const VariantDataItem *item, itemList) {
itemValueMap[item->at(rowIndex).toString()][item->at(columnIndex).toString()]
diff --git a/examples/examples.pri b/examples/examples.pri
index bfce7b0d..ca91aad0 100644
--- a/examples/examples.pri
+++ b/examples/examples.pri
@@ -22,6 +22,7 @@ QT += datavisualization
contains(TARGET, qml.*) {
uri = QtDataVisualization
lib_name = datavisualizationqml2
+ vis_lib_name = DataVisualization
uri_replaced = $$replace(uri, \\., $$QMAKE_DIR_SEP)
make_qmldir_path = $$DESTDIR/$$uri_replaced
@@ -57,6 +58,7 @@ contains(TARGET, qml.*) {
} else {
# linux, android
src_lib = lib$${lib_name}.so
+ vis_src_lib = lib$${vis_lib_name}.so
}
}
copy_lib.target = $$make_qmldir_path/$$src_lib
@@ -73,6 +75,9 @@ contains(TARGET, qml.*) {
android_qmldir.path = /assets/qml/$$uri_replaced
android_qmlplugin.files = $$copy_lib.target
android_qmlplugin.path = $$target.path
+ vis_lib_dir = $$OUT_PWD/../../lib/$$vis_src_lib
+ vis_lib_formatted = $$replace(vis_lib_dir, /, $$QMAKE_DIR_SEP)
+ ANDROID_EXTRA_LIBS = $$vis_lib_formatted
INSTALLS += android_qmldir android_qmlplugin
}
}
diff --git a/examples/examples.pro b/examples/examples.pro
index 7d9f306a..d126b26d 100644
--- a/examples/examples.pro
+++ b/examples/examples.pro
@@ -1,9 +1,11 @@
TEMPLATE = subdirs
SUBDIRS += qmlbars \
qmlscatter \
- qmlsurface
+ qmlsurface \
+ qmlcustominput
!android: {
SUBDIRS += bars \
+ custominput \
customproxy \
itemmodel \
scatter \
diff --git a/examples/itemmodel/doc/src/itemmodel.qdoc b/examples/itemmodel/doc/src/itemmodel.qdoc
index 682ebb1f..6812c374 100644
--- a/examples/itemmodel/doc/src/itemmodel.qdoc
+++ b/examples/itemmodel/doc/src/itemmodel.qdoc
@@ -26,9 +26,9 @@
the data being drawn at run-time. The example shows how to:
\list
- \li How to create an application with Q3DBars and widgets
- \li How to use QItemModelBarDataMapping and QItemModelBarDataProxy to set data to the graph
- \li How to use a table widget to modify the data in the graph
+ \li Create an application with Q3DBars and widgets
+ \li Use QItemModelBarDataProxy to set data to the graph
+ \li Use a table widget to modify the data in the graph
\endlist
For instructions about how to interact with the graph, see \l{Qt Data Visualization Interacting with Data}{this page}.
@@ -42,7 +42,7 @@
\snippet ../examples/itemmodel/main.cpp 0
The call to QWidget::createWindowContainer is required, as all data visualization types
- (Q3DBars, Q3DScatter, Q3DSurface) inherit QWindow. Any class inheriting QWindow cannot be used
+ (Q3DBars, Q3DScatter, and Q3DSurface) inherit QWindow. Any class inheriting QWindow cannot be used
as a widget any other way.
Then we'll create a layout and add the graph and the table widget into it:
@@ -52,20 +52,21 @@
The table widget is going to be used to display the numerical data being inserted into the
graph, and to modify it (See \l {Adding data to the graph} and \l {Interacting with the data}).
- We need to instantiate QItemModelBarDataMapping and QItemModelBarDataProxy and give them to the
- graph:
+ We need to instantiate QItemModelBarDataProxy and a QBar3DSeries for it, and give the series
+ to the graph:
\snippet ../examples/itemmodel/main.cpp 2
- Here we tell the mapping object to directly map the model's rows and columns into the proxy's rows and
+ Here we tell the proxy to directly map the model's rows and columns into the proxy's rows and
columns instead of defining row and column roles to map for them. Then we give the model from
- the table widget and the mapping object to the proxy. Finally we set the proxy as the active
- data proxy for the graph.
+ the table widget to the proxy. We also create a series instance and set the proxy to it.
+ We customize the series visuals a bit by changing the object mesh to pyramids, and finally
+ add the series to the graph.
Next, let's create another class to handle the data addition and other interaction with the
- graph. Let's call it GraphDataGenerator (See \l {Setting up the graph} and
- \l {Adding data to the graph} for details) and connect some signals between Q3DBars,
- GraphDataGenerator, and QTableWidget (See \l {Interacting with the data} for a closer look):
+ graph. Let's call it \c GraphDataGenerator (See \l {Setting up the graph} and
+ \l {Adding data to the graph} for details) and connect some signals between QBar3DSeries,
+ \c GraphDataGenerator, and QTableWidget (See \l {Interacting with the data} for a closer look):
\snippet ../examples/itemmodel/main.cpp 3
@@ -75,7 +76,7 @@
\section1 Setting up the graph
- Let's set up the visual attributes for the graph in the constructor of GraphDataGenerator:
+ Let's set up the visual attributes for the graph in the constructor of \c GraphDataGenerator:
\snippet ../examples/itemmodel/main.cpp 5
\snippet ../examples/itemmodel/main.cpp 6
@@ -86,16 +87,17 @@
easily try how changing it affects the graph. The second line sets bar spacings to 0.2, which
means there will be a gap of 20% of the bar's thickness between the bars in both directions.
- Then, we set the bar type to flat pyramids, overriding the default bar type.
We want to be able to select rows of data for a closer inspection, so we set the selection mode
to slice row. This means that whenever we select a bar in the graph, the whole row will be
displayed separately.
+ We don't want to use the default colors, so we set one of the predefined themes as the active theme.
+
Next line sets the font to \c Impact. If your system doesn't have it, it will be replaced by
the system default.
- And finally, we set theme to \c Digia and camera position to \c {Preset Front}. Now the initial
- graph settings are done.
+ And finally, we set the camera position to one of the predefined camera positions.
+ Now the initial graph settings are done.
\note You do not need to set any of these in case you're happy with the defaults. You can
easily try them by commenting out the contents of the constructor.
@@ -119,8 +121,8 @@
The main thing \c start() does is set up the data model. It also activates a timer for getting
the accurate dimensions of the table widget after it's been filled with data. The reason we
do this is that the widget doesn't know its final visual domensions until all the data has been
- inserted to it and it has been shown. The whole data timer implementation is not vital for the
- application, so we won't take a closer look at it. It's just there to make the table look better.
+ inserted to it and it has been shown. The data timer usage is not vital for the
+ application, so we won't take a closer look at it. It's just there to make QTableWidget look better.
In \c setupModel() we first introduce the row and column labels, and the actual data:
@@ -130,10 +132,6 @@
\snippet ../examples/itemmodel/main.cpp 10
- The other lines there are pretty self-explanatory except for the one with the segment count.
- We're setting it to five as we want the value axis (the Y-axis) to show more values than just
- the lowest and the highest.
-
Next we will set up the table widget:
\snippet ../examples/itemmodel/main.cpp 11
@@ -149,11 +147,10 @@
\snippet ../examples/itemmodel/main.cpp 2
- We created QItemModelBarDataMapping and QItemModelBarDataProxy instances, and gave the proxy
- the model of the table widget and the model mapping we just created. Then we set the proxy as
- the active proxy for the graph. The proxy maps the rows and the columns in the model of the table
- widget into rows and columns for itself using the model mapping, and the graph gets the data
- to be displayed from its active proxy.
+ We created QItemModelBarDataProxy instance, and gave the proxy the model of the table widget
+ we just created. The proxy maps the rows and the columns in the model of the table widget into
+ rows and columns for itself directly, as we set the QItemModelBarDataProxy::useModelCategories
+ property to true, and the graph gets the data to be displayed via the series that owns the proxy.
\section1 Interacting with the data
@@ -163,19 +160,19 @@
Now we'll find out what these were for.
- The first one connects a signal from Q3DBars to the GraphDataGenerator. Signal
- Q3DBars::selectedBarPosChanged() is emitted when a bar is selected from the graph. We connect
+ The first one connects a signal from Q3DBars to the \c GraphDataGenerator. Signal
+ QBar3DSeries::selectedBarChanged() is emitted when a bar is selected from the series. We connect
that to a method in the data generator that selects the same data item in the table widget:
\snippet ../examples/itemmodel/main.cpp 13
The second connection does the opposite; it connects a signal from the table widget to a
- method in the data generator. The method then selects the corresponding bar in the graph:
+ method in the data generator. The method then selects the corresponding bar in the series:
\snippet ../examples/itemmodel/main.cpp 14
You can even select an item in the widget and change the value of it, and the new value is
- updated to the graph. This is handled again by the active proxy with mapping between the data
+ updated to the graph. This is handled again by the proxy with mapping between the data
in the table widget and itself.
\image itemmodel-example.png
diff --git a/examples/itemmodel/main.cpp b/examples/itemmodel/main.cpp
index fac6b442..46aa8bb8 100644
--- a/examples/itemmodel/main.cpp
+++ b/examples/itemmodel/main.cpp
@@ -22,6 +22,8 @@
#include <QtDataVisualization/q3dvalueaxis.h>
#include <QtDataVisualization/q3dscene.h>
#include <QtDataVisualization/q3dcamera.h>
+#include <QtDataVisualization/qbar3dseries.h>
+#include <QtDataVisualization/q3dtheme.h>
#include <QApplication>
#include <QVBoxLayout>
@@ -76,12 +78,8 @@ GraphDataGenerator::GraphDataGenerator(Q3DBars *bargraph, QTableWidget *tableWid
//! [5]
// Set up bar specifications; make the bars as wide as they are deep,
// and add a small space between them
- m_graph->setBarThickness(1.0);
+ m_graph->setBarThickness(1.0f);
m_graph->setBarSpacing(QSizeF(0.2, 0.2));
-
- // Set bar type to flat pyramids
- m_graph->setBarType(QDataVis::MeshStylePyramids, false);
-
//! [5]
#ifndef USE_STATIC_DATA
@@ -90,7 +88,7 @@ GraphDataGenerator::GraphDataGenerator(Q3DBars *bargraph, QTableWidget *tableWid
m_tableWidget->setColumnCount(m_columnCount);
// Set selection mode to full
- m_graph->setSelectionMode(QDataVis::SelectionModeItemRowAndColumn);
+ m_graph->setSelectionMode(QDataVis::SelectionItemRowAndColumn);
// Hide axis labels by explicitly setting one empty string as label list
m_graph->rowAxis()->setCategoryLabels(QStringList(QString()));
@@ -101,10 +99,7 @@ GraphDataGenerator::GraphDataGenerator(Q3DBars *bargraph, QTableWidget *tableWid
//! [6]
// Set selection mode to slice row
- m_graph->setSelectionMode(QDataVis::SelectionModeSliceRow);
-
- // Set font
- m_graph->setFont(QFont("Impact", 20));
+ m_graph->setSelectionMode(QDataVis::SelectionItemAndRow | QDataVis::SelectionSlice);
//! [6]
#endif
@@ -112,10 +107,13 @@ GraphDataGenerator::GraphDataGenerator(Q3DBars *bargraph, QTableWidget *tableWid
//! [7]
// Set theme
- m_graph->setTheme(QDataVis::ThemeDigia);
+ m_graph->setTheme(new Q3DTheme(Q3DTheme::ThemeDigia));
+
+ // Set font
+ m_graph->theme()->setFont(QFont("Impact", 20));
// Set preset camera position
- m_graph->scene()->activeCamera()->setCameraPreset(QDataVis::CameraPresetFront);
+ m_graph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetFront);
//! [7]
}
@@ -159,11 +157,11 @@ void GraphDataGenerator::setupModel()
weeks << "week 1" << "week 2" << "week 3" << "week 4" << "week 5";
// Set up data Mon Tue Wed Thu Fri Sat Sun
- qreal hours[5][7] = {{2.0, 1.0, 3.0, 0.2, 1.0, 5.0, 10.0}, // week 1
- {0.5, 1.0, 3.0, 1.0, 2.0, 2.0, 3.0}, // week 2
- {1.0, 1.0, 2.0, 1.0, 4.0, 4.0, 4.0}, // week 3
- {0.0, 1.0, 0.0, 0.0, 2.0, 2.0, 0.3}, // week 4
- {3.0, 3.0, 6.0, 2.0, 2.0, 1.0, 1.0}}; // week 5
+ float hours[5][7] = {{2.0f, 1.0f, 3.0f, 0.2f, 1.0f, 5.0f, 10.0f}, // week 1
+ {0.5f, 1.0f, 3.0f, 1.0f, 2.0f, 2.0f, 3.0f}, // week 2
+ {1.0f, 1.0f, 2.0f, 1.0f, 4.0f, 4.0f, 4.0f}, // week 3
+ {0.0f, 1.0f, 0.0f, 0.0f, 2.0f, 2.0f, 0.3f}, // week 4
+ {3.0f, 3.0f, 6.0f, 2.0f, 2.0f, 1.0f, 1.0f}}; // week 5
//! [9]
// Add labels
@@ -171,7 +169,6 @@ void GraphDataGenerator::setupModel()
m_graph->rowAxis()->setTitle("Week of year");
m_graph->columnAxis()->setTitle("Day of week");
m_graph->valueAxis()->setTitle("Hours spent on the Internet");
- m_graph->valueAxis()->setSegmentCount(5);
m_graph->valueAxis()->setLabelFormat("%.1f h");
//! [10]
@@ -203,7 +200,7 @@ void GraphDataGenerator::addRow()
for (int i = 0; i < m_columnCount; i++) {
QModelIndex index = m_tableWidget->model()->index(0, i);
m_tableWidget->model()->setData(index,
- ((qreal)i / (qreal)m_columnCount) / 2.0 + (qreal)(rand() % 30) / 100.0);
+ ((float)i / (float)m_columnCount) / 2.0f + (float)(rand() % 30) / 100.0f);
}
m_tableWidget->resizeColumnsToContents();
}
@@ -222,7 +219,7 @@ void GraphDataGenerator::selectedFromTable(int currentRow, int currentColumn,
{
Q_UNUSED(previousRow)
Q_UNUSED(previousColumn)
- m_graph->setSelectedBarPos(QPoint(currentRow, currentColumn));
+ m_graph->seriesList().at(0)->setSelectedBar(QPoint(currentRow, currentColumn));
}
//! [14]
@@ -264,16 +261,17 @@ int main(int argc, char **argv)
//! [2]
// Since we are dealing with QTableWidget, the model will already have data sorted properly
- // in rows and columns, so create a mapping to utilize this.
- QItemModelBarDataMapping *mapping = new QItemModelBarDataMapping;
- mapping->setUseModelCategories(true);
- QItemModelBarDataProxy *proxy = new QItemModelBarDataProxy(tableWidget->model(), mapping);
- graph->setActiveDataProxy(proxy);
+ // into rows and columns, so we simply set useModelCategories property to true to utilize this.
+ QItemModelBarDataProxy *proxy = new QItemModelBarDataProxy(tableWidget->model());
+ proxy->setUseModelCategories(true);
+ QBar3DSeries *series = new QBar3DSeries(proxy);
+ series->setMesh(QAbstract3DSeries::MeshPyramid);
+ graph->addSeries(series);
//! [2]
//! [3]
GraphDataGenerator generator(graph, tableWidget);
- QObject::connect(graph, &Q3DBars::selectedBarPosChanged, &generator,
+ QObject::connect(series, &QBar3DSeries::selectedBarChanged, &generator,
&GraphDataGenerator::selectFromTable);
QObject::connect(tableWidget, &QTableWidget::currentCellChanged, &generator,
&GraphDataGenerator::selectedFromTable);
diff --git a/examples/qmlbars/doc/images/qmlbars-example.png b/examples/qmlbars/doc/images/qmlbars-example.png
index 159b9b7c..00fb4a4f 100644
--- a/examples/qmlbars/doc/images/qmlbars-example.png
+++ b/examples/qmlbars/doc/images/qmlbars-example.png
Binary files differ
diff --git a/examples/qmlbars/doc/src/qmlbars.qdoc b/examples/qmlbars/doc/src/qmlbars.qdoc
index 9f51f89e..d56253d0 100644
--- a/examples/qmlbars/doc/src/qmlbars.qdoc
+++ b/examples/qmlbars/doc/src/qmlbars.qdoc
@@ -27,9 +27,9 @@
\image qmlbars-example.png
- The interesting thing about this example is remapping the data, so we concentrate on that
- and skip explaining the basic Bars3D functionality - for more detailed QML example documentation,
- see \l{Qt Quick 2 Scatter Example}.
+ The interesting thing about this example is switching series and displaying more than one series
+ at once. We'll concentrate on those and skip explaining the basic Bars3D functionality - for
+ more detailed QML example documentation, see \l{Qt Quick 2 Scatter Example}.
\section1 Data
@@ -37,17 +37,27 @@
The data is defined in a list model in \c data.qml like this:
\snippet ../examples/qmlbars/qml/qmlbars/data.qml 0
- \dots 4
+ \dots
Each data item has four roles: year, month, income, and expenses. Years and months are natural to
- map to rows and columns of a bar chart, but we can only show either income or expenses as the value.
- We choose to default to showing expenses when we initialize the mapping item:
+ map to rows and columns of a bar chart, but we can only show either income or expenses as the
+ value.
- \snippet ../examples/qmlbars/qml/qmlbars/data.qml 1
+ Now we need to add the data to the Bars3D graph. We will create two Bar3DSeries inside it,
+ starting with a series for the income:
- Final piece we need for handling data is the proxy to bring the model and mapping together:
+ \snippet ../examples/qmlbars/qml/qmlbars/main.qml 3
+ \dots
- \snippet ../examples/qmlbars/qml/qmlbars/data.qml 2
+ The data is attached to the \c itemModel property of the ItemModelBarDataProxy inside the
+ series.
+
+ Then we add another series for the expenses:
+
+ \snippet ../examples/qmlbars/qml/qmlbars/main.qml 4
+ \dots
+
+ We use the \c visible property of the series to hide the second series for now.
\section1 Custom axis labels
@@ -57,12 +67,12 @@
\snippet ../examples/qmlbars/qml/qmlbars/axes.qml 0
- \section1 Using mapping
+ \section1 Switching series
In the \c main.qml, we set up the graph and various UI elements. There are three interesting
- mapping related code blocks we want to highlight here. The first one shows how to change the
- visualized data from expenses to income, and vice versa, by simply changing the value role on the
- BarDataMapping item:
+ code blocks we want to highlight here. The first one shows how to change the
+ visualized data between income, expenses, and both, by simply changing visibility of the two
+ series:
\snippet ../examples/qmlbars/qml/qmlbars/main.qml 0
@@ -73,11 +83,11 @@
\snippet ../examples/qmlbars/qml/qmlbars/main.qml 1
- The filtering is done by setting \c autoRowCategories to false on the BarDataMapping item and defining
+ The filtering is done by setting \c autoRowCategories to false on the ItemModelBarDataProxy item and defining
the row categories explicitly. This way, only the items in specified rows are visualized.
The third interesting block shows how to get the row and column index of an item if you know the
- row and column values by using BarDataMapping methods \c rowCategoryIndex() and \c columnCategoryIndex():
+ row and column values by using ItemModelBarDataProxy methods \c rowCategoryIndex() and \c columnCategoryIndex():
\snippet ../examples/qmlbars/qml/qmlbars/main.qml 2
*/
diff --git a/examples/qmlbars/main.cpp b/examples/qmlbars/main.cpp
index 58cd5e32..889e2fa4 100644
--- a/examples/qmlbars/main.cpp
+++ b/examples/qmlbars/main.cpp
@@ -29,6 +29,17 @@ int main(int argc, char *argv[])
QGuiApplication app(argc, argv);
QtQuick2ApplicationViewer viewer;
+
+#if !defined(QT_OPENGL_ES_2)
+ // Enable antialiasing
+ QSurfaceFormat surfaceFormat;
+ surfaceFormat.setDepthBufferSize(24);
+ surfaceFormat.setSamples(8);
+ surfaceFormat.setRenderableType(QSurfaceFormat::OpenGL);
+ surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
+ viewer.setFormat(surfaceFormat);
+#endif
+
#ifdef Q_OS_ANDROID
viewer.addImportPath(QString::fromLatin1("assets:/qml"));
viewer.engine()->addPluginPath(QString::fromLatin1("%1/../%2").arg(QDir::homePath(),
diff --git a/examples/qmlbars/qml/qmlbars/axes.qml b/examples/qmlbars/qml/qmlbars/axes.qml
index b6134e09..f5eb8d26 100644
--- a/examples/qmlbars/qml/qmlbars/axes.qml
+++ b/examples/qmlbars/qml/qmlbars/axes.qml
@@ -31,7 +31,7 @@ Item {
//! [0]
CategoryAxis3D {
id: columnAxis
- categoryLabels: ["January", "February", "March", "April", "May", "June",
+ labels: ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"]
}
//! [0]
diff --git a/examples/qmlbars/qml/qmlbars/data.qml b/examples/qmlbars/qml/qmlbars/data.qml
index 210eedde..5a17bcd1 100644
--- a/examples/qmlbars/qml/qmlbars/data.qml
+++ b/examples/qmlbars/qml/qmlbars/data.qml
@@ -20,25 +20,8 @@ import QtQuick 2.1
import QtDataVisualization 1.0
Item {
- property alias mapping: valueMapping
property alias model: dataModel
- property alias proxy: modelProxy
- //! [1]
- BarDataMapping {
- id: valueMapping
- rowRole: "year"
- columnRole: "month"
- valueRole: "expenses"
- }
- //! [1]
- //! [2]
- ItemModelBarDataProxy {
- id: modelProxy
- activeMapping: valueMapping
- itemModel: dataModel
- }
- //! [2]
//! [0]
ListModel {
id: dataModel
diff --git a/examples/qmlbars/qml/qmlbars/main.qml b/examples/qmlbars/qml/qmlbars/main.qml
index 78102023..1f8c1a3d 100644
--- a/examples/qmlbars/qml/qmlbars/main.qml
+++ b/examples/qmlbars/qml/qmlbars/main.qml
@@ -18,7 +18,9 @@
import QtQuick 2.1
import QtQuick.Controls 1.0
+import QtQuick.Layouts 1.0
import QtDataVisualization 1.0
+import QtQuick.Window 2.0
import "."
Item {
@@ -27,6 +29,9 @@ Item {
height: 1024
visible: true
+ property int buttonLayoutHeight: 180;
+ state: Screen.width < Screen.height ? "portrait" : "landscape"
+
Data {
id: graphData
}
@@ -35,134 +40,265 @@ Item {
id: graphAxes
}
+ property Bar3DSeries selectedSeries
+ selectedSeries: barSeries
+
+ function handleSelectionChange(series, position) {
+ if (position != series.invalidSelectionPosition()) {
+ selectedSeries = series
+ }
+
+ // Set tableView current row to selected bar
+ var rowRole = series.dataProxy.rowLabels[position.x];
+ var colRole = series.dataProxy.columnLabels[position.y];
+ var currentRow = tableView.currentRow
+ if (currentRow === -1 || rowRole !== graphData.model.get(currentRow).year
+ || colRole !== graphData.model.get(currentRow).month) {
+ var totalRows = tableView.rowCount;
+ for (var i = 0; i < totalRows; i++) {
+ var currentRowRole = graphData.model.get(i).year
+ var currentColRole = graphData.model.get(i).month
+ if (currentRowRole === rowRole && currentColRole === colRole) {
+ tableView.currentRow = i
+ // Workaround to 5.2 row selection issue
+ if (typeof tableView.selection != "undefined") {
+ tableView.selection.clear()
+ tableView.selection.select(i)
+ }
+ break
+ }
+ }
+ }
+ }
+
Item {
id: dataView
- width: parent.width - tableView.width
- height: parent.height
- anchors.right: parent.right;
+ anchors.right: mainview.right;
+ anchors.bottom: mainview.bottom
Bars3D {
id: testGraph
width: dataView.width
height: dataView.height
shadowQuality: AbstractGraph3D.ShadowQualityMedium
- selectionMode: AbstractGraph3D.SelectionModeItem
- font.pointSize: 35
- theme: AbstractGraph3D.ThemeRetro
- labelStyle: AbstractGraph3D.LabelStyleFromTheme
- dataProxy: graphData.proxy
- barThickness: 0.5
+ selectionMode: AbstractGraph3D.SelectionItem
+ theme: Theme3D {
+ type: Theme3D.ThemeRetro
+ labelBorderEnabled: true
+ font.pointSize: 35
+ labelBackgroundEnabled: true
+ colorStyle: Theme3D.ColorStyleRangeGradient
+ singleHighlightGradient: customGradient
+
+ ColorGradient {
+ id: customGradient
+ ColorGradientStop { position: 1.0; color: "#FFFF00" }
+ ColorGradientStop { position: 0.0; color: "#808000" }
+ }
+ }
+ barThickness: 0.7
barSpacing: Qt.size(0.5, 0.5)
barSpacingRelative: false
- scene.activeCamera.cameraPreset: AbstractGraph3D.CameraPresetRight
+ scene.activeCamera.cameraPreset: Camera3D.CameraPresetIsometricLeftHigh
columnAxis: graphAxes.column
- valueAxis: graphAxes.expenses
- itemLabelFormat: "@valueTitle for @colLabel, @rowLabel: @valueLabel"
-
- onSelectedBarPosChanged: {
- // Set tableView current row to selected bar
- var rowRole = graphData.proxy.rowLabels[position.x];
- var colRole = graphData.proxy.columnLabels[position.y];
- var currentRow = tableView.currentRow
- if (currentRow === -1 || rowRole !== graphData.model.get(currentRow).year
- || colRole !== graphData.model.get(currentRow).month) {
- var totalRows = tableView.rowCount;
- for (var i = 0; i < totalRows; i++) {
- var currentRowRole = graphData.model.get(i).year
- var currentColRole = graphData.model.get(i).month
- if (currentRowRole === rowRole && currentColRole === colRole) {
- tableView.currentRow = i
- // Workaround to 5.2 row selection issue
- if (typeof tableView.selection != "undefined") {
- tableView.selection.clear()
- tableView.selection.select(i)
- }
- break
- }
- }
+ valueAxis: graphAxes.income
+
+ //! [3]
+ Bar3DSeries {
+ id: barSeries
+ itemLabelFormat: "Income for @colLabel, @rowLabel: @valueLabel"
+ baseGradient: barGradient
+
+ ItemModelBarDataProxy {
+ id: modelProxy
+ itemModel: graphData.model
+ rowRole: "year"
+ columnRole: "month"
+ valueRole: "income"
}
- }
- }
- }
+ //! [3]
- Button {
- id: mappingToggle
- anchors.bottom: parent.bottom
- width: tableView.width
- height: 60
- text: "Show Income"
- //! [0]
- onClicked: {
- if (graphData.mapping.valueRole === "expenses") {
- graphData.mapping.valueRole = "income"
- text = "Show Expenses"
- testGraph.valueAxis = graphAxes.income
- } else {
- graphData.mapping.valueRole = "expenses"
- text = "Show Income"
- testGraph.valueAxis = graphAxes.expenses
- }
- }
- //! [0]
- }
+ ColorGradient {
+ id: barGradient
+ ColorGradientStop { position: 1.0; color: "#00FF00" }
+ ColorGradientStop { position: 0.0; color: "#006000" }
+ }
- Button {
- id: shadowToggle
- anchors.bottom: mappingToggle.top
- width: tableView.width
- height: 60
- text: "Hide Shadows"
- onClicked: {
- if (testGraph.shadowQuality == AbstractGraph3D.ShadowQualityNone) {
- testGraph.shadowQuality = AbstractGraph3D.ShadowQualityMedium;
- text = "Hide Shadows"
- } else {
- testGraph.shadowQuality = AbstractGraph3D.ShadowQualityNone;
- text = "Show Shadows"
+ onSelectedBarChanged: handleSelectionChange(barSeries, position)
}
- }
- }
- Button {
- id: dataToggle
- anchors.bottom: shadowToggle.top
- width: tableView.width
- height: 60
- text: "Show 2010 - 2012"
- //! [1]
- onClicked: {
- if (testGraph.rowAxis.max !== 6) {
- text = "Show 2010 - 2012"
- graphData.mapping.autoRowCategories = true
- } else {
- text = "Show all years"
- // Explicitly defining row categories, since we do not want to show data for
- // all years in the model, just for the selected ones.
- graphData.mapping.autoRowCategories = false
- graphData.mapping.rowCategories = ["2010", "2011", "2012"]
+ //! [4]
+ Bar3DSeries {
+ id: secondarySeries
+ visible: false
+ itemLabelFormat: "Expenses for @colLabel, @rowLabel: @valueLabel"
+ baseGradient: secondaryGradient
+
+ ItemModelBarDataProxy {
+ id: secondaryProxy
+ itemModel: graphData.model
+ rowRole: "year"
+ columnRole: "month"
+ valueRole: "expenses"
+ }
+ //! [4]
+
+ ColorGradient {
+ id: secondaryGradient
+ ColorGradientStop { position: 1.0; color: "#FF0000" }
+ ColorGradientStop { position: 0.0; color: "#600000" }
+ }
+
+ onSelectedBarChanged: handleSelectionChange(secondarySeries, position)
}
}
- //! [1]
}
TableView {
id: tableView
- x: 0
- y: 0
- width: 298
- height: parent.height - mappingToggle.height - shadowToggle.height - dataToggle.height
- TableViewColumn{ role: "year" ; title: "Year" ; width: 80 }
- TableViewColumn{ role: "month" ; title: "Month" ; width: 80 }
- TableViewColumn{ role: "expenses" ; title: "Expenses" ; width: 60 }
- TableViewColumn{ role: "income" ; title: "Income" ; width: 60 }
+ anchors.top: parent.top
+ anchors.left: parent.left
+ TableViewColumn{ role: "year" ; title: "Year" ; width: tableView.width / 4 }
+ TableViewColumn{ role: "month" ; title: "Month" ; width: tableView.width / 4 }
+ TableViewColumn{ role: "expenses" ; title: "Expenses" ; width: tableView.width / 4 }
+ TableViewColumn{ role: "income" ; title: "Income" ; width: tableView.width / 4 }
model: graphData.model
//! [2]
onCurrentRowChanged: {
- var rowIndex = graphData.proxy.activeMapping.rowCategoryIndex(graphData.model.get(currentRow).year)
- var colIndex = graphData.proxy.activeMapping.columnCategoryIndex(graphData.model.get(currentRow).month)
- testGraph.selectedBarPos = Qt.point(rowIndex, colIndex)
+ var rowIndex = modelProxy.rowCategoryIndex(graphData.model.get(currentRow).year)
+ var colIndex = modelProxy.columnCategoryIndex(graphData.model.get(currentRow).month)
+ if (selectedSeries.visible)
+ mainview.selectedSeries.selectedBar = Qt.point(rowIndex, colIndex)
+ else if (barSeries.visible)
+ barSeries.selectedBar = Qt.point(rowIndex, colIndex)
+ else
+ secondarySeries.selectedBar = Qt.point(rowIndex, colIndex)
}
//! [2]
}
+
+ ColumnLayout {
+ id: controlLayout
+ spacing: 0
+
+ Button {
+ id: dataToggle
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ text: "Show 2010 - 2012"
+ clip: true
+ //! [1]
+ onClicked: {
+ if (testGraph.rowAxis.max !== 6) {
+ text = "Show 2010 - 2012"
+ modelProxy.autoRowCategories = true
+ secondaryProxy.autoRowCategories = true
+ } else {
+ text = "Show all years"
+ // Explicitly defining row categories, since we do not want to show data for
+ // all years in the model, just for the selected ones.
+ modelProxy.autoRowCategories = false
+ secondaryProxy.autoRowCategories = false
+ modelProxy.rowCategories = ["2010", "2011", "2012"]
+ secondaryProxy.rowCategories = ["2010", "2011", "2012"]
+ }
+ }
+ //! [1]
+ }
+
+ Button {
+ id: shadowToggle
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ text: "Hide Shadows"
+ clip: true
+ onClicked: {
+ if (testGraph.shadowQuality == AbstractGraph3D.ShadowQualityNone) {
+ testGraph.shadowQuality = AbstractGraph3D.ShadowQualityMedium;
+ text = "Hide Shadows"
+ } else {
+ testGraph.shadowQuality = AbstractGraph3D.ShadowQualityNone;
+ text = "Show Shadows"
+ }
+ }
+ }
+
+ Button {
+ id: seriesToggle
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ text: "Show Expenses"
+ clip: true
+ //! [0]
+ onClicked: {
+ if (!secondarySeries.visible) {
+ text = "Show Both"
+ testGraph.valueAxis = graphAxes.expenses
+ barSeries.visible = false
+ secondarySeries.visible = true
+ } else if (!barSeries.visible){
+ barSeries.visible = true
+ text = "Show Income"
+ testGraph.valueAxis = graphAxes.income
+ } else {
+ secondarySeries.visible = false
+ text = "Show Expenses"
+ testGraph.valueAxis = graphAxes.income
+ }
+ }
+ //! [0]
+ }
+ }
+
+ states: [
+ State {
+ name: "landscape"
+ PropertyChanges {
+ target: dataView
+ width: mainview.width / 4 * 3
+ height: mainview.height
+ }
+ PropertyChanges {
+ target: tableView
+ height: mainview.height - buttonLayoutHeight
+ anchors.right: dataView.left
+ anchors.left: mainview.left
+ anchors.bottom: undefined
+ }
+ PropertyChanges {
+ target: controlLayout
+ width: mainview.width / 4
+ height: buttonLayoutHeight
+ anchors.top: tableView.bottom
+ anchors.bottom: mainview.bottom
+ anchors.left: mainview.left
+ anchors.right: dataView.left
+ }
+ },
+ State {
+ name: "portrait"
+ PropertyChanges {
+ target: dataView
+ width: mainview.height / 4 * 3
+ height: mainview.width
+ }
+ PropertyChanges {
+ target: tableView
+ height: mainview.width
+ anchors.right: controlLayout.left
+ anchors.left: mainview.left
+ anchors.bottom: dataView.top
+ }
+ PropertyChanges {
+ target: controlLayout
+ width: mainview.height / 4
+ height: mainview.width / 4
+ anchors.top: mainview.top
+ anchors.bottom: dataView.top
+ anchors.left: undefined
+ anchors.right: mainview.right
+ }
+ }
+ ]
}
diff --git a/examples/qmlbars/qtquick2applicationviewer/qtquick2applicationviewer.pri b/examples/qmlbars/qtquick2applicationviewer/qtquick2applicationviewer.pri
index a071e63d..e5f7990f 100644
--- a/examples/qmlbars/qtquick2applicationviewer/qtquick2applicationviewer.pri
+++ b/examples/qmlbars/qtquick2applicationviewer/qtquick2applicationviewer.pri
@@ -61,6 +61,16 @@ android-no-sdk {
export($$itempath)
INSTALLS += $$item
}
+
+ x86 {
+ target.path = /libs/x86
+ } else: armeabi-v7a {
+ target.path = /libs/armeabi-v7a
+ } else {
+ target.path = /libs/armeabi
+ }
+
+ export(target.path)
INSTALLS += target
} else:win32 {
copyCommand =
diff --git a/examples/qmlcustominput/doc/images/qmlcustominput-example.png b/examples/qmlcustominput/doc/images/qmlcustominput-example.png
new file mode 100644
index 00000000..436f4da5
--- /dev/null
+++ b/examples/qmlcustominput/doc/images/qmlcustominput-example.png
Binary files differ
diff --git a/examples/qmlcustominput/doc/src/qmlcustominput.qdoc b/examples/qmlcustominput/doc/src/qmlcustominput.qdoc
new file mode 100644
index 00000000..14943aa0
--- /dev/null
+++ b/examples/qmlcustominput/doc/src/qmlcustominput.qdoc
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+/*!
+ \example qmlcustominput
+ \title Qt Quick Custom Input Example
+ \ingroup qtdatavisualization_examples
+ \brief Customizing input in a Qt Quick application.
+
+ The Qt Quick Custom Input example shows how to customize the 3D graph controls from Qt Quick using the MouseArea to capture and process mouse events in Qt Quick.
+ Custom input handling code in this example shows how the camera is now controlled by using NumberAnimation to animate the camera and item selection
+ is done on mouseover rather than clicking any mouse buttons. Also the code shows how to implement similar zoom with mouse wheel functionality as the default
+ input handler implements.
+
+ \image qmlcustominput-example.png
+
+ \section1 Removing default input handling
+
+ The default input handling mechanism is disabled by setting the inputHandler property to null.
+
+ \snippet ../examples/qmlcustominput/qml/qmlcustominput/main.qml 0
+ \dots 0
+ \snippet ../examples/qmlcustominput/qml/qmlcustominput/main.qml 1
+ \dots 0
+
+ \section1 Implementing custom selection handling
+
+ The on mouseover selection handling is implemented using standard MouseArea to capture the mouse events.
+ The mouse area is configured to capture hover events and has two custom properties for \c mouseX and \c mouseY
+ to store the last known mouse coordinates.
+
+ \snippet ../examples/qmlcustominput/qml/qmlcustominput/main.qml 2
+
+ Whenever a pointer movement related signal is received the code updates the \c mouseX and \c mouseY properties.
+
+ \snippet ../examples/qmlcustominput/qml/qmlcustominput/main.qml 3
+
+ As the selection is one shot, and is cleared each time a 3D frame is rendered, a timer is setup to retrigger selection so that the selection moves to the item
+ currently under the mouse cursor as the camera animates around the graph even when the mouse cursor is not moving.
+
+ \snippet ../examples/qmlcustominput/qml/qmlcustominput/main.qml 4
+
+ \section1 Implementing custom zoom handling
+
+ The camera has a zoom factor that represents amount of zoom in percentages. In this example the zoom range is limited
+ between 10% and 500%. This range is then divided to four subranges where angleDelta is scaled to different amount of zoom change
+ based on the current subrange.
+
+ \dots
+ \snippet ../examples/qmlcustominput/qml/qmlcustominput/main.qml 5
+ \dots
+
+ \section1 Implementing custom camera handling
+
+ The camera is animated to constantly rotate around the graph with two animations. The rotation around the graph is done with
+ a simple NumberAnimation that just increments during 20 seconds from 0 degrees to 360 degrees and sets the \l Q3DCamera::xRotation property.
+
+ \snippet ../examples/qmlcustominput/qml/qmlcustominput/main.qml 6
+
+ The camera movement up and down is implemented with a SequentialAnimation that varies the \l Q3DCamera::yRotation property of the camera
+ from 5 degrees to 45 degrees and back with in and out easing.
+
+ \snippet ../examples/qmlcustominput/qml/qmlcustominput/main.qml 7
+*/
diff --git a/examples/qmlcustominput/main.cpp b/examples/qmlcustominput/main.cpp
new file mode 100644
index 00000000..8724e511
--- /dev/null
+++ b/examples/qmlcustominput/main.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#include <QtGui/QGuiApplication>
+#include "qtquick2applicationviewer.h"
+#ifdef Q_OS_ANDROID
+#include <QDir>
+#include <QQmlEngine>
+#endif
+#include <QDebug>
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ QtQuick2ApplicationViewer viewer;
+
+#if !defined(QT_OPENGL_ES_2)
+ // Enable antialiasing
+ QSurfaceFormat surfaceFormat;
+ surfaceFormat.setDepthBufferSize(24);
+ surfaceFormat.setSamples(8);
+ surfaceFormat.setRenderableType(QSurfaceFormat::OpenGL);
+ surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
+ viewer.setFormat(surfaceFormat);
+#endif
+
+#ifdef Q_OS_ANDROID
+ viewer.addImportPath(QString::fromLatin1("assets:/qml"));
+ viewer.engine()->addPluginPath(QString::fromLatin1("%1/../%2").arg(QDir::homePath(),
+ QString::fromLatin1("lib")));
+#endif
+ viewer.setTitle(QStringLiteral("QML Custom Input"));
+
+ viewer.setSource(QUrl("qrc:/qml/main.qml"));
+ viewer.setResizeMode(QQuickView::SizeRootObjectToView);
+ viewer.show();
+
+ return app.exec();
+}
diff --git a/examples/qmlcustominput/qml/qmlcustominput/data.qml b/examples/qmlcustominput/qml/qmlcustominput/data.qml
new file mode 100644
index 00000000..1de07998
--- /dev/null
+++ b/examples/qmlcustominput/qml/qmlcustominput/data.qml
@@ -0,0 +1,1088 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import QtDataVisualization 1.0
+
+Item {
+ property alias model: dataModel
+
+ ListModel {
+ id: dataModel
+ ListElement{ xPos: -10.0000; yPos: 5.00000; zPos: -5.00000 }
+ ListElement{ xPos: -9.06229; yPos: 3.07132; zPos: -4.54268 }
+ ListElement{ xPos: -8.55132; yPos: 4.19424; zPos: -4.03318 }
+ ListElement{ xPos: -8.03806; yPos: 4.75162; zPos: -3.99583 }
+ ListElement{ xPos: -9.50337; yPos: 4.90684; zPos: -4.21947 }
+ ListElement{ xPos: -9.93819; yPos: 3.42724; zPos: -3.58955 }
+ ListElement{ xPos: -7.84971; yPos: 3.15272; zPos: -4.90367 }
+ ListElement{ xPos: -7.30477; yPos: 2.91062; zPos: -4.11078 }
+ ListElement{ xPos: -7.11201; yPos: 3.68863; zPos: -4.52683 }
+ ListElement{ xPos: -8.83267; yPos: 2.96504; zPos: -3.61108 }
+ ListElement{ xPos: -6.94874; yPos: 2.49808; zPos: -2.92883 }
+ ListElement{ xPos: -9.02606; yPos: 4.7496; zPos: -4.18193 }
+ ListElement{ xPos: -9.5434; yPos: 3.15534; zPos: -3.83789 }
+ ListElement{ xPos: -6.8679; yPos: 3.66922; zPos: -3.58288 }
+ ListElement{ xPos: -8.16487; yPos: 1.82227; zPos: -4.64523 }
+ ListElement{ xPos: -7.42165; yPos: 3.18192; zPos: -4.22791 }
+ ListElement{ xPos: -7.99257; yPos: 3.06559; zPos: -4.33262 }
+ ListElement{ xPos: -8.98851; yPos: 2.64924; zPos: -4.44595 }
+ ListElement{ xPos: -6.36774; yPos: 3.96697; zPos: -4.38998 }
+ ListElement{ xPos: -7.18413; yPos: 3.32417; zPos: -4.04636 }
+ ListElement{ xPos: -7.91649; yPos: 3.46826; zPos: -2.78126 }
+ ListElement{ xPos: -7.49495; yPos: 3.12306; zPos: -3.14539 }
+ ListElement{ xPos: -7.5445; yPos: 2.85744; zPos: -3.68421 }
+
+ ListElement{ xPos: 2.25354; yPos: 1.36828; zPos: -1.32025 }
+ ListElement{ xPos: -2.35524; yPos: -0.081203; zPos: 1.23267 }
+ ListElement{ xPos: 2.6517; yPos: -1.20549; zPos: 2.73606 }
+ ListElement{ xPos: -2.55382; yPos: 3.48814; zPos: -0.454971 }
+ ListElement{ xPos: -3.85468; yPos: 0.263955; zPos: 0.578276 }
+ ListElement{ xPos: 2.85275; yPos: 1.32315; zPos: 1.0565 }
+ ListElement{ xPos: -0.404099; yPos: -2.36811; zPos: -1.60324 }
+ ListElement{ xPos: 1.58908; yPos: 0.363782; zPos: -0.554303 }
+ ListElement{ xPos: 0.251507; yPos: 0.124637; zPos: -0.752568 }
+ ListElement{ xPos: -2.45626; yPos: -0.722719; zPos: -1.11764 }
+ ListElement{ xPos: 4.15342; yPos: 1.92247; zPos: -0.954975 }
+ ListElement{ xPos: 2.05845; yPos: 0.643191; zPos: -0.121564 }
+ ListElement{ xPos: 0.253468; yPos: 0.814651; zPos: 3.05732 }
+ ListElement{ xPos: 1.51724; yPos: 0.244303; zPos: 2.25864 }
+ ListElement{ xPos: 1.15; yPos: -0.487518; zPos: 0.815931 }
+ ListElement{ xPos: -0.0538979; yPos: 0.124927; zPos: 0.251571 }
+ ListElement{ xPos: 0.941523; yPos: -0.483498; zPos: -3.2731 }
+ ListElement{ xPos: 3.55074; yPos: -1.04714; zPos: -0.954301 }
+ ListElement{ xPos: -2.43125; yPos: -0.964099; zPos: -0.658537 }
+ ListElement{ xPos: 4.25459; yPos: 0.163296; zPos: 2.05563 }
+ ListElement{ xPos: -0.612031; yPos: 1.03234; zPos: -0.227175 }
+ ListElement{ xPos: 0.78338; yPos: -0.847922; zPos: -0.959189 }
+ ListElement{ xPos: -4.20076; yPos: 1.44907; zPos: 0.853836 }
+ ListElement{ xPos: -1.59466; yPos: -1.27511; zPos: -1.5686 }
+ ListElement{ xPos: -3.3567; yPos: -1.96864; zPos: 1.83224 }
+ ListElement{ xPos: -2.75169; yPos: -0.964221; zPos: -1.26465 }
+ ListElement{ xPos: -2.45624; yPos: 0.287046; zPos: -4.55032 }
+ ListElement{ xPos: 2.73649; yPos: -1.48789; zPos: -0.653082 }
+ ListElement{ xPos: 2.73284; yPos: 2.2912; zPos: -2.4933 }
+ ListElement{ xPos: -0.854321; yPos: -2.04288; zPos: 3.7516 }
+ ListElement{ xPos: -1.35708; yPos: -1.84915; zPos: 2.35985 }
+ ListElement{ xPos: -3.25001; yPos: -1.64456; zPos: -4.45419 }
+ ListElement{ xPos: -0.356834; yPos: -0.569139; zPos: -1.75308 }
+ ListElement{ xPos: -0.813569; yPos: -0.287899; zPos: -0.0535036 }
+ ListElement{ xPos: 4.75975; yPos: -1.48817; zPos: -2.45957 }
+ ListElement{ xPos: 4.35294; yPos: 1.46154; zPos: 0.814214 }
+ ListElement{ xPos: -3.22467; yPos: 2.76903; zPos: 0.510435 }
+ ListElement{ xPos: 2.49494; yPos: 1.9286; zPos: 0.552287 }
+ ListElement{ xPos: -0.456521; yPos: 0.688277; zPos: -0.82788 }
+ ListElement{ xPos: -2.72568; yPos: 2.80278; zPos: -2.45782 }
+ ListElement{ xPos: -1.65023; yPos: 1.32005; zPos: -2.05754 }
+ ListElement{ xPos: -1.63551; yPos: 1.88519; zPos: -3.65544 }
+ ListElement{ xPos: -1.20008; yPos: -0.723785; zPos: 0.853563 }
+ ListElement{ xPos: 1.45448; yPos: 1.08701; zPos: 2.17385 }
+ ListElement{ xPos: -3.9042; yPos: -1.16916; zPos: -0.85395 }
+ ListElement{ xPos: 3.15645; yPos: 0.123932; zPos: -0.950988 }
+ ListElement{ xPos: -1.35924; yPos: -2.64015; zPos: -0.54254 }
+ ListElement{ xPos: -4.15753; yPos: 1.28294; zPos: -4.47502 }
+ ListElement{ xPos: -2.7885; yPos: 2.48535; zPos: -0.159651 }
+ ListElement{ xPos: -3.44364; yPos: 0.627232; zPos: 0.611881 }
+ ListElement{ xPos: -1.55639; yPos: -0.967484; zPos: 2.35497 }
+ ListElement{ xPos: -0.752853; yPos: 1.16736; zPos: -0.757871 }
+ ListElement{ xPos: -0.859974; yPos: 0.640213; zPos: -1.75453 }
+ ListElement{ xPos: 0.85744; yPos: 0.480175; zPos: 2.97204 }
+ ListElement{ xPos: 4.0571; yPos: 3.24083; zPos: -0.183622 }
+ ListElement{ xPos: 0.658087; yPos: 0.841418; zPos: 0.357839 }
+ ListElement{ xPos: -2.13027; yPos: 0.920836; zPos: -2.758 }
+ ListElement{ xPos: -0.65825; yPos: 0.164257; zPos: 1.69478 }
+ ListElement{ xPos: -1.88335; yPos: -1.4811; zPos: -2.15408 }
+ ListElement{ xPos: -1.67331; yPos: 2.96982; zPos: 1.85521 }
+ ListElement{ xPos: -0.750937; yPos: 0.282914; zPos: -0.758707 }
+ ListElement{ xPos: 2.29891; yPos: 1.16949; zPos: 2.65927 }
+ ListElement{ xPos: 2.69132; yPos: 2.92632; zPos: -0.206126 }
+ ListElement{ xPos: -1.65771; yPos: 3.28846; zPos: 2.50201 }
+ ListElement{ xPos: -0.568799; yPos: 2.5289; zPos: -1.15875 }
+ ListElement{ xPos: -1.85383; yPos: 0.528953; zPos: -2.32418 }
+ ListElement{ xPos: 0.159422; yPos: -2.36165; zPos: -0.569393 }
+ ListElement{ xPos: -3.96506; yPos: 0.282374; zPos: -0.254519 }
+ ListElement{ xPos: 0.150933; yPos: -3.88058; zPos: -0.759422 }
+ ListElement{ xPos: -1.17917; yPos: -1.96176; zPos: 0.95589 }
+ ListElement{ xPos: -0.340817; yPos: -3.52333; zPos: -1.45715 }
+ ListElement{ xPos: 3.21784; yPos: -2.56593; zPos: 2.55468 }
+ ListElement{ xPos: 0.060965; yPos: -2.44153; zPos: 1.35813 }
+ ListElement{ xPos: 1.4594; yPos: -1.96511; zPos: 0.170228 }
+ ListElement{ xPos: 3.55017; yPos: -2.16882; zPos: 1.75539 }
+ ListElement{ xPos: 2.89487; yPos: -0.727481; zPos: -0.39588 }
+ ListElement{ xPos: -1.65151; yPos: -0.603877; zPos: 0.250508 }
+ ListElement{ xPos: -4.35232; yPos: -1.32155; zPos: -2.31877 }
+ ListElement{ xPos: 2.75852; yPos: -1.88931; zPos: 1.77874 }
+ ListElement{ xPos: 2.75452; yPos: -0.64123; zPos: 2.45546 }
+ ListElement{ xPos: 0.151914; yPos: -0.888395; zPos: -0.260935 }
+ ListElement{ xPos: 0.150593; yPos: 0.0461652; zPos: -0.158206 }
+ ListElement{ xPos: -1.22087; yPos: -2.92034; zPos: -3.78604 }
+ ListElement{ xPos: -0.761622; yPos: 0.161856; zPos: 3.5586 }
+ ListElement{ xPos: -1.88456; yPos: -2.48094; zPos: 0.287091 }
+ ListElement{ xPos: 1.25293; yPos: 2.64374; zPos: 1.6532 }
+ ListElement{ xPos: -0.657609; yPos: 1.32547; zPos: -0.557301 }
+ ListElement{ xPos: 3.85995; yPos: 2.32568; zPos: -1.38265 }
+ ListElement{ xPos: 1.65572; yPos: -2.28977; zPos: 0.957488 }
+ ListElement{ xPos: -2.45312; yPos: -2.96071; zPos: 3.45147 }
+ ListElement{ xPos: -1.75259; yPos: 0.365259; zPos: 1.60113 }
+ ListElement{ xPos: 1.14045; yPos: -0.844805; zPos: 0.359343 }
+ ListElement{ xPos: -1.55951; yPos: 1.65687; zPos: -3.10398 }
+ ListElement{ xPos: 0.441652; yPos: -1.36623; zPos: -1.55494 }
+ ListElement{ xPos: -3.95762; yPos: 0.288753; zPos: 3.7791 }
+ ListElement{ xPos: -1.80101; yPos: -0.241499; zPos: 2.29693 }
+ ListElement{ xPos: -0.456931; yPos: 1.64399; zPos: 1.35559 }
+ ListElement{ xPos: -0.691421; yPos: -0.723378; zPos: 2.51839 }
+ ListElement{ xPos: -1.20658; yPos: -3.04063; zPos: -1.552 }
+ ListElement{ xPos: -0.958574; yPos: 1.48688; zPos: 0.950152 }
+ ListElement{ xPos: 1.76319; yPos: -1.36072; zPos: 2.15866 }
+ ListElement{ xPos: -3.91301; yPos: -0.328932; zPos: -2.45524 }
+ ListElement{ xPos: 2.9553; yPos: 3.12703; zPos: -2.43321 }
+ ListElement{ xPos: 3.55939; yPos: -1.48028; zPos: 0.152252 }
+ ListElement{ xPos: -1.41545; yPos: 3.247; zPos: 0.779314 }
+ ListElement{ xPos: -3.34482; yPos: -0.894538; zPos: 0.209302 }
+ ListElement{ xPos: 1.15338; yPos: 0.362332; zPos: -2.7924 }
+ ListElement{ xPos: 0.468852; yPos: 0.120872; zPos: 1.35593 }
+ ListElement{ xPos: 1.98778; yPos: -3.32292; zPos: -0.758591 }
+ ListElement{ xPos: 0.420718; yPos: -0.225014; zPos: -2.44806 }
+ ListElement{ xPos: 0.550207; yPos: 1.56432; zPos: 2.25317 }
+ ListElement{ xPos: 4.35156; yPos: -0.966178; zPos: -0.791032 }
+ ListElement{ xPos: 3.35179; yPos: -1.04981; zPos: -0.854089 }
+ ListElement{ xPos: 1.70857; yPos: -0.281369; zPos: -0.254686 }
+ ListElement{ xPos: -3.05855; yPos: -0.443693; zPos: 1.30251 }
+ ListElement{ xPos: -3.9509; yPos: -2.72179; zPos: -3.83489 }
+ ListElement{ xPos: 2.19632; yPos: 1.32915; zPos: 1.15345 }
+ ListElement{ xPos: 1.42782; yPos: -0.449435; zPos: -2.85005 }
+ ListElement{ xPos: -2.19053; yPos: 0.049866; zPos: 2.87493 }
+ ListElement{ xPos: 2.45196; yPos: -2.44705; zPos: -2.85302 }
+ ListElement{ xPos: 4.35263; yPos: 0.245956; zPos: 1.12886 }
+ ListElement{ xPos: 1.8167; yPos: 1.85407; zPos: -0.714159 }
+ ListElement{ xPos: 1.88577; yPos: 2.04227; zPos: -0.959396 }
+ ListElement{ xPos: 1.6522; yPos: -2.48289; zPos: 0.355373 }
+ ListElement{ xPos: -3.39965; yPos: 0.286834; zPos: -1.68171 }
+ ListElement{ xPos: 1.85639; yPos: 1.47419; zPos: 2.25749 }
+ ListElement{ xPos: -2.5216; yPos: -0.88573; zPos: -2.69594 }
+ ListElement{ xPos: -0.143043; yPos: 0.28453; zPos: -1.75898 }
+ ListElement{ xPos: -2.52745; yPos: -2.76741; zPos: -0.257011 }
+ ListElement{ xPos: 0.381448; yPos: -1.64793; zPos: -0.756889 }
+ ListElement{ xPos: 2.30469; yPos: -1.28844; zPos: -2.79271 }
+ ListElement{ xPos: -1.72491; yPos: -1.48634; zPos: -2.61686 }
+ ListElement{ xPos: 0.503342; yPos: 0.248352; zPos: -2.27162 }
+ ListElement{ xPos: 0.457491; yPos: -1.88183; zPos: -0.951124 }
+ ListElement{ xPos: -1.23123; yPos: 0.963519; zPos: 2.3569 }
+ ListElement{ xPos: -0.55709; yPos: -0.364372; zPos: -1.82528 }
+ ListElement{ xPos: 2.73963; yPos: -0.567024; zPos: -0.496936 }
+ ListElement{ xPos: 1.17979; yPos: 2.76252; zPos: -2.35641 }
+ ListElement{ xPos: -1.20723; yPos: -2.1692; zPos: 3.14368 }
+ ListElement{ xPos: -0.0504301; yPos: 1.76714; zPos: 1.64265 }
+ ListElement{ xPos: 1.45714; yPos: -0.725448; zPos: 0.739217 }
+ ListElement{ xPos: 0.246123; yPos: -3.27811; zPos: -0.251218 }
+ ListElement{ xPos: -0.894632; yPos: 1.08758; zPos: -0.17184 }
+ ListElement{ xPos: -2.45217; yPos: 0.565077; zPos: -0.557015 }
+ ListElement{ xPos: 2.51301; yPos: 1.1271; zPos: 2.25057 }
+ ListElement{ xPos: -1.05099; yPos: -2.1688; zPos: -1.88996 }
+ ListElement{ xPos: 1.26945; yPos: -2.1225; zPos: -1.55031 }
+ ListElement{ xPos: -4.30129; yPos: -0.760298; zPos: 0.259868 }
+ ListElement{ xPos: -0.157336; yPos: -0.237532; zPos: -2.69483 }
+ ListElement{ xPos: -2.95778; yPos: 1.36212; zPos: -3.65524 }
+ ListElement{ xPos: 2.74003; yPos: 1.16234; zPos: 2.05928 }
+ ListElement{ xPos: 0.955294; yPos: -1.52182; zPos: -1.05684 }
+ ListElement{ xPos: -1.87004; yPos: 2.72729; zPos: -0.550608 }
+ ListElement{ xPos: 0.459439; yPos: 2.88101; zPos: -4.4135 }
+ ListElement{ xPos: 1.35069; yPos: 1.08445; zPos: -0.808625 }
+ ListElement{ xPos: -2.70034; yPos: -1.36291; zPos: -2.65126 }
+ ListElement{ xPos: 0.353099; yPos: 2.32354; zPos: -1.61885 }
+ ListElement{ xPos: -0.453359; yPos: 1.67524; zPos: 0.122888 }
+ ListElement{ xPos: 3.7506; yPos: 1.12855; zPos: -3.86338 }
+ ListElement{ xPos: 0.548626; yPos: 2.63101; zPos: 0.552261 }
+ ListElement{ xPos: -0.753935; yPos: -3.52241; zPos: -3.21122 }
+ ListElement{ xPos: 0.258935; yPos: -1.32453; zPos: 2.25745 }
+ ListElement{ xPos: -2.8797; yPos: -1.60832; zPos: -2.45626 }
+ ListElement{ xPos: 0.151838; yPos: -0.565264; zPos: 3.98539 }
+ ListElement{ xPos: 2.1508; yPos: -1.68734; zPos: -1.75076 }
+ ListElement{ xPos: -4.23947; yPos: -1.92531; zPos: 2.35438 }
+ ListElement{ xPos: 1.95273; yPos: -1.32736; zPos: 0.313398 }
+ ListElement{ xPos: 0.533647; yPos: 0.646686; zPos: 0.75712 }
+ ListElement{ xPos: 0.856619; yPos: -0.843249; zPos: -0.577773 }
+ ListElement{ xPos: -2.15649; yPos: -1.64285; zPos: -2.31055 }
+ ListElement{ xPos: -0.851309; yPos: -2.84717; zPos: -0.324933 }
+ ListElement{ xPos: -3.17772; yPos: -0.324817; zPos: -0.858394 }
+ ListElement{ xPos: 3.45303; yPos: 0.529449; zPos: 0.818094 }
+ ListElement{ xPos: 1.42912; yPos: 0.238088; zPos: 0.385617 }
+ ListElement{ xPos: 0.459586; yPos: 1.7661; zPos: -0.153761 }
+ ListElement{ xPos: 0.855577; yPos: 3.16845; zPos: -2.19548 }
+ ListElement{ xPos: 2.15181; yPos: 0.729021; zPos: -0.955922 }
+ ListElement{ xPos: -2.40113; yPos: 0.665756; zPos: -0.521366 }
+ ListElement{ xPos: 1.45469; yPos: -0.462177; zPos: -1.95869 }
+ ListElement{ xPos: 0.629115; yPos: -1.84769; zPos: 1.86755 }
+ ListElement{ xPos: 3.47576; yPos: -0.209875; zPos: -0.555502 }
+ ListElement{ xPos: 0.295075; yPos: -0.840772; zPos: 4.68895 }
+ ListElement{ xPos: -0.253301; yPos: -2.49078; zPos: 2.11749 }
+ ListElement{ xPos: -1.15923; yPos: -3.163; zPos: -3.05671 }
+ ListElement{ xPos: 1.45484; yPos: 0.963654; zPos: -0.734942 }
+ ListElement{ xPos: 0.354307; yPos: 0.520772; zPos: -1.32278 }
+ ListElement{ xPos: 2.65725; yPos: 0.284589; zPos: -0.856856 }
+ ListElement{ xPos: -1.2596; yPos: 0.765493; zPos: -1.66469 }
+ ListElement{ xPos: -0.656057; yPos: -2.16906; zPos: 3.72144 }
+ ListElement{ xPos: -0.251559; yPos: -2.36406; zPos: -1.89709 }
+ ListElement{ xPos: 0.35608; yPos: -0.80463; zPos: 1.85674 }
+ ListElement{ xPos: 0.0508692; yPos: 0.615674; zPos: 0.856785 }
+ ListElement{ xPos: -2.50726; yPos: 2.28743; zPos: -2.05697 }
+ ListElement{ xPos: 1.65272; yPos: 1.29604; zPos: 2.11481 }
+ ListElement{ xPos: -3.2878; yPos: -0.244516; zPos: 0.799732 }
+ ListElement{ xPos: -2.18989; yPos: -0.847222; zPos: -0.264559 }
+ ListElement{ xPos: 0.452832; yPos: 0.960993; zPos: 2.53691 }
+ ListElement{ xPos: -2.43913; yPos: 1.28957; zPos: 2.75427 }
+ ListElement{ xPos: -1.72889; yPos: -3.29414; zPos: -2.31426 }
+ ListElement{ xPos: 0.952615; yPos: -0.0844651; zPos: 0.346607 }
+ ListElement{ xPos: 1.41175; yPos: 0.889643; zPos: 0.450356 }
+ ListElement{ xPos: 2.13145; yPos: 1.08697; zPos: 0.223055 }
+ ListElement{ xPos: -2.16002; yPos: -0.225505; zPos: -0.602641 }
+ ListElement{ xPos: 0.54028; yPos: 1.24765; zPos: -0.456129 }
+ ListElement{ xPos: 2.55086; yPos: -0.56734; zPos: -2.65051 }
+ ListElement{ xPos: -4.53921; yPos: -0.483588; zPos: -1.25013 }
+ ListElement{ xPos: 3.45413; yPos: -0.44258; zPos: 2.29687 }
+ ListElement{ xPos: -0.257456; yPos: 0.64624; zPos: 1.65041 }
+ ListElement{ xPos: 1.25559; yPos: -0.65493; zPos: -0.358872 }
+ ListElement{ xPos: 1.9599; yPos: -1.56965; zPos: -4.17044 }
+ ListElement{ xPos: 2.75996; yPos: -1.98665; zPos: 3.31794 }
+ ListElement{ xPos: 3.05837; yPos: 1.04847; zPos: -0.975536 }
+ ListElement{ xPos: -2.95407; yPos: 1.40294; zPos: -2.25825 }
+ ListElement{ xPos: 1.38718; yPos: 0.360709; zPos: -2.98211 }
+ ListElement{ xPos: 0.481728; yPos: -2.48564; zPos: 3.25864 }
+ ListElement{ xPos: -1.15089; yPos: 0.363522; zPos: 0.458662 }
+ ListElement{ xPos: -2.25551; yPos: 0.0421839; zPos: 0.650008 }
+ ListElement{ xPos: -1.85862; yPos: -0.969237; zPos: 4.25313 }
+ ListElement{ xPos: 1.55797; yPos: 0.0465051; zPos: -3.85709 }
+ ListElement{ xPos: 0.0555338; yPos: 0.682957; zPos: -2.45556 }
+ ListElement{ xPos: -0.186868; yPos: -0.482811; zPos: 1.96957 }
+ ListElement{ xPos: 2.197; yPos: -1.5248; zPos: -4.20912 }
+ ListElement{ xPos: 3.40636; yPos: 0.626269; zPos: -2.05757 }
+ ListElement{ xPos: 0.780426; yPos: 2.68048; zPos: -0.852693 }
+ ListElement{ xPos: 1.65184; yPos: 1.68951; zPos: -0.892089 }
+ ListElement{ xPos: 2.11929; yPos: -2.44406; zPos: 1.21168 }
+ ListElement{ xPos: -0.153348; yPos: -1.88112; zPos: -0.357374 }
+ ListElement{ xPos: -0.359393; yPos: 1.76654; zPos: 1.63063 }
+ ListElement{ xPos: -2.15954; yPos: 0.0819277; zPos: 0.757621 }
+ ListElement{ xPos: -0.159898; yPos: -3.36316; zPos: 0.359582 }
+ ListElement{ xPos: 2.74125; yPos: -2.84148; zPos: 0.355785 }
+ ListElement{ xPos: -1.3558; yPos: 0.0027827; zPos: -0.588162 }
+ ListElement{ xPos: -0.354346; yPos: -2.56747; zPos: -0.984403 }
+ ListElement{ xPos: -2.75082; yPos: -3.56807; zPos: 1.5599 }
+ ListElement{ xPos: -2.54708; yPos: -0.686147; zPos: 2.75649 }
+ ListElement{ xPos: 1.35138; yPos: 0.692978; zPos: -2.24969 }
+ ListElement{ xPos: -1.39826; yPos: -0.246682; zPos: -1.65876 }
+ ListElement{ xPos: -1.46629; yPos: -1.44446; zPos: 4.45293 }
+ ListElement{ xPos: -1.89442; yPos: 3.64549; zPos: 2.05732 }
+ ListElement{ xPos: -0.658093; yPos: 0.0815129; zPos: 3.95269 }
+ ListElement{ xPos: 2.25603; yPos: 2.96329; zPos: -2.35993 }
+ ListElement{ xPos: 1.36323; yPos: 1.64488; zPos: -0.0538547 }
+ ListElement{ xPos: 1.75659; yPos: 2.24227; zPos: -2.8522 }
+ ListElement{ xPos: -0.0566584; yPos: -1.56465; zPos: -0.0503143 }
+ ListElement{ xPos: -3.8532; yPos: -0.822258; zPos: -0.345406 }
+ ListElement{ xPos: 0.951328; yPos: 0.329296; zPos: -2.52211 }
+ ListElement{ xPos: -2.48659; yPos: 0.410856; zPos: -3.55401 }
+ ListElement{ xPos: 3.72676; yPos: 2.36324; zPos: 3.65589 }
+ ListElement{ xPos: 0.559972; yPos: 0.884984; zPos: 3.15283 }
+ ListElement{ xPos: -1.37624; yPos: -1.36007; zPos: -2.16578 }
+ ListElement{ xPos: 2.05543; yPos: 0.4472; zPos: -0.82911 }
+ ListElement{ xPos: -4.75258; yPos: 1.8779; zPos: -1.75376 }
+ ListElement{ xPos: 0.15648; yPos: 2.64039; zPos: -2.21467 }
+ ListElement{ xPos: -2.0593; yPos: -2.56775; zPos: 1.15037 }
+ ListElement{ xPos: -3.70217; yPos: 2.12375; zPos: 1.3652 }
+ ListElement{ xPos: 1.05566; yPos: 0.98299; zPos: 4.02985 }
+ ListElement{ xPos: -0.766882; yPos: -0.88359; zPos: 1.35525 }
+ ListElement{ xPos: 0.951335; yPos: -1.84689; zPos: 0.178337 }
+ ListElement{ xPos: 0.751608; yPos: 1.1691; zPos: 4.25273 }
+ ListElement{ xPos: -1.36367; yPos: 0.728904; zPos: 0.655858 }
+ ListElement{ xPos: 3.17581; yPos: -0.0844758; zPos: -1.75811 }
+ ListElement{ xPos: 2.85546; yPos: -0.683618; zPos: 0.653701 }
+ ListElement{ xPos: -0.471118; yPos: 3.04176; zPos: -2.35393 }
+ ListElement{ xPos: 3.0574; yPos: -0.601996; zPos: -0.611932 }
+ ListElement{ xPos: -0.854024; yPos: -0.44532; zPos: 0.355575 }
+ ListElement{ xPos: 0.05047; yPos: -1.92888; zPos: 0.64818 }
+ ListElement{ xPos: -1.25515; yPos: -1.44466; zPos: 1.90429 }
+ ListElement{ xPos: -1.67201; yPos: 0.0461708; zPos: -0.796655 }
+ ListElement{ xPos: 1.45345; yPos: -1.66159; zPos: -3.48143 }
+ ListElement{ xPos: -2.84514; yPos: -1.24586; zPos: -3.47945 }
+ ListElement{ xPos: 0.287402; yPos: -0.688276; zPos: -3.75664 }
+ ListElement{ xPos: 3.35908; yPos: 0.687828; zPos: -1.94406 }
+ ListElement{ xPos: -2.39167; yPos: 1.08322; zPos: -1.73508 }
+ ListElement{ xPos: 1.52152; yPos: 1.86032; zPos: -1.25351 }
+ ListElement{ xPos: 1.55931; yPos: 3.64414; zPos: 1.35944 }
+ ListElement{ xPos: 1.15954; yPos: -1.36058; zPos: 0.758814 }
+ ListElement{ xPos: -1.95325; yPos: 0.0851092; zPos: -0.854106 }
+ ListElement{ xPos: -2.25254; yPos: -0.523024; zPos: 1.05486 }
+ ListElement{ xPos: -2.68036; yPos: -1.32901; zPos: 1.05877 }
+ ListElement{ xPos: -0.485956; yPos: -1.52164; zPos: 2.45303 }
+ ListElement{ xPos: -0.0546215; yPos: 0.640683; zPos: -2.85953 }
+ ListElement{ xPos: 4.45295; yPos: -0.246051; zPos: -0.159626 }
+ ListElement{ xPos: 3.4523; yPos: 1.7215; zPos: -1.10587 }
+ ListElement{ xPos: 3.35142; yPos: -1.72053; zPos: -0.252105 }
+ ListElement{ xPos: 1.74251; yPos: 2.76108; zPos: 2.51524 }
+ ListElement{ xPos: 2.15054; yPos: -2.88101; zPos: -1.7527 }
+ ListElement{ xPos: -3.70517; yPos: -0.0470951; zPos: 0.258921 }
+ ListElement{ xPos: -0.45593; yPos: -3.47184; zPos: -2.95345 }
+ ListElement{ xPos: 3.15988; yPos: -2.32107; zPos: 0.105299 }
+ ListElement{ xPos: 0.751449; yPos: -2.88762; zPos: -3.45245 }
+ ListElement{ xPos: 2.9794; yPos: 0.493172; zPos: -0.654683 }
+ ListElement{ xPos: -1.87713; yPos: -2.48632; zPos: -3.534 }
+ ListElement{ xPos: 1.65266; yPos: 3.16008; zPos: 2.1579 }
+ ListElement{ xPos: -1.25239; yPos: -0.763119; zPos: 2.15776 }
+ ListElement{ xPos: 3.5572; yPos: 0.282681; zPos: 2.44174 }
+ ListElement{ xPos: 0.251145; yPos: 0.520256; zPos: 2.3184 }
+ ListElement{ xPos: -1.78596; yPos: -1.36913; zPos: -2.50818 }
+ ListElement{ xPos: 3.82122; yPos: 1.04473; zPos: 0.456159 }
+ ListElement{ xPos: 2.45979; yPos: -0.722759; zPos: -4.05123 }
+ ListElement{ xPos: -0.855594; yPos: 0.163792; zPos: -0.553702 }
+ ListElement{ xPos: 0.656895; yPos: 0.529982; zPos: 3.35129 }
+ ListElement{ xPos: 0.857952; yPos: -0.0885677; zPos: 0.695128 }
+ ListElement{ xPos: -0.143269; yPos: 1.12972; zPos: -3.155 }
+ ListElement{ xPos: -2.95923; yPos: 0.241767; zPos: 0.832165 }
+ ListElement{ xPos: 0.253329; yPos: -0.622952; zPos: -0.459799 }
+ ListElement{ xPos: 0.151499; yPos: 2.5297; zPos: 1.53059 }
+ ListElement{ xPos: 0.655464; yPos: -1.49902; zPos: -1.51071 }
+ ListElement{ xPos: 4.7585; yPos: 1.76425; zPos: 1.15164 }
+ ListElement{ xPos: -1.75063; yPos: -1.44645; zPos: -3.65525 }
+ ListElement{ xPos: 0.850392; yPos: 0.0417223; zPos: -0.340588 }
+ ListElement{ xPos: -0.557015; yPos: -0.282305; zPos: -1.85291 }
+ ListElement{ xPos: -4.05639; yPos: 0.522959; zPos: -2.3507 }
+ ListElement{ xPos: -0.358137; yPos: -0.967852; zPos: 0.807832 }
+ ListElement{ xPos: -1.82056; yPos: -0.0483894; zPos: 0.0541359 }
+ ListElement{ xPos: -2.16623; yPos: 0.129809; zPos: -2.52513 }
+ ListElement{ xPos: -1.85591; yPos: -1.04417; zPos: -1.28501 }
+ ListElement{ xPos: -1.79647; yPos: -3.44045; zPos: -1.73399 }
+ ListElement{ xPos: 2.25342; yPos: 0.161308; zPos: -0.0517495 }
+ ListElement{ xPos: -1.37877; yPos: 0.243596; zPos: -1.52931 }
+ ListElement{ xPos: -0.059299; yPos: -0.480825; zPos: 1.7137 }
+ ListElement{ xPos: -2.54357; yPos: 0.286685; zPos: -2.11495 }
+ ListElement{ xPos: 3.92334; yPos: -0.442936; zPos: -0.852895 }
+ ListElement{ xPos: -0.390023; yPos: -1.96437; zPos: 1.38718 }
+ ListElement{ xPos: 1.35263; yPos: 2.92968; zPos: -1.1545 }
+ ListElement{ xPos: -2.25892; yPos: -2.27429; zPos: -0.451533 }
+ ListElement{ xPos: -0.2215; yPos: -0.126727; zPos: 0.155541 }
+ ListElement{ xPos: 0.715932; yPos: 1.47509; zPos: -3.52895 }
+ ListElement{ xPos: -0.382939; yPos: 3.16461; zPos: 2.65165 }
+ ListElement{ xPos: -1.14437; yPos: -1.44682; zPos: 0.456601 }
+ ListElement{ xPos: 0.251892; yPos: -1.0431; zPos: 4.31548 }
+ ListElement{ xPos: -2.23281; yPos: -2.48698; zPos: 0.46995 }
+ ListElement{ xPos: 0.954231; yPos: -3.4323; zPos: -1.20233 }
+ ListElement{ xPos: 2.75569; yPos: -1.66383; zPos: -1.95486 }
+ ListElement{ xPos: 0.750644; yPos: -1.84163; zPos: -0.159206 }
+ ListElement{ xPos: -0.757387; yPos: -1.84192; zPos: 0.354209 }
+ ListElement{ xPos: -2.85509; yPos: -2.12151; zPos: -0.954754 }
+ ListElement{ xPos: -0.888427; yPos: -2.8403; zPos: -0.157387 }
+ ListElement{ xPos: -1.95265; yPos: -0.445753; zPos: 2.17956 }
+ ListElement{ xPos: -1.05845; yPos: -2.48694; zPos: -1.25315 }
+ ListElement{ xPos: -2.66497; yPos: -1.48251; zPos: 0.873192 }
+ ListElement{ xPos: 2.50491; yPos: -1.0833; zPos: 1.99667 }
+ ListElement{ xPos: 0.453931; yPos: 2.52158; zPos: 0.456875 }
+ ListElement{ xPos: 1.55859; yPos: -0.161924; zPos: 0.256619 }
+ ListElement{ xPos: -2.92585; yPos: 0.368018; zPos: 0.35908 }
+ ListElement{ xPos: 2.95509; yPos: -1.56248; zPos: -2.74469 }
+ ListElement{ xPos: 3.46082; yPos: -1.76026; zPos: 3.05835 }
+ ListElement{ xPos: 1.75644; yPos: -2.84241; zPos: 0.507631 }
+ ListElement{ xPos: -0.959006; yPos: 0.649579; zPos: 1.10824 }
+ ListElement{ xPos: 2.63856; yPos: 2.0417; zPos: 0.187281 }
+ ListElement{ xPos: -0.150004; yPos: -0.0838836; zPos: -0.949314 }
+ ListElement{ xPos: 2.26402; yPos: -1.28916; zPos: 2.85284 }
+ ListElement{ xPos: -0.821239; yPos: 2.68795; zPos: -0.317185 }
+ ListElement{ xPos: 3.47124; yPos: 0.840813; zPos: -2.65322 }
+ ListElement{ xPos: -0.253209; yPos: -0.244177; zPos: 0.457348 }
+ ListElement{ xPos: 2.76181; yPos: 1.64033; zPos: -1.95329 }
+ ListElement{ xPos: 1.35105; yPos: -2.96027; zPos: 0.659952 }
+ ListElement{ xPos: -1.45423; yPos: -0.24358; zPos: 0.832696 }
+ ListElement{ xPos: 1.45109; yPos: 1.64958; zPos: -3.45448 }
+ ListElement{ xPos: -1.15659; yPos: 3.08225; zPos: 1.11445 }
+ ListElement{ xPos: 0.806359; yPos: 1.88298; zPos: -2.13001 }
+ ListElement{ xPos: 1.15538; yPos: 3.04545; zPos: -0.759437 }
+ ListElement{ xPos: -0.450074; yPos: 1.36121; zPos: -0.155042 }
+ ListElement{ xPos: -2.80924; yPos: -1.24207; zPos: 2.55513 }
+ ListElement{ xPos: 4.48859; yPos: 2.04394; zPos: 1.25324 }
+ ListElement{ xPos: -0.958741; yPos: 1.24575; zPos: 3.65169 }
+ ListElement{ xPos: 3.45143; yPos: 1.3276; zPos: 2.5144 }
+ ListElement{ xPos: -3.25232; yPos: 1.12514; zPos: -1.21425 }
+ ListElement{ xPos: -2.45327; yPos: 0.681109; zPos: 4.35764 }
+ ListElement{ xPos: 0.55395; yPos: -0.128353; zPos: -3.95705 }
+ ListElement{ xPos: -0.352458; yPos: 3.08882; zPos: -0.340631 }
+ ListElement{ xPos: 1.35213; yPos: -2.92251; zPos: -3.31166 }
+ ListElement{ xPos: 0.52621; yPos: -0.279201; zPos: 0.959619 }
+ ListElement{ xPos: 1.2243; yPos: -0.240093; zPos: -0.75247 }
+ ListElement{ xPos: -1.29854; yPos: 2.16477; zPos: 3.3507 }
+ ListElement{ xPos: -3.35677; yPos: 2.36713; zPos: 3.4585 }
+ ListElement{ xPos: 0.957717; yPos: -0.885793; zPos: 1.25827 }
+ ListElement{ xPos: 0.150983; yPos: 1.24269; zPos: 0.539106 }
+ ListElement{ xPos: 1.84986; yPos: 1.56932; zPos: -1.05811 }
+ ListElement{ xPos: -1.35563; yPos: 3.82103; zPos: -1.45287 }
+ ListElement{ xPos: 1.4544; yPos: -2.6453; zPos: 0.58082 }
+ ListElement{ xPos: 2.05908; yPos: 1.16496; zPos: 1.44075 }
+ ListElement{ xPos: 2.9507; yPos: -2.4957; zPos: 0.153512 }
+ ListElement{ xPos: -1.10289; yPos: 0.763085; zPos: -1.65351 }
+ ListElement{ xPos: -2.50708; yPos: -2.467; zPos: 1.05892 }
+ ListElement{ xPos: 3.55284; yPos: -1.8509; zPos: -2.55732 }
+ ListElement{ xPos: -0.848034; yPos: 1.24305; zPos: -3.7516 }
+ ListElement{ xPos: -1.35051; yPos: -2.48178; zPos: 2.85326 }
+ ListElement{ xPos: -2.18554; yPos: 1.48771; zPos: -0.155205 }
+ ListElement{ xPos: -0.459278; yPos: 2.68404; zPos: 2.85727 }
+ ListElement{ xPos: 0.854722; yPos: 1.47322; zPos: -3.35951 }
+ ListElement{ xPos: -2.23505; yPos: -2.24254; zPos: 0.353203 }
+ ListElement{ xPos: 1.42395; yPos: -2.32169; zPos: 0.558188 }
+ ListElement{ xPos: 3.65106; yPos: 1.12201; zPos: -4.58409 }
+ ListElement{ xPos: 0.11; yPos: -0.68782; zPos: 1.85804 }
+ ListElement{ xPos: -1.9551; yPos: -0.560204; zPos: -2.0577 }
+ ListElement{ xPos: 1.85964; yPos: 1.32737; zPos: -4.40673 }
+ ListElement{ xPos: -0.616311; yPos: 0.649737; zPos: -0.30189 }
+ ListElement{ xPos: -1.55375; yPos: 1.52043; zPos: -3.75629 }
+ ListElement{ xPos: 1.85417; yPos: 0.486964; zPos: 0.654806 }
+ ListElement{ xPos: 3.35638; yPos: 2.52599; zPos: 1.94343 }
+ ListElement{ xPos: 0.491389; yPos: 1.40427; zPos: -1.31935 }
+ ListElement{ xPos: -2.72939; yPos: 0.844341; zPos: 1.62621 }
+ ListElement{ xPos: -0.525985; yPos: 1.31415; zPos: 0.484015 }
+ ListElement{ xPos: 2.25998; yPos: -1.719; zPos: 1.25143 }
+ ListElement{ xPos: 1.79268; yPos: 2.46378; zPos: -0.951188 }
+ ListElement{ xPos: -3.55105; yPos: 1.04122; zPos: 3.9501 }
+ ListElement{ xPos: 0.954251; yPos: 1.28296; zPos: 2.05486 }
+ ListElement{ xPos: -3.15267; yPos: 1.96498; zPos: -0.361707 }
+ ListElement{ xPos: 1.35358; yPos: -0.921098; zPos: -1.71743 }
+ ListElement{ xPos: -3.16896; yPos: -3.08548; zPos: 0.903411 }
+ ListElement{ xPos: 1.25127; yPos: -2.44903; zPos: 2.25616 }
+ ListElement{ xPos: -3.88899; yPos: 0.761334; zPos: -1.05751 }
+ ListElement{ xPos: -1.05163; yPos: -3.89783; zPos: -0.883668 }
+ ListElement{ xPos: -4.189; yPos: 1.24176; zPos: -2.63816 }
+ ListElement{ xPos: 2.45671; yPos: -1.84859; zPos: 0.352808 }
+ ListElement{ xPos: -1.59618; yPos: 2.16255; zPos: 4.33699 }
+ ListElement{ xPos: 2.10913; yPos: -1.88673; zPos: -0.952497 }
+ ListElement{ xPos: -1.85571; yPos: -0.287392; zPos: 0.277176 }
+ ListElement{ xPos: 0.751967; yPos: 1.04568; zPos: -1.35427 }
+ ListElement{ xPos: 2.85792; yPos: 1.60982; zPos: -2.05454 }
+ ListElement{ xPos: -2.13152; yPos: -0.260207; zPos: -2.15124 }
+ ListElement{ xPos: 1.75432; yPos: 2.28936; zPos: 0.756254 }
+ ListElement{ xPos: 1.95711; yPos: -0.681098; zPos: -2.38037 }
+ ListElement{ xPos: -0.826273; yPos: 1.08361; zPos: 1.6515 }
+ ListElement{ xPos: -1.85118; yPos: 1.89481; zPos: -0.756754 }
+ ListElement{ xPos: -3.0571; yPos: 2.44795; zPos: 0.355341 }
+ ListElement{ xPos: -0.455122; yPos: -3.58071; zPos: -2.85209 }
+ ListElement{ xPos: -0.95805; yPos: 0.641282; zPos: 2.15189 }
+ ListElement{ xPos: -1.35515; yPos: -0.234803; zPos: -0.825819 }
+ ListElement{ xPos: 2.12472; yPos: -0.0444431; zPos: 0.651227 }
+ ListElement{ xPos: 2.67573; yPos: 0.223987; zPos: 2.75712 }
+ ListElement{ xPos: 1.65871; yPos: -0.163059; zPos: 1.6513 }
+ ListElement{ xPos: -1.85429; yPos: 0.68862; zPos: 1.9576 }
+ ListElement{ xPos: -3.05186; yPos: -2.2804; zPos: 0.100919 }
+ ListElement{ xPos: 3.41813; yPos: -1.88775; zPos: 3.67075 }
+ ListElement{ xPos: -0.753778; yPos: 0.36467; zPos: 1.55333 }
+ ListElement{ xPos: 2.97628; yPos: -1.36503; zPos: -1.85135 }
+ ListElement{ xPos: 0.477128; yPos: 1.08862; zPos: 0.858931 }
+ ListElement{ xPos: -1.0531; yPos: 1.0488; zPos: 2.15218 }
+ ListElement{ xPos: 2.66911; yPos: -2.08876; zPos: -0.182397 }
+ ListElement{ xPos: 0.5117; yPos: -2.84097; zPos: -0.953684 }
+ ListElement{ xPos: 0.468302; yPos: 1.88616; zPos: 2.05369 }
+ ListElement{ xPos: -3.16099; yPos: -2.76085; zPos: -2.75679 }
+ ListElement{ xPos: -2.6593; yPos: 3.52373; zPos: -1.24072 }
+ ListElement{ xPos: -4.37957; yPos: -0.286903; zPos: 3.63863 }
+ ListElement{ xPos: -2.85958; yPos: -2.56921; zPos: -2.85723 }
+ ListElement{ xPos: -0.159735; yPos: 2.72758; zPos: -2.80575 }
+ ListElement{ xPos: -0.951849; yPos: -0.607465; zPos: 1.05633 }
+ ListElement{ xPos: 1.93077; yPos: 2.56422; zPos: 1.25446 }
+ ListElement{ xPos: -0.859754; yPos: 0.248106; zPos: 0.0584456 }
+ ListElement{ xPos: 2.4023; yPos: 2.56659; zPos: -1.2588 }
+ ListElement{ xPos: 2.35295; yPos: -1.08729; zPos: 2.7851 }
+ ListElement{ xPos: -2.1537; yPos: -0.765032; zPos: 2.83652 }
+ ListElement{ xPos: 1.40185; yPos: 1.29804; zPos: 2.3588 }
+ ListElement{ xPos: -0.991566; yPos: 1.72049; zPos: 4.17146 }
+ ListElement{ xPos: 3.76736; yPos: -1.48837; zPos: 2.05329 }
+ ListElement{ xPos: -0.251896; yPos: 0.765367; zPos: -1.4087 }
+ ListElement{ xPos: -1.6228; yPos: 0.328693; zPos: 0.0528287 }
+ ListElement{ xPos: 2.56735; yPos: -3.08103; zPos: 0.853144 }
+ ListElement{ xPos: 0.0531812; yPos: -1.96216; zPos: 1.55734 }
+ ListElement{ xPos: -3.77052; yPos: 0.8421; zPos: -0.258953 }
+ ListElement{ xPos: 2.35523; yPos: 0.676643; zPos: -1.55789 }
+ ListElement{ xPos: 1.16702; yPos: 2.64474; zPos: -1.45533 }
+ ListElement{ xPos: 2.55709; yPos: -1.56013; zPos: 2.05351 }
+ ListElement{ xPos: -2.15518; yPos: 3.56253; zPos: 3.257 }
+ ListElement{ xPos: -0.553936; yPos: -1.24935; zPos: 2.65224 }
+ ListElement{ xPos: -0.355931; yPos: 1.32374; zPos: 0.859863 }
+ ListElement{ xPos: -1.92974; yPos: 1.2482; zPos: 1.15936 }
+ ListElement{ xPos: 0.350652; yPos: -2.44371; zPos: -1.35611 }
+ ListElement{ xPos: 2.98996; yPos: -1.08527; zPos: -4.30641 }
+ ListElement{ xPos: 1.82765; yPos: -0.440236; zPos: 1.25528 }
+ ListElement{ xPos: -0.689231; yPos: -1.08813; zPos: -0.668663 }
+ ListElement{ xPos: -0.326426; yPos: -0.881857; zPos: -1.45371 }
+ ListElement{ xPos: -1.0655; yPos: 2.12466; zPos: 2.34146 }
+ ListElement{ xPos: 3.1563; yPos: 0.523166; zPos: -2.8572 }
+ ListElement{ xPos: 0.455505; yPos: 2.48775; zPos: -1.33482 }
+ ListElement{ xPos: 0.53939; yPos: -0.847333; zPos: 0.732877 }
+ ListElement{ xPos: -0.683025; yPos: -0.448889; zPos: -1.35747 }
+ ListElement{ xPos: -1.7711; yPos: -0.125587; zPos: -2.55083 }
+ ListElement{ xPos: -0.512871; yPos: 0.520964; zPos: 1.40731 }
+ ListElement{ xPos: 4.93857; yPos: -1.6805; zPos: -0.127298 }
+ ListElement{ xPos: 1.46098; yPos: -1.64073; zPos: 1.35833 }
+ ListElement{ xPos: 0.0518058; yPos: 0.285151; zPos: -2.2437 }
+ ListElement{ xPos: 1.5587; yPos: -1.23067; zPos: 0.458753 }
+ ListElement{ xPos: 3.13089; yPos: 3.64132; zPos: 1.45181 }
+ ListElement{ xPos: -1.55648; yPos: 2.167; zPos: 0.153491 }
+ ListElement{ xPos: 3.94451; yPos: -2.56372; zPos: -1.25276 }
+ ListElement{ xPos: 4.15866; yPos: 0.646921; zPos: 2.65542 }
+ ListElement{ xPos: -2.88189; yPos: 0.562407; zPos: -1.35379 }
+ ListElement{ xPos: 1.31686; yPos: 1.2808; zPos: 0.804375 }
+ ListElement{ xPos: -2.36912; yPos: -3.08775; zPos: 1.28335 }
+ ListElement{ xPos: 0.575203; yPos: -0.36483; zPos: -2.43958 }
+ ListElement{ xPos: 0.613108; yPos: 0.526892; zPos: 2.75368 }
+ ListElement{ xPos: 3.96027; yPos: -0.525425; zPos: -4.25746 }
+ ListElement{ xPos: -0.510821; yPos: 1.28578; zPos: -0.058488 }
+ ListElement{ xPos: -0.254704; yPos: -3.847; zPos: 3.15258 }
+ ListElement{ xPos: -0.925874; yPos: -1.72014; zPos: -3.15341 }
+ ListElement{ xPos: 0.85704; yPos: 0.84788; zPos: -1.75947 }
+ ListElement{ xPos: -3.35712; yPos: 0.722104; zPos: 2.15645 }
+ ListElement{ xPos: -1.67305; yPos: 0.681216; zPos: 1.65726 }
+ ListElement{ xPos: -3.64682; yPos: 0.867926; zPos: 2.63525 }
+ ListElement{ xPos: -0.715921; yPos: 1.96081; zPos: -0.939934 }
+ ListElement{ xPos: -2.45646; yPos: 1.3249; zPos: -2.75733 }
+ ListElement{ xPos: -1.75798; yPos: 0.725382; zPos: -0.851921 }
+ ListElement{ xPos: -2.78528; yPos: 0.679275; zPos: -2.59212 }
+ ListElement{ xPos: -2.24551; yPos: -3.4597; zPos: -1.85735 }
+ ListElement{ xPos: 0.85142; yPos: 2.28058; zPos: -3.75328 }
+ ListElement{ xPos: -3.85054; yPos: 2.44519; zPos: 4.35081 }
+ ListElement{ xPos: -3.6553; yPos: 0.521917; zPos: 0.293354 }
+ ListElement{ xPos: -4.35959; yPos: -0.528198; zPos: 1.55557 }
+ ListElement{ xPos: 1.45186; yPos: -0.0891161; zPos: -0.468118 }
+ ListElement{ xPos: 1.85594; yPos: -0.761461; zPos: -4.68083 }
+ ListElement{ xPos: 0.950642; yPos: 0.526239; zPos: -1.30614 }
+ ListElement{ xPos: -2.50526; yPos: -0.885606; zPos: -0.362569 }
+ ListElement{ xPos: -2.96569; yPos: 1.68519; zPos: -1.15965 }
+ ListElement{ xPos: -3.212; yPos: 0.260715; zPos: 1.18472 }
+ ListElement{ xPos: 0.950556; yPos: -0.282806; zPos: 0.776252 }
+ ListElement{ xPos: 3.66678; yPos: 1.08585; zPos: -2.15646 }
+ ListElement{ xPos: -0.806289; yPos: 1.72784; zPos: 2.85906 }
+ ListElement{ xPos: 0.363827; yPos: 1.76644; zPos: 0.931866 }
+ ListElement{ xPos: -1.34204; yPos: -0.563686; zPos: -2.34091 }
+ ListElement{ xPos: -2.81333; yPos: 0.415358; zPos: 4.28363 }
+ ListElement{ xPos: 1.52053; yPos: -0.327359; zPos: 0.35052 }
+ ListElement{ xPos: -0.633441; yPos: -0.240518; zPos: 4.05745 }
+ ListElement{ xPos: -2.38947; yPos: -1.84662; zPos: -2.29572 }
+ ListElement{ xPos: -1.95744; yPos: -0.863705; zPos: 1.85889 }
+ ListElement{ xPos: -0.0509082; yPos: -0.164164; zPos: 3.8571 }
+ ListElement{ xPos: 0.156438; yPos: -2.64188; zPos: 1.75836 }
+ ListElement{ xPos: -3.85642; yPos: 1.48025; zPos: 0.171659 }
+ ListElement{ xPos: 0.253545; yPos: 1.0852; zPos: -2.45243 }
+ ListElement{ xPos: -4.11318; yPos: 0.41655; zPos: -0.120976 }
+ ListElement{ xPos: -1.44928; yPos: -0.328222; zPos: -0.871279 }
+ ListElement{ xPos: -1.90972; yPos: -1.8495; zPos: -3.16966 }
+ ListElement{ xPos: 0.359433; yPos: 1.3236; zPos: -3.95045 }
+ ListElement{ xPos: -2.60974; yPos: -1.04138; zPos: 4.25836 }
+ ListElement{ xPos: -3.16336; yPos: -0.961581; zPos: -1.65161 }
+ ListElement{ xPos: -0.552909; yPos: -1.16942; zPos: 4.05164 }
+ ListElement{ xPos: -3.10918; yPos: -1.2402; zPos: -0.555073 }
+ ListElement{ xPos: 2.25494; yPos: 1.24432; zPos: 3.44063 }
+ ListElement{ xPos: -1.24998; yPos: -1.24928; zPos: -4.05493 }
+ ListElement{ xPos: 3.05441; yPos: 1.92762; zPos: 1.43329 }
+ ListElement{ xPos: 0.557032; yPos: -2.7688; zPos: -3.25463 }
+ ListElement{ xPos: -2.05665; yPos: 1.6357; zPos: 0.656665 }
+ ListElement{ xPos: -0.459042; yPos: 0.122664; zPos: -0.152961 }
+ ListElement{ xPos: 2.17715; yPos: 2.96833; zPos: 1.1332 }
+ ListElement{ xPos: 0.0536573; yPos: -2.08635; zPos: -0.736471 }
+ ListElement{ xPos: -3.15658; yPos: 1.0818; zPos: -0.172166 }
+ ListElement{ xPos: -1.95784; yPos: 0.44402; zPos: 0.612685 }
+ ListElement{ xPos: 0.15168; yPos: -0.323951; zPos: 2.85563 }
+ ListElement{ xPos: 0.559356; yPos: 1.63101; zPos: 0.558005 }
+ ListElement{ xPos: -2.05643; yPos: 1.84615; zPos: -1.87964 }
+ ListElement{ xPos: -0.254098; yPos: 0.368208; zPos: 1.23061 }
+ ListElement{ xPos: 4.6438; yPos: -0.209283; zPos: 0.695869 }
+ ListElement{ xPos: -1.95087; yPos: -0.859788; zPos: 0.0539467 }
+ ListElement{ xPos: -0.351737; yPos: -1.04291; zPos: 0.869198 }
+ ListElement{ xPos: 0.776319; yPos: 3.04922; zPos: -3.55278 }
+ ListElement{ xPos: -0.158751; yPos: 1.12538; zPos: -2.59681 }
+ ListElement{ xPos: -0.560997; yPos: -1.68381; zPos: 1.56935 }
+ ListElement{ xPos: 1.71385; yPos: -0.446223; zPos: -1.56843 }
+ ListElement{ xPos: 4.05142; yPos: -1.3243; zPos: 2.85052 }
+ ListElement{ xPos: 1.68685; yPos: -1.56305; zPos: 2.159 }
+ ListElement{ xPos: 0.359977; yPos: -1.16029; zPos: 1.25037 }
+ ListElement{ xPos: -2.65045; yPos: -1.28532; zPos: 0.459338 }
+ ListElement{ xPos: 0.542068; yPos: 1.52601; zPos: -1.35562 }
+ ListElement{ xPos: 1.34386; yPos: 1.68231; zPos: -2.75114 }
+ ListElement{ xPos: 1.25123; yPos: 0.43108; zPos: 0.383897 }
+ ListElement{ xPos: -0.952936; yPos: 3.6889; zPos: 1.75759 }
+ ListElement{ xPos: -3.55855; yPos: 0.484241; zPos: 1.15503 }
+ ListElement{ xPos: -1.71394; yPos: -2.64568; zPos: -3.30684 }
+ ListElement{ xPos: -2.23513; yPos: -2.46812; zPos: 1.05321 }
+ ListElement{ xPos: 0.160986; yPos: 0.442362; zPos: -1.05077 }
+ ListElement{ xPos: 2.05433; yPos: 0.473204; zPos: 0.823968 }
+ ListElement{ xPos: 0.482077; yPos: 0.0477338; zPos: 4.21712 }
+ ListElement{ xPos: -1.25348; yPos: 0.767612; zPos: 0.455813 }
+ ListElement{ xPos: 1.61308; yPos: 2.04125; zPos: -2.95433 }
+ ListElement{ xPos: -2.05862; yPos: -0.444052; zPos: 1.35177 }
+ ListElement{ xPos: -3.2582; yPos: 0.44354; zPos: 2.15898 }
+ ListElement{ xPos: -1.75935; yPos: 0.0459283; zPos: 2.35061 }
+ ListElement{ xPos: -4.15501; yPos: 0.68674; zPos: 0.802439 }
+ ListElement{ xPos: -1.66005; yPos: 1.12067; zPos: 0.552901 }
+ ListElement{ xPos: -0.150828; yPos: 3.4151; zPos: 3.05446 }
+ ListElement{ xPos: -0.274381; yPos: 0.0405946; zPos: -1.45463 }
+ ListElement{ xPos: 2.94543; yPos: -0.360918; zPos: 1.45895 }
+ ListElement{ xPos: -1.42494; yPos: 1.56503; zPos: 1.31012 }
+ ListElement{ xPos: 3.45402; yPos: -1.27808; zPos: -4.29049 }
+ ListElement{ xPos: -1.14819; yPos: 0.674339; zPos: 1.55807 }
+ ListElement{ xPos: -0.356159; yPos: 1.52295; zPos: -0.351445 }
+ ListElement{ xPos: 0.387809; yPos: 0.965119; zPos: 1.84271 }
+ ListElement{ xPos: 2.56165; yPos: -1.84639; zPos: 1.65056 }
+ ListElement{ xPos: -0.619108; yPos: 2.24004; zPos: -2.92134 }
+ ListElement{ xPos: -0.254288; yPos: -2.32744; zPos: -0.720931 }
+ ListElement{ xPos: 3.3508; yPos: -2.24501; zPos: 1.58268 }
+ ListElement{ xPos: 1.69434; yPos: 1.96814; zPos: 3.97439 }
+ ListElement{ xPos: 1.80785; yPos: 0.685502; zPos: -1.55595 }
+ ListElement{ xPos: 2.71587; yPos: 1.76415; zPos: -2.98124 }
+ ListElement{ xPos: -2.35151; yPos: -0.697338; zPos: -3.96269 }
+ ListElement{ xPos: -1.85759; yPos: 1.96899; zPos: -1.25212 }
+ ListElement{ xPos: -4.05922; yPos: 1.12838; zPos: -2.7597 }
+ ListElement{ xPos: -2.85434; yPos: -1.36487; zPos: 0.659987 }
+ ListElement{ xPos: -1.75616; yPos: 2.12969; zPos: -1.35032 }
+ ListElement{ xPos: -2.95985; yPos: -0.0854955; zPos: 3.65545 }
+ ListElement{ xPos: -2.46049; yPos: 2.45378; zPos: 4.51969 }
+ ListElement{ xPos: -0.0577358; yPos: 0.0427911; zPos: 0.359068 }
+ ListElement{ xPos: -3.25346; yPos: 0.161829; zPos: 1.12956 }
+ ListElement{ xPos: 3.55498; yPos: 2.32482; zPos: 1.33302 }
+ ListElement{ xPos: 4.99905; yPos: -1.88748; zPos: 0.450165 }
+ ListElement{ xPos: -2.35406; yPos: -1.44715; zPos: -0.745307 }
+ ListElement{ xPos: 2.44217; yPos: -0.642981; zPos: 0.126924 }
+ ListElement{ xPos: 1.73283; yPos: 1.67362; zPos: 1.91136 }
+ ListElement{ xPos: 1.34239; yPos: -0.434386; zPos: -0.449795 }
+ ListElement{ xPos: -0.9813; yPos: -2.72962; zPos: -3.6889 }
+ ListElement{ xPos: 1.29807; yPos: -0.448566; zPos: 2.13911 }
+ ListElement{ xPos: 0.654017; yPos: 3.54591; zPos: -1.55982 }
+ ListElement{ xPos: -1.55508; yPos: -2.64564; zPos: 0.555 }
+ ListElement{ xPos: 1.92722; yPos: -0.322513; zPos: -2.13691 }
+ ListElement{ xPos: 1.35913; yPos: -2.84853; zPos: -0.470788 }
+ ListElement{ xPos: 0.257868; yPos: -2.68874; zPos: -0.268328 }
+ ListElement{ xPos: -2.05043; yPos: -1.68405; zPos: -3.05075 }
+ ListElement{ xPos: 1.65173; yPos: -0.446801; zPos: -0.75339 }
+ ListElement{ xPos: -1.25655; yPos: 0.965275; zPos: -4.15374 }
+ ListElement{ xPos: -4.27942; yPos: -0.564403; zPos: 1.45826 }
+ ListElement{ xPos: 0.950669; yPos: -2.4416; zPos: -1.68235 }
+ ListElement{ xPos: -0.0541107; yPos: 0.882274; zPos: 3.15308 }
+ ListElement{ xPos: -1.65016; yPos: -0.886156; zPos: -3.85588 }
+ ListElement{ xPos: 0.355613; yPos: 0.217671; zPos: 4.25412 }
+ ListElement{ xPos: 0.800472; yPos: 0.847259; zPos: 3.11114 }
+ ListElement{ xPos: 1.8599; yPos: -2.16981; zPos: -2.22314 }
+ ListElement{ xPos: -2.05061; yPos: 0.164561; zPos: -0.452181 }
+ ListElement{ xPos: 0.854144; yPos: 1.84334; zPos: -1.45981 }
+ ListElement{ xPos: 1.68547; yPos: 1.56536; zPos: -1.45874 }
+ ListElement{ xPos: 1.25244; yPos: -0.844991; zPos: -2.95475 }
+ ListElement{ xPos: -1.92348; yPos: 2.32119; zPos: -1.80444 }
+ ListElement{ xPos: -0.645646; yPos: 2.45193; zPos: -3.65332 }
+ ListElement{ xPos: 4.45803; yPos: 0.527732; zPos: 3.02031 }
+ ListElement{ xPos: 2.74572; yPos: 0.287964; zPos: -1.80485 }
+ ListElement{ xPos: 0.35961; yPos: -2.56437; zPos: 3.97194 }
+ ListElement{ xPos: -0.956828; yPos: -1.28915; zPos: 1.64424 }
+ ListElement{ xPos: 0.414971; yPos: -0.235061; zPos: -2.15757 }
+ ListElement{ xPos: -0.0530542; yPos: -1.08464; zPos: -4.11853 }
+ ListElement{ xPos: 3.17203; yPos: -1.21013; zPos: -3.85806 }
+ ListElement{ xPos: 0.758948; yPos: 0.124698; zPos: -3.10188 }
+ ListElement{ xPos: -1.65404; yPos: -1.16204; zPos: -1.65357 }
+ ListElement{ xPos: -1.65985; yPos: 3.84433; zPos: 4.65101 }
+ ListElement{ xPos: 2.83444; yPos: -2.69529; zPos: -1.65021 }
+ ListElement{ xPos: 1.29814; yPos: -2.76926; zPos: -2.27139 }
+ ListElement{ xPos: 0.462382; yPos: 3.04217; zPos: 3.45153 }
+ ListElement{ xPos: -3.61944; yPos: 1.04723; zPos: -0.638308 }
+ ListElement{ xPos: 2.25235; yPos: 1.64048; zPos: 2.95175 }
+ ListElement{ xPos: -3.05826; yPos: -0.76526; zPos: -2.38243 }
+ ListElement{ xPos: -2.8506; yPos: 2.12102; zPos: -0.659444 }
+ ListElement{ xPos: -0.10046; yPos: 0.0887098; zPos: -1.63621 }
+ ListElement{ xPos: -1.55585; yPos: -1.36073; zPos: 2.2076 }
+ ListElement{ xPos: -0.474968; yPos: 1.56568; zPos: -0.302349 }
+ ListElement{ xPos: 0.36584; yPos: -2.36102; zPos: 1.35289 }
+ ListElement{ xPos: 0.224784; yPos: -0.637694; zPos: 1.62444 }
+ ListElement{ xPos: -0.658172; yPos: 1.9689; zPos: -3.13712 }
+ ListElement{ xPos: 0.646334; yPos: -1.04672; zPos: 2.59285 }
+ ListElement{ xPos: -2.63054; yPos: -1.08263; zPos: -0.851087 }
+ ListElement{ xPos: 1.45804; yPos: -2.56159; zPos: -2.66388 }
+ ListElement{ xPos: -2.45748; yPos: 0.0409116; zPos: -2.85428 }
+ ListElement{ xPos: -0.0561462; yPos: -1.24229; zPos: -1.25145 }
+ ListElement{ xPos: -2.95391; yPos: -1.80896; zPos: -2.05036 }
+ ListElement{ xPos: 4.36778; yPos: -0.969951; zPos: 3.53686 }
+ ListElement{ xPos: 2.15582; yPos: -1.67173; zPos: -0.831609 }
+ ListElement{ xPos: -1.27059; yPos: -1.14919; zPos: 1.7569 }
+ ListElement{ xPos: -1.57398; yPos: -1.28091; zPos: -0.251735 }
+ ListElement{ xPos: 2.59506; yPos: -2.6408; zPos: -0.345589 }
+ ListElement{ xPos: -1.64147; yPos: -0.360324; zPos: 3.1562 }
+ ListElement{ xPos: -0.125427; yPos: -0.641484; zPos: -3.66095 }
+ ListElement{ xPos: -1.9148; yPos: 1.8885; zPos: 2.12972 }
+ ListElement{ xPos: -2.85768; yPos: -2.28782; zPos: -1.55719 }
+ ListElement{ xPos: -1.37239; yPos: -0.485964; zPos: -2.22291 }
+ ListElement{ xPos: 0.516294; yPos: 0.281078; zPos: 0.652612 }
+ ListElement{ xPos: -1.13028; yPos: 0.246659; zPos: -2.25636 }
+ ListElement{ xPos: 1.7555; yPos: -1.41602; zPos: 0.348449 }
+ ListElement{ xPos: 1.5355; yPos: -1.32646; zPos: -2.82417 }
+ ListElement{ xPos: -0.95426; yPos: 2.0824; zPos: -0.383507 }
+ ListElement{ xPos: 2.75739; yPos: 0.241779; zPos: 0.755701 }
+ ListElement{ xPos: 0.752655; yPos: 0.56204; zPos: -1.55738 }
+ ListElement{ xPos: 1.1271; yPos: -3.76145; zPos: 0.43701 }
+ ListElement{ xPos: 0.326656; yPos: -1.24467; zPos: 2.62222 }
+ ListElement{ xPos: -0.259702; yPos: 2.68152; zPos: -3.18542 }
+ ListElement{ xPos: 1.88504; yPos: -0.760623; zPos: 4.42592 }
+ ListElement{ xPos: 0.251673; yPos: 0.472252; zPos: -1.99239 }
+ ListElement{ xPos: -1.66934; yPos: -0.129677; zPos: -2.49048 }
+ ListElement{ xPos: -1.25499; yPos: 2.36151; zPos: -2.98447 }
+ ListElement{ xPos: 2.65331; yPos: 0.0443886; zPos: 0.108819 }
+ ListElement{ xPos: -3.35439; yPos: 0.0872109; zPos: -1.33429 }
+ ListElement{ xPos: 3.35597; yPos: 0.0403626; zPos: 2.8203 }
+ ListElement{ xPos: 4.45191; yPos: 1.24824; zPos: -0.95821 }
+ ListElement{ xPos: -0.171441; yPos: -1.52622; zPos: -4.68253 }
+ ListElement{ xPos: 1.19986; yPos: 1.72992; zPos: -3.29566 }
+ ListElement{ xPos: -0.451339; yPos: 1.92976; zPos: 1.21534 }
+ ListElement{ xPos: -0.743119; yPos: -0.160688; zPos: 0.805688 }
+ ListElement{ xPos: 2.38678; yPos: 0.272829; zPos: 2.75457 }
+ ListElement{ xPos: 1.72464; yPos: 2.08232; zPos: -0.950389 }
+ ListElement{ xPos: 2.11167; yPos: 1.56576; zPos: 1.21969 }
+ ListElement{ xPos: 3.05157; yPos: -1.56838; zPos: -0.450535 }
+ ListElement{ xPos: 0.132417; yPos: -3.08279; zPos: -1.34127 }
+ ListElement{ xPos: 1.65441; yPos: -0.325204; zPos: -0.825145 }
+ ListElement{ xPos: 2.05515; yPos: -1.8417; zPos: 1.8561 }
+ ListElement{ xPos: -0.555858; yPos: 1.52007; zPos: -0.80122 }
+ ListElement{ xPos: -2.05026; yPos: 1.52773; zPos: 2.33529 }
+ ListElement{ xPos: -2.35231; yPos: -3.28716; zPos: 3.53598 }
+ ListElement{ xPos: -2.25771; yPos: 2.5667; zPos: -1.92243 }
+ ListElement{ xPos: 0.386884; yPos: -3.28674; zPos: 3.49336 }
+ ListElement{ xPos: 0.957272; yPos: -1.68124; zPos: -1.89095 }
+ ListElement{ xPos: 2.99881; yPos: 2.24992; zPos: -0.0535837 }
+ ListElement{ xPos: 3.19604; yPos: 2.92893; zPos: -2.16276 }
+ ListElement{ xPos: 2.55903; yPos: 3.12413; zPos: 2.95022 }
+ ListElement{ xPos: -0.570758; yPos: -2.85326; zPos: -0.339255 }
+ ListElement{ xPos: 0.356627; yPos: 0.641074; zPos: 0.355538 }
+ ListElement{ xPos: -1.15777; yPos: -0.162227; zPos: -0.455885 }
+ ListElement{ xPos: -2.4871; yPos: -0.885492; zPos: -0.374875 }
+ ListElement{ xPos: 1.55464; yPos: -1.48929; zPos: -0.593706 }
+ ListElement{ xPos: -0.852655; yPos: -2.08736; zPos: -1.18281 }
+ ListElement{ xPos: 0.504087; yPos: -0.879247; zPos: 1.35148 }
+ ListElement{ xPos: -2.15261; yPos: 1.04511; zPos: -3.25543 }
+ ListElement{ xPos: -0.653745; yPos: -1.32873; zPos: -3.18964 }
+ ListElement{ xPos: 0.35973; yPos: -0.844255; zPos: -1.72034 }
+ ListElement{ xPos: -2.11112; yPos: 0.962572; zPos: 2.59386 }
+ ListElement{ xPos: 1.47531; yPos: -0.693626; zPos: -3.15249 }
+ ListElement{ xPos: -1.35814; yPos: 0.767202; zPos: 3.45094 }
+ ListElement{ xPos: -3.05812; yPos: -1.26298; zPos: 1.45287 }
+ ListElement{ xPos: -1.63927; yPos: 0.893568; zPos: -1.94978 }
+ ListElement{ xPos: 0.751992; yPos: 1.68559; zPos: 2.3618 }
+ ListElement{ xPos: 0.58205; yPos: -0.769076; zPos: -0.958994 }
+ ListElement{ xPos: -2.38512; yPos: -0.166005; zPos: -1.25855 }
+ ListElement{ xPos: -0.556071; yPos: -2.28164; zPos: 1.57032 }
+ ListElement{ xPos: 0.589172; yPos: -0.244834; zPos: 0.553728 }
+ ListElement{ xPos: -0.468648; yPos: -0.927756; zPos: -0.737048 }
+ ListElement{ xPos: -2.66659; yPos: -1.64374; zPos: -0.995568 }
+ ListElement{ xPos: 0.251499; yPos: -1.24569; zPos: 0.95028 }
+ ListElement{ xPos: 0.737721; yPos: 2.88575; zPos: 0.448918 }
+ ListElement{ xPos: -0.634421; yPos: -1.84377; zPos: -2.47094 }
+ ListElement{ xPos: 0.556349; yPos: 2.86774; zPos: 1.62621 }
+ ListElement{ xPos: -3.29644; yPos: 3.28642; zPos: -3.45459 }
+ ListElement{ xPos: -1.45045; yPos: 2.52138; zPos: 2.75329 }
+ ListElement{ xPos: 1.87449; yPos: -2.68651; zPos: 3.60371 }
+ ListElement{ xPos: -0.656424; yPos: -2.56828; zPos: 1.35509 }
+ ListElement{ xPos: 1.95771; yPos: -1.48325; zPos: -3.85265 }
+ ListElement{ xPos: 3.85074; yPos: 0.0825779; zPos: -1.65283 }
+ ListElement{ xPos: -1.17278; yPos: -1.69258; zPos: -1.05875 }
+ ListElement{ xPos: 1.25754; yPos: -0.0439433; zPos: 1.3571 }
+ ListElement{ xPos: 2.91459; yPos: 2.08715; zPos: 0.259842 }
+ ListElement{ xPos: 0.748196; yPos: 2.52132; zPos: 0.659051 }
+ ListElement{ xPos: -1.85745; yPos: -1.88355; zPos: 1.05259 }
+ ListElement{ xPos: 1.69311; yPos: 1.12299; zPos: -3.05453 }
+ ListElement{ xPos: -2.86301; yPos: 0.123274; zPos: 0.559289 }
+ ListElement{ xPos: -1.43146; yPos: 1.64425; zPos: -1.95053 }
+ ListElement{ xPos: 2.35287; yPos: 0.414621; zPos: -0.950807 }
+ ListElement{ xPos: 0.952585; yPos: -0.280452; zPos: -0.844588 }
+ ListElement{ xPos: -1.53836; yPos: -1.76396; zPos: 2.51742 }
+ ListElement{ xPos: -3.05431; yPos: 2.45; zPos: -0.26571 }
+ ListElement{ xPos: -0.637412; yPos: 1.12028; zPos: -0.587387 }
+ ListElement{ xPos: -1.71017; yPos: -0.728497; zPos: -1.05087 }
+ ListElement{ xPos: 0.454027; yPos: 0.849208; zPos: -0.151716 }
+ ListElement{ xPos: -3.54846; yPos: 0.367137; zPos: 1.1484 }
+ ListElement{ xPos: 0.200816; yPos: -2.08832; zPos: 0.255433 }
+ ListElement{ xPos: -2.15817; yPos: 0.725338; zPos: 0.852676 }
+ ListElement{ xPos: -2.45708; yPos: -0.725538; zPos: -0.859435 }
+ ListElement{ xPos: 4.25339; yPos: 1.84177; zPos: -0.555145 }
+ ListElement{ xPos: 0.119319; yPos: -1.32041; zPos: -1.45864 }
+ ListElement{ xPos: -3.65177; yPos: 0.361323; zPos: 0.351554 }
+ ListElement{ xPos: 0.928598; yPos: 0.321024; zPos: -3.64759 }
+ ListElement{ xPos: -0.250062; yPos: 1.84912; zPos: 0.949887 }
+ ListElement{ xPos: 3.59593; yPos: 0.929451; zPos: -2.15224 }
+ ListElement{ xPos: 0.658599; yPos: 2.36796; zPos: 4.11632 }
+ ListElement{ xPos: 0.55841; yPos: -1.08657; zPos: 0.258326 }
+ ListElement{ xPos: 1.9419; yPos: 0.0488641; zPos: -3.75375 }
+ ListElement{ xPos: 0.0589998; yPos: 0.521351; zPos: -3.85723 }
+ ListElement{ xPos: 3.45108; yPos: 0.562199; zPos: 4.20946 }
+ ListElement{ xPos: -0.255073; yPos: 2.36504; zPos: -3.556 }
+ ListElement{ xPos: 1.95848; yPos: 1.28698; zPos: 4.25014 }
+ ListElement{ xPos: 1.85411; yPos: 3.12131; zPos: 0.652769 }
+ ListElement{ xPos: -3.3589; yPos: 0.801817; zPos: -1.5591 }
+ ListElement{ xPos: 2.48128; yPos: -0.163406; zPos: 1.25243 }
+ ListElement{ xPos: 2.52135; yPos: 0.960467; zPos: 1.45432 }
+ ListElement{ xPos: 0.827496; yPos: -0.163021; zPos: -0.558886 }
+ ListElement{ xPos: -3.45032; yPos: -0.0831453; zPos: 0.851212 }
+ ListElement{ xPos: -3.45334; yPos: 0.855944; zPos: 1.35596 }
+ ListElement{ xPos: -0.834644; yPos: 0.245598; zPos: -1.23878 }
+ ListElement{ xPos: 3.64558; yPos: 1.16831; zPos: -0.18559 }
+ ListElement{ xPos: -1.45919; yPos: -3.08196; zPos: -0.329805 }
+ ListElement{ xPos: -3.65715; yPos: -1.04485; zPos: 0.159208 }
+ ListElement{ xPos: 1.35463; yPos: -0.766382; zPos: 0.558632 }
+ ListElement{ xPos: -2.75899; yPos: -1.67431; zPos: -1.55069 }
+ ListElement{ xPos: 1.67539; yPos: 2.04337; zPos: 0.912884 }
+ ListElement{ xPos: 3.51677; yPos: -3.24285; zPos: 0.170272 }
+ ListElement{ xPos: -4.25189; yPos: 0.56589; zPos: -4.35936 }
+ ListElement{ xPos: -2.68545; yPos: -0.448243; zPos: 0.540342 }
+ ListElement{ xPos: 0.279844; yPos: -0.641466; zPos: -0.353986 }
+ ListElement{ xPos: -3.27626; yPos: -3.52006; zPos: 1.77644 }
+ ListElement{ xPos: -0.724096; yPos: -1.84647; zPos: -2.45271 }
+ ListElement{ xPos: -4.18603; yPos: 0.123376; zPos: 3.85066 }
+ ListElement{ xPos: -4.05156; yPos: 0.0499386; zPos: -0.332945 }
+ ListElement{ xPos: 2.69508; yPos: 2.32777; zPos: 1.26256 }
+ ListElement{ xPos: -0.353726; yPos: 1.07252; zPos: -0.738837 }
+ ListElement{ xPos: -0.947178; yPos: 0.36459; zPos: 1.55593 }
+ ListElement{ xPos: -0.058346; yPos: 2.44781; zPos: -4.35023 }
+ ListElement{ xPos: 1.51586; yPos: -0.961109; zPos: -3.43483 }
+ ListElement{ xPos: -2.8852; yPos: 2.08863; zPos: -1.75468 }
+ ListElement{ xPos: -0.297867; yPos: 0.722757; zPos: 0.91355 }
+ ListElement{ xPos: -1.12917; yPos: -1.68328; zPos: 0.175315 }
+ ListElement{ xPos: -1.24248; yPos: -0.323519; zPos: -0.854841 }
+ ListElement{ xPos: 0.751943; yPos: 0.564075; zPos: 3.95073 }
+ ListElement{ xPos: 1.15436; yPos: 2.81813; zPos: 0.653114 }
+ ListElement{ xPos: -2.55058; yPos: -2.56486; zPos: 0.756618 }
+ ListElement{ xPos: 0.959794; yPos: 0.845224; zPos: -0.854001 }
+ ListElement{ xPos: -2.15033; yPos: 0.248556; zPos: -3.16151 }
+ ListElement{ xPos: 0.353224; yPos: -1.68637; zPos: 0.457949 }
+ ListElement{ xPos: -0.753237; yPos: -2.48313; zPos: -0.355373 }
+ ListElement{ xPos: 0.296585; yPos: 2.04822; zPos: 0.198473 }
+ ListElement{ xPos: -2.4737; yPos: 0.682952; zPos: 1.85349 }
+ ListElement{ xPos: 1.9027; yPos: 0.882796; zPos: 1.45908 }
+ ListElement{ xPos: 0.254799; yPos: 1.92572; zPos: -1.70848 }
+ ListElement{ xPos: -0.951602; yPos: -0.698987; zPos: -2.22682 }
+ ListElement{ xPos: 0.262582; yPos: -2.44093; zPos: 1.05636 }
+ ListElement{ xPos: 0.385415; yPos: -0.685667; zPos: -3.35928 }
+ ListElement{ xPos: 0.055981; yPos: 0.523585; zPos: -3.36093 }
+ ListElement{ xPos: -0.0518635; yPos: -0.889068; zPos: -0.840648 }
+ ListElement{ xPos: 0.455171; yPos: 2.84624; zPos: -1.98276 }
+ ListElement{ xPos: 2.85475; yPos: -0.685697; zPos: -2.45695 }
+ ListElement{ xPos: -1.05047; yPos: -1.92121; zPos: 0.931666 }
+ ListElement{ xPos: -2.75962; yPos: -0.164458; zPos: -1.55261 }
+ ListElement{ xPos: 1.91811; yPos: 1.65767; zPos: 3.15004 }
+ ListElement{ xPos: -2.25653; yPos: 0.856735; zPos: -4.351 }
+ ListElement{ xPos: 1.89178; yPos: -0.728669; zPos: -3.8803 }
+ ListElement{ xPos: -3.25958; yPos: -1.16223; zPos: -1.85148 }
+ ListElement{ xPos: -1.6291; yPos: -2.32967; zPos: -0.874786 }
+ ListElement{ xPos: 3.17524; yPos: 0.327351; zPos: 2.15337 }
+ ListElement{ xPos: -1.05094; yPos: -0.560694; zPos: -3.4581 }
+ ListElement{ xPos: 0.759785; yPos: -1.0801; zPos: -0.257876 }
+ ListElement{ xPos: -0.4597; yPos: -2.2404; zPos: 2.54341 }
+ ListElement{ xPos: 0.242266; yPos: 0.121832; zPos: 0.780878 }
+ ListElement{ xPos: -1.6573; yPos: 1.56049; zPos: -1.61749 }
+ ListElement{ xPos: 1.39912; yPos: -2.84395; zPos: -0.25965 }
+ ListElement{ xPos: 0.552342; yPos: 1.36924; zPos: 2.95278 }
+ ListElement{ xPos: -1.92932; yPos: -0.883981; zPos: 0.0589583 }
+ ListElement{ xPos: -1.9026; yPos: 0.56297; zPos: -0.723523 }
+ ListElement{ xPos: -1.25867; yPos: -0.529617; zPos: 2.3503 }
+ ListElement{ xPos: 2.16527; yPos: -0.723364; zPos: -1.45609 }
+ ListElement{ xPos: -0.984608; yPos: -0.720375; zPos: -2.05144 }
+ ListElement{ xPos: 0.946803; yPos: -0.969188; zPos: -3.14625 }
+ ListElement{ xPos: 2.7986; yPos: -2.36069; zPos: 1.25827 }
+ ListElement{ xPos: 3.37979; yPos: -1.11699; zPos: -3.55116 }
+ ListElement{ xPos: -0.753992; yPos: -1.9649; zPos: 2.98548 }
+ ListElement{ xPos: -0.456321; yPos: 0.525303; zPos: -0.109174 }
+ ListElement{ xPos: 0.8642; yPos: 0.153147; zPos: -3.34749 }
+ ListElement{ xPos: -0.450507; yPos: -0.443265; zPos: -2.8325 }
+ ListElement{ xPos: -3.24876; yPos: 3.12791; zPos: 0.576143 }
+ ListElement{ xPos: -3.14755; yPos: 2.84502; zPos: -0.45749 }
+ ListElement{ xPos: 0.226819; yPos: -1.28172; zPos: 0.939501 }
+ ListElement{ xPos: -0.650725; yPos: -1.40317; zPos: -1.35211 }
+ ListElement{ xPos: -0.451625; yPos: 1.84271; zPos: -0.950536 }
+ ListElement{ xPos: -1.36693; yPos: 0.850218; zPos: -1.09799 }
+ ListElement{ xPos: 2.35374; yPos: -0.28759; zPos: 1.55815 }
+ ListElement{ xPos: 2.60577; yPos: -2.46765; zPos: 1.2633 }
+ ListElement{ xPos: 1.21562; yPos: -1.72153; zPos: -0.4034 }
+ ListElement{ xPos: -2.43216; yPos: 3.04268; zPos: 1.90109 }
+ ListElement{ xPos: -1.85365; yPos: -0.16523; zPos: -2.98947 }
+ ListElement{ xPos: -0.953475; yPos: -2.76164; zPos: 2.53396 }
+ ListElement{ xPos: 2.55264; yPos: -0.645611; zPos: 3.25479 }
+ ListElement{ xPos: -0.675476; yPos: -0.724382; zPos: -1.4566 }
+ ListElement{ xPos: 0.801062; yPos: 0.16778; zPos: 2.21815 }
+ ListElement{ xPos: 0.680443; yPos: 0.0407888; zPos: 3.27279 }
+ ListElement{ xPos: -3.75426; yPos: -0.247624; zPos: 0.26307 }
+ ListElement{ xPos: 0.427609; yPos: -0.322312; zPos: 0.652005 }
+ ListElement{ xPos: -2.17428; yPos: -3.68643; zPos: 0.256619 }
+ ListElement{ xPos: 0.456732; yPos: -2.44858; zPos: 3.13051 }
+ ListElement{ xPos: 0.524175; yPos: -1.88231; zPos: -1.93171 }
+ ListElement{ xPos: 0.92311; yPos: 1.8354; zPos: -1.2502 }
+ ListElement{ xPos: 2.69502; yPos: 2.25543; zPos: -4.25127 }
+ ListElement{ xPos: 0.259357; yPos: 2.28099; zPos: -0.476734 }
+ ListElement{ xPos: -0.327316; yPos: -1.24908; zPos: 0.78628 }
+ ListElement{ xPos: 0.190362; yPos: -3.26019; zPos: 0.0545844 }
+ ListElement{ xPos: -1.25409; yPos: -0.761609; zPos: 2.65361 }
+ ListElement{ xPos: 2.86816; yPos: 0.443709; zPos: 0.556137 }
+ ListElement{ xPos: 2.60289; yPos: -0.680561; zPos: 0.248414 }
+ ListElement{ xPos: 1.75631; yPos: -0.162859; zPos: -3.62488 }
+ ListElement{ xPos: -0.559754; yPos: -0.16222; zPos: 2.35858 }
+ ListElement{ xPos: 0.157552; yPos: -1.72639; zPos: -0.48056 }
+ ListElement{ xPos: 3.69492; yPos: -0.848265; zPos: -0.256413 }
+ ListElement{ xPos: -1.4264; yPos: -1.48589; zPos: -2.724 }
+ ListElement{ xPos: 1.15372; yPos: -0.27228; zPos: -2.75499 }
+ ListElement{ xPos: -1.85159; yPos: 1.76577; zPos: -0.858854 }
+ ListElement{ xPos: 0.0580466; yPos: -0.41133; zPos: 1.05649 }
+ ListElement{ xPos: -1.25289; yPos: 0.528142; zPos: -0.386138 }
+ ListElement{ xPos: -0.858101; yPos: -0.245127; zPos: 1.95078 }
+ ListElement{ xPos: -1.95302; yPos: -0.0862415; zPos: -1.95806 }
+ ListElement{ xPos: -2.79133; yPos: -0.527094; zPos: -0.356931 }
+ ListElement{ xPos: 0.110597; yPos: 0.167534; zPos: 4.12784 }
+ ListElement{ xPos: -0.637771; yPos: -0.526587; zPos: -1.25734 }
+ ListElement{ xPos: -2.311; yPos: -0.489068; zPos: -2.8594 }
+ ListElement{ xPos: -0.352617; yPos: -1.23939; zPos: -1.85435 }
+ ListElement{ xPos: 1.78814; yPos: -0.265883; zPos: 3.35913 }
+ ListElement{ xPos: 2.75557; yPos: -2.32271; zPos: 3.15559 }
+ ListElement{ xPos: 2.85426; yPos: 0.443661; zPos: 0.921828 }
+ ListElement{ xPos: -2.14262; yPos: 0.400863; zPos: 1.11614 }
+ ListElement{ xPos: 4.45496; yPos: -0.488668; zPos: -3.7533 }
+ ListElement{ xPos: 0.754719; yPos: -1.44165; zPos: 0.853323 }
+ ListElement{ xPos: -0.856506; yPos: 1.76559; zPos: 1.05702 }
+ ListElement{ xPos: -0.418565; yPos: -0.921031; zPos: -2.43699 }
+ ListElement{ xPos: -1.29292; yPos: -0.282271; zPos: -1.62927 }
+ ListElement{ xPos: -0.759531; yPos: 0.566692; zPos: -0.750991 }
+ ListElement{ xPos: 0.559787; yPos: 1.72479; zPos: -0.26667 }
+ ListElement{ xPos: 2.75533; yPos: -0.245187; zPos: -0.543844 }
+ ListElement{ xPos: -2.27924; yPos: -1.04154; zPos: -4.05156 }
+ ListElement{ xPos: 3.35852; yPos: -0.561129; zPos: -2.98986 }
+ ListElement{ xPos: 2.41843; yPos: -0.321119; zPos: -1.55651 }
+ ListElement{ xPos: 0.85431; yPos: -0.883719; zPos: -2.17826 }
+ ListElement{ xPos: 0.417867; yPos: 0.242995; zPos: -0.456326 }
+ ListElement{ xPos: -4.17449; yPos: -0.720086; zPos: 0.355145 }
+ ListElement{ xPos: -0.577386; yPos: 0.0440364; zPos: -0.950268 }
+ ListElement{ xPos: -2.8156; yPos: 2.92346; zPos: 0.958713 }
+ ListElement{ xPos: -1.65138; yPos: 0.963561; zPos: 1.25265 }
+ ListElement{ xPos: 1.45117; yPos: 0.845424; zPos: 0.252789 }
+ ListElement{ xPos: 2.27848; yPos: -1.76777; zPos: 0.0117707 }
+ ListElement{ xPos: -0.754248; yPos: 1.08381; zPos: -2.15345 }
+ ListElement{ xPos: -3.15415; yPos: -0.162292; zPos: -1.15347 }
+ ListElement{ xPos: 2.55396; yPos: -1.68912; zPos: 1.15698 }
+ ListElement{ xPos: 0.159561; yPos: 1.84202; zPos: 0.428428 }
+ ListElement{ xPos: -1.58079; yPos: 2.04207; zPos: 3.29578 }
+ ListElement{ xPos: -1.05711; yPos: -0.843112; zPos: -1.98122 }
+ ListElement{ xPos: 0.138866; yPos: -2.96642; zPos: -0.212247 }
+ ListElement{ xPos: 2.6778; yPos: 0.686972; zPos: -2.6553 }
+ ListElement{ xPos: -0.498291; yPos: -0.362846; zPos: -1.0538 }
+ ListElement{ xPos: 1.19872; yPos: 0.0476518; zPos: -2.42077 }
+ ListElement{ xPos: -2.3972; yPos: 1.40393; zPos: -0.1943 }
+ ListElement{ xPos: 0.85034; yPos: -1.24222; zPos: 1.5646 }
+ ListElement{ xPos: 0.142174; yPos: 0.249903; zPos: -2.75252 }
+ ListElement{ xPos: 1.15197; yPos: 1.32746; zPos: -1.70104 }
+ ListElement{ xPos: 0.359387; yPos: -1.65115; zPos: -2.75243 }
+ ListElement{ xPos: 0.357917; yPos: -1.36406; zPos: 2.55102 }
+ ListElement{ xPos: -1.65268; yPos: -0.28339; zPos: 2.75665 }
+ ListElement{ xPos: -3.82681; yPos: -3.28984; zPos: 2.55128 }
+ ListElement{ xPos: -2.61371; yPos: 1.08247; zPos: -0.457068 }
+ ListElement{ xPos: 1.67152; yPos: -2.25527; zPos: 2.45819 }
+ ListElement{ xPos: -0.753832; yPos: 1.1682; zPos: -1.95913 }
+ ListElement{ xPos: -2.05131; yPos: 3.04537; zPos: 1.91954 }
+ ListElement{ xPos: -0.695378; yPos: 2.88924; zPos: 1.41965 }
+ ListElement{ xPos: 3.25767; yPos: -2.76934; zPos: -0.354127 }
+ ListElement{ xPos: -0.746795; yPos: 1.36034; zPos: 1.85953 }
+ ListElement{ xPos: 0.859135; yPos: 1.08222; zPos: 0.959116 }
+ ListElement{ xPos: 1.15898; yPos: 1.32443; zPos: 3.41981 }
+ ListElement{ xPos: 3.67954; yPos: 0.447177; zPos: -0.414029 }
+ ListElement{ xPos: 0.907323; yPos: 2.12852; zPos: 1.95837 }
+ ListElement{ xPos: -0.683456; yPos: -0.247536; zPos: 1.05621 }
+ ListElement{ xPos: -1.67809; yPos: 0.641544; zPos: -1.31143 }
+ ListElement{ xPos: -1.30192; yPos: -0.677394; zPos: -1.95159 }
+ ListElement{ xPos: -0.105665; yPos: 0.365205; zPos: -1.2567 }
+ ListElement{ xPos: 1.12189; yPos: -1.48969; zPos: 0.957166 }
+ ListElement{ xPos: 1.25554; yPos: -1.92186; zPos: -0.904086 }
+ ListElement{ xPos: 0.117786; yPos: 2.23836; zPos: -0.498009 }
+ ListElement{ xPos: -2.85788; yPos: 0.643364; zPos: 0.55867 }
+ ListElement{ xPos: -1.66115; yPos: 2.56146; zPos: -2.28632 }
+ ListElement{ xPos: -3.29334; yPos: -0.0894367; zPos: -0.656519 }
+ ListElement{ xPos: 3.15561; yPos: -0.769732; zPos: 1.15695 }
+ ListElement{ xPos: 1.25684; yPos: 0.64652; zPos: -2.6002 }
+ ListElement{ xPos: 2.65231; yPos: -3.52625; zPos: 1.55617 }
+ ListElement{ xPos: -1.8573; yPos: -1.76276; zPos: -1.74075 }
+ ListElement{ xPos: -1.55648; yPos: 1.2592; zPos: 2.1585 }
+ ListElement{ xPos: -0.555522; yPos: 2.88068; zPos: -2.85423 }
+ ListElement{ xPos: -3.14249; yPos: -0.288592; zPos: -3.35534 }
+ ListElement{ xPos: 2.45413; yPos: 0.0854903; zPos: -2.20507 }
+ ListElement{ xPos: -2.05464; yPos: 0.887836; zPos: -0.658349 }
+ ListElement{ xPos: 1.12708; yPos: -0.568106; zPos: -3.65865 }
+ ListElement{ xPos: -0.59147; yPos: -0.685439; zPos: 0.301612 }
+ ListElement{ xPos: 0.473679; yPos: 0.886411; zPos: -1.65386 }
+ ListElement{ xPos: 1.65166; yPos: 0.166741; zPos: 0.751119 }
+ ListElement{ xPos: -0.299287; yPos: 1.72233; zPos: 0.618559 }
+ ListElement{ xPos: 1.15181; yPos: -0.488026; zPos: 0.124448 }
+ ListElement{ xPos: 0.0561315; yPos: 1.04877; zPos: 2.15922 }
+ ListElement{ xPos: 0.154258; yPos: -0.64401; zPos: -1.31179 }
+ ListElement{ xPos: 1.75863; yPos: -1.88571; zPos: -2.8537 }
+ ListElement{ xPos: 3.35024; yPos: 1.28154; zPos: -1.05461 }
+ ListElement{ xPos: -3.71738; yPos: -2.88631; zPos: -1.05314 }
+ ListElement{ xPos: -1.78258; yPos: 3.08967; zPos: 0.150476 }
+ ListElement{ xPos: 3.47828; yPos: -2.524; zPos: -2.45502 }
+ ListElement{ xPos: -0.159138; yPos: 0.160633; zPos: -0.338796 }
+ ListElement{ xPos: -2.15885; yPos: -0.82959; zPos: 1.25022 }
+ ListElement{ xPos: -1.95268; yPos: -0.841195; zPos: -3.19487 }
+ ListElement{ xPos: -0.281381; yPos: -0.887435; zPos: -3.55807 }
+ ListElement{ xPos: 0.415164; yPos: 0.326482; zPos: -1.55411 }
+ ListElement{ xPos: 1.92868; yPos: -2.84771; zPos: -0.556196 }
+ ListElement{ xPos: 1.05804; yPos: 1.32866; zPos: 0.66596 }
+ ListElement{ xPos: 2.46545; yPos: 1.00747; zPos: 2.35957 }
+ ListElement{ xPos: -0.77358; yPos: 0.284677; zPos: -1.38805 }
+ ListElement{ xPos: 0.851046; yPos: 0.960742; zPos: -2.70934 }
+ ListElement{ xPos: -0.858208; yPos: -0.884015; zPos: 1.16663 }
+ ListElement{ xPos: 1.55291; yPos: 0.282705; zPos: -3.18254 }
+ ListElement{ xPos: 1.99034; yPos: 0.286298; zPos: -1.75821 }
+ ListElement{ xPos: 0.259097; yPos: -2.04379; zPos: -0.858936 }
+ ListElement{ xPos: -1.5956; yPos: 2.04693; zPos: -1.35234 }
+ ListElement{ xPos: -0.775432; yPos: 1.24465; zPos: 1.95935 }
+ ListElement{ xPos: 1.65595; yPos: -1.04954; zPos: -0.954437 }
+ ListElement{ xPos: -2.35417; yPos: -1.76095; zPos: -0.248306 }
+ ListElement{ xPos: 0.855717; yPos: -2.92161; zPos: 3.4496 }
+ ListElement{ xPos: -0.717941; yPos: 2.52993; zPos: 1.25007 }
+ ListElement{ xPos: -3.42927; yPos: 0.673305; zPos: 0.995742 }
+
+ ListElement{ xPos: 8.00000; yPos: -2.05136; zPos: 4.02113 }
+ ListElement{ xPos: 7.88929; yPos: -2.2029; zPos: 5.0000 }
+ ListElement{ xPos: 7.61596; yPos: -2.44569; zPos: 4.54892 }
+ ListElement{ xPos: 7.41949; yPos: -2.64169; zPos: 3.82339 }
+ ListElement{ xPos: 7.21192; yPos: -2.87947; zPos: 4.89423 }
+ ListElement{ xPos: 7.08346; yPos: -2.38649; zPos: 4.19212 }
+ ListElement{ xPos: 6.90279; yPos: -3.33038; zPos: 4.9273 }
+ ListElement{ xPos: 6.78959; yPos: -3.55575; zPos: 3.55127 }
+ ListElement{ xPos: 6.57074; yPos: -3.75902; zPos: 3.32517 }
+ ListElement{ xPos: 6.30756; yPos: -3.40499; zPos: 3.78366 }
+ ListElement{ xPos: 7.90893; yPos: -3.3237; zPos: 2.48012 }
+ ListElement{ xPos: 6.24078; yPos: -4.04978; zPos: 3.47459 }
+ ListElement{ xPos: 7.93452; yPos: -4.6865; zPos: 4.08057 }
+ ListElement{ xPos: 5.98731; yPos: -2.26113; zPos: 2.82166 }
+ ListElement{ xPos: 5.46898; yPos: -3.99581; zPos: 3.25024 }
+ ListElement{ xPos: 7.92353; yPos: -3.34471; zPos: 3.42168 }
+ ListElement{ xPos: 6.8456; yPos: -5.00000; zPos: 2.36145 }
+ ListElement{ xPos: 7.62888; yPos: -3.82465; zPos: 2.7879 }
+ ListElement{ xPos: 7.18034; yPos: -3.94376; zPos: 2.74348 }
+ ListElement{ xPos: 6.02527; yPos: -4.36523; zPos: 2.56247 }
+ ListElement{ xPos: 7.82353; yPos: -3.04345; zPos: 2.62974 }
+ ListElement{ xPos: 7.82539; yPos: -3.6881; zPos: 2.96164 }
+ ListElement{ xPos: 7.10508; yPos: -3.6174; zPos: 4.22416 }
+ ListElement{ xPos: 7.64684; yPos: -3.88431; zPos: 3.9336 }
+ ListElement{ xPos: 7.46411; yPos: -4.21516; zPos: 3.32001 }
+ ListElement{ xPos: 6.98777; yPos: -3.94024; zPos: 3.14694 }
+ ListElement{ xPos: 7.36355; yPos: -4.24875; zPos: 1.72061 }
+ ListElement{ xPos: 7.92773; yPos: -4.52065; zPos: 2.62078 }
+ ListElement{ xPos: 6.04598; yPos: -4.48682; zPos: 2.74494 }
+ ListElement{ xPos: 7.83353; yPos: -3.9271; zPos: 3.82815 }
+ ListElement{ xPos: 6.76279; yPos: -3.58031; zPos: 2.92525 }
+ ListElement{ xPos: 7.14794; yPos: -4.42742; zPos: 2.62365 }
+ ListElement{ xPos: 5.32696; yPos: -3.28733; zPos: 3.34916 }
+ ListElement{ xPos: 6.43655; yPos: -4.60784; zPos: 2.41548 }
+ ListElement{ xPos: 5.66033; yPos: -4.98497; zPos: 3.72282 }
+ }
+}
diff --git a/examples/qmlcustominput/qml/qmlcustominput/main.qml b/examples/qmlcustominput/qml/qmlcustominput/main.qml
new file mode 100644
index 00000000..f777fd6b
--- /dev/null
+++ b/examples/qmlcustominput/qml/qmlcustominput/main.qml
@@ -0,0 +1,206 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import QtQuick.Layouts 1.0
+import QtDataVisualization 1.0
+import "."
+
+Item {
+ id: mainView
+ width: 1280
+ height: 720
+ visible: true
+
+ Data {
+ id: graphData
+ }
+
+ Item {
+ id: dataView
+ anchors.bottom: parent.bottom
+ width: parent.width
+ height: parent.height - buttonLayout.height
+
+ //! [0]
+ Scatter3D {
+ //! [0]
+ id: scatterGraph
+ width: dataView.width
+ height: dataView.height
+ theme: Theme3D { type: Theme3D.ThemeDigia }
+ shadowQuality: AbstractGraph3D.ShadowQualityMedium
+ scene.activeCamera.yRotation: 30.0
+ //! [1]
+ inputHandler: null
+ //! [1]
+
+ Scatter3DSeries {
+ id: scatterSeries
+ itemLabelFormat: "X:@xLabel Y:@yLabel Z:@zLabel"
+ mesh: Abstract3DSeries.MeshCube
+
+ ItemModelScatterDataProxy {
+ itemModel: graphData.model
+ xPosRole: "xPos"
+ yPosRole: "yPos"
+ zPosRole: "zPos"
+ }
+ }
+ }
+
+ //! [2]
+ MouseArea {
+ id: inputArea
+ anchors.fill: parent
+ hoverEnabled: true
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ property int mouseX: -1
+ property int mouseY: -1
+ //! [2]
+
+ //! [3]
+ onPositionChanged: {
+ mouseX = mouse.x;
+ mouseY = mouse.y;
+ }
+ //! [3]
+
+ //! [5]
+ onWheel: {
+ // Adjust zoom level based on what zoom range we're in.
+ var zoomLevel = scatterGraph.scene.activeCamera.zoomLevel;
+ if (zoomLevel > 100)
+ zoomLevel += wheel.angleDelta.y / 12.0;
+ else if (zoomLevel > 50)
+ zoomLevel += wheel.angleDelta.y / 60.0;
+ else
+ zoomLevel += wheel.angleDelta.y / 120.0;
+ if (zoomLevel > 500)
+ zoomLevel = 500;
+ else if (zoomLevel < 10)
+ zoomLevel = 10;
+
+ scatterGraph.scene.activeCamera.zoomLevel = zoomLevel;
+ }
+ //! [5]
+ }
+
+ //! [4]
+ Timer {
+ id: reselectTimer
+ interval: 10
+ running: true
+ repeat: true
+ onTriggered: {
+ scatterGraph.scene.selectionQueryPosition = Qt.point(inputArea.mouseX, inputArea.mouseY);
+ }
+ }
+ //! [4]
+ }
+
+ //! [6]
+ NumberAnimation {
+ id: cameraAnimationX
+ loops: Animation.Infinite
+ running: true
+ target: scatterGraph.scene.activeCamera
+ property:"xRotation"
+ from: 0.0
+ to: 360.0
+ duration: 20000
+ }
+ //! [6]
+
+
+ //! [7]
+ SequentialAnimation {
+ id: cameraAnimationY
+ loops: Animation.Infinite
+ running: true
+
+ NumberAnimation {
+ target: scatterGraph.scene.activeCamera
+ property:"yRotation"
+ from: 5.0
+ to: 45.0
+ duration: 9000
+ easing.type: Easing.InOutSine
+ }
+
+ NumberAnimation {
+ target: scatterGraph.scene.activeCamera
+ property:"yRotation"
+ from: 45.0
+ to: 5.0
+ duration: 9000
+ easing.type: Easing.InOutSine
+ }
+ }
+ //! [7]
+
+ RowLayout {
+ id: buttonLayout
+ Layout.minimumHeight: shadowToggle.height
+ width: parent.width
+ anchors.left: parent.left
+ spacing: 0
+
+ NewButton {
+ id: shadowToggle
+ Layout.fillHeight: true
+ Layout.minimumWidth: parent.width / 3 // 3 buttons divided equally in the layout
+ text: "Hide Shadows"
+
+ onClicked: {
+ if (scatterGraph.shadowQuality === AbstractGraph3D.ShadowQualityNone) {
+ scatterGraph.shadowQuality = AbstractGraph3D.ShadowQualitySoftMedium;
+ text = "Hide Shadows";
+ } else {
+ scatterGraph.shadowQuality = AbstractGraph3D.ShadowQualityNone;
+ text = "Show Shadows";
+ }
+ }
+ }
+
+ NewButton {
+ id: cameraToggle
+ Layout.fillHeight: true
+ Layout.minimumWidth: parent.width / 3
+ text: "Animate Camera"
+
+ onClicked: {
+ cameraAnimationX.paused = !cameraAnimationX.paused;
+ cameraAnimationY.paused = cameraAnimationX.paused;
+ if (cameraAnimationX.paused) {
+ text = "Animate Camera";
+ } else {
+ text = "Pause Camera";
+ }
+ }
+ }
+
+ NewButton {
+ id: exitButton
+ Layout.fillHeight: true
+ Layout.minimumWidth: parent.width / 3
+ text: "Quit"
+ onClicked: Qt.quit(0);
+ }
+ }
+}
diff --git a/examples/qmlcustominput/qml/qmlcustominput/newbutton.qml b/examples/qmlcustominput/qml/qmlcustominput/newbutton.qml
new file mode 100644
index 00000000..e44c9d1a
--- /dev/null
+++ b/examples/qmlcustominput/qml/qmlcustominput/newbutton.qml
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import QtQuick.Controls 1.0
+import QtQuick.Controls.Styles 1.0
+
+Item {
+ id: newbutton
+
+ property alias text: buttonText.text
+
+ signal clicked
+
+ implicitWidth: buttonText.implicitWidth + 5
+ implicitHeight: buttonText.implicitHeight + 10
+
+ Button {
+ id: buttonText
+ width: parent.width
+ height: parent.height
+
+ style: ButtonStyle {
+ label: Component {
+ Text {
+ text: buttonText.text
+ clip: true
+ wrapMode: Text.WordWrap
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ anchors.fill: parent
+ }
+ }
+ }
+ onClicked: newbutton.clicked()
+ }
+}
diff --git a/examples/qmlcustominput/qmlcustominput.desktop b/examples/qmlcustominput/qmlcustominput.desktop
new file mode 100644
index 00000000..536f87a9
--- /dev/null
+++ b/examples/qmlcustominput/qmlcustominput.desktop
@@ -0,0 +1,11 @@
+[Desktop Entry]
+Encoding=UTF-8
+Version=1.0
+Type=Application
+Terminal=false
+Name=qmlcustominput
+Exec=/opt/qmlcustominput/bin/qmlcustominput
+Icon=qmlcustominput64
+X-Window-Icon=
+X-HildonDesk-ShowInToolbar=true
+X-Osso-Type=application/x-executable
diff --git a/examples/qmlcustominput/qmlcustominput.pro b/examples/qmlcustominput/qmlcustominput.pro
new file mode 100644
index 00000000..c58eff49
--- /dev/null
+++ b/examples/qmlcustominput/qmlcustominput.pro
@@ -0,0 +1,26 @@
+!include( ../examples.pri ) {
+ error( "Couldn't find the examples.pri file!" )
+}
+
+QT += widgets
+
+# Add more folders to ship with the application, here
+folder_01.source = qml/qmlcustominput
+folder_01.target = qml
+DEPLOYMENTFOLDERS = folder_01
+
+# Additional import path used to resolve QML modules in Creator's code model
+QML_IMPORT_PATH =
+
+# The .cpp file which was generated for your project. Feel free to hack it.
+SOURCES += main.cpp
+
+# Please do not modify the following two lines. Required for deployment.
+include(qtquick2applicationviewer/qtquick2applicationviewer.pri)
+qtcAddDeployment()
+
+RESOURCES += \
+ qmlcustominput.qrc
+
+OTHER_FILES += doc/src/* \
+ doc/images/*
diff --git a/examples/qmlcustominput/qmlcustominput.qrc b/examples/qmlcustominput/qmlcustominput.qrc
new file mode 100644
index 00000000..5e1ff40c
--- /dev/null
+++ b/examples/qmlcustominput/qmlcustominput.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/qml">
+ <file alias="main.qml">qml/qmlcustominput/main.qml</file>
+ <file alias="Data.qml">qml/qmlcustominput/data.qml</file>
+ <file alias="NewButton.qml">qml/qmlcustominput/newbutton.qml</file>
+ </qresource>
+</RCC>
diff --git a/examples/qmlcustominput/qmlcustominput64.png b/examples/qmlcustominput/qmlcustominput64.png
new file mode 100644
index 00000000..707d5c4e
--- /dev/null
+++ b/examples/qmlcustominput/qmlcustominput64.png
Binary files differ
diff --git a/examples/qmlcustominput/qmlcustominput80.png b/examples/qmlcustominput/qmlcustominput80.png
new file mode 100644
index 00000000..6ad8096c
--- /dev/null
+++ b/examples/qmlcustominput/qmlcustominput80.png
Binary files differ
diff --git a/examples/qmlcustominput/qtquick2applicationviewer/qtquick2applicationviewer.cpp b/examples/qmlcustominput/qtquick2applicationviewer/qtquick2applicationviewer.cpp
new file mode 100644
index 00000000..10709d7a
--- /dev/null
+++ b/examples/qmlcustominput/qtquick2applicationviewer/qtquick2applicationviewer.cpp
@@ -0,0 +1,81 @@
+// checksum 0x4f6f version 0x90005
+/*
+ This file was generated by the Qt Quick 2 Application wizard of Qt Creator.
+ QtQuick2ApplicationViewer is a convenience class containing mobile device specific
+ code such as screen orientation handling. Also QML paths and debugging are
+ handled here.
+ It is recommended not to modify this file, since newer versions of Qt Creator
+ may offer an updated version of it.
+*/
+
+#include "qtquick2applicationviewer.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDir>
+#include <QtQml/QQmlEngine>
+
+class QtQuick2ApplicationViewerPrivate
+{
+ QString mainQmlFile;
+ friend class QtQuick2ApplicationViewer;
+ static QString adjustPath(const QString &path);
+};
+
+QString QtQuick2ApplicationViewerPrivate::adjustPath(const QString &path)
+{
+#if defined(Q_OS_MAC)
+ if (!QDir::isAbsolutePath(path))
+ return QString::fromLatin1("%1/../Resources/%2")
+ .arg(QCoreApplication::applicationDirPath(), path);
+#elif defined(Q_OS_BLACKBERRY)
+ if (!QDir::isAbsolutePath(path))
+ return QString::fromLatin1("app/native/%1").arg(path);
+#elif !defined(Q_OS_ANDROID)
+ QString pathInInstallDir =
+ QString::fromLatin1("%1/../%2").arg(QCoreApplication::applicationDirPath(), path);
+ if (QFileInfo(pathInInstallDir).exists())
+ return pathInInstallDir;
+ pathInInstallDir =
+ QString::fromLatin1("%1/%2").arg(QCoreApplication::applicationDirPath(), path);
+ if (QFileInfo(pathInInstallDir).exists())
+ return pathInInstallDir;
+#endif
+ return path;
+}
+
+QtQuick2ApplicationViewer::QtQuick2ApplicationViewer(QWindow *parent)
+ : QQuickView(parent)
+ , d(new QtQuick2ApplicationViewerPrivate())
+{
+ connect(engine(), SIGNAL(quit()), SLOT(close()));
+ setResizeMode(QQuickView::SizeRootObjectToView);
+}
+
+QtQuick2ApplicationViewer::~QtQuick2ApplicationViewer()
+{
+ delete d;
+}
+
+void QtQuick2ApplicationViewer::setMainQmlFile(const QString &file)
+{
+ d->mainQmlFile = QtQuick2ApplicationViewerPrivate::adjustPath(file);
+#ifdef Q_OS_ANDROID
+ setSource(QUrl(QLatin1String("assets:/")+d->mainQmlFile));
+#else
+ setSource(QUrl::fromLocalFile(d->mainQmlFile));
+#endif
+}
+
+void QtQuick2ApplicationViewer::addImportPath(const QString &path)
+{
+ engine()->addImportPath(QtQuick2ApplicationViewerPrivate::adjustPath(path));
+}
+
+void QtQuick2ApplicationViewer::showExpanded()
+{
+#if defined(Q_WS_SIMULATOR) || defined(Q_OS_QNX)
+ showFullScreen();
+#else
+ show();
+#endif
+}
diff --git a/examples/qmlcustominput/qtquick2applicationviewer/qtquick2applicationviewer.h b/examples/qmlcustominput/qtquick2applicationviewer/qtquick2applicationviewer.h
new file mode 100644
index 00000000..cf66f140
--- /dev/null
+++ b/examples/qmlcustominput/qtquick2applicationviewer/qtquick2applicationviewer.h
@@ -0,0 +1,33 @@
+// checksum 0xfde6 version 0x90005
+/*
+ This file was generated by the Qt Quick 2 Application wizard of Qt Creator.
+ QtQuick2ApplicationViewer is a convenience class containing mobile device specific
+ code such as screen orientation handling. Also QML paths and debugging are
+ handled here.
+ It is recommended not to modify this file, since newer versions of Qt Creator
+ may offer an updated version of it.
+*/
+
+#ifndef QTQUICK2APPLICATIONVIEWER_H
+#define QTQUICK2APPLICATIONVIEWER_H
+
+#include <QtQuick/QQuickView>
+
+class QtQuick2ApplicationViewer : public QQuickView
+{
+ Q_OBJECT
+
+public:
+ explicit QtQuick2ApplicationViewer(QWindow *parent = 0);
+ virtual ~QtQuick2ApplicationViewer();
+
+ void setMainQmlFile(const QString &file);
+ void addImportPath(const QString &path);
+
+ void showExpanded();
+
+private:
+ class QtQuick2ApplicationViewerPrivate *d;
+};
+
+#endif // QTQUICK2APPLICATIONVIEWER_H
diff --git a/examples/qmlcustominput/qtquick2applicationviewer/qtquick2applicationviewer.pri b/examples/qmlcustominput/qtquick2applicationviewer/qtquick2applicationviewer.pri
new file mode 100644
index 00000000..e5f7990f
--- /dev/null
+++ b/examples/qmlcustominput/qtquick2applicationviewer/qtquick2applicationviewer.pri
@@ -0,0 +1,180 @@
+# checksum 0x7b0d version 0x90005
+# This file was generated by the Qt Quick 2 Application wizard of Qt Creator.
+# The code below adds the QtQuick2ApplicationViewer to the project and handles
+# the activation of QML debugging.
+# It is recommended not to modify this file, since newer versions of Qt Creator
+# may offer an updated version of it.
+
+QT += qml quick
+
+SOURCES += $$PWD/qtquick2applicationviewer.cpp
+HEADERS += $$PWD/qtquick2applicationviewer.h
+INCLUDEPATH += $$PWD
+# This file was generated by an application wizard of Qt Creator.
+# The code below handles deployment to Android and Maemo, aswell as copying
+# of the application data to shadow build directories on desktop.
+# It is recommended not to modify this file, since newer versions of Qt Creator
+# may offer an updated version of it.
+
+defineTest(qtcAddDeployment) {
+for(deploymentfolder, DEPLOYMENTFOLDERS) {
+ item = item$${deploymentfolder}
+ greaterThan(QT_MAJOR_VERSION, 4) {
+ itemsources = $${item}.files
+ } else {
+ itemsources = $${item}.sources
+ }
+ $$itemsources = $$eval($${deploymentfolder}.source)
+ itempath = $${item}.path
+ $$itempath= $$eval($${deploymentfolder}.target)
+ export($$itemsources)
+ export($$itempath)
+ DEPLOYMENT += $$item
+}
+
+MAINPROFILEPWD = $$PWD
+
+android-no-sdk {
+ for(deploymentfolder, DEPLOYMENTFOLDERS) {
+ item = item$${deploymentfolder}
+ itemfiles = $${item}.files
+ $$itemfiles = $$eval($${deploymentfolder}.source)
+ itempath = $${item}.path
+ $$itempath = /data/user/qt/$$eval($${deploymentfolder}.target)
+ export($$itemfiles)
+ export($$itempath)
+ INSTALLS += $$item
+ }
+
+ target.path = /data/user/qt
+
+ export(target.path)
+ INSTALLS += target
+} else:android {
+ for(deploymentfolder, DEPLOYMENTFOLDERS) {
+ item = item$${deploymentfolder}
+ itemfiles = $${item}.files
+ $$itemfiles = $$eval($${deploymentfolder}.source)
+ itempath = $${item}.path
+ $$itempath = /assets/$$eval($${deploymentfolder}.target)
+ export($$itemfiles)
+ export($$itempath)
+ INSTALLS += $$item
+ }
+
+ x86 {
+ target.path = /libs/x86
+ } else: armeabi-v7a {
+ target.path = /libs/armeabi-v7a
+ } else {
+ target.path = /libs/armeabi
+ }
+
+ export(target.path)
+ INSTALLS += target
+} else:win32 {
+ copyCommand =
+ for(deploymentfolder, DEPLOYMENTFOLDERS) {
+ source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source)
+ source = $$replace(source, /, \\)
+ sourcePathSegments = $$split(source, \\)
+ target = $$OUT_PWD/$$eval($${deploymentfolder}.target)/$$last(sourcePathSegments)
+ target = $$replace(target, /, \\)
+ target ~= s,\\\\\\.?\\\\,\\,
+ !isEqual(source,$$target) {
+ !isEmpty(copyCommand):copyCommand += &&
+ isEqual(QMAKE_DIR_SEP, \\) {
+ copyCommand += $(COPY_DIR) \"$$source\" \"$$target\"
+ } else {
+ source = $$replace(source, \\\\, /)
+ target = $$OUT_PWD/$$eval($${deploymentfolder}.target)
+ target = $$replace(target, \\\\, /)
+ copyCommand += test -d \"$$target\" || mkdir -p \"$$target\" && cp -r \"$$source\" \"$$target\"
+ }
+ }
+ }
+ !isEmpty(copyCommand) {
+ copyCommand = @echo Copying application data... && $$copyCommand
+ copydeploymentfolders.commands = $$copyCommand
+ first.depends = $(first) copydeploymentfolders
+ export(first.depends)
+ export(copydeploymentfolders.commands)
+ QMAKE_EXTRA_TARGETS += first copydeploymentfolders
+ }
+} else:unix {
+ maemo5 {
+ desktopfile.files = $${TARGET}.desktop
+ desktopfile.path = /usr/share/applications/hildon
+ icon.files = $${TARGET}64.png
+ icon.path = /usr/share/icons/hicolor/64x64/apps
+ } else:!isEmpty(MEEGO_VERSION_MAJOR) {
+ desktopfile.files = $${TARGET}_harmattan.desktop
+ desktopfile.path = /usr/share/applications
+ icon.files = $${TARGET}80.png
+ icon.path = /usr/share/icons/hicolor/80x80/apps
+ } else { # Assumed to be a Desktop Unix
+ copyCommand =
+ for(deploymentfolder, DEPLOYMENTFOLDERS) {
+ source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source)
+ source = $$replace(source, \\\\, /)
+ macx {
+ target = $$OUT_PWD/$${TARGET}.app/Contents/Resources/$$eval($${deploymentfolder}.target)
+ } else {
+ target = $$OUT_PWD/$$eval($${deploymentfolder}.target)
+ }
+ target = $$replace(target, \\\\, /)
+ sourcePathSegments = $$split(source, /)
+ targetFullPath = $$target/$$last(sourcePathSegments)
+ targetFullPath ~= s,/\\.?/,/,
+ !isEqual(source,$$targetFullPath) {
+ !isEmpty(copyCommand):copyCommand += &&
+ copyCommand += $(MKDIR) \"$$target\"
+ copyCommand += && $(COPY_DIR) \"$$source\" \"$$target\"
+ }
+ }
+ !isEmpty(copyCommand) {
+ copyCommand = @echo Copying application data... && $$copyCommand
+ copydeploymentfolders.commands = $$copyCommand
+ first.depends = $(first) copydeploymentfolders
+ export(first.depends)
+ export(copydeploymentfolders.commands)
+ QMAKE_EXTRA_TARGETS += first copydeploymentfolders
+ }
+ }
+ !isEmpty(target.path) {
+ installPrefix = $${target.path}
+ } else {
+ installPrefix = /opt/$${TARGET}
+ }
+ for(deploymentfolder, DEPLOYMENTFOLDERS) {
+ item = item$${deploymentfolder}
+ itemfiles = $${item}.files
+ $$itemfiles = $$eval($${deploymentfolder}.source)
+ itempath = $${item}.path
+ $$itempath = $${installPrefix}/$$eval($${deploymentfolder}.target)
+ export($$itemfiles)
+ export($$itempath)
+ INSTALLS += $$item
+ }
+
+ !isEmpty(desktopfile.path) {
+ export(icon.files)
+ export(icon.path)
+ export(desktopfile.files)
+ export(desktopfile.path)
+ INSTALLS += icon desktopfile
+ }
+
+ isEmpty(target.path) {
+ target.path = $${installPrefix}/bin
+ export(target.path)
+ }
+ INSTALLS += target
+}
+
+export (ICON)
+export (INSTALLS)
+export (DEPLOYMENT)
+export (LIBS)
+export (QMAKE_EXTRA_TARGETS)
+}
diff --git a/examples/qmlscatter/doc/images/qmlscatter-example.png b/examples/qmlscatter/doc/images/qmlscatter-example.png
index 7ba226fe..ff9df1fc 100644
--- a/examples/qmlscatter/doc/images/qmlscatter-example.png
+++ b/examples/qmlscatter/doc/images/qmlscatter-example.png
Binary files differ
diff --git a/examples/qmlscatter/doc/images/qmlscatter-newproject.png b/examples/qmlscatter/doc/images/qmlscatter-newproject.png
index 32ce2e1c..7c81cae8 100644
--- a/examples/qmlscatter/doc/images/qmlscatter-newproject.png
+++ b/examples/qmlscatter/doc/images/qmlscatter-newproject.png
Binary files differ
diff --git a/examples/qmlscatter/doc/src/qmlscatter.qdoc b/examples/qmlscatter/doc/src/qmlscatter.qdoc
index 92e7ba35..b0f1fd1f 100644
--- a/examples/qmlscatter/doc/src/qmlscatter.qdoc
+++ b/examples/qmlscatter/doc/src/qmlscatter.qdoc
@@ -31,7 +31,9 @@
\section1 Creating the application
- The application main is created by creating a new Qt Quick 2 Application project in QtCreator:
+ The application main is created by creating a new Qt Quick Application project in QtCreator.
+ The dialog shown here is from QtCreator 3.0.0, and it may look a bit different in other
+ versions:
\image qmlscatter-newproject.png
@@ -89,33 +91,36 @@
\snippet ../examples/qmlscatter/qml/qmlscatter/main.qml 1
Then we'll add another \c Item inside it, and call it \c dataView. This will be the item to hold
- the \c Scatter3D graph. We'll anchor it to the parent bottom:
+ the Scatter3D graph. We'll anchor it to the parent bottom:
\snippet ../examples/qmlscatter/qml/qmlscatter/main.qml 9
- Next we're ready to add the \c Scatter3D graph itself. We'll add it inside the \c dataView and
+ Next we're ready to add the Scatter3D graph itself. We'll add it inside the \c dataView and
name it \c {scatterGraph}. Let's make it fill the \c {dataView}:
\snippet ../examples/qmlscatter/qml/qmlscatter/main.qml 2
- Now the graph is ready for use, but has no data. It also has the default proxy, axes, and visual
+ Now the graph is ready for use, but has no data. It also has the default axes and visual
properties.
Let's modify some visual properties first by adding the following inside \c {scatterGraph}:
\snippet ../examples/qmlscatter/qml/qmlscatter/main.qml 3
- We changed the font, theme, and shadow quality. We're happy with the other visual properties,
- so we won't change them.
+ We added a built-in Theme3D and changed the font in it. We also changed the shadow quality.
+ We're happy with the other visual properties, so we won't change them.
Then it's time to start feeding the graph some data.
\section1 Adding data to the graph
- Let's create a \c Data item inside the \c mainView and name it \c {graphData}:
+ Let's create a \c Data item inside the \c mainView and name it \c {seriesOneData}:
\snippet ../examples/qmlscatter/qml/qmlscatter/main.qml 4
+ We'll add two more of these: \c seriesTwoData and \c seriesThreeData to add to the three series
+ we're going to have. They are added similarly as \c {seriesOneData}.
+
This is the component that holds our data in \c {data.qml}. It has an \c Item as the main
component.
@@ -125,37 +130,39 @@
\snippet ../examples/qmlscatter/qml/qmlscatter/data.qml 0
\dots
- That itself doesn't do us much good, so we'll create a \c ScatterDataMapping and name it
- \c {scatterMapping}:
+ We'll add two more of these for the other two series, and name them \c dataModelTwo and
+ \c {dataModelThree}.
+
+ Then we need to expose the data models to be usable from \c {main.qml}. We do this by defining
+ them as aliases in the main data component:
\snippet ../examples/qmlscatter/qml/qmlscatter/data.qml 1
- In \c scatterMapping we need to define axis roles to match the roles in the \c ListElement
- items of the \c {dataModel}.
+ Now we can use the data from \c data.qml with \c scatterGraph in \c {main.qml}. First we'll add
+ a Scatter3DSeries and call it \c {scatterSeries}:
- We'll still need a data proxy, so we'll create a \c ItemModelScatterDataProxy and call it
- \c {modelProxy}:
+ \snippet ../examples/qmlscatter/qml/qmlscatter/main.qml 5
- \snippet ../examples/qmlscatter/qml/qmlscatter/data.qml 2
+ Then we'll set up selection label format for the series:
- We set \c scatterMapping as the active mapping and \c dataModel as the item model.
+ \snippet ../examples/qmlscatter/qml/qmlscatter/main.qml 10
- We still need to expose the proxy to be usable from \c {main.qml}. We do this by defining it as
- an alias in the main data component:
+ And finally the data for series one in a ItemModelScatterDataProxy. We set the data itself as
+ \c itemModel for the proxy:
- \snippet ../examples/qmlscatter/qml/qmlscatter/data.qml 3
+ \snippet ../examples/qmlscatter/qml/qmlscatter/main.qml 11
- Now we can use the data from \c data.qml with \c scatterGraph in \c {main.qml}. We'll just set
- \c proxy as the \c dataProxy for the graph:
+ We'll add the other two series in the same way, but modify some series-specific details a bit:
- \snippet ../examples/qmlscatter/qml/qmlscatter/main.qml 5
+ \snippet ../examples/qmlscatter/qml/qmlscatter/main.qml 12
+ \dots
- We'll set up selection label format and the axes in \c scatterGraph as well:
+ Then we'll modify the properties of the default axes in \c scatterGraph a bit:
\snippet ../examples/qmlscatter/qml/qmlscatter/main.qml 6
- After that we'll add a few buttons to the \c mainView to control the graph. We'll only show one
- as an example:
+ After that we'll just add a few buttons to the \c mainView to control the graph. We'll only
+ show one as an example:
\snippet ../examples/qmlscatter/qml/qmlscatter/main.qml 7
diff --git a/examples/qmlscatter/main.cpp b/examples/qmlscatter/main.cpp
index cc3fa4c3..159612e9 100644
--- a/examples/qmlscatter/main.cpp
+++ b/examples/qmlscatter/main.cpp
@@ -29,6 +29,17 @@ int main(int argc, char *argv[])
QGuiApplication app(argc, argv);
QtQuick2ApplicationViewer viewer;
+
+#if !defined(QT_OPENGL_ES_2)
+ // Enable antialiasing
+ QSurfaceFormat surfaceFormat;
+ surfaceFormat.setDepthBufferSize(24);
+ surfaceFormat.setSamples(8);
+ surfaceFormat.setRenderableType(QSurfaceFormat::OpenGL);
+ surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
+ viewer.setFormat(surfaceFormat);
+#endif
+
#ifdef Q_OS_ANDROID
viewer.addImportPath(QString::fromLatin1("assets:/qml"));
viewer.engine()->addPluginPath(QString::fromLatin1("%1/../%2").arg(QDir::homePath(),
diff --git a/examples/qmlscatter/qml/qmlscatter/data.qml b/examples/qmlscatter/qml/qmlscatter/data.qml
index 4ad9d7fc..bf4853df 100644
--- a/examples/qmlscatter/qml/qmlscatter/data.qml
+++ b/examples/qmlscatter/qml/qmlscatter/data.qml
@@ -20,27 +20,12 @@ import QtQuick 2.1
import QtDataVisualization 1.0
Item {
- //! [3]
- property alias proxy: modelProxy
- //! [3]
-
//! [1]
- ScatterDataMapping {
- id: scatterMapping
- xPosRole: "xPos"
- yPosRole: "yPos"
- zPosRole: "zPos"
- }
+ property alias model: dataModel
+ property alias modelTwo: dataModelTwo
+ property alias modelThree: dataModelThree
//! [1]
- //! [2]
- ItemModelScatterDataProxy {
- id: modelProxy
- activeMapping: scatterMapping
- itemModel: dataModel
- }
- //! [2]
-
//! [0]
ListModel {
id: dataModel
@@ -68,7 +53,10 @@ Item {
ListElement{ xPos: -7.9 ; yPos: 3.4 ; zPos: -2.78 }
ListElement{ xPos: -7.4 ; yPos: 3.12 ; zPos: -3.1 }
ListElement{ xPos: -7.54 ; yPos: 2.8 ; zPos: -3.68 }
+ }
+ ListModel {
+ id: dataModelTwo
ListElement{ xPos: 2.25 ; yPos: 1.36 ; zPos: -1.3 }
ListElement{ xPos: -2 ; yPos: -0.08 ; zPos: 1 }
ListElement{ xPos: 2.65 ; yPos: -1.2 ; zPos: 2.7 }
@@ -1069,20 +1057,23 @@ Item {
ListElement{ xPos: 0.85 ; yPos: -2.92 ; zPos: 3.4 }
ListElement{ xPos: -0.7 ; yPos: 2.52 ; zPos: 1 }
ListElement{ xPos: -3.4 ; yPos: 0.6 ; zPos: 0.9 }
+ }
+ ListModel {
+ id: dataModelThree
ListElement{ xPos: 8.0; yPos: -2.0; zPos: 4.0 }
ListElement{ xPos: 7.8; yPos: -2.2; zPos: 5.0 }
ListElement{ xPos: 7.6; yPos: -2.4; zPos: 4.5 }
- ListElement{ xPos: 7.4; yPos: -2.6; zPos: 3.8 }
+ ListElement{ xPos: 9.4; yPos: -2.6; zPos: 3.8 }
ListElement{ xPos: 7.2; yPos: -2.8; zPos: 4.8 }
- ListElement{ xPos: 7.0; yPos: -2.3; zPos: 4.1 }
+ ListElement{ xPos: 9.0; yPos: -2.3; zPos: 4.1 }
ListElement{ xPos: 6.9; yPos: -3.3; zPos: 4.9 }
ListElement{ xPos: 6.7; yPos: -3.5; zPos: 3.5 }
ListElement{ xPos: 6.5; yPos: -3.7; zPos: 3.3 }
ListElement{ xPos: 6.3; yPos: -3.4; zPos: 3.7 }
ListElement{ xPos: 7.9 ; yPos: -3.32 ; zPos: 2.48 }
ListElement{ xPos: 6.2 ; yPos: -4.04 ; zPos: 3.4 }
- ListElement{ xPos: 8.06 ; yPos: -4.6 ; zPos: 4.08 }
+ ListElement{ xPos: 9.06 ; yPos: -4.6 ; zPos: 4.08 }
ListElement{ xPos: 5.98 ; yPos: -2.26 ; zPos: 2.82 }
ListElement{ xPos: 5.46 ; yPos: -3.9 ; zPos: 3.2 }
ListElement{ xPos: 8.14 ; yPos: -3.34 ; zPos: 3.42 }
@@ -1093,13 +1084,13 @@ Item {
ListElement{ xPos: 8.64 ; yPos: -3.04 ; zPos: 2.62 }
ListElement{ xPos: 7.82 ; yPos: -3.68 ; zPos: 2.96 }
ListElement{ xPos: 7.1 ; yPos: -3.6 ; zPos: 4.22 }
- ListElement{ xPos: 7.6 ; yPos: -3.88 ; zPos: 3.9 }
- ListElement{ xPos: 7.46 ; yPos: -4.2 ; zPos: 3.32 }
+ ListElement{ xPos: 8.6 ; yPos: -3.88 ; zPos: 3.9 }
+ ListElement{ xPos: 8.46 ; yPos: -4.2 ; zPos: 3.32 }
ListElement{ xPos: 6.98 ; yPos: -3.94 ; zPos: 3.1 }
ListElement{ xPos: 7.36 ; yPos: -4.24 ; zPos: 1.72 }
- ListElement{ xPos: 8.42 ; yPos: -4.52 ; zPos: 2.62 }
+ ListElement{ xPos: 9.42 ; yPos: -4.52 ; zPos: 2.62 }
ListElement{ xPos: 6.04 ; yPos: -4.48 ; zPos: 2.74 }
- ListElement{ xPos: 8.7 ; yPos: -3.92 ; zPos: 3.82 }
+ ListElement{ xPos: 10.0 ; yPos: -3.92 ; zPos: 3.82 }
ListElement{ xPos: 6.76 ; yPos: -3.5 ; zPos: 2.92 }
ListElement{ xPos: 7 ; yPos: -4.42 ; zPos: 2.62 }
ListElement{ xPos: 5.32 ; yPos: -3.28 ; zPos: 3.34 }
diff --git a/examples/qmlscatter/qml/qmlscatter/main.qml b/examples/qmlscatter/qml/qmlscatter/main.qml
index 7fd4ec84..22eab76b 100644
--- a/examples/qmlscatter/qml/qmlscatter/main.qml
+++ b/examples/qmlscatter/qml/qmlscatter/main.qml
@@ -18,6 +18,7 @@
//! [0]
import QtQuick 2.1
+import QtQuick.Layouts 1.0
import QtDataVisualization 1.0
import "."
//! [0]
@@ -30,10 +31,18 @@ Item {
//! [4]
Data {
- id: graphData
+ id: seriesOneData
}
//! [4]
+ Data {
+ id: seriesTwoData
+ }
+
+ Data {
+ id: seriesThreeData
+ }
+
//! [8]
//! [9]
Item {
@@ -41,7 +50,7 @@ Item {
anchors.bottom: parent.bottom
//! [9]
width: parent.width
- height: parent.height - shadowToggle.height
+ height: parent.height - buttonLayout.height
//! [8]
//! [2]
@@ -51,16 +60,14 @@ Item {
height: dataView.height
//! [2]
//! [3]
- font.family: "Lucida Handwriting"
- font.pointSize: 40
- theme: AbstractGraph3D.ThemeIsabelle
+ theme: Theme3D {
+ type: Theme3D.ThemeIsabelle
+ font.family: "Lucida Handwriting"
+ font.pointSize: 40
+ }
shadowQuality: AbstractGraph3D.ShadowQualitySoftLow
//! [3]
- //! [5]
- dataProxy: graphData.proxy
- //! [5]
//! [6]
- itemLabelFormat: "X:@xLabel Y:@yLabel Z:@zLabel"
axisX.segmentCount: 3
axisX.subSegmentCount: 2
axisX.labelFormat: "%.2f"
@@ -71,91 +78,151 @@ Item {
axisY.subSegmentCount: 2
axisY.labelFormat: "%.2f"
//! [6]
+ //! [5]
+ Scatter3DSeries {
+ id: scatterSeries
+ //! [5]
+ //! [10]
+ itemLabelFormat: "Series 1: X:@xLabel Y:@yLabel Z:@zLabel"
+ //! [10]
+
+ //! [11]
+ ItemModelScatterDataProxy {
+ itemModel: seriesOneData.model
+ xPosRole: "xPos"
+ yPosRole: "yPos"
+ zPosRole: "zPos"
+ }
+ //! [11]
+ }
+
+ //! [12]
+ Scatter3DSeries {
+ id: scatterSeriesTwo
+ itemLabelFormat: "Series 2: X:@xLabel Y:@yLabel Z:@zLabel"
+ itemSize: 0.1
+ mesh: Abstract3DSeries.MeshCube
+ //! [12]
+
+ ItemModelScatterDataProxy {
+ itemModel: seriesTwoData.modelTwo
+ xPosRole: "xPos"
+ yPosRole: "yPos"
+ zPosRole: "zPos"
+ }
+ }
+ Scatter3DSeries {
+ id: scatterSeriesThree
+ itemLabelFormat: "Series 3: X:@xLabel Y:@yLabel Z:@zLabel"
+ itemSize: 0.2
+ mesh: Abstract3DSeries.MeshMinimal
+
+ ItemModelScatterDataProxy {
+ itemModel: seriesThreeData.modelThree
+ xPosRole: "xPos"
+ yPosRole: "yPos"
+ zPosRole: "zPos"
+ }
+ }
}
}
- //! [7]
- NewButton {
- id: shadowToggle
- width: parent.width / 6 // We're adding 6 buttons and want to divide them equally
- text: "Hide Shadows"
- onClicked: {
- if (scatterGraph.shadowQuality === AbstractGraph3D.ShadowQualityNone) {
- scatterGraph.shadowQuality = AbstractGraph3D.ShadowQualitySoftLow;
- text = "Hide Shadows";
- } else {
- scatterGraph.shadowQuality = AbstractGraph3D.ShadowQualityNone;
- text = "Show Shadows";
+ RowLayout {
+ id: buttonLayout
+ Layout.minimumHeight: cameraToggle.height
+ width: parent.width
+ anchors.left: parent.left
+ spacing: 0
+ //! [7]
+ NewButton {
+ id: shadowToggle
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ text: "Hide Shadows"
+ onClicked: {
+ if (scatterGraph.shadowQuality === AbstractGraph3D.ShadowQualityNone) {
+ scatterGraph.shadowQuality = AbstractGraph3D.ShadowQualitySoftLow;
+ text = "Hide Shadows";
+ } else {
+ scatterGraph.shadowQuality = AbstractGraph3D.ShadowQualityNone;
+ text = "Show Shadows";
+ }
}
}
- }
- //! [7]
-
- NewButton {
- id: smoothToggle
- width: parent.width / 6
- text: "Use Smooth Dots"
- anchors.left: shadowToggle.right
- onClicked: {
- if (scatterGraph.objectSmoothingEnabled === false) {
- text = "Use Flat Dots";
- scatterGraph.objectSmoothingEnabled = true;
- } else {
- text = "Use Smooth Dots"
- scatterGraph.objectSmoothingEnabled = false;
+ //! [7]
+
+ NewButton {
+ id: smoothToggle
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ text: "Use Smooth for Series One"
+ onClicked: {
+ if (scatterSeries.meshSmooth === false) {
+ text = "Use Flat for Series One";
+ scatterSeries.meshSmooth = true;
+ } else {
+ text = "Use Smooth for Series One"
+ scatterSeries.meshSmooth = false;
+ }
}
}
- }
- NewButton {
- id: cameraToggle
- width: parent.width / 6
- text: "Change Camera Placement"
- anchors.left: smoothToggle.right
- onClicked: {
- if (scatterGraph.scene.activeCamera.cameraPreset === AbstractGraph3D.CameraPresetFront) {
- scatterGraph.scene.activeCamera.cameraPreset = AbstractGraph3D.CameraPresetIsometricRightHigh;
- } else {
- scatterGraph.scene.activeCamera.cameraPreset = AbstractGraph3D.CameraPresetFront;
+ NewButton {
+ id: cameraToggle
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ text: "Change Camera Placement"
+ onClicked: {
+ if (scatterGraph.scene.activeCamera.cameraPreset === Camera3D.CameraPresetFront) {
+ scatterGraph.scene.activeCamera.cameraPreset =
+ Camera3D.CameraPresetIsometricRightHigh;
+ } else {
+ scatterGraph.scene.activeCamera.cameraPreset = Camera3D.CameraPresetFront;
+ }
}
}
- }
- NewButton {
- id: themeToggle
- width: parent.width / 6
- text: "Change Theme"
- anchors.left: cameraToggle.right
- onClicked: {
- if (scatterGraph.theme === AbstractGraph3D.ThemeArmyBlue) {
- scatterGraph.theme = AbstractGraph3D.ThemeIsabelle;
- } else {
- scatterGraph.theme = AbstractGraph3D.ThemeArmyBlue;
+ NewButton {
+ id: themeToggle
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ text: "Change Theme"
+ onClicked: {
+ if (scatterGraph.theme.type === Theme3D.ThemeArmyBlue) {
+ // Ownership of the theme is transferred and old theme is destroyed when setting
+ // a new one, so we need to create them dynamically
+ scatterGraph.theme = Qt.createQmlObject('import QtDataVisualization 1.0;
+ Theme3D {type: Theme3D.ThemeIsabelle; font.family: "Lucida Handwriting";
+ font.pointSize: 40}', parent);
+ } else {
+ scatterGraph.theme = Qt.createQmlObject('import QtDataVisualization 1.0;
+ Theme3D {type: Theme3D.ThemeArmyBlue}', parent);
+ }
}
}
- }
- NewButton {
- id: backgroundToggle
- width: parent.width / 6
- text: "Hide Background"
- anchors.left: themeToggle.right
- onClicked: {
- if (scatterGraph.backgroundVisible === true) {
- scatterGraph.backgroundVisible = false;
- text = "Show Background";
- } else {
- scatterGraph.backgroundVisible = true;
- text = "Hide Background";
+ NewButton {
+ id: backgroundToggle
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ text: "Hide Background"
+ onClicked: {
+ if (scatterGraph.theme.backgroundEnabled === true) {
+ scatterGraph.theme.backgroundEnabled = false;
+ text = "Show Background";
+ } else {
+ scatterGraph.theme.backgroundEnabled = true;
+ text = "Hide Background";
+ }
}
}
- }
- NewButton {
- id: exitButton
- width: parent.width / 6
- text: "Quit"
- anchors.left: backgroundToggle.right
- onClicked: Qt.quit(0);
+ NewButton {
+ id: exitButton
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ text: "Quit"
+ onClicked: Qt.quit(0);
+ }
}
}
diff --git a/examples/qmlscatter/qml/qmlscatter/newbutton.qml b/examples/qmlscatter/qml/qmlscatter/newbutton.qml
index 895db183..e44c9d1a 100644
--- a/examples/qmlscatter/qml/qmlscatter/newbutton.qml
+++ b/examples/qmlscatter/qml/qmlscatter/newbutton.qml
@@ -18,6 +18,7 @@
import QtQuick 2.1
import QtQuick.Controls 1.0
+import QtQuick.Controls.Styles 1.0
Item {
id: newbutton
@@ -26,17 +27,25 @@ Item {
signal clicked
- height: 80
+ implicitWidth: buttonText.implicitWidth + 5
+ implicitHeight: buttonText.implicitHeight + 10
Button {
+ id: buttonText
width: parent.width
height: parent.height
- Text {
- id: buttonText
- wrapMode: Text.WordWrap
- verticalAlignment: Text.AlignVCenter
- horizontalAlignment: Text.AlignHCenter
- anchors.fill: parent
+
+ style: ButtonStyle {
+ label: Component {
+ Text {
+ text: buttonText.text
+ clip: true
+ wrapMode: Text.WordWrap
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ anchors.fill: parent
+ }
+ }
}
onClicked: newbutton.clicked()
}
diff --git a/examples/qmlscatter/qtquick2applicationviewer/qtquick2applicationviewer.pri b/examples/qmlscatter/qtquick2applicationviewer/qtquick2applicationviewer.pri
index a071e63d..e5f7990f 100644
--- a/examples/qmlscatter/qtquick2applicationviewer/qtquick2applicationviewer.pri
+++ b/examples/qmlscatter/qtquick2applicationviewer/qtquick2applicationviewer.pri
@@ -61,6 +61,16 @@ android-no-sdk {
export($$itempath)
INSTALLS += $$item
}
+
+ x86 {
+ target.path = /libs/x86
+ } else: armeabi-v7a {
+ target.path = /libs/armeabi-v7a
+ } else {
+ target.path = /libs/armeabi
+ }
+
+ export(target.path)
INSTALLS += target
} else:win32 {
copyCommand =
diff --git a/examples/qmlsurface/doc/images/qmlsurface-example.png b/examples/qmlsurface/doc/images/qmlsurface-example.png
index 85350b5a..57b2633b 100644
--- a/examples/qmlsurface/doc/images/qmlsurface-example.png
+++ b/examples/qmlsurface/doc/images/qmlsurface-example.png
Binary files differ
diff --git a/examples/qmlsurface/doc/src/qmlsurface.qdoc b/examples/qmlsurface/doc/src/qmlsurface.qdoc
index 12e326c8..ffbdf305 100644
--- a/examples/qmlsurface/doc/src/qmlsurface.qdoc
+++ b/examples/qmlsurface/doc/src/qmlsurface.qdoc
@@ -35,54 +35,74 @@
This example shows two methods to set data to surface graph, using the HeightMapSurfaceDataProxy
and ItemModelSurfaceDataProxy. First we go through setting the data using the height map specific
- data proxy. It is done with the code snippet below. The \c heightMapFile property specifies the image
- file containing the height data. The value properties defines the minimum and maximum values for
- surface area width and depth. This example shows the terrain around Tycho crater at imaginary
- position from 67 to 97 and from 30 to 60. Note that on the graph the scale on the Y dimension
- exaggerates the height.
+ data proxy. It is done with the code snippet below. The proxy itself is contained in a
+ Surface3DSeries. Inside the HeightMapSurfaceDataProxy the \c heightMapFile specifies the
+ image file containing the height data. The value properties in the proxy define the minimum
+ and maximum values for surface area width and depth. This example shows the terrain around Tycho
+ crater at imaginary position from 67 to 97 and from 30 to 60. Note that on the graph the scale
+ on the Y dimension exaggerates the height.
- \snippet ../examples/qmlsurface/qml/qmlsurface/data.qml 0
+ \snippet ../examples/qmlsurface/qml/qmlsurface/main.qml 4
- The other method to set surface data used in this example is with model mapping. We do that by first
- defining a ListModel containing the data for the surface:
+ The other method to set surface data used in this example is with model mapping. We do that by
+ first defining a \c ListModel containing the data for the surface:
- \snippet ../examples/qmlsurface/qml/qmlsurface/data.qml 1
+ \snippet ../examples/qmlsurface/qml/qmlsurface/data.qml 0
\dots 4
- Then we set up a SurfaceDataMapping which maps the roles for columns, rows and values. In this
- example the row holds values for longitude, column for latitude and the value is for height.
+ Then we set up a Surface3DSeries with a ItemModelSurfaceDataProxy:
- \snippet ../examples/qmlsurface/qml/qmlsurface/data.qml 2
+ \snippet ../examples/qmlsurface/qml/qmlsurface/main.qml 5
+ \dots
- The ItemModelSurfaceDataProxy is created to tie the model and the mapping together.
+ We add the actual data to the \c itemModel of the ItemModelSurfaceDataProxy. We also define the
+ roles for columns, rows and values. In this example the row holds values for longitude, column
+ for latitude and the value is for height.
- \snippet ../examples/qmlsurface/qml/qmlsurface/data.qml 3
+ \dots 0
+ \snippet ../examples/qmlsurface/qml/qmlsurface/main.qml 6
\section1 Showing data
In the \c main.qml, we set up the Surface3D element to show the data and various UI elements
- to illustrate few interesting features. First is the surface gradient, which can be defined
- as seen in this code snippet. With the \c ColorGradient we set example colors from position 0.0 to
- 1.0. This element is set for \c gradient property in Surface3D.
+ to illustrate few interesting features.
+
+ First is the gradient to be used for the surface, which can be defined as seen in the following
+ snippet. With the ColorGradient we set example colors from position 0.0 to 1.0.
\snippet ../examples/qmlsurface/qml/qmlsurface/main.qml 0
- Other interesting features can be controlled with buttons. The first button is to toggle on and off
- the surface grid, for which use the following code.
+ This element is set into the \c baseGradients property in the \c theme used in Surface3D:
+
+ \snippet ../examples/qmlsurface/qml/qmlsurface/main.qml 7
+
+ Other interesting features can be controlled with buttons.
+
+ The first button is to toggle on and off the surface grid, for which we use the following code:
\snippet ../examples/qmlsurface/qml/qmlsurface/main.qml 1
- Second button is for surface smooth status, which is controlled with this code.
+ Second button is for surface shading mode, which is controlled with this code:
\snippet ../examples/qmlsurface/qml/qmlsurface/main.qml 2
- Third and fourth buttons are for controlling background features. The last button is for switching
- between HeightMapSurfaceDataProxy and ItemModelSurfaceDataProxy, for which we use the following
- code. We also set the maximum value to 500 in model proxy to make the surface flatter and
- 250 on height map proxy to show exaggerated height. At the same time the color position
- on the gradient is modified.
+ Third button is for series visibility, which is controlled with this code:
+
+ \snippet ../examples/qmlsurface/qml/qmlsurface/main.qml 8
+
+ Notice that the \c drawMode and \c flatShadingEnable properties are set for both series.
+
+ Fourth and fifth buttons are for controlling background features.
+
+ The last button is for switching between the two series, one of which uses
+ HeightMapSurfaceDataProxy and the other one ItemModelSurfaceDataProxy. For this we use the
+ following code:
\snippet ../examples/qmlsurface/qml/qmlsurface/main.qml 3
+ We also set the maximum value to 500 in model proxy to make the surface flatter and
+ 250 on height map proxy to show exaggerated height. At the same time the middle color position
+ on the gradient is modified to match the value range change.
+
\section1 Example contents
*/
diff --git a/examples/qmlsurface/main.cpp b/examples/qmlsurface/main.cpp
index ac9dda35..21c987b3 100644
--- a/examples/qmlsurface/main.cpp
+++ b/examples/qmlsurface/main.cpp
@@ -30,6 +30,16 @@ int main(int argc, char *argv[])
QtQuick2ApplicationViewer viewer;
+#if !defined(QT_OPENGL_ES_2)
+ // Enable antialiasing
+ QSurfaceFormat surfaceFormat;
+ surfaceFormat.setDepthBufferSize(24);
+ surfaceFormat.setSamples(8);
+ surfaceFormat.setRenderableType(QSurfaceFormat::OpenGL);
+ surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
+ viewer.setFormat(surfaceFormat);
+#endif
+
#ifdef Q_OS_ANDROID
viewer.addImportPath(QString::fromLatin1("assets:/qml"));
viewer.engine()->addPluginPath(QString::fromLatin1("%1/../%2").arg(QDir::homePath(),
diff --git a/examples/qmlsurface/qml/qmlsurface/data.qml b/examples/qmlsurface/qml/qmlsurface/data.qml
index e5678669..8637c29c 100644
--- a/examples/qmlsurface/qml/qmlsurface/data.qml
+++ b/examples/qmlsurface/qml/qmlsurface/data.qml
@@ -20,47 +20,15 @@ import QtQuick 2.1
import QtDataVisualization 1.0
Item {
- property alias mapping: surfaceMapping
property alias model: dataModel
- property alias proxy: modelProxy
- property alias heightProxy: heightMapProxy
//! [0]
- HeightMapSurfaceDataProxy {
- id: heightMapProxy
- heightMapFile: ":/heightmaps/image"
- // We don't want the default data values set by heightmap proxy.
- minZValue: 30
- maxZValue: 60
- minXValue: 67
- maxXValue: 97
- }
- //! [0]
-
- //! [2]
- SurfaceDataMapping {
- id: surfaceMapping
- rowRole: "longitude"
- columnRole: "latitude"
- valueRole: "height"
- }
- //! [2]
-
- //! [3]
- ItemModelSurfaceDataProxy {
- id: modelProxy
- activeMapping: surfaceMapping
- itemModel: dataModel
- }
- //! [3]
-
- //! [1]
ListModel {
id: dataModel
ListElement{ longitude: "0"; latitude: "0"; height: "124"; }
ListElement{ longitude: "0"; latitude: "1"; height: "125"; }
ListElement{ longitude: "0"; latitude: "2"; height: "124"; }
- //! [1]
+ //! [0]
ListElement{ longitude: "0"; latitude: "3"; height: "118"; }
ListElement{ longitude: "0"; latitude: "4"; height: "112"; }
ListElement{ longitude: "0"; latitude: "5"; height: "111"; }
diff --git a/examples/qmlsurface/qml/qmlsurface/main.qml b/examples/qmlsurface/qml/qmlsurface/main.qml
index 6d6b2821..07a07891 100644
--- a/examples/qmlsurface/qml/qmlsurface/main.qml
+++ b/examples/qmlsurface/qml/qmlsurface/main.qml
@@ -17,6 +17,7 @@
****************************************************************************/
import QtQuick 2.1
+import QtQuick.Layouts 1.0
import QtDataVisualization 1.0
import "."
@@ -26,13 +27,16 @@ Item {
height: 720
visible: true
+ property int buttonMaximumWidth: surfaceGridToggle.width
+ property int buttonMinimumHeight: seriesToggle.height
+
Data {
id: surfaceData
}
Item {
id: surfaceView
- width: mainview.width - surfaceGridToggle.width
+ width: mainview.width - buttonLayout.width
height: mainview.height
anchors.right: mainview.right;
@@ -40,7 +44,7 @@ Item {
ColorGradient {
id: surfaceGradient
ColorGradientStop { position: 0.0; color: "darkslategray" }
- ColorGradientStop { id: middleGradient; position: 0.55; color: "peru" }
+ ColorGradientStop { id: middleGradient; position: 0.25; color: "peru" }
ColorGradientStop { position: 1.0; color: "red" }
}
//! [0]
@@ -49,17 +53,20 @@ Item {
id: surfaceplot
width: surfaceView.width
height: surfaceView.height
- theme: AbstractGraph3D.ThemeStoneMoss
+ //! [7]
+ theme: Theme3D {
+ type: Theme3D.ThemeStoneMoss
+ font.family: "STCaiyun"
+ font.pointSize: 35
+ colorStyle: Theme3D.ColorStyleRangeGradient
+ baseGradients: [surfaceGradient]
+ }
+ //! [7]
shadowQuality: AbstractGraph3D.ShadowQualityMedium
- selectionMode: AbstractGraph3D.SelectionModeSliceRow
- smoothSurfaceEnabled: true
- surfaceGridEnabled: false
- font.family: "STCaiyun"
- font.pointSize: 35
- scene.activeCamera.cameraPreset: AbstractGraph3D.CameraPresetIsometricLeft
- dataProxy: surfaceData.heightProxy
+ selectionMode: AbstractGraph3D.SelectionSlice | AbstractGraph3D.SelectionItemAndRow
+ scene.activeCamera.cameraPreset: Camera3D.CameraPresetIsometricLeft
axisY.min: 0.0
- axisY.max: 250.0
+ axisY.max: 500.0
axisX.segmentCount: 10
axisX.subSegmentCount: 2
axisX.labelFormat: "%i"
@@ -69,107 +76,173 @@ Item {
axisY.segmentCount: 5
axisY.subSegmentCount: 2
axisY.labelFormat: "%i"
- gradient: surfaceGradient
-
- // Since flat is not supported on all platforms, and changes back to smooth
- // asynchronously on those platforms, handle button text on changed
- // signal handler rather than when we set the value.
- onSmoothSurfaceEnabledChanged: {
- if (enabled === true) {
- smoothSurfaceToggle.text = "Show Flat"
- } else {
- smoothSurfaceToggle.text = "Show Smooth"
+
+ //! [5]
+ Surface3DSeries {
+ id: surfaceSeries
+ flatShadingEnabled: false
+ drawMode: Surface3DSeries.DrawSurface
+
+ ItemModelSurfaceDataProxy {
+ //! [5]
+ //! [6]
+ itemModel: surfaceData.model
+ rowRole: "longitude"
+ columnRole: "latitude"
+ valueRole: "height"
+ }
+ //! [6]
+
+ onFlatShadingSupportedChanged: {
+ flatShadingToggle.text = "Flat not supported"
}
}
}
}
- NewButton {
- id: surfaceGridToggle
+ // TODO: Kept outside until surface supports multiple added series (QTRD-2579)
+ //! [4]
+ Surface3DSeries {
+ id: heightSeries
+ flatShadingEnabled: false
+ drawMode: Surface3DSeries.DrawSurface
+
+ HeightMapSurfaceDataProxy {
+ heightMapFile: ":/heightmaps/image"
+ // We don't want the default data values set by heightmap proxy.
+ minZValue: 30
+ maxZValue: 60
+ minXValue: 67
+ maxXValue: 97
+ }
+ }
+ //! [4]
+ ColumnLayout {
+ id: buttonLayout
anchors.top: parent.top
anchors.left: parent.left
- width: 200
- text: "Show Surface Grid"
- //! [1]
- onClicked: {
- if (surfaceplot.surfaceGridEnabled === false) {
- surfaceplot.surfaceGridEnabled = true;
- text = "Hide Surface Grid"
- } else {
- surfaceplot.surfaceGridEnabled = false;
- text = "Show Surface Grid"
+ spacing: 0
+
+ NewButton {
+ id: surfaceGridToggle
+ Layout.maximumWidth: buttonMaximumWidth
+ Layout.fillWidth: true
+ Layout.minimumHeight: buttonMinimumHeight
+ text: "Show Surface Grid"
+ //! [1]
+ onClicked: {
+ if (surfaceSeries.drawMode & Surface3DSeries.DrawWireframe) {
+ surfaceSeries.drawMode &= ~Surface3DSeries.DrawWireframe;
+ heightSeries.drawMode &= ~Surface3DSeries.DrawWireframe;
+ text = "Show Surface Grid"
+ } else {
+ surfaceSeries.drawMode |= Surface3DSeries.DrawWireframe;
+ heightSeries.drawMode |= Surface3DSeries.DrawWireframe;
+ text = "Hide Surface Grid"
+ }
}
+ //! [1]
}
- //! [1]
- }
- NewButton {
- id: smoothSurfaceToggle
- anchors.top: surfaceGridToggle.bottom
- width: surfaceGridToggle.width
- text: "Show Flat"
- //! [2]
- onClicked: {
- if (surfaceplot.smoothSurfaceEnabled === true) {
- surfaceplot.smoothSurfaceEnabled = false;
- } else {
- surfaceplot.smoothSurfaceEnabled = true;
+ NewButton {
+ id: surfaceToggle
+ Layout.maximumWidth: buttonMaximumWidth
+ Layout.fillWidth: true
+ Layout.minimumHeight: buttonMinimumHeight
+ text: "Hide Surface"
+ //! [8]
+ onClicked: {
+ if (surfaceSeries.drawMode & Surface3DSeries.DrawSurface) {
+ surfaceSeries.drawMode &= ~Surface3DSeries.DrawSurface;
+ heightSeries.drawMode &= ~Surface3DSeries.DrawSurface;
+ text = "Show Surface"
+ } else {
+ surfaceSeries.drawMode |= Surface3DSeries.DrawSurface;
+ heightSeries.drawMode |= Surface3DSeries.DrawSurface;
+ text = "Hide Surface"
+ }
}
+ //! [8]
}
- //! [2]
- }
- NewButton {
- id: backgroundToggle
- anchors.top: smoothSurfaceToggle.bottom
- width: smoothSurfaceToggle.width
- text: "Hide Background"
- onClicked: {
- if (surfaceplot.backgroundVisible === true) {
- surfaceplot.backgroundVisible = false;
- text = "Show Background"
- } else {
- surfaceplot.backgroundVisible = true;
- text = "Hide Background"
+ NewButton {
+ id: flatShadingToggle
+ Layout.maximumWidth: buttonMaximumWidth
+ Layout.fillWidth: true
+ Layout.minimumHeight: buttonMinimumHeight
+
+ text: "Show Flat"
+ enabled: surfaceSeries.flatShadingSupported
+ //! [2]
+ onClicked: {
+ if (surfaceSeries.flatShadingEnabled === true) {
+ surfaceSeries.flatShadingEnabled = false;
+ heightSeries.flatShadingEnabled = false;
+ text = "Show Flat"
+ } else {
+ surfaceSeries.flatShadingEnabled = true;
+ heightSeries.flatShadingEnabled = true;
+ text = "Show Smooth"
+ }
}
+ //! [2]
}
- }
- NewButton {
- id: gridToggle
- anchors.top: backgroundToggle.bottom
- width: backgroundToggle.width
- text: "Hide Grid"
- onClicked: {
- if (surfaceplot.gridVisible === true) {
- surfaceplot.gridVisible = false;
- text = "Show Grid"
- } else {
- surfaceplot.gridVisible = true;
- text = "Hide Grid"
+ NewButton {
+ id: backgroundToggle
+ Layout.maximumWidth: buttonMaximumWidth
+ Layout.fillWidth: true
+ Layout.minimumHeight: buttonMinimumHeight
+ text: "Hide Background"
+ onClicked: {
+ if (surfaceplot.theme.backgroundEnabled === true) {
+ surfaceplot.theme.backgroundEnabled = false;
+ text = "Show Background"
+ } else {
+ surfaceplot.theme.backgroundEnabled = true;
+ text = "Hide Background"
+ }
}
}
- }
- NewButton {
- id: proxyToggle
- anchors.top: gridToggle.bottom
- width: gridToggle.width
- text: "Switch to Item Model Proxy"
- //! [3]
- onClicked: {
- if (surfaceplot.dataProxy === surfaceData.heightProxy) {
- surfaceplot.axisY.max = 500.0
- surfaceplot.dataProxy = surfaceData.proxy
- middleGradient.position = 0.25
- text = "Switch to Height Map Proxy"
- } else {
- surfaceplot.axisY.max = 250.0
- surfaceplot.dataProxy = surfaceData.heightProxy
- middleGradient.position = 0.55
- text = "Switch to Item Model Proxy"
+ NewButton {
+ id: gridToggle
+ Layout.maximumWidth: buttonMaximumWidth
+ Layout.fillWidth: true
+ Layout.minimumHeight: buttonMinimumHeight
+ text: "Hide Grid"
+ onClicked: {
+ if (surfaceplot.theme.gridEnabled === true) {
+ surfaceplot.theme.gridEnabled = false;
+ text = "Show Grid"
+ } else {
+ surfaceplot.theme.gridEnabled = true;
+ text = "Hide Grid"
+ }
+ }
+ }
+
+ NewButton {
+ id: seriesToggle
+ Layout.maximumWidth: buttonMaximumWidth
+ Layout.fillWidth: true
+ Layout.minimumHeight: buttonMinimumHeight
+ text: "Switch to Height Map Series"
+ //! [3]
+ onClicked: {
+ if (surfaceplot.seriesList[0] === heightSeries) {
+ surfaceplot.axisY.max = 500.0
+ surfaceplot.seriesList = [surfaceSeries]
+ middleGradient.position = 0.25
+ text = "Switch to Height Map Series"
+ } else {
+ surfaceplot.axisY.max = 250.0
+ surfaceplot.seriesList = [heightSeries]
+ middleGradient.position = 0.50
+ text = "Switch to Item Model Series"
+ }
}
+ //! [3]
}
- //! [3]
}
}
diff --git a/examples/qmlsurface/qml/qmlsurface/newbutton.qml b/examples/qmlsurface/qml/qmlsurface/newbutton.qml
index 895db183..e44c9d1a 100644
--- a/examples/qmlsurface/qml/qmlsurface/newbutton.qml
+++ b/examples/qmlsurface/qml/qmlsurface/newbutton.qml
@@ -18,6 +18,7 @@
import QtQuick 2.1
import QtQuick.Controls 1.0
+import QtQuick.Controls.Styles 1.0
Item {
id: newbutton
@@ -26,17 +27,25 @@ Item {
signal clicked
- height: 80
+ implicitWidth: buttonText.implicitWidth + 5
+ implicitHeight: buttonText.implicitHeight + 10
Button {
+ id: buttonText
width: parent.width
height: parent.height
- Text {
- id: buttonText
- wrapMode: Text.WordWrap
- verticalAlignment: Text.AlignVCenter
- horizontalAlignment: Text.AlignHCenter
- anchors.fill: parent
+
+ style: ButtonStyle {
+ label: Component {
+ Text {
+ text: buttonText.text
+ clip: true
+ wrapMode: Text.WordWrap
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ anchors.fill: parent
+ }
+ }
}
onClicked: newbutton.clicked()
}
diff --git a/examples/qmlsurface/qtquick2applicationviewer/qtquick2applicationviewer.pri b/examples/qmlsurface/qtquick2applicationviewer/qtquick2applicationviewer.pri
index a071e63d..e5f7990f 100644
--- a/examples/qmlsurface/qtquick2applicationviewer/qtquick2applicationviewer.pri
+++ b/examples/qmlsurface/qtquick2applicationviewer/qtquick2applicationviewer.pri
@@ -61,6 +61,16 @@ android-no-sdk {
export($$itempath)
INSTALLS += $$item
}
+
+ x86 {
+ target.path = /libs/x86
+ } else: armeabi-v7a {
+ target.path = /libs/armeabi-v7a
+ } else {
+ target.path = /libs/armeabi
+ }
+
+ export(target.path)
INSTALLS += target
} else:win32 {
copyCommand =
diff --git a/examples/scatter/doc/src/scatter.qdoc b/examples/scatter/doc/src/scatter.qdoc
index 2016a052..173ea6e3 100644
--- a/examples/scatter/doc/src/scatter.qdoc
+++ b/examples/scatter/doc/src/scatter.qdoc
@@ -38,13 +38,13 @@
\section1 Creating the application
- First, in main.cpp, we create a QApplication, instantiate Q3DScatter and a window container
+ First, in main.cpp, we create a QApplication, instantiate Q3DScatter, and a window container
for it:
\snippet ../examples/scatter/main.cpp 0
The call to QWidget::createWindowContainer is required, as all data visualization types
- (Q3DBars, Q3DScatter, Q3DSurface) inherit QWindow. Any class inheriting QWindow cannot be used
+ (Q3DBars, Q3DScatter, and Q3DSurface) inherit QWindow. Any class inheriting QWindow cannot be used
as a widget any other way.
Then we'll create horizontal and vertical layouts. We'll add the graph and the vertical
@@ -56,7 +56,7 @@
\l {Using widgets to control the graph}
Next, let's create another class to handle the data addition and other interaction with the
- graph. Let's call it ScatterDataModifier (See \l {Setting up the graph} and
+ graph. Let's call it \c ScatterDataModifier (See \l {Setting up the graph} and
\l {Adding data to the graph} for details):
\snippet ../examples/scatter/main.cpp 2
@@ -67,7 +67,7 @@
\section1 Setting up the graph
- Let's set up some visual qualities for the graph in the constructor of the ScatterDataModifier
+ Let's set up some visual qualities for the graph in the constructor of the \c ScatterDataModifier
class we instantiated in the application main:
\snippet ../examples/scatter/scatterdatamodifier.cpp 0
@@ -79,8 +79,8 @@
\snippet ../examples/scatter/scatterdatamodifier.cpp 1
- And finally we create a QScatterDataProxy, set a label format for it and set it as the active
- proxy for the graph:
+ And finally we create a QScatterDataProxy and the associated QScatter3DSeries. We set custom label format
+ for the series and add it to the graph:
\snippet ../examples/scatter/scatterdatamodifier.cpp 2
@@ -88,21 +88,16 @@
\section1 Adding data to the graph
- In application main, we called \c {modifier->start()} after constructing all the necessary
- objects. This is how it looks like:
+ The last thing we do in the \c ScatterDataModifier constructor is to add data to the graph:
\snippet ../examples/scatter/scatterdatamodifier.cpp 3
- There is nothing in it except a call to another method. There is actually no need for a
- separate \c start() method, but we keep it here in case we want to add some more functionality
- in it that can be done only after all construction in application main is done.
-
The actual data addition is done in \c addData() method. First we configure the axes we created
in constructor:
\snippet ../examples/scatter/scatterdatamodifier.cpp 4
- This could have been done in the ScatterDataModifier's constructor, but we added it here
+ This could have been done in the constructor of \c {ScatterDataModifier}, but we added it here
to keep the constructor simpler and the axes configuration near the data.
Next we create a data array:
@@ -149,7 +144,7 @@
\li Dot style
\li Theme
\li Shadow quality
- \li Font
+ \li Label font
\endlist
\section1 Example contents
diff --git a/examples/scatter/main.cpp b/examples/scatter/main.cpp
index c652361b..af95dd05 100644
--- a/examples/scatter/main.cpp
+++ b/examples/scatter/main.cpp
@@ -73,10 +73,12 @@ int main(int argc, char **argv)
smoothCheckBox->setText(QStringLiteral("Smooth dots"));
smoothCheckBox->setChecked(true);
- QComboBox *barStyleList = new QComboBox(widget);
- barStyleList->addItem(QStringLiteral("Sphere"));
- barStyleList->addItem(QStringLiteral("Tetrahedron"));
- barStyleList->setCurrentIndex(0);
+ QComboBox *itemStyleList = new QComboBox(widget);
+ itemStyleList->addItem(QStringLiteral("Sphere"), int(QAbstract3DSeries::MeshSphere));
+ itemStyleList->addItem(QStringLiteral("Cube"), int(QAbstract3DSeries::MeshCube));
+ itemStyleList->addItem(QStringLiteral("Minimal"), int(QAbstract3DSeries::MeshMinimal));
+ itemStyleList->addItem(QStringLiteral("Point"), int(QAbstract3DSeries::MeshPoint));
+ itemStyleList->setCurrentIndex(0);
QPushButton *cameraButton = new QPushButton(widget);
cameraButton->setText(QStringLiteral("Change camera preset"));
@@ -110,7 +112,7 @@ int main(int argc, char **argv)
vLayout->addWidget(gridCheckBox);
vLayout->addWidget(smoothCheckBox, 0, Qt::AlignTop);
vLayout->addWidget(new QLabel(QStringLiteral("Change dot style")));
- vLayout->addWidget(barStyleList);
+ vLayout->addWidget(itemStyleList);
vLayout->addWidget(new QLabel(QStringLiteral("Change theme")));
vLayout->addWidget(themeList);
vLayout->addWidget(new QLabel(QStringLiteral("Adjust shadow quality")));
@@ -136,7 +138,11 @@ int main(int argc, char **argv)
QObject::connect(smoothCheckBox, &QCheckBox::stateChanged, modifier,
&ScatterDataModifier::setSmoothDots);
- QObject::connect(barStyleList, SIGNAL(currentIndexChanged(int)), modifier,
+ QObject::connect(modifier, &ScatterDataModifier::backgroundEnabledChanged,
+ backgroundCheckBox, &QCheckBox::setChecked);
+ QObject::connect(modifier, &ScatterDataModifier::gridEnabledChanged,
+ gridCheckBox, &QCheckBox::setChecked);
+ QObject::connect(itemStyleList, SIGNAL(currentIndexChanged(int)), modifier,
SLOT(changeStyle(int)));
QObject::connect(themeList, SIGNAL(currentIndexChanged(int)), modifier,
@@ -152,11 +158,13 @@ int main(int argc, char **argv)
QObject::connect(fontList, &QFontComboBox::currentFontChanged, modifier,
&ScatterDataModifier::changeFont);
+
+ QObject::connect(modifier, &ScatterDataModifier::fontChanged, fontList,
+ &QFontComboBox::setCurrentFont);
//! [6]
//! [3]
widget->show();
- modifier->start();
return app.exec();
//! [3]
}
diff --git a/examples/scatter/scatterdatamodifier.cpp b/examples/scatter/scatterdatamodifier.cpp
index ce5a1bd7..ade4eb59 100644
--- a/examples/scatter/scatterdatamodifier.cpp
+++ b/examples/scatter/scatterdatamodifier.cpp
@@ -21,7 +21,11 @@
#include <QtDataVisualization/q3dvalueaxis.h>
#include <QtDataVisualization/q3dscene.h>
#include <QtDataVisualization/q3dcamera.h>
+#include <QtDataVisualization/qscatter3dseries.h>
+#include <QtDataVisualization/q3dtheme.h>
#include <qmath.h>
+#include <QComboBox>
+
using namespace QtDataVisualization;
//#define RANDOM_SCATTER // Uncomment this to switch to random scatter
@@ -31,17 +35,16 @@ const int numberOfItems = 3600;
ScatterDataModifier::ScatterDataModifier(Q3DScatter *scatter)
: m_graph(scatter),
m_fontSize(40.0f),
- m_style(QDataVis::MeshStyleSpheres),
+ m_style(QAbstract3DSeries::MeshSphere),
m_smooth(true)
{
//! [0]
- QFont font = m_graph->font();
+ m_graph->setTheme(new Q3DTheme(Q3DTheme::ThemeEbony));
+ QFont font = m_graph->theme()->font();
font.setPointSize(m_fontSize);
- m_graph->setFont(font);
- m_graph->setObjectType(QDataVis::MeshStyleSpheres, true);
- m_graph->setTheme(QDataVis::ThemeEbony);
+ m_graph->theme()->setFont(font);
m_graph->setShadowQuality(QDataVis::ShadowQualitySoftLow);
- m_graph->scene()->activeCamera()->setCameraPreset(QDataVis::CameraPresetFront);
+ m_graph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetFront);
//! [0]
//! [1]
@@ -52,11 +55,14 @@ ScatterDataModifier::ScatterDataModifier(Q3DScatter *scatter)
//! [2]
QScatterDataProxy *proxy = new QScatterDataProxy;
- proxy->setItemLabelFormat("@xTitle: @xLabel @yTitle: @yLabel @zTitle: @zLabel");
- m_graph->setActiveDataProxy(proxy);
+ QScatter3DSeries *series = new QScatter3DSeries(proxy);
+ series->setItemLabelFormat("@xTitle: @xLabel @yTitle: @yLabel @zTitle: @zLabel");
+ m_graph->addSeries(series);
//! [2]
- changeLabelStyle();
+ //! [3]
+ addData();
+ //! [3]
}
ScatterDataModifier::~ScatterDataModifier()
@@ -64,23 +70,16 @@ ScatterDataModifier::~ScatterDataModifier()
delete m_graph;
}
-//! [3]
-void ScatterDataModifier::start()
-{
- addData();
-}
-//! [3]
-
void ScatterDataModifier::addData()
{
+ // Configure the axes according to the data
//! [4]
- // Add labels
m_graph->axisX()->setTitle("X");
m_graph->axisY()->setTitle("Y");
m_graph->axisZ()->setTitle("Z");
- m_graph->axisX()->setRange(-30.0, 30.0);
- m_graph->axisY()->setRange(-1.0, 1.0);
- m_graph->axisZ()->setRange(-30.0, 30.0);
+ m_graph->axisX()->setRange(-30.0f, 30.0f);
+ m_graph->axisY()->setRange(-1.0f, 1.0f);
+ m_graph->axisZ()->setRange(-30.0f, 30.0f);
//! [4]
//! [5]
@@ -99,7 +98,7 @@ void ScatterDataModifier::addData()
float limit = qSqrt(numberOfItems) / 2.0f;
for (float i = -limit; i < limit; i++) {
for (float j = -limit; j < limit; j++) {
- ptrToDataArray->setPosition(QVector3D(i, qCos(qDegreesToRadians((i * j) / 3.0)), j));
+ ptrToDataArray->setPosition(QVector3D(i, qCos(qDegreesToRadians((i * j) / 3.0f)), j));
ptrToDataArray++;
}
}
@@ -107,53 +106,56 @@ void ScatterDataModifier::addData()
#endif
//! [7]
- m_graph->activeDataProxy()->resetArray(dataArray);
+ m_graph->seriesList().at(0)->dataProxy()->resetArray(dataArray);
//! [7]
}
//! [8]
void ScatterDataModifier::changeStyle(int style)
{
- m_style = QDataVis::MeshStyle(style + 5); // skip unsupported mesh types
- m_graph->setObjectType(m_style, m_smooth);
+ QComboBox *comboBox = qobject_cast<QComboBox *>(sender());
+ if (comboBox) {
+ m_style = QAbstract3DSeries::Mesh(comboBox->itemData(style).toInt());
+ if (m_graph->seriesList().size())
+ m_graph->seriesList().at(0)->setMesh(m_style);
+ }
}
void ScatterDataModifier::setSmoothDots(int smooth)
{
m_smooth = bool(smooth);
- m_graph->setObjectType(m_style, m_smooth);
+ QScatter3DSeries *series = m_graph->seriesList().at(0);
+ series->setMeshSmooth(m_smooth);
}
void ScatterDataModifier::changeTheme(int theme)
{
- m_graph->setTheme((QDataVis::Theme)theme);
+ m_graph->setTheme(new Q3DTheme(Q3DTheme::Theme(theme)));
+ emit backgroundEnabledChanged(m_graph->theme()->isBackgroundEnabled());
+ emit gridEnabledChanged(m_graph->theme()->isGridEnabled());
+ emit fontChanged(m_graph->theme()->font());
}
void ScatterDataModifier::changePresetCamera()
{
- static int preset = QDataVis::CameraPresetFrontLow;
+ static int preset = Q3DCamera::CameraPresetFrontLow;
- m_graph->scene()->activeCamera()->setCameraPreset((QDataVis::CameraPreset)preset);
+ m_graph->scene()->activeCamera()->setCameraPreset((Q3DCamera::CameraPreset)preset);
- if (++preset > QDataVis::CameraPresetDirectlyBelow)
- preset = QDataVis::CameraPresetFrontLow;
+ if (++preset > Q3DCamera::CameraPresetDirectlyBelow)
+ preset = Q3DCamera::CameraPresetFrontLow;
}
void ScatterDataModifier::changeLabelStyle()
{
- static int style = QDataVis::LabelStyleFromTheme;
-
- m_graph->setLabelStyle((QDataVis::LabelStyle)style);
-
- if (++style > QDataVis::LabelStyleTransparent)
- style = QDataVis::LabelStyleOpaque;
+ m_graph->theme()->setLabelBackgroundEnabled(!m_graph->theme()->isLabelBackgroundEnabled());
}
void ScatterDataModifier::changeFont(const QFont &font)
{
QFont newFont = font;
newFont.setPointSizeF(m_fontSize);
- m_graph->setFont(newFont);
+ m_graph->theme()->setFont(newFont);
}
void ScatterDataModifier::shadowQualityUpdatedByVisual(QDataVis::ShadowQuality sq)
@@ -170,12 +172,12 @@ void ScatterDataModifier::changeShadowQuality(int quality)
void ScatterDataModifier::setBackgroundEnabled(int enabled)
{
- m_graph->setBackgroundVisible((bool)enabled);
+ m_graph->theme()->setBackgroundEnabled((bool)enabled);
}
void ScatterDataModifier::setGridEnabled(int enabled)
{
- m_graph->setGridVisible((bool)enabled);
+ m_graph->theme()->setGridEnabled((bool)enabled);
}
//! [8]
diff --git a/examples/scatter/scatterdatamodifier.h b/examples/scatter/scatterdatamodifier.h
index 5cc9348b..78dd45e3 100644
--- a/examples/scatter/scatterdatamodifier.h
+++ b/examples/scatter/scatterdatamodifier.h
@@ -20,6 +20,7 @@
#define SCATTERDATAMODIFIER_H
#include <QtDataVisualization/q3dscatter.h>
+#include <QtDataVisualization/qabstract3dseries.h>
#include <QtGui/QFont>
using namespace QtDataVisualization;
@@ -49,13 +50,16 @@ public slots:
void shadowQualityUpdatedByVisual(QDataVis::ShadowQuality shadowQuality);
signals:
+ void backgroundEnabledChanged(bool enabled);
+ void gridEnabledChanged(bool enabled);
void shadowQualityChanged(int quality);
+ void fontChanged(QFont font);
private:
QVector3D randVector();
Q3DScatter *m_graph;
int m_fontSize;
- QDataVis::MeshStyle m_style;
+ QAbstract3DSeries::Mesh m_style;
bool m_smooth;
};
diff --git a/examples/surface/doc/src/surface.qdoc b/examples/surface/doc/src/surface.qdoc
index e669948c..6f49a3dc 100644
--- a/examples/surface/doc/src/surface.qdoc
+++ b/examples/surface/doc/src/surface.qdoc
@@ -30,8 +30,8 @@
\li How to set up a basic QSurfaceDataProxy and set data for it.
\li How to use QHeightMapSurfaceDataProxy for showing 3D height maps.
\li Three different selection modes for studying the graph.
- \li Axis range usage for selecting slices from the graph.
- \li Theme usage on the surface graph.
+ \li Axis range usage for displaying selected portions of the graph.
+ \li Changing theme.
\li How to set a custom surface gradient.
\endlist
@@ -41,13 +41,13 @@
\section1 Creating the application
- First, in \c main.cpp, we create a QApplication, instantiate Q3DSurface and a window container
+ First, in \c main.cpp, we create a QApplication, instantiate Q3DSurface, and a window container
for it:
\snippet ../examples/surface/main.cpp 0
The call to QWidget::createWindowContainer is required, as all data visualization types
- (Q3DBars, Q3DScatter, Q3DSurface) inherit QWindow. Any class inheriting QWindow cannot be used
+ (Q3DBars, Q3DScatter, and Q3DSurface) inherit QWindow. Any class inheriting QWindow cannot be used
as a widget any other way.
Then we'll create horizontal and vertical layouts. We'll add the graph with the container and
@@ -62,39 +62,41 @@
\section1 Setting up proxies and data
- First we instantiate a new QSurfaceDataProxy:
+ First we instantiate a new QSurfaceDataProxy and attach it to a new QSurface3DSeries:
\snippet ../examples/surface/surfacegraph.cpp 0
- Then we fill it with a simple square root and sin wave data. This is done by
- creating a new QSurfaceDataArray instance and adding QSurfaceDataRow elements.
- The created QSurfaceDataArray is set to be a the data array for the QSurfaceDataProxy.
+ Then we fill the proxy with a simple square root and sin wave data. This is done by
+ creating a new \c QSurfaceDataArray instance and adding \c QSurfaceDataRow elements to it.
+ The created \c QSurfaceDataArray is set to be a the data array for the QSurfaceDataProxy.
\snippet ../examples/surface/surfacegraph.cpp 1
The height map is created by instantiating a QHeightMapSurfaceDataProxy with
- a QImage containing the height data. The method setValueRanges is used to define
- the value range of the map. In our example the map is from imaginary position of
+ a QImage containing the height data. The method QHeightMapSurfaceDataProxy::setValueRanges() is
+ used to define the value range of the map. In our example the map is from imaginary position of
34.0\unicode 0x00B0 N - 40.0\unicode 0x00B0 N and 18.0\unicode 0x00B0 E - 24.0\unicode 0x00B0 E.
These values are used to show and position the map to the axis.
\snippet ../examples/surface/surfacegraph.cpp 2
For demonstrating different proxies this example has two radio buttons which
- the user can use to switch between active proxies. When the user selects the
- Sqrt&Sin radio button the selected proxy is activated with the following
+ the user can use to switch between the series. When the user selects the
+ \c {Sqrt & Sin} radio button, the selected series is activated with the following
code. First we set the decorative issues like enable the grid for the surface and
- select the flat surface mode. Next lines define the axis label format and value
- ranges. Since the algorithm studies the value variation between -8.0 and 8.0 we
- set these values for X and Z coordinates. The value itself varies between 0.0 and
- 2.0. The method setActiveDataProxy sets the basic data proxy to be active.
+ select the flat shading mode. Next lines define the axis label format and value
+ ranges. The Y-value value of the function we use to generate the points varies between
+ 0.0 and 2.0, but no individual point actually hits exactly those, so we set the Y-axis range
+ explicitly. The other axes we are happy to leave to automatically adjust their range to the
+ data, which is the default behavior. Finally we make sure the correct series is added to the
+ graph. We need to first remove the other series, since surface graphs only support a single
+ series at a time:
\snippet ../examples/surface/surfacegraph.cpp 3
- When the Height Map radio button is activated, the following code sets the proxy on.
- First the surface grid is turned off and the smooth mode is activated. The axis label
- format is set to show N and E letters and ranges are set to the imaginary coordinates.
- Finally the height map proxy is set to be active.
+ When the \c{Height Map} radio button is activated, the following code sets the correct series active.
+ The axis label format is set to show N and E letters and ranges are set to the imaginary coordinates.
+ Auto adjusting Y-axis range is fine for our height map surface, so we ensure it is set.
\snippet ../examples/surface/surfacegraph.cpp 4
@@ -110,14 +112,18 @@
The example has four slider controls for adjusting the min and max values for X and Z
axis. When selecting the proxy these sliders are adjusted so that one step on the slider
- moves the range by one segment step. Finally the ranges are set for the graph like this:
+ moves the range by one segment step:
+
+ \snippet ../examples/surface/surfacegraph.cpp 8
+
+ The ranges are set for the axes like this:
\snippet ../examples/surface/surfacegraph.cpp 5
\section1 Themes
- Q3Dsurface supports all the themes QtDatavisualization has. The example has a pull
- down menu for selecting the theme. The following code snippet is connected to the
+ Q3DSurface supports all the themes Qt Data Visualization has. The example has a pull
+ down menu for selecting the theme. The following method is connected to the
menu to activate the selected theme.
\snippet ../examples/surface/surfacegraph.cpp 6
@@ -125,8 +131,9 @@
\section1 Custom surface gradients
The example demonstrates the custom surface gradients with two push buttons. The gradient
- can be defined with QLinearGradient where the desired colors are set to positions. Following
- snippet shows how to create an example gradient and set it to the graph.
+ can be defined with QLinearGradient where the desired colors are set to positions. The following
+ code shows how to create an example gradient and set it to the series. Note that you also need
+ to change the color style to Q3DTheme::ColorStyleRangeGradient to actually use the gradient.
\snippet ../examples/surface/surfacegraph.cpp 7
*/
diff --git a/examples/surface/main.cpp b/examples/surface/main.cpp
index e448af94..313ddf6d 100644
--- a/examples/surface/main.cpp
+++ b/examples/surface/main.cpp
@@ -58,7 +58,7 @@ int main(int argc, char **argv)
QGroupBox *modelGroupBox = new QGroupBox(QStringLiteral("Model"));
QRadioButton *sqrtSinModelRB = new QRadioButton(widget);
- sqrtSinModelRB->setText(QStringLiteral("Sqrt&Sin"));
+ sqrtSinModelRB->setText(QStringLiteral("Sqrt && Sin"));
sqrtSinModelRB->setChecked(false);
QRadioButton *heightMapModelRB = new QRadioButton(widget);
diff --git a/examples/surface/surfacegraph.cpp b/examples/surface/surfacegraph.cpp
index bb07cb96..24ab3715 100644
--- a/examples/surface/surfacegraph.cpp
+++ b/examples/surface/surfacegraph.cpp
@@ -19,6 +19,7 @@
#include "surfacegraph.h"
#include <QtDataVisualization/Q3DValueAxis>
+#include <QtDataVisualization/Q3DTheme>
#include <QtGui/QImage>
#include <QtCore/qmath.h>
@@ -37,17 +38,18 @@ SurfaceGraph::SurfaceGraph(Q3DSurface *surface)
m_graph->setAxisX(new Q3DValueAxis);
m_graph->setAxisY(new Q3DValueAxis);
m_graph->setAxisZ(new Q3DValueAxis);
- m_graph->setLabelStyle(QDataVis::LabelStyleFromTheme);
//! [0]
- sqrtSinProxy = new QSurfaceDataProxy();
+ m_sqrtSinProxy = new QSurfaceDataProxy();
+ m_sqrtSinSeries = new QSurface3DSeries(m_sqrtSinProxy);
//! [0]
fillSqrtSinProxy();
//! [2]
QImage heightMapImage(":/maps/mountain");
m_heightMapProxy = new QHeightMapSurfaceDataProxy(heightMapImage);
- m_heightMapProxy->setValueRanges(34.0, 40.0, 18.0, 24.0);
+ m_heightMapSeries = new QSurface3DSeries(m_heightMapProxy);
+ m_heightMapProxy->setValueRanges(34.0f, 40.0f, 18.0f, 24.0f);
//! [2]
m_heightMapWidth = heightMapImage.width();
m_heightMapHeight = heightMapImage.height();
@@ -68,146 +70,156 @@ void SurfaceGraph::fillSqrtSinProxy()
dataArray->reserve(sampleCountZ);
for (int i = 0 ; i < sampleCountZ ; i++) {
QSurfaceDataRow *newRow = new QSurfaceDataRow(sampleCountX);
- float z = i * stepZ + sampleMin;
+ // Keep values within range bounds, since just adding step can cause minor drift due
+ // to the rounding errors.
+ float z = qMin(sampleMax, (i * stepZ + sampleMin));
int index = 0;
for (int j = 0; j < sampleCountX; j++) {
- float x = j * stepX + sampleMin;
- float R = qSqrt(z * z + x * x) + 0.01;
- float y = (qSin(R) / R + 0.24) * 1.61;
+ float x = qMin(sampleMax, (j * stepX + sampleMin));
+ float R = qSqrt(z * z + x * x) + 0.01f;
+ float y = (qSin(R) / R + 0.24f) * 1.61f;
(*newRow)[index++].setPosition(QVector3D(x, y, z));
}
*dataArray << newRow;
}
- sqrtSinProxy->resetArray(dataArray);
+ m_sqrtSinProxy->resetArray(dataArray);
}
//! [1]
-void SurfaceGraph::enableSqrtSinModel()
+void SurfaceGraph::enableSqrtSinModel(bool enable)
{
- //! [3]
- m_graph->setSurfaceGridEnabled(true);
- m_graph->setSmoothSurfaceEnabled(false);
-
- m_graph->axisX()->setLabelFormat("%.2f");
- m_graph->axisZ()->setLabelFormat("%.2f");
- m_graph->axisX()->setRange(sampleMin, sampleMax);
- m_graph->axisY()->setRange(0.0, 2.0);
- m_graph->axisZ()->setRange(sampleMin, sampleMax);
-
- m_graph->setActiveDataProxy(sqrtSinProxy);
- //! [3]
-
- // Reset range sliders for Sqrt&Sin
- m_rangeMinX = sampleMin;
- m_rangeMinZ = sampleMin;
- m_stepX = (sampleMax - sampleMin) / qreal(sampleCountX - 1);
- m_stepZ = (sampleMax - sampleMin) / qreal(sampleCountZ - 1);
- m_axisMinSliderX->setMaximum(sampleCountX - 2);
- m_axisMinSliderX->setValue(0);
- m_axisMaxSliderX->setMaximum(sampleCountX - 1);
- m_axisMaxSliderX->setValue(sampleCountX - 1);
- m_axisMinSliderZ->setMaximum(sampleCountZ - 2);
- m_axisMinSliderZ->setValue(0);
- m_axisMaxSliderZ->setMaximum(sampleCountZ - 1);
- m_axisMaxSliderZ->setValue(sampleCountZ - 1);
+ if (enable) {
+ //! [3]
+ m_sqrtSinSeries->setDrawMode(QSurface3DSeries::DrawSurfaceAndWireframe);
+ m_sqrtSinSeries->setFlatShadingEnabled(true);
+
+ m_graph->axisX()->setLabelFormat("%.2f");
+ m_graph->axisZ()->setLabelFormat("%.2f");
+ m_graph->axisX()->setRange(sampleMin, sampleMax);
+ m_graph->axisY()->setRange(0.0f, 2.0f);
+ m_graph->axisZ()->setRange(sampleMin, sampleMax);
+
+ m_graph->removeSeries(m_heightMapSeries);
+ m_graph->addSeries(m_sqrtSinSeries);
+ //! [3]
+
+ //! [8]
+ // Reset range sliders for Sqrt&Sin
+ m_rangeMinX = sampleMin;
+ m_rangeMinZ = sampleMin;
+ m_stepX = (sampleMax - sampleMin) / float(sampleCountX - 1);
+ m_stepZ = (sampleMax - sampleMin) / float(sampleCountZ - 1);
+ m_axisMinSliderX->setMaximum(sampleCountX - 2);
+ m_axisMinSliderX->setValue(0);
+ m_axisMaxSliderX->setMaximum(sampleCountX - 1);
+ m_axisMaxSliderX->setValue(sampleCountX - 1);
+ m_axisMinSliderZ->setMaximum(sampleCountZ - 2);
+ m_axisMinSliderZ->setValue(0);
+ m_axisMaxSliderZ->setMaximum(sampleCountZ - 1);
+ m_axisMaxSliderZ->setValue(sampleCountZ - 1);
+ //! [8]
+ }
}
-void SurfaceGraph::enableHeightMapModel()
+void SurfaceGraph::enableHeightMapModel(bool enable)
{
- //! [4]
- m_graph->setSurfaceGridEnabled(false);
- m_graph->setSmoothSurfaceEnabled(true);
-
- m_graph->axisX()->setLabelFormat("%.1f N");
- m_graph->axisZ()->setLabelFormat("%.1f E");
- m_graph->axisX()->setRange(34.0, 40.0);
- m_graph->axisY()->setAutoAdjustRange(true);
- m_graph->axisZ()->setRange(18.0, 24.0);
-
- m_graph->setActiveDataProxy(m_heightMapProxy);
- //! [4]
-
- // Reset range sliders for height map
- int mapGridCountX = m_heightMapWidth / heightMapGridStepX;
- int mapGridCountZ = m_heightMapHeight / heightMapGridStepZ;
- m_rangeMinX = 34.0;
- m_rangeMinZ = 18.0;
- m_stepX = 6.0 / qreal(mapGridCountX - 1);
- m_stepZ = 6.0 / qreal(mapGridCountZ - 1);
- m_axisMinSliderX->setMaximum(mapGridCountX - 2);
- m_axisMinSliderX->setValue(0);
- m_axisMaxSliderX->setMaximum(mapGridCountX - 1);
- m_axisMaxSliderX->setValue(mapGridCountX - 1);
- m_axisMinSliderZ->setMaximum(mapGridCountZ - 2);
- m_axisMinSliderZ->setValue(0);
- m_axisMaxSliderZ->setMaximum(mapGridCountZ - 1);
- m_axisMaxSliderZ->setValue(mapGridCountZ - 1);
+ if (enable) {
+ //! [4]
+ m_heightMapSeries->setDrawMode(QSurface3DSeries::DrawSurface);
+ m_heightMapSeries->setFlatShadingEnabled(false);
+
+ m_graph->axisX()->setLabelFormat("%.1f N");
+ m_graph->axisZ()->setLabelFormat("%.1f E");
+ m_graph->axisX()->setRange(34.0f, 40.0f);
+ m_graph->axisY()->setAutoAdjustRange(true);
+ m_graph->axisZ()->setRange(18.0f, 24.0f);
+
+ m_graph->removeSeries(m_sqrtSinSeries);
+ m_graph->addSeries(m_heightMapSeries);
+ //! [4]
+
+ // Reset range sliders for height map
+ int mapGridCountX = m_heightMapWidth / heightMapGridStepX;
+ int mapGridCountZ = m_heightMapHeight / heightMapGridStepZ;
+ m_rangeMinX = 34.0f;
+ m_rangeMinZ = 18.0f;
+ m_stepX = 6.0f / float(mapGridCountX - 1);
+ m_stepZ = 6.0f / float(mapGridCountZ - 1);
+ m_axisMinSliderX->setMaximum(mapGridCountX - 2);
+ m_axisMinSliderX->setValue(0);
+ m_axisMaxSliderX->setMaximum(mapGridCountX - 1);
+ m_axisMaxSliderX->setValue(mapGridCountX - 1);
+ m_axisMinSliderZ->setMaximum(mapGridCountZ - 2);
+ m_axisMinSliderZ->setValue(0);
+ m_axisMaxSliderZ->setMaximum(mapGridCountZ - 1);
+ m_axisMaxSliderZ->setValue(mapGridCountZ - 1);
+ }
}
void SurfaceGraph::adjustXMin(int min)
{
- qreal minX = m_stepX * qreal(min) + m_rangeMinX;
+ float minX = m_stepX * float(min) + m_rangeMinX;
int max = m_axisMaxSliderX->value();
if (min >= max) {
max = min + 1;
m_axisMaxSliderX->setValue(max);
}
- qreal maxX = m_stepX * max + m_rangeMinX;
+ float maxX = m_stepX * max + m_rangeMinX;
setAxisXRange(minX, maxX);
}
void SurfaceGraph::adjustXMax(int max)
{
- qreal maxX = m_stepX * qreal(max) + m_rangeMinX;
+ float maxX = m_stepX * float(max) + m_rangeMinX;
int min = m_axisMinSliderX->value();
if (max <= min) {
min = max - 1;
m_axisMinSliderX->setValue(min);
}
- qreal minX = m_stepX * min + m_rangeMinX;
+ float minX = m_stepX * min + m_rangeMinX;
setAxisXRange(minX, maxX);
}
void SurfaceGraph::adjustZMin(int min)
{
- qreal minZ = m_stepZ * qreal(min) + m_rangeMinZ;
+ float minZ = m_stepZ * float(min) + m_rangeMinZ;
int max = m_axisMaxSliderZ->value();
if (min >= max) {
max = min + 1;
m_axisMaxSliderZ->setValue(max);
}
- qreal maxZ = m_stepZ * max + m_rangeMinZ;
+ float maxZ = m_stepZ * max + m_rangeMinZ;
setAxisZRange(minZ, maxZ);
}
void SurfaceGraph::adjustZMax(int max)
{
- qreal maxX = m_stepZ * qreal(max) + m_rangeMinZ;
+ float maxX = m_stepZ * float(max) + m_rangeMinZ;
int min = m_axisMinSliderZ->value();
if (max <= min) {
min = max - 1;
m_axisMinSliderZ->setValue(min);
}
- qreal minX = m_stepZ * min + m_rangeMinZ;
+ float minX = m_stepZ * min + m_rangeMinZ;
setAxisZRange(minX, maxX);
}
//! [5]
-void SurfaceGraph::setAxisXRange(qreal min, qreal max)
+void SurfaceGraph::setAxisXRange(float min, float max)
{
m_graph->axisX()->setRange(min, max);
}
-void SurfaceGraph::setAxisZRange(qreal min, qreal max)
+void SurfaceGraph::setAxisZRange(float min, float max)
{
m_graph->axisZ()->setRange(min, max);
}
@@ -216,7 +228,7 @@ void SurfaceGraph::setAxisZRange(qreal min, qreal max)
//! [6]
void SurfaceGraph::changeTheme(int theme)
{
- m_graph->setTheme((QDataVis::Theme)theme);
+ m_graph->setTheme(new Q3DTheme(Q3DTheme::Theme(theme)));
}
//! [6]
@@ -229,7 +241,8 @@ void SurfaceGraph::setBlackToYellowGradient()
gr.setColorAt(0.67, Qt::red);
gr.setColorAt(1.0, Qt::yellow);
- m_graph->setGradient(gr);
+ m_graph->seriesList().at(0)->setBaseGradient(gr);
+ m_graph->seriesList().at(0)->setColorStyle(Q3DTheme::ColorStyleRangeGradient);
//! [7]
}
@@ -241,6 +254,7 @@ void SurfaceGraph::setGreenToRedGradient()
gr.setColorAt(0.8, Qt::red);
gr.setColorAt(1.0, Qt::darkRed);
- m_graph->setGradient(gr);
+ m_graph->seriesList().at(0)->setBaseGradient(gr);
+ m_graph->seriesList().at(0)->setColorStyle(Q3DTheme::ColorStyleRangeGradient);
}
diff --git a/examples/surface/surfacegraph.h b/examples/surface/surfacegraph.h
index ac297bf6..ecdec672 100644
--- a/examples/surface/surfacegraph.h
+++ b/examples/surface/surfacegraph.h
@@ -22,6 +22,7 @@
#include <QtDataVisualization/Q3DSurface>
#include <QtDataVisualization/QSurfaceDataProxy>
#include <QtDataVisualization/QHeightMapSurfaceDataProxy>
+#include <QtDataVisualization/QSurface3DSeries>
#include <QtWidgets/QSlider>
using namespace QtDataVisualization;
@@ -33,14 +34,16 @@ public:
explicit SurfaceGraph(Q3DSurface *surface);
~SurfaceGraph();
- void enableHeightMapModel();
- void enableSqrtSinModel();
+ void enableHeightMapModel(bool enable);
+ void enableSqrtSinModel(bool enable);
//! [0]
- void toggleModeNone() { m_graph->setSelectionMode(QDataVis::SelectionModeNone); }
- void toggleModeItem() { m_graph->setSelectionMode(QDataVis::SelectionModeItem); }
- void toggleModeSliceRow() { m_graph->setSelectionMode(QDataVis::SelectionModeSliceRow); }
- void toggleModeSliceColumn() { m_graph->setSelectionMode(QDataVis::SelectionModeSliceColumn); }
+ void toggleModeNone() { m_graph->setSelectionMode(QDataVis::SelectionNone); }
+ void toggleModeItem() { m_graph->setSelectionMode(QDataVis::SelectionItem); }
+ void toggleModeSliceRow() { m_graph->setSelectionMode(QDataVis::SelectionItemAndRow
+ | QDataVis::SelectionSlice); }
+ void toggleModeSliceColumn() { m_graph->setSelectionMode(QDataVis::SelectionItemAndColumn
+ | QDataVis::SelectionSlice); }
//! [0]
void setBlackToYellowGradient();
@@ -62,21 +65,23 @@ public slots:
private:
Q3DSurface *m_graph;
QHeightMapSurfaceDataProxy *m_heightMapProxy;
- QSurfaceDataProxy *sqrtSinProxy;
+ QSurfaceDataProxy *m_sqrtSinProxy;
+ QSurface3DSeries *m_heightMapSeries;
+ QSurface3DSeries *m_sqrtSinSeries;
QSlider *m_axisMinSliderX;
QSlider *m_axisMaxSliderX;
QSlider *m_axisMinSliderZ;
QSlider *m_axisMaxSliderZ;
- qreal m_rangeMinX;
- qreal m_rangeMinZ;
- qreal m_stepX;
- qreal m_stepZ;
+ float m_rangeMinX;
+ float m_rangeMinZ;
+ float m_stepX;
+ float m_stepZ;
int m_heightMapWidth;
int m_heightMapHeight;
- void setAxisXRange(qreal min, qreal max);
- void setAxisZRange(qreal min, qreal max);
+ void setAxisXRange(float min, float max);
+ void setAxisZRange(float min, float max);
void fillSqrtSinProxy();
};
diff --git a/src/datavisualization/axis/q3dabstractaxis.cpp b/src/datavisualization/axis/q3dabstractaxis.cpp
index b0372adc..0b284947 100644
--- a/src/datavisualization/axis/q3dabstractaxis.cpp
+++ b/src/datavisualization/axis/q3dabstractaxis.cpp
@@ -51,6 +51,7 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
/*!
* \qmlproperty list AbstractAxis3D::labels
* Defines the labels for the axis.
+ * \note Setting this property for ValueAxis3D does nothing, as it generates labels automatically.
*/
/*!
@@ -124,27 +125,6 @@ Q3DAbstractAxis::~Q3DAbstractAxis()
}
/*!
- * \property Q3DAbstractAxis::title
- *
- * Defines the title for the axis.
- */
-QString Q3DAbstractAxis::title() const
-{
- return d_ptr->m_title;
-}
-
-/*!
- * \property Q3DAbstractAxis::labels
- *
- * Defines the labels for the axis.
- */
-QStringList Q3DAbstractAxis::labels() const
-{
- d_ptr->updateLabels();
- return d_ptr->m_labels;
-}
-
-/*!
* \property Q3DAbstractAxis::orientation
*
* Defines the orientation of the axis, one of \c Q3DAbstractAxis::AxisOrientation.
@@ -164,6 +144,11 @@ Q3DAbstractAxis::AxisType Q3DAbstractAxis::type() const
return d_ptr->m_type;
}
+/*!
+ * \property Q3DAbstractAxis::title
+ *
+ * Defines the title for the axis.
+ */
void Q3DAbstractAxis::setTitle(QString title)
{
if (d_ptr->m_title != title) {
@@ -172,12 +157,34 @@ void Q3DAbstractAxis::setTitle(QString title)
}
}
+QString Q3DAbstractAxis::title() const
+{
+ return d_ptr->m_title;
+}
+
+/*!
+ * \property Q3DAbstractAxis::labels
+ *
+ * Defines the labels for the axis.
+ * \note Setting this property for Q3DValueAxis does nothing, as it generates labels automatically.
+ */
+void Q3DAbstractAxis::setLabels(const QStringList &labels)
+{
+ Q_UNUSED(labels)
+}
+
+QStringList Q3DAbstractAxis::labels() const
+{
+ d_ptr->updateLabels();
+ return d_ptr->m_labels;
+}
+
/*!
* Sets value range of the axis from \a min to \a max.
* When setting the range, the max is adjusted if necessary, to ensure that the range remains valid.
* \note For Q3DCategoryAxis this specifies the index range of rows or columns to show.
*/
-void Q3DAbstractAxis::setRange(qreal min, qreal max)
+void Q3DAbstractAxis::setRange(float min, float max)
{
d_ptr->setRange(min, max);
setAutoAdjustRange(false);
@@ -191,7 +198,7 @@ void Q3DAbstractAxis::setRange(qreal min, qreal max)
* valid.
* \note For Q3DCategoryAxis this specifies the index of the first row or column to show.
*/
-void Q3DAbstractAxis::setMin(qreal min)
+void Q3DAbstractAxis::setMin(float min)
{
d_ptr->setMin(min);
setAutoAdjustRange(false);
@@ -205,18 +212,18 @@ void Q3DAbstractAxis::setMin(qreal min)
* valid.
* \note For Q3DCategoryAxis this specifies the index of the last row or column to show.
*/
-void Q3DAbstractAxis::setMax(qreal max)
+void Q3DAbstractAxis::setMax(float max)
{
d_ptr->setMax(max);
setAutoAdjustRange(false);
}
-qreal Q3DAbstractAxis::min() const
+float Q3DAbstractAxis::min() const
{
return d_ptr->m_min;
}
-qreal Q3DAbstractAxis::max() const
+float Q3DAbstractAxis::max() const
{
return d_ptr->m_max;
}
@@ -241,6 +248,12 @@ bool Q3DAbstractAxis::isAutoAdjustRange() const
return d_ptr->m_autoAdjust;
}
+/*!
+ * \fn Q3DAbstractAxis::rangeChanged(float min, float max)
+ *
+ * Emits range \a min and \a max values when range changes.
+ */
+
// Q3DAbstractAxisPrivate
Q3DAbstractAxisPrivate::Q3DAbstractAxisPrivate(Q3DAbstractAxis *q, Q3DAbstractAxis::AxisType type)
@@ -249,8 +262,8 @@ Q3DAbstractAxisPrivate::Q3DAbstractAxisPrivate(Q3DAbstractAxis *q, Q3DAbstractAx
m_orientation(Q3DAbstractAxis::AxisOrientationNone),
m_type(type),
m_isDefaultAxis(false),
- m_min(0.0),
- m_max(10.0),
+ m_min(0.0f),
+ m_max(10.0f),
m_autoAdjust(true),
m_onlyPositiveValues(false),
m_allowMinMaxSame(false)
@@ -263,10 +276,12 @@ Q3DAbstractAxisPrivate::~Q3DAbstractAxisPrivate()
void Q3DAbstractAxisPrivate::setOrientation(Q3DAbstractAxis::AxisOrientation orientation)
{
- if (m_orientation == Q3DAbstractAxis::AxisOrientationNone)
+ if (m_orientation == Q3DAbstractAxis::AxisOrientationNone) {
m_orientation = orientation;
- else
+ emit q_ptr->orientationChanged(orientation);
+ } else {
Q_ASSERT("Attempted to reset axis orientation.");
+ }
}
void Q3DAbstractAxisPrivate::updateLabels()
@@ -274,38 +289,39 @@ void Q3DAbstractAxisPrivate::updateLabels()
// Default implementation does nothing
}
-void Q3DAbstractAxisPrivate::setRange(qreal min, qreal max)
+void Q3DAbstractAxisPrivate::setRange(float min, float max)
{
bool adjusted = false;
if (m_onlyPositiveValues) {
- if (min < 0.0) {
- min = 0.0;
+ if (min < 0.0f) {
+ min = 0.0f;
adjusted = true;
}
- if (max < 0.0) {
- max = 0.0;
+ if (max < 0.0f) {
+ max = 0.0f;
adjusted = true;
}
}
// If min >= max, we adjust ranges so that
- // m_max becomes (min + 1.0)
+ // m_max becomes (min + 1.0f)
// as axes need some kind of valid range.
- bool dirty = false;
+ bool minDirty = false;
+ bool maxDirty = false;
if (m_min != min) {
m_min = min;
- dirty = true;
+ minDirty = true;
}
if (m_max != max || min > max || (!m_allowMinMaxSame && min == max)) {
if (min > max || (!m_allowMinMaxSame && min == max)) {
- m_max = min + 1.0;
+ m_max = min + 1.0f;
adjusted = true;
} else {
m_max = max;
}
- dirty = true;
+ maxDirty = true;
}
- if (dirty) {
+ if (minDirty || maxDirty) {
if (adjusted) {
qWarning() << "Warning: Tried to set invalid range for axis."
" Range automatically adjusted to a valid one:"
@@ -313,49 +329,60 @@ void Q3DAbstractAxisPrivate::setRange(qreal min, qreal max)
}
emit q_ptr->rangeChanged(m_min, m_max);
}
+
+ if (minDirty)
+ emit q_ptr->minChanged(m_min);
+ if (maxDirty)
+ emit q_ptr->maxChanged(m_max);
}
-void Q3DAbstractAxisPrivate::setMin(qreal min)
+void Q3DAbstractAxisPrivate::setMin(float min)
{
if (m_onlyPositiveValues) {
- if (min < 0.0) {
- min = 0.0;
+ if (min < 0.0f) {
+ min = 0.0f;
qWarning() << "Warning: Tried to set negative minimum for an axis that only supports"
" positive values:" << min;
}
}
if (m_min != min) {
+ bool maxChanged = false;
if (min > m_max || (!m_allowMinMaxSame && min == m_max)) {
- qreal oldMax = m_max;
- m_max = min + 1.0;
+ float oldMax = m_max;
+ m_max = min + 1.0f;
qWarning() << "Warning: Tried to set minimum to equal or larger than maximum for"
" value axis. Maximum automatically adjusted to a valid one:"
<< oldMax << "-->" << m_max;
+ maxChanged = true;
}
m_min = min;
emit q_ptr->rangeChanged(m_min, m_max);
+ emit q_ptr->minChanged(m_min);
+ if (maxChanged)
+ emit q_ptr->maxChanged(m_max);
}
}
-void Q3DAbstractAxisPrivate::setMax(qreal max)
+void Q3DAbstractAxisPrivate::setMax(float max)
{
if (m_onlyPositiveValues) {
- if (max < 0.0) {
- max = 0.0;
+ if (max < 0.0f) {
+ max = 0.0f;
qWarning() << "Warning: Tried to set negative maximum for an axis that only supports"
" positive values:" << max;
}
}
if (m_max != max) {
+ bool minChanged = false;
if (m_min > max || (!m_allowMinMaxSame && m_min == max)) {
- qreal oldMin = m_min;
- m_min = max - 1.0;
- if (m_onlyPositiveValues && m_min < 0.0) {
- m_min = 0.0;
- if (!m_allowMinMaxSame && max == 0.0) {
+ float oldMin = m_min;
+ m_min = max - 1.0f;
+ if (m_onlyPositiveValues && m_min < 0.0f) {
+ m_min = 0.0f;
+ if (!m_allowMinMaxSame && max == 0.0f) {
m_min = oldMin;
qWarning() << "Unable to set maximum value to zero.";
return;
@@ -364,9 +391,13 @@ void Q3DAbstractAxisPrivate::setMax(qreal max)
qWarning() << "Warning: Tried to set maximum to equal or smaller than minimum for"
" value axis. Minimum automatically adjusted to a valid one:"
<< oldMin << "-->" << m_min;
+ minChanged = true;
}
m_max = max;
emit q_ptr->rangeChanged(m_min, m_max);
+ emit q_ptr->maxChanged(m_max);
+ if (minChanged)
+ emit q_ptr->minChanged(m_min);
}
}
diff --git a/src/datavisualization/axis/q3dabstractaxis.h b/src/datavisualization/axis/q3dabstractaxis.h
index 9e5c426a..825290f5 100644
--- a/src/datavisualization/axis/q3dabstractaxis.h
+++ b/src/datavisualization/axis/q3dabstractaxis.h
@@ -35,11 +35,11 @@ class QT_DATAVISUALIZATION_EXPORT Q3DAbstractAxis : public QObject
Q_ENUMS(AxisOrientation)
Q_ENUMS(AxisType)
Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged)
- Q_PROPERTY(QStringList labels READ labels NOTIFY labelsChanged)
- Q_PROPERTY(AxisOrientation orientation READ orientation)
- Q_PROPERTY(AxisType type READ type)
- Q_PROPERTY(qreal min READ min WRITE setMin NOTIFY rangeChanged)
- Q_PROPERTY(qreal max READ max WRITE setMax NOTIFY rangeChanged)
+ Q_PROPERTY(QStringList labels READ labels WRITE setLabels NOTIFY labelsChanged)
+ Q_PROPERTY(AxisOrientation orientation READ orientation NOTIFY orientationChanged)
+ Q_PROPERTY(AxisType type READ type CONSTANT)
+ Q_PROPERTY(float min READ min WRITE setMin NOTIFY minChanged)
+ Q_PROPERTY(float max READ max WRITE setMax NOTIFY maxChanged)
Q_PROPERTY(bool autoAdjustRange READ isAutoAdjustRange WRITE setAutoAdjustRange NOTIFY autoAdjustRangeChanged)
public:
@@ -63,26 +63,33 @@ protected:
public:
virtual ~Q3DAbstractAxis();
+ void setTitle(QString title);
QString title() const;
+
+ void setLabels(const QStringList &labels);
QStringList labels() const;
AxisOrientation orientation() const;
AxisType type() const;
- qreal min() const;
- qreal max() const;
- bool isAutoAdjustRange() const;
+ void setMin(float min);
+ float min() const;
+
+ void setMax(float max);
+ float max() const;
- void setTitle(QString title);
- void setRange(qreal min, qreal max);
- void setMin(qreal min);
- void setMax(qreal max);
void setAutoAdjustRange(bool autoAdjust);
+ bool isAutoAdjustRange() const;
+
+ void setRange(float min, float max);
signals:
void titleChanged(QString newTitle);
void labelsChanged();
- void rangeChanged(qreal min, qreal max);
+ void orientationChanged(AxisOrientation orientation);
+ void minChanged(float value);
+ void maxChanged(float value);
+ void rangeChanged(float min, float max);
void autoAdjustRangeChanged(bool autoAdjust);
protected:
diff --git a/src/datavisualization/axis/q3dabstractaxis_p.h b/src/datavisualization/axis/q3dabstractaxis_p.h
index 902f65be..3293e41e 100644
--- a/src/datavisualization/axis/q3dabstractaxis_p.h
+++ b/src/datavisualization/axis/q3dabstractaxis_p.h
@@ -47,9 +47,9 @@ public:
inline bool isDefaultAxis() { return m_isDefaultAxis; }
inline void setDefaultAxis(bool isDefault) { m_isDefaultAxis = isDefault; }
- virtual void setRange(qreal min, qreal max);
- virtual void setMin(qreal min);
- virtual void setMax (qreal max);
+ virtual void setRange(float min, float max);
+ virtual void setMin(float min);
+ virtual void setMax (float max);
protected:
virtual void updateLabels();
@@ -61,8 +61,8 @@ protected:
Q3DAbstractAxis::AxisOrientation m_orientation;
Q3DAbstractAxis::AxisType m_type;
bool m_isDefaultAxis;
- qreal m_min;
- qreal m_max;
+ float m_min;
+ float m_max;
bool m_autoAdjust;
bool m_onlyPositiveValues;
bool m_allowMinMaxSame;
diff --git a/src/datavisualization/axis/q3dcategoryaxis.cpp b/src/datavisualization/axis/q3dcategoryaxis.cpp
index 63026379..26a75f93 100644
--- a/src/datavisualization/axis/q3dcategoryaxis.cpp
+++ b/src/datavisualization/axis/q3dcategoryaxis.cpp
@@ -49,10 +49,14 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*/
/*!
- * \qmlproperty list CategoryAxis3D::categoryLabels
+ * \qmlproperty list CategoryAxis3D::labels
+ *
* Defines labels for axis applied to categories. If there are fewer labels than categories, the
* remaining ones do not have a label. If category labels are not defined explicitly, labels are
- * generated from the data row and column labels.
+ * generated from the data row (or column) labels.
+ *
+ * \note If the graph has multiple visible series and category labels are not defined explicitly,
+ * changing the rows (or columns) on any of the attached series will regenerate the labels.
*/
/*!
@@ -61,6 +65,7 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
Q3DCategoryAxis::Q3DCategoryAxis(QObject *parent) :
Q3DAbstractAxis(new Q3DCategoryAxisPrivate(this), parent)
{
+ connect(this, &Q3DCategoryAxis::labelsChanged, this, &Q3DAbstractAxis::labelsChanged);
}
/*!
@@ -71,22 +76,21 @@ Q3DCategoryAxis::~Q3DCategoryAxis()
}
/*!
- * \property Q3DCategoryAxis::categoryLabels
+ * \property Q3DCategoryAxis::labels
*
* Defines labels for axis applied to categories. If there are fewer labels than categories, the
* remaining ones do not have a label. If category labels are not defined explicitly, labels are
- * generated from the data row and column labels.
+ * generated from the data row (or column) labels.
*
- * \note CategoryLabels actually reads/writes the Q3DAbstractAxis::labels property,
- * which is read only there. Since subclass cannot have property with same name,
- * this partially duplicate property is necessary.
+ * \note If the graph has multiple visible series and category labels are not defined explicitly,
+ * changing the rows (or columns) on any of the attached series will regenerate the labels.
*/
-QStringList Q3DCategoryAxis::categoryLabels() const
+QStringList Q3DCategoryAxis::labels() const
{
- return labels();
+ return Q3DAbstractAxis::labels();
}
-void Q3DCategoryAxis::setCategoryLabels(const QStringList &labels)
+void Q3DCategoryAxis::setLabels(const QStringList &labels)
{
dptr()->m_labelsExplicitlySet = !labels.isEmpty();
bool labelsFromData = false;
diff --git a/src/datavisualization/axis/q3dcategoryaxis.h b/src/datavisualization/axis/q3dcategoryaxis.h
index ef545950..7b2b4744 100644
--- a/src/datavisualization/axis/q3dcategoryaxis.h
+++ b/src/datavisualization/axis/q3dcategoryaxis.h
@@ -28,14 +28,17 @@ class Q3DCategoryAxisPrivate;
class QT_DATAVISUALIZATION_EXPORT Q3DCategoryAxis : public Q3DAbstractAxis
{
Q_OBJECT
- Q_PROPERTY(QStringList categoryLabels READ categoryLabels WRITE setCategoryLabels)
+ Q_PROPERTY(QStringList labels READ labels WRITE setLabels NOTIFY labelsChanged)
public:
explicit Q3DCategoryAxis(QObject *parent = 0);
virtual ~Q3DCategoryAxis();
- QStringList categoryLabels() const;
- void setCategoryLabels(const QStringList &labels);
+ void setLabels(const QStringList &labels);
+ QStringList labels() const;
+
+signals:
+ void labelsChanged();
protected:
Q3DCategoryAxisPrivate *dptr();
diff --git a/src/datavisualization/axis/q3dvalueaxis.cpp b/src/datavisualization/axis/q3dvalueaxis.cpp
index 9865625c..746c8617 100644
--- a/src/datavisualization/axis/q3dvalueaxis.cpp
+++ b/src/datavisualization/axis/q3dvalueaxis.cpp
@@ -197,7 +197,7 @@ Q3DValueAxisPrivate::~Q3DValueAxisPrivate()
{
}
-void Q3DValueAxisPrivate::setRange(qreal min, qreal max)
+void Q3DValueAxisPrivate::setRange(float min, float max)
{
bool dirty = (min != m_min || max != m_max);
@@ -207,7 +207,7 @@ void Q3DValueAxisPrivate::setRange(qreal min, qreal max)
emitLabelsChanged();
}
-void Q3DValueAxisPrivate::setMin(qreal min)
+void Q3DValueAxisPrivate::setMin(float min)
{
bool dirty = (min != m_min);
@@ -217,7 +217,7 @@ void Q3DValueAxisPrivate::setMin(qreal min)
emitLabelsChanged();
}
-void Q3DValueAxisPrivate::setMax(qreal max)
+void Q3DValueAxisPrivate::setMax(float max)
{
bool dirty = (max != m_max);
@@ -244,14 +244,14 @@ void Q3DValueAxisPrivate::updateLabels()
newLabels.reserve(m_segmentCount + 1);
// First label is at axis min, which is an extra segment
- qreal segmentStep = (m_max - m_min) / m_segmentCount;
+ float segmentStep = (m_max - m_min) / m_segmentCount;
QString formatString(m_labelFormat);
Utils::ParamType paramType = Utils::findFormatParamType(formatString);
QByteArray formatArray = formatString.toUtf8();
for (int i = 0; i < m_segmentCount; i++) {
- qreal value = m_min + (segmentStep * i);
+ float value = m_min + (segmentStep * i);
newLabels.append(Utils::formatLabel(formatArray, paramType, value));
}
diff --git a/src/datavisualization/axis/q3dvalueaxis_p.h b/src/datavisualization/axis/q3dvalueaxis_p.h
index 5d0084e6..0a98bb04 100644
--- a/src/datavisualization/axis/q3dvalueaxis_p.h
+++ b/src/datavisualization/axis/q3dvalueaxis_p.h
@@ -42,9 +42,9 @@ public:
Q3DValueAxisPrivate(Q3DValueAxis *q);
virtual ~Q3DValueAxisPrivate();
- virtual void setRange(qreal min, qreal max);
- virtual void setMin(qreal min);
- virtual void setMax (qreal max);
+ virtual void setRange(float min, float max);
+ virtual void setMin(float min);
+ virtual void setMax (float max);
protected:
void emitLabelsChanged();
diff --git a/src/datavisualization/common.pri b/src/datavisualization/common.pri
index 5b03ab98..4ffa5646 100644
--- a/src/datavisualization/common.pri
+++ b/src/datavisualization/common.pri
@@ -6,4 +6,5 @@ INCLUDEPATH += $$PWD/engine \
$$PWD/utils \
$$PWD/axis \
$$PWD/data \
- $$PWD/input
+ $$PWD/input \
+ $$PWD/theme
diff --git a/src/datavisualization/data/abstractitemmodelhandler.cpp b/src/datavisualization/data/abstractitemmodelhandler.cpp
index 0ad0ac0b..41f520a4 100644
--- a/src/datavisualization/data/abstractitemmodelhandler.cpp
+++ b/src/datavisualization/data/abstractitemmodelhandler.cpp
@@ -17,14 +17,12 @@
****************************************************************************/
#include "abstractitemmodelhandler_p.h"
-#include "qabstractdatamapping.h"
#include <QTimer>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
AbstractItemModelHandler::AbstractItemModelHandler(QObject *parent)
: QObject(parent),
- m_activeMapping(0),
resolvePending(0)
{
m_resolveTimer.setSingleShot(true);
@@ -38,33 +36,37 @@ AbstractItemModelHandler::~AbstractItemModelHandler()
void AbstractItemModelHandler::setItemModel(const QAbstractItemModel *itemModel)
{
- if (!m_itemModel.isNull())
- QObject::disconnect(m_itemModel, 0, this, 0);
-
- m_itemModel = itemModel;
-
- if (!m_itemModel.isNull()) {
- QObject::connect(m_itemModel.data(), &QAbstractItemModel::columnsInserted,
- this, &AbstractItemModelHandler::handleColumnsInserted);
- QObject::connect(m_itemModel.data(), &QAbstractItemModel::columnsMoved,
- this, &AbstractItemModelHandler::handleColumnsMoved);
- QObject::connect(m_itemModel.data(), &QAbstractItemModel::columnsRemoved,
- this, &AbstractItemModelHandler::handleColumnsRemoved);
- QObject::connect(m_itemModel.data(), &QAbstractItemModel::dataChanged,
- this, &AbstractItemModelHandler::handleDataChanged);
- QObject::connect(m_itemModel.data(), &QAbstractItemModel::layoutChanged,
- this, &AbstractItemModelHandler::handleLayoutChanged);
- QObject::connect(m_itemModel.data(), &QAbstractItemModel::modelReset,
- this, &AbstractItemModelHandler::handleModelReset);
- QObject::connect(m_itemModel.data(), &QAbstractItemModel::rowsInserted,
- this, &AbstractItemModelHandler::handleRowsInserted);
- QObject::connect(m_itemModel.data(), &QAbstractItemModel::rowsMoved,
- this, &AbstractItemModelHandler::handleRowsMoved);
- QObject::connect(m_itemModel.data(), &QAbstractItemModel::rowsRemoved,
- this, &AbstractItemModelHandler::handleRowsRemoved);
+ if (itemModel != m_itemModel.data()) {
+ if (!m_itemModel.isNull())
+ QObject::disconnect(m_itemModel, 0, this, 0);
+
+ m_itemModel = itemModel;
+
+ if (!m_itemModel.isNull()) {
+ QObject::connect(m_itemModel.data(), &QAbstractItemModel::columnsInserted,
+ this, &AbstractItemModelHandler::handleColumnsInserted);
+ QObject::connect(m_itemModel.data(), &QAbstractItemModel::columnsMoved,
+ this, &AbstractItemModelHandler::handleColumnsMoved);
+ QObject::connect(m_itemModel.data(), &QAbstractItemModel::columnsRemoved,
+ this, &AbstractItemModelHandler::handleColumnsRemoved);
+ QObject::connect(m_itemModel.data(), &QAbstractItemModel::dataChanged,
+ this, &AbstractItemModelHandler::handleDataChanged);
+ QObject::connect(m_itemModel.data(), &QAbstractItemModel::layoutChanged,
+ this, &AbstractItemModelHandler::handleLayoutChanged);
+ QObject::connect(m_itemModel.data(), &QAbstractItemModel::modelReset,
+ this, &AbstractItemModelHandler::handleModelReset);
+ QObject::connect(m_itemModel.data(), &QAbstractItemModel::rowsInserted,
+ this, &AbstractItemModelHandler::handleRowsInserted);
+ QObject::connect(m_itemModel.data(), &QAbstractItemModel::rowsMoved,
+ this, &AbstractItemModelHandler::handleRowsMoved);
+ QObject::connect(m_itemModel.data(), &QAbstractItemModel::rowsRemoved,
+ this, &AbstractItemModelHandler::handleRowsRemoved);
+ }
+ if (!m_resolveTimer.isActive())
+ m_resolveTimer.start(0);
+
+ emit itemModelChanged(itemModel);
}
- if (!m_resolveTimer.isActive())
- m_resolveTimer.start(0);
}
const QAbstractItemModel *AbstractItemModelHandler::itemModel() const
@@ -72,59 +74,6 @@ const QAbstractItemModel *AbstractItemModelHandler::itemModel() const
return m_itemModel.data();
}
-void AbstractItemModelHandler::setActiveMapping(QAbstractDataMapping *mapping)
-{
- if (m_activeMapping)
- QObject::disconnect(m_activeMapping, 0, this, 0);
-
- if (mapping)
- addMapping(mapping);
-
- m_activeMapping = mapping;
-
- if (m_activeMapping) {
- QObject::connect(m_activeMapping, &QAbstractDataMapping::mappingChanged,
- this, &AbstractItemModelHandler::handleMappingChanged);
- }
-
- if (!m_resolveTimer.isActive())
- m_resolveTimer.start(0);
-}
-
-QAbstractDataMapping *AbstractItemModelHandler::activeMapping() const
-{
- return m_activeMapping;
-}
-
-void AbstractItemModelHandler::addMapping(QAbstractDataMapping *mapping)
-{
- Q_ASSERT(mapping);
- AbstractItemModelHandler *owner = qobject_cast<AbstractItemModelHandler *>(mapping->parent());
- if (owner != this) {
- Q_ASSERT_X(!owner, "addMapping", "Mapping already attached to a proxy.");
- mapping->setParent(this);
- }
- if (!m_mappings.contains(mapping))
- m_mappings.append(mapping);
-}
-
-void AbstractItemModelHandler::releaseMapping(QAbstractDataMapping *mapping)
-{
- if (mapping && m_mappings.contains(mapping)) {
- // If the mapping is in use, clear the existing mapping
- if (m_activeMapping == mapping)
- setActiveMapping(0);
-
- m_mappings.removeAll(mapping);
- mapping->setParent(0);
- }
-}
-
-QList<QAbstractDataMapping *> AbstractItemModelHandler::mappings() const
-{
- return m_mappings;
-}
-
void AbstractItemModelHandler::handleColumnsInserted(const QModelIndex &parent,
int start, int end)
{
diff --git a/src/datavisualization/data/abstractitemmodelhandler_p.h b/src/datavisualization/data/abstractitemmodelhandler_p.h
index fbaaa1f9..b4d55b4a 100644
--- a/src/datavisualization/data/abstractitemmodelhandler_p.h
+++ b/src/datavisualization/data/abstractitemmodelhandler_p.h
@@ -36,8 +36,6 @@
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-class QAbstractDataMapping;
-
class AbstractItemModelHandler : public QObject
{
Q_OBJECT
@@ -47,11 +45,6 @@ public:
virtual void setItemModel(const QAbstractItemModel *itemModel);
virtual const QAbstractItemModel *itemModel() const;
- virtual void setActiveMapping(QAbstractDataMapping *mapping);
- virtual QAbstractDataMapping *activeMapping() const;
- virtual void addMapping(QAbstractDataMapping *mapping);
- virtual void releaseMapping(QAbstractDataMapping *mapping);
- virtual QList<QAbstractDataMapping *> mappings() const;
public slots:
virtual void handleColumnsInserted(const QModelIndex &parent, int start, int end);
@@ -72,14 +65,15 @@ public slots:
virtual void handleMappingChanged();
virtual void handlePendingResolve();
+signals:
+ void itemModelChanged(const QAbstractItemModel *itemModel);
+
protected:
virtual void resolveModel() = 0;
QPointer<const QAbstractItemModel> m_itemModel; // Not owned
- QAbstractDataMapping *m_activeMapping;
bool resolvePending;
QTimer m_resolveTimer;
- QList<QAbstractDataMapping *> m_mappings;
private:
Q_DISABLE_COPY(AbstractItemModelHandler)
diff --git a/src/datavisualization/data/baritemmodelhandler.cpp b/src/datavisualization/data/baritemmodelhandler.cpp
index f7611668..b67a3d8a 100644
--- a/src/datavisualization/data/baritemmodelhandler.cpp
+++ b/src/datavisualization/data/baritemmodelhandler.cpp
@@ -17,7 +17,6 @@
****************************************************************************/
#include "baritemmodelhandler_p.h"
-#include "qitemmodelbardatamapping_p.h"
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
@@ -36,14 +35,13 @@ BarItemModelHandler::~BarItemModelHandler()
// Resolve entire item model into QBarDataArray.
void BarItemModelHandler::resolveModel()
{
- QItemModelBarDataMapping *mapping = static_cast<QItemModelBarDataMapping *>(m_activeMapping);
- if (m_itemModel.isNull() || !mapping) {
+ if (m_itemModel.isNull()) {
m_proxy->resetArray(0);
return;
}
- if (!mapping->useModelCategories()
- && (mapping->rowRole().isEmpty() || mapping->columnRole().isEmpty())) {
+ if (!m_proxy->useModelCategories()
+ && (m_proxy->rowRole().isEmpty() || m_proxy->columnRole().isEmpty())) {
m_proxy->resetArray(0);
return;
}
@@ -54,11 +52,11 @@ void BarItemModelHandler::resolveModel()
QHash<int, QByteArray> roleHash = m_itemModel->roleNames();
// Default to display role if no mapping
- int valueRole = roleHash.key(mapping->valueRole().toLatin1(), Qt::DisplayRole);
+ int valueRole = roleHash.key(m_proxy->valueRole().toLatin1(), Qt::DisplayRole);
int rowCount = m_itemModel->rowCount();
int columnCount = m_itemModel->columnCount();
- if (mapping->useModelCategories()) {
+ if (m_proxy->useModelCategories()) {
// If dimensions have changed, recreate the array
if (m_proxyArray != m_proxy->array() || columnCount != m_columnCount
|| rowCount != m_proxyArray->size()) {
@@ -79,11 +77,11 @@ void BarItemModelHandler::resolveModel()
columnLabels << m_itemModel->headerData(i, Qt::Horizontal).toString();
m_columnCount = columnCount;
} else {
- int rowRole = roleHash.key(mapping->rowRole().toLatin1());
- int columnRole = roleHash.key(mapping->columnRole().toLatin1());
+ int rowRole = roleHash.key(m_proxy->rowRole().toLatin1());
+ int columnRole = roleHash.key(m_proxy->columnRole().toLatin1());
- bool generateRows = mapping->autoRowCategories();
- bool generateColumns = mapping->autoColumnCategories();
+ bool generateRows = m_proxy->autoRowCategories();
+ bool generateColumns = m_proxy->autoColumnCategories();
QStringList rowList;
QStringList columnList;
// For detecting duplicates in categories generation, using QHashes should be faster than
@@ -92,7 +90,7 @@ void BarItemModelHandler::resolveModel()
QHash<QString, bool> columnListHash;
// Sort values into rows and columns
- typedef QHash<QString, qreal> ColumnValueMap;
+ typedef QHash<QString, float> ColumnValueMap;
QHash <QString, ColumnValueMap> itemValueMap;
for (int i = 0; i < rowCount; i++) {
for (int j = 0; j < columnCount; j++) {
@@ -112,14 +110,14 @@ void BarItemModelHandler::resolveModel()
}
if (generateRows)
- mapping->dptr()->m_rowCategories = rowList;
+ m_proxy->dptr()->m_rowCategories = rowList;
else
- rowList = mapping->rowCategories();
+ rowList = m_proxy->rowCategories();
if (generateColumns)
- mapping->dptr()->m_columnCategories = columnList;
+ m_proxy->dptr()->m_columnCategories = columnList;
else
- columnList = mapping->columnCategories();
+ columnList = m_proxy->columnCategories();
// If dimensions have changed, recreate the array
if (m_proxyArray != m_proxy->array() || columnList.size() != m_columnCount
diff --git a/src/datavisualization/data/baritemmodelhandler_p.h b/src/datavisualization/data/baritemmodelhandler_p.h
index 54b45f2e..99192b55 100644
--- a/src/datavisualization/data/baritemmodelhandler_p.h
+++ b/src/datavisualization/data/baritemmodelhandler_p.h
@@ -30,7 +30,7 @@
#define BARITEMMODELHANDLER_P_H
#include "abstractitemmodelhandler_p.h"
-#include "qitemmodelbardataproxy.h"
+#include "qitemmodelbardataproxy_p.h"
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
diff --git a/src/datavisualization/data/barrenderitem.cpp b/src/datavisualization/data/barrenderitem.cpp
index 558e2f96..67029c60 100644
--- a/src/datavisualization/data/barrenderitem.cpp
+++ b/src/datavisualization/data/barrenderitem.cpp
@@ -25,7 +25,8 @@ BarRenderItem::BarRenderItem()
: AbstractRenderItem(),
m_value(0),
m_height(0.0f),
- m_sliceLabelItem(0)
+ m_sliceLabelItem(0),
+ m_seriesIndex(0)
{
}
@@ -37,6 +38,7 @@ BarRenderItem::BarRenderItem(const BarRenderItem &other)
m_height = other.m_height;
m_sliceLabel = other.m_sliceLabel;
m_sliceLabelItem = 0;
+ m_seriesIndex = other.m_seriesIndex;
}
BarRenderItem::~BarRenderItem()
diff --git a/src/datavisualization/data/barrenderitem_p.h b/src/datavisualization/data/barrenderitem_p.h
index 6cd2b0fa..480d5049 100644
--- a/src/datavisualization/data/barrenderitem_p.h
+++ b/src/datavisualization/data/barrenderitem_p.h
@@ -47,8 +47,8 @@ public:
inline const QPoint &position() const { return m_position; }
// Actual cached data value of the bar (needed to trigger label reformats)
- inline void setValue(qreal value);
- inline qreal value() const { return m_value; }
+ inline void setValue(float value);
+ inline float value() const { return m_value; }
// Normalized bar height
inline void setHeight(GLfloat height) { m_height = height; }
@@ -61,17 +61,23 @@ public:
void setSliceLabel(const QString &label);
QString &sliceLabel(); // Formats label if not previously formatted
+ // Series index in visual series that this item belongs to.
+ // This is only utilized by slicing, so it may not be up to date on all items.
+ inline void setSeriesIndex(int seriesIndex) { m_seriesIndex = seriesIndex; }
+ inline int seriesIndex() { return m_seriesIndex; }
+
protected:
- qreal m_value;
+ float m_value;
QPoint m_position; // x = row, y = column
GLfloat m_height;
QString m_sliceLabel;
LabelItem *m_sliceLabelItem;
+ int m_seriesIndex;
friend class QBarDataItem;
};
-void BarRenderItem::setValue(qreal value)
+void BarRenderItem::setValue(float value)
{
m_value = value;
// Force reformatting on next access by setting label string to null string
diff --git a/src/datavisualization/data/data.pri b/src/datavisualization/data/data.pri
index 770d2bd1..6ebfed6b 100644
--- a/src/datavisualization/data/data.pri
+++ b/src/datavisualization/data/data.pri
@@ -8,8 +8,6 @@ HEADERS += \
$$PWD/barrenderitem_p.h \
$$PWD/qbardataitem.h \
$$PWD/qbardataitem_p.h \
- $$PWD/qitemmodelbardatamapping.h \
- $$PWD/qitemmodelbardatamapping_p.h \
$$PWD/qitemmodelbardataproxy_p.h \
$$PWD/qitemmodelbardataproxy.h \
$$PWD/scatterrenderitem_p.h \
@@ -17,26 +15,28 @@ HEADERS += \
$$PWD/qscatterdataitem_p.h \
$$PWD/qscatterdataproxy.h \
$$PWD/qscatterdataproxy_p.h \
- $$PWD/qitemmodelscatterdatamapping.h \
- $$PWD/qitemmodelscatterdatamapping_p.h \
$$PWD/qitemmodelscatterdataproxy.h \
$$PWD/qitemmodelscatterdataproxy_p.h \
$$PWD/abstractitemmodelhandler_p.h \
$$PWD/baritemmodelhandler_p.h \
- $$PWD/qabstractdatamapping.h \
- $$PWD/qabstractdatamapping_p.h \
$$PWD/scatteritemmodelhandler_p.h \
$$PWD/qsurfacedataproxy.h \
$$PWD/qsurfacedataproxy_p.h \
$$PWD/qheightmapsurfacedataproxy.h \
$$PWD/qheightmapsurfacedataproxy_p.h \
- $$PWD/qitemmodelsurfacedatamapping.h \
- $$PWD/qitemmodelsurfacedatamapping_p.h \
$$PWD/qitemmodelsurfacedataproxy.h \
$$PWD/qitemmodelsurfacedataproxy_p.h \
$$PWD/surfaceitemmodelhandler_p.h \
$$PWD/qsurfacedataitem.h \
- $$PWD/qsurfacedataitem_p.h
+ $$PWD/qsurfacedataitem_p.h \
+ $$PWD/qabstract3dseries.h \
+ $$PWD/qabstract3dseries_p.h \
+ $$PWD/qbar3dseries.h \
+ $$PWD/qbar3dseries_p.h \
+ $$PWD/qscatter3dseries.h \
+ $$PWD/qscatter3dseries_p.h \
+ $$PWD/qsurface3dseries.h \
+ $$PWD/qsurface3dseries_p.h
SOURCES += \
$$PWD/labelitem.cpp \
@@ -45,20 +45,20 @@ SOURCES += \
$$PWD/abstractrenderitem.cpp \
$$PWD/barrenderitem.cpp \
$$PWD/qbardataitem.cpp \
- $$PWD/qitemmodelbardatamapping.cpp \
$$PWD/qitemmodelbardataproxy.cpp \
$$PWD/scatterrenderitem.cpp \
$$PWD/qscatterdataitem.cpp \
$$PWD/qscatterdataproxy.cpp \
- $$PWD/qitemmodelscatterdatamapping.cpp \
$$PWD/qitemmodelscatterdataproxy.cpp \
$$PWD/abstractitemmodelhandler.cpp \
$$PWD/baritemmodelhandler.cpp \
- $$PWD/qabstractdatamapping.cpp \
$$PWD/scatteritemmodelhandler.cpp \
$$PWD/qsurfacedataproxy.cpp \
$$PWD/qheightmapsurfacedataproxy.cpp \
- $$PWD/qitemmodelsurfacedatamapping.cpp \
$$PWD/qitemmodelsurfacedataproxy.cpp \
$$PWD/surfaceitemmodelhandler.cpp \
- $$PWD/qsurfacedataitem.cpp
+ $$PWD/qsurfacedataitem.cpp \
+ $$PWD/qabstract3dseries.cpp \
+ $$PWD/qbar3dseries.cpp \
+ $$PWD/qscatter3dseries.cpp \
+ $$PWD/qsurface3dseries.cpp
diff --git a/src/datavisualization/data/qabstract3dseries.cpp b/src/datavisualization/data/qabstract3dseries.cpp
new file mode 100644
index 00000000..2c869574
--- /dev/null
+++ b/src/datavisualization/data/qabstract3dseries.cpp
@@ -0,0 +1,667 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#include "qabstract3dseries.h"
+#include "qabstract3dseries_p.h"
+#include "qabstractdataproxy_p.h"
+#include "abstract3dcontroller_p.h"
+
+QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
+/*!
+ * \class QAbstract3DSeries
+ * \inmodule QtDataVisualization
+ * \brief Base class for all QtDataVisualization series.
+ * \since Qt Data Visualization 1.0
+ *
+ * You use the visualization type specific inherited classes instead of the base class.
+ * \sa QBar3DSeries, QScatter3DSeries, QSurface3DSeries, {Qt Data Visualization Data Handling}
+ */
+
+/*!
+ * \qmltype Abstract3DSeries
+ * \inqmlmodule QtDataVisualization
+ * \since QtDataVisualization 1.0
+ * \ingroup datavisualization_qml
+ * \instantiates QAbstract3DSeries
+ * \brief Base type for all QtDataVisualization series.
+ *
+ * This type is uncreatable, but contains properties that are exposed via subtypes.
+ * \sa Bar3DSeries, Scatter3DSeries, Surface3DSeries, {Qt Data Visualization Data Handling}
+ */
+
+/*!
+ * \qmlproperty Abstract3DSeries.SeriesType Abstract3DSeries::type
+ * The type of the series.
+ */
+
+/*!
+ * \qmlproperty string Abstract3DSeries::itemLabelFormat
+ *
+ * Label format for data items in this series. This format is used for single item labels,
+ * for example, when an item is selected. How the format is interpreted depends on series type. See
+ * each series class documentation for more information.
+ */
+
+/*!
+ * \qmlproperty bool Abstract3DSeries::visible
+ * Sets the visibility of the series. If false, the series is not rendered.
+ */
+
+/*!
+ * \qmlproperty Abstract3DSeries.Mesh Abstract3DSeries::mesh
+ *
+ * Sets the mesh of the items in the series, or the selection pointer in case of
+ * Surface3DSeries. If the \a mesh is \l{QAbstract3DSeries::MeshUserDefined}{Abstract3DSeries.MeshUserDefined},
+ * then the userDefinedMesh property must also be set for items to render properly.
+ * The default value depends on the graph type.
+ */
+
+/*!
+ * \qmlproperty bool Abstract3DSeries::meshSmooth
+ *
+ * If \a enable is \c true, smooth versions of predefined meshes set via mesh property are used.
+ * This property doesn't affect custom meshes used when mesh is
+ * \l{QAbstract3DSeries::MeshUserDefined}{Abstract3DSeries.MeshUserDefined}.
+ * Defaults to \c false.
+ */
+
+/*!
+ * \qmlproperty string Abstract3DSeries::userDefinedMesh
+ *
+ * Sets the \a fileName for user defined custom mesh for objects that is used when mesh
+ * is \l{QAbstract3DSeries::MeshUserDefined}{Abstract3DSeries.MeshUserDefined}.
+ * \note The file specified by \a fileName needs to be in Wavefront obj format and include
+ * vertices, normals and UVs. It also needs to be in triangles.
+ */
+
+/*!
+ * \qmlproperty Theme3D.ColorStyle Abstract3DSeries::colorStyle
+ *
+ * Sets the color \a style for the series.
+ * See \l{Theme3D::colorStyle}{Theme3D.colorStyle}
+ * documentation for more information.
+ */
+
+/*!
+ * \qmlproperty Color Abstract3DSeries::baseColor
+ *
+ * Sets the base \c color of the series.
+ * See \l{Theme3D::baseColors}{Theme3D.baseColors}
+ * documentation for more information.
+ *
+ * \sa colorStyle
+ */
+
+/*!
+ * \qmlproperty ColorGradient Abstract3DSeries::baseGradient
+ *
+ * Sets the base \c gradient of the series.
+ * See \l{Theme3D::baseGradients}{Theme3D.baseGradients}
+ * documentation for more information.
+ *
+ * \sa colorStyle
+ */
+
+/*!
+ * \qmlproperty Color Abstract3DSeries::singleHighlightColor
+ *
+ * Sets the single item highlight \c color of the series.
+ * See \l{Theme3D::singleHighlightColor}{Theme3D.singleHighlightColor}
+ * documentation for more information.
+ *
+ * \sa colorStyle
+ */
+
+/*!
+ * \qmlproperty ColorGradient Abstract3DSeries::singleHighlightGradient
+ *
+ * Sets the single item highlight \c gradient of the series.
+ * See \l{Theme3D::singleHighlightGradient}{Theme3D.singleHighlightGradient}
+ * documentation for more information.
+ *
+ * \sa colorStyle
+ */
+
+/*!
+ * \qmlproperty Color Abstract3DSeries::multiHighlightColor
+ *
+ * Sets the multiple item highlight \c color of the series.
+ * See \l{Theme3D::multiHighlightColor}{Theme3D.multiHighlightColor}
+ * documentation for more information.
+ *
+ * \sa colorStyle
+ */
+
+/*!
+ * \qmlproperty ColorGradient Abstract3DSeries::multiHighlightGradient
+ *
+ * Sets the multiple item highlight \c gradient of the series.
+ * See \l{Theme3D::multiHighlightGradient}{Theme3D.multiHighlightGradient}
+ * documentation for more information.
+ *
+ * \sa colorStyle
+ */
+
+/*!
+ * \enum QAbstract3DSeries::SeriesType
+ *
+ * Type of the series.
+ *
+ * \value SeriesTypeNone
+ * No series type.
+ * \value SeriesTypeBar
+ * Series type for Q3DBars.
+ * \value SeriesTypeScatter
+ * Series type for Q3DScatter.
+ * \value SeriesTypeSurface
+ * Series type for Q3DSurface.
+ */
+
+/*!
+ * \enum QAbstract3DSeries::Mesh
+ *
+ * Predefined mesh types. All styles are not usable with all visualization types.
+ *
+ * \value MeshUserDefined
+ * User defined mesh, set via QAbstract3DSeries::userDefinedMesh property.
+ * \value MeshBar
+ * Basic rectangular bar.
+ * \value MeshCube
+ * Basic cube.
+ * \value MeshPyramid
+ * Four-sided pyramid.
+ * \value MeshCone
+ * Basic cone.
+ * \value MeshCylinder
+ * Basic cylinder.
+ * \value MeshBevelBar
+ * Slightly beveled (rounded) rectangular bar.
+ * \value MeshBevelCube
+ * Slightly beveled (rounded) cube.
+ * \value MeshSphere
+ * Sphere.
+ * \value MeshMinimal
+ * The minimal 3D mesh: a triangular pyramid. Usable only with Q3DScatter.
+ * \value MeshPoint
+ * 2D point. Usable only with Q3DScatter.
+ * \b Note: Shadows and color gradients do not affect this style.
+ */
+
+/*!
+ * \internal
+ */
+QAbstract3DSeries::QAbstract3DSeries(QAbstract3DSeriesPrivate *d, QObject *parent) :
+ QObject(parent),
+ d_ptr(d)
+{
+}
+
+/*!
+ * Destroys QAbstract3DSeries.
+ */
+QAbstract3DSeries::~QAbstract3DSeries()
+{
+}
+
+/*!
+ * \property QAbstract3DSeries::type
+ *
+ * The type of the series.
+ */
+QAbstract3DSeries::SeriesType QAbstract3DSeries::type() const
+{
+ return d_ptr->m_type;
+}
+
+/*!
+ * \property QAbstract3DSeries::itemLabelFormat
+ *
+ * Sets label \a format for data items in this series. This format is used for single item labels,
+ * for example, when an item is selected. How the format is interpreted depends on series type. See
+ * each series class documentation for more information.
+ *
+ * \sa QBar3DSeries, QScatter3DSeries, QSurface3DSeries
+ */
+void QAbstract3DSeries::setItemLabelFormat(const QString &format)
+{
+ if (d_ptr->m_itemLabelFormat != format) {
+ d_ptr->setItemLabelFormat(format);
+ emit itemLabelFormatChanged(format);
+ }
+}
+
+QString QAbstract3DSeries::itemLabelFormat() const
+{
+ return d_ptr->m_itemLabelFormat;
+}
+
+/*!
+ * \property QAbstract3DSeries::visible
+ *
+ * Sets the visibility of the series. If \a visible is false, the series is not rendered.
+ * Defaults to true.
+ */
+void QAbstract3DSeries::setVisible(bool visible)
+{
+ if (d_ptr->m_visible != visible) {
+ d_ptr->setVisible(visible);
+ emit visibilityChanged(visible);
+ }
+}
+
+bool QAbstract3DSeries::isVisible() const
+{
+ return d_ptr->m_visible;
+}
+
+/*!
+ * \property QAbstract3DSeries::mesh
+ *
+ * Sets the mesh of the items in the series, or the selection pointer in case of
+ * QSurface3DSeries. If the \a mesh is MeshUserDefined, then the userDefinedMesh property
+ * must also be set for items to render properly. The default value depends on the graph type.
+ */
+void QAbstract3DSeries::setMesh(QAbstract3DSeries::Mesh mesh)
+{
+ if ((mesh == QAbstract3DSeries::MeshPoint || mesh == QAbstract3DSeries::MeshMinimal)
+ && type() != QAbstract3DSeries::SeriesTypeScatter) {
+ qWarning() << "Specified style is only supported for QScatter3DSeries.";
+ } else if (d_ptr->m_mesh != mesh) {
+ d_ptr->setMesh(mesh);
+ emit meshChanged(mesh);
+ }
+}
+
+QAbstract3DSeries::Mesh QAbstract3DSeries::mesh() const
+{
+ return d_ptr->m_mesh;
+}
+
+/*!
+ * \property QAbstract3DSeries::meshSmooth
+ *
+ * If \a enable is \c true, smooth versions of predefined meshes set via mesh property are used.
+ * This property doesn't affect custom meshes used when mesh is MeshUserDefined.
+ * Defaults to \c false.
+ */
+void QAbstract3DSeries::setMeshSmooth(bool enable)
+{
+ if (d_ptr->m_meshSmooth != enable) {
+ d_ptr->setMeshSmooth(enable);
+ emit meshSmoothChanged(enable);
+ }
+}
+
+bool QAbstract3DSeries::isMeshSmooth() const
+{
+ return d_ptr->m_meshSmooth;
+}
+
+/*!
+ * \property QAbstract3DSeries::userDefinedMesh
+ *
+ * Sets the \a fileName for user defined custom mesh for objects that is used when mesh
+ * is MeshUserDefined.
+ * \note The file specified by \a fileName needs to be in Wavefront obj format and include
+ * vertices, normals and UVs. It also needs to be in triangles.
+ */
+void QAbstract3DSeries::setUserDefinedMesh(const QString &fileName)
+{
+ if (d_ptr->m_userDefinedMesh != fileName) {
+ d_ptr->setUserDefinedMesh(fileName);
+ emit userDefinedMeshChanged(fileName);
+ }
+}
+
+QString QAbstract3DSeries::userDefinedMesh() const
+{
+ return d_ptr->m_userDefinedMesh;
+}
+
+/*!
+ * \property QAbstract3DSeries::colorStyle
+ *
+ * Sets the color \a style for the series.
+ * See Q3DTheme::ColorStyle documentation for more information.
+ */
+void QAbstract3DSeries::setColorStyle(Q3DTheme::ColorStyle style)
+{
+ if (d_ptr->m_colorStyle != style) {
+ d_ptr->setColorStyle(style);
+ emit colorStyleChanged(style);
+ }
+ d_ptr->m_themeTracker.colorStyleOverride = true;
+}
+
+Q3DTheme::ColorStyle QAbstract3DSeries::colorStyle() const
+{
+ return d_ptr->m_colorStyle;
+}
+
+/*!
+ * \property QAbstract3DSeries::baseColor
+ *
+ * Sets the base \c color of the series.
+ * See Q3DTheme::baseColor documentation for more information.
+ *
+ * \sa colorStyle
+ */
+void QAbstract3DSeries::setBaseColor(const QColor &color)
+{
+ if (d_ptr->m_baseColor != color) {
+ d_ptr->setBaseColor(color);
+ emit baseColorChanged(color);
+ }
+ d_ptr->m_themeTracker.baseColorOverride = true;
+}
+
+QColor QAbstract3DSeries::baseColor() const
+{
+ return d_ptr->m_baseColor;
+}
+
+/*!
+ * \property QAbstract3DSeries::baseGradient
+ *
+ * Sets the base \c gradient of the series.
+ * See Q3DTheme::baseGradient documentation for more information.
+ *
+ * \sa colorStyle
+ */
+void QAbstract3DSeries::setBaseGradient(const QLinearGradient &gradient)
+{
+ if (d_ptr->m_baseGradient != gradient) {
+ d_ptr->setBaseGradient(gradient);
+ emit baseGradientChanged(gradient);
+ }
+ d_ptr->m_themeTracker.baseGradientOverride = true;
+}
+
+QLinearGradient QAbstract3DSeries::baseGradient() const
+{
+ return d_ptr->m_baseGradient;
+}
+
+/*!
+ * \property QAbstract3DSeries::singleHighlightColor
+ *
+ * Sets the single item highlight \c color of the series.
+ * See Q3DTheme::singleHighlightColor documentation for more information.
+ *
+ * \sa colorStyle
+ */
+void QAbstract3DSeries::setSingleHighlightColor(const QColor &color)
+{
+ if (d_ptr->m_singleHighlightColor != color) {
+ d_ptr->setSingleHighlightColor(color);
+ emit singleHighlightColorChanged(color);
+ }
+ d_ptr->m_themeTracker.singleHighlightColorOverride = true;
+}
+
+QColor QAbstract3DSeries::singleHighlightColor() const
+{
+ return d_ptr->m_singleHighlightColor;
+}
+
+/*!
+ * \property QAbstract3DSeries::singleHighlightGradient
+ *
+ * Sets the single item highlight \c gradient of the series.
+ * See Q3DTheme::singleHighlightGradient documentation for more information.
+ *
+ * \sa colorStyle
+ */
+void QAbstract3DSeries::setSingleHighlightGradient(const QLinearGradient &gradient)
+{
+ if (d_ptr->m_singleHighlightGradient != gradient) {
+ d_ptr->setSingleHighlightGradient(gradient);
+ emit singleHighlightGradientChanged(gradient);
+ }
+ d_ptr->m_themeTracker.singleHighlightGradientOverride = true;
+}
+
+QLinearGradient QAbstract3DSeries::singleHighlightGradient() const
+{
+ return d_ptr->m_singleHighlightGradient;
+}
+
+/*!
+ * \property QAbstract3DSeries::multiHighlightColor
+ *
+ * Sets the multiple item highlight \c color of the series.
+ * See Q3DTheme::multiHighlightColor documentation for more information.
+ *
+ * \sa colorStyle
+ */
+void QAbstract3DSeries::setMultiHighlightColor(const QColor &color)
+{
+ if (d_ptr->m_multiHighlightColor != color) {
+ d_ptr->setMultiHighlightColor(color);
+ emit multiHighlightColorChanged(color);
+ }
+ d_ptr->m_themeTracker.multiHighlightColorOverride = true;
+}
+
+QColor QAbstract3DSeries::multiHighlightColor() const
+{
+ return d_ptr->m_multiHighlightColor;
+}
+
+/*!
+ * \property QAbstract3DSeries::multiHighlightGradient
+ *
+ * Sets the multiple item highlight \c gradient of the series.
+ * See Q3DTheme::multiHighlightGradient documentation for more information.
+ *
+ * \sa colorStyle
+ */
+void QAbstract3DSeries::setMultiHighlightGradient(const QLinearGradient &gradient)
+{
+ if (d_ptr->m_multiHighlightGradient != gradient) {
+ d_ptr->setMultiHighlightGradient(gradient);
+ emit multiHighlightGradientChanged(gradient);
+ }
+ d_ptr->m_themeTracker.multiHighlightGradientOverride = true;
+}
+
+QLinearGradient QAbstract3DSeries::multiHighlightGradient() const
+{
+ return d_ptr->m_multiHighlightGradient;
+}
+
+// QAbstract3DSeriesPrivate
+
+QAbstract3DSeriesPrivate::QAbstract3DSeriesPrivate(QAbstract3DSeries *q, QAbstract3DSeries::SeriesType type)
+ : QObject(0),
+ q_ptr(q),
+ m_type(type),
+ m_dataProxy(0),
+ m_visible(true),
+ m_controller(0),
+ m_mesh(QAbstract3DSeries::MeshCube),
+ m_meshSmooth(false),
+ m_colorStyle(Q3DTheme::ColorStyleUniform)
+{
+}
+
+QAbstract3DSeriesPrivate::~QAbstract3DSeriesPrivate()
+{
+}
+
+QAbstractDataProxy *QAbstract3DSeriesPrivate::dataProxy() const
+{
+ return m_dataProxy;
+}
+
+void QAbstract3DSeriesPrivate::setDataProxy(QAbstractDataProxy *proxy)
+{
+ Q_ASSERT(proxy && proxy != m_dataProxy && !proxy->d_ptr->series());
+
+ delete m_dataProxy;
+ m_dataProxy = proxy;
+
+ proxy->d_ptr->setSeries(q_ptr); // also sets parent
+
+ if (m_controller) {
+ connectControllerAndProxy(m_controller);
+ m_controller->markDataDirty();
+ }
+}
+
+void QAbstract3DSeriesPrivate::setController(Abstract3DController *controller)
+{
+ connectControllerAndProxy(controller);
+ m_controller = controller;
+ q_ptr->setParent(controller);
+}
+
+void QAbstract3DSeriesPrivate::setItemLabelFormat(const QString &format)
+{
+ m_itemLabelFormat = format;
+ m_changeTracker.itemLabelFormatChanged = true;
+ if (m_controller)
+ m_controller->markSeriesVisualsDirty();
+}
+
+void QAbstract3DSeriesPrivate::setVisible(bool visible)
+{
+ m_visible = visible;
+ if (m_controller)
+ m_controller->markSeriesVisualsDirty();
+}
+
+void QAbstract3DSeriesPrivate::setMesh(QAbstract3DSeries::Mesh mesh)
+{
+ m_mesh = mesh;
+ m_changeTracker.meshChanged = true;
+ if (m_controller)
+ m_controller->markSeriesVisualsDirty();
+}
+
+void QAbstract3DSeriesPrivate::setMeshSmooth(bool enable)
+{
+ m_meshSmooth = enable;
+ m_changeTracker.meshSmoothChanged = true;
+ if (m_controller)
+ m_controller->markSeriesVisualsDirty();
+}
+
+void QAbstract3DSeriesPrivate::setUserDefinedMesh(const QString &meshFile)
+{
+ m_userDefinedMesh = meshFile;
+ m_changeTracker.userDefinedMeshChanged = true;
+ if (m_controller)
+ m_controller->markSeriesVisualsDirty();
+}
+
+void QAbstract3DSeriesPrivate::setColorStyle(Q3DTheme::ColorStyle style)
+{
+ m_colorStyle = style;
+ m_changeTracker.colorStyleChanged = true;
+ if (m_controller)
+ m_controller->markSeriesVisualsDirty();
+}
+
+void QAbstract3DSeriesPrivate::setBaseColor(const QColor &color)
+{
+ m_baseColor = color;
+ m_changeTracker.baseColorChanged = true;
+ if (m_controller)
+ m_controller->markSeriesVisualsDirty();
+}
+
+void QAbstract3DSeriesPrivate::setBaseGradient(const QLinearGradient &gradient)
+{
+ m_baseGradient = gradient;
+ m_changeTracker.baseGradientChanged = true;
+ if (m_controller)
+ m_controller->markSeriesVisualsDirty();
+}
+
+void QAbstract3DSeriesPrivate::setSingleHighlightColor(const QColor &color)
+{
+ m_singleHighlightColor = color;
+ m_changeTracker.singleHighlightColorChanged = true;
+ if (m_controller)
+ m_controller->markSeriesVisualsDirty();
+}
+
+void QAbstract3DSeriesPrivate::setSingleHighlightGradient(const QLinearGradient &gradient)
+{
+ m_singleHighlightGradient = gradient;
+ m_changeTracker.singleHighlightGradientChanged = true;
+ if (m_controller)
+ m_controller->markSeriesVisualsDirty();
+}
+
+void QAbstract3DSeriesPrivate::setMultiHighlightColor(const QColor &color)
+{
+ m_multiHighlightColor = color;
+ m_changeTracker.multiHighlightColorChanged = true;
+ if (m_controller)
+ m_controller->markSeriesVisualsDirty();
+}
+
+void QAbstract3DSeriesPrivate::setMultiHighlightGradient(const QLinearGradient &gradient)
+{
+ m_multiHighlightGradient = gradient;
+ m_changeTracker.multiHighlightGradientChanged = true;
+ if (m_controller)
+ m_controller->markSeriesVisualsDirty();
+}
+
+void QAbstract3DSeriesPrivate::resetToTheme(const Q3DTheme &theme, int seriesIndex, bool force)
+{
+ int themeIndex = seriesIndex;
+ if (force || !m_themeTracker.colorStyleOverride) {
+ q_ptr->setColorStyle(theme.colorStyle());
+ m_themeTracker.colorStyleOverride = false;
+ }
+ if (force || !m_themeTracker.baseColorOverride) {
+ if (theme.baseColors().size() <= seriesIndex)
+ themeIndex = seriesIndex % theme.baseColors().size();
+ q_ptr->setBaseColor(theme.baseColors().at(themeIndex));
+ m_themeTracker.baseColorOverride = false;
+ }
+ if (force || !m_themeTracker.baseGradientOverride) {
+ if (theme.baseGradients().size() <= seriesIndex)
+ themeIndex = seriesIndex % theme.baseGradients().size();
+ q_ptr->setBaseGradient(theme.baseGradients().at(themeIndex));
+ m_themeTracker.baseGradientOverride = false;
+ }
+ if (force || !m_themeTracker.singleHighlightColorOverride) {
+ q_ptr->setSingleHighlightColor(theme.singleHighlightColor());
+ m_themeTracker.singleHighlightColorOverride = false;
+ }
+ if (force || !m_themeTracker.singleHighlightGradientOverride) {
+ q_ptr->setSingleHighlightGradient(theme.singleHighlightGradient());
+ m_themeTracker.singleHighlightGradientOverride = false;
+ }
+ if (force || !m_themeTracker.multiHighlightColorOverride) {
+ q_ptr->setMultiHighlightColor(theme.multiHighlightColor());
+ m_themeTracker.multiHighlightColorOverride = false;
+ }
+ if (force || !m_themeTracker.multiHighlightGradientOverride) {
+ q_ptr->setMultiHighlightGradient(theme.multiHighlightGradient());
+ m_themeTracker.multiHighlightGradientOverride = false;
+ }
+}
+
+QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/data/qabstract3dseries.h b/src/datavisualization/data/qabstract3dseries.h
new file mode 100644
index 00000000..ebe73510
--- /dev/null
+++ b/src/datavisualization/data/qabstract3dseries.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#ifndef QABSTRACT3DSERIES_H
+#define QABSTRACT3DSERIES_H
+
+#include <QtDataVisualization/qdatavisualizationenums.h>
+#include <QtDataVisualization/q3dtheme.h>
+#include <QObject>
+#include <QScopedPointer>
+#include <QLinearGradient>
+
+QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
+class QAbstract3DSeriesPrivate;
+
+class QT_DATAVISUALIZATION_EXPORT QAbstract3DSeries : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(SeriesType)
+ Q_ENUMS(Mesh)
+ Q_PROPERTY(SeriesType type READ type CONSTANT)
+ Q_PROPERTY(QString itemLabelFormat READ itemLabelFormat WRITE setItemLabelFormat NOTIFY itemLabelFormatChanged)
+ Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibilityChanged)
+ Q_PROPERTY(Mesh mesh READ mesh WRITE setMesh NOTIFY meshChanged)
+ Q_PROPERTY(bool meshSmooth READ isMeshSmooth WRITE setMeshSmooth NOTIFY meshSmoothChanged)
+ Q_PROPERTY(QString userDefinedMesh READ userDefinedMesh WRITE setUserDefinedMesh NOTIFY userDefinedMeshChanged)
+ Q_PROPERTY(QtDataVisualization::Q3DTheme::ColorStyle colorStyle READ colorStyle WRITE setColorStyle NOTIFY colorStyleChanged)
+ Q_PROPERTY(QColor baseColor READ baseColor WRITE setBaseColor NOTIFY baseColorChanged)
+ Q_PROPERTY(QLinearGradient baseGradient READ baseGradient WRITE setBaseGradient NOTIFY baseGradientChanged)
+ Q_PROPERTY(QColor singleHighlightColor READ singleHighlightColor WRITE setSingleHighlightColor NOTIFY singleHighlightColorChanged)
+ Q_PROPERTY(QLinearGradient singleHighlightGradient READ singleHighlightGradient WRITE setSingleHighlightGradient NOTIFY singleHighlightGradientChanged)
+ Q_PROPERTY(QColor multiHighlightColor READ multiHighlightColor WRITE setMultiHighlightColor NOTIFY multiHighlightColorChanged)
+ Q_PROPERTY(QLinearGradient multiHighlightGradient READ multiHighlightGradient WRITE setMultiHighlightGradient NOTIFY multiHighlightGradientChanged)
+
+public:
+ enum SeriesType {
+ SeriesTypeNone = 0,
+ SeriesTypeBar = 1,
+ SeriesTypeScatter = 2,
+ SeriesTypeSurface = 4
+ };
+
+ enum Mesh {
+ MeshUserDefined = 0,
+ MeshBar,
+ MeshCube,
+ MeshPyramid,
+ MeshCone,
+ MeshCylinder,
+ MeshBevelBar,
+ MeshBevelCube,
+ MeshSphere,
+ MeshMinimal,
+ MeshPoint
+ };
+
+protected:
+ explicit QAbstract3DSeries(QAbstract3DSeriesPrivate *d, QObject *parent = 0);
+
+public:
+ virtual ~QAbstract3DSeries();
+
+ SeriesType type() const;
+
+ void setItemLabelFormat(const QString &format);
+ QString itemLabelFormat() const;
+
+ void setVisible(bool visible);
+ bool isVisible() const;
+
+ void setMesh(Mesh mesh);
+ Mesh mesh() const;
+
+ void setMeshSmooth(bool enable);
+ bool isMeshSmooth() const;
+
+ void setUserDefinedMesh(const QString &fileName);
+ QString userDefinedMesh() const;
+
+ void setColorStyle(Q3DTheme::ColorStyle style);
+ Q3DTheme::ColorStyle colorStyle() const;
+ void setBaseColor(const QColor &color);
+ QColor baseColor() const;
+ void setBaseGradient(const QLinearGradient &gradient);
+ QLinearGradient baseGradient() const;
+ void setSingleHighlightColor(const QColor &color);
+ QColor singleHighlightColor() const;
+ void setSingleHighlightGradient(const QLinearGradient &gradient);
+ QLinearGradient singleHighlightGradient() const;
+ void setMultiHighlightColor(const QColor &color);
+ QColor multiHighlightColor() const;
+ void setMultiHighlightGradient(const QLinearGradient &gradient);
+ QLinearGradient multiHighlightGradient() const;
+
+signals:
+ void itemLabelFormatChanged(QString format);
+ void visibilityChanged(bool visible);
+ void meshChanged(Mesh mesh);
+ void meshSmoothChanged(bool enabled);
+ void userDefinedMeshChanged(QString fileName);
+ void colorStyleChanged(Q3DTheme::ColorStyle style);
+ void baseColorChanged(QColor color);
+ void baseGradientChanged(QLinearGradient gradient);
+ void singleHighlightColorChanged(QColor color);
+ void singleHighlightGradientChanged(QLinearGradient gradient);
+ void multiHighlightColorChanged(QColor color);
+ void multiHighlightGradientChanged(QLinearGradient gradient);
+
+protected:
+ QScopedPointer<QAbstract3DSeriesPrivate> d_ptr;
+
+private:
+ Q_DISABLE_COPY(QAbstract3DSeries)
+
+ friend class Abstract3DController;
+ friend class Bars3DController;
+ friend class Surface3DController;
+ friend class Scatter3DController;
+ friend class QBar3DSeries;
+ friend class SeriesRenderCache;
+};
+
+QT_DATAVISUALIZATION_END_NAMESPACE
+
+#endif
diff --git a/src/datavisualization/data/qabstract3dseries_p.h b/src/datavisualization/data/qabstract3dseries_p.h
new file mode 100644
index 00000000..7b2ea2e6
--- /dev/null
+++ b/src/datavisualization/data/qabstract3dseries_p.h
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the QtDataVisualization 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 "datavisualizationglobal_p.h"
+#include "qabstract3dseries.h"
+#include <QString>
+
+#ifndef QABSTRACT3DSERIES_P_H
+#define QABSTRACT3DSERIES_P_H
+
+QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
+class QAbstractDataProxy;
+class Abstract3DController;
+
+struct QAbstract3DSeriesChangeBitField {
+ bool itemLabelFormatChanged : 1;
+ bool meshChanged : 1;
+ bool meshSmoothChanged : 1;
+ bool userDefinedMeshChanged : 1;
+ bool colorStyleChanged : 1;
+ bool baseColorChanged : 1;
+ bool baseGradientChanged : 1;
+ bool singleHighlightColorChanged : 1;
+ bool singleHighlightGradientChanged : 1;
+ bool multiHighlightColorChanged : 1;
+ bool multiHighlightGradientChanged : 1;
+
+ QAbstract3DSeriesChangeBitField()
+ : itemLabelFormatChanged(true),
+ meshChanged(true),
+ meshSmoothChanged(true),
+ userDefinedMeshChanged(true),
+ colorStyleChanged(true),
+ baseColorChanged(true),
+ baseGradientChanged(true),
+ singleHighlightColorChanged(true),
+ singleHighlightGradientChanged(true),
+ multiHighlightColorChanged(true),
+ multiHighlightGradientChanged(true)
+ {
+ }
+};
+
+struct QAbstract3DSeriesThemeOverrideBitField {
+ bool colorStyleOverride : 1;
+ bool baseColorOverride : 1;
+ bool baseGradientOverride : 1;
+ bool singleHighlightColorOverride : 1;
+ bool singleHighlightGradientOverride : 1;
+ bool multiHighlightColorOverride : 1;
+ bool multiHighlightGradientOverride : 1;
+
+ QAbstract3DSeriesThemeOverrideBitField()
+ : colorStyleOverride(false),
+ baseColorOverride(false),
+ baseGradientOverride(false),
+ singleHighlightColorOverride(false),
+ singleHighlightGradientOverride(false),
+ multiHighlightColorOverride(false),
+ multiHighlightGradientOverride(false)
+ {
+ }
+};
+
+class QAbstract3DSeriesPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QAbstract3DSeriesPrivate(QAbstract3DSeries *q, QAbstract3DSeries::SeriesType type);
+ virtual ~QAbstract3DSeriesPrivate();
+
+ QAbstractDataProxy *dataProxy() const;
+ virtual void setDataProxy(QAbstractDataProxy *proxy);
+ virtual void setController(Abstract3DController *controller);
+ virtual void connectControllerAndProxy(Abstract3DController *newController) = 0;
+
+ void setItemLabelFormat(const QString &format);
+ void setVisible(bool visible);
+ void setMesh(QAbstract3DSeries::Mesh mesh);
+ void setMeshSmooth(bool enable);
+ void setUserDefinedMesh(const QString &meshFile);
+
+ void setColorStyle(Q3DTheme::ColorStyle style);
+ void setBaseColor(const QColor &color);
+ void setBaseGradient(const QLinearGradient &gradient);
+ void setSingleHighlightColor(const QColor &color);
+ void setSingleHighlightGradient(const QLinearGradient &gradient);
+ void setMultiHighlightColor(const QColor &color);
+ void setMultiHighlightGradient(const QLinearGradient &gradient);
+
+ void resetToTheme(const Q3DTheme &theme, int seriesIndex, bool force);
+
+ QAbstract3DSeriesChangeBitField m_changeTracker;
+ QAbstract3DSeriesThemeOverrideBitField m_themeTracker;
+ QAbstract3DSeries *q_ptr;
+ QAbstract3DSeries::SeriesType m_type;
+ QString m_itemLabelFormat;
+ QAbstractDataProxy *m_dataProxy;
+ bool m_visible;
+ Abstract3DController *m_controller;
+ QAbstract3DSeries::Mesh m_mesh;
+ bool m_meshSmooth;
+ QString m_userDefinedMesh;
+
+ Q3DTheme::ColorStyle m_colorStyle;
+ QColor m_baseColor;
+ QLinearGradient m_baseGradient;
+ QColor m_singleHighlightColor;
+ QLinearGradient m_singleHighlightGradient;
+ QColor m_multiHighlightColor;
+ QLinearGradient m_multiHighlightGradient;
+
+};
+
+QT_DATAVISUALIZATION_END_NAMESPACE
+
+#endif // QAbstract3DSeries_P_H
diff --git a/src/datavisualization/data/qabstractdatamapping.cpp b/src/datavisualization/data/qabstractdatamapping.cpp
deleted file mode 100644
index a0698810..00000000
--- a/src/datavisualization/data/qabstractdatamapping.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use contact form at http://qt.digia.com
-**
-** This file is part of the QtDataVisualization module.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** contact form at http://qt.digia.com
-**
-****************************************************************************/
-
-#include "qabstractdatamapping_p.h"
-
-QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-
-/*!
- * \class QAbstractDataMapping
- * \inmodule QtDataVisualization
- * \brief Abstract base class for QtDataVisualization data mapping classes.
- * \since Qt Data Visualization 1.0
- *
- * Data mapping classes provide a way to map data from an external data source to one of
- * QtDataVisualization data proxies.
- * \sa QItemModelBarDataMapping, QItemModelScatterDataMapping
- */
-
-/*!
- * \internal
- */
-QAbstractDataMapping::QAbstractDataMapping(QAbstractDataMappingPrivate *d, QObject *parent)
- : QObject(parent),
- d_ptr(d)
-{
-}
-
-/*!
- * Destroys QAbstractDataMapping.
- */
-QAbstractDataMapping::~QAbstractDataMapping()
-{
-}
-
-/*!
- * \fn void QAbstractDataMapping::mappingChanged()
- *
- * Emitted when any mapping has changed.
- */
-
-// QItemModelBarDataMappingPrivate
-
-QAbstractDataMappingPrivate::QAbstractDataMappingPrivate(QAbstractDataMapping *q,
- QAbstractDataProxy::DataType type)
- : QObject(0),
- q_ptr(q),
- m_type(type)
-{
-}
-
-QAbstractDataMappingPrivate::~QAbstractDataMappingPrivate()
-{
-}
-
-QT_DATAVISUALIZATION_END_NAMESPACE
-
diff --git a/src/datavisualization/data/qabstractdataproxy.cpp b/src/datavisualization/data/qabstractdataproxy.cpp
index 4a2f4ee5..fa0934c3 100644
--- a/src/datavisualization/data/qabstractdataproxy.cpp
+++ b/src/datavisualization/data/qabstractdataproxy.cpp
@@ -18,6 +18,7 @@
#include "qabstractdataproxy.h"
#include "qabstractdataproxy_p.h"
+#include "qabstract3dseries_p.h"
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
@@ -49,14 +50,6 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*/
/*!
- * \qmlproperty string AbstractDataProxy::itemLabelFormat
- *
- * Label format for data items in this proxy. This format is used for single item labels,
- * for example, when an item is selected. How the format is interpreted depends on proxy type. See
- * each proxy class documentation for more information.
- */
-
-/*!
* \enum QAbstractDataProxy::DataType
*
* Data type of the proxy.
@@ -97,42 +90,13 @@ QAbstractDataProxy::DataType QAbstractDataProxy::type() const
return d_ptr->m_type;
}
-/*!
- * \property QAbstractDataProxy::itemLabelFormat
- *
- * Sets label \a format for data items in this proxy. This format is used for single item labels,
- * for example, when an item is selected. How the format is interpreted depends on proxy type. See
- * each proxy class documentation for more information.
- *
- * \sa QBarDataProxy, QScatterDataProxy, QSurfaceDataProxy
- */
-void QAbstractDataProxy::setItemLabelFormat(const QString &format)
-{
- d_ptr->setItemLabelFormat(format);
- emit itemLabelFormatChanged();
-}
-
-/*!
- * \return label format for data items in this proxy.
- */
-QString QAbstractDataProxy::itemLabelFormat() const
-{
- return d_ptr->m_itemLabelFormat;
-}
-
-/*!
- * \fn void QAbstractDataProxy::itemLabelFormatChanged()
- *
- * Emitted when label format changes.
- */
-
// QAbstractDataProxyPrivate
QAbstractDataProxyPrivate::QAbstractDataProxyPrivate(QAbstractDataProxy *q, QAbstractDataProxy::DataType type)
: QObject(0),
q_ptr(q),
m_type(type),
- m_isDefaultProxy(false)
+ m_series(0)
{
}
@@ -140,9 +104,10 @@ QAbstractDataProxyPrivate::~QAbstractDataProxyPrivate()
{
}
-void QAbstractDataProxyPrivate::setItemLabelFormat(const QString &format)
+void QAbstractDataProxyPrivate::setSeries(QAbstract3DSeries *series)
{
- m_itemLabelFormat = format;
+ setParent(series);
+ m_series = series;
}
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/data/qabstractdataproxy.h b/src/datavisualization/data/qabstractdataproxy.h
index db0e0863..2a053c60 100644
--- a/src/datavisualization/data/qabstractdataproxy.h
+++ b/src/datavisualization/data/qabstractdataproxy.h
@@ -31,8 +31,7 @@ class QT_DATAVISUALIZATION_EXPORT QAbstractDataProxy : public QObject
{
Q_OBJECT
Q_ENUMS(DataType)
- Q_PROPERTY(DataType type READ type)
- Q_PROPERTY(QString itemLabelFormat READ itemLabelFormat WRITE setItemLabelFormat NOTIFY itemLabelFormatChanged)
+ Q_PROPERTY(DataType type READ type CONSTANT)
public:
enum DataType {
@@ -50,22 +49,13 @@ public:
DataType type() const;
- void setItemLabelFormat(const QString &format);
- QString itemLabelFormat() const;
-
-signals:
- void itemLabelFormatChanged();
-
protected:
QScopedPointer<QAbstractDataProxyPrivate> d_ptr;
private:
Q_DISABLE_COPY(QAbstractDataProxy)
- friend class Abstract3DController;
- friend class Bars3DController;
- friend class Scatter3DController;
- friend class Surface3DController;
+ friend class QAbstract3DSeriesPrivate;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/data/qabstractdataproxy_p.h b/src/datavisualization/data/qabstractdataproxy_p.h
index 4aa1b678..90504ccb 100644
--- a/src/datavisualization/data/qabstractdataproxy_p.h
+++ b/src/datavisualization/data/qabstractdataproxy_p.h
@@ -35,6 +35,8 @@
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+class QAbstract3DSeries;
+
class QAbstractDataProxyPrivate : public QObject
{
Q_OBJECT
@@ -42,16 +44,13 @@ public:
QAbstractDataProxyPrivate(QAbstractDataProxy *q, QAbstractDataProxy::DataType type);
virtual ~QAbstractDataProxyPrivate();
- void setItemLabelFormat(const QString &format);
-
- inline bool isDefaultProxy() { return m_isDefaultProxy; }
- inline void setDefaultProxy(bool isDefault) { m_isDefaultProxy = isDefault; }
+ inline QAbstract3DSeries *series() { return m_series; }
+ virtual void setSeries(QAbstract3DSeries *series);
protected:
QAbstractDataProxy *q_ptr;
QAbstractDataProxy::DataType m_type;
- QString m_itemLabelFormat;
- bool m_isDefaultProxy;
+ QAbstract3DSeries *m_series;
private:
friend class QAbstractDataProxy;
diff --git a/src/datavisualization/data/qbar3dseries.cpp b/src/datavisualization/data/qbar3dseries.cpp
new file mode 100644
index 00000000..18e8b2ed
--- /dev/null
+++ b/src/datavisualization/data/qbar3dseries.cpp
@@ -0,0 +1,276 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#include "qbar3dseries_p.h"
+#include "bars3dcontroller_p.h"
+
+QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
+/*!
+ * \class QBar3DSeries
+ * \inmodule QtDataVisualization
+ * \brief Base series class for Q3DBars.
+ * \since Qt Data Visualization 1.0
+ *
+ * QBar3DSeries manages the series specific visual elements, as well as series data
+ * (via data proxy).
+ *
+ * If no data proxy is set explicitly for the series, the series creates a default
+ * proxy. Setting another proxy will destroy the existing proxy and all data added to it.
+ *
+ * QBar3DSeries supports the following format tags for QAbstract3DSeries::setItemLabelFormat():
+ * \table
+ * \row
+ * \li @rowTitle \li Title from row axis
+ * \row
+ * \li @colTitle \li Title from column axis
+ * \row
+ * \li @valueTitle \li Title from value axis
+ * \row
+ * \li @rowIdx \li Visible row index
+ * \row
+ * \li @colIdx \li Visible Column index
+ * \row
+ * \li @rowLabel \li Label from row axis
+ * \row
+ * \li @colLabel \li Label from column axis
+ * \row
+ * \li @valueLabel \li Item value formatted using the same format the value axis attached to the graph uses,
+ * see \l{Q3DValueAxis::setLabelFormat()} for more information.
+ * \row
+ * \li %<format spec> \li Item value in specified format.
+ * \endtable
+ *
+ * For example:
+ * \snippet doc_src_qtdatavisualization.cpp 1
+ *
+ * \sa {Qt Data Visualization Data Handling}
+ */
+
+/*!
+ * \qmltype Bar3DSeries
+ * \inqmlmodule QtDataVisualization
+ * \since QtDataVisualization 1.0
+ * \ingroup datavisualization_qml
+ * \instantiates QBar3DSeries
+ * \inherits Abstract3DSeries
+ * \brief Base series type for Bars3D.
+ *
+ * This type manages the series specific visual elements, as well as series data
+ * (via data proxy).
+ *
+ * For more complete description, see QBar3DSeries.
+ *
+ * \sa {Qt Data Visualization Data Handling}
+ */
+
+/*!
+ * \qmlproperty BarDataProxy Bar3DSeries::dataProxy
+ *
+ * This property holds the active data \a proxy. The series assumes ownership of any proxy set to
+ * it and deletes any previously set proxy when a new one is added. The \a proxy cannot be null or
+ * set to another series.
+ */
+
+/*!
+ * \qmlproperty point Bar3DSeries::selectedBar
+ *
+ * Selects a bar at the \a position. The \a position is the (row, column) position in
+ * the data array of the series.
+ * Only one bar can be selected at a time.
+ * To clear selection, set invalidSelectionPosition() as the \a position.
+ * If this series is added to a graph, the graph can adjust the selection according to user
+ * interaction or if it becomes invalid. Selecting a bar on another added series will also
+ * clear the selection.
+ */
+
+/*!
+ * \qmlmethod point Bar3DSeries::invalidSelectionPosition()
+ * \return an invalid position for selection. Set this position to selectedBar property if you
+ * want to clear the selection.
+ */
+
+/*!
+ * Constructs QBar3DSeries with the given \a parent.
+ */
+QBar3DSeries::QBar3DSeries(QObject *parent) :
+ QAbstract3DSeries(new QBar3DSeriesPrivate(this), parent)
+{
+ // Default proxy
+ dptr()->setDataProxy(new QBarDataProxy);
+}
+
+/*!
+ * Constructs QBar3DSeries with the given \a dataProxy and the \a parent.
+ */
+QBar3DSeries::QBar3DSeries(QBarDataProxy *dataProxy, QObject *parent) :
+ QAbstract3DSeries(new QBar3DSeriesPrivate(this), parent)
+{
+ dptr()->setDataProxy(dataProxy);
+}
+
+/*!
+ * \internal
+ */
+QBar3DSeries::QBar3DSeries(QBar3DSeriesPrivate *d, QObject *parent) :
+ QAbstract3DSeries(d, parent)
+{
+}
+
+/*!
+ * Destroys QBar3DSeries.
+ */
+QBar3DSeries::~QBar3DSeries()
+{
+}
+
+/*!
+ * \property QBar3DSeries::dataProxy
+ *
+ * This property holds the active data \a proxy. The series assumes ownership of any proxy set to
+ * it and deletes any previously set proxy when a new one is added. The \a proxy cannot be null or
+ * set to another series.
+ */
+void QBar3DSeries::setDataProxy(QBarDataProxy *proxy)
+{
+ d_ptr->setDataProxy(proxy);
+}
+
+QBarDataProxy *QBar3DSeries::dataProxy() const
+{
+ return static_cast<QBarDataProxy *>(d_ptr->dataProxy());
+}
+
+/*!
+ * \property QBar3DSeries::selectedBar
+ *
+ * Selects a bar at the \a position. The \a position is the (row, column) position in
+ * the data array of the series.
+ * Only one bar can be selected at a time.
+ * To clear selection, set invalidSelectionPosition() as the \a position.
+ * If this series is added to a graph, the graph can adjust the selection according to user
+ * interaction or if it becomes invalid. Selecting a bar on another added series will also
+ * clear the selection.
+ */
+void QBar3DSeries::setSelectedBar(const QPoint &position)
+{
+ // Don't do this in private to avoid loops, as that is used for callback from controller.
+ if (d_ptr->m_controller)
+ static_cast<Bars3DController *>(d_ptr->m_controller)->setSelectedBar(position, this);
+ else
+ dptr()->setSelectedBar(position);
+}
+
+QPoint QBar3DSeries::selectedBar() const
+{
+ return dptrc()->m_selectedBar;
+}
+
+/*!
+ * \return an invalid position for selection. Set this position to selectedBar property if you
+ * want to clear the selection.
+ */
+QPoint QBar3DSeries::invalidSelectionPosition() const
+{
+ return Bars3DController::invalidSelectionPosition();
+}
+
+/*!
+ * \internal
+ */
+QBar3DSeriesPrivate *QBar3DSeries::dptr()
+{
+ return static_cast<QBar3DSeriesPrivate *>(d_ptr.data());
+}
+
+/*!
+ * \internal
+ */
+const QBar3DSeriesPrivate *QBar3DSeries::dptrc() const
+{
+ return static_cast<const QBar3DSeriesPrivate *>(d_ptr.data());
+}
+
+// QBar3DSeriesPrivate
+
+QBar3DSeriesPrivate::QBar3DSeriesPrivate(QBar3DSeries *q)
+ : QAbstract3DSeriesPrivate(q, QAbstract3DSeries::SeriesTypeBar),
+ m_selectedBar(Bars3DController::invalidSelectionPosition())
+{
+ m_itemLabelFormat = QStringLiteral("@valueTitle: @valueLabel");
+ m_mesh = QAbstract3DSeries::MeshBevelBar;
+}
+
+QBar3DSeriesPrivate::~QBar3DSeriesPrivate()
+{
+}
+
+QBar3DSeries *QBar3DSeriesPrivate::qptr()
+{
+ return static_cast<QBar3DSeries *>(q_ptr);
+}
+
+void QBar3DSeriesPrivate::setDataProxy(QAbstractDataProxy *proxy)
+{
+ Q_ASSERT(proxy->type() == QAbstractDataProxy::DataTypeBar);
+
+ QAbstract3DSeriesPrivate::setDataProxy(proxy);
+
+ emit qptr()->dataProxyChanged(static_cast<QBarDataProxy *>(proxy));
+}
+
+void QBar3DSeriesPrivate::connectControllerAndProxy(Abstract3DController *newController)
+{
+ QBarDataProxy *barDataProxy = static_cast<QBarDataProxy *>(m_dataProxy);
+
+ if (m_controller && barDataProxy) {
+ // Disconnect old controller/old proxy
+ QObject::disconnect(barDataProxy, 0, m_controller, 0);
+ QObject::disconnect(q_ptr, 0, m_controller, 0);
+ }
+
+ if (newController && barDataProxy) {
+ Bars3DController *controller = static_cast<Bars3DController *>(newController);
+ QObject::connect(barDataProxy, &QBarDataProxy::arrayReset, controller,
+ &Bars3DController::handleArrayReset);
+ QObject::connect(barDataProxy, &QBarDataProxy::rowsAdded, controller,
+ &Bars3DController::handleRowsAdded);
+ QObject::connect(barDataProxy, &QBarDataProxy::rowsChanged, controller,
+ &Bars3DController::handleRowsChanged);
+ QObject::connect(barDataProxy, &QBarDataProxy::rowsRemoved, controller,
+ &Bars3DController::handleRowsRemoved);
+ QObject::connect(barDataProxy, &QBarDataProxy::rowsInserted, controller,
+ &Bars3DController::handleRowsInserted);
+ QObject::connect(barDataProxy, &QBarDataProxy::itemChanged, controller,
+ &Bars3DController::handleItemChanged);
+ QObject::connect(barDataProxy, &QBarDataProxy::rowLabelsChanged, controller,
+ &Bars3DController::handleDataRowLabelsChanged);
+ QObject::connect(barDataProxy, &QBarDataProxy::columnLabelsChanged, controller,
+ &Bars3DController::handleDataColumnLabelsChanged);
+ }
+}
+
+void QBar3DSeriesPrivate::setSelectedBar(const QPoint &position)
+{
+ if (position != m_selectedBar) {
+ m_selectedBar = position;
+ emit qptr()->selectedBarChanged(m_selectedBar);
+ }
+}
+
+QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/data/qbar3dseries.h b/src/datavisualization/data/qbar3dseries.h
new file mode 100644
index 00000000..5883cbfb
--- /dev/null
+++ b/src/datavisualization/data/qbar3dseries.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#ifndef QBAR3DSERIES_H
+#define QBAR3DSERIES_H
+
+#include <QtDataVisualization/qabstract3dseries.h>
+#include <QtDataVisualization/qbardataproxy.h>
+#include <QPoint>
+
+QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
+class QBar3DSeriesPrivate;
+
+class QT_DATAVISUALIZATION_EXPORT QBar3DSeries : public QAbstract3DSeries
+{
+ Q_OBJECT
+ Q_PROPERTY(QBarDataProxy *dataProxy READ dataProxy WRITE setDataProxy NOTIFY dataProxyChanged)
+ Q_PROPERTY(QPoint selectedBar READ selectedBar WRITE setSelectedBar NOTIFY selectedBarChanged)
+
+public:
+ explicit QBar3DSeries(QObject *parent = 0);
+ explicit QBar3DSeries(QBarDataProxy *dataProxy, QObject *parent = 0);
+ virtual ~QBar3DSeries();
+
+ void setDataProxy(QBarDataProxy *proxy);
+ QBarDataProxy *dataProxy() const;
+
+ void setSelectedBar(const QPoint &position);
+ QPoint selectedBar() const;
+ QPoint invalidSelectionPosition() const;
+
+signals:
+ void dataProxyChanged(QBarDataProxy *proxy);
+ void selectedBarChanged(QPoint position);
+
+protected:
+ explicit QBar3DSeries(QBar3DSeriesPrivate *d, QObject *parent = 0);
+ QBar3DSeriesPrivate *dptr();
+ const QBar3DSeriesPrivate *dptrc() const;
+
+private:
+ Q_DISABLE_COPY(QBar3DSeries)
+
+ friend class Bars3DController;
+};
+
+QT_DATAVISUALIZATION_END_NAMESPACE
+
+#endif
diff --git a/src/datavisualization/data/qitemmodelscatterdatamapping_p.h b/src/datavisualization/data/qbar3dseries_p.h
index 62ff42b4..89edb84a 100644
--- a/src/datavisualization/data/qitemmodelscatterdatamapping_p.h
+++ b/src/datavisualization/data/qbar3dseries_p.h
@@ -26,29 +26,33 @@
//
// We mean it.
-#ifndef QITEMMODELSCATTERDATAMAPPING_P_H
-#define QITEMMODELSCATTERDATAMAPPING_P_H
+#ifndef QBAR3DSERIES_P_H
+#define QBAR3DSERIES_P_H
-#include "qitemmodelscatterdatamapping.h"
-#include "qabstractdatamapping_p.h"
+#include "qbar3dseries.h"
+#include "qabstract3dseries_p.h"
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-class QItemModelScatterDataMappingPrivate : public QAbstractDataMappingPrivate
+class QBar3DSeriesPrivate : public QAbstract3DSeriesPrivate
{
Q_OBJECT
public:
- QItemModelScatterDataMappingPrivate(QItemModelScatterDataMapping *q);
- virtual ~QItemModelScatterDataMappingPrivate();
+ QBar3DSeriesPrivate(QBar3DSeries *q);
+ virtual ~QBar3DSeriesPrivate();
+
+ virtual void setDataProxy(QAbstractDataProxy *proxy);
+ virtual void connectControllerAndProxy(Abstract3DController *newController);
+
+ void setSelectedBar(const QPoint &position);
private:
- //QString m_labelRole;
- QString m_xPosRole;
- QString m_yPosRole;
- QString m_zPosRole;
- //QString m_valueRole;
+ QBar3DSeries *qptr();
- friend class QItemModelScatterDataMapping;
+ QPoint m_selectedBar;
+
+private:
+ friend class QBar3DSeries;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/data/qbardataitem.cpp b/src/datavisualization/data/qbardataitem.cpp
index a474d785..e564bd5d 100644
--- a/src/datavisualization/data/qbardataitem.cpp
+++ b/src/datavisualization/data/qbardataitem.cpp
@@ -37,14 +37,14 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*/
QBarDataItem::QBarDataItem()
: d_ptr(0), // private data doesn't exist by default (optimization)
- m_value(0.0)
+ m_value(0.0f)
{
}
/*!
* Constructs QBarDataItem with \a value.
*/
-QBarDataItem::QBarDataItem(qreal value)
+QBarDataItem::QBarDataItem(float value)
: d_ptr(0),
m_value(value)
{
@@ -81,12 +81,12 @@ QBarDataItem &QBarDataItem::operator=(const QBarDataItem &other)
}
/*!
- * \fn void QBarDataItem::setValue(qreal value)
+ * \fn void QBarDataItem::setValue(float value)
* Sets \a value to this data item.
*/
/*!
- * \fn qreal QBarDataItem::value() const
+ * \fn float QBarDataItem::value() const
* \return value of this data item.
*/
diff --git a/src/datavisualization/data/qbardataitem.h b/src/datavisualization/data/qbardataitem.h
index 68bbcedf..60a4a19f 100644
--- a/src/datavisualization/data/qbardataitem.h
+++ b/src/datavisualization/data/qbardataitem.h
@@ -29,16 +29,14 @@ class QT_DATAVISUALIZATION_EXPORT QBarDataItem
{
public:
QBarDataItem();
- QBarDataItem(qreal value);
+ QBarDataItem(float value);
QBarDataItem(const QBarDataItem &other);
~QBarDataItem();
QBarDataItem &operator=(const QBarDataItem &other);
- void setValue(qreal value) { m_value = value; }
- qreal value() const { return m_value; }
-
- // TODO Set color, label format, ...?
+ void setValue(float value) { m_value = value; }
+ float value() const { return m_value; }
protected:
virtual void createExtraData();
@@ -46,7 +44,7 @@ protected:
QBarDataItemPrivate *d_ptr;
private:
- qreal m_value;
+ float m_value;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/data/qbardataproxy.cpp b/src/datavisualization/data/qbardataproxy.cpp
index 13517b4b..80768059 100644
--- a/src/datavisualization/data/qbardataproxy.cpp
+++ b/src/datavisualization/data/qbardataproxy.cpp
@@ -18,6 +18,7 @@
#include "qbardataproxy.h"
#include "qbardataproxy_p.h"
+#include "qbar3dseries_p.h"
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
@@ -43,32 +44,6 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
* This enables the option of having row labels that relate to the position of the data in the
* array rather than the data itself.
*
- * QBarDataProxy supports the following format tags for QAbstractDataProxy::setItemLabelFormat():
- * \table
- * \row
- * \li @rowTitle \li Title from row axis
- * \row
- * \li @colTitle \li Title from column axis
- * \row
- * \li @valueTitle \li Title from value axis
- * \row
- * \li @rowIdx \li Visible row index
- * \row
- * \li @colIdx \li Visible Column index
- * \row
- * \li @rowLabel \li Label from row axis
- * \row
- * \li @colLabel \li Label from column axis
- * \row
- * \li @valueLabel \li Item value formatted using the same format the value axis attached to the graph uses,
- * see \l{Q3DValueAxis::setLabelFormat()} for more information.
- * \row
- * \li %<format spec> \li Item value in specified format.
- * \endtable
- *
- * For example:
- * \snippet doc_src_qtdatavisualization.cpp 1
- *
* \sa {Qt Data Visualization Data Handling}
*/
@@ -110,6 +85,12 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*/
/*!
+ * \qmlproperty Bar3DSeries BarDataProxy::series
+ *
+ * The series this proxy is attached to.
+ */
+
+/*!
* Constructs QBarDataProxy with the given \a parent.
*/
QBarDataProxy::QBarDataProxy(QObject *parent) :
@@ -133,11 +114,22 @@ QBarDataProxy::~QBarDataProxy()
}
/*!
+ * \property QBarDataProxy::series
+ *
+ * The series this proxy is attached to.
+ */
+QBar3DSeries *QBarDataProxy::series()
+{
+ return static_cast<QBar3DSeries *>(d_ptr->series());
+}
+
+/*!
* Clears the existing array and row and column labels.
*/
void QBarDataProxy::resetArray()
{
resetArray(0, QStringList(), QStringList());
+ emit rowCountChanged(rowCount());
}
/*!
@@ -151,6 +143,7 @@ void QBarDataProxy::resetArray(QBarDataArray *newArray)
{
dptr()->resetArray(newArray, 0, 0);
emit arrayReset();
+ emit rowCountChanged(rowCount());
}
/*!
@@ -165,10 +158,11 @@ void QBarDataProxy::resetArray(QBarDataArray *newArray, const QStringList &rowLa
{
dptr()->resetArray(newArray, &rowLabels, &columnLabels);
emit arrayReset();
+ emit rowCountChanged(rowCount());
}
/*!
- * Changes existing rows by replacing a row at \a rowIndex with \a row. The \a row can be
+ * Changes existing rows by replacing a row at \a rowIndex with a new \a row. The \a row can be
* the same as the existing row already stored at the \a rowIndex.
* Existing row labels are not affected.
*/
@@ -230,6 +224,7 @@ int QBarDataProxy::addRow(QBarDataRow *row)
{
int addIndex = dptr()->addRow(row, 0);
emit rowsAdded(addIndex, 1);
+ emit rowCountChanged(rowCount());
return addIndex;
}
@@ -242,6 +237,7 @@ int QBarDataProxy::addRow(QBarDataRow *row, const QString &label)
{
int addIndex = dptr()->addRow(row, &label);
emit rowsAdded(addIndex, 1);
+ emit rowCountChanged(rowCount());
return addIndex;
}
@@ -255,6 +251,7 @@ int QBarDataProxy::addRows(const QBarDataArray &rows)
{
int addIndex = dptr()->addRows(rows, 0);
emit rowsAdded(addIndex, rows.size());
+ emit rowCountChanged(rowCount());
return addIndex;
}
@@ -267,6 +264,7 @@ int QBarDataProxy::addRows(const QBarDataArray &rows, const QStringList &labels)
{
int addIndex = dptr()->addRows(rows, &labels);
emit rowsAdded(addIndex, rows.size());
+ emit rowCountChanged(rowCount());
return addIndex;
}
@@ -281,6 +279,7 @@ void QBarDataProxy::insertRow(int rowIndex, QBarDataRow *row)
{
dptr()->insertRow(rowIndex, row, 0);
emit rowsInserted(rowIndex, 1);
+ emit rowCountChanged(rowCount());
}
/*!
@@ -291,6 +290,7 @@ void QBarDataProxy::insertRow(int rowIndex, QBarDataRow *row, const QString &lab
{
dptr()->insertRow(rowIndex, row, &label);
emit rowsInserted(rowIndex, 1);
+ emit rowCountChanged(rowCount());
}
/*!
@@ -304,6 +304,7 @@ void QBarDataProxy::insertRows(int rowIndex, const QBarDataArray &rows)
{
dptr()->insertRows(rowIndex, rows, 0);
emit rowsInserted(rowIndex, rows.size());
+ emit rowCountChanged(rowCount());
}
/*!
@@ -314,6 +315,7 @@ void QBarDataProxy::insertRows(int rowIndex, const QBarDataArray &rows, const QS
{
dptr()->insertRows(rowIndex, rows, &labels);
emit rowsInserted(rowIndex, rows.size());
+ emit rowCountChanged(rowCount());
}
/*!
@@ -328,6 +330,7 @@ void QBarDataProxy::removeRows(int rowIndex, int removeCount, bool removeLabels)
if (rowIndex < rowCount() && removeCount >= 1) {
dptr()->removeRows(rowIndex, removeCount, removeLabels);
emit rowsRemoved(rowIndex, removeCount);
+ emit rowCountChanged(rowCount());
}
}
@@ -482,7 +485,6 @@ QBarDataProxyPrivate::QBarDataProxyPrivate(QBarDataProxy *q)
: QAbstractDataProxyPrivate(q, QAbstractDataProxy::DataTypeBar),
m_dataArray(new QBarDataArray)
{
- m_itemLabelFormat = QStringLiteral("@valueTitle: @valueLabel");
}
QBarDataProxyPrivate::~QBarDataProxyPrivate()
@@ -693,7 +695,7 @@ QPair<GLfloat, GLfloat> QBarDataProxyPrivate::limitValues(int startRow, int endR
endColumn = qMin(endColumn, row->size() - 1);
for (int j = startColumn; j <= endColumn; j++) {
const QBarDataItem &item = m_dataArray->at(i)->at(j);
- qreal itemValue = item.value();
+ float itemValue = item.value();
if (limits.second < itemValue)
limits.second = itemValue;
if (limits.first > itemValue)
@@ -704,4 +706,11 @@ QPair<GLfloat, GLfloat> QBarDataProxyPrivate::limitValues(int startRow, int endR
return limits;
}
+void QBarDataProxyPrivate::setSeries(QAbstract3DSeries *series)
+{
+ QAbstractDataProxyPrivate::setSeries(series);
+ QBar3DSeries *barSeries = static_cast<QBar3DSeries *>(series);
+ emit qptr()->seriesChanged(barSeries);
+}
+
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/data/qbardataproxy.h b/src/datavisualization/data/qbardataproxy.h
index 758700df..94e15116 100644
--- a/src/datavisualization/data/qbardataproxy.h
+++ b/src/datavisualization/data/qbardataproxy.h
@@ -30,27 +30,21 @@ typedef QVector<QBarDataItem> QBarDataRow;
typedef QList<QBarDataRow *> QBarDataArray;
class QBarDataProxyPrivate;
+class QBar3DSeries;
class QT_DATAVISUALIZATION_EXPORT QBarDataProxy : public QAbstractDataProxy
{
Q_OBJECT
- Q_PROPERTY(int rowCount READ rowCount)
+ Q_PROPERTY(int rowCount READ rowCount NOTIFY rowCountChanged)
Q_PROPERTY(QStringList rowLabels READ rowLabels WRITE setRowLabels NOTIFY rowLabelsChanged)
Q_PROPERTY(QStringList columnLabels READ columnLabels WRITE setColumnLabels NOTIFY columnLabelsChanged)
+ Q_PROPERTY(QBar3DSeries *series READ series NOTIFY seriesChanged)
public:
explicit QBarDataProxy(QObject *parent = 0);
virtual ~QBarDataProxy();
- // TODO: Replace first part of class description in docs with this once all TODOs are done:
- /*
- * QBarDataProxy is optimized for adding, inserting, and removing rows of data.
- * Adding a column essentially means modifying every row, which is comparatively very inefficient.
- * Proxy is also optimized to use cases where the only defining characteristic of an individual
- * bar is its value. Modifying other data that might be added in the future such as color of
- * individual bar requires allocating additional data object for the bar.
- */
-
+ QBar3DSeries *series();
int rowCount() const;
QStringList rowLabels() const;
@@ -72,31 +66,19 @@ public:
void setRows(int rowIndex, const QBarDataArray &rows);
void setRows(int rowIndex, const QBarDataArray &rows, const QStringList &labels);
- // Setting a column is comparatively inefficient as it changes all rows.
- // Can resize rows that are shorter than columnIndex.
- // TODO void setColumn(int columnIndex, const QBarDataRow &column);
- // TODO void setColumns(int columnIndex, const QBarDataArray &columns);
-
void setItem(int rowIndex, int columnIndex, const QBarDataItem &item);
- // Change block of items
- // TODO setItems(int rowIndex, int columnIndex, QBarDataArray *items);
int addRow(QBarDataRow *row);
int addRow(QBarDataRow *row, const QString &label);
int addRows(const QBarDataArray &rows);
int addRows(const QBarDataArray &rows, const QStringList &labels);
- // TODO int addColumn(const QBarDataRow &column); // returns the index of the added column
- // TODO int addColumns(const QBarDataArray &columns); // returns the index of the first added column
void insertRow(int rowIndex, QBarDataRow *row);
void insertRow(int rowIndex, QBarDataRow *row, const QString &label);
void insertRows(int rowIndex, const QBarDataArray &rows);
void insertRows(int rowIndex, const QBarDataArray &rows, const QStringList &labels);
- // TODO void insertColumn(int columnIndex, const QBarDataRow &column);
- // TODO void insertColumns(int columnIndex, const QBarDataArray &columns);
void removeRows(int rowIndex, int removeCount, bool removeLabels = true);
- // TODO void removeColumns(int columnIndex, int removeCount);
signals:
void arrayReset();
@@ -104,15 +86,12 @@ signals:
void rowsChanged(int startIndex, int count);
void rowsRemoved(int startIndex, int count);
void rowsInserted(int startIndex, int count);
- // TODO void columnsChanged(int startIndex, int count);
- // TODO void columnsAdded(int startIndex, int count);
- // TODO void columnsRemoved(int startIndex, int count);
- // TODO void columnsInserted(int startIndex, int count);
- void itemChanged(int rowIndex, int columnIndex); // TODO remove once itemsChanged is added?
- // TODO void itemsChanged(int rowIndex, int columnIndex, int rowCount, int columnCount);
+ void itemChanged(int rowIndex, int columnIndex);
+ void rowCountChanged(int count);
void rowLabelsChanged();
void columnLabelsChanged();
+ void seriesChanged(QBar3DSeries *series);
protected:
explicit QBarDataProxy(QBarDataProxyPrivate *d, QObject *parent = 0);
diff --git a/src/datavisualization/data/qbardataproxy_p.h b/src/datavisualization/data/qbardataproxy_p.h
index 4d51bd5b..84726a02 100644
--- a/src/datavisualization/data/qbardataproxy_p.h
+++ b/src/datavisualization/data/qbardataproxy_p.h
@@ -56,6 +56,8 @@ public:
QPair<GLfloat, GLfloat> limitValues(int startRow, int startColumn, int rowCount,
int columnCount) const;
+ virtual void setSeries(QAbstract3DSeries *series);
+
private:
QBarDataProxy *qptr();
void clearRow(int rowIndex);
diff --git a/src/datavisualization/data/qheightmapsurfacedataproxy.cpp b/src/datavisualization/data/qheightmapsurfacedataproxy.cpp
index 251ae70a..ce379592 100644
--- a/src/datavisualization/data/qheightmapsurfacedataproxy.cpp
+++ b/src/datavisualization/data/qheightmapsurfacedataproxy.cpp
@@ -59,11 +59,12 @@ const float defaultMaxValue = 10.0f;
*/
/*!
- * \qmlproperty image HeightMapSurfaceDataProxy::heightMap
+ * \qmlproperty string HeightMapSurfaceDataProxy::heightMapFile
*
- * A height map to be visualized. Setting this property replaces current data with height map data.
+ * A file with a height map image to be visualized. Setting this property replaces current data
+ * with height map data.
*
- * There are several formats the image can be given in, but if it is not in a directly usable
+ * There are several formats the image file can be given in, but if it is not in a directly usable
* format, a conversion is made. \note If the result seems wrong, the automatic conversion failed
* and you should try converting the image yourself before setting it. Preferred format is
* QImage::Format_RGB32 in grayscale.
@@ -81,16 +82,7 @@ const float defaultMaxValue = 10.0f;
*/
/*!
- * \qmlproperty string HeightMapSurfaceDataProxy::heightMapFile
- *
- * A file with a height map image to be visualized. Setting this property replaces current data
- * with height map data.
- *
- * \sa heightMap
- */
-
-/*!
- * \qmlproperty qreal HeightMapSurfaceDataProxy::minXValue
+ * \qmlproperty real HeightMapSurfaceDataProxy::minXValue
*
* The minimum X value for the generated surface points.
* When setting this property the corresponding maximum value is adjusted if necessary,
@@ -98,7 +90,7 @@ const float defaultMaxValue = 10.0f;
*/
/*!
- * \qmlproperty qreal HeightMapSurfaceDataProxy::maxXValue
+ * \qmlproperty real HeightMapSurfaceDataProxy::maxXValue
*
* The maximum X value for the generated surface points.
* When setting this property the corresponding minimum value is adjusted if necessary,
@@ -106,7 +98,7 @@ const float defaultMaxValue = 10.0f;
*/
/*!
- * \qmlproperty qreal HeightMapSurfaceDataProxy::minZValue
+ * \qmlproperty real HeightMapSurfaceDataProxy::minZValue
*
* The minimum Z value for the generated surface points.
* When setting this property the corresponding maximum value is adjusted if necessary,
@@ -114,7 +106,7 @@ const float defaultMaxValue = 10.0f;
*/
/*!
- * \qmlproperty qreal HeightMapSurfaceDataProxy::maxZValue
+ * \qmlproperty real HeightMapSurfaceDataProxy::maxZValue
*
* The maximum Z value for the generated surface points.
* When setting this property the corresponding minimum value is adjusted if necessary,
@@ -202,6 +194,7 @@ void QHeightMapSurfaceDataProxy::setHeightMapFile(const QString &filename)
{
dptr()->m_heightMapFile = filename;
setHeightMap(QImage(filename));
+ emit heightMapFileChanged(filename);
}
QString QHeightMapSurfaceDataProxy::heightMapFile() const
@@ -330,50 +323,70 @@ QHeightMapSurfaceDataProxy *QHeightMapSurfaceDataProxyPrivate::qptr()
void QHeightMapSurfaceDataProxyPrivate::setValueRanges(float minX, float maxX, float minZ, float maxZ)
{
- bool changed = false;
- if (m_minXValue != minX || m_minZValue != minZ) {
+ bool minXChanged = false;
+ bool maxXChanged = false;
+ bool minZChanged = false;
+ bool maxZChanged = false;
+ if (m_minXValue != minX) {
m_minXValue = minX;
+ minXChanged = true;
+ }
+ if (m_minZValue != minZ) {
m_minZValue = minZ;
- changed = true;
+ minZChanged = true;
}
if (m_maxXValue != maxX || minX >= maxX) {
if (minX >= maxX) {
- m_maxXValue = minX + 1.0;
+ m_maxXValue = minX + 1.0f;
qWarning() << "Warning: Tried to set invalid range for X value range."
" Range automatically adjusted to a valid one:"
<< minX << "-" << maxX << "-->" << m_minXValue << "-" << m_maxXValue;
} else {
m_maxXValue = maxX;
}
- changed = true;
+ maxXChanged = true;
}
if (m_maxZValue != maxZ || minZ >= maxZ) {
if (minZ >= maxZ) {
- m_maxZValue = minZ + 1.0;
+ m_maxZValue = minZ + 1.0f;
qWarning() << "Warning: Tried to set invalid range for Z value range."
" Range automatically adjusted to a valid one:"
<< minZ << "-" << maxZ << "-->" << m_minZValue << "-" << m_maxZValue;
} else {
m_maxZValue = maxZ;
}
- changed = true;
+ maxZChanged = true;
}
- if (changed && !m_resolveTimer.isActive())
+ if (minXChanged)
+ emit qptr()->minXValueChanged(m_minXValue);
+ if (minZChanged)
+ emit qptr()->minZValueChanged(m_minZValue);
+ if (maxXChanged)
+ emit qptr()->maxXValueChanged(m_maxXValue);
+ if (maxZChanged)
+ emit qptr()->maxZValueChanged(m_maxZValue);
+
+ if ((minXChanged || minZChanged || maxXChanged || maxZChanged) && !m_resolveTimer.isActive())
m_resolveTimer.start(0);
}
void QHeightMapSurfaceDataProxyPrivate::setMinXValue(float min)
{
if (min != m_minXValue) {
+ bool maxChanged = false;
if (min >= m_maxXValue) {
- qreal oldMax = m_maxXValue;
- m_maxXValue = min + 1.0;
+ float oldMax = m_maxXValue;
+ m_maxXValue = min + 1.0f;
qWarning() << "Warning: Tried to set minimum X to equal or larger than maximum X for"
" value range. Maximum automatically adjusted to a valid one:"
<< oldMax << "-->" << m_maxXValue;
+ maxChanged = true;
}
m_minXValue = min;
+ emit qptr()->minXValueChanged(m_minXValue);
+ if (maxChanged)
+ emit qptr()->maxXValueChanged(m_maxXValue);
if (!m_resolveTimer.isActive())
m_resolveTimer.start(0);
@@ -383,14 +396,19 @@ void QHeightMapSurfaceDataProxyPrivate::setMinXValue(float min)
void QHeightMapSurfaceDataProxyPrivate::setMaxXValue(float max)
{
if (m_maxXValue != max) {
+ bool minChanged = false;
if (max <= m_minXValue) {
- qreal oldMin = m_minXValue;
- m_minXValue = max - 1.0;
+ float oldMin = m_minXValue;
+ m_minXValue = max - 1.0f;
qWarning() << "Warning: Tried to set maximum X to equal or smaller than minimum X for"
" value range. Minimum automatically adjusted to a valid one:"
<< oldMin << "-->" << m_minXValue;
+ minChanged = true;
}
m_maxXValue = max;
+ emit qptr()->maxXValueChanged(m_maxXValue);
+ if (minChanged)
+ emit qptr()->minXValueChanged(m_minXValue);
if (!m_resolveTimer.isActive())
m_resolveTimer.start(0);
@@ -400,14 +418,19 @@ void QHeightMapSurfaceDataProxyPrivate::setMaxXValue(float max)
void QHeightMapSurfaceDataProxyPrivate::setMinZValue(float min)
{
if (min != m_minZValue) {
+ bool maxChanged = false;
if (min >= m_maxZValue) {
- qreal oldMax = m_maxZValue;
- m_maxZValue = min + 1.0;
+ float oldMax = m_maxZValue;
+ m_maxZValue = min + 1.0f;
qWarning() << "Warning: Tried to set minimum Z to equal or larger than maximum Z for"
" value range. Maximum automatically adjusted to a valid one:"
<< oldMax << "-->" << m_maxZValue;
+ maxChanged = true;
}
m_minZValue = min;
+ emit qptr()->minZValueChanged(m_minZValue);
+ if (maxChanged)
+ emit qptr()->maxZValueChanged(m_maxZValue);
if (!m_resolveTimer.isActive())
m_resolveTimer.start(0);
@@ -417,14 +440,19 @@ void QHeightMapSurfaceDataProxyPrivate::setMinZValue(float min)
void QHeightMapSurfaceDataProxyPrivate::setMaxZValue(float max)
{
if (m_maxZValue != max) {
+ bool minChanged = false;
if (max <= m_minZValue) {
- qreal oldMin = m_minZValue;
- m_minZValue = max - 1.0;
+ float oldMin = m_minZValue;
+ m_minZValue = max - 1.0f;
qWarning() << "Warning: Tried to set maximum Z to equal or smaller than minimum Z for"
" value range. Minimum automatically adjusted to a valid one:"
<< oldMin << "-->" << m_minZValue;
+ minChanged = true;
}
m_maxZValue = max;
+ emit qptr()->maxZValueChanged(m_maxZValue);
+ if (minChanged)
+ emit qptr()->minZValueChanged(m_minZValue);
if (!m_resolveTimer.isActive())
m_resolveTimer.start(0);
@@ -434,6 +462,7 @@ void QHeightMapSurfaceDataProxyPrivate::setMaxZValue(float max)
void QHeightMapSurfaceDataProxyPrivate::handlePendingResolve()
{
QImage heightImage = m_heightMap;
+
// Convert to RGB32 to be sure we're reading the right bytes
if (heightImage.format() != QImage::Format_RGB32)
heightImage = heightImage.convertToFormat(QImage::Format_RGB32);
@@ -460,30 +489,63 @@ void QHeightMapSurfaceDataProxyPrivate::handlePendingResolve()
float xMul = (m_maxXValue - m_minXValue) / float(imageWidth - 1);
float zMul = (m_maxZValue - m_minZValue) / float(imageHeight - 1);
+ // Last row and column are explicitly set to max values, as relying
+ // on multiplier can cause rounding errors, resulting in the value being
+ // slightly over the specified maximum, which in turn can lead to it not
+ // getting rendered.
+ int lastRow = imageHeight - 1;
+ int lastCol = imageWidth - 1;
+
if (heightImage.isGrayscale()) {
// Grayscale, it's enough to read Red byte
for (int i = 0; i < imageHeight; i++, bitCount -= widthBits) {
QSurfaceDataRow &newRow = *dataArray->at(i);
- for (int j = 0; j < imageWidth; j++)
- newRow[j].setPosition(QVector3D((float(j) * xMul) + m_minXValue, float(bits[bitCount + (j * 4)]),
- (float(i) * zMul) + m_minZValue));
+ float zVal;
+ if (i == lastRow)
+ zVal = m_maxZValue;
+ else
+ zVal = (float(i) * zMul) + m_minZValue;
+ int j = 0;
+ for (; j < lastCol; j++)
+ newRow[j].setPosition(QVector3D((float(j) * xMul) + m_minXValue,
+ float(bits[bitCount + (j * 4)]),
+ zVal));
+ newRow[j].setPosition(QVector3D(m_maxXValue,
+ float(bits[bitCount + (j * 4)]),
+ zVal));
}
} else {
// Not grayscale, we'll need to calculate height from RGB
for (int i = 0; i < imageHeight; i++, bitCount -= widthBits) {
QSurfaceDataRow &newRow = *dataArray->at(i);
- for (int j = 0; j < imageWidth; j++) {
- int nextpixel = j * 4;
+ float zVal;
+ if (i == lastRow)
+ zVal = m_maxZValue;
+ else
+ zVal = (float(i) * zMul) + m_minZValue;
+ int j = 0;
+ int nextpixel = 0;
+ for (; j < lastCol; j++) {
+ nextpixel = j * 4;
height = (float(bits[bitCount + nextpixel])
+ float(bits[1 + bitCount + nextpixel])
+ float(bits[2 + bitCount + nextpixel]));
- newRow[j].setPosition(QVector3D((float(j) * xMul) + m_minXValue, height / 3.0f,
- (float(i) * zMul) + m_minZValue));
+ newRow[j].setPosition(QVector3D((float(j) * xMul) + m_minXValue,
+ height / 3.0f,
+ zVal));
}
+ nextpixel = j * 4;
+ height = (float(bits[bitCount + nextpixel])
+ + float(bits[1 + bitCount + nextpixel])
+ + float(bits[2 + bitCount + nextpixel]));
+ newRow[j].setPosition(QVector3D(m_maxXValue,
+ height / 3.0f,
+ zVal));
}
}
qptr()->resetArray(dataArray);
+ emit qptr()->heightMapChanged(m_heightMap);
}
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/data/qheightmapsurfacedataproxy.h b/src/datavisualization/data/qheightmapsurfacedataproxy.h
index 3306059f..16132b0d 100644
--- a/src/datavisualization/data/qheightmapsurfacedataproxy.h
+++ b/src/datavisualization/data/qheightmapsurfacedataproxy.h
@@ -31,12 +31,12 @@ class QT_DATAVISUALIZATION_EXPORT QHeightMapSurfaceDataProxy : public QSurfaceDa
{
Q_OBJECT
- Q_PROPERTY(QImage heightMap READ heightMap WRITE setHeightMap)
- Q_PROPERTY(QString heightMapFile READ heightMapFile WRITE setHeightMapFile)
- Q_PROPERTY(float minXValue READ minXValue WRITE setMinXValue)
- Q_PROPERTY(float maxXValue READ maxXValue WRITE setMaxXValue)
- Q_PROPERTY(float minZValue READ minZValue WRITE setMinZValue)
- Q_PROPERTY(float maxZValue READ maxZValue WRITE setMaxZValue)
+ Q_PROPERTY(QImage heightMap READ heightMap WRITE setHeightMap NOTIFY heightMapChanged)
+ Q_PROPERTY(QString heightMapFile READ heightMapFile WRITE setHeightMapFile NOTIFY heightMapFileChanged)
+ Q_PROPERTY(float minXValue READ minXValue WRITE setMinXValue NOTIFY minXValueChanged)
+ Q_PROPERTY(float maxXValue READ maxXValue WRITE setMaxXValue NOTIFY maxXValueChanged)
+ Q_PROPERTY(float minZValue READ minZValue WRITE setMinZValue NOTIFY minZValueChanged)
+ Q_PROPERTY(float maxZValue READ maxZValue WRITE setMaxZValue NOTIFY maxZValueChanged)
public:
explicit QHeightMapSurfaceDataProxy(QObject *parent = 0);
@@ -45,7 +45,6 @@ public:
void setHeightMap(const QImage &image);
QImage heightMap() const;
-
void setHeightMapFile(const QString &filename);
QString heightMapFile() const;
@@ -59,6 +58,14 @@ public:
void setMaxZValue(float max);
float maxZValue() const;
+signals:
+ void heightMapChanged(QImage image);
+ void heightMapFileChanged(QString filename);
+ void minXValueChanged(float value);
+ void maxXValueChanged(float value);
+ void minZValueChanged(float value);
+ void maxZValueChanged(float value);
+
protected:
explicit QHeightMapSurfaceDataProxy(QHeightMapSurfaceDataProxyPrivate *d, QObject *parent = 0);
QHeightMapSurfaceDataProxyPrivate *dptr();
diff --git a/src/datavisualization/data/qitemmodelbardatamapping.cpp b/src/datavisualization/data/qitemmodelbardatamapping.cpp
deleted file mode 100644
index 0e92680f..00000000
--- a/src/datavisualization/data/qitemmodelbardatamapping.cpp
+++ /dev/null
@@ -1,407 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use contact form at http://qt.digia.com
-**
-** This file is part of the QtDataVisualization module.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** contact form at http://qt.digia.com
-**
-****************************************************************************/
-
-#include "qitemmodelbardatamapping_p.h"
-
-QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-
-/*!
- * \class QItemModelBarDataMapping
- * \inmodule QtDataVisualization
- * \brief Item model mapping for Q3DBars.
- * \since Qt Data Visualization 1.0
- *
- * QItemModelBarDataMapping is used to map roles of QAbstractItemModel to rows, columns, and values
- * of Q3DBars. There are three ways to use QItemModelBarDataMapping:
- *
- * 1) If useModelCategories property is set to true, QItemModelBarDataMapping will map rows and
- * columns of QAbstractItemModel to rows and columns of Q3DBars, and uses the value returned for
- * Qt::DisplayRole as bar value by default.
- * The value role to be used can be redefined if Qt::DisplayRole is not suitable.
- *
- * 2) For models that do not have data already neatly sorted into rows and columns, such as
- * QAbstractListModel based models, you can define a role from the model to map for each of row,
- * column and value.
- *
- * 3) If you do not want to include all data contained in the model, or the autogenerated rows and
- * columns are not ordered as you wish, you can specify which rows and columns should be included
- * and in which order by defining an explicit list of categories for either or both of rows and
- * columns.
- *
- * For example, assume that you have a custom QAbstractItemModel for storing various monthly values
- * related to a business.
- * Each item in the model has the roles "year", "month", "income", and "expenses".
- * You could do the following to display the data in a bar graph:
- *
- * \snippet doc_src_qtdatavisualization.cpp 3
- *
- * \sa QItemModelBarDataProxy, {Qt Data Visualization Data Handling}
- */
-
-/*!
- * \qmltype BarDataMapping
- * \inqmlmodule QtDataVisualization
- * \since QtDataVisualization 1.0
- * \ingroup datavisualization_qml
- * \instantiates QItemModelBarDataMapping
- * \brief Item model mapping for Bars3D.
- *
- * This type is used to map roles of AbstractItemModel to rows, columns, and values of Bars3D. For
- * a more complete description, see QItemModelBarDataMapping.
- *
- * Usage example:
- *
- * \snippet doc_src_qmldatavisualization.cpp 4
- *
- * \sa ItemModelBarDataProxy, {Qt Data Visualization Data Handling}
- */
-
-/*!
- * \qmlproperty string BarDataMapping::rowRole
- * The row role of the mapping.
- */
-
-/*!
- * \qmlproperty string BarDataMapping::columnRole
- * The column role of the mapping.
- */
-
-/*!
- * \qmlproperty string BarDataMapping::valueRole
- * The value role of the mapping.
- */
-
-/*!
- * \qmlproperty list BarDataMapping::rowCategories
- * The row categories of the mapping. Only items with row roles that are found in this list are
- * included when the data is resolved. The rows are ordered in the same order as they are in this list.
- */
-
-/*!
- * \qmlproperty list BarDataMapping::columnCategories
- * The column categories of the mapping. Only items with column roles that are found in this list are
- * included when the data is resolved. The columns are ordered in the same order as they are in this list.
- */
-
-/*!
- * \qmlproperty list BarDataMapping::useModelCategories
- * When set to true, the mapping ignores row and column roles and categories, and uses
- * the rows and columns from the model instead. Defaults to false.
- */
-
-/*!
- * \qmlproperty list BarDataMapping::autoRowCategories
- * When set to true, the mapping ignores any explicitly set row categories
- * and overwrites them with automatically generated ones whenever the
- * data from the model is resolved. Defaults to true.
- */
-
-/*!
- * \qmlproperty list BarDataMapping::autoColumnCategories
- * When set to true, the mapping ignores any explicitly set column categories
- * and overwrites them with automatically generated ones whenever the
- * data from model is resolved. Defaults to true.
- */
-
-/*!
- * Constructs QItemModelBarDataMapping with the given \a parent.
- */
-QItemModelBarDataMapping::QItemModelBarDataMapping(QObject *parent)
- : QAbstractDataMapping(new QItemModelBarDataMappingPrivate(this), parent)
-{
-}
-
-/*!
- * Constructs QItemModelBarDataMapping with \a valueRole and the given \a parent.
- * This constructor is meant to be used with models that have data properly sorted
- * in rows and columns already, so it also sets useModelCategories property to true.
- */
-QItemModelBarDataMapping::QItemModelBarDataMapping(const QString &valueRole, QObject *parent)
- : QAbstractDataMapping(new QItemModelBarDataMappingPrivate(this), parent)
-{
- dptr()->m_valueRole = valueRole;
- dptr()->m_useModelCategories = true;
-}
-
-/*!
- * Constructs QItemModelBarDataMapping with \a rowRole, \a columnRole, \a valueRole
- * and the given \a parent.
- */
-QItemModelBarDataMapping::QItemModelBarDataMapping(const QString &rowRole,
- const QString &columnRole,
- const QString &valueRole,
- QObject *parent)
- : QAbstractDataMapping(new QItemModelBarDataMappingPrivate(this), parent)
-{
- dptr()->m_rowRole = rowRole;
- dptr()->m_columnRole = columnRole;
- dptr()->m_valueRole = valueRole;
-}
-
-/*!
- * Constructs QItemModelBarDataMapping with \a rowRole, \a columnRole, \a valueRole,
- * \a rowCategories, \a columnCategories and the given \a parent. This constructor
- * also sets autoRowCategories and autoColumnCategories to false.
- */
-QItemModelBarDataMapping::QItemModelBarDataMapping(const QString &rowRole,
- const QString &columnRole,
- const QString &valueRole,
- const QStringList &rowCategories,
- const QStringList &columnCategories,
- QObject *parent)
- : QAbstractDataMapping(new QItemModelBarDataMappingPrivate(this), parent)
-{
- dptr()->m_rowRole = rowRole;
- dptr()->m_columnRole = columnRole;
- dptr()->m_valueRole = valueRole;
- dptr()->m_rowCategories = rowCategories;
- dptr()->m_columnCategories = columnCategories;
- dptr()->m_autoRowCategories = false;
- dptr()->m_autoColumnCategories = false;
-}
-
-/*!
- * Destroys QItemModelBarDataMapping.
- */
-QItemModelBarDataMapping::~QItemModelBarDataMapping()
-{
-}
-
-/*!
- * \property QItemModelBarDataMapping::rowRole
- *
- * Defines the row role for the mapping.
- */
-void QItemModelBarDataMapping::setRowRole(const QString &role)
-{
- if (dptr()->m_rowRole != role) {
- dptr()->m_rowRole = role;
- emit mappingChanged();
- }
-}
-
-QString QItemModelBarDataMapping::rowRole() const
-{
- return dptrc()->m_rowRole;
-}
-
-/*!
- * \property QItemModelBarDataMapping::columnRole
- *
- * Defines the column role for the mapping.
- */
-void QItemModelBarDataMapping::setColumnRole(const QString &role)
-{
- if (dptr()->m_columnRole != role) {
- dptr()->m_columnRole = role;
- emit mappingChanged();
- }
-}
-
-QString QItemModelBarDataMapping::columnRole() const
-{
- return dptrc()->m_columnRole;
-}
-
-/*!
- * \property QItemModelBarDataMapping::valueRole
- *
- * Defines the value role for the mapping.
- */
-void QItemModelBarDataMapping::setValueRole(const QString &role)
-{
- if (dptr()->m_valueRole != role) {
- dptr()->m_valueRole = role;
- emit mappingChanged();
- }
-}
-
-QString QItemModelBarDataMapping::valueRole() const
-{
- return dptrc()->m_valueRole;
-}
-
-/*!
- * \property QItemModelBarDataMapping::rowCategories
- *
- * Defines the row categories for the mapping.
- */
-void QItemModelBarDataMapping::setRowCategories(const QStringList &categories)
-{
- if (dptr()->m_rowCategories != categories) {
- dptr()->m_rowCategories = categories;
- emit mappingChanged();
- }
-}
-
-QStringList QItemModelBarDataMapping::rowCategories() const
-{
- return dptrc()->m_rowCategories;
-}
-
-/*!
- * \property QItemModelBarDataMapping::columnCategories
- *
- * Defines the column categories for the mapping.
- */
-void QItemModelBarDataMapping::setColumnCategories(const QStringList &categories)
-{
- if (dptr()->m_columnCategories != categories) {
- dptr()->m_columnCategories = categories;
- emit mappingChanged();
- }
-}
-
-QStringList QItemModelBarDataMapping::columnCategories() const
-{
- return dptrc()->m_columnCategories;
-}
-
-/*!
- * \property QItemModelBarDataMapping::useModelCategories
- *
- * When set to true, the mapping ignores row and column roles and categories, and uses
- * the rows and columns from the model instead. Defaults to false.
- */
-void QItemModelBarDataMapping::setUseModelCategories(bool enable)
-{
- if (dptr()->m_useModelCategories != enable) {
- dptr()->m_useModelCategories = enable;
- emit mappingChanged();
- }
-}
-
-bool QItemModelBarDataMapping::useModelCategories() const
-{
- return dptrc()->m_useModelCategories;
-}
-
-/*!
- * \property QItemModelBarDataMapping::autoRowCategories
- *
- * When set to true, the mapping ignores any explicitly set row categories
- * and overwrites them with automatically generated ones whenever the
- * data from model is resolved. Defaults to true.
- */
-void QItemModelBarDataMapping::setAutoRowCategories(bool enable)
-{
- if (dptr()->m_autoRowCategories != enable) {
- dptr()->m_autoRowCategories = enable;
- emit mappingChanged();
- }
-}
-
-bool QItemModelBarDataMapping::autoRowCategories() const
-{
- return dptrc()->m_autoRowCategories;
-}
-
-/*!
- * \property QItemModelBarDataMapping::autoColumnCategories
- *
- * When set to true, the mapping ignores any explicitly set column categories
- * and overwrites them with automatically generated ones whenever the
- * data from model is resolved. Defaults to true.
- */
-void QItemModelBarDataMapping::setAutoColumnCategories(bool enable)
-{
- if (dptr()->m_autoColumnCategories != enable) {
- dptr()->m_autoColumnCategories = enable;
- emit mappingChanged();
- }
-}
-
-bool QItemModelBarDataMapping::autoColumnCategories() const
-{
- return dptrc()->m_autoColumnCategories;
-}
-
-/*!
- * Changes \a rowRole, \a columnRole, \a valueRole, \a rowCategories and \a columnCategories to the
- * mapping.
- */
-void QItemModelBarDataMapping::remap(const QString &rowRole,
- const QString &columnRole,
- const QString &valueRole,
- const QStringList &rowCategories,
- const QStringList &columnCategories)
-{
- dptr()->m_rowRole = rowRole;
- dptr()->m_columnRole = columnRole;
- dptr()->m_valueRole = valueRole;
- dptr()->m_rowCategories = rowCategories;
- dptr()->m_columnCategories = columnCategories;
-
- emit mappingChanged();
-}
-
-/*!
- * /return index of the specified \a category in row categories list.
- * If the row categories list is empty, -1 is returned.
- * \note If the automatic row categories generation is in use, this method will
- * not return a valid index before the data in the model is resolved for the first time.
- */
-int QItemModelBarDataMapping::rowCategoryIndex(const QString &category)
-{
- return dptr()->m_rowCategories.indexOf(category);
-}
-
-/*!
- * /return index of the specified \a category in column categories list.
- * If the category is not found, -1 is returned.
- * \note If the automatic column categories generation is in use, this method will
- * not return a valid index before the data in the model is resolved for the first time.
- */
-int QItemModelBarDataMapping::columnCategoryIndex(const QString &category)
-{
- return dptr()->m_columnCategories.indexOf(category);
-}
-
-/*!
- * \internal
- */
-QItemModelBarDataMappingPrivate *QItemModelBarDataMapping::dptr()
-{
- return static_cast<QItemModelBarDataMappingPrivate *>(d_ptr.data());
-}
-
-/*!
- * \internal
- */
-const QItemModelBarDataMappingPrivate *QItemModelBarDataMapping::dptrc() const
-{
- return static_cast<const QItemModelBarDataMappingPrivate *>(d_ptr.data());
-}
-
-// QItemModelBarDataMappingPrivate
-
-QItemModelBarDataMappingPrivate::QItemModelBarDataMappingPrivate(QItemModelBarDataMapping *q)
- : QAbstractDataMappingPrivate(q, QAbstractDataProxy::DataTypeBar),
- m_useModelCategories(false),
- m_autoRowCategories(true),
- m_autoColumnCategories(true)
-{
-}
-
-QItemModelBarDataMappingPrivate::~QItemModelBarDataMappingPrivate()
-{
-}
-
-
-QT_DATAVISUALIZATION_END_NAMESPACE
-
diff --git a/src/datavisualization/data/qitemmodelbardatamapping.h b/src/datavisualization/data/qitemmodelbardatamapping.h
deleted file mode 100644
index a5ef33b8..00000000
--- a/src/datavisualization/data/qitemmodelbardatamapping.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use contact form at http://qt.digia.com
-**
-** This file is part of the QtDataVisualization module.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** contact form at http://qt.digia.com
-**
-****************************************************************************/
-
-#ifndef QITEMMODELBARDATAMAPPING_H
-#define QITEMMODELBARDATAMAPPING_H
-
-#include <QtDataVisualization/qdatavisualizationenums.h>
-#include <QtDataVisualization/qabstractdatamapping.h>
-#include <QStringList>
-
-QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-
-class QItemModelBarDataMappingPrivate;
-
-class QT_DATAVISUALIZATION_EXPORT QItemModelBarDataMapping : public QAbstractDataMapping
-{
- Q_OBJECT
- Q_PROPERTY(QString rowRole READ rowRole WRITE setRowRole)
- Q_PROPERTY(QString columnRole READ columnRole WRITE setColumnRole)
- Q_PROPERTY(QString valueRole READ valueRole WRITE setValueRole)
- Q_PROPERTY(QStringList rowCategories READ rowCategories WRITE setRowCategories)
- Q_PROPERTY(QStringList columnCategories READ columnCategories WRITE setColumnCategories)
- Q_PROPERTY(bool useModelCategories READ useModelCategories WRITE setUseModelCategories)
- Q_PROPERTY(bool autoRowCategories READ autoRowCategories WRITE setAutoRowCategories)
- Q_PROPERTY(bool autoColumnCategories READ autoColumnCategories WRITE setAutoColumnCategories)
-
-public:
- explicit QItemModelBarDataMapping(QObject *parent = 0);
- QItemModelBarDataMapping(const QString &valueRole, QObject *parent = 0);
- QItemModelBarDataMapping(const QString &rowRole, const QString &columnRole,
- const QString &valueRole, QObject *parent = 0);
- QItemModelBarDataMapping(const QString &rowRole, const QString &columnRole,
- const QString &valueRole, const QStringList &rowCategories,
- const QStringList &columnCategories, QObject *parent = 0);
- virtual ~QItemModelBarDataMapping();
-
- void setRowRole(const QString &role);
- QString rowRole() const;
- void setColumnRole(const QString &role);
- QString columnRole() const;
- void setValueRole(const QString &role);
- QString valueRole() const;
-
- void setRowCategories(const QStringList &categories);
- QStringList rowCategories() const;
- void setColumnCategories(const QStringList &categories);
- QStringList columnCategories() const;
-
- void setUseModelCategories(bool enable);
- bool useModelCategories() const;
- void setAutoRowCategories(bool enable);
- bool autoRowCategories() const;
- void setAutoColumnCategories(bool enable);
- bool autoColumnCategories() const;
-
- void remap(const QString &rowRole, const QString &columnRole,
- const QString &valueRole, const QStringList &rowCategories,
- const QStringList &columnCategories);
-
- Q_INVOKABLE int rowCategoryIndex(const QString& category);
- Q_INVOKABLE int columnCategoryIndex(const QString& category);
-
-protected:
- QItemModelBarDataMappingPrivate *dptr();
- const QItemModelBarDataMappingPrivate *dptrc() const;
-
-private:
- Q_DISABLE_COPY(QItemModelBarDataMapping)
-
- friend class BarItemModelHandler;
-};
-
-QT_DATAVISUALIZATION_END_NAMESPACE
-
-#endif
diff --git a/src/datavisualization/data/qitemmodelbardataproxy.cpp b/src/datavisualization/data/qitemmodelbardataproxy.cpp
index a28e05e1..e3354015 100644
--- a/src/datavisualization/data/qitemmodelbardataproxy.cpp
+++ b/src/datavisualization/data/qitemmodelbardataproxy.cpp
@@ -29,13 +29,36 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
* \since Qt Data Visualization 1.0
*
* QItemModelBarDataProxy allows you to use QAbstractItemModel derived models as a data source
- * for Q3DBars. It uses QItemModelBarDataMapping instance to map data from the model to Q3DBars
- * graph.
+ * for Q3DBars. It uses the defined mappings to map data from the model to rows, columns, and
+ * values of Q3DBars graph.
*
- * The data is resolved asynchronously whenever the mapping or the model changes.
+ * The data is resolved asynchronously whenever mappings or the model changes.
* QBarDataProxy::arrayReset() is emitted when the data has been resolved.
*
- * \sa QItemModelBarDataMapping, {Qt Data Visualization Data Handling}
+ * There are three ways to use mappings:
+ *
+ * 1) If useModelCategories property is set to true, this proxy will map rows and
+ * columns of QAbstractItemModel directly to rows and columns of Q3DBars, and uses the value
+ * returned for Qt::DisplayRole as bar value by default.
+ * The value role to be used can be redefined if Qt::DisplayRole is not suitable.
+ *
+ * 2) For models that do not have data already neatly sorted into rows and columns, such as
+ * QAbstractListModel based models, you can define a role from the model to map for each of row,
+ * column and value.
+ *
+ * 3) If you do not want to include all data contained in the model, or the autogenerated rows and
+ * columns are not ordered as you wish, you can specify which rows and columns should be included
+ * and in which order by defining an explicit list of categories for either or both of rows and
+ * columns.
+ *
+ * For example, assume that you have a custom QAbstractItemModel for storing various monthly values
+ * related to a business.
+ * Each item in the model has the roles "year", "month", "income", and "expenses".
+ * You could do the following to display the data in a bar graph:
+ *
+ * \snippet doc_src_qtdatavisualization.cpp 3
+ *
+ * \sa {Qt Data Visualization Data Handling}
*/
/*!
@@ -52,11 +75,13 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
* Data is resolved asynchronously whenever the mapping or the model changes.
* QBarDataProxy::arrayReset() is emitted when the data has been resolved.
*
+ * For more details, see QItemModelBarDataProxy documentation.
+ *
* Usage example:
*
* \snippet doc_src_qmldatavisualization.cpp 7
*
- * \sa BarDataProxy, BarDataMapping, {Qt Data Visualization Data Handling}
+ * \sa BarDataProxy, {Qt Data Visualization Data Handling}
*/
/*!
@@ -65,30 +90,133 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*/
/*!
- * \qmlproperty list ItemModelBarDataProxy::activeMapping
- * The active mapping. Modifying a mapping that is set to the proxy will trigger data set
- * re-resolving.
+ * \qmlproperty string ItemModelBarDataProxy::rowRole
+ * The row role of the mapping.
+ */
+
+/*!
+ * \qmlproperty string ItemModelBarDataProxy::columnRole
+ * The column role of the mapping.
+ */
+
+/*!
+ * \qmlproperty string ItemModelBarDataProxy::valueRole
+ * The value role of the mapping.
+ */
+
+/*!
+ * \qmlproperty list ItemModelBarDataProxy::rowCategories
+ * The row categories of the mapping. Only items with row roles that are found in this list are
+ * included when the data is resolved. The rows are ordered in the same order as they are in this list.
+ */
+
+/*!
+ * \qmlproperty list ItemModelBarDataProxy::columnCategories
+ * The column categories of the mapping. Only items with column roles that are found in this list are
+ * included when the data is resolved. The columns are ordered in the same order as they are in this list.
+ */
+
+/*!
+ * \qmlproperty list ItemModelBarDataProxy::useModelCategories
+ * When set to true, the mapping ignores row and column roles and categories, and uses
+ * the rows and columns from the model instead. Row and column headers are used for row and column
+ * labels. Defaults to false.
+ */
+
+/*!
+ * \qmlproperty list ItemModelBarDataProxy::autoRowCategories
+ * When set to true, the mapping ignores any explicitly set row categories
+ * and overwrites them with automatically generated ones whenever the
+ * data from the model is resolved. Defaults to true.
+ */
+
+/*!
+ * \qmlproperty list ItemModelBarDataProxy::autoColumnCategories
+ * When set to true, the mapping ignores any explicitly set column categories
+ * and overwrites them with automatically generated ones whenever the
+ * data from model is resolved. Defaults to true.
*/
/*!
- * Constructs QItemModelBarDataProxy.
+ * Constructs QItemModelBarDataProxy with optional \a parent.
*/
-QItemModelBarDataProxy::QItemModelBarDataProxy() :
- QBarDataProxy(new QItemModelBarDataProxyPrivate(this))
+QItemModelBarDataProxy::QItemModelBarDataProxy(QObject *parent)
+ : QBarDataProxy(new QItemModelBarDataProxyPrivate(this), parent)
{
+ dptr()->connectItemModelHandler();
}
/*!
- * Constructs QItemModelBarDataProxy with \a itemModel and \a mapping. Proxy takes ownership of the
- * \a mapping, but doesn't take ownership of the \a itemModel, as typically item models are owned
- * by other controls.
+ * Constructs QItemModelBarDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
+ * ownership of the \a itemModel, as typically item models are owned by other controls.
+ */
+QItemModelBarDataProxy::QItemModelBarDataProxy(const QAbstractItemModel *itemModel, QObject *parent)
+ : QBarDataProxy(new QItemModelBarDataProxyPrivate(this), parent)
+{
+ setItemModel(itemModel);
+ dptr()->connectItemModelHandler();
+}
+
+/*!
+ * Constructs QItemModelBarDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
+ * ownership of the \a itemModel, as typically item models are owned by other controls.
+ * The value role is set to \a valueRole.
+ * This constructor is meant to be used with models that have data properly sorted
+ * in rows and columns already, so it also sets useModelCategories property to true.
+ */
+QItemModelBarDataProxy::QItemModelBarDataProxy(const QAbstractItemModel *itemModel,
+ const QString &valueRole, QObject *parent)
+ : QBarDataProxy(new QItemModelBarDataProxyPrivate(this), parent)
+{
+ dptr()->m_itemModelHandler->setItemModel(itemModel);
+ dptr()->m_valueRole = valueRole;
+ dptr()->m_useModelCategories = true;
+ dptr()->connectItemModelHandler();
+}
+
+/*!
+ * Constructs QItemModelBarDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
+ * ownership of the \a itemModel, as typically item models are owned by other controls.
+ * The role mappings are set with \a rowRole, \a columnRole, and \a valueRole.
+ */
+QItemModelBarDataProxy::QItemModelBarDataProxy(const QAbstractItemModel *itemModel,
+ const QString &rowRole,
+ const QString &columnRole,
+ const QString &valueRole, QObject *parent)
+ : QBarDataProxy(new QItemModelBarDataProxyPrivate(this), parent)
+{
+ dptr()->m_itemModelHandler->setItemModel(itemModel);
+ dptr()->m_rowRole = rowRole;
+ dptr()->m_columnRole = columnRole;
+ dptr()->m_valueRole = valueRole;
+ dptr()->connectItemModelHandler();
+}
+
+/*!
+ * Constructs QItemModelBarDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
+ * ownership of the \a itemModel, as typically item models are owned by other controls.
+ * The role mappings are set with \a rowRole, \a columnRole, and \a valueRole.
+ * Row and column categories are set with \a rowCategories and \a columnCategories.
+ * This constructor also sets autoRowCategories and autoColumnCategories to false.
*/
QItemModelBarDataProxy::QItemModelBarDataProxy(const QAbstractItemModel *itemModel,
- QItemModelBarDataMapping *mapping) :
- QBarDataProxy(new QItemModelBarDataProxyPrivate(this))
+ const QString &rowRole,
+ const QString &columnRole,
+ const QString &valueRole,
+ const QStringList &rowCategories,
+ const QStringList &columnCategories,
+ QObject *parent)
+ : QBarDataProxy(new QItemModelBarDataProxyPrivate(this), parent)
{
dptr()->m_itemModelHandler->setItemModel(itemModel);
- dptr()->m_itemModelHandler->setActiveMapping(mapping);
+ dptr()->m_rowRole = rowRole;
+ dptr()->m_columnRole = columnRole;
+ dptr()->m_valueRole = valueRole;
+ dptr()->m_rowCategories = rowCategories;
+ dptr()->m_columnCategories = columnCategories;
+ dptr()->m_autoRowCategories = false;
+ dptr()->m_autoColumnCategories = false;
+ dptr()->connectItemModelHandler();
}
/*!
@@ -115,50 +243,191 @@ const QAbstractItemModel *QItemModelBarDataProxy::itemModel() const
}
/*!
- * \property QItemModelBarDataProxy::activeMapping
+ * \property QItemModelBarDataProxy::rowRole
+ *
+ * Defines the row role for the mapping.
+ */
+void QItemModelBarDataProxy::setRowRole(const QString &role)
+{
+ if (dptr()->m_rowRole != role) {
+ dptr()->m_rowRole = role;
+ emit rowRoleChanged(role);
+ }
+}
+
+QString QItemModelBarDataProxy::rowRole() const
+{
+ return dptrc()->m_rowRole;
+}
+
+/*!
+ * \property QItemModelBarDataProxy::columnRole
*
- * Defines data mapping. Proxy takes ownership of the \a mapping.
- * Modifying a mapping that is set to the proxy will trigger data set re-resolving.
+ * Defines the column role for the mapping.
*/
-void QItemModelBarDataProxy::setActiveMapping(QItemModelBarDataMapping *mapping)
+void QItemModelBarDataProxy::setColumnRole(const QString &role)
{
- dptr()->m_itemModelHandler->setActiveMapping(mapping);
+ if (dptr()->m_columnRole != role) {
+ dptr()->m_columnRole = role;
+ emit columnRoleChanged(role);
+ }
}
-QItemModelBarDataMapping *QItemModelBarDataProxy::activeMapping() const
+QString QItemModelBarDataProxy::columnRole() const
{
- return static_cast<QItemModelBarDataMapping *>(dptrc()->m_itemModelHandler->activeMapping());
+ return dptrc()->m_columnRole;
}
/*!
- * Transfers the ownership of the \a mapping to this proxy. The mapping is not taken to use yet.
- * \sa setActiveMapping(), releaseMapping()
+ * \property QItemModelBarDataProxy::valueRole
+ *
+ * Defines the value role for the mapping.
+ */
+void QItemModelBarDataProxy::setValueRole(const QString &role)
+{
+ if (dptr()->m_valueRole != role) {
+ dptr()->m_valueRole = role;
+ emit valueRoleChanged(role);
+ }
+}
+
+QString QItemModelBarDataProxy::valueRole() const
+{
+ return dptrc()->m_valueRole;
+}
+
+/*!
+ * \property QItemModelBarDataProxy::rowCategories
+ *
+ * Defines the row categories for the mapping.
+ */
+void QItemModelBarDataProxy::setRowCategories(const QStringList &categories)
+{
+ if (dptr()->m_rowCategories != categories) {
+ dptr()->m_rowCategories = categories;
+ emit rowCategoriesChanged(categories);
+ }
+}
+
+QStringList QItemModelBarDataProxy::rowCategories() const
+{
+ return dptrc()->m_rowCategories;
+}
+
+/*!
+ * \property QItemModelBarDataProxy::columnCategories
+ *
+ * Defines the column categories for the mapping.
+ */
+void QItemModelBarDataProxy::setColumnCategories(const QStringList &categories)
+{
+ if (dptr()->m_columnCategories != categories) {
+ dptr()->m_columnCategories = categories;
+ emit columnCategoriesChanged(categories);
+ }
+}
+
+QStringList QItemModelBarDataProxy::columnCategories() const
+{
+ return dptrc()->m_columnCategories;
+}
+
+/*!
+ * \property QItemModelBarDataProxy::useModelCategories
+ *
+ * When set to true, the mapping ignores row and column roles and categories, and uses
+ * the rows and columns from the model instead. Defaults to false.
*/
-void QItemModelBarDataProxy::addMapping(QItemModelBarDataMapping *mapping)
+void QItemModelBarDataProxy::setUseModelCategories(bool enable)
{
- dptr()->m_itemModelHandler->addMapping(mapping);
+ if (dptr()->m_useModelCategories != enable) {
+ dptr()->m_useModelCategories = enable;
+ emit useModelCategoriesChanged(enable);
+ }
+}
+
+bool QItemModelBarDataProxy::useModelCategories() const
+{
+ return dptrc()->m_useModelCategories;
+}
+
+/*!
+ * \property QItemModelBarDataProxy::autoRowCategories
+ *
+ * When set to true, the mapping ignores any explicitly set row categories
+ * and overwrites them with automatically generated ones whenever the
+ * data from model is resolved. Defaults to true.
+ */
+void QItemModelBarDataProxy::setAutoRowCategories(bool enable)
+{
+ if (dptr()->m_autoRowCategories != enable) {
+ dptr()->m_autoRowCategories = enable;
+ emit autoRowCategoriesChanged(enable);
+ }
+}
+
+bool QItemModelBarDataProxy::autoRowCategories() const
+{
+ return dptrc()->m_autoRowCategories;
+}
+
+/*!
+ * \property QItemModelBarDataProxy::autoColumnCategories
+ *
+ * When set to true, the mapping ignores any explicitly set column categories
+ * and overwrites them with automatically generated ones whenever the
+ * data from model is resolved. Defaults to true.
+ */
+void QItemModelBarDataProxy::setAutoColumnCategories(bool enable)
+{
+ if (dptr()->m_autoColumnCategories != enable) {
+ dptr()->m_autoColumnCategories = enable;
+ emit autoColumnCategoriesChanged(enable);
+ }
+}
+
+bool QItemModelBarDataProxy::autoColumnCategories() const
+{
+ return dptrc()->m_autoColumnCategories;
}
/*!
- * Releases the ownership of the \a mapping back to the caller. If the mapping was the currently
- * active one, no mapping remains active after this call.
+ * Changes \a rowRole, \a columnRole, \a valueRole, \a rowCategories and \a columnCategories to the
+ * mapping.
*/
-void QItemModelBarDataProxy::releaseMapping(QItemModelBarDataMapping *mapping)
+void QItemModelBarDataProxy::remap(const QString &rowRole,
+ const QString &columnRole,
+ const QString &valueRole,
+ const QStringList &rowCategories,
+ const QStringList &columnCategories)
{
- dptr()->m_itemModelHandler->releaseMapping(mapping);
+ setRowRole(rowRole);
+ setColumnRole(columnRole);
+ setValueRole(valueRole);
+ setRowCategories(rowCategories);
+ setColumnCategories(columnCategories);
}
/*!
- * \return list of mappings owned by the proxy.
+ * /return index of the specified \a category in row categories list.
+ * If the row categories list is empty, -1 is returned.
+ * \note If the automatic row categories generation is in use, this method will
+ * not return a valid index before the data in the model is resolved for the first time.
*/
-QList<QItemModelBarDataMapping *> QItemModelBarDataProxy::mappings() const
+int QItemModelBarDataProxy::rowCategoryIndex(const QString &category)
{
- QList<QItemModelBarDataMapping *> retList;
- QList<QAbstractDataMapping *> abstractList = dptrc()->m_itemModelHandler->mappings();
- foreach (QAbstractDataMapping *mapping, abstractList)
- retList.append(static_cast<QItemModelBarDataMapping *>(mapping));
+ return dptr()->m_rowCategories.indexOf(category);
+}
- return retList;
+/*!
+ * /return index of the specified \a category in column categories list.
+ * If the category is not found, -1 is returned.
+ * \note If the automatic column categories generation is in use, this method will
+ * not return a valid index before the data in the model is resolved for the first time.
+ */
+int QItemModelBarDataProxy::columnCategoryIndex(const QString &category)
+{
+ return dptr()->m_columnCategories.indexOf(category);
}
/*!
@@ -177,11 +446,36 @@ const QItemModelBarDataProxyPrivate *QItemModelBarDataProxy::dptrc() const
return static_cast<const QItemModelBarDataProxyPrivate *>(d_ptr.data());
}
+void QItemModelBarDataProxyPrivate::connectItemModelHandler()
+{
+ QObject::connect(m_itemModelHandler, &BarItemModelHandler::itemModelChanged,
+ qptr(), &QItemModelBarDataProxy::itemModelChanged);
+ QObject::connect(qptr(), &QItemModelBarDataProxy::rowRoleChanged,
+ m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
+ QObject::connect(qptr(), &QItemModelBarDataProxy::columnRoleChanged,
+ m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
+ QObject::connect(qptr(), &QItemModelBarDataProxy::valueRoleChanged,
+ m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
+ QObject::connect(qptr(), &QItemModelBarDataProxy::rowCategoriesChanged,
+ m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
+ QObject::connect(qptr(), &QItemModelBarDataProxy::columnCategoriesChanged,
+ m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
+ QObject::connect(qptr(), &QItemModelBarDataProxy::useModelCategoriesChanged,
+ m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
+ QObject::connect(qptr(), &QItemModelBarDataProxy::autoRowCategoriesChanged,
+ m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
+ QObject::connect(qptr(), &QItemModelBarDataProxy::autoColumnCategoriesChanged,
+ m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
+}
+
// QItemModelBarDataProxyPrivate
QItemModelBarDataProxyPrivate::QItemModelBarDataProxyPrivate(QItemModelBarDataProxy *q)
: QBarDataProxyPrivate(q),
- m_itemModelHandler(new BarItemModelHandler(q))
+ m_itemModelHandler(new BarItemModelHandler(q)),
+ m_useModelCategories(false),
+ m_autoRowCategories(true),
+ m_autoColumnCategories(true)
{
}
diff --git a/src/datavisualization/data/qitemmodelbardataproxy.h b/src/datavisualization/data/qitemmodelbardataproxy.h
index 2a96f0c8..597ab48f 100644
--- a/src/datavisualization/data/qitemmodelbardataproxy.h
+++ b/src/datavisualization/data/qitemmodelbardataproxy.h
@@ -20,7 +20,6 @@
#define QITEMMODELBARDATAPROXY_H
#include <QtDataVisualization/qbardataproxy.h>
-#include <QtDataVisualization/qitemmodelbardatamapping.h>
#include <QAbstractItemModel>
#include <QStringList>
@@ -31,23 +30,69 @@ class QItemModelBarDataProxyPrivate;
class QT_DATAVISUALIZATION_EXPORT QItemModelBarDataProxy : public QBarDataProxy
{
Q_OBJECT
- Q_PROPERTY(const QAbstractItemModel* itemModel READ itemModel WRITE setItemModel)
- Q_PROPERTY(QItemModelBarDataMapping* activeMapping READ activeMapping WRITE setActiveMapping)
+ Q_PROPERTY(const QAbstractItemModel* itemModel READ itemModel WRITE setItemModel NOTIFY itemModelChanged)
+ Q_PROPERTY(QString rowRole READ rowRole WRITE setRowRole NOTIFY rowRoleChanged)
+ Q_PROPERTY(QString columnRole READ columnRole WRITE setColumnRole NOTIFY columnRoleChanged)
+ Q_PROPERTY(QString valueRole READ valueRole WRITE setValueRole NOTIFY valueRoleChanged)
+ Q_PROPERTY(QStringList rowCategories READ rowCategories WRITE setRowCategories NOTIFY rowCategoriesChanged)
+ Q_PROPERTY(QStringList columnCategories READ columnCategories WRITE setColumnCategories NOTIFY columnCategoriesChanged)
+ Q_PROPERTY(bool useModelCategories READ useModelCategories WRITE setUseModelCategories NOTIFY useModelCategoriesChanged)
+ Q_PROPERTY(bool autoRowCategories READ autoRowCategories WRITE setAutoRowCategories NOTIFY autoRowCategoriesChanged)
+ Q_PROPERTY(bool autoColumnCategories READ autoColumnCategories WRITE setAutoColumnCategories NOTIFY autoColumnCategoriesChanged)
public:
- explicit QItemModelBarDataProxy();
- explicit QItemModelBarDataProxy(const QAbstractItemModel *itemModel,
- QItemModelBarDataMapping *mapping);
+ explicit QItemModelBarDataProxy(QObject *parent = 0);
+ QItemModelBarDataProxy(const QAbstractItemModel *itemModel, QObject *parent = 0);
+ QItemModelBarDataProxy(const QAbstractItemModel *itemModel, const QString &valueRole,
+ QObject *parent = 0);
+ QItemModelBarDataProxy(const QAbstractItemModel *itemModel, const QString &rowRole,
+ const QString &columnRole, const QString &valueRole,
+ QObject *parent = 0);
+ QItemModelBarDataProxy(const QAbstractItemModel *itemModel, const QString &rowRole,
+ const QString &columnRole, const QString &valueRole,
+ const QStringList &rowCategories, const QStringList &columnCategories,
+ QObject *parent = 0);
virtual ~QItemModelBarDataProxy();
void setItemModel(const QAbstractItemModel *itemModel);
const QAbstractItemModel *itemModel() const;
- void setActiveMapping(QItemModelBarDataMapping *mapping);
- QItemModelBarDataMapping *activeMapping() const;
- void addMapping(QItemModelBarDataMapping *mapping);
- void releaseMapping(QItemModelBarDataMapping *mapping);
- QList<QItemModelBarDataMapping *> mappings() const;
+ void setRowRole(const QString &role);
+ QString rowRole() const;
+ void setColumnRole(const QString &role);
+ QString columnRole() const;
+ void setValueRole(const QString &role);
+ QString valueRole() const;
+
+ void setRowCategories(const QStringList &categories);
+ QStringList rowCategories() const;
+ void setColumnCategories(const QStringList &categories);
+ QStringList columnCategories() const;
+
+ void setUseModelCategories(bool enable);
+ bool useModelCategories() const;
+ void setAutoRowCategories(bool enable);
+ bool autoRowCategories() const;
+ void setAutoColumnCategories(bool enable);
+ bool autoColumnCategories() const;
+
+ void remap(const QString &rowRole, const QString &columnRole,
+ const QString &valueRole, const QStringList &rowCategories,
+ const QStringList &columnCategories);
+
+ Q_INVOKABLE int rowCategoryIndex(const QString& category);
+ Q_INVOKABLE int columnCategoryIndex(const QString& category);
+
+signals:
+ void itemModelChanged(const QAbstractItemModel* itemModel);
+ void rowRoleChanged(QString role);
+ void columnRoleChanged(QString role);
+ void valueRoleChanged(QString role);
+ void rowCategoriesChanged(QStringList categories);
+ void columnCategoriesChanged(QStringList categories);
+ void useModelCategoriesChanged(bool enable);
+ void autoRowCategoriesChanged(bool enable);
+ void autoColumnCategoriesChanged(bool enable);
protected:
QItemModelBarDataProxyPrivate *dptr();
@@ -55,6 +100,8 @@ protected:
private:
Q_DISABLE_COPY(QItemModelBarDataProxy)
+
+ friend class BarItemModelHandler;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/data/qitemmodelbardataproxy_p.h b/src/datavisualization/data/qitemmodelbardataproxy_p.h
index fc646f0d..63c5b3ff 100644
--- a/src/datavisualization/data/qitemmodelbardataproxy_p.h
+++ b/src/datavisualization/data/qitemmodelbardataproxy_p.h
@@ -31,8 +31,6 @@
#include "qitemmodelbardataproxy.h"
#include "qbardataproxy_p.h"
-#include <QPointer>
-#include <QTimer>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
@@ -45,11 +43,26 @@ public:
QItemModelBarDataProxyPrivate(QItemModelBarDataProxy *q);
virtual ~QItemModelBarDataProxyPrivate();
+ void connectItemModelHandler();
+
private:
QItemModelBarDataProxy *qptr();
BarItemModelHandler *m_itemModelHandler;
+ QString m_rowRole;
+ QString m_columnRole;
+ QString m_valueRole;
+
+ // For row/column items, sort items into these categories. Other categories are ignored.
+ QStringList m_rowCategories;
+ QStringList m_columnCategories;
+
+ bool m_useModelCategories;
+ bool m_autoRowCategories;
+ bool m_autoColumnCategories;
+
+ friend class BarItemModelHandler;
friend class QItemModelBarDataProxy;
};
diff --git a/src/datavisualization/data/qitemmodelscatterdatamapping.cpp b/src/datavisualization/data/qitemmodelscatterdatamapping.cpp
deleted file mode 100644
index 3d94d0ce..00000000
--- a/src/datavisualization/data/qitemmodelscatterdatamapping.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use contact form at http://qt.digia.com
-**
-** This file is part of the QtDataVisualization module.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** contact form at http://qt.digia.com
-**
-****************************************************************************/
-
-#include "qitemmodelscatterdatamapping_p.h"
-
-QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-
-/*!
- * \class QItemModelScatterDataMapping
- * \inmodule QtDataVisualization
- * \brief Item model mapping for Q3DScatter.
- * \since Qt Data Visualization 1.0
- *
- * QItemModelScatterDataMapping is used to map roles of QAbstractItemModel to the XYZ-values
- * of Q3DScatter points.
- *
- * QItemModelScatterDataMapping ignores rows and columns of the QAbstractItemModel and treats
- * all items equally. It requires the model to provide at least three roles for the data items
- * that can be mapped to X, Y, and Z-values for the scatter points.
- *
- * For example, assume that you have a custom QAbstractItemModel for storing various measurements
- * done on material samples, providing data for roles such as "density", "hardness", and
- * "conductivity". You could visualize these properties on a scatter graph:
- *
- * \snippet doc_src_qtdatavisualization.cpp 4
- *
- * \sa QItemModelScatterDataProxy, {Qt Data Visualization Data Handling}
- */
-
-/*!
- * \qmltype ScatterDataMapping
- * \inqmlmodule QtDataVisualization
- * \since QtDataVisualization 1.0
- * \ingroup datavisualization_qml
- * \instantiates QItemModelScatterDataMapping
- * \brief Item model mapping for Scatter3D.
- *
- * This type is used to map roles of AbstractItemModel to the XYZ-values of Scatter3D points. For
- * a more complete description, see QItemModelScatterDataMapping.
- *
- * Usage example:
- *
- * \snippet doc_src_qmldatavisualization.cpp 5
- *
- * \sa ItemModelScatterDataProxy, {Qt Data Visualization Data Handling}
- */
-
-/*!
- * \qmlproperty string ScatterDataMapping::xPosRole
- * The X position role of the mapping.
- */
-
-/*!
- * \qmlproperty string ScatterDataMapping::yPosRole
- * The Y position role of the mapping.
- */
-
-/*!
- * \qmlproperty string ScatterDataMapping::zPosRole
- * The Z position role of the mapping.
- */
-
-/*!
- * Constructs QItemModelScatterDataMapping with the given \a parent.
- */
-QItemModelScatterDataMapping::QItemModelScatterDataMapping(QObject *parent)
- : QAbstractDataMapping(new QItemModelScatterDataMappingPrivate(this), parent)
-{
-}
-
-/*!
- * Constructs QItemModelScatterDataMapping with \a xPosRole, \a yPosRole, \a zPosRole
- * and the given \a parent.
- */
-QItemModelScatterDataMapping::QItemModelScatterDataMapping(const QString &xPosRole,
- const QString &yPosRole,
- const QString &zPosRole,
- QObject *parent)
- : QAbstractDataMapping(new QItemModelScatterDataMappingPrivate(this), parent)
-{
- dptr()->m_xPosRole = xPosRole;
- dptr()->m_yPosRole = yPosRole;
- dptr()->m_zPosRole = zPosRole;
-}
-
-/*!
- * Destroys QItemModelScatterDataMapping.
- */
-QItemModelScatterDataMapping::~QItemModelScatterDataMapping()
-{
-}
-
-/*!
- * \property QItemModelScatterDataMapping::xPosRole
- *
- * Defines the X position role for the mapping.
- */
-void QItemModelScatterDataMapping::setXPosRole(const QString &role)
-{
- dptr()->m_xPosRole = role;
- emit mappingChanged();
-}
-
-QString QItemModelScatterDataMapping::xPosRole() const
-{
- return dptrc()->m_xPosRole;
-}
-
-/*!
- * \property QItemModelScatterDataMapping::yPosRole
- *
- * Defines the Y position role for the mapping.
- */
-void QItemModelScatterDataMapping::setYPosRole(const QString &role)
-{
- dptr()->m_yPosRole = role;
- emit mappingChanged();
-}
-
-QString QItemModelScatterDataMapping::yPosRole() const
-{
- return dptrc()->m_yPosRole;
-}
-
-/*!
- * \property QItemModelScatterDataMapping::zPosRole
- *
- * Defines the Z position role for the mapping.
- */
-void QItemModelScatterDataMapping::setZPosRole(const QString &role)
-{
- dptr()->m_zPosRole = role;
- emit mappingChanged();
-}
-
-QString QItemModelScatterDataMapping::zPosRole() const
-{
- return dptrc()->m_zPosRole;
-}
-
-/*!
- * Changes \a xPosRole, \a yPosRole and \a zPosRole to the mapping.
- *
- * Emits mappingChanged() signal after remapping.
- */
-void QItemModelScatterDataMapping::remap(const QString &xPosRole, const QString &yPosRole,
- const QString &zPosRole)
-{
- dptr()->m_xPosRole = xPosRole;
- dptr()->m_yPosRole = yPosRole;
- dptr()->m_zPosRole = zPosRole;
-
- emit mappingChanged();
-}
-
-/*!
- * \internal
- */
-QItemModelScatterDataMappingPrivate *QItemModelScatterDataMapping::dptr()
-{
- return static_cast<QItemModelScatterDataMappingPrivate *>(d_ptr.data());
-}
-
-/*!
- * \internal
- */
-const QItemModelScatterDataMappingPrivate *QItemModelScatterDataMapping::dptrc() const
-{
- return static_cast<const QItemModelScatterDataMappingPrivate *>(d_ptr.data());
-}
-
-// QItemModelScatterDataMappingPrivate
-
-QItemModelScatterDataMappingPrivate::QItemModelScatterDataMappingPrivate(
- QItemModelScatterDataMapping *q)
- : QAbstractDataMappingPrivate(q, QAbstractDataProxy::DataTypeScatter)
-{
-}
-
-QItemModelScatterDataMappingPrivate::~QItemModelScatterDataMappingPrivate()
-{
-}
-
-QT_DATAVISUALIZATION_END_NAMESPACE
-
diff --git a/src/datavisualization/data/qitemmodelscatterdatamapping.h b/src/datavisualization/data/qitemmodelscatterdatamapping.h
deleted file mode 100644
index 62f2fefc..00000000
--- a/src/datavisualization/data/qitemmodelscatterdatamapping.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use contact form at http://qt.digia.com
-**
-** This file is part of the QtDataVisualization module.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** contact form at http://qt.digia.com
-**
-****************************************************************************/
-
-#ifndef QITEMMODELSCATTERDATAMAPPING_H
-#define QITEMMODELSCATTERDATAMAPPING_H
-
-#include <QtDataVisualization/qdatavisualizationenums.h>
-#include <QtDataVisualization/qabstractdatamapping.h>
-#include <QObject>
-
-QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-
-class QItemModelScatterDataMappingPrivate;
-
-class QT_DATAVISUALIZATION_EXPORT QItemModelScatterDataMapping : public QAbstractDataMapping
-{
- Q_OBJECT
- Q_PROPERTY(QString xPosRole READ xPosRole WRITE setXPosRole)
- Q_PROPERTY(QString yPosRole READ yPosRole WRITE setYPosRole)
- Q_PROPERTY(QString zPosRole READ zPosRole WRITE setZPosRole)
-
-public:
- explicit QItemModelScatterDataMapping(QObject *parent = 0);
- QItemModelScatterDataMapping(const QString &xPosRole, const QString &yPosRole,
- const QString &zPosRole, QObject *parent = 0);
- virtual ~QItemModelScatterDataMapping();
-
- void setXPosRole(const QString &role);
- QString xPosRole() const;
- void setYPosRole(const QString &role);
- QString yPosRole() const;
- void setZPosRole(const QString &role);
- QString zPosRole() const;
-
- void remap(const QString &xPosRole, const QString &yPosRole, const QString &zPosRole);
-
-protected:
- QItemModelScatterDataMappingPrivate *dptr();
- const QItemModelScatterDataMappingPrivate *dptrc() const;
-
-private:
- Q_DISABLE_COPY(QItemModelScatterDataMapping)
-};
-
-QT_DATAVISUALIZATION_END_NAMESPACE
-
-#endif
diff --git a/src/datavisualization/data/qitemmodelscatterdataproxy.cpp b/src/datavisualization/data/qitemmodelscatterdataproxy.cpp
index 66a0a63b..50b57423 100644
--- a/src/datavisualization/data/qitemmodelscatterdataproxy.cpp
+++ b/src/datavisualization/data/qitemmodelscatterdataproxy.cpp
@@ -29,12 +29,22 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
* \since Qt Data Visualization 1.0
*
* QItemModelScatterDataProxy allows you to use QAbstractItemModel derived models as a data source
- * for Q3DScatter. It maps roles defined in QItemModelScatterDataMapping to roles in the model.
+ * for Q3DScatter. It maps roles of QAbstractItemModel to the XYZ-values of Q3DScatter points.
*
* The data is resolved asynchronously whenever the mapping or the model changes.
* QScatterDataProxy::arrayReset() is emitted when the data has been resolved.
*
- * /sa {Qt Data Visualization Data Handling}
+ * Mapping ignores rows and columns of the QAbstractItemModel and treats
+ * all items equally. It requires the model to provide at least three roles for the data items
+ * that can be mapped to X, Y, and Z-values for the scatter points.
+ *
+ * For example, assume that you have a custom QAbstractItemModel for storing various measurements
+ * done on material samples, providing data for roles such as "density", "hardness", and
+ * "conductivity". You could visualize these properties on a scatter graph using this proxy:
+ *
+ * \snippet doc_src_qtdatavisualization.cpp 4
+ *
+ * \sa {Qt Data Visualization Data Handling}
*/
/*!
@@ -51,11 +61,13 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
* The data is resolved asynchronously whenever the mapping or the model changes.
* QScatterDataProxy::arrayReset() is emitted when the data has been resolved.
*
+ * For more details, see QItemModelScatterDataProxy documentation.
+ *
* Usage example:
*
* \snippet doc_src_qmldatavisualization.cpp 8
*
- * \sa ScatterDataProxy, ScatterDataMapping, {Qt Data Visualization Data Handling}
+ * \sa ScatterDataProxy, {Qt Data Visualization Data Handling}
*/
/*!
@@ -64,29 +76,59 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*/
/*!
- * \qmlproperty list ItemModelScatterDataProxy::activeMapping
- * The active mapping. Modifying a mapping that is set to the proxy will trigger data set
- * re-resolving.
+ * \qmlproperty string ItemModelScatterDataProxy::xPosRole
+ * The X position role of the mapping.
*/
/*!
- * Constructs QItemModelScatterDataProxy.
+ * \qmlproperty string ItemModelScatterDataProxy::yPosRole
+ * The Y position role of the mapping.
*/
-QItemModelScatterDataProxy::QItemModelScatterDataProxy() :
- QScatterDataProxy(new QItemModelScatterDataProxyPrivate(this))
+
+/*!
+ * \qmlproperty string ItemModelScatterDataProxy::zPosRole
+ * The Z position role of the mapping.
+ */
+
+/*!
+ * Constructs QItemModelScatterDataProxy with optional \a parent.
+ */
+QItemModelScatterDataProxy::QItemModelScatterDataProxy(QObject *parent)
+ : QScatterDataProxy(new QItemModelScatterDataProxyPrivate(this), parent)
{
+ dptr()->connectItemModelHandler();
}
/*!
- * Constructs QItemModelScatterDataProxy with \a itemModel and \a mapping. Does not take ownership
- * of the model or the mapping, but does connect to them to listen for changes.
+ * Constructs QItemModelScatterDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
+ * ownership of the \a itemModel, as typically item models are owned by other controls.
*/
QItemModelScatterDataProxy::QItemModelScatterDataProxy(const QAbstractItemModel *itemModel,
- QItemModelScatterDataMapping *mapping) :
- QScatterDataProxy(new QItemModelScatterDataProxyPrivate(this))
+ QObject *parent)
+ : QScatterDataProxy(new QItemModelScatterDataProxyPrivate(this), parent)
{
dptr()->m_itemModelHandler->setItemModel(itemModel);
- dptr()->m_itemModelHandler->setActiveMapping(mapping);
+ dptr()->connectItemModelHandler();
+}
+
+/*!
+ * Constructs QItemModelScatterDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
+ * ownership of the \a itemModel, as typically item models are owned by other controls.
+ * The xPosRole property is set to \a xPosRole, yPosRole property to \a yPosRole, and zPosRole property
+ * to \a zPosRole.
+ */
+QItemModelScatterDataProxy::QItemModelScatterDataProxy(const QAbstractItemModel *itemModel,
+ const QString &xPosRole,
+ const QString &yPosRole,
+ const QString &zPosRole,
+ QObject *parent)
+ : QScatterDataProxy(new QItemModelScatterDataProxyPrivate(this), parent)
+{
+ dptr()->m_itemModelHandler->setItemModel(itemModel);
+ dptr()->m_xPosRole = xPosRole;
+ dptr()->m_yPosRole = yPosRole;
+ dptr()->m_zPosRole = zPosRole;
+ dptr()->connectItemModelHandler();
}
/*!
@@ -113,50 +155,68 @@ const QAbstractItemModel *QItemModelScatterDataProxy::itemModel() const
}
/*!
- * \property QItemModelScatterDataProxy::activeMapping
+ * \property QItemModelScatterDataProxy::xPosRole
*
- * Defines the data mapping. The proxy takes ownership of the \a mapping.
- * Modifying a mapping that is set to the proxy will trigger data set re-resolving.
+ * Defines the X position role for the mapping.
*/
-void QItemModelScatterDataProxy::setActiveMapping(QItemModelScatterDataMapping *mapping)
+void QItemModelScatterDataProxy::setXPosRole(const QString &role)
{
- dptr()->m_itemModelHandler->setActiveMapping(mapping);
+ if (dptr()->m_xPosRole != role) {
+ dptr()->m_xPosRole = role;
+ emit xPosRoleChanged(role);
+ }
}
-QItemModelScatterDataMapping *QItemModelScatterDataProxy::activeMapping() const
+QString QItemModelScatterDataProxy::xPosRole() const
{
- return static_cast<QItemModelScatterDataMapping *>(dptrc()->m_itemModelHandler->activeMapping());
+ return dptrc()->m_xPosRole;
}
/*!
- * Transfers the ownership of the \a mapping to this proxy. The mapping is not taken to use yet.
- * \sa setActiveMapping(), releaseMapping()
+ * \property QItemModelScatterDataProxy::yPosRole
+ *
+ * Defines the Y position role for the mapping.
*/
-void QItemModelScatterDataProxy::addMapping(QItemModelScatterDataMapping *mapping)
+void QItemModelScatterDataProxy::setYPosRole(const QString &role)
{
- dptr()->m_itemModelHandler->addMapping(mapping);
+ if (dptr()->m_yPosRole != role) {
+ dptr()->m_yPosRole = role;
+ emit yPosRoleChanged(role);
+ }
+}
+
+QString QItemModelScatterDataProxy::yPosRole() const
+{
+ return dptrc()->m_yPosRole;
}
/*!
- * Releases the ownership of the \a mapping back to the caller. If the mapping was the currently
- * active one, no mapping remains active after this call.
+ * \property QItemModelScatterDataProxy::zPosRole
+ *
+ * Defines the Z position role for the mapping.
*/
-void QItemModelScatterDataProxy::releaseMapping(QItemModelScatterDataMapping *mapping)
+void QItemModelScatterDataProxy::setZPosRole(const QString &role)
{
- dptr()->m_itemModelHandler->releaseMapping(mapping);
+ if (dptr()->m_zPosRole != role) {
+ dptr()->m_zPosRole = role;
+ emit zPosRoleChanged(role);
+ }
+}
+
+QString QItemModelScatterDataProxy::zPosRole() const
+{
+ return dptrc()->m_zPosRole;
}
/*!
- * \return list of mappings owned by the proxy.
+ * Changes \a xPosRole, \a yPosRole and \a zPosRole mapping.
*/
-QList<QItemModelScatterDataMapping *> QItemModelScatterDataProxy::mappings() const
+void QItemModelScatterDataProxy::remap(const QString &xPosRole, const QString &yPosRole,
+ const QString &zPosRole)
{
- QList<QItemModelScatterDataMapping *> retList;
- QList<QAbstractDataMapping *> abstractList = dptrc()->m_itemModelHandler->mappings();
- foreach (QAbstractDataMapping *mapping, abstractList)
- retList.append(static_cast<QItemModelScatterDataMapping *>(mapping));
-
- return retList;
+ setXPosRole(xPosRole);
+ setYPosRole(yPosRole);
+ setZPosRole(zPosRole);
}
/*!
@@ -175,6 +235,18 @@ const QItemModelScatterDataProxyPrivate *QItemModelScatterDataProxy::dptrc() con
return static_cast<const QItemModelScatterDataProxyPrivate *>(d_ptr.data());
}
+void QItemModelScatterDataProxyPrivate::connectItemModelHandler()
+{
+ QObject::connect(m_itemModelHandler, &ScatterItemModelHandler::itemModelChanged,
+ qptr(), &QItemModelScatterDataProxy::itemModelChanged);
+ QObject::connect(qptr(), &QItemModelScatterDataProxy::xPosRoleChanged,
+ m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
+ QObject::connect(qptr(), &QItemModelScatterDataProxy::yPosRoleChanged,
+ m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
+ QObject::connect(qptr(), &QItemModelScatterDataProxy::zPosRoleChanged,
+ m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
+}
+
// QItemModelScatterDataProxyPrivate
QItemModelScatterDataProxyPrivate::QItemModelScatterDataProxyPrivate(QItemModelScatterDataProxy *q)
diff --git a/src/datavisualization/data/qitemmodelscatterdataproxy.h b/src/datavisualization/data/qitemmodelscatterdataproxy.h
index 891950c1..f2a7d78c 100644
--- a/src/datavisualization/data/qitemmodelscatterdataproxy.h
+++ b/src/datavisualization/data/qitemmodelscatterdataproxy.h
@@ -20,7 +20,6 @@
#define QITEMMODELSCATTERDATAPROXY_H
#include <QtDataVisualization/qscatterdataproxy.h>
-#include <QtDataVisualization/qitemmodelscatterdatamapping.h>
#include <QAbstractItemModel>
#include <QStringList>
@@ -31,23 +30,36 @@ class QItemModelScatterDataProxyPrivate;
class QT_DATAVISUALIZATION_EXPORT QItemModelScatterDataProxy : public QScatterDataProxy
{
Q_OBJECT
- Q_PROPERTY(const QAbstractItemModel* itemModel READ itemModel WRITE setItemModel)
- Q_PROPERTY(QItemModelScatterDataMapping* activeMapping READ activeMapping WRITE setActiveMapping)
+ Q_PROPERTY(const QAbstractItemModel* itemModel READ itemModel WRITE setItemModel NOTIFY itemModelChanged)
+ Q_PROPERTY(QString xPosRole READ xPosRole WRITE setXPosRole NOTIFY xPosRoleChanged)
+ Q_PROPERTY(QString yPosRole READ yPosRole WRITE setYPosRole NOTIFY yPosRoleChanged)
+ Q_PROPERTY(QString zPosRole READ zPosRole WRITE setZPosRole NOTIFY zPosRoleChanged)
public:
- explicit QItemModelScatterDataProxy();
- explicit QItemModelScatterDataProxy(const QAbstractItemModel *itemModel,
- QItemModelScatterDataMapping *mapping);
+ explicit QItemModelScatterDataProxy(QObject *parent = 0);
+ QItemModelScatterDataProxy(const QAbstractItemModel *itemModel, QObject *parent = 0);
+ QItemModelScatterDataProxy(const QAbstractItemModel *itemModel,
+ const QString &xPosRole, const QString &yPosRole,
+ const QString &zPosRole, QObject *parent = 0);
virtual ~QItemModelScatterDataProxy();
void setItemModel(const QAbstractItemModel *itemModel);
const QAbstractItemModel *itemModel() const;
- void setActiveMapping(QItemModelScatterDataMapping *mapping);
- QItemModelScatterDataMapping *activeMapping() const;
- void addMapping(QItemModelScatterDataMapping *mapping);
- void releaseMapping(QItemModelScatterDataMapping *mapping);
- QList<QItemModelScatterDataMapping *> mappings() const;
+ void setXPosRole(const QString &role);
+ QString xPosRole() const;
+ void setYPosRole(const QString &role);
+ QString yPosRole() const;
+ void setZPosRole(const QString &role);
+ QString zPosRole() const;
+
+ void remap(const QString &xPosRole, const QString &yPosRole, const QString &zPosRole);
+
+signals:
+ void itemModelChanged(const QAbstractItemModel* itemModel);
+ void xPosRoleChanged(QString role);
+ void yPosRoleChanged(QString role);
+ void zPosRoleChanged(QString role);
protected:
QItemModelScatterDataProxyPrivate *dptr();
@@ -55,6 +67,8 @@ protected:
private:
Q_DISABLE_COPY(QItemModelScatterDataProxy)
+
+ friend class ScatterItemModelHandler;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/data/qitemmodelscatterdataproxy_p.h b/src/datavisualization/data/qitemmodelscatterdataproxy_p.h
index 854062a3..8c86ef09 100644
--- a/src/datavisualization/data/qitemmodelscatterdataproxy_p.h
+++ b/src/datavisualization/data/qitemmodelscatterdataproxy_p.h
@@ -31,8 +31,6 @@
#include "qitemmodelscatterdataproxy.h"
#include "qscatterdataproxy_p.h"
-#include <QPointer>
-#include <QTimer>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
@@ -45,11 +43,17 @@ public:
QItemModelScatterDataProxyPrivate(QItemModelScatterDataProxy *q);
virtual ~QItemModelScatterDataProxyPrivate();
+ void connectItemModelHandler();
+
private:
QItemModelScatterDataProxy *qptr();
ScatterItemModelHandler *m_itemModelHandler;
+ QString m_xPosRole;
+ QString m_yPosRole;
+ QString m_zPosRole;
+ friend class ScatterItemModelHandler;
friend class QItemModelScatterDataProxy;
};
diff --git a/src/datavisualization/data/qitemmodelsurfacedatamapping.cpp b/src/datavisualization/data/qitemmodelsurfacedatamapping.cpp
deleted file mode 100644
index bfe62c6d..00000000
--- a/src/datavisualization/data/qitemmodelsurfacedatamapping.cpp
+++ /dev/null
@@ -1,411 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use contact form at http://qt.digia.com
-**
-** This file is part of the QtDataVisualization module.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** contact form at http://qt.digia.com
-**
-****************************************************************************/
-
-#include "qitemmodelsurfacedatamapping_p.h"
-
-QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-
-/*!
- * \class QItemModelSurfaceDataMapping
- * \inmodule QtDataVisualization
- * \brief Item model mapping for Q3DSurface.
- * \since Qt Data Visualization 1.0
- *
- * QItemModelSurfaceDataMapping is used to map roles of QAbstractItemModel to rows, columns, and values
- * of Q3DSurface. There are three ways to use QItemModelSurfaceDataMapping:
- *
- * 1) If useModelCategories property is set to true, QItemModelSurfaceDataMapping will map rows and
- * columns of QAbstractItemModel to rows and columns of Q3DSurface, and uses the value returned for
- * Qt::DisplayRole as bar value by default.
- * The value role to be used can be redefined if Qt::DisplayRole is not suitable.
- *
- * 2) For models that do not have data already neatly sorted into rows and columns, such as
- * QAbstractListModel based models, you can define a role from the model to map for each of row,
- * column and value.
- *
- * 3) If you do not want to include all data contained in the model, or the autogenerated rows and
- * columns are not ordered as you wish, you can specify which rows and columns should be included
- * and in which order by defining an explicit list of categories for either or both of rows and
- * columns.
- *
- * For example, assume that you have a custom QAbstractItemModel storing surface topography data.
- * Each item in the model has the roles "longitude", "latitude", and "height". The item model already
- * contains the data properly sorted so that longitudes and latitudes are first encountered in
- * correct order, which enables us to utilize the row and column category autogeneration.
- * You could do the following to display the data in a surface graph:
- *
- * \snippet doc_src_qtdatavisualization.cpp 5
- *
- * \sa QItemModelSurfaceDataProxy, {Qt Data Visualization Data Handling}
- */
-
-/*!
- * \qmltype SurfaceDataMapping
- * \inqmlmodule QtDataVisualization
- * \since QtDataVisualization 1.0
- * \ingroup datavisualization_qml
- * \instantiates QItemModelSurfaceDataMapping
- * \brief Item model mapping for Surface3D.
- *
- * This type is used to map roles of AbstractItemModel to rows, columns, and values of Surface3D.
- * For a more complete description, see QItemModelSurfaceDataMapping.
- *
- * Usage example:
- *
- * \snippet doc_src_qmldatavisualization.cpp 6
- *
- * \sa ItemModelSurfaceDataProxy, {Qt Data Visualization Data Handling}
- */
-
-/*!
- * \qmlproperty string SurfaceDataMapping::rowRole
- * The row role of the mapping.
- */
-
-/*!
- * \qmlproperty string SurfaceDataMapping::columnRole
- * The column role of the mapping.
- */
-
-/*!
- * \qmlproperty string SurfaceDataMapping::valueRole
- * The value role of the mapping.
- */
-
-/*!
- * \qmlproperty list SurfaceDataMapping::rowCategories
- * The row categories of the mapping. Only items with row roles that are found in this list are
- * included when data is resolved. The rows are ordered in the same order as they are in this list.
- */
-
-/*!
- * \qmlproperty list SurfaceDataMapping::columnCategories
- * The column categories of the mapping. Only items with column roles that are found in this list are
- * included when data is resolved. The columns are ordered in the same order as they are in this list.
- */
-
-/*!
- * \qmlproperty list SurfaceDataMapping::useModelCategories
- * When set to true, the mapping ignores row and column roles and categories, and uses
- * the rows and columns from the model instead. Defaults to false.
- */
-
-/*!
- * \qmlproperty list SurfaceDataMapping::autoRowCategories
- * When set to true, the mapping ignores any explicitly set row categories
- * and overwrites them with automatically generated ones whenever the
- * data from model is resolved. Proxy minimum and maximum row values are also
- * autogenerated from data when this is set to true. Defaults to true.
- */
-
-/*!
- * \qmlproperty list SurfaceDataMapping::autoColumnCategories
- * When set to true, the mapping ignores any explicitly set column categories
- * and overwrites them with automatically generated ones whenever the
- * data from model is resolved. Proxy minimum and maximum column values are also
- * autogenerated from data when this is set to true. Defaults to true.
- */
-
-/*!
- * Constructs QItemModelSurfaceDataMapping with the given \a parent.
- */
-QItemModelSurfaceDataMapping::QItemModelSurfaceDataMapping(QObject *parent)
- : QAbstractDataMapping(new QItemModelSurfaceDataMappingPrivate(this), parent)
-{
-}
-
-/*!
- * Constructs QItemModelSurfaceDataMapping with \a valueRole and the given \a parent.
- * This constructor is meant to be used with models that have data properly sorted
- * in rows and columns already, so it also sets useModelCategories property to true.
- */
-QItemModelSurfaceDataMapping::QItemModelSurfaceDataMapping(const QString &valueRole, QObject *parent)
- : QAbstractDataMapping(new QItemModelSurfaceDataMappingPrivate(this), parent)
-{
- dptr()->m_valueRole = valueRole;
- dptr()->m_useModelCategories = true;
-}
-
-/*!
- * Constructs QItemModelSurfaceDataMapping with \a rowRole, \a columnRole, \a valueRole,
- * and the given \a parent.
- */
-QItemModelSurfaceDataMapping::QItemModelSurfaceDataMapping(const QString &rowRole,
- const QString &columnRole,
- const QString &valueRole,
- QObject *parent)
- : QAbstractDataMapping(new QItemModelSurfaceDataMappingPrivate(this), parent)
-{
- dptr()->m_rowRole = rowRole;
- dptr()->m_columnRole = columnRole;
- dptr()->m_valueRole = valueRole;
-}
-
-/*!
- * Constructs QItemModelSurfaceDataMapping with \a rowRole, \a columnRole, \a valueRole,
- * \a rowCategories, \a columnCategories, and the given \a parent. This constructor
- * also sets autoRowCategories and autoColumnCategories to false.
- */
-QItemModelSurfaceDataMapping::QItemModelSurfaceDataMapping(const QString &rowRole,
- const QString &columnRole,
- const QString &valueRole,
- const QStringList &rowCategories,
- const QStringList &columnCategories,
- QObject *parent)
- : QAbstractDataMapping(new QItemModelSurfaceDataMappingPrivate(this), parent)
-{
- dptr()->m_rowRole = rowRole;
- dptr()->m_columnRole = columnRole;
- dptr()->m_valueRole = valueRole;
- dptr()->m_rowCategories = rowCategories;
- dptr()->m_columnCategories = columnCategories;
- dptr()->m_autoRowCategories = false;
- dptr()->m_autoColumnCategories = false;
-}
-
-/*!
- * Destroys QItemModelSurfaceDataMapping.
- */
-QItemModelSurfaceDataMapping::~QItemModelSurfaceDataMapping()
-{
-}
-
-/*!
- * \property QItemModelSurfaceDataMapping::rowRole
- *
- * Defines the row role for the mapping.
- */
-void QItemModelSurfaceDataMapping::setRowRole(const QString &role)
-{
- if (dptr()->m_rowRole != role) {
- dptr()->m_rowRole = role;
- emit mappingChanged();
- }
-}
-
-QString QItemModelSurfaceDataMapping::rowRole() const
-{
- return dptrc()->m_rowRole;
-}
-
-/*!
- * \property QItemModelSurfaceDataMapping::columnRole
- *
- * Defines the column role for the mapping.
- */
-void QItemModelSurfaceDataMapping::setColumnRole(const QString &role)
-{
- if (dptr()->m_columnRole != role) {
- dptr()->m_columnRole = role;
- emit mappingChanged();
- }
-}
-
-QString QItemModelSurfaceDataMapping::columnRole() const
-{
- return dptrc()->m_columnRole;
-}
-
-/*!
- * \property QItemModelSurfaceDataMapping::valueRole
- *
- * Defines the value role for the mapping.
- */
-void QItemModelSurfaceDataMapping::setValueRole(const QString &role)
-{
- if (dptr()->m_valueRole != role) {
- dptr()->m_valueRole = role;
- emit mappingChanged();
- }
-}
-
-QString QItemModelSurfaceDataMapping::valueRole() const
-{
- return dptrc()->m_valueRole;
-}
-
-/*!
- * \property QItemModelSurfaceDataMapping::rowCategories
- *
- * Defines the row categories for the mapping.
- */
-void QItemModelSurfaceDataMapping::setRowCategories(const QStringList &categories)
-{
- if (dptr()->m_rowCategories != categories) {
- dptr()->m_rowCategories = categories;
- emit mappingChanged();
- }
-}
-
-QStringList QItemModelSurfaceDataMapping::rowCategories() const
-{
- return dptrc()->m_rowCategories;
-}
-
-/*!
- * \property QItemModelSurfaceDataMapping::columnCategories
- *
- * Defines the column categories for the mapping.
- */
-void QItemModelSurfaceDataMapping::setColumnCategories(const QStringList &categories)
-{
- if (dptr()->m_columnCategories != categories) {
- dptr()->m_columnCategories = categories;
- emit mappingChanged();
- }
-}
-
-QStringList QItemModelSurfaceDataMapping::columnCategories() const
-{
- return dptrc()->m_columnCategories;
-}
-
-/*!
- * \property QItemModelSurfaceDataMapping::useModelCategories
- *
- * When set to true, the mapping ignores row and column roles and categories, and uses
- * the rows and columns from the model instead. Defaults to false.
- */
-void QItemModelSurfaceDataMapping::setUseModelCategories(bool enable)
-{
- if (dptr()->m_useModelCategories != enable) {
- dptr()->m_useModelCategories = enable;
- emit mappingChanged();
- }
-}
-
-bool QItemModelSurfaceDataMapping::useModelCategories() const
-{
- return dptrc()->m_useModelCategories;
-}
-
-/*!
- * \property QItemModelSurfaceDataMapping::autoRowCategories
- *
- * When set to true, the mapping ignores any explicitly set row categories
- * and overwrites them with automatically generated ones whenever the
- * data from model is resolved. Proxy minimum and maximum row values are also
- * autogenerated from data when this is set to true. Defaults to true.
- */
-void QItemModelSurfaceDataMapping::setAutoRowCategories(bool enable)
-{
- if (dptr()->m_autoRowCategories != enable) {
- dptr()->m_autoRowCategories = enable;
- emit mappingChanged();
- }
-}
-
-bool QItemModelSurfaceDataMapping::autoRowCategories() const
-{
- return dptrc()->m_autoRowCategories;
-}
-
-/*!
- * \property QItemModelSurfaceDataMapping::autoColumnCategories
- *
- * When set to true, the mapping ignores any explicitly set column categories
- * and overwrites them with automatically generated ones whenever the
- * data from model is resolved. Proxy minimum and maximum column values are also
- * autogenerated from data when this is set to true. Defaults to true.
- */
-void QItemModelSurfaceDataMapping::setAutoColumnCategories(bool enable)
-{
- if (dptr()->m_autoColumnCategories != enable) {
- dptr()->m_autoColumnCategories = enable;
- emit mappingChanged();
- }
-}
-
-bool QItemModelSurfaceDataMapping::autoColumnCategories() const
-{
- return dptrc()->m_autoColumnCategories;
-}
-
-/*!
- * Changes \a rowRole, \a columnRole, \a valueRole, \a rowCategories and \a columnCategories to the
- * mapping.
- */
-void QItemModelSurfaceDataMapping::remap(const QString &rowRole,
- const QString &columnRole,
- const QString &valueRole,
- const QStringList &rowCategories,
- const QStringList &columnCategories)
-{
- dptr()->m_rowRole = rowRole;
- dptr()->m_columnRole = columnRole;
- dptr()->m_valueRole = valueRole;
- dptr()->m_rowCategories = rowCategories;
- dptr()->m_columnCategories = columnCategories;
-
- emit mappingChanged();
-}
-
-/*!
- * /return index of the specified \a category in row categories list.
- * If the row categories list is empty, -1 is returned.
- * \note If the automatic row categories generation is in use, this method will
- * not return a valid index before the data in the model is resolved for the first time.
- */
-int QItemModelSurfaceDataMapping::rowCategoryIndex(const QString &category)
-{
- return dptr()->m_rowCategories.indexOf(category);
-}
-
-/*!
- * /return index of the specified \a category in column categories list.
- * \note If the automatic column categories generation is in use, this method will
- * not return a valid index before the data in the model is resolved for the first time.
- */
-int QItemModelSurfaceDataMapping::columnCategoryIndex(const QString &category)
-{
- return dptr()->m_columnCategories.indexOf(category);
-}
-
-/*!
- * \internal
- */
-QItemModelSurfaceDataMappingPrivate *QItemModelSurfaceDataMapping::dptr()
-{
- return static_cast<QItemModelSurfaceDataMappingPrivate *>(d_ptr.data());
-}
-
-/*!
- * \internal
- */
-const QItemModelSurfaceDataMappingPrivate *QItemModelSurfaceDataMapping::dptrc() const
-{
- return static_cast<const QItemModelSurfaceDataMappingPrivate *>(d_ptr.data());
-}
-
-// QItemModelSurfaceDataMappingPrivate
-
-QItemModelSurfaceDataMappingPrivate::QItemModelSurfaceDataMappingPrivate(QItemModelSurfaceDataMapping *q)
- : QAbstractDataMappingPrivate(q, QAbstractDataProxy::DataTypeSurface),
- m_useModelCategories(false),
- m_autoRowCategories(true),
- m_autoColumnCategories(true)
-{
-}
-
-QItemModelSurfaceDataMappingPrivate::~QItemModelSurfaceDataMappingPrivate()
-{
-}
-
-
-QT_DATAVISUALIZATION_END_NAMESPACE
-
diff --git a/src/datavisualization/data/qitemmodelsurfacedatamapping.h b/src/datavisualization/data/qitemmodelsurfacedatamapping.h
deleted file mode 100644
index 7e8817bf..00000000
--- a/src/datavisualization/data/qitemmodelsurfacedatamapping.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use contact form at http://qt.digia.com
-**
-** This file is part of the QtDataVisualization module.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** contact form at http://qt.digia.com
-**
-****************************************************************************/
-
-#ifndef QITEMMODELSURFACEDATAMAPPING_H
-#define QITEMMODELSURFACEDATAMAPPING_H
-
-#include <QtDataVisualization/qdatavisualizationenums.h>
-#include <QtDataVisualization/qabstractdatamapping.h>
-#include <QStringList>
-
-QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-
-class QItemModelSurfaceDataMappingPrivate;
-
-class QT_DATAVISUALIZATION_EXPORT QItemModelSurfaceDataMapping : public QAbstractDataMapping
-{
- Q_OBJECT
- Q_PROPERTY(QString rowRole READ rowRole WRITE setRowRole)
- Q_PROPERTY(QString columnRole READ columnRole WRITE setColumnRole)
- Q_PROPERTY(QString valueRole READ valueRole WRITE setValueRole)
- Q_PROPERTY(QStringList rowCategories READ rowCategories WRITE setRowCategories)
- Q_PROPERTY(QStringList columnCategories READ columnCategories WRITE setColumnCategories)
- Q_PROPERTY(bool useModelCategories READ useModelCategories WRITE setUseModelCategories)
- Q_PROPERTY(bool autoRowCategories READ autoRowCategories WRITE setAutoRowCategories)
- Q_PROPERTY(bool autoColumnCategories READ autoColumnCategories WRITE setAutoColumnCategories)
-
-public:
- explicit QItemModelSurfaceDataMapping(QObject *parent = 0);
- QItemModelSurfaceDataMapping(const QString &valueRole, QObject *parent = 0);
- QItemModelSurfaceDataMapping(const QString &rowRole, const QString &columnRole,
- const QString &valueRole, QObject *parent = 0);
- QItemModelSurfaceDataMapping(const QString &rowRole, const QString &columnRole,
- const QString &valueRole, const QStringList &rowCategories,
- const QStringList &columnCategories, QObject *parent = 0);
- virtual ~QItemModelSurfaceDataMapping();
-
- void setRowRole(const QString &role);
- QString rowRole() const;
- void setColumnRole(const QString &role);
- QString columnRole() const;
- void setValueRole(const QString &role);
- QString valueRole() const;
-
- void setRowCategories(const QStringList &categories);
- QStringList rowCategories() const;
- void setColumnCategories(const QStringList &categories);
- QStringList columnCategories() const;
-
- void setUseModelCategories(bool enable);
- bool useModelCategories() const;
- void setAutoRowCategories(bool enable);
- bool autoRowCategories() const;
- void setAutoColumnCategories(bool enable);
- bool autoColumnCategories() const;
-
- void remap(const QString &rowRole, const QString &columnRole,
- const QString &valueRole, const QStringList &rowCategories,
- const QStringList &columnCategories);
-
- Q_INVOKABLE int rowCategoryIndex(const QString& category);
- Q_INVOKABLE int columnCategoryIndex(const QString& category);
-
-protected:
- QItemModelSurfaceDataMappingPrivate *dptr();
- const QItemModelSurfaceDataMappingPrivate *dptrc() const;
-
-private:
- Q_DISABLE_COPY(QItemModelSurfaceDataMapping)
-
- friend class SurfaceItemModelHandler;
-};
-
-QT_DATAVISUALIZATION_END_NAMESPACE
-
-#endif
diff --git a/src/datavisualization/data/qitemmodelsurfacedatamapping_p.h b/src/datavisualization/data/qitemmodelsurfacedatamapping_p.h
deleted file mode 100644
index 9896f868..00000000
--- a/src/datavisualization/data/qitemmodelsurfacedatamapping_p.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use contact form at http://qt.digia.com
-**
-** This file is part of the QtDataVisualization module.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** contact form at http://qt.digia.com
-**
-****************************************************************************/
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the QtDataVisualization 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 "qitemmodelsurfacedatamapping.h"
-#include "qabstractdatamapping_p.h"
-
-#ifndef QITEMMODELSURFACEDATAMAPPING_P_H
-#define QITEMMODELSURFACEDATAMAPPING_P_H
-
-QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-
-class QItemModelSurfaceDataMappingPrivate : public QAbstractDataMappingPrivate
-{
- Q_OBJECT
-public:
- QItemModelSurfaceDataMappingPrivate(QItemModelSurfaceDataMapping *q);
- virtual ~QItemModelSurfaceDataMappingPrivate();
-
-private:
- QString m_rowRole;
- QString m_columnRole;
- QString m_valueRole;
-
- // For row/column items, sort items into these categories. Other categories are ignored.
- QStringList m_rowCategories;
- QStringList m_columnCategories;
-
- bool m_useModelCategories;
- bool m_autoRowCategories;
- bool m_autoColumnCategories;
-
- friend class QItemModelSurfaceDataMapping;
- friend class SurfaceItemModelHandler;
-};
-
-QT_DATAVISUALIZATION_END_NAMESPACE
-
-#endif
diff --git a/src/datavisualization/data/qitemmodelsurfacedataproxy.cpp b/src/datavisualization/data/qitemmodelsurfacedataproxy.cpp
index d3f0f076..191e0d7f 100644
--- a/src/datavisualization/data/qitemmodelsurfacedataproxy.cpp
+++ b/src/datavisualization/data/qitemmodelsurfacedataproxy.cpp
@@ -31,12 +31,37 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
* \since Qt Data Visualization 1.0
*
* QItemModelSurfaceDataProxy allows you to use QAbstractItemModel derived models as a data source
- * for Q3DSurface. It maps roles defined in QItemModelSurfaceDataMapping to roles in the model.
+ * for Q3DSurface. It uses the defined mappings to map data from the model to rows, columns, and
+ * values of Q3DSurface graph.
*
* Data is resolved asynchronously whenever the mapping or the model changes.
* QSurfaceDataProxy::arrayReset() is emitted when the data has been resolved.
*
- * /sa {Qt Data Visualization Data Handling}
+ * There are three ways to use mappings:
+ *
+ * 1) If useModelCategories property is set to true, this proxy will map rows and
+ * columns of QAbstractItemModel to rows and columns of Q3DSurface, and uses the value returned for
+ * Qt::DisplayRole as bar value by default.
+ * The value role to be used can be redefined if Qt::DisplayRole is not suitable.
+ *
+ * 2) For models that do not have data already neatly sorted into rows and columns, such as
+ * QAbstractListModel based models, you can define a role from the model to map for each of row,
+ * column and value.
+ *
+ * 3) If you do not want to include all data contained in the model, or the autogenerated rows and
+ * columns are not ordered as you wish, you can specify which rows and columns should be included
+ * and in which order by defining an explicit list of categories for either or both of rows and
+ * columns.
+ *
+ * For example, assume that you have a custom QAbstractItemModel storing surface topography data.
+ * Each item in the model has the roles "longitude", "latitude", and "height". The item model already
+ * contains the data properly sorted so that longitudes and latitudes are first encountered in
+ * correct order, which enables us to utilize the row and column category autogeneration.
+ * You could do the following to display the data in a surface graph:
+ *
+ * \snippet doc_src_qtdatavisualization.cpp 5
+ *
+ * \sa {Qt Data Visualization Data Handling}
*/
/*!
@@ -53,11 +78,13 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
* Data is resolved asynchronously whenever the mapping or the model changes.
* QSurfaceDataProxy::arrayReset() is emitted when the data has been resolved.
*
+ * For more details, see QItemModelSurfaceDataProxy documentation.
+ *
* Usage example:
*
* \snippet doc_src_qmldatavisualization.cpp 9
*
- * \sa SurfaceDataProxy, SurfaceDataMapping, {Qt Data Visualization Data Handling}
+ * \sa SurfaceDataProxy, {Qt Data Visualization Data Handling}
*/
/*!
@@ -66,29 +93,140 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*/
/*!
- * \qmlproperty list ItemModelSurfaceDataProxy::activeMapping
- * The active mapping. Modifying a mapping that is set to the proxy will trigger data set
- * re-resolving.
+ * \qmlproperty string ItemModelSurfaceDataProxy::rowRole
+ * The row role of the mapping.
+ * In addition to defining which row the data belongs to, the value indicated by row role
+ * is also set as the Z-coordinate value of the QSurfaceDataItem when model data is resolved.
*/
/*!
- * Constructs QItemModelSurfaceDataProxy.
+ * \qmlproperty string ItemModelSurfaceDataProxy::columnRole
+ * The column role of the mapping.
+ * In addition to defining which column the data belongs to, the value indicated by column role
+ * is also set as the X-coordinate value of the QSurfaceDataItem when model data is resolved.
*/
-QItemModelSurfaceDataProxy::QItemModelSurfaceDataProxy() :
- QSurfaceDataProxy(new QItemModelSurfaceDataProxyPrivate(this))
+
+/*!
+ * \qmlproperty string ItemModelSurfaceDataProxy::valueRole
+ * The value role of the mapping.
+ * The value indicated by value role is set as Y-coodrinate value of the
+ * QSurfaceDataItem when model data is resolved.
+ */
+
+/*!
+ * \qmlproperty list ItemModelSurfaceDataProxy::rowCategories
+ * The row categories of the mapping. Only items with row roles that are found in this list are
+ * included when data is resolved. The rows are ordered in the same order as they are in this list.
+ */
+
+/*!
+ * \qmlproperty list ItemModelSurfaceDataProxy::columnCategories
+ * The column categories of the mapping. Only items with column roles that are found in this list are
+ * included when data is resolved. The columns are ordered in the same order as they are in this list.
+ */
+
+/*!
+ * \qmlproperty list ItemModelSurfaceDataProxy::useModelCategories
+ * When set to true, the mapping ignores row and column roles and categories, and uses
+ * the rows and columns from the model instead. Defaults to false.
+ */
+
+/*!
+ * \qmlproperty list ItemModelSurfaceDataProxy::autoRowCategories
+ * When set to true, the mapping ignores any explicitly set row categories
+ * and overwrites them with automatically generated ones whenever the
+ * data from model is resolved. Proxy minimum and maximum row values are also
+ * autogenerated from data when this is set to true. Defaults to true.
+ */
+
+/*!
+ * \qmlproperty list ItemModelSurfaceDataProxy::autoColumnCategories
+ * When set to true, the mapping ignores any explicitly set column categories
+ * and overwrites them with automatically generated ones whenever the
+ * data from model is resolved. Proxy minimum and maximum column values are also
+ * autogenerated from data when this is set to true. Defaults to true.
+ */
+
+/*!
+ * Constructs QItemModelSurfaceDataProxy with optional \a parent.
+ */
+QItemModelSurfaceDataProxy::QItemModelSurfaceDataProxy(QObject *parent)
+ : QSurfaceDataProxy(new QItemModelSurfaceDataProxyPrivate(this), parent)
{
+ dptr()->connectItemModelHandler();
}
/*!
- * Constructs QItemModelSurfaceDataProxy with \a itemModel and \a mapping. Does not take ownership
- * of the model or the mapping, but does connect to them to listen for changes.
+ * Constructs QItemModelSurfaceDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
+ * ownership of the \a itemModel, as typically item models are owned by other controls.
+ */
+QItemModelSurfaceDataProxy::QItemModelSurfaceDataProxy(const QAbstractItemModel *itemModel, QObject *parent)
+ : QSurfaceDataProxy(new QItemModelSurfaceDataProxyPrivate(this), parent)
+{
+ dptr()->m_itemModelHandler->setItemModel(itemModel);
+ dptr()->connectItemModelHandler();
+}
+
+/*!
+ * Constructs QItemModelSurfaceDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
+ * ownership of the \a itemModel, as typically item models are owned by other controls.
+ * The value role is set to \a valueRole.
+ * This constructor is meant to be used with models that have data properly sorted
+ * in rows and columns already, so it also sets useModelCategories property to true.
+ */
+QItemModelSurfaceDataProxy::QItemModelSurfaceDataProxy(const QAbstractItemModel *itemModel,
+ const QString &valueRole, QObject *parent)
+ : QSurfaceDataProxy(new QItemModelSurfaceDataProxyPrivate(this), parent)
+{
+ dptr()->m_itemModelHandler->setItemModel(itemModel);
+ dptr()->m_valueRole = valueRole;
+ dptr()->m_useModelCategories = true;
+ dptr()->connectItemModelHandler();
+}
+
+/*!
+ * Constructs QItemModelSurfaceDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
+ * ownership of the \a itemModel, as typically item models are owned by other controls.
+ * The role mappings are set with \a rowRole, \a columnRole, and \a valueRole.
+ */
+QItemModelSurfaceDataProxy::QItemModelSurfaceDataProxy(const QAbstractItemModel *itemModel,
+ const QString &rowRole,
+ const QString &columnRole,
+ const QString &valueRole, QObject *parent)
+ : QSurfaceDataProxy(new QItemModelSurfaceDataProxyPrivate(this), parent)
+{
+ dptr()->m_itemModelHandler->setItemModel(itemModel);
+ dptr()->m_rowRole = rowRole;
+ dptr()->m_columnRole = columnRole;
+ dptr()->m_valueRole = valueRole;
+ dptr()->connectItemModelHandler();
+}
+
+/*!
+ * Constructs QItemModelSurfaceDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
+ * ownership of the \a itemModel, as typically item models are owned by other controls.
+ * The role mappings are set with \a rowRole, \a columnRole, and \a valueRole.
+ * Row and column categories are set with \a rowCategories and \a columnCategories.
+ * This constructor also sets autoRowCategories and autoColumnCategories to false.
*/
QItemModelSurfaceDataProxy::QItemModelSurfaceDataProxy(const QAbstractItemModel *itemModel,
- QItemModelSurfaceDataMapping *mapping) :
- QSurfaceDataProxy(new QItemModelSurfaceDataProxyPrivate(this))
+ const QString &rowRole,
+ const QString &columnRole,
+ const QString &valueRole,
+ const QStringList &rowCategories,
+ const QStringList &columnCategories,
+ QObject *parent)
+ : QSurfaceDataProxy(new QItemModelSurfaceDataProxyPrivate(this), parent)
{
dptr()->m_itemModelHandler->setItemModel(itemModel);
- dptr()->m_itemModelHandler->setActiveMapping(mapping);
+ dptr()->m_rowRole = rowRole;
+ dptr()->m_columnRole = columnRole;
+ dptr()->m_valueRole = valueRole;
+ dptr()->m_rowCategories = rowCategories;
+ dptr()->m_columnCategories = columnCategories;
+ dptr()->m_autoRowCategories = false;
+ dptr()->m_autoColumnCategories = false;
+ dptr()->connectItemModelHandler();
}
/*!
@@ -115,50 +253,191 @@ const QAbstractItemModel *QItemModelSurfaceDataProxy::itemModel() const
}
/*!
- * \property QItemModelSurfaceDataProxy::activeMapping
+ * \property QItemModelSurfaceDataProxy::rowRole
*
- * Defines data mapping. Proxy takes ownership of the \a mapping.
- * Modifying a mapping that is set to the proxy will trigger data set re-resolving.
+ * Defines the row role for the mapping.
*/
-void QItemModelSurfaceDataProxy::setActiveMapping(QItemModelSurfaceDataMapping *mapping)
+void QItemModelSurfaceDataProxy::setRowRole(const QString &role)
{
- dptr()->m_itemModelHandler->setActiveMapping(mapping);
+ if (dptr()->m_rowRole != role) {
+ dptr()->m_rowRole = role;
+ emit rowRoleChanged(role);
+ }
}
-QItemModelSurfaceDataMapping *QItemModelSurfaceDataProxy::activeMapping() const
+QString QItemModelSurfaceDataProxy::rowRole() const
{
- return static_cast<QItemModelSurfaceDataMapping *>(dptrc()->m_itemModelHandler->activeMapping());
+ return dptrc()->m_rowRole;
}
/*!
- * Transfers the ownership of the \a mapping to this proxy. The mapping is not taken to use yet.
- * \sa setActiveMapping(), releaseMapping()
+ * \property QItemModelSurfaceDataProxy::columnRole
+ *
+ * Defines the column role for the mapping.
*/
-void QItemModelSurfaceDataProxy::addMapping(QItemModelSurfaceDataMapping *mapping)
+void QItemModelSurfaceDataProxy::setColumnRole(const QString &role)
+{
+ if (dptr()->m_columnRole != role) {
+ dptr()->m_columnRole = role;
+ emit columnRoleChanged(role);
+ }
+}
+
+QString QItemModelSurfaceDataProxy::columnRole() const
{
- dptr()->m_itemModelHandler->addMapping(mapping);
+ return dptrc()->m_columnRole;
}
/*!
- * Releases the ownership of the \a mapping back to the caller. If the mapping was the currently
- * active one, no mapping remains active after this call.
+ * \property QItemModelSurfaceDataProxy::valueRole
+ *
+ * Defines the value role for the mapping.
*/
-void QItemModelSurfaceDataProxy::releaseMapping(QItemModelSurfaceDataMapping *mapping)
+void QItemModelSurfaceDataProxy::setValueRole(const QString &role)
{
- dptr()->m_itemModelHandler->releaseMapping(mapping);
+ if (dptr()->m_valueRole != role) {
+ dptr()->m_valueRole = role;
+ emit valueRoleChanged(role);
+ }
+}
+
+QString QItemModelSurfaceDataProxy::valueRole() const
+{
+ return dptrc()->m_valueRole;
}
/*!
- * \return list of mappings owned by the proxy.
+ * \property QItemModelSurfaceDataProxy::rowCategories
+ *
+ * Defines the row categories for the mapping.
*/
-QList<QItemModelSurfaceDataMapping *> QItemModelSurfaceDataProxy::mappings() const
+void QItemModelSurfaceDataProxy::setRowCategories(const QStringList &categories)
{
- QList<QItemModelSurfaceDataMapping *> retList;
- QList<QAbstractDataMapping *> abstractList = dptrc()->m_itemModelHandler->mappings();
- foreach (QAbstractDataMapping *mapping, abstractList)
- retList.append(static_cast<QItemModelSurfaceDataMapping *>(mapping));
+ if (dptr()->m_rowCategories != categories) {
+ dptr()->m_rowCategories = categories;
+ emit rowCategoriesChanged(categories);
+ }
+}
+
+QStringList QItemModelSurfaceDataProxy::rowCategories() const
+{
+ return dptrc()->m_rowCategories;
+}
+
+/*!
+ * \property QItemModelSurfaceDataProxy::columnCategories
+ *
+ * Defines the column categories for the mapping.
+ */
+void QItemModelSurfaceDataProxy::setColumnCategories(const QStringList &categories)
+{
+ if (dptr()->m_columnCategories != categories) {
+ dptr()->m_columnCategories = categories;
+ emit columnCategoriesChanged(categories);
+ }
+}
+
+QStringList QItemModelSurfaceDataProxy::columnCategories() const
+{
+ return dptrc()->m_columnCategories;
+}
+
+/*!
+ * \property QItemModelSurfaceDataProxy::useModelCategories
+ *
+ * When set to true, the mapping ignores row and column roles and categories, and uses
+ * the rows and columns from the model instead. Defaults to false.
+ */
+void QItemModelSurfaceDataProxy::setUseModelCategories(bool enable)
+{
+ if (dptr()->m_useModelCategories != enable) {
+ dptr()->m_useModelCategories = enable;
+ emit useModelCategoriesChanged(enable);
+ }
+}
+
+bool QItemModelSurfaceDataProxy::useModelCategories() const
+{
+ return dptrc()->m_useModelCategories;
+}
+
+/*!
+ * \property QItemModelSurfaceDataProxy::autoRowCategories
+ *
+ * When set to true, the mapping ignores any explicitly set row categories
+ * and overwrites them with automatically generated ones whenever the
+ * data from model is resolved. Defaults to true.
+ */
+void QItemModelSurfaceDataProxy::setAutoRowCategories(bool enable)
+{
+ if (dptr()->m_autoRowCategories != enable) {
+ dptr()->m_autoRowCategories = enable;
+ emit autoRowCategoriesChanged(enable);
+ }
+}
- return retList;
+bool QItemModelSurfaceDataProxy::autoRowCategories() const
+{
+ return dptrc()->m_autoRowCategories;
+}
+
+/*!
+ * \property QItemModelSurfaceDataProxy::autoColumnCategories
+ *
+ * When set to true, the mapping ignores any explicitly set column categories
+ * and overwrites them with automatically generated ones whenever the
+ * data from model is resolved. Defaults to true.
+ */
+void QItemModelSurfaceDataProxy::setAutoColumnCategories(bool enable)
+{
+ if (dptr()->m_autoColumnCategories != enable) {
+ dptr()->m_autoColumnCategories = enable;
+ emit autoColumnCategoriesChanged(enable);
+ }
+}
+
+bool QItemModelSurfaceDataProxy::autoColumnCategories() const
+{
+ return dptrc()->m_autoColumnCategories;
+}
+
+/*!
+ * Changes \a rowRole, \a columnRole, \a valueRole, \a rowCategories and \a columnCategories to the
+ * mapping.
+ */
+void QItemModelSurfaceDataProxy::remap(const QString &rowRole,
+ const QString &columnRole,
+ const QString &valueRole,
+ const QStringList &rowCategories,
+ const QStringList &columnCategories)
+{
+ setRowRole(rowRole);
+ setColumnRole(columnRole);
+ setValueRole(valueRole);
+ setRowCategories(rowCategories);
+ setColumnCategories(columnCategories);
+}
+
+/*!
+ * /return index of the specified \a category in row categories list.
+ * If the row categories list is empty, -1 is returned.
+ * \note If the automatic row categories generation is in use, this method will
+ * not return a valid index before the data in the model is resolved for the first time.
+ */
+int QItemModelSurfaceDataProxy::rowCategoryIndex(const QString &category)
+{
+ return dptr()->m_rowCategories.indexOf(category);
+}
+
+/*!
+ * /return index of the specified \a category in column categories list.
+ * If the category is not found, -1 is returned.
+ * \note If the automatic column categories generation is in use, this method will
+ * not return a valid index before the data in the model is resolved for the first time.
+ */
+int QItemModelSurfaceDataProxy::columnCategoryIndex(const QString &category)
+{
+ return dptr()->m_columnCategories.indexOf(category);
}
/*!
@@ -177,11 +456,36 @@ const QItemModelSurfaceDataProxyPrivate *QItemModelSurfaceDataProxy::dptrc() con
return static_cast<const QItemModelSurfaceDataProxyPrivate *>(d_ptr.data());
}
+void QItemModelSurfaceDataProxyPrivate::connectItemModelHandler()
+{
+ QObject::connect(m_itemModelHandler, &SurfaceItemModelHandler::itemModelChanged,
+ qptr(), &QItemModelSurfaceDataProxy::itemModelChanged);
+ QObject::connect(qptr(), &QItemModelSurfaceDataProxy::rowRoleChanged,
+ m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
+ QObject::connect(qptr(), &QItemModelSurfaceDataProxy::columnRoleChanged,
+ m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
+ QObject::connect(qptr(), &QItemModelSurfaceDataProxy::valueRoleChanged,
+ m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
+ QObject::connect(qptr(), &QItemModelSurfaceDataProxy::rowCategoriesChanged,
+ m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
+ QObject::connect(qptr(), &QItemModelSurfaceDataProxy::columnCategoriesChanged,
+ m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
+ QObject::connect(qptr(), &QItemModelSurfaceDataProxy::useModelCategoriesChanged,
+ m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
+ QObject::connect(qptr(), &QItemModelSurfaceDataProxy::autoRowCategoriesChanged,
+ m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
+ QObject::connect(qptr(), &QItemModelSurfaceDataProxy::autoColumnCategoriesChanged,
+ m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
+}
+
// QItemModelSurfaceDataProxyPrivate
QItemModelSurfaceDataProxyPrivate::QItemModelSurfaceDataProxyPrivate(QItemModelSurfaceDataProxy *q)
: QSurfaceDataProxyPrivate(q),
- m_itemModelHandler(new SurfaceItemModelHandler(q))
+ m_itemModelHandler(new SurfaceItemModelHandler(q)),
+ m_useModelCategories(false),
+ m_autoRowCategories(true),
+ m_autoColumnCategories(true)
{
}
diff --git a/src/datavisualization/data/qitemmodelsurfacedataproxy.h b/src/datavisualization/data/qitemmodelsurfacedataproxy.h
index 080bf54b..ee6b4d99 100644
--- a/src/datavisualization/data/qitemmodelsurfacedataproxy.h
+++ b/src/datavisualization/data/qitemmodelsurfacedataproxy.h
@@ -20,7 +20,6 @@
#define QITEMMODELSURFACEDATAPROXY_H
#include <QtDataVisualization/qsurfacedataproxy.h>
-#include <QtDataVisualization/qitemmodelsurfacedatamapping.h>
#include <QAbstractItemModel>
#include <QStringList>
@@ -31,23 +30,69 @@ class QItemModelSurfaceDataProxyPrivate;
class QT_DATAVISUALIZATION_EXPORT QItemModelSurfaceDataProxy : public QSurfaceDataProxy
{
Q_OBJECT
- Q_PROPERTY(const QAbstractItemModel* itemModel READ itemModel WRITE setItemModel)
- Q_PROPERTY(QItemModelSurfaceDataMapping* activeMapping READ activeMapping WRITE setActiveMapping)
+ Q_PROPERTY(const QAbstractItemModel* itemModel READ itemModel WRITE setItemModel NOTIFY itemModelChanged)
+ Q_PROPERTY(QString rowRole READ rowRole WRITE setRowRole NOTIFY rowRoleChanged)
+ Q_PROPERTY(QString columnRole READ columnRole WRITE setColumnRole NOTIFY columnRoleChanged)
+ Q_PROPERTY(QString valueRole READ valueRole WRITE setValueRole NOTIFY valueRoleChanged)
+ Q_PROPERTY(QStringList rowCategories READ rowCategories WRITE setRowCategories NOTIFY rowCategoriesChanged)
+ Q_PROPERTY(QStringList columnCategories READ columnCategories WRITE setColumnCategories NOTIFY columnCategoriesChanged)
+ Q_PROPERTY(bool useModelCategories READ useModelCategories WRITE setUseModelCategories NOTIFY useModelCategoriesChanged)
+ Q_PROPERTY(bool autoRowCategories READ autoRowCategories WRITE setAutoRowCategories NOTIFY autoRowCategoriesChanged)
+ Q_PROPERTY(bool autoColumnCategories READ autoColumnCategories WRITE setAutoColumnCategories NOTIFY autoColumnCategoriesChanged)
public:
- explicit QItemModelSurfaceDataProxy();
- explicit QItemModelSurfaceDataProxy(const QAbstractItemModel *itemModel,
- QItemModelSurfaceDataMapping *mapping);
+ explicit QItemModelSurfaceDataProxy(QObject *parent = 0);
+ QItemModelSurfaceDataProxy(const QAbstractItemModel *itemModel, QObject *parent = 0);
+ QItemModelSurfaceDataProxy(const QAbstractItemModel *itemModel, const QString &valueRole,
+ QObject *parent = 0);
+ QItemModelSurfaceDataProxy(const QAbstractItemModel *itemModel, const QString &rowRole,
+ const QString &columnRole, const QString &valueRole,
+ QObject *parent = 0);
+ QItemModelSurfaceDataProxy(const QAbstractItemModel *itemModel, const QString &rowRole,
+ const QString &columnRole, const QString &valueRole,
+ const QStringList &rowCategories, const QStringList &columnCategories,
+ QObject *parent = 0);
virtual ~QItemModelSurfaceDataProxy();
void setItemModel(const QAbstractItemModel *itemModel);
const QAbstractItemModel *itemModel() const;
- void setActiveMapping(QItemModelSurfaceDataMapping *mapping);
- QItemModelSurfaceDataMapping *activeMapping() const;
- void addMapping(QItemModelSurfaceDataMapping *mapping);
- void releaseMapping(QItemModelSurfaceDataMapping *mapping);
- QList<QItemModelSurfaceDataMapping *> mappings() const;
+ void setRowRole(const QString &role);
+ QString rowRole() const;
+ void setColumnRole(const QString &role);
+ QString columnRole() const;
+ void setValueRole(const QString &role);
+ QString valueRole() const;
+
+ void setRowCategories(const QStringList &categories);
+ QStringList rowCategories() const;
+ void setColumnCategories(const QStringList &categories);
+ QStringList columnCategories() const;
+
+ void setUseModelCategories(bool enable);
+ bool useModelCategories() const;
+ void setAutoRowCategories(bool enable);
+ bool autoRowCategories() const;
+ void setAutoColumnCategories(bool enable);
+ bool autoColumnCategories() const;
+
+ void remap(const QString &rowRole, const QString &columnRole,
+ const QString &valueRole, const QStringList &rowCategories,
+ const QStringList &columnCategories);
+
+ Q_INVOKABLE int rowCategoryIndex(const QString& category);
+ Q_INVOKABLE int columnCategoryIndex(const QString& category);
+
+signals:
+ void itemModelChanged(const QAbstractItemModel* itemModel);
+ void rowRoleChanged(QString role);
+ void columnRoleChanged(QString role);
+ void valueRoleChanged(QString role);
+ void rowCategoriesChanged(QStringList categories);
+ void columnCategoriesChanged(QStringList categories);
+ void useModelCategoriesChanged(bool enable);
+ void autoRowCategoriesChanged(bool enable);
+ void autoColumnCategoriesChanged(bool enable);
protected:
QItemModelSurfaceDataProxyPrivate *dptr();
@@ -55,6 +100,8 @@ protected:
private:
Q_DISABLE_COPY(QItemModelSurfaceDataProxy)
+
+ friend class SurfaceItemModelHandler;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/data/qitemmodelsurfacedataproxy_p.h b/src/datavisualization/data/qitemmodelsurfacedataproxy_p.h
index ff9d13de..e4505c40 100644
--- a/src/datavisualization/data/qitemmodelsurfacedataproxy_p.h
+++ b/src/datavisualization/data/qitemmodelsurfacedataproxy_p.h
@@ -31,8 +31,6 @@
#include "qitemmodelsurfacedataproxy.h"
#include "qsurfacedataproxy_p.h"
-#include <QPointer>
-#include <QTimer>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
@@ -45,11 +43,26 @@ public:
QItemModelSurfaceDataProxyPrivate(QItemModelSurfaceDataProxy *q);
virtual ~QItemModelSurfaceDataProxyPrivate();
+ void connectItemModelHandler();
+
private:
QItemModelSurfaceDataProxy *qptr();
SurfaceItemModelHandler *m_itemModelHandler;
+ QString m_rowRole;
+ QString m_columnRole;
+ QString m_valueRole;
+
+ // For row/column items, sort items into these categories. Other categories are ignored.
+ QStringList m_rowCategories;
+ QStringList m_columnCategories;
+
+ bool m_useModelCategories;
+ bool m_autoRowCategories;
+ bool m_autoColumnCategories;
+
+ friend class SurfaceItemModelHandler;
friend class QItemModelSurfaceDataProxy;
};
diff --git a/src/datavisualization/data/qscatter3dseries.cpp b/src/datavisualization/data/qscatter3dseries.cpp
new file mode 100644
index 00000000..47971f5f
--- /dev/null
+++ b/src/datavisualization/data/qscatter3dseries.cpp
@@ -0,0 +1,302 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#include "qscatter3dseries_p.h"
+#include "scatter3dcontroller_p.h"
+
+QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
+/*!
+ * \class QScatter3DSeries
+ * \inmodule QtDataVisualization
+ * \brief Base series class for Q3DScatter.
+ * \since Qt Data Visualization 1.0
+ *
+ * QScatter3DSeries manages the series specific visual elements, as well as series data
+ * (via data proxy).
+ *
+ * If no data proxy is set explicitly for the series, the series creates a default
+ * proxy. Setting another proxy will destroy the existing proxy and all data added to it.
+ *
+ * QScatter3DSeries supports the following format tags for QAbstract3DSeries::setItemLabelFormat():
+ * \table
+ * \row
+ * \li @xTitle \li Title from X axis
+ * \row
+ * \li @yTitle \li Title from Y axis
+ * \row
+ * \li @zTitle \li Title from Z axis
+ * \row
+ * \li @xLabel \li Item value formatted using the same format the X axis attached to the graph uses,
+ * see \l{Q3DValueAxis::setLabelFormat()} for more information.
+ * \row
+ * \li @yLabel \li Item value formatted using the same format the Y axis attached to the graph uses,
+ * see \l{Q3DValueAxis::setLabelFormat()} for more information.
+ * \row
+ * \li @zLabel \li Item value formatted using the same format the Z axis attached to the graph uses,
+ * see \l{Q3DValueAxis::setLabelFormat()} for more information.
+ * \endtable
+ *
+ * For example:
+ * \snippet doc_src_qtdatavisualization.cpp 1
+ *
+ * \sa {Qt Data Visualization Data Handling}
+ */
+
+/*!
+ * \qmltype Scatter3DSeries
+ * \inqmlmodule QtDataVisualization
+ * \since QtDataVisualization 1.0
+ * \ingroup datavisualization_qml
+ * \instantiates QScatter3DSeries
+ * \inherits Abstract3DSeries
+ * \brief Base series type for Scatter3D.
+ *
+ * This type manages the series specific visual elements, as well as series data
+ * (via data proxy).
+ *
+ * For more complete description, see QScatter3DSeries.
+ *
+ * \sa {Qt Data Visualization Data Handling}
+ */
+
+/*!
+ * \qmlproperty ScatterDataProxy Scatter3DSeries::dataProxy
+ *
+ * This property holds the active data \a proxy. The series assumes ownership of any proxy set to
+ * it and deletes any previously set proxy when a new one is added. The \a proxy cannot be null or
+ * set to another series.
+ */
+
+/*!
+ * \qmlproperty int Scatter3DSeries::selectedItem
+ *
+ * Selects an item at the \a index. The \a index is the index in the data array of the series.
+ * Only one item can be selected at a time.
+ * To clear selection, set invalidSelectionIndex() as the \a index.
+ * If this series is added to a graph, the graph can adjust the selection according to user
+ * interaction or if it becomes invalid. Selecting an item on another added series will also
+ * clear the selection.
+ */
+
+/*!
+ * \qmlproperty float Scatter3DSeries::itemSize
+ *
+ * Set item size for the series. Size must be between 0.0 and 1.0. Setting the size to 0.0
+ * causes item size to be automatically scaled based on combined item count in all the series for
+ * the graph. Preset default is \c 0.0.
+ */
+
+/*!
+ * \qmlmethod int Scatter3DSeries::invalidSelectionIndex()
+ * \return an invalid index for selection. Set this index to selectedItem property if you
+ * want to clear the selection.
+ */
+
+/*!
+ * Constructs QScatter3DSeries with the given \a parent.
+ */
+QScatter3DSeries::QScatter3DSeries(QObject *parent) :
+ QAbstract3DSeries(new QScatter3DSeriesPrivate(this), parent)
+{
+ // Default proxy
+ dptr()->setDataProxy(new QScatterDataProxy);
+}
+
+/*!
+ * Constructs QScatter3DSeries with the given \a dataProxy and the \a parent.
+ */
+QScatter3DSeries::QScatter3DSeries(QScatterDataProxy *dataProxy, QObject *parent) :
+ QAbstract3DSeries(new QScatter3DSeriesPrivate(this), parent)
+{
+ dptr()->setDataProxy(dataProxy);
+}
+
+/*!
+ * \internal
+ */
+QScatter3DSeries::QScatter3DSeries(QScatter3DSeriesPrivate *d, QObject *parent) :
+ QAbstract3DSeries(d, parent)
+{
+}
+
+/*!
+ * Destroys QScatter3DSeries.
+ */
+QScatter3DSeries::~QScatter3DSeries()
+{
+}
+
+/*!
+ * \property QScatter3DSeries::dataProxy
+ *
+ * This property holds the active data \a proxy. The series assumes ownership of any proxy set to
+ * it and deletes any previously set proxy when a new one is added. The \a proxy cannot be null or
+ * set to another series.
+ */
+void QScatter3DSeries::setDataProxy(QScatterDataProxy *proxy)
+{
+ d_ptr->setDataProxy(proxy);
+}
+
+QScatterDataProxy *QScatter3DSeries::dataProxy() const
+{
+ return static_cast<QScatterDataProxy *>(d_ptr->dataProxy());
+}
+
+/*!
+ * \property QScatter3DSeries::selectedItem
+ *
+ * Selects an item at the \a index. The \a index is the index in the data array of the series.
+ * Only one item can be selected at a time.
+ * To clear selection, set invalidSelectionIndex() as the \a index.
+ * If this series is added to a graph, the graph can adjust the selection according to user
+ * interaction or if it becomes invalid. Selecting an item on another added series will also
+ * clear the selection.
+ */
+void QScatter3DSeries::setSelectedItem(int index)
+{
+ // Don't do this in private to avoid loops, as that is used for callback from controller.
+ if (d_ptr->m_controller)
+ static_cast<Scatter3DController *>(d_ptr->m_controller)->setSelectedItem(index, this);
+ else
+ dptr()->setSelectedItem(index);
+}
+
+int QScatter3DSeries::selectedItem() const
+{
+ return dptrc()->m_selectedItem;
+}
+
+/*!
+ * \property QScatter3DSeries::itemSize
+ *
+ * Set item \a size for the series. Size must be between 0.0f and 1.0f. Setting the size to 0.0f
+ * causes item size to be automatically scaled based on combined item count in all the series for
+ * the graph. Preset default is \c 0.0f.
+ */
+void QScatter3DSeries::setItemSize(float size)
+{
+ if (size < 0.0f || size > 1.0f) {
+ qWarning("Invalid size. Valid range for itemSize is 0.0f...1.0f");
+ } else if (size != dptr()->m_itemSize) {
+ dptr()->setItemSize(size);
+ emit itemSizeChanged(size);
+ }
+}
+
+float QScatter3DSeries::itemSize() const
+{
+ return dptrc()->m_itemSize;
+}
+
+/*!
+ * \return an invalid index for selection. Set this index to selectedItem property if you
+ * want to clear the selection.
+ */
+int QScatter3DSeries::invalidSelectionIndex() const
+{
+ return Scatter3DController::invalidSelectionIndex();
+}
+
+/*!
+ * \internal
+ */
+QScatter3DSeriesPrivate *QScatter3DSeries::dptr()
+{
+ return static_cast<QScatter3DSeriesPrivate *>(d_ptr.data());
+}
+
+/*!
+ * \internal
+ */
+const QScatter3DSeriesPrivate *QScatter3DSeries::dptrc() const
+{
+ return static_cast<const QScatter3DSeriesPrivate *>(d_ptr.data());
+}
+
+// QScatter3DSeriesPrivate
+
+QScatter3DSeriesPrivate::QScatter3DSeriesPrivate(QScatter3DSeries *q)
+ : QAbstract3DSeriesPrivate(q, QAbstract3DSeries::SeriesTypeScatter),
+ m_selectedItem(Scatter3DController::invalidSelectionIndex()),
+ m_itemSize(0.0f)
+{
+ m_itemLabelFormat = QStringLiteral("@valueTitle: @valueLabel");
+ m_mesh = QAbstract3DSeries::MeshSphere;
+}
+
+QScatter3DSeriesPrivate::~QScatter3DSeriesPrivate()
+{
+}
+
+QScatter3DSeries *QScatter3DSeriesPrivate::qptr()
+{
+ return static_cast<QScatter3DSeries *>(q_ptr);
+}
+
+void QScatter3DSeriesPrivate::setDataProxy(QAbstractDataProxy *proxy)
+{
+ Q_ASSERT(proxy->type() == QAbstractDataProxy::DataTypeScatter);
+
+ QAbstract3DSeriesPrivate::setDataProxy(proxy);
+
+ emit qptr()->dataProxyChanged(static_cast<QScatterDataProxy *>(proxy));
+}
+
+void QScatter3DSeriesPrivate::connectControllerAndProxy(Abstract3DController *newController)
+{
+ QScatterDataProxy *scatterDataProxy = static_cast<QScatterDataProxy *>(m_dataProxy);
+
+ if (m_controller && scatterDataProxy) {
+ //Disconnect old controller/old proxy
+ QObject::disconnect(scatterDataProxy, 0, m_controller, 0);
+ QObject::disconnect(q_ptr, 0, m_controller, 0);
+ }
+
+ if (newController && scatterDataProxy) {
+ Scatter3DController *controller = static_cast<Scatter3DController *>(newController);
+ QObject::connect(scatterDataProxy, &QScatterDataProxy::arrayReset,
+ controller, &Scatter3DController::handleArrayReset);
+ QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsAdded,
+ controller, &Scatter3DController::handleItemsAdded);
+ QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsChanged,
+ controller, &Scatter3DController::handleItemsChanged);
+ QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsRemoved,
+ controller, &Scatter3DController::handleItemsRemoved);
+ QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsInserted,
+ controller, &Scatter3DController::handleItemsInserted);
+ }
+}
+
+void QScatter3DSeriesPrivate::setSelectedItem(int index)
+{
+ if (index != m_selectedItem) {
+ m_selectedItem = index;
+ emit qptr()->selectedItemChanged(m_selectedItem);
+ }
+}
+
+void QScatter3DSeriesPrivate::setItemSize(float size)
+{
+ m_itemSize = size;
+ if (m_controller)
+ m_controller->markSeriesVisualsDirty();
+}
+
+QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/data/qscatter3dseries.h b/src/datavisualization/data/qscatter3dseries.h
new file mode 100644
index 00000000..1d9abc11
--- /dev/null
+++ b/src/datavisualization/data/qscatter3dseries.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#ifndef QSCATTER3DSERIES_H
+#define QSCATTER3DSERIES_H
+
+#include <QtDataVisualization/qabstract3dseries.h>
+#include <QtDataVisualization/qscatterdataproxy.h>
+
+QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
+class QScatter3DSeriesPrivate;
+
+class QT_DATAVISUALIZATION_EXPORT QScatter3DSeries : public QAbstract3DSeries
+{
+ Q_OBJECT
+ Q_PROPERTY(QScatterDataProxy *dataProxy READ dataProxy WRITE setDataProxy NOTIFY dataProxyChanged)
+ Q_PROPERTY(int selectedItem READ selectedItem WRITE setSelectedItem NOTIFY selectedItemChanged)
+ Q_PROPERTY(float itemSize READ itemSize WRITE setItemSize NOTIFY itemSizeChanged)
+
+public:
+ explicit QScatter3DSeries(QObject *parent = 0);
+ explicit QScatter3DSeries(QScatterDataProxy *dataProxy, QObject *parent = 0);
+ virtual ~QScatter3DSeries();
+
+ void setDataProxy(QScatterDataProxy *proxy);
+ QScatterDataProxy *dataProxy() const;
+
+ void setSelectedItem(int index);
+ int selectedItem() const;
+
+ void setItemSize(float size);
+ float itemSize() const;
+
+ Q_INVOKABLE int invalidSelectionIndex() const;
+
+signals:
+ void dataProxyChanged(QScatterDataProxy *proxy);
+ void selectedItemChanged(int index);
+ void itemSizeChanged(float size);
+
+protected:
+ explicit QScatter3DSeries(QScatter3DSeriesPrivate *d, QObject *parent = 0);
+ QScatter3DSeriesPrivate *dptr();
+ const QScatter3DSeriesPrivate *dptrc() const;
+
+private:
+ Q_DISABLE_COPY(QScatter3DSeries)
+
+ friend class Scatter3DController;
+};
+
+QT_DATAVISUALIZATION_END_NAMESPACE
+
+#endif
diff --git a/src/datavisualization/data/qitemmodelbardatamapping_p.h b/src/datavisualization/data/qscatter3dseries_p.h
index 90a17fdb..a09536c9 100644
--- a/src/datavisualization/data/qitemmodelbardatamapping_p.h
+++ b/src/datavisualization/data/qscatter3dseries_p.h
@@ -26,36 +26,34 @@
//
// We mean it.
-#include "qitemmodelbardatamapping.h"
-#include "qabstractdatamapping_p.h"
+#ifndef QSCATTER3DSERIES_P_H
+#define QSCATTER3DSERIES_P_H
-#ifndef QITEMMODELBARDATAMAPPING_P_H
-#define QITEMMODELBARDATAMAPPING_P_H
+#include "qscatter3dseries.h"
+#include "qabstract3dseries_p.h"
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-class QItemModelBarDataMappingPrivate : public QAbstractDataMappingPrivate
+class QScatter3DSeriesPrivate : public QAbstract3DSeriesPrivate
{
Q_OBJECT
public:
- QItemModelBarDataMappingPrivate(QItemModelBarDataMapping *q);
- virtual ~QItemModelBarDataMappingPrivate();
+ QScatter3DSeriesPrivate(QScatter3DSeries *q);
+ virtual ~QScatter3DSeriesPrivate();
-private:
- QString m_rowRole;
- QString m_columnRole;
- QString m_valueRole;
+ virtual void setDataProxy(QAbstractDataProxy *proxy);
+ virtual void connectControllerAndProxy(Abstract3DController *newController);
- // For row/column items, sort items into these categories. Other categories are ignored.
- QStringList m_rowCategories;
- QStringList m_columnCategories;
+ void setSelectedItem(int index);
+ void setItemSize(float size);
- bool m_useModelCategories;
- bool m_autoRowCategories;
- bool m_autoColumnCategories;
+private:
+ QScatter3DSeries *qptr();
+ int m_selectedItem;
+ float m_itemSize;
- friend class QItemModelBarDataMapping;
- friend class BarItemModelHandler;
+private:
+ friend class QScatter3DSeries;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/data/qscatterdataitem.cpp b/src/datavisualization/data/qscatterdataitem.cpp
index 5c6f1f66..2c0c0d5a 100644
--- a/src/datavisualization/data/qscatterdataitem.cpp
+++ b/src/datavisualization/data/qscatterdataitem.cpp
@@ -72,13 +72,11 @@ QScatterDataItem::~QScatterDataItem()
QScatterDataItem &QScatterDataItem::operator=(const QScatterDataItem &other)
{
m_position = other.m_position;
- //m_size = other.m_size;
if (other.d_ptr)
createExtraData();
else
d_ptr = 0;
- // TODO set extra data
return *this;
}
@@ -123,16 +121,6 @@ QScatterDataItem &QScatterDataItem::operator=(const QScatterDataItem &other)
* \return the Z component of the position of this data item.
*/
-//void QScatterDataItem::setSize(qreal size)
-//{
-// m_size = size;
-//}
-
-//const qreal &QScatterDataItem::size() const
-//{
-// return m_size;
-//}
-
/*!
* \internal
*/
diff --git a/src/datavisualization/data/qscatterdataitem.h b/src/datavisualization/data/qscatterdataitem.h
index 29154259..7992864c 100644
--- a/src/datavisualization/data/qscatterdataitem.h
+++ b/src/datavisualization/data/qscatterdataitem.h
@@ -45,9 +45,6 @@ public:
inline float y() const { return m_position.y(); }
inline float z() const { return m_position.z(); }
- //void setSize(qreal size);
- //qreal size() const;
-
protected:
virtual void createExtraData();
@@ -55,7 +52,6 @@ protected:
private:
QVector3D m_position;
- //qreal m_size;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/data/qscatterdataproxy.cpp b/src/datavisualization/data/qscatterdataproxy.cpp
index c9bd56d7..e0876d64 100644
--- a/src/datavisualization/data/qscatterdataproxy.cpp
+++ b/src/datavisualization/data/qscatterdataproxy.cpp
@@ -18,6 +18,7 @@
#include "qscatterdataproxy.h"
#include "qscatterdataproxy_p.h"
+#include "qscatter3dseries_p.h"
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
@@ -31,29 +32,7 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*
* QScatterDataProxy takes ownership of all QScatterDataArrays and QScatterDataItems passed to it.
*
- * QScatterDataProxy supports the following format tags for QAbstractDataProxy::setItemLabelFormat():
- * \table
- * \row
- * \li @xTitle \li Title from X axis
- * \row
- * \li @yTitle \li Title from Y axis
- * \row
- * \li @zTitle \li Title from Z axis
- * \row
- * \li @xLabel \li Item value formatted using the same format the X axis attached to the graph uses,
- * see \l{Q3DValueAxis::setLabelFormat()} for more information.
- * \row
- * \li @yLabel \li Item value formatted using the same format the Y axis attached to the graph uses,
- * see \l{Q3DValueAxis::setLabelFormat()} for more information.
- * \row
- * \li @zLabel \li Item value formatted using the same format the Z axis attached to the graph uses,
- * see \l{Q3DValueAxis::setLabelFormat()} for more information.
- * \endtable
- *
- * For example:
- * \snippet doc_src_qtdatavisualization.cpp 2
- *
- * /sa {Qt Data Visualization Data Handling}
+ * \sa {Qt Data Visualization Data Handling}
*/
/*!
@@ -80,6 +59,12 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*/
/*!
+ * \qmlproperty Scatter3DSeries ScatterDataProxy::series
+ *
+ * The series this proxy is attached to.
+ */
+
+/*!
* Constructs QScatterDataProxy with the given \a parent.
*/
QScatterDataProxy::QScatterDataProxy(QObject *parent) :
@@ -103,6 +88,16 @@ QScatterDataProxy::~QScatterDataProxy()
}
/*!
+ * \property QScatterDataProxy::series
+ *
+ * The series this proxy is attached to.
+ */
+QScatter3DSeries *QScatterDataProxy::series()
+{
+ return static_cast<QScatter3DSeries *>(d_ptr->series());
+}
+
+/*!
* Takes ownership of the \a newArray. Clears the existing array if the \a newArray is
* different from the existing array. If it's the same array, this just triggers arrayReset()
* signal.
@@ -114,6 +109,7 @@ void QScatterDataProxy::resetArray(QScatterDataArray *newArray)
dptr()->resetArray(newArray);
emit arrayReset();
+ emit itemCountChanged(itemCount());
}
/*!
@@ -143,6 +139,7 @@ int QScatterDataProxy::addItem(const QScatterDataItem &item)
{
int addIndex = dptr()->addItem(item);
emit itemsAdded(addIndex, 1);
+ emit itemCountChanged(itemCount());
return addIndex;
}
@@ -155,6 +152,7 @@ int QScatterDataProxy::addItems(const QScatterDataArray &items)
{
int addIndex = dptr()->addItems(items);
emit itemsAdded(addIndex, items.size());
+ emit itemCountChanged(itemCount());
return addIndex;
}
@@ -166,6 +164,7 @@ void QScatterDataProxy::insertItem(int index, const QScatterDataItem &item)
{
dptr()->insertItem(index, item);
emit itemsInserted(index, 1);
+ emit itemCountChanged(itemCount());
}
/*!
@@ -175,6 +174,7 @@ void QScatterDataProxy::insertItems(int index, const QScatterDataArray &items)
{
dptr()->insertItems(index, items);
emit itemsInserted(index, items.size());
+ emit itemCountChanged(itemCount());
}
/*!
@@ -183,8 +183,12 @@ void QScatterDataProxy::insertItems(int index, const QScatterDataArray &items)
*/
void QScatterDataProxy::removeItems(int index, int removeCount)
{
+ if (index >= dptr()->m_dataArray->size())
+ return;
+
dptr()->removeItems(index, removeCount);
emit itemsRemoved(index, removeCount);
+ emit itemCountChanged(itemCount());
}
/*!
@@ -277,7 +281,6 @@ QScatterDataProxyPrivate::QScatterDataProxyPrivate(QScatterDataProxy *q)
: QAbstractDataProxyPrivate(q, QAbstractDataProxy::DataTypeScatter),
m_dataArray(new QScatterDataArray)
{
- m_itemLabelFormat = QStringLiteral("(@xLabel, @yLabel, @zLabel)");
}
QScatterDataProxyPrivate::~QScatterDataProxyPrivate()
@@ -346,22 +349,63 @@ void QScatterDataProxyPrivate::removeItems(int index, int removeCount)
m_dataArray->remove(index, removeCount);
}
-QVector3D QScatterDataProxyPrivate::limitValues()
+void QScatterDataProxyPrivate::limitValues(QVector3D &minValues, QVector3D &maxValues) const
{
- QVector3D limits;
- for (int i = 0; i < m_dataArray->size(); i++) {
- const QScatterDataItem &item = m_dataArray->at(i);
- float xValue = qAbs(item.position().x());
- if (limits.x() < xValue)
- limits.setX(xValue);
- float yValue = qAbs(item.position().y());
- if (limits.y() < yValue)
- limits.setY(yValue);
- float zValue = qAbs(item.position().z());
- if (limits.z() < zValue)
- limits.setZ(zValue);
+ if (m_dataArray->isEmpty())
+ return;
+
+ const QVector3D &firstPos = m_dataArray->at(0).position();
+
+ float minX = firstPos.x();
+ float maxX = minX;
+ float minY = firstPos.y();
+ float maxY = minY;
+ float minZ = firstPos.z();
+ float maxZ = minZ;
+
+ if (m_dataArray->size() > 1) {
+ for (int i = 1; i < m_dataArray->size(); i++) {
+ const QVector3D &pos = m_dataArray->at(i).position();
+
+ float value = pos.x();
+ if (minX > value)
+ minX = value;
+ if (maxX < value)
+ maxX = value;
+
+ value = pos.y();
+ if (minY > value)
+ minY = value;
+ if (maxY < value)
+ maxY = value;
+
+ value = pos.z();
+ if (minZ > value)
+ minZ = value;
+ if (maxZ < value)
+ maxZ = value;
+ }
}
- return limits;
+
+ minValues.setX(minX);
+ minValues.setY(minY);
+ minValues.setZ(minZ);
+
+ maxValues.setX(maxX);
+ maxValues.setY(maxY);
+ maxValues.setZ(maxZ);
+}
+
+void QScatterDataProxyPrivate::setSeries(QAbstract3DSeries *series)
+{
+ QAbstractDataProxyPrivate::setSeries(series);
+ QScatter3DSeries *scatterSeries = static_cast<QScatter3DSeries *>(series);
+ emit qptr()->seriesChanged(scatterSeries);
+}
+
+QScatterDataProxy *QScatterDataProxyPrivate::qptr()
+{
+ return static_cast<QScatterDataProxy *>(q_ptr);
}
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/data/qscatterdataproxy.h b/src/datavisualization/data/qscatterdataproxy.h
index 178bc900..acb3d3d4 100644
--- a/src/datavisualization/data/qscatterdataproxy.h
+++ b/src/datavisualization/data/qscatterdataproxy.h
@@ -27,25 +27,20 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
typedef QVector<QScatterDataItem> QScatterDataArray;
class QScatterDataProxyPrivate;
+class QScatter3DSeries;
class QT_DATAVISUALIZATION_EXPORT QScatterDataProxy : public QAbstractDataProxy
{
Q_OBJECT
- Q_PROPERTY(int itemCount READ itemCount)
+ Q_PROPERTY(int itemCount READ itemCount NOTIFY itemCountChanged)
+ Q_PROPERTY(QScatter3DSeries *series READ series NOTIFY seriesChanged)
public:
explicit QScatterDataProxy(QObject *parent = 0);
virtual ~QScatterDataProxy();
- // TODO: Replace first part of class description in docs with this once all TODOs are done:
- /*
- * QScatterDataProxy handles adding, inserting, changing and removing data items.
- * QScatterDataProxy is optimized to use cases where the only defining characteristics of an
- * individual scatter item are it's position and size. Modifying other data that might be
- * added in the future such as color requires allocating additional data object for the bar.
- */
-
+ QScatter3DSeries *series();
int itemCount() const;
const QScatterDataArray *array() const;
const QScatterDataItem *itemAt(int index) const;
@@ -70,6 +65,9 @@ signals:
void itemsRemoved(int startIndex, int count);
void itemsInserted(int startIndex, int count);
+ void itemCountChanged(int count);
+ void seriesChanged(QScatter3DSeries *series);
+
protected:
explicit QScatterDataProxy(QScatterDataProxyPrivate *d, QObject *parent = 0);
QScatterDataProxyPrivate *dptr();
diff --git a/src/datavisualization/data/qscatterdataproxy_p.h b/src/datavisualization/data/qscatterdataproxy_p.h
index 9920e3a7..322c8937 100644
--- a/src/datavisualization/data/qscatterdataproxy_p.h
+++ b/src/datavisualization/data/qscatterdataproxy_p.h
@@ -51,9 +51,11 @@ public:
void insertItems(int index, const QScatterDataArray &items);
void removeItems(int index, int removeCount);
- QVector3D limitValues();
+ void limitValues(QVector3D &minValues, QVector3D &maxValues) const;
+ virtual void setSeries(QAbstract3DSeries *series);
private:
+ QScatterDataProxy *qptr();
QScatterDataArray *m_dataArray;
friend class QScatterDataProxy;
diff --git a/src/datavisualization/data/qsurface3dseries.cpp b/src/datavisualization/data/qsurface3dseries.cpp
new file mode 100644
index 00000000..cf794077
--- /dev/null
+++ b/src/datavisualization/data/qsurface3dseries.cpp
@@ -0,0 +1,381 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#include "qsurface3dseries_p.h"
+#include "surface3dcontroller_p.h"
+
+QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
+/*!
+ * \class QSurface3DSeries
+ * \inmodule QtDataVisualization
+ * \brief Base series class for Q3DSurface.
+ * \since Qt Data Visualization 1.0
+ *
+ * QSurface3DSeries manages the series specific visual elements, as well as series data
+ * (via data proxy).
+ *
+ * If no data proxy is set explicitly for the series, the series creates a default
+ * proxy. Setting another proxy will destroy the existing proxy and all data added to it.
+ *
+ * The object mesh set via QAbstract3DSeries::mesh property defines the selection
+ * pointer shape in surface series.
+ *
+ * QSurface3DSeries supports the following format tags for QAbstract3DSeries::setItemLabelFormat():
+ * \table
+ * \row
+ * \li @xTitle \li Title from X axis
+ * \row
+ * \li @yTitle \li Title from Y axis
+ * \row
+ * \li @zTitle \li Title from Z axis
+ * \row
+ * \li @xLabel \li Item value formatted using the same format as the X axis attached to the graph uses,
+ * see \l{Q3DValueAxis::setLabelFormat()} for more information.
+ * \row
+ * \li @yLabel \li Item value formatted using the same format as the Y axis attached to the graph uses,
+ * see \l{Q3DValueAxis::setLabelFormat()} for more information.
+ * \row
+ * \li @zLabel \li Item value formatted using the same format as the Z axis attached to the graph uses,
+ * see \l{Q3DValueAxis::setLabelFormat()} for more information.
+ * \endtable
+ *
+ * For example:
+ * \snippet doc_src_qtdatavisualization.cpp 1
+ *
+ * \sa {Qt Data Visualization Data Handling}
+ */
+
+/*!
+ * \qmltype Surface3DSeries
+ * \inqmlmodule QtDataVisualization
+ * \since QtDataVisualization 1.0
+ * \ingroup datavisualization_qml
+ * \instantiates QSurface3DSeries
+ * \inherits Abstract3DSeries
+ * \brief Base series type for Surfaces3D.
+ *
+ * This type manages the series specific visual elements, as well as series data
+ * (via data proxy).
+ *
+ * For more complete description, see QSurface3DSeries.
+ *
+ * \sa {Qt Data Visualization Data Handling}
+ */
+
+/*!
+ * \qmlproperty SurfaceDataProxy Surface3DSeries::dataProxy
+ *
+ * This property holds the active data \a proxy. The series assumes ownership of any proxy set to
+ * it and deletes any previously set proxy when a new one is added. The \a proxy cannot be null or
+ * set to another series.
+ */
+
+/*!
+ * \qmlproperty point Surface3DSeries::selectedPoint
+ *
+ * Selects a surface grid point in a \a position. The position is the (row, column) position in
+ * the data array of the series.
+ * Only one point can be selected at a time.
+ * To clear selection, set invalidSelectionPosition() as the \a position.
+ * If this series is added to a graph, the graph can adjust the selection according to user
+ * interaction or if it becomes invalid.
+ */
+
+/*!
+ * \qmlmethod point Surface3DSeries::invalidSelectionPosition()
+ * \return a point signifying an invalid selection position. Set this to selectedPoint property
+ * to clear the selection.
+ */
+
+/*!
+ * \qmlproperty bool Surface3DSeries::flatShadingEnabled
+ *
+ * Sets surface flat shading to \a enabled. It is preset to \c true by default.
+ * When disabled, the normals on the surface are interpolated making edges looking round.
+ * When enabled, the normals are kept same on a triangle making the color of the triangle solid.
+ * This makes the data more readable from the model.
+ * \note Flat shaded surfaces require at least GLSL version 1.2 with GL_EXT_gpu_shader4 extension.
+ * The value of flatShadingSupported property indicates if flat shading is supported at runtime.
+ */
+
+/*!
+ * \qmlproperty bool Surface3DSeries::surfaceGridEnabled
+ *
+ * Sets surface grid to \a enabled. It is preset to \c true by default.
+ */
+
+/*!
+ * \qmlproperty bool Surface3DSeries::flatShadingSupported
+ *
+ * Flat shading for surfaces requires at least GLSL version 1.2 with GL_EXT_gpu_shader4 extension.
+ * If true, flat shading for surfaces is supported by current system.
+ * \note This read-only property is set to its correct value after first render pass.
+ * Before then it is always true.
+ */
+
+/*!
+ * \enum QSurface3DSeries::DrawFlag
+ *
+ * Drawing mode of the surface. Values of this enumeration can be combined with OR operator.
+ *
+ * \value DrawWireframe
+ * Only the grid is drawn.
+ * \value DrawSurface
+ * Only the surface is drawn.
+ * \value DrawSurfaceAndWireframe
+ * Both the surface and grid are drawn.
+ */
+
+/*!
+ * Constructs QSurface3DSeries with the given \a parent.
+ */
+QSurface3DSeries::QSurface3DSeries(QObject *parent) :
+ QAbstract3DSeries(new QSurface3DSeriesPrivate(this), parent)
+{
+ // Default proxy
+ dptr()->setDataProxy(new QSurfaceDataProxy);
+}
+
+/*!
+ * Constructs QSurface3DSeries with the given \a dataProxy and the \a parent.
+ */
+QSurface3DSeries::QSurface3DSeries(QSurfaceDataProxy *dataProxy, QObject *parent) :
+ QAbstract3DSeries(new QSurface3DSeriesPrivate(this), parent)
+{
+ dptr()->setDataProxy(dataProxy);
+}
+
+/*!
+ * \internal
+ */
+QSurface3DSeries::QSurface3DSeries(QSurface3DSeriesPrivate *d, QObject *parent) :
+ QAbstract3DSeries(d, parent)
+{
+}
+
+/*!
+ * Destroys QSurface3DSeries.
+ */
+QSurface3DSeries::~QSurface3DSeries()
+{
+}
+
+/*!
+ * \property QSurface3DSeries::dataProxy
+ *
+ * This property holds the active data \a proxy. The series assumes ownership of any proxy set to
+ * it and deletes any previously set proxy when a new one is added. The \a proxy cannot be null or
+ * set to another series.
+ */
+void QSurface3DSeries::setDataProxy(QSurfaceDataProxy *proxy)
+{
+ d_ptr->setDataProxy(proxy);
+}
+
+QSurfaceDataProxy *QSurface3DSeries::dataProxy() const
+{
+ return static_cast<QSurfaceDataProxy *>(d_ptr->dataProxy());
+}
+
+/*!
+ * \property QSurface3DSeries::selectedPoint
+ *
+ * Selects a surface grid point in a \a position. The position is the (row, column) position in
+ * the data array of the series.
+ * Only one point can be selected at a time.
+ * To clear selection, set invalidSelectionPosition() as the \a position.
+ * If this series is added to a graph, the graph can adjust the selection according to user
+ * interaction or if it becomes invalid.
+ */
+void QSurface3DSeries::setSelectedPoint(const QPoint &position)
+{
+ // Don't do this in private to avoid loops, as that is used for callback from controller.
+ if (d_ptr->m_controller)
+ static_cast<Surface3DController *>(d_ptr->m_controller)->setSelectedPoint(position, this);
+ else
+ dptr()->setSelectedPoint(position);
+}
+
+QPoint QSurface3DSeries::selectedPoint() const
+{
+ return dptrc()->m_selectedPoint;
+}
+
+/*!
+ * \return a QPoint signifying an invalid selection position. Set this to selectedPoint property
+ * to clear the selection.
+ */
+QPoint QSurface3DSeries::invalidSelectionPosition() const
+{
+ return Surface3DController::invalidSelectionPosition();
+}
+
+/*!
+ * \property QSurface3DSeries::flatShadingEnabled
+ *
+ * Sets surface flat shading to \a enabled. It is preset to \c true by default.
+ * When disabled, the normals on the surface are interpolated making edges looking round.
+ * When enabled, the normals are kept same on a triangle making the color of the triangle solid.
+ * This makes the data more readable from the model.
+ * \note Flat shaded surfaces require at least GLSL version 1.2 with GL_EXT_gpu_shader4 extension.
+ * The value of flatShadingSupported property indicates if flat shading is supported at runtime.
+ */
+void QSurface3DSeries::setFlatShadingEnabled(bool enabled)
+{
+ if (dptr()->m_flatShadingEnabled != enabled) {
+ dptr()->setFlatShadingEnabled(enabled);
+ emit flatShadingEnabledChanged(enabled);
+ }
+}
+
+bool QSurface3DSeries::isFlatShadingEnabled() const
+{
+ return dptrc()->m_flatShadingEnabled;
+}
+
+/*!
+ * \property QSurface3DSeries::flatShadingSupported
+ * Flat shading for surfaces requires at least GLSL version 1.2 with GL_EXT_gpu_shader4 extension.
+ * If true, flat shading for surfaces is supported by current system.
+ * \note This read-only property is set to its correct value after first render pass.
+ * Before then it is always true.
+ */
+bool QSurface3DSeries::isFlatShadingSupported() const
+{
+ if (d_ptr->m_controller)
+ return static_cast<Surface3DController *>(d_ptr->m_controller)->isFlatShadingSupported();
+ else
+ return true;
+}
+
+/*!
+ * \property QSurface3DSeries::drawMode
+ *
+ * Sets the drawing \a mode to one of QSurface3DSeries::DrawFlag.
+ */
+void QSurface3DSeries::setDrawMode(QSurface3DSeries::DrawFlags mode)
+{
+ if (dptr()->m_drawMode != mode) {
+ dptr()->setDrawMode(mode);
+ emit drawModeChanged(mode);
+ }
+}
+
+QSurface3DSeries::DrawFlags QSurface3DSeries::drawMode() const
+{
+ return dptrc()->m_drawMode;
+}
+
+/*!
+ * \internal
+ */
+QSurface3DSeriesPrivate *QSurface3DSeries::dptr()
+{
+ return static_cast<QSurface3DSeriesPrivate *>(d_ptr.data());
+}
+
+/*!
+ * \internal
+ */
+const QSurface3DSeriesPrivate *QSurface3DSeries::dptrc() const
+{
+ return static_cast<const QSurface3DSeriesPrivate *>(d_ptr.data());
+}
+
+// QSurface3DSeriesPrivate
+
+QSurface3DSeriesPrivate::QSurface3DSeriesPrivate(QSurface3DSeries *q)
+ : QAbstract3DSeriesPrivate(q, QAbstract3DSeries::SeriesTypeSurface),
+ m_selectedPoint(Surface3DController::invalidSelectionPosition()),
+ m_flatShadingEnabled(true),
+ m_drawMode(QSurface3DSeries::DrawSurfaceAndWireframe)
+{
+ m_itemLabelFormat = QStringLiteral("(@xLabel, @yLabel, @zLabel)");
+ m_mesh = QAbstract3DSeries::MeshSphere;
+}
+
+QSurface3DSeriesPrivate::~QSurface3DSeriesPrivate()
+{
+}
+
+QSurface3DSeries *QSurface3DSeriesPrivate::qptr()
+{
+ return static_cast<QSurface3DSeries *>(q_ptr);
+}
+
+void QSurface3DSeriesPrivate::setDataProxy(QAbstractDataProxy *proxy)
+{
+ Q_ASSERT(proxy->type() == QAbstractDataProxy::DataTypeSurface);
+
+ QAbstract3DSeriesPrivate::setDataProxy(proxy);
+
+ emit qptr()->dataProxyChanged(static_cast<QSurfaceDataProxy *>(proxy));
+}
+
+void QSurface3DSeriesPrivate::connectControllerAndProxy(Abstract3DController *newController)
+{
+ QSurfaceDataProxy *surfaceDataProxy = static_cast<QSurfaceDataProxy *>(m_dataProxy);
+
+ if (m_controller && surfaceDataProxy) {
+ //Disconnect old controller/old proxy
+ QObject::disconnect(surfaceDataProxy, 0, m_controller, 0);
+ QObject::disconnect(q_ptr, 0, m_controller, 0);
+ }
+
+ if (newController && surfaceDataProxy) {
+ Surface3DController *controller = static_cast<Surface3DController *>(newController);
+
+ QObject::connect(surfaceDataProxy, &QSurfaceDataProxy::arrayReset, controller,
+ &Surface3DController::handleArrayReset);
+ QObject::connect(surfaceDataProxy, &QSurfaceDataProxy::rowsAdded, controller,
+ &Surface3DController::handleRowsAdded);
+ QObject::connect(surfaceDataProxy, &QSurfaceDataProxy::rowsChanged, controller,
+ &Surface3DController::handleRowsChanged);
+ QObject::connect(surfaceDataProxy, &QSurfaceDataProxy::rowsRemoved, controller,
+ &Surface3DController::handleRowsRemoved);
+ QObject::connect(surfaceDataProxy, &QSurfaceDataProxy::rowsInserted, controller,
+ &Surface3DController::handleRowsInserted);
+ QObject::connect(surfaceDataProxy, &QSurfaceDataProxy::itemChanged, controller,
+ &Surface3DController::handleItemChanged);
+ }
+}
+
+void QSurface3DSeriesPrivate::setSelectedPoint(const QPoint &position)
+{
+ if (position != m_selectedPoint) {
+ m_selectedPoint = position;
+ emit qptr()->selectedPointChanged(m_selectedPoint);
+ }
+}
+
+void QSurface3DSeriesPrivate::setFlatShadingEnabled(bool enabled)
+{
+ m_flatShadingEnabled = enabled;
+ if (m_controller)
+ m_controller->markSeriesVisualsDirty();
+}
+
+void QSurface3DSeriesPrivate::setDrawMode(QSurface3DSeries::DrawFlags mode)
+{
+ m_drawMode = mode;
+ if (m_controller)
+ m_controller->markSeriesVisualsDirty();
+}
+
+QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/data/qsurface3dseries.h b/src/datavisualization/data/qsurface3dseries.h
new file mode 100644
index 00000000..6681495b
--- /dev/null
+++ b/src/datavisualization/data/qsurface3dseries.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#ifndef QSURFACE3DSERIES_H
+#define QSURFACE3DSERIES_H
+
+#include <QtDataVisualization/qabstract3dseries.h>
+#include <QtDataVisualization/qsurfacedataproxy.h>
+
+QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
+class QSurface3DSeriesPrivate;
+
+class QT_DATAVISUALIZATION_EXPORT QSurface3DSeries : public QAbstract3DSeries
+{
+ Q_OBJECT
+ Q_FLAGS(DrawFlag DrawFlags)
+ Q_PROPERTY(QSurfaceDataProxy *dataProxy READ dataProxy WRITE setDataProxy NOTIFY dataProxyChanged)
+ Q_PROPERTY(QPoint selectedPoint READ selectedPoint WRITE setSelectedPoint NOTIFY selectedPointChanged)
+ Q_PROPERTY(bool flatShadingEnabled READ isFlatShadingEnabled WRITE setFlatShadingEnabled NOTIFY flatShadingEnabledChanged)
+ Q_PROPERTY(bool flatShadingSupported READ isFlatShadingSupported NOTIFY flatShadingSupportedChanged)
+ Q_PROPERTY(QtDataVisualization::QSurface3DSeries::DrawFlags drawMode READ drawMode WRITE setDrawMode NOTIFY drawModeChanged)
+
+public:
+ enum DrawFlag {
+ DrawWireframe = 1,
+ DrawSurface = 2,
+ DrawSurfaceAndWireframe = DrawWireframe | DrawSurface
+ };
+ Q_DECLARE_FLAGS(DrawFlags, DrawFlag)
+
+ explicit QSurface3DSeries(QObject *parent = 0);
+ explicit QSurface3DSeries(QSurfaceDataProxy *dataProxy, QObject *parent = 0);
+ virtual ~QSurface3DSeries();
+
+ void setDataProxy(QSurfaceDataProxy *proxy);
+ QSurfaceDataProxy *dataProxy() const;
+
+ void setSelectedPoint(const QPoint &position);
+ QPoint selectedPoint() const;
+ QPoint invalidSelectionPosition() const;
+
+ void setFlatShadingEnabled(bool enabled);
+ bool isFlatShadingEnabled() const;
+
+ void setDrawMode(QSurface3DSeries::DrawFlags mode);
+ QSurface3DSeries::DrawFlags drawMode() const;
+
+ bool isFlatShadingSupported() const;
+
+signals:
+ void dataProxyChanged(QSurfaceDataProxy *proxy);
+ void selectedPointChanged(QPoint position);
+ void flatShadingEnabledChanged(bool enable);
+ void flatShadingSupportedChanged(bool enable);
+ void drawModeChanged(QSurface3DSeries::DrawFlags mode);
+
+protected:
+ explicit QSurface3DSeries(QSurface3DSeriesPrivate *d, QObject *parent = 0);
+ QSurface3DSeriesPrivate *dptr();
+ const QSurface3DSeriesPrivate *dptrc() const;
+
+private:
+ Q_DISABLE_COPY(QSurface3DSeries)
+
+ friend class Surface3DController;
+};
+
+QT_DATAVISUALIZATION_END_NAMESPACE
+
+#endif
diff --git a/src/datavisualization/data/qsurface3dseries_p.h b/src/datavisualization/data/qsurface3dseries_p.h
new file mode 100644
index 00000000..00bfbed2
--- /dev/null
+++ b/src/datavisualization/data/qsurface3dseries_p.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the QtDataVisualization API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef QSURFACE3DSERIES_P_H
+#define QSURFACE3DSERIES_P_H
+
+#include "qsurface3dseries.h"
+#include "qabstract3dseries_p.h"
+
+QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
+class QSurface3DSeriesPrivate : public QAbstract3DSeriesPrivate
+{
+ Q_OBJECT
+public:
+ QSurface3DSeriesPrivate(QSurface3DSeries *q);
+ virtual ~QSurface3DSeriesPrivate();
+
+ virtual void setDataProxy(QAbstractDataProxy *proxy);
+ virtual void connectControllerAndProxy(Abstract3DController *newController);
+
+ void setSelectedPoint(const QPoint &position);
+ void setFlatShadingEnabled(bool enabled);
+ void setDrawMode(QSurface3DSeries::DrawFlags mode);
+
+private:
+ QSurface3DSeries *qptr();
+
+ QPoint m_selectedPoint;
+ bool m_flatShadingEnabled;
+ QSurface3DSeries::DrawFlags m_drawMode;
+
+private:
+ friend class QSurface3DSeries;
+};
+
+QT_DATAVISUALIZATION_END_NAMESPACE
+
+#endif
diff --git a/src/datavisualization/data/qsurfacedataproxy.cpp b/src/datavisualization/data/qsurfacedataproxy.cpp
index 7fe44464..5ea05d75 100644
--- a/src/datavisualization/data/qsurfacedataproxy.cpp
+++ b/src/datavisualization/data/qsurfacedataproxy.cpp
@@ -18,6 +18,7 @@
#include "qsurfacedataproxy.h"
#include "qsurfacedataproxy_p.h"
+#include "qsurface3dseries_p.h"
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
@@ -35,32 +36,23 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*
* All rows must have the same number of items.
*
- * When determining what rows and columns are visible, the first item in each row and the first item in
- * each column determine if the whole row or column is visible, even if other items in the row or column
- * individually have different X- or Z-coordinates.
+ * QSurfaceDataProxy takes ownership of all QSurfaceDataRows passed to it, whether directly or
+ * in a QSurfaceDataArray container.
+ * If you use QSurfaceDataRow pointers to directly modify data after adding the array to the proxy,
+ * you must also emit proper signal to make the graph update.
+ *
+ * To make a sensible surface, the X-value of each successive item in the same row must be greater than the
+ * previous item in that row, and the the Z-value of each successive item in a column must be greater than
+ * the previous item in that column.
+ *
+ * \note In the initial release, only surfaces with straight rows and columns are fully supported. Any row
+ * with items that do not have the exact same Z-value or any columns with items that do not have the exact
+ * same X-value may get clipped incorrectly if the whole surface doesn't fit to the visible X or Z axis
+ * ranges.
*
* \note Surfaces with less than two rows or columns are not considered valid surfaces and will
* not get rendered.
*
- * QSurfaceDataProxy supports the following format tags for QAbstractDataProxy::setItemLabelFormat():
- * \table
- * \row
- * \li @xTitle \li Title from X axis
- * \row
- * \li @yTitle \li Title from Y axis
- * \row
- * \li @zTitle \li Title from Z axis
- * \row
- * \li @xLabel \li Item value formatted using the same format as the X axis attached to the graph uses,
- * see \l{Q3DValueAxis::setLabelFormat()} for more information.
- * \row
- * \li @yLabel \li Item value formatted using the same format as the Y axis attached to the graph uses,
- * see \l{Q3DValueAxis::setLabelFormat()} for more information.
- * \row
- * \li @zLabel \li Item value formatted using the same format as the Z axis attached to the graph uses,
- * see \l{Q3DValueAxis::setLabelFormat()} for more information.
- * \endtable
- *
* \sa {Qt Data Visualization Data Handling}
*/
@@ -94,6 +86,12 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*/
/*!
+ * \qmlproperty Surface3DSeries SurfaceDataProxy::series
+ *
+ * The series this proxy is attached to.
+ */
+
+/*!
* Constructs QSurfaceDataProxy with the given \a parent.
*/
QSurfaceDataProxy::QSurfaceDataProxy(QObject *parent) :
@@ -117,6 +115,16 @@ QSurfaceDataProxy::~QSurfaceDataProxy()
}
/*!
+ * \property QSurfaceDataProxy::series
+ *
+ * The series this proxy is attached to.
+ */
+QSurface3DSeries *QSurfaceDataProxy::series()
+{
+ return static_cast<QSurface3DSeries *>(d_ptr->series());
+}
+
+/*!
* Takes ownership of the \a newArray. Clears the existing array if the \a newArray is
* different from the existing array. If it's the same array, this just triggers arrayReset()
* signal.
@@ -129,6 +137,105 @@ void QSurfaceDataProxy::resetArray(QSurfaceDataArray *newArray)
dptr()->resetArray(newArray);
}
emit arrayReset();
+ emit rowCountChanged(rowCount());
+ emit columnCountChanged(columnCount());
+}
+
+/*!
+ * Changes existing row by replacing a row at \a rowIndex with a new \a row. The \a row can be
+ * the same as the existing row already stored at the \a rowIndex. The new \a row must have
+ * the same number of columns as the row it is replacing.
+ */
+void QSurfaceDataProxy::setRow(int rowIndex, QSurfaceDataRow *row)
+{
+ dptr()->setRow(rowIndex, row);
+ emit rowsChanged(rowIndex, 1);
+}
+
+/*!
+ * Changes existing rows by replacing a rows starting at \a rowIndex with \a rows.
+ * The rows in the \a rows array can be the same as the existing rows already
+ * stored at the \a rowIndex. The new rows must have the same number of columns
+ * as the rows they are replacing.
+ */
+void QSurfaceDataProxy::setRows(int rowIndex, const QSurfaceDataArray &rows)
+{
+ dptr()->setRows(rowIndex, rows);
+ emit rowsChanged(rowIndex, rows.size());
+}
+
+/*!
+ * Changes a single item at \a rowIndex, \a columnIndex to the \a item.
+ */
+void QSurfaceDataProxy::setItem(int rowIndex, int columnIndex, const QSurfaceDataItem &item)
+{
+ dptr()->setItem(rowIndex, columnIndex, item);
+ emit itemChanged(rowIndex, columnIndex);
+}
+
+/*!
+ * Adds a new \a row to the end of array. The new \a row must have
+ * the same number of columns as the rows at the initial array.
+ *
+ * \return index of the added row.
+ */
+int QSurfaceDataProxy::addRow(QSurfaceDataRow *row)
+{
+ int addIndex = dptr()->addRow(row);
+ emit rowsAdded(addIndex, 1);
+ emit rowCountChanged(rowCount());
+ return addIndex;
+}
+
+/*!
+ * Adds new \a rows to the end of array. The new rows must have the same number of columns
+ * as the rows at the initial array.
+ *
+ * \return index of the first added row.
+ */
+int QSurfaceDataProxy::addRows(const QSurfaceDataArray &rows)
+{
+ int addIndex = dptr()->addRows(rows);
+ emit rowsAdded(addIndex, rows.size());
+ emit rowCountChanged(rowCount());
+ return addIndex;
+}
+
+/*!
+ * Inserts a new \a row into \a rowIndex.
+ * If rowIndex is equal to array size, rows are added to end of the array. The new \a row must have
+ * the same number of columns as the rows at the initial array.
+ */
+void QSurfaceDataProxy::insertRow(int rowIndex, QSurfaceDataRow *row)
+{
+ dptr()->insertRow(rowIndex, row);
+ emit rowsInserted(rowIndex, 1);
+ emit rowCountChanged(rowCount());
+}
+
+/*!
+ * Inserts new \a rows into \a rowIndex.
+ * If rowIndex is equal to array size, rows are added to end of the array. The new \a rows must have
+ * the same number of columns as the rows at the initial array.
+ */
+void QSurfaceDataProxy::insertRows(int rowIndex, const QSurfaceDataArray &rows)
+{
+ dptr()->insertRows(rowIndex, rows);
+ emit rowsInserted(rowIndex, rows.size());
+ emit rowCountChanged(rowCount());
+}
+
+/*!
+ * Removes \a removeCount rows staring at \a rowIndex. Attempting to remove rows past the end of the
+ * array does nothing.
+ */
+void QSurfaceDataProxy::removeRows(int rowIndex, int removeCount)
+{
+ if (rowIndex < rowCount() && removeCount >= 1) {
+ dptr()->removeRows(rowIndex, removeCount);
+ emit rowsRemoved(rowIndex, removeCount);
+ emit rowCountChanged(rowCount());
+ }
}
/*!
@@ -195,6 +302,47 @@ const QSurfaceDataProxyPrivate *QSurfaceDataProxy::dptrc() const
* emit this signal yourself or the graph won't get updated.
*/
+/*!
+ * \fn void QSurfaceDataProxy::rowsAdded(int startIndex, int count)
+ *
+ * Emitted when rows have been added. Provides \a startIndex and \a count of rows added.
+ * If you add rows directly to the array without calling addRow() or addRows(), you
+ * need to emit this signal yourself or the graph won't get updated.
+ */
+
+/*!
+ * \fn void QSurfaceDataProxy::rowsChanged(int startIndex, int count)
+ *
+ * Emitted when rows have changed. Provides \a startIndex and \a count of changed rows.
+ * If you change rows directly in the array without calling setRow() or setRows(), you
+ * need to emit this signal yourself or the graph won't get updated.
+ */
+
+/*!
+ * \fn void QSurfaceDataProxy::rowsRemoved(int startIndex, int count)
+ *
+ * Emitted when rows have been removed. Provides \a startIndex and \a count of rows removed.
+ * Index is the current array size if rows were removed from the end of the array.
+ * If you remove rows directly from the array without calling removeRows(), you
+ * need to emit this signal yourself or the graph won't get updated.
+ */
+
+/*!
+ * \fn void QSurfaceDataProxy::rowsInserted(int startIndex, int count)
+ *
+ * Emitted when rows have been inserted. Provides \a startIndex and \a count of inserted rows.
+ * If you insert rows directly into the array without calling insertRow() or insertRows(), you
+ * need to emit this signal yourself or the graph won't get updated.
+ */
+
+/*!
+ * \fn void QSurfaceDataProxy::itemChanged(int rowIndex, int columnIndex)
+ *
+ * Emitted when an item has changed. Provides \a rowIndex and \a columnIndex of changed item.
+ * If you change an item directly in the array without calling setItem(), you
+ * need to emit this signal yourself or the graph won't get updated.
+ */
+
//
// QSurfaceDataProxyPrivate
//
@@ -203,7 +351,6 @@ QSurfaceDataProxyPrivate::QSurfaceDataProxyPrivate(QSurfaceDataProxy *q)
: QAbstractDataProxyPrivate(q, QAbstractDataProxy::DataTypeSurface),
m_dataArray(new QSurfaceDataArray)
{
- m_itemLabelFormat = QStringLiteral("@yLabel (@xLabel, @zLabel)");
}
QSurfaceDataProxyPrivate::~QSurfaceDataProxyPrivate()
@@ -222,15 +369,95 @@ void QSurfaceDataProxyPrivate::resetArray(QSurfaceDataArray *newArray)
}
}
+void QSurfaceDataProxyPrivate::setRow(int rowIndex, QSurfaceDataRow *row)
+{
+ Q_ASSERT(rowIndex >= 0 && rowIndex < m_dataArray->size());
+ Q_ASSERT(m_dataArray->at(rowIndex)->size() == row->size());
+
+ if (row != m_dataArray->at(rowIndex)) {
+ clearRow(rowIndex);
+ (*m_dataArray)[rowIndex] = row;
+ }
+}
+
+void QSurfaceDataProxyPrivate::setRows(int rowIndex, const QSurfaceDataArray &rows)
+{
+ QSurfaceDataArray &dataArray = *m_dataArray;
+ Q_ASSERT(rowIndex >= 0 && (rowIndex + rows.size()) <= dataArray.size());
+
+ for (int i = 0; i < rows.size(); i++) {
+ Q_ASSERT(m_dataArray->at(rowIndex)->size() == rows.at(i)->size());
+ if (rows.at(i) != dataArray.at(rowIndex)) {
+ clearRow(rowIndex);
+ dataArray[rowIndex] = rows.at(i);
+ }
+ rowIndex++;
+ }
+}
+
+void QSurfaceDataProxyPrivate::setItem(int rowIndex, int columnIndex, const QSurfaceDataItem &item)
+{
+ Q_ASSERT(rowIndex >= 0 && rowIndex < m_dataArray->size());
+ QSurfaceDataRow &row = *(*m_dataArray)[rowIndex];
+ Q_ASSERT(columnIndex < row.size());
+ row[columnIndex] = item;
+}
+
+int QSurfaceDataProxyPrivate::addRow(QSurfaceDataRow *row)
+{
+ Q_ASSERT(m_dataArray->at(0)->size() == row->size());
+ int currentSize = m_dataArray->size();
+ m_dataArray->append(row);
+ return currentSize;
+}
+
+int QSurfaceDataProxyPrivate::addRows(const QSurfaceDataArray &rows)
+{
+ int currentSize = m_dataArray->size();
+ for (int i = 0; i < rows.size(); i++) {
+ Q_ASSERT(m_dataArray->at(0)->size() == rows.at(i)->size());
+ m_dataArray->append(rows.at(i));
+ }
+ return currentSize;
+}
+
+void QSurfaceDataProxyPrivate::insertRow(int rowIndex, QSurfaceDataRow *row)
+{
+ Q_ASSERT(rowIndex >= 0 && rowIndex <= m_dataArray->size());
+ Q_ASSERT(m_dataArray->at(0)->size() == row->size());
+ m_dataArray->insert(rowIndex, row);
+}
+
+void QSurfaceDataProxyPrivate::insertRows(int rowIndex, const QSurfaceDataArray &rows)
+{
+ Q_ASSERT(rowIndex >= 0 && rowIndex <= m_dataArray->size());
+
+ for (int i = 0; i < rows.size(); i++) {
+ Q_ASSERT(m_dataArray->at(0)->size() == rows.at(i)->size());
+ m_dataArray->insert(rowIndex++, rows.at(i));
+ }
+}
+
+void QSurfaceDataProxyPrivate::removeRows(int rowIndex, int removeCount)
+{
+ Q_ASSERT(rowIndex >= 0);
+ int maxRemoveCount = m_dataArray->size() - rowIndex;
+ removeCount = qMin(removeCount, maxRemoveCount);
+ for (int i = 0; i < removeCount; i++) {
+ clearRow(rowIndex);
+ m_dataArray->removeAt(rowIndex);
+ }
+}
+
QSurfaceDataProxy *QSurfaceDataProxyPrivate::qptr()
{
return static_cast<QSurfaceDataProxy *>(q_ptr);
}
-void QSurfaceDataProxyPrivate::limitValues(QVector3D &minValues, QVector3D &maxValues)
+void QSurfaceDataProxyPrivate::limitValues(QVector3D &minValues, QVector3D &maxValues) const
{
- qreal min = 0.0;
- qreal max = 0.0;
+ float min = 0.0f;
+ float max = 0.0f;
int rows = m_dataArray->size();
int columns = 0;
@@ -246,7 +473,7 @@ void QSurfaceDataProxyPrivate::limitValues(QVector3D &minValues, QVector3D &maxV
QSurfaceDataRow *row = m_dataArray->at(i);
if (row) {
for (int j = 0; j < columns; j++) {
- qreal itemValue = m_dataArray->at(i)->at(j).y();
+ float itemValue = m_dataArray->at(i)->at(j).y();
if (min > itemValue)
min = itemValue;
if (max < itemValue)
@@ -286,4 +513,11 @@ void QSurfaceDataProxyPrivate::clearArray()
delete m_dataArray;
}
+void QSurfaceDataProxyPrivate::setSeries(QAbstract3DSeries *series)
+{
+ QAbstractDataProxyPrivate::setSeries(series);
+ QSurface3DSeries *surfaceSeries = static_cast<QSurface3DSeries *>(series);
+ emit qptr()->seriesChanged(surfaceSeries);
+}
+
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/data/qsurfacedataproxy.h b/src/datavisualization/data/qsurfacedataproxy.h
index 460fa437..04c6dbf7 100644
--- a/src/datavisualization/data/qsurfacedataproxy.h
+++ b/src/datavisualization/data/qsurfacedataproxy.h
@@ -28,18 +28,21 @@ typedef QVector<QSurfaceDataItem> QSurfaceDataRow;
typedef QList<QSurfaceDataRow *> QSurfaceDataArray;
class QSurfaceDataProxyPrivate;
+class QSurface3DSeries;
class QT_DATAVISUALIZATION_EXPORT QSurfaceDataProxy : public QAbstractDataProxy
{
Q_OBJECT
- Q_PROPERTY(int rowCount READ rowCount)
- Q_PROPERTY(int columnCount READ columnCount)
+ Q_PROPERTY(int rowCount READ rowCount NOTIFY rowCountChanged)
+ Q_PROPERTY(int columnCount READ columnCount NOTIFY columnCountChanged)
+ Q_PROPERTY(QSurface3DSeries *series READ series NOTIFY seriesChanged)
public:
explicit QSurfaceDataProxy(QObject *parent = 0);
virtual ~QSurfaceDataProxy();
+ QSurface3DSeries *series();
int rowCount() const;
int columnCount() const;
const QSurfaceDataArray *array() const;
@@ -47,8 +50,30 @@ public:
void resetArray(QSurfaceDataArray *newArray);
+ void setRow(int rowIndex, QSurfaceDataRow *row);
+ void setRows(int rowIndex, const QSurfaceDataArray &rows);
+
+ void setItem(int rowIndex, int columnIndex, const QSurfaceDataItem &item);
+
+ int addRow(QSurfaceDataRow *row);
+ int addRows(const QSurfaceDataArray &rows);
+
+ void insertRow(int rowIndex, QSurfaceDataRow *row);
+ void insertRows(int rowIndex, const QSurfaceDataArray &rows);
+
+ void removeRows(int rowIndex, int removeCount);
+
signals:
void arrayReset();
+ void rowsAdded(int startIndex, int count);
+ void rowsChanged(int startIndex, int count);
+ void rowsRemoved(int startIndex, int count);
+ void rowsInserted(int startIndex, int count);
+ void itemChanged(int rowIndex, int columnIndex);
+
+ void rowCountChanged(int count);
+ void columnCountChanged(int count);
+ void seriesChanged(QSurface3DSeries *series);
protected:
explicit QSurfaceDataProxy(QSurfaceDataProxyPrivate *d, QObject *parent = 0);
diff --git a/src/datavisualization/data/qsurfacedataproxy_p.h b/src/datavisualization/data/qsurfacedataproxy_p.h
index 4c8c2820..1fda354c 100644
--- a/src/datavisualization/data/qsurfacedataproxy_p.h
+++ b/src/datavisualization/data/qsurfacedataproxy_p.h
@@ -44,8 +44,17 @@ public:
virtual ~QSurfaceDataProxyPrivate();
void resetArray(QSurfaceDataArray *newArray);
+ void setRow(int rowIndex, QSurfaceDataRow *row);
+ void setRows(int rowIndex, const QSurfaceDataArray &rows);
+ void setItem(int rowIndex, int columnIndex, const QSurfaceDataItem &item);
+ int addRow(QSurfaceDataRow *row);
+ int addRows(const QSurfaceDataArray &rows);
+ void insertRow(int rowIndex, QSurfaceDataRow *row);
+ void insertRows(int rowIndex, const QSurfaceDataArray &rows);
+ void removeRows(int rowIndex, int removeCount);
+ void limitValues(QVector3D &minValues, QVector3D &maxValues) const;
- void limitValues(QVector3D &minValues, QVector3D &maxValues);
+ virtual void setSeries(QAbstract3DSeries *series);
protected:
QSurfaceDataArray *m_dataArray;
diff --git a/src/datavisualization/data/scatteritemmodelhandler.cpp b/src/datavisualization/data/scatteritemmodelhandler.cpp
index 34230ae0..a70b35b0 100644
--- a/src/datavisualization/data/scatteritemmodelhandler.cpp
+++ b/src/datavisualization/data/scatteritemmodelhandler.cpp
@@ -35,8 +35,7 @@ ScatterItemModelHandler::~ScatterItemModelHandler()
// Resolve entire item model into QScatterDataArray.
void ScatterItemModelHandler::resolveModel()
{
- QItemModelScatterDataMapping *mapping = static_cast<QItemModelScatterDataMapping *>(m_activeMapping);
- if (m_itemModel.isNull() || !mapping) {
+ if (m_itemModel.isNull()) {
m_proxy->resetArray(0);
m_proxyArray = 0;
return;
@@ -45,9 +44,9 @@ void ScatterItemModelHandler::resolveModel()
static const int noRoleIndex = -1;
QHash<int, QByteArray> roleHash = m_itemModel->roleNames();
- const int xPosRole = roleHash.key(mapping->xPosRole().toLatin1(), noRoleIndex);
- const int yPosRole = roleHash.key(mapping->yPosRole().toLatin1(), noRoleIndex);
- const int zPosRole = roleHash.key(mapping->zPosRole().toLatin1(), noRoleIndex);
+ const int xPosRole = roleHash.key(m_proxy->xPosRole().toLatin1(), noRoleIndex);
+ const int yPosRole = roleHash.key(m_proxy->yPosRole().toLatin1(), noRoleIndex);
+ const int zPosRole = roleHash.key(m_proxy->zPosRole().toLatin1(), noRoleIndex);
const int columnCount = m_itemModel->columnCount();
const int rowCount = m_itemModel->rowCount();
const int totalCount = rowCount * columnCount;
diff --git a/src/datavisualization/data/scatteritemmodelhandler_p.h b/src/datavisualization/data/scatteritemmodelhandler_p.h
index 9b8a19a2..72f8f76c 100644
--- a/src/datavisualization/data/scatteritemmodelhandler_p.h
+++ b/src/datavisualization/data/scatteritemmodelhandler_p.h
@@ -30,7 +30,7 @@
#define SCATTERITEMMODELHANDLER_P_H
#include "abstractitemmodelhandler_p.h"
-#include "qitemmodelscatterdataproxy.h"
+#include "qitemmodelscatterdataproxy_p.h"
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
diff --git a/src/datavisualization/data/scatterrenderitem_p.h b/src/datavisualization/data/scatterrenderitem_p.h
index 58e91e96..5a97c1e9 100644
--- a/src/datavisualization/data/scatterrenderitem_p.h
+++ b/src/datavisualization/data/scatterrenderitem_p.h
@@ -48,13 +48,14 @@ public:
inline bool isVisible() const { return m_visible; }
inline void setVisible(bool visible) { m_visible = visible; }
- //inline void setSize(qreal size);
- //inline qreal size() const { return m_size; }
+ // TODO: Will we ever support item specific size? If not, remove.
+ //inline void setSize(float size);
+ //inline float size() const { return m_size; }
protected:
QVector3D m_position;
bool m_visible;
- //qreal m_size; // TODO in case we need a fourth variable that adjusts scatter item size
+ //float m_size; // TODO in case we need a fourth variable that adjusts scatter item size
friend class QScatterDataItem;
};
diff --git a/src/datavisualization/data/surfaceitemmodelhandler.cpp b/src/datavisualization/data/surfaceitemmodelhandler.cpp
index 70482162..10b4ccc5 100644
--- a/src/datavisualization/data/surfaceitemmodelhandler.cpp
+++ b/src/datavisualization/data/surfaceitemmodelhandler.cpp
@@ -17,7 +17,6 @@
****************************************************************************/
#include "surfaceitemmodelhandler_p.h"
-#include "qitemmodelsurfacedatamapping_p.h"
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
@@ -35,15 +34,14 @@ SurfaceItemModelHandler::~SurfaceItemModelHandler()
// Resolve entire item model into QSurfaceDataArray.
void SurfaceItemModelHandler::resolveModel()
{
- QItemModelSurfaceDataMapping *mapping = static_cast<QItemModelSurfaceDataMapping *>(m_activeMapping);
- if (m_itemModel.isNull() || !mapping) {
+ if (m_itemModel.isNull()) {
m_proxy->resetArray(0);
m_proxyArray = 0;
return;
}
- if (!mapping->useModelCategories()
- && (mapping->rowRole().isEmpty() || mapping->columnRole().isEmpty())) {
+ if (!m_proxy->useModelCategories()
+ && (m_proxy->rowRole().isEmpty() || m_proxy->columnRole().isEmpty())) {
m_proxy->resetArray(0);
m_proxyArray = 0;
return;
@@ -52,11 +50,11 @@ void SurfaceItemModelHandler::resolveModel()
QHash<int, QByteArray> roleHash = m_itemModel->roleNames();
// Default to display role if no mapping
- int valueRole = roleHash.key(mapping->valueRole().toLatin1(), Qt::DisplayRole);
+ int valueRole = roleHash.key(m_proxy->valueRole().toLatin1(), Qt::DisplayRole);
int rowCount = m_itemModel->rowCount();
int columnCount = m_itemModel->columnCount();
- if (mapping->useModelCategories()) {
+ if (m_proxy->useModelCategories()) {
// If dimensions have changed, recreate the array
if (m_proxyArray != m_proxy->array() || columnCount != m_proxy->columnCount()
|| rowCount != m_proxyArray->size()) {
@@ -75,11 +73,11 @@ void SurfaceItemModelHandler::resolveModel()
}
}
} else {
- int rowRole = roleHash.key(mapping->rowRole().toLatin1());
- int columnRole = roleHash.key(mapping->columnRole().toLatin1());
+ int rowRole = roleHash.key(m_proxy->rowRole().toLatin1());
+ int columnRole = roleHash.key(m_proxy->columnRole().toLatin1());
- bool generateRows = mapping->autoRowCategories();
- bool generateColumns = mapping->autoColumnCategories();
+ bool generateRows = m_proxy->autoRowCategories();
+ bool generateColumns = m_proxy->autoColumnCategories();
QStringList rowList;
QStringList columnList;
@@ -89,7 +87,7 @@ void SurfaceItemModelHandler::resolveModel()
QHash<QString, bool> columnListHash;
// Sort values into rows and columns
- typedef QHash<QString, qreal> ColumnValueMap;
+ typedef QHash<QString, float> ColumnValueMap;
QHash <QString, ColumnValueMap> itemValueMap;
for (int i = 0; i < rowCount; i++) {
for (int j = 0; j < columnCount; j++) {
@@ -109,14 +107,14 @@ void SurfaceItemModelHandler::resolveModel()
}
if (generateRows)
- mapping->dptr()->m_rowCategories = rowList;
+ m_proxy->dptr()->m_rowCategories = rowList;
else
- rowList = mapping->rowCategories();
+ rowList = m_proxy->rowCategories();
if (generateColumns)
- mapping->dptr()->m_columnCategories = columnList;
+ m_proxy->dptr()->m_columnCategories = columnList;
else
- columnList = mapping->columnCategories();
+ columnList = m_proxy->columnCategories();
// If dimensions have changed, recreate the array
if (m_proxyArray != m_proxy->array() || columnList.size() != m_proxy->columnCount()
diff --git a/src/datavisualization/data/surfaceitemmodelhandler_p.h b/src/datavisualization/data/surfaceitemmodelhandler_p.h
index bcf642c5..de0d2885 100644
--- a/src/datavisualization/data/surfaceitemmodelhandler_p.h
+++ b/src/datavisualization/data/surfaceitemmodelhandler_p.h
@@ -30,7 +30,7 @@
#define SURFACEITEMMODELHANDLER_P_H
#include "abstractitemmodelhandler_p.h"
-#include "qitemmodelsurfacedataproxy.h"
+#include "qitemmodelsurfacedataproxy_p.h"
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
diff --git a/src/datavisualization/datavisualization.pro b/src/datavisualization/datavisualization.pro
index bfb07440..6107eaa6 100644
--- a/src/datavisualization/datavisualization.pro
+++ b/src/datavisualization/datavisualization.pro
@@ -14,14 +14,11 @@ include($$PWD/common.pri)
include($$PWD/engine/engine.pri)
include($$PWD/global/global.pri)
include($$PWD/utils/utils.pri)
+include($$PWD/theme/theme.pri)
include($$PWD/axis/axis.pri)
include($$PWD/data/data.pri)
include($$PWD/input/input.pri)
-android {
- CONFIG += static
-}
-
OTHER_FILES += doc/qtdatavisualization.qdocconf \
doc/src/* \
doc/images/* \
diff --git a/src/datavisualization/doc/qtdatavisualization.qdocconf b/src/datavisualization/doc/qtdatavisualization.qdocconf
index fffcd3c4..7a7fa0b1 100644
--- a/src/datavisualization/doc/qtdatavisualization.qdocconf
+++ b/src/datavisualization/doc/qtdatavisualization.qdocconf
@@ -2,7 +2,7 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
project = QtDataVisualization
description = Qt Data Visualization Reference Documentation
-version = 0.1.0
+version = 1.0.0
exampledirs += ../../../examples \
snippets
@@ -18,14 +18,14 @@ depends += qtcore \
qhp.projects = qtdatavisualization
qhp.qtdatavisualization.file = qtdatavisualization.qhp
-qhp.qtdatavisualization.namespace = com.digia.qtdatavisualization.010
+qhp.qtdatavisualization.namespace = com.digia.qtdatavisualization.100
qhp.qtdatavisualization.virtualFolder = qtdatavisualization
qhp.qtdatavisualization.indexTitle = Qt Data Visualization
qhp.qtdatavisualization.indexRoot =
-qhp.qtdatavisualization.filterAttributes = qtdatavisualization 0.1.0 qtrefdoc
-qhp.qtdatavisualization.customFilters.Qt.name = QtDataVisualization 0.1.0
-qhp.qtdatavisualization.customFilters.Qt.filterAttributes = qtdatavisualization 0.1.0
+qhp.qtdatavisualization.filterAttributes = qtdatavisualization 1.0.0 qtrefdoc
+qhp.qtdatavisualization.customFilters.Qt.name = QtDataVisualization 1.0.0
+qhp.qtdatavisualization.customFilters.Qt.filterAttributes = qtdatavisualization 1.0.0
qhp.qtdatavisualization.subprojects = gettingstarted examples classes types
qhp.qtdatavisualization.subprojects.gettingstarted.title = Getting Started
qhp.qtdatavisualization.subprojects.gettingstarted.indexTitle = Qt Data Visualization Getting Started
diff --git a/src/datavisualization/doc/snippets/doc_src_q3dbars_construction.cpp b/src/datavisualization/doc/snippets/doc_src_q3dbars_construction.cpp
index 7c47183c..2b4a0aed 100644
--- a/src/datavisualization/doc/snippets/doc_src_q3dbars_construction.cpp
+++ b/src/datavisualization/doc/snippets/doc_src_q3dbars_construction.cpp
@@ -27,15 +27,18 @@ int main(int argc, char **argv)
//! [4]
Q3DBars bars;
+ bars.setFlags(bars.flags() ^ Qt::FramelessWindowHint);
//! [4]
//! [0]
bars.rowAxis()->setRange(0, 4);
bars.columnAxis()->setRange(0, 4);
//! [0]
//! [1]
+ QBar3DSeries *series = new QBar3DSeries;
QBarDataRow *data = new QBarDataRow;
- *data << 1.0 << 3.0 << 7.5 << 5.0 << 2.2;
- bars.activeDataProxy()->addRow(data);
+ *data << 1.0f << 3.0f << 7.5f << 5.0f << 2.2f;
+ series->dataProxy()->addRow(data);
+ bars.addSeries(series);
//! [1]
//! [2]
bars.show();
diff --git a/src/datavisualization/doc/snippets/doc_src_q3dscatter_construction.cpp b/src/datavisualization/doc/snippets/doc_src_q3dscatter_construction.cpp
index cce43fec..15820bf1 100644
--- a/src/datavisualization/doc/snippets/doc_src_q3dscatter_construction.cpp
+++ b/src/datavisualization/doc/snippets/doc_src_q3dscatter_construction.cpp
@@ -27,11 +27,14 @@ int main(int argc, char **argv)
//! [0]
Q3DScatter scatter;
+ scatter.setFlags(scatter.flags() ^ Qt::FramelessWindowHint);
//! [0]
//! [1]
+ QScatter3DSeries *series = new QScatter3DSeries;
QScatterDataArray data;
data << QVector3D(0.5f, 0.5f, 0.5f) << QVector3D(-0.3f, -0.5f, -0.4f) << QVector3D(0.0f, -0.3f, 0.2f);
- scatter.activeDataProxy()->addItems(data);
+ series->dataProxy()->addItems(data);
+ scatter.addSeries(series);
//! [1]
//! [2]
scatter.show();
diff --git a/src/datavisualization/doc/snippets/doc_src_q3dsurface_construction.cpp b/src/datavisualization/doc/snippets/doc_src_q3dsurface_construction.cpp
index 67587efc..245be2f4 100644
--- a/src/datavisualization/doc/snippets/doc_src_q3dsurface_construction.cpp
+++ b/src/datavisualization/doc/snippets/doc_src_q3dsurface_construction.cpp
@@ -27,6 +27,7 @@ int main(int argc, char **argv)
//! [0]
Q3DSurface surface;
+ surface.setFlags(surface.flags() ^ Qt::FramelessWindowHint);
//! [0]
//! [1]
QSurfaceDataArray *data = new QSurfaceDataArray;
@@ -41,7 +42,9 @@ int main(int argc, char **argv)
//! [2]
//! [3]
- surface.activeDataProxy()->resetArray(data);
+ QSurface3DSeries *series = new QSurface3DSeries;
+ series->dataProxy()->resetArray(data);
+ surface.addSeries(series);
//! [3]
//! [4]
surface.show();
diff --git a/src/datavisualization/doc/snippets/doc_src_q3dtheme.cpp b/src/datavisualization/doc/snippets/doc_src_q3dtheme.cpp
new file mode 100644
index 00000000..5a539e62
--- /dev/null
+++ b/src/datavisualization/doc/snippets/doc_src_q3dtheme.cpp
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#include <QtDataVisualization/Q3DBars>
+#include <QtDataVisualization/Q3DTheme>
+
+using namespace QtDataVisualization;
+
+int main(int argc, char **argv)
+{
+ //! [0]
+ Q3DTheme *theme = new Q3DTheme(Q3DTheme::ThemeQt);
+ //! [0]
+
+ //! [1]
+ Q3DTheme *theme = new Q3DTheme(Q3DTheme::ThemeQt);
+ theme->setBackgroundEnabled(false);
+ theme->setLabelBackgroundEnabled(false);
+ //! [1]
+
+ //! [2]
+ Q3DTheme *theme = new Q3DTheme();
+ theme->setAmbientLightStrength(0.3f);
+ theme->setBackgroundColor(QColor(QRgb(0x99ca53)));
+ theme->setBackgroundEnabled(true);
+ theme->setBaseColor(QColor(QRgb(0x209fdf)));
+ theme->setColorStyle(Q3DTheme::ColorStyleUniform);
+ theme->setFont(QFont(QStringLiteral("Impact"), 35));
+ theme->setGridEnabled(true);
+ theme->setGridLineColor(QColor(QRgb(0x99ca53)));
+ theme->setHighlightLightStrength(7.0f);
+ theme->setLabelBackgroundColor(QColor(0xf6, 0xa6, 0x25, 0xa0));
+ theme->setLabelBackgroundEnabled(true);
+ theme->setLabelBorderEnabled(true);
+ theme->setLabelTextColor(QColor(QRgb(0x404044)));
+ theme->setLightColor(Qt::white);
+ theme->setLightStrength(6.0f);
+ theme->setMultiHighlightColor(QColor(QRgb(0x6d5fd5)));
+ theme->setSingleHighlightColor(QColor(QRgb(0xf6a625)));
+ theme->setWindowColor(QColor(QRgb(0xffffff)));
+ //! [2]
+
+ //! [3]
+ Q3DBars *graph = new Q3DBars();
+ graph->setTheme(new Q3DTheme(Q3DTheme::ThemePrimaryColors));
+ graph->theme()->setBaseColor(Qt::red);
+ graph->theme()->setSingleHighlightColor(Qt::yellow);
+ //! [3]
+}
+
+//! [4]
+Scatter3D {
+ ...
+ theme: Theme3D { type: Theme3D.ThemeRetro }
+ ...
+}
+//! [4]
+
+//! [5]
+Bars3D {
+ ...
+ theme: Theme3D {
+ type: Theme3D.ThemeRetro
+ labelBorderEnabled: true
+ font.pointSize: 35
+ labelBackgroundEnabled: false
+ }
+ ...
+}
+//! [5]
+
+//! [6]
+Surface3D {
+ ...
+ theme: Theme3D {
+ ambientLightStrength: 0.5
+ backgroundColor: "red"
+ backgroundEnabled: true
+ baseColor: "blue"
+ colorStyle: Theme3D.ColorStyleUniform
+ font.family: "Lucida Handwriting"
+ font.pointSize: 35
+ gridEnabled: false
+ gridLineColor: "black"
+ highlightLightStrength: 0.5
+ labelBackgroundColor: "black"
+ labelBackgroundEnabled: true
+ labelBorderEnabled: false
+ labelTextColor: "white"
+ lightColor: "yellow"
+ lightStrength: 0.4
+ multiHighlightColor: "green"
+ singleHighlightColor: "darkRed"
+ windowColor: "white"
+ }
+ ...
+}
+//! [6]
diff --git a/src/datavisualization/doc/snippets/doc_src_qmldatavisualization.cpp b/src/datavisualization/doc/snippets/doc_src_qmldatavisualization.cpp
index 204e1cee..03f6e847 100644
--- a/src/datavisualization/doc/snippets/doc_src_qmldatavisualization.cpp
+++ b/src/datavisualization/doc/snippets/doc_src_qmldatavisualization.cpp
@@ -24,17 +24,27 @@ import QtDataVisualization 1.0
Bars3D {
rows: 4
columns: 4
- dataProxy: barProxy // an ItemModelBarDataProxy
barSpacing: Qt.size(0.5, 0.5)
barSpacingRelative: false
- itemLabelFormat: "@valueTitle for @colLabel, @rowLabel: @valueLabel"
+
+ Bar3DSeries {
+ itemLabelFormat: "@valueTitle for @colLabel, @rowLabel: @valueLabel"
+
+ ItemModelBarDataProxy {
+ itemModel: model // E.g. a list model defined elsewhere containing monthly expenses data.
+ // Mapping model roles to bar series rows, columns, and values.
+ rowRole: "year"
+ columnRole: "city"
+ valueRole: "expenses"
+ rowCategories: ["2010", "2011", "2012", "2013"]
+ columnCategories: ["Oulu", "Rauma", "Helsinki", "Tampere"]
+ }
+ }
}
//! [1]
//! [2]
Scatter3D {
- dataProxy: scatterProxy // an ItemModelScatterDataProxy
- itemLabelFormat: "X:@xLabel Y:@yLabel Z:@zLabel"
axisX.segmentCount: 2
axisX.subSegmentCount: 2
axisX.labelFormat: "%.2f"
@@ -44,12 +54,23 @@ Scatter3D {
axisY.segmentCount: 3
axisY.subSegmentCount: 2
axisY.labelFormat: "%.2f"
+
+ Scatter3DSeries {
+ itemLabelFormat: "X:@xLabel Y:@yLabel Z:@zLabel"
+
+ ItemModelScatterDataProxy {
+ itemModel: model // E.g. a list model defined elsewhere containing point coordinates.
+ // Mapping model roles to scatter series item coordinates.
+ xPosRole: "xPos"
+ yPosRole: "yPos"
+ zPosRole: "zPos"
+ }
+ }
}
//! [2]
//! [3]
Surface3D {
- dataProxy: surfaceProxy // an ItemModelSurfaceDataProxy
axisX.min: 0.0
axisX.max: 10.0
axisZ.min: 0.0
@@ -64,58 +85,47 @@ Surface3D {
axisZ.labelFormat: "%i"
axisY.segmentCount: 5
axisY.labelFormat: "%.1f"
+
+ Surface3DSeries {
+ ItemModelSurfaceDataProxy {
+ itemModel: model // E.g. a list model defined elsewhere containing population data.
+ // Mapping model roles to surface series rows, columns, and values.
+ rowRole: "longitude"
+ columnRole: "latitude"
+ valueRole: "pop_density"
+ }
+ }
}
//! [3]
-//! [4]
-BarDataMapping {
- id: barMapping
+//! [7]
+ItemModelBarDataProxy {
+ itemModel: model // E.g. a list model defined elsewhere containing monthly expenses data.
+ // Mapping model roles to bar series rows, columns, and values.
rowRole: "year"
columnRole: "city"
valueRole: "expenses"
rowCategories: ["2010", "2011", "2012", "2013"]
columnCategories: ["Oulu", "Rauma", "Helsinki", "Tampere"]
}
-//! [4]
-
-//! [5]
-ScatterDataMapping {
- id: scatterMapping
- xPosRole: "xPos"
- yPosRole: "yPos"
- zPosRole: "zPos"
-}
-//! [5]
-
-//! [6]
-SurfaceDataMapping {
- id: surfaceMapping
- rowRole: "latitude"
- columnRole: "longitude"
- valueRole: "population"
-}
-//! [6]
-
-//! [7]
-ItemModelBarDataProxy {
- id: barProxy
- activeMapping: barMapping // a BarDataMapping
- itemModel: dataModel // a ListModel
-}
//! [7]
//! [8]
ItemModelScatterDataProxy {
- id: scatterProxy
- activeMapping: scatterMapping // a ScatterDataMapping
- itemModel: dataModel // a ListModel
+ itemModel: model // E.g. a list model defined elsewhere containing point coordinates.
+ // Mapping model roles to scatter series item coordinates.
+ xPosRole: "xPos"
+ yPosRole: "yPos"
+ zPosRole: "zPos"
}
//! [8]
//! [9]
ItemModelSurfaceDataProxy {
- id: surfaceProxy
- activeMapping: surfaceMapping // a SurfaceDataMapping
- itemModel: dataModel // a ListModel
+ itemModel: model // E.g. a list model defined elsewhere containing population data.
+ // Mapping model roles to surface series rows, columns, and values.
+ rowRole: "longitude"
+ columnRole: "latitude"
+ valueRole: "pop_density"
}
//! [9]
diff --git a/src/datavisualization/doc/snippets/doc_src_qtdatavisualization.cpp b/src/datavisualization/doc/snippets/doc_src_qtdatavisualization.cpp
index d32bde0e..6a336422 100644
--- a/src/datavisualization/doc/snippets/doc_src_qtdatavisualization.cpp
+++ b/src/datavisualization/doc/snippets/doc_src_qtdatavisualization.cpp
@@ -47,36 +47,32 @@ QStringList months;
years << "2006" << "2007" << "2008" << "2009" << "2010" << "2011" << "2012";
months << "jan" << "feb" << "mar" << "apr" << "may" << "jun" << "jul" << "aug" << "sep" << "oct" << "nov" << "dec";
-QItemModelBarDataMapping *mapping = new QItemModelBarDataMapping(QStringLiteral("year"), // Row role
- QStringLiteral("month"), // Column role
- QStringLiteral("income"), // Value role
- years, // Row categories
- months); // Column categories
-
-QItemModelBarDataProxy *proxy = new QItemModelBarDataProxy(customModel, mapping);
+QItemModelBarDataProxy *proxy = new QItemModelBarDataProxy(customModel,
+ QStringLiteral("year"), // Row role
+ QStringLiteral("month"), // Column role
+ QStringLiteral("income"), // Value role
+ years, // Row categories
+ months); // Column categories
//...
-// To display different data later, you can simply change the mapping of the current
-// mapping object, or set another mapping object.
-proxy->activeMapping()->setValueRole(QStringLiteral("expenses"));
+// To display different data later, you can simply change the mapping.
+proxy->setValueRole(QStringLiteral("expenses"));
//! [3]
//! [4]
// Map "density" value to X-axis, "hardness" to Y-axis and "conductivity" to Z-axis.
-QItemModelScatterDataMapping *mapping = new QItemModelScatterDataMapping(QStringLiteral("density"),
- QStringLiteral("hardness"),
- QStringLiteral("conductivity"))
-
-QItemModelScatterDataProxy *proxy = new QItemModelScatterDataProxy(customModel, mapping);
+QItemModelScatterDataProxy *proxy = new QItemModelScatterDataProxy(customModel,
+ QStringLiteral("density"),
+ QStringLiteral("hardness"),
+ QStringLiteral("conductivity"));
//! [4]
//! [5]
-QItemModelSurfaceDataMapping *mapping = new QItemModelSurfaceDataMapping(QStringLiteral("longitude"), // Row role
- QStringLiteral("latitude"), // Column role
- QStringLiteral("height")); // value role
-
-QItemModelSurfaceDataProxy *proxy = new QItemModelSurfaceDataProxy(customModel, mapping);
+QItemModelSurfaceDataProxy *proxy = new QItemModelSurfaceDataProxy(customModel,
+ QStringLiteral("longitude"), // Row role
+ QStringLiteral("latitude"), // Column role
+ QStringLiteral("height")); // value role
//! [5]
//! [6]
@@ -116,5 +112,19 @@ for (int i = 0; i < 10; i++) {
}
newProxy->resetArray(dataArray);
-graph->setActiveDataProxy(newProxy);
+graph->addSeries(new QBar3DSeries(newProxy));
//! [10]
+
+//! [11]
+Q3DBars graph;
+QBar3DSeries *series = new QBar3DSeries;
+QLinearGradient barGradient(0, 0, 1, 100);
+barGradient.setColorAt(1.0, Qt::white);
+barGradient.setColorAt(0.0, Qt::black);
+
+series->setBaseGradient(barGradient);
+series->setColorStyle(Q3DTheme::ColorStyleObjectGradient);
+series->setMesh(QAbstract3DSeries::MeshCylinder);
+
+graph->addSeries(series);
+//! [11]
diff --git a/src/datavisualization/doc/src/qtdatavisualization-index.qdoc b/src/datavisualization/doc/src/qtdatavisualization-index.qdoc
index 456f8ac5..c37d98a4 100644
--- a/src/datavisualization/doc/src/qtdatavisualization-index.qdoc
+++ b/src/datavisualization/doc/src/qtdatavisualization-index.qdoc
@@ -32,10 +32,10 @@
\li Uses OpenGL for rendering the data
\li QML2 support
\li Customizable axes for data - control viewable data window with axis ranges
- \li Customizable input handling (upcoming feature - not supported in technology preview)
- \li Customizable scene handling - full control of cameras and lights (upcoming feature -
- not supported in technology preview)
- \li Customizable themes (upcoming feature - not supported in technology preview)
+ \li Customizable input handling
+ \li Customizable scene handling - full control of viewports
+ (upcoming feature - not fully supported in alpha)
+ \li Customizable themes
\endlist
\section1 Getting Started
@@ -62,8 +62,8 @@
\section1 Articles
\list
- \li \l{Qt Data Visualization Data Handling}{Data input}
- \li \l{Qt Data Visualization Interacting with Data}{Interacting with visualized data}
+ \li \l{Qt Data Visualization Data Handling}{Data Handling}
+ \li \l{Qt Data Visualization Interacting with Data}{Interacting with Data}
\endlist
\section1 References
diff --git a/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc b/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc
index 59331bf9..7493709f 100644
--- a/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc
+++ b/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc
@@ -35,10 +35,6 @@
\qmlproperty AbstractGraph3D.SelectionMode AbstractGraph3D::selectionMode
Active selection mode in the visualization.
*/
-/*!
- \qmlproperty AbstractGraph3D.LabelStyle AbstractGraph3D::labelStyle
- Label style.
- */
/*!
\qmlproperty AbstractGraph3D.ShadowQuality AbstractGraph3D::shadowQuality
@@ -46,32 +42,11 @@
*/
/*!
- \qmlproperty AbstractGraph3D.CameraPreset AbstractGraph3D::cameraPreset
- Camera preset.
- */
-
-/*!
- \qmlproperty AbstractGraph3D.Theme AbstractGraph3D::theme
- Theme of the graph. Theme affects visualization colors, label colors, text color, background color, window
- color and grid color. Lighting is also adjusted by themes.
- */
-
-/*!
- \qmlproperty font AbstractGraph3D::font
- Font used for labels.
- */
-
-/*!
- \qmlproperty bool AbstractGraph3D::gridVisible
- Grid visibility. If false, grid lines are not drawn.
- */
-
-/*!
- \qmlproperty bool AbstractGraph3D::backgroundVisible
- Background visibility. If false, background is not drawn.
+ \qmlproperty AbstractInputHandler3D AbstractGraph3D::inputHandler
+ Input handler. You can disable default input handlers by setting this property to \c null.
*/
/*!
- \qmlproperty string AbstractGraph3D::itemLabelFormat
- Label format of single item labels, e.g. a selected datapoint.
+ \qmlproperty Theme3D AbstractGraph3D::theme
+ Theme of the graph.
*/
diff --git a/src/datavisualization/doc/src/qtdatavisualization-qml-bars3d.qdoc b/src/datavisualization/doc/src/qtdatavisualization-qml-bars3d.qdoc
index 935662b3..fc1b732c 100644
--- a/src/datavisualization/doc/src/qtdatavisualization-qml-bars3d.qdoc
+++ b/src/datavisualization/doc/src/qtdatavisualization-qml-bars3d.qdoc
@@ -36,28 +36,7 @@
*
* See \l{Qt Quick 2 Bars Example} for more thorough usage example.
*
- * \sa ItemModelBarDataProxy, Scatter3D, Surface3D, {Qt Data Visualization C++ Classes}
- */
-
-/*!
- * \qmlmethod void Bars3D::setBarColor(const QColor &baseColor, bool uniform)
- * Set bar color using your own color. \a baseColor sets the base color of a bar. The \a uniform
- * -flag is used to define if color needs to be uniform throughout bar's length, or will the colors
- * be applied by height, starting with dark at the bottom. It is \c true by default.
- *
- * Calling this method overrides colors from theme.
- *
- * \sa AbstractGraph3D::theme
- *
- * \warning This method is subject to change.
- */
-
-/*!
- * \qmlproperty BarDataProxy Bars3D::dataProxy
- * The active data proxy.
- *
- * If a proxy is not given, a temporary default proxy is created and activated.
- * This temporary proxy is destroyed if another proxy is explicitly set active via this property.
+ * \sa Bar3DSeries, ItemModelBarDataProxy, Scatter3D, Surface3D, {Qt Data Visualization C++ Classes}
*/
/*!
@@ -87,11 +66,6 @@
/*!
- * \qmlproperty Bars3D.MeshStyle Bars3D::barType
- * Bar object type.
- */
-
-/*!
* \qmlproperty real Bars3D::barThickness
* Bar thickness ratio between X and Z dimensions. 1.0 means bars are as wide as they are deep, 0.5
* makes them twice as deep as they are wide.
@@ -108,29 +82,23 @@
*/
/*!
- * \qmlproperty bool Bars3D::barSmoothingEnabled
- * Bar smoothing. If false, bar shading is flat.
- */
-
-/*!
- * \qmlproperty string Bars3D::meshFileName
- * Override bar type with a mesh object.
- * \note Object needs to be in Wavefront obj format and include vertices, normals and UVs.
- * It also needs to be in triangles.
- */
-
-/*!
- * \qmlproperty int Bars3D::rows
- * Row count of data window.
+ * \qmlproperty list<QBar3DSeries> Bars3D::seriesList
+ * This property holds the series of the graph.
+ * By default, this property contains an empty list.
+ * To set the series, either use the addSeries() function or define them as children of the graph.
*/
/*!
- * \qmlproperty int Bars3D::columns
- * Column count of data window.
+ * \qmlmethod void Bars3D::addSeries(QBar3DSeries *series)
+ * Adds the \a series to the graph. A graph can contain multiple series, but only one set of axes,
+ * so the rows and columns of all series must match for the visualized data to be meaningful.
+ * If the graph has multiple visible series, only the first one added will
+ * generate the row or column labels on the axes in cases where the labels are not explicitly set
+ * to the axes. If the newly added series has specified a selected bar, it will be highlighted and
+ * any existing selection will be cleared. Only one added series can have an active selection.
*/
/*!
- * \qmlproperty point Bars3D::selectedBarPos
- * Position of the selected bar in data window. Only one bar can be selected at a time.
- * To clear selection, specify an illegal position, e.g. Qt.point(-1.0, -1.0).
+ * \qmlmethod void Bars3D::removeSeries(QBar3DSeries *series)
+ * Remove the \a series from the graph.
*/
diff --git a/src/datavisualization/doc/src/qtdatavisualization-qml-scatter3d.qdoc b/src/datavisualization/doc/src/qtdatavisualization-qml-scatter3d.qdoc
index db5c381d..1f04424f 100644
--- a/src/datavisualization/doc/src/qtdatavisualization-qml-scatter3d.qdoc
+++ b/src/datavisualization/doc/src/qtdatavisualization-qml-scatter3d.qdoc
@@ -36,28 +36,7 @@
See \l{Qt Quick 2 Scatter Example} for more thorough usage example.
- \sa ItemModelScatterDataProxy, Bars3D, Surface3D, {Qt Data Visualization C++ Classes}
- */
-
-/*!
- * \qmlmethod void Scatter3D::setObjectColor(const QColor &baseColor, bool uniform)
- * Set item color using your own colors. \a baseColor sets the base color of a item. The \a uniform
- * -flag is used to define if color needs to be uniform throughout item's length, or will the colors
- * be applied by height. It is \c true by default.
- *
- * Calling this method overrides colors from theme.
- *
- * \sa AbstractGraph3D::theme
- *
- * \warning This method is subject to change.
- */
-
-/*!
- \qmlproperty ScatterDataProxy Scatter3D::dataProxy
- The active data proxy.
-
- If a proxy is not given, a temporary default proxy is created and activated.
- This temporary proxy is destroyed if another proxy is explicitly set active via this property.
+ \sa Scatter3DSeries, ScatterDataProxy, Bars3D, Surface3D, {Qt Data Visualization C++ Classes}
*/
/*!
@@ -88,18 +67,20 @@
*/
/*!
- \qmlproperty Scatter3D.MeshStyle Scatter3D::objectType
- Dot object type.
+ * \qmlproperty list<QScatter3DSeries> Scatter3D::seriesList
+ * This property holds the series of the graph.
+ * By default, this property contains an empty list.
+ * To set the series, either use the addSeries() function or define them as children of the graph.
*/
/*!
- \qmlproperty bool Scatter3D::objectSmoothingEnabled
- Dot smoothing. If false, dot shading is flat.
+ * \qmlmethod void Scatter3D::addSeries(QScatter3DSeries *series)
+ * Adds the \a series to the graph. A graph can contain multiple series, but has only one set of
+ * axes. If the newly added series has specified a selected item, it will be highlighted and
+ * any existing selection will be cleared. Only one added series can have an active selection.
*/
/*!
- \qmlproperty string Scatter3D::meshFileName
- Override object type with a mesh object.
- \note Object needs to be in Wavefront obj format and include vertices, normals and UVs.
- It also needs to be in triangles.
+ * \qmlmethod void Scatter3D::removeSeries(QScatter3DSeries *series)
+ * Remove the \a series from the graph.
*/
diff --git a/src/datavisualization/doc/src/qtdatavisualization-qml-surface3d.qdoc b/src/datavisualization/doc/src/qtdatavisualization-qml-surface3d.qdoc
index 7d79a19e..a3886008 100644
--- a/src/datavisualization/doc/src/qtdatavisualization-qml-surface3d.qdoc
+++ b/src/datavisualization/doc/src/qtdatavisualization-qml-surface3d.qdoc
@@ -36,15 +36,7 @@
See \l{Qt Quick 2 Surface Example} for more thorough usage example.
- \sa ItemModelSurfaceDataProxy, Bars3D, Scatter3D, {Qt Data Visualization C++ Classes}
- */
-
-/*!
- \qmlproperty SurfaceDataProxy Surface3D::dataProxy
- The active data proxy.
-
- If a proxy is not given, a temporary default proxy is created and activated.
- This temporary proxy is destroyed if another proxy is explicitly set active via this property.
+ \sa Surface3DSeries, ItemModelSurfaceDataProxy, Bars3D, Scatter3D, {Qt Data Visualization C++ Classes}
*/
/*!
@@ -75,16 +67,26 @@
*/
/*!
- \qmlproperty bool Surface3D::smoothSurfaceEnabled
- The smoothing of surface. If false, the shading of the surface is flat.
+/*!
+ \qmlproperty ColorGradient Surface3D::gradient
+ The current surface gradient. Setting this property replaces the previous gradient.
+ */
+
+/*!
+ * \qmlproperty list<QSurface3DSeries> Surface3D::seriesList
+ * This property holds the series of the graph.
+ * By default, this property contains an empty list.
+ * To set the series, either use the addSeries() function or define them as children of the graph.
+ * \note The surface graph currently supports only a single series at a time.
*/
/*!
- \qmlproperty bool Surface3D::surfaceGridEnabled
- The surface grid visibility. If false, no surface grid is drawn.
+ * \qmlmethod void Surface3D::addSeries(QSurface3DSeries *series)
+ * Adds the \a series to the graph.
+ * \note The surface graph currently supports only a single series at a time.
*/
/*!
- \qmlproperty ColorGradient Surface3D::gradient
- The current surface gradient. Setting this property replaces the previous gradient.
+ * \qmlmethod void Surface3D::removeSeries(QSurface3DSeries *series)
+ * Remove the \a series from the graph.
*/
diff --git a/src/datavisualization/doc/src/qtdatavisualization.qdoc b/src/datavisualization/doc/src/qtdatavisualization.qdoc
index add1c252..9c951877 100644
--- a/src/datavisualization/doc/src/qtdatavisualization.qdoc
+++ b/src/datavisualization/doc/src/qtdatavisualization.qdoc
@@ -167,47 +167,60 @@
\page qtdatavisualization_data_handling.html
\title Qt Data Visualization Data Handling
+ \section1 Series
+
+ Series is combination of logically connected set of data items (handled by a data proxy)
+ and visual properties that describe how the data items should be rendered, such as item
+ meshes and colors. Each visualization type has its own series type. For example, bar graphs
+ use QBar3DSeries. Bar and scatter graphs can have multiple series added simultaneously.
+ Surface graphs support only a single series at a time.
+
+ This code snippet shows how to use QBar3DSeries to render bars as cylinders and with a
+ gradient instead of a uniform color:
+
+ \snippet doc_src_qtdatavisualization.cpp 11
+
\section1 Data proxies
The data that users wish to visualize comes in many formats, all of which cannot obviously be
directly supported. Therefore, Qt Data Visualization implements data proxies into which
user can feed their data in a known format. Each visualization type has a basic proxy type,
which takes data in a format suitable for that visualization.
- For example, the basic proxy for Q3DBars is QBarDataProxy, which stores rows of QBarDataItem
+ For example, the basic proxy for QBar3DSeries is QBarDataProxy, which stores rows of QBarDataItem
objects. Each QBarDataItem stores a single bar value. Additional typedefs are provided for
- QBarDataArray and QBarDataRow containers.
+ \c QBarDataArray and \c QBarDataRow containers.
- This code snipped shows how to use basic proxy when your data is stored in some hypothetical
+ This code snippet shows how to use basic proxy when your data is stored in some hypothetical
\c myData object:
\snippet doc_src_qtdatavisualization.cpp 10
- \note The graph objects can own more than one data proxy, but only one proxy can be
- active at a time. If you need to switch back and forth between two different sets of data,
- it may be more efficient to store each set in a different proxy and just change the active
- proxy, rather than reset the data in one proxy every time you need to switch.
+ \note Series objects can own only a single proxy at a time. The existing proxy is deleted
+ when another is set to the series. Graphs can contain multiple series, though.
+ If you need to switch back and forth between two different sets of data,
+ it is usually more efficient to store each set in a different series and just change the series,
+ rather than reset the data in one proxy every time you need to switch.
\section1 Item models and data mapping
For common use cases, Qt Data Visualization offers specialized proxies. One such case is having
data in an item model (QAbstractItemModel subclass), which is a common way to store data in
- Qt applications. Each of the visualization types offers a special proxy and a corresponding mapping
- class for this purpose, for example, QItemModelBarDataProxy and QItemModelBarDataMapping for Q3DBars.
+ Qt applications. Each of the visualization types offers a special proxy class for this purpose,
+ for example, QItemModelBarDataProxy for QBar3DSeries.
These proxies are simple to use: just give them a pointer to the item model containing the
- data and the mapping object containing rules how to map the data into format the basic proxy can
- digest.
+ data and the rules how to map the data into format the basic proxy can digest.
- Mapping objects work with item model roles. Each data item in the model can have different
- values for different roles. For example, with QItemModelBarDataMapping you can specify which
+ Mapping works with item model roles. Each data item in the model can have different
+ values for different roles. For example, with QItemModelBarDataProxy you can specify which
role is used to determine which row the item belongs to, which role does the same for columns,
and which role specifies the value of the item. When the proxy resolves the data from the model,
it uses these mappings to generate the rows and columns of the bar graph.
- Depending on the visualization type, mapping classes may support other functionalities as well,
- such as QItemModelBarDataMapping optionally mapping QAbstractItemModel rows and columns directly
- into bar graph rows and columns. See individual mapping classes for more information and examples
- about how to use them: QItemModelBarDataMapping, QItemModelScatterDataMapping, and
- QItemModelSurfaceDataMapping.
+ Depending on the visualization type, proxies may support other functionalities as well,
+ such as QItemModelBarDataProxy optionally mapping QAbstractItemModel rows and columns directly
+ into bar graph rows and columns. See individual proxy classes for more information and examples
+ about how to use them: QItemModelBarDataProxy, QItemModelScatterDataProxy, and
+ QItemModelSurfaceDataProxy.
\section1 Other custom proxies
@@ -244,8 +257,6 @@
For the best performance with the scatter and surface graphs, only keep the data you need in the
proxy.
-
- \note Data handling is not yet fully optimized in the technology preview version.
*/
/*!
@@ -255,21 +266,15 @@
\section1 Interacting with data
You can interact with the rendered graph with either mouse or touch to rotate, zoom, or select
- data. For the mouse controls, see Q3DInputHandler documentation, and for the touch controls,
- see QTouch3DInputHandler documentation.
-
- \note In the technology preview version, default input handlers cannot be replaced or even accessed
- via the public API. This feature is planned for the final release.
+ data. For the default mouse controls, see Q3DInputHandler documentation, and for the default
+ touch controls, see QTouch3DInputHandler documentation.
\section1 Data selection modes
All visualization types support selecting a single data item - a bar, a scatter item, or a surface
- vertex - using mouse, touch, and programmatically via the graph APIs. The selected item is highlighted
- in the rendered graph, and selecting causes emission of a graph specific signal for this purpose,
- for example, Q3DBars::selectedBarPosChanged(), which the application can handle.
-
- \note The surface graph doesn't have a fully implemented selection API yet. It only supports
- selection with mouse and touch in the technology preview version.
+ vertex - using mouse, touch, and programmatically via the series APIs. The selected item is highlighted
+ in the rendered graph, and selecting causes emission of a series specific signal for this purpose,
+ for example, QBar3DSeries::selectedBarChanged(), which the application can handle.
Bar and surface graphs support slice selection modes, where the selected row or column is drawn
in a separate viewport as a pseudo-2D graph. This makes it easier to see the actual values of
@@ -277,4 +282,7 @@
Bar graph additionally supports simply highlighting the whole row and/or column of the selected bar
without opening the slice view.
+
+ When multiple series are added to a graph, selecting an item in one of them will clear the selection
+ on other series.
*/
diff --git a/src/datavisualization/engine/abstract3dcontroller.cpp b/src/datavisualization/engine/abstract3dcontroller.cpp
index bfdc375e..9835dbe4 100644
--- a/src/datavisualization/engine/abstract3dcontroller.cpp
+++ b/src/datavisualization/engine/abstract3dcontroller.cpp
@@ -27,21 +27,19 @@
#include "qabstractdataproxy_p.h"
#include "qabstract3dinputhandler_p.h"
#include "qtouch3dinputhandler.h"
+#include "qabstract3dseries_p.h"
+#include "thememanager_p.h"
+#include "q3dscene_p.h"
#include <QThread>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-Abstract3DController::Abstract3DController(QRect boundRect, QObject *parent) :
+Abstract3DController::Abstract3DController(QRect initialViewport, QObject *parent) :
QObject(parent),
- m_boundingRect(boundRect.x(), boundRect.y(), boundRect.width(), boundRect.height()),
- m_theme(),
- m_font(QFont(QStringLiteral("Arial"))),
- m_selectionMode(QDataVis::SelectionModeItem),
+ m_themeManager(new ThemeManager(this)),
+ m_selectionMode(QDataVis::SelectionItem),
m_shadowQuality(QDataVis::ShadowQualityMedium),
- m_labelStyle(QDataVis::LabelStyleTransparent),
- m_isBackgroundEnabled(true),
- m_isGridEnabled(true),
m_scene(new Q3DScene()),
m_activeInputHandler(0),
m_axisX(0),
@@ -49,10 +47,14 @@ Abstract3DController::Abstract3DController(QRect boundRect, QObject *parent) :
m_axisZ(0),
m_renderer(0),
m_isDataDirty(true),
- m_data(0),
+ m_isSeriesVisibilityDirty(true),
+ m_isSeriesVisualsDirty(true),
m_renderPending(false)
{
- m_theme.useTheme(QDataVis::ThemeQt);
+ // Set initial theme
+ setTheme(new Q3DTheme(Q3DTheme::ThemeQt));
+
+ m_scene->d_ptr->setViewport(initialViewport);
// Populate the scene
m_scene->activeLight()->setPosition(defaultLightPos);
@@ -63,8 +65,10 @@ Abstract3DController::Abstract3DController(QRect boundRect, QObject *parent) :
inputHandler->d_ptr->m_isDefaultHandler = true;
setActiveInputHandler(inputHandler);
connect(inputHandler, &QAbstract3DInputHandler::inputStateChanged, this,
- &Abstract3DController::emitNeedRender);
- connect(m_scene, &Q3DScene::needRender, this,
+ &Abstract3DController::handleInputStateChanged);
+ connect(inputHandler, &QAbstract3DInputHandler::positionChanged, this,
+ &Abstract3DController::handleInputPositionChanged);
+ connect(m_scene->d_ptr.data(), &Q3DScenePrivate::needRender, this,
&Abstract3DController::emitNeedRender);
}
@@ -76,46 +80,62 @@ Abstract3DController::~Abstract3DController()
else
delete m_renderer;
delete m_scene;
+ delete m_themeManager;
}
+/**
+ * @brief setRenderer Sets the renderer to be used. isInitialized returns true from this point onwards.
+ * @param renderer Renderer to be used.
+ */
void Abstract3DController::setRenderer(Abstract3DRenderer *renderer)
{
m_renderer = renderer;
}
-void Abstract3DController::synchDataToRenderer()
+void Abstract3DController::addSeries(QAbstract3DSeries *series)
{
- // If we don't have a renderer, don't do anything
- if (!m_renderer)
- return;
-
- if (m_changeTracker.boundingRectChanged || m_changeTracker.sizeChanged) {
- m_renderer->updateBoundingRect(m_boundingRect);
- m_changeTracker.boundingRectChanged = false;
- m_changeTracker.sizeChanged = false;
+ if (series && !m_seriesList.contains(series)) {
+ int oldSize = m_seriesList.size();
+ m_seriesList.append(series);
+ series->d_ptr->setController(this);
+ QObject::connect(series, &QAbstract3DSeries::visibilityChanged,
+ this, &Abstract3DController::handleSeriesVisibilityChanged);
+ if (series->isVisible())
+ handleSeriesVisibilityChangedBySender(series);
+ series->d_ptr->resetToTheme(*m_themeManager->theme(), oldSize, false);
}
+}
- if (m_changeTracker.positionChanged) {
- m_renderer->updatePosition(m_boundingRect);
- m_changeTracker.positionChanged = false;
+void Abstract3DController::removeSeries(QAbstract3DSeries *series)
+{
+ if (series && series->d_ptr->m_controller == this) {
+ m_seriesList.removeAll(series);
+ QObject::disconnect(series, &QAbstract3DSeries::visibilityChanged,
+ this, &Abstract3DController::handleSeriesVisibilityChanged);
+ series->d_ptr->setController(0);
+ m_isDataDirty = true;
+ m_isSeriesVisibilityDirty = true;
+ emitNeedRender();
}
+}
- m_renderer->updateScene(m_scene);
+QList<QAbstract3DSeries *> Abstract3DController::seriesList()
+{
+ return m_seriesList;
+}
- if (m_changeTracker.themeChanged) {
- m_renderer->updateTheme(m_theme);
- m_changeTracker.themeChanged = false;
- }
+/**
+ * @brief synchDataToRenderer Called on the render thread while main GUI thread is blocked before rendering.
+ */
+void Abstract3DController::synchDataToRenderer()
+{
+ // If we don't have a renderer, don't do anything
+ if (!m_renderer)
+ return;
- if (m_changeTracker.fontChanged) {
- m_renderer->updateFont(m_font);
- m_changeTracker.fontChanged = false;
- }
+ m_renderer->updateScene(m_scene);
- if (m_changeTracker.labelStyleChanged) {
- m_renderer->updateLabelStyle(m_labelStyle);
- m_changeTracker.labelStyleChanged = false;
- }
+ m_renderer->updateTheme(m_themeManager->theme());
if (m_changeTracker.shadowQualityChanged) {
m_renderer->updateShadowQuality(m_shadowQuality);
@@ -127,21 +147,6 @@ void Abstract3DController::synchDataToRenderer()
m_changeTracker.selectionModeChanged = false;
}
- if (m_changeTracker.objFileChanged) {
- m_renderer->updateMeshFileName(m_objFile);
- m_changeTracker.objFileChanged = false;
- }
-
- if (m_changeTracker.gridEnabledChanged) {
- m_renderer->updateGridEnabled(m_isGridEnabled);
- m_changeTracker.gridEnabledChanged = false;
- }
-
- if (m_changeTracker.backgroundEnabledChanged) {
- m_renderer->updateBackgroundEnabled(m_isBackgroundEnabled);
- m_changeTracker.backgroundEnabledChanged = false;
- }
-
if (m_changeTracker.axisXTypeChanged) {
m_renderer->updateAxisType(Q3DAbstractAxis::AxisOrientationX, m_axisX->type());
m_changeTracker.axisXTypeChanged = false;
@@ -284,6 +289,19 @@ void Abstract3DController::synchDataToRenderer()
valueAxisZ->labelFormat());
}
}
+
+ if (m_isSeriesVisibilityDirty || m_isSeriesVisualsDirty) {
+ m_renderer->updateSeries(m_seriesList, m_isSeriesVisibilityDirty);
+ m_isSeriesVisibilityDirty = false;
+ m_isSeriesVisualsDirty = false;
+ }
+
+ if (m_isDataDirty) {
+ // Series list supplied above in updateSeries() is used to access the data,
+ // so no data needs to be passed in updateData()
+ m_renderer->updateData();
+ m_isDataDirty = false;
+ }
}
void Abstract3DController::render(const GLuint defaultFboHandle)
@@ -306,156 +324,126 @@ void Abstract3DController::mouseDoubleClickEvent(QMouseEvent *event)
{
if (m_activeInputHandler)
m_activeInputHandler->mouseDoubleClickEvent(event);
-
- emitNeedRender();
}
void Abstract3DController::touchEvent(QTouchEvent *event)
{
if (m_activeInputHandler)
m_activeInputHandler->touchEvent(event);
-
- emitNeedRender();
}
void Abstract3DController::mousePressEvent(QMouseEvent *event, const QPoint &mousePos)
{
if (m_activeInputHandler)
m_activeInputHandler->mousePressEvent(event, mousePos);
-
- emitNeedRender();
}
void Abstract3DController::mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos)
{
if (m_activeInputHandler)
m_activeInputHandler->mouseReleaseEvent(event, mousePos);
-
- emitNeedRender();
}
void Abstract3DController::mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos)
{
if (m_activeInputHandler)
m_activeInputHandler->mouseMoveEvent(event, mousePos);
-
- emitNeedRender();
}
void Abstract3DController::wheelEvent(QWheelEvent *event)
{
if (m_activeInputHandler)
m_activeInputHandler->wheelEvent(event);
-
- emitNeedRender();
}
-void Abstract3DController::setSize(const int width, const int height)
+void Abstract3DController::handleThemeColorStyleChanged(Q3DTheme::ColorStyle style)
{
- m_boundingRect.setWidth(width);
- m_boundingRect.setHeight(height);
- m_scene->setViewportSize(width, height);
-
- m_changeTracker.boundingRectChanged = true;
- emitNeedRender();
-}
-
-const QSize Abstract3DController::size()
-{
- return m_boundingRect.size();
-}
-
-const QRect Abstract3DController::boundingRect()
-{
- return m_boundingRect;
-}
-
-void Abstract3DController::setBoundingRect(const QRect boundingRect)
-{
- m_boundingRect = boundingRect;
- m_scene->setViewport(boundingRect);
-
- m_changeTracker.boundingRectChanged = true;
- emitNeedRender();
-}
-
-void Abstract3DController::setWidth(const int width)
-{
- m_boundingRect.setWidth(width);
- m_scene->setViewportSize(width, m_scene->viewport().height());
-
- m_changeTracker.sizeChanged = true;
- emitNeedRender();
-}
-
-int Abstract3DController::width()
-{
- return m_boundingRect.width();
-}
-
-void Abstract3DController::setHeight(const int height)
-{
- m_boundingRect.setHeight(height);
- m_scene->setViewportSize(m_scene->viewport().width(), height);
-
- m_changeTracker.sizeChanged = true;
- emitNeedRender();
-}
-
-int Abstract3DController::height()
-{
- return m_boundingRect.height();
-}
-
-void Abstract3DController::setX(const int x)
-{
- m_boundingRect.setX(x);
-
- m_changeTracker.positionChanged = true;
- emitNeedRender();
-}
-
-int Abstract3DController::x()
-{
- return m_boundingRect.x();
-}
-
-void Abstract3DController::setY(const int y)
-{
- m_boundingRect.setY(y);
-
- m_changeTracker.positionChanged = true;
- emitNeedRender();
+ // Set value for series that have not explicitly set this value
+ foreach (QAbstract3DSeries *series, m_seriesList) {
+ if (!series->d_ptr->m_themeTracker.colorStyleOverride) {
+ series->setColorStyle(style);
+ series->d_ptr->m_themeTracker.colorStyleOverride = false;
+ }
+ }
+ markSeriesVisualsDirty();
}
-int Abstract3DController::y()
+void Abstract3DController::handleThemeBaseColorsChanged(const QList<QColor> &colors)
{
- return m_boundingRect.y();
+ int colorIdx = 0;
+ // Set value for series that have not explicitly set this value
+ foreach (QAbstract3DSeries *series, m_seriesList) {
+ if (!series->d_ptr->m_themeTracker.baseColorOverride) {
+ series->setBaseColor(colors.at(colorIdx));
+ series->d_ptr->m_themeTracker.baseColorOverride = false;
+ }
+ if (++colorIdx >= colors.size())
+ colorIdx = 0;
+ }
+ markSeriesVisualsDirty();
}
-QRect Abstract3DController::primarySubViewport() const
+void Abstract3DController::handleThemeBaseGradientsChanged(const QList<QLinearGradient> &gradients)
{
- return m_scene->primarySubViewport();
+ int gradientIdx = 0;
+ // Set value for series that have not explicitly set this value
+ foreach (QAbstract3DSeries *series, m_seriesList) {
+ if (!series->d_ptr->m_themeTracker.baseGradientOverride) {
+ series->setBaseGradient(gradients.at(gradientIdx));
+ series->d_ptr->m_themeTracker.baseGradientOverride = false;
+ }
+ if (++gradientIdx >= gradients.size())
+ gradientIdx = 0;
+ }
+ markSeriesVisualsDirty();
}
-void Abstract3DController::setPrimarySubViewport(const QRect &primarySubViewport)
+void Abstract3DController::handleThemeSingleHighlightColorChanged(const QColor &color)
{
- m_scene->setPrimarySubViewport(primarySubViewport);
+ // Set value for series that have not explicitly set this value
+ foreach (QAbstract3DSeries *series, m_seriesList) {
+ if (!series->d_ptr->m_themeTracker.singleHighlightColorOverride) {
+ series->setSingleHighlightColor(color);
+ series->d_ptr->m_themeTracker.singleHighlightColorOverride = false;
+ }
+ }
+ markSeriesVisualsDirty();
}
-QRect Abstract3DController::secondarySubViewport() const
+void Abstract3DController::handleThemeSingleHighlightGradientChanged(const QLinearGradient &gradient)
{
- return m_scene->secondarySubViewport();
+ // Set value for series that have not explicitly set this value
+ foreach (QAbstract3DSeries *series, m_seriesList) {
+ if (!series->d_ptr->m_themeTracker.singleHighlightGradientOverride) {
+ series->setSingleHighlightGradient(gradient);
+ series->d_ptr->m_themeTracker.singleHighlightGradientOverride = false;
+ }
+ }
+ markSeriesVisualsDirty();
}
-void Abstract3DController::setSecondarySubViewport(const QRect &secondarySubViewport)
+void Abstract3DController::handleThemeMultiHighlightColorChanged(const QColor &color)
{
- m_scene->setSecondarySubViewport(secondarySubViewport);
+ // Set value for series that have not explicitly set this value
+ foreach (QAbstract3DSeries *series, m_seriesList) {
+ if (!series->d_ptr->m_themeTracker.multiHighlightColorOverride) {
+ series->setMultiHighlightColor(color);
+ series->d_ptr->m_themeTracker.multiHighlightColorOverride = false;
+ }
+ }
+ markSeriesVisualsDirty();
}
-void Abstract3DController::updateDevicePixelRatio(qreal ratio)
+void Abstract3DController::handleThemeMultiHighlightGradientChanged(const QLinearGradient &gradient)
{
- m_scene->setDevicePixelRatio(ratio);
+ // Set value for series that have not explicitly set this value
+ foreach (QAbstract3DSeries *series, m_seriesList) {
+ if (!series->d_ptr->m_themeTracker.multiHighlightGradientOverride) {
+ series->setMultiHighlightGradient(gradient);
+ series->d_ptr->m_themeTracker.multiHighlightGradientOverride = false;
+ }
+ }
+ markSeriesVisualsDirty();
}
void Abstract3DController::setAxisX(Q3DAbstractAxis *axis)
@@ -532,64 +520,6 @@ QList<Q3DAbstractAxis *> Abstract3DController::axes() const
return m_axes;
}
-QAbstractDataProxy *Abstract3DController::activeDataProxy() const
-{
- return m_data;
-}
-
-void Abstract3DController::addDataProxy(QAbstractDataProxy *proxy)
-{
- Q_ASSERT(proxy);
- Abstract3DController *owner = qobject_cast<Abstract3DController *>(proxy->parent());
- if (owner != this) {
- Q_ASSERT_X(!owner, "addDataProxy", "Proxy already attached to a graph.");
- proxy->setParent(this);
- }
- if (!m_dataProxies.contains(proxy))
- m_dataProxies.append(proxy);
-}
-
-void Abstract3DController::releaseDataProxy(QAbstractDataProxy *proxy)
-{
- if (proxy && m_dataProxies.contains(proxy)) {
- // Clear the default status from released default proxies
- if (proxy->d_ptr->isDefaultProxy())
- proxy->d_ptr->setDefaultProxy(false);
-
- // If the proxy is in use, replace it with a temporary one
- if (m_data == proxy)
- setActiveDataProxy(0);
-
- m_dataProxies.removeAll(proxy);
- proxy->setParent(0);
- }
-}
-
-QList<QAbstractDataProxy *> Abstract3DController::dataProxies() const
-{
- return m_dataProxies;
-}
-
-void Abstract3DController::setActiveDataProxy(QAbstractDataProxy *proxy)
-{
- // If existing proxy is the default proxy, delete it
- if (m_data) {
- if (m_data->d_ptr->isDefaultProxy()) {
- m_dataProxies.removeAll(m_data);
- delete m_data;
- } else {
- // Disconnect the old proxy from use
- QObject::disconnect(m_data, 0, this, 0);
- }
- }
-
- // Assume ownership and activate
- addDataProxy(proxy);
- m_data = proxy;
- m_isDataDirty = true;
- emitNeedRender();
-}
-
void Abstract3DController::addInputHandler(QAbstract3DInputHandler *inputHandler)
{
Q_ASSERT(inputHandler);
@@ -665,110 +595,55 @@ void Abstract3DController::setZoomLevel(int zoomLevel)
emitNeedRender();
}
-void Abstract3DController::setObjectColor(const QColor &baseColor, bool uniform)
+void Abstract3DController::setTheme(Q3DTheme *theme)
{
- m_theme.m_baseColor = baseColor;
- m_theme.m_uniformColor = uniform;
-
- m_changeTracker.themeChanged = true;
- emitNeedRender();
-}
-
-QColor Abstract3DController::objectColor() const
-{
- return m_theme.m_baseColor;
-}
-
-void Abstract3DController::setTheme(QDataVis::Theme theme)
-{
- m_theme.useTheme(theme);
-
- m_changeTracker.themeChanged = true;
- emitNeedRender();
-}
-
-Theme Abstract3DController::theme()
-{
- return m_theme;
-}
-
-void Abstract3DController::setFont(const QFont &font)
-{
- m_font = font;
-
- m_changeTracker.fontChanged = true;
- emitNeedRender();
+ if (theme != m_themeManager->theme()) {
+ m_themeManager->setTheme(theme);
+ m_changeTracker.themeChanged = true;
+ // Reset all attached series to the new theme
+ for (int i = 0; i < m_seriesList.size(); i++)
+ m_seriesList.at(i)->d_ptr->resetToTheme(*theme, i, true);
+ markSeriesVisualsDirty();
+ emit themeChanged(theme);
+ }
}
-QFont Abstract3DController::font()
+Q3DTheme *Abstract3DController::theme() const
{
- return m_font;
+ return m_themeManager->theme();
}
-void Abstract3DController::setSelectionMode(QDataVis::SelectionMode mode)
+void Abstract3DController::setSelectionMode(QDataVis::SelectionFlags mode)
{
- m_selectionMode = mode;
- m_changeTracker.selectionModeChanged = true;
- emitNeedRender();
+ if (mode != m_selectionMode) {
+ m_selectionMode = mode;
+ m_changeTracker.selectionModeChanged = true;
+ emit selectionModeChanged(mode);
+ emitNeedRender();
+ }
}
-QDataVis::SelectionMode Abstract3DController::selectionMode()
+QDataVis::SelectionFlags Abstract3DController::selectionMode() const
{
return m_selectionMode;
}
void Abstract3DController::setShadowQuality(QDataVis::ShadowQuality quality)
{
- m_shadowQuality = quality;
-
- m_changeTracker.shadowQualityChanged = true;
- emit shadowQualityChanged(m_shadowQuality);
- emitNeedRender();
+ if (quality != m_shadowQuality) {
+ m_shadowQuality = quality;
+ m_changeTracker.shadowQualityChanged = true;
+ emit shadowQualityChanged(m_shadowQuality);
+ emitNeedRender();
+ }
}
-QDataVis::ShadowQuality Abstract3DController::shadowQuality()
+QDataVis::ShadowQuality Abstract3DController::shadowQuality() const
{
return m_shadowQuality;
}
-void Abstract3DController::setLabelStyle(QDataVis::LabelStyle style)
-{
- m_labelStyle = style;
-
- m_changeTracker.labelStyleChanged = true;
- emitNeedRender();
-}
-
-QDataVis::LabelStyle Abstract3DController::labelStyle()
-{
- return m_labelStyle;
-}
-
-void Abstract3DController::setBackgroundEnabled(bool enable)
-{
- m_isBackgroundEnabled = enable;
- m_changeTracker.backgroundEnabledChanged = true;
- emitNeedRender();
-}
-
-bool Abstract3DController::backgroundEnabled()
-{
- return m_isBackgroundEnabled;
-}
-
-void Abstract3DController::setGridEnabled(bool enable)
-{
- m_isGridEnabled = enable;
- m_changeTracker.gridEnabledChanged = true;
- emitNeedRender();
-}
-
-bool Abstract3DController::gridEnabled()
-{
- return m_isGridEnabled;
-}
-
-bool Abstract3DController::isSlicingActive()
+bool Abstract3DController::isSlicingActive() const
{
return m_scene->isSlicingActive();
}
@@ -779,37 +654,21 @@ void Abstract3DController::setSlicingActive(bool isSlicing)
emitNeedRender();
}
-QDataVis::InputState Abstract3DController::inputState()
-{
- if (m_activeInputHandler)
- return m_activeInputHandler->inputState();
- else
- return QDataVis::InputStateNone;
-}
-
-QPoint Abstract3DController::inputPosition()
+Q3DScene *Abstract3DController::scene()
{
- if (m_activeInputHandler)
- return m_activeInputHandler->inputPosition();
- else
- return QPoint(0,0);
+ return m_scene;
}
-void Abstract3DController::setMeshFileName(const QString &fileName)
+void Abstract3DController::markDataDirty()
{
- m_objFile = fileName;
- m_changeTracker.objFileChanged = true;
+ m_isDataDirty = true;
emitNeedRender();
}
-QString Abstract3DController::meshFileName()
-{
- return m_objFile;
-}
-
-Q3DScene *Abstract3DController::scene()
+void Abstract3DController::markSeriesVisualsDirty()
{
- return m_scene;
+ m_isSeriesVisualsDirty = true;
+ emitNeedRender();
}
void Abstract3DController::handleAxisTitleChanged(const QString &title)
@@ -849,7 +708,7 @@ void Abstract3DController::handleAxisLabelsChangedBySender(QObject *sender)
emitNeedRender();
}
-void Abstract3DController::handleAxisRangeChanged(qreal min, qreal max)
+void Abstract3DController::handleAxisRangeChanged(float min, float max)
{
Q_UNUSED(min)
Q_UNUSED(max)
@@ -927,6 +786,38 @@ void Abstract3DController::handleAxisLabelFormatChanged(const QString &format)
handleAxisLabelFormatChangedBySender(sender());
}
+void Abstract3DController::handleInputStateChanged(QAbstract3DInputHandler::InputState state)
+{
+ // When in automatic slicing mode, input state change to overview disables slice mode
+ if (m_selectionMode.testFlag(QDataVis::SelectionSlice)
+ && state == QAbstract3DInputHandler::InputStateOnPrimaryView) {
+ setSlicingActive(false);
+ }
+
+ m_changeTracker.inputStateChanged = true;
+ emitNeedRender();
+}
+
+void Abstract3DController::handleInputPositionChanged(const QPoint &position)
+{
+ Q_UNUSED(position)
+
+ m_changeTracker.inputPositionChanged = true;
+ emitNeedRender();
+}
+
+void Abstract3DController::handleSeriesVisibilityChanged(bool visible)
+{
+ Q_UNUSED(visible)
+
+ handleSeriesVisibilityChangedBySender(sender());
+}
+
+void Abstract3DController::handleRequestShadowQuality(QDataVis::ShadowQuality quality)
+{
+ setShadowQuality(quality);
+}
+
void Abstract3DController::handleAxisLabelFormatChangedBySender(QObject *sender)
{
// Label format changing needs to dirty the data so that labels are reset.
@@ -945,6 +836,15 @@ void Abstract3DController::handleAxisLabelFormatChangedBySender(QObject *sender)
emitNeedRender();
}
+void Abstract3DController::handleSeriesVisibilityChangedBySender(QObject *sender)
+{
+ Q_UNUSED(sender)
+
+ m_isDataDirty = true;
+ m_isSeriesVisibilityDirty = true;
+ emitNeedRender();
+}
+
void Abstract3DController::setAxisHelper(Q3DAbstractAxis::AxisOrientation orientation,
Q3DAbstractAxis *axis, Q3DAbstractAxis **axisPtr)
{
@@ -1024,12 +924,7 @@ Q3DAbstractAxis *Abstract3DController::createDefaultAxis(Q3DAbstractAxis::AxisOr
Q3DValueAxis *Abstract3DController::createDefaultValueAxis()
{
// Default value axis has single segment, empty label format, and auto scaling
- // TODO: Grid should be also hidden, but that is not currently controlled by axis
Q3DValueAxis *defaultAxis = new Q3DValueAxis;
- defaultAxis->setSegmentCount(1);
- defaultAxis->setSubSegmentCount(1);
- defaultAxis->setAutoAdjustRange(true);
- defaultAxis->setLabelFormat(QString());
defaultAxis->d_ptr->setDefaultAxis(true);
return defaultAxis;
@@ -1038,9 +933,7 @@ Q3DValueAxis *Abstract3DController::createDefaultValueAxis()
Q3DCategoryAxis *Abstract3DController::createDefaultCategoryAxis()
{
// Default category axis has no labels
- // TODO: Grid should be also hidden, but that is not currently controlled by axis.
Q3DCategoryAxis *defaultAxis = new Q3DCategoryAxis;
- defaultAxis->setAutoAdjustRange(true);
defaultAxis->d_ptr->setDefaultAxis(true);
return defaultAxis;
}
diff --git a/src/datavisualization/engine/abstract3dcontroller_p.h b/src/datavisualization/engine/abstract3dcontroller_p.h
index f17c6c4d..c56b8a72 100644
--- a/src/datavisualization/engine/abstract3dcontroller_p.h
+++ b/src/datavisualization/engine/abstract3dcontroller_p.h
@@ -26,19 +26,19 @@
//
// We mean it.
-#ifndef CONTROLLER3DBASE_H
-#define CONTROLLER3DBASE_H
+#ifndef ABSTRACT3DCONTROLLER_P_H
+#define ABSTRACT3DCONTROLLER_P_H
#include "datavisualizationglobal_p.h"
-#include "theme_p.h"
#include "q3dabstractaxis.h"
#include "drawer_p.h"
#include "qabstract3dinputhandler.h"
#include "qabstractdataproxy.h"
-#include "q3dscene.h"
+#include "q3dscene_p.h"
#include "q3dbox.h"
#include <QObject>
+#include <QLinearGradient>
class QFont;
@@ -46,55 +46,45 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class CameraHelper;
class Abstract3DRenderer;
+class QAbstract3DSeries;
+class ThemeManager;
struct Abstract3DChangeBitField {
- bool positionChanged : 1;
- bool zoomLevelChanged : 1;
- bool themeChanged : 1;
- bool fontChanged : 1;
- bool labelStyleChanged : 1;
- bool boundingRectChanged : 1;
- bool sizeChanged : 1;
- bool shadowQualityChanged : 1;
- bool selectionModeChanged : 1;
- bool objFileChanged : 1;
- bool gridEnabledChanged : 1;
- bool backgroundEnabledChanged : 1;
- bool axisXTypeChanged : 1;
- bool axisYTypeChanged : 1;
- bool axisZTypeChanged : 1;
- bool axisXTitleChanged : 1;
- bool axisYTitleChanged : 1;
- bool axisZTitleChanged : 1;
- bool axisXLabelsChanged : 1;
- bool axisYLabelsChanged : 1;
- bool axisZLabelsChanged : 1;
- bool axisXRangeChanged : 1;
- bool axisYRangeChanged : 1;
- bool axisZRangeChanged : 1;
- bool axisXSegmentCountChanged : 1;
- bool axisYSegmentCountChanged : 1;
- bool axisZSegmentCountChanged : 1;
- bool axisXSubSegmentCountChanged : 1;
- bool axisYSubSegmentCountChanged : 1;
- bool axisZSubSegmentCountChanged : 1;
- bool axisXLabelFormatChanged : 1;
- bool axisYLabelFormatChanged : 1;
- bool axisZLabelFormatChanged : 1;
+ bool zoomLevelChanged : 1;
+ bool themeChanged : 1;
+ bool shadowQualityChanged : 1;
+ bool selectionModeChanged : 1;
+ bool objFileChanged : 1;
+ bool axisXTypeChanged : 1;
+ bool axisYTypeChanged : 1;
+ bool axisZTypeChanged : 1;
+ bool axisXTitleChanged : 1;
+ bool axisYTitleChanged : 1;
+ bool axisZTitleChanged : 1;
+ bool axisXLabelsChanged : 1;
+ bool axisYLabelsChanged : 1;
+ bool axisZLabelsChanged : 1;
+ bool axisXRangeChanged : 1;
+ bool axisYRangeChanged : 1;
+ bool axisZRangeChanged : 1;
+ bool axisXSegmentCountChanged : 1;
+ bool axisYSegmentCountChanged : 1;
+ bool axisZSegmentCountChanged : 1;
+ bool axisXSubSegmentCountChanged : 1;
+ bool axisYSubSegmentCountChanged : 1;
+ bool axisZSubSegmentCountChanged : 1;
+ bool axisXLabelFormatChanged : 1;
+ bool axisYLabelFormatChanged : 1;
+ bool axisZLabelFormatChanged : 1;
+ bool inputStateChanged : 1;
+ bool inputPositionChanged : 1;
Abstract3DChangeBitField() :
- positionChanged(true),
zoomLevelChanged(true),
themeChanged(true),
- fontChanged(true),
- labelStyleChanged(true),
- boundingRectChanged(true),
- sizeChanged(true),
shadowQualityChanged(true),
selectionModeChanged(true),
objFileChanged(true),
- gridEnabledChanged(true),
- backgroundEnabledChanged(true),
axisXTypeChanged(true),
axisYTypeChanged(true),
axisZTypeChanged(true),
@@ -143,18 +133,11 @@ public:
private:
Abstract3DChangeBitField m_changeTracker;
- QRect m_boundingRect;
GLfloat m_horizontalRotation;
GLfloat m_verticalRotation;
- Theme m_theme;
- QFont m_font;
- QDataVis::SelectionMode m_selectionMode;
+ ThemeManager *m_themeManager;
+ QDataVis::SelectionFlags m_selectionMode;
QDataVis::ShadowQuality m_shadowQuality;
- QDataVis::LabelStyle m_labelStyle;
- bool m_isBackgroundEnabled;
- bool m_isGridEnabled;
- QString m_objFile;
-
Q3DScene *m_scene;
protected:
@@ -169,51 +152,26 @@ protected:
QList<Q3DAbstractAxis *> m_axes; // List of all added axes
Abstract3DRenderer *m_renderer;
bool m_isDataDirty;
-
- QAbstractDataProxy *m_data;
- QList<QAbstractDataProxy *> m_dataProxies;
-
+ bool m_isSeriesVisibilityDirty;
+ bool m_isSeriesVisualsDirty;
bool m_renderPending;
- explicit Abstract3DController(QRect boundRect, QObject *parent = 0);
+ QList<QAbstract3DSeries *> m_seriesList;
+
+ explicit Abstract3DController(QRect initialViewport, QObject *parent = 0);
virtual ~Abstract3DController();
public:
inline bool isInitialized() { return (m_renderer != 0); }
-
- /**
- * @brief synchDataToRenderer Called on the render thread while main GUI thread is blocked before rendering.
- */
virtual void synchDataToRenderer();
-
virtual void render(const GLuint defaultFboHandle = 0);
-
- /**
- * @brief setRenderer Sets the renderer to be used. isInitialized returns true from this point onwards.
- * @param renderer Renderer to be used.
- */
+ virtual void initializeOpenGL() = 0;
void setRenderer(Abstract3DRenderer *renderer);
- // Size
- virtual void setSize(const int width, const int height);
- virtual const QSize size();
- virtual const QRect boundingRect();
- virtual void setBoundingRect(const QRect boundingRect);
- virtual void setWidth(const int width);
- virtual int width();
- virtual void setHeight(const int height);
- virtual int height();
- virtual void setX(const int x);
- virtual int x();
- virtual void setY(const int y);
- virtual int y();
-
- virtual QRect primarySubViewport() const;
- virtual void setPrimarySubViewport(const QRect &primarySubViewport);
-
- virtual QRect secondarySubViewport() const;
- virtual void setSecondarySubViewport(const QRect &secondarySubViewport);
+ virtual void addSeries(QAbstract3DSeries *series);
+ virtual void removeSeries(QAbstract3DSeries *series);
+ QList<QAbstract3DSeries *> seriesList();
virtual void setAxisX(Q3DAbstractAxis *axis);
virtual Q3DAbstractAxis *axisX();
@@ -230,63 +188,27 @@ public:
virtual void setActiveInputHandler(QAbstract3DInputHandler *inputHandler);
virtual QAbstract3DInputHandler *activeInputHandler();
- virtual QAbstractDataProxy *activeDataProxy() const;
- virtual void addDataProxy(QAbstractDataProxy *proxy);
- virtual void releaseDataProxy(QAbstractDataProxy *proxy);
- virtual QList<QAbstractDataProxy *> dataProxies() const;
- virtual void setActiveDataProxy(QAbstractDataProxy *proxy);
- virtual void updateDevicePixelRatio(qreal ratio);
-
virtual int zoomLevel();
virtual void setZoomLevel(int zoomLevel);
- // Set color if you don't want to use themes.
- virtual void setObjectColor(const QColor &baseColor, bool uniform = true);
- virtual QColor objectColor() const;
-
- // Set theme (bar colors, shaders, window color, background colors, light intensity and text
- // colors are affected)
- virtual void setTheme(QDataVis::Theme theme);
- virtual Theme theme();
+ virtual void setTheme(Q3DTheme *theme);
+ virtual Q3DTheme *theme() const;
- // Set font
- virtual void setFont(const QFont &font);
- virtual QFont font();
+ virtual void setSelectionMode(QDataVis::SelectionFlags mode);
+ virtual QDataVis::SelectionFlags selectionMode() const;
- // Selection mode
- virtual void setSelectionMode(QDataVis::SelectionMode mode);
- virtual QDataVis::SelectionMode selectionMode();
-
- // Adjust shadow quality
virtual void setShadowQuality(QDataVis::ShadowQuality quality);
- virtual QDataVis::ShadowQuality shadowQuality();
-
- // Label style adjustment
- virtual void setLabelStyle(QDataVis::LabelStyle style);
- virtual QDataVis::LabelStyle labelStyle();
+ virtual QDataVis::ShadowQuality shadowQuality() const;
- // Enable or disable background mesh
- virtual void setBackgroundEnabled(bool enable);
- virtual bool backgroundEnabled();
-
- // Enable or disable background grid
- virtual void setGridEnabled(bool enable);
- virtual bool gridEnabled();
-
- // Query input state and position
- QDataVis::InputState inputState();
- QPoint inputPosition();
-
- // Enable or disable slicing mode
- bool isSlicingActive();
+ bool isSlicingActive() const;
void setSlicingActive(bool isSlicing);
+ Q3DScene *scene();
- // override bar type with own mesh
- virtual void setMeshFileName(const QString &fileName);
- virtual QString meshFileName();
+ void markDataDirty();
+ void markSeriesVisualsDirty();
- Q3DScene *scene();
+ void emitNeedRender();
virtual void mouseDoubleClickEvent(QMouseEvent *event);
virtual void touchEvent(QTouchEvent *event);
@@ -303,32 +225,50 @@ public:
virtual void handleAxisAutoAdjustRangeChangedInOrientation(
Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust) = 0;
virtual void handleAxisLabelFormatChangedBySender(QObject *sender);
+ virtual void handleSeriesVisibilityChangedBySender(QObject *sender);
public slots:
void handleAxisTitleChanged(const QString &title);
void handleAxisLabelsChanged();
- void handleAxisRangeChanged(qreal min, qreal max);
+ void handleAxisRangeChanged(float min, float max);
void handleAxisSegmentCountChanged(int count);
void handleAxisSubSegmentCountChanged(int count);
void handleAxisAutoAdjustRangeChanged(bool autoAdjust);
void handleAxisLabelFormatChanged(const QString &format);
+ void handleInputStateChanged(QAbstract3DInputHandler::InputState state);
+ void handleInputPositionChanged(const QPoint &position);
+ void handleSeriesVisibilityChanged(bool visible);
+
+ void handleThemeColorStyleChanged(Q3DTheme::ColorStyle style);
+ void handleThemeBaseColorsChanged(const QList<QColor> &color);
+ void handleThemeBaseGradientsChanged(const QList<QLinearGradient> &gradient);
+ void handleThemeSingleHighlightColorChanged(const QColor &color);
+ void handleThemeSingleHighlightGradientChanged(const QLinearGradient &gradient);
+ void handleThemeMultiHighlightColorChanged(const QColor &color);
+ void handleThemeMultiHighlightGradientChanged(const QLinearGradient &gradient);
+
+ // Renderer callback handlers
+ void handleRequestShadowQuality(QDataVis::ShadowQuality quality);
signals:
void shadowQualityChanged(QDataVis::ShadowQuality quality);
void activeInputHandlerChanged(QAbstract3DInputHandler *inputHandler);
+ void themeChanged(Q3DTheme *theme);
+ void selectionModeChanged(QDataVis::SelectionFlags mode);
void needRender();
protected:
virtual Q3DAbstractAxis *createDefaultAxis(Q3DAbstractAxis::AxisOrientation orientation);
Q3DValueAxis *createDefaultValueAxis();
Q3DCategoryAxis *createDefaultCategoryAxis();
- void emitNeedRender();
private:
void setAxisHelper(Q3DAbstractAxis::AxisOrientation orientation, Q3DAbstractAxis *axis,
Q3DAbstractAxis **axisPtr);
+
+ friend class Bars3DController;
};
QT_DATAVISUALIZATION_END_NAMESPACE
-#endif // CONTROLLER3DBASE_H
+#endif
diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp
index eef810df..74088b7c 100644
--- a/src/datavisualization/engine/abstract3drenderer.cpp
+++ b/src/datavisualization/engine/abstract3drenderer.cpp
@@ -23,24 +23,27 @@
#include "q3dscene_p.h"
#include "q3dcamera_p.h"
#include "q3dlight_p.h"
+#include "qabstract3dseries_p.h"
+#include "q3dtheme_p.h"
+#include "objecthelper_p.h"
+
+Q_DECLARE_METATYPE(QtDataVisualization::QDataVis::ShadowQuality)
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller)
: QObject(0),
- m_controller(controller),
m_hasNegativeValues(false),
- m_cachedTheme(),
- m_cachedFont(QFont(QStringLiteral("Arial"))),
- m_cachedLabelStyle(QDataVis::LabelStyleFromTheme),
- m_drawer(new Drawer(m_cachedTheme, m_cachedFont, m_cachedLabelStyle)),
- m_cachedBoundingRect(QRect(0,0,0,0)),
+ m_cachedTheme(new Q3DTheme()),
+ m_drawer(new Drawer(m_cachedTheme)),
m_cachedShadowQuality(QDataVis::ShadowQualityMedium),
m_autoScaleAdjustment(1.0f),
- m_cachedSelectionMode(QDataVis::SelectionModeNone),
- m_cachedIsGridEnabled(false),
- m_cachedIsBackgroundEnabled(false),
- m_cachedScene(new Q3DScene())
+ m_cachedSelectionMode(QDataVis::SelectionNone),
+ m_textureHelper(0),
+ m_cachedScene(new Q3DScene()),
+ m_selectionDirty(true),
+ m_selectionState(SelectNone),
+ m_devicePixelRatio(1.0f)
#ifdef DISPLAY_RENDER_SPEED
, m_isFirstFrame(true),
m_numFrames(0)
@@ -48,15 +51,21 @@ Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller)
{
QObject::connect(m_drawer, &Drawer::drawerChanged, this, &Abstract3DRenderer::updateTextures);
- QObject::connect(this, &Abstract3DRenderer::needRender, m_controller,
+ QObject::connect(this, &Abstract3DRenderer::needRender, controller,
&Abstract3DController::needRender, Qt::QueuedConnection);
+ QObject::connect(this, &Abstract3DRenderer::requestShadowQuality, controller,
+ &Abstract3DController::handleRequestShadowQuality, Qt::QueuedConnection);
}
Abstract3DRenderer::~Abstract3DRenderer()
{
+ for (int i = 0; i < m_visibleSeriesList.size(); i++)
+ m_visibleSeriesList[i].cleanup(m_textureHelper);
+
delete m_drawer;
delete m_textureHelper;
delete m_cachedScene;
+ delete m_cachedTheme;
}
void Abstract3DRenderer::initializeOpenGL()
@@ -93,7 +102,7 @@ void Abstract3DRenderer::render(const GLuint defaultFboHandle)
// Measure speed (as milliseconds per frame)
m_numFrames++;
if (m_lastFrameTime.elapsed() >= 1000) { // print only if last measurement was more than 1s ago
- qDebug() << qreal(m_lastFrameTime.elapsed()) / qreal(m_numFrames) << "ms/frame (=" << qreal(m_numFrames) << "fps)";
+ qDebug() << float(m_lastFrameTime.elapsed()) / float(m_numFrames) << "ms/frame (=" << float(m_numFrames) << "fps)";
m_numFrames = 0;
m_lastFrameTime.restart();
}
@@ -108,17 +117,17 @@ void Abstract3DRenderer::render(const GLuint defaultFboHandle)
glDisable(GL_BLEND); // For QtQuick2 blending is enabled by default, but we don't want it to be
}
- glViewport(m_cachedScene->viewport().x(),
- m_cachedScene->viewport().y(),
- m_cachedScene->viewport().width(),
- m_cachedScene->viewport().height());
-
- QVector3D clearColor = Utils::vectorFromColor(m_cachedTheme.m_windowColor);
+ // Clear the graph background to the theme color
+ glViewport(m_viewport.x(),
+ m_viewport.y(),
+ m_viewport.width(),
+ m_viewport.height());
+ QVector3D clearColor = Utils::vectorFromColor(m_cachedTheme->windowColor());
glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
-QString Abstract3DRenderer::generateValueLabel(const QString &format, qreal value)
+QString Abstract3DRenderer::generateValueLabel(const QString &format, float value)
{
QString valueLabelFormat = format;
Utils::ParamType valueParamType = Utils::findFormatParamType(valueLabelFormat);
@@ -126,126 +135,140 @@ QString Abstract3DRenderer::generateValueLabel(const QString &format, qreal valu
return Utils::formatLabel(valueFormatArray, valueParamType, value);
}
-void Abstract3DRenderer::updateDataModel(QAbstractDataProxy *dataProxy)
+void Abstract3DRenderer::updateSelectionState(SelectionState state)
{
- m_cachedItemLabelFormat = dataProxy->itemLabelFormat();
+ m_selectionState = state;
}
-QString Abstract3DRenderer::itemLabelFormat() const
+void Abstract3DRenderer::updateInputPosition(const QPoint &position)
{
- return m_cachedItemLabelFormat;
+ m_inputPosition = position;
}
-void Abstract3DRenderer::updateBoundingRect(const QRect &boundingRect)
+void Abstract3DRenderer::initGradientShaders(const QString &vertexShader, const QString &fragmentShader)
{
- m_cachedBoundingRect = boundingRect;
- handleResize();
+ // Do nothing by default
+ Q_UNUSED(vertexShader)
+ Q_UNUSED(fragmentShader)
}
-void Abstract3DRenderer::updatePosition(const QRect &boundingRect)
+void Abstract3DRenderer::updateTheme(Q3DTheme *theme)
{
- m_cachedBoundingRect = boundingRect;
+ // Synchronize the controller theme with renderer
+ bool changed = theme->d_ptr->sync(*m_cachedTheme->d_ptr);
+
+ if (changed) {
+ // Update drawer if sync changed something
+ m_drawer->setTheme(m_cachedTheme);
+ // Re-initialize shaders
+ reInitShaders();
+ }
}
-void Abstract3DRenderer::updateTheme(Theme theme)
+void Abstract3DRenderer::updateScene(Q3DScene *scene)
{
- m_cachedTheme.setFromTheme(theme);
+ m_viewport = scene->d_ptr->glViewport();
+ m_secondarySubViewport = scene->d_ptr->glSecondarySubViewport();
- m_drawer->setTheme(m_cachedTheme);
- // Re-initialize shaders
- handleShadowQualityChange();
-}
+ if (m_primarySubViewport != scene->d_ptr->glPrimarySubViewport()) {
+ // Resize of primary subviewport means resizing shadow and selection buffers
+ m_primarySubViewport = scene->d_ptr->glPrimarySubViewport();
+ handleResize();
+ }
-void Abstract3DRenderer::updateScene(Q3DScene *scene)
-{
- // Synchronize the controller scene to that of the renderer, and vice versa.
- // Controller scene had priority if both have changed same values.
+ if (m_devicePixelRatio != scene->devicePixelRatio()) {
+ m_devicePixelRatio = scene->devicePixelRatio();
+ handleResize();
+ }
+
+ scene->activeCamera()->d_ptr->updateViewMatrix(m_autoScaleAdjustment);
+ // Set light position (rotate light with activeCamera, a bit above it (as set in defaultLightPos))
+ scene->setLightPositionRelativeToCamera(defaultLightPos);
+
+ QPoint logicalPixelPosition = scene->selectionQueryPosition();
+ updateInputPosition(QPoint(logicalPixelPosition.x() * m_devicePixelRatio,
+ logicalPixelPosition.y() * m_devicePixelRatio));
+
+ if (Q3DScene::invalidSelectionPoint() == logicalPixelPosition) {
+ updateSelectionState(SelectNone);
+ } else {
+ // Selections are one-shot, reset selection active to false before processing
+ scene->setSelectionQueryPosition(Q3DScene::invalidSelectionPoint());
+
+ if (scene->isSlicingActive()) {
+ if (scene->isPointInPrimarySubView(logicalPixelPosition))
+ updateSelectionState(SelectOnOverview);
+ else if (scene->isPointInSecondarySubView(logicalPixelPosition))
+ updateSelectionState(SelectOnSlice);
+ else
+ updateSelectionState(SelectNone);
+ } else {
+ updateSelectionState(SelectOnScene);
+ }
+ }
+
+ // Synchronize the controller scene with renderer
scene->d_ptr->sync(*m_cachedScene->d_ptr);
- m_cachedScene->d_ptr->sync(*scene->d_ptr);
}
-void Abstract3DRenderer::handleShadowQualityChange()
+void Abstract3DRenderer::reInitShaders()
{
#if !defined(QT_OPENGL_ES_2)
if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
- if (!m_cachedTheme.m_uniformColor) {
- initShaders(QStringLiteral(":/shaders/vertexShadow"),
- QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY"));
- } else {
- initShaders(QStringLiteral(":/shaders/vertexShadow"),
- QStringLiteral(":/shaders/fragmentShadowNoTex"));
- }
+ initGradientShaders(QStringLiteral(":/shaders/vertexShadow"),
+ QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY"));
+ initShaders(QStringLiteral(":/shaders/vertexShadow"),
+ QStringLiteral(":/shaders/fragmentShadowNoTex"));
initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"),
QStringLiteral(":/shaders/fragmentShadowNoTex"));
} else {
- if (!m_cachedTheme.m_uniformColor) {
- initShaders(QStringLiteral(":/shaders/vertex"),
- QStringLiteral(":/shaders/fragmentColorOnY"));
- } else {
- initShaders(QStringLiteral(":/shaders/vertex"),
- QStringLiteral(":/shaders/fragment"));
- }
+ initGradientShaders(QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragmentColorOnY"));
+ initShaders(QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragment"));
initBackgroundShaders(QStringLiteral(":/shaders/vertex"),
QStringLiteral(":/shaders/fragment"));
}
#else
- if (!m_cachedTheme.m_uniformColor) {
- initShaders(QStringLiteral(":/shaders/vertexES2"),
- QStringLiteral(":/shaders/fragmentColorOnYES2"));
- } else {
- initShaders(QStringLiteral(":/shaders/vertexES2"),
- QStringLiteral(":/shaders/fragmentES2"));
- }
- initBackgroundShaders(QStringLiteral(":/shaders/vertexES2"),
+ initGradientShaders(QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragmentColorOnYES2"));
+ initShaders(QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragmentES2"));
+ initBackgroundShaders(QStringLiteral(":/shaders/vertex"),
QStringLiteral(":/shaders/fragmentES2"));
#endif
}
-void Abstract3DRenderer::updateFont(const QFont &font)
-{
- m_cachedFont = font;
- m_drawer->setFont(font);
-}
-
-void Abstract3DRenderer::updateLabelStyle(QDataVis::LabelStyle style)
+void Abstract3DRenderer::handleShadowQualityChange()
{
- m_cachedLabelStyle = style;
- m_drawer->setStyle(style);
-}
+ reInitShaders();
-void Abstract3DRenderer::updateMeshFileName(const QString &objFileName)
-{
- if (objFileName != m_cachedObjFile) {
- m_cachedObjFile = objFileName;
- loadMeshFile();
+#if defined(QT_OPENGL_ES_2)
+ if (m_cachedShadowQuality != QDataVis::ShadowQualityNone) {
+ emit requestShadowQuality(QDataVis::ShadowQualityNone);
+ qWarning("Shadows are not yet supported for OpenGL ES2");
+ m_cachedShadowQuality = QDataVis::ShadowQualityNone;
}
+#endif
}
-void Abstract3DRenderer::updateSelectionMode(QDataVis::SelectionMode mode)
+void Abstract3DRenderer::updateSelectionMode(QDataVis::SelectionFlags mode)
{
m_cachedSelectionMode = mode;
-}
-
-void Abstract3DRenderer::updateGridEnabled(bool enable)
-{
- m_cachedIsGridEnabled = enable;
-}
-
-void Abstract3DRenderer::updateBackgroundEnabled(bool enable)
-{
- m_cachedIsBackgroundEnabled = enable;
+ m_selectionDirty = true;
}
void Abstract3DRenderer::handleResize()
{
- if (m_cachedBoundingRect.width() == 0 || m_cachedBoundingRect.height() == 0)
+ if (m_primarySubViewport.width() == 0 || m_primarySubViewport.height() == 0)
return;
+
// Calculate zoom level based on aspect ratio
GLfloat div;
GLfloat zoomAdjustment;
- div = qMin(m_cachedBoundingRect.width(), m_cachedBoundingRect.height());
- zoomAdjustment = defaultRatio * ((m_cachedBoundingRect.width() / div)
- / (m_cachedBoundingRect.height() / div));
+ div = qMin(m_primarySubViewport.width(), m_primarySubViewport.height());
+ zoomAdjustment = defaultRatio * ((m_primarySubViewport.width() / div)
+ / (m_primarySubViewport.height() / div));
m_autoScaleAdjustment = qMin(zoomAdjustment, 1.0f); // clamp to 1.0f
// Re-init selection buffer
@@ -272,7 +295,7 @@ void Abstract3DRenderer::updateAxisLabels(Q3DAbstractAxis::AxisOrientation orien
axisCacheForOrientation(orientation).setLabels(labels);
}
-void Abstract3DRenderer::updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, qreal min, qreal max)
+void Abstract3DRenderer::updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, float min, float max)
{
AxisRenderCache &cache = axisCacheForOrientation(orientation);
cache.setMin(min);
@@ -294,6 +317,42 @@ void Abstract3DRenderer::updateAxisLabelFormat(Q3DAbstractAxis::AxisOrientation
axisCacheForOrientation(orientation).setLabelFormat(format);
}
+void Abstract3DRenderer::fixMeshFileName(QString &fileName, QAbstract3DSeries::Mesh mesh)
+{
+ // Default implementation does nothing.
+ Q_UNUSED(fileName)
+ Q_UNUSED(mesh)
+}
+
+void Abstract3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList,
+ bool updateVisibility)
+{
+ int visibleCount = 0;
+ if (updateVisibility) {
+ int oldSize = m_visibleSeriesList.size();
+ foreach (QAbstract3DSeries *current, seriesList) {
+ if (current->isVisible())
+ visibleCount++;
+ }
+
+ // Clean up series caches that are about to be permanently deleted.
+ // Can't just use cache destructor, as resize will call that to all items.
+ if (visibleCount < oldSize) {
+ for (int i = visibleCount; i < oldSize; i++)
+ m_visibleSeriesList[i].cleanup(m_textureHelper);
+ }
+
+ if (visibleCount != oldSize)
+ m_visibleSeriesList.resize(visibleCount);
+
+ visibleCount = 0;
+ }
+ foreach (QAbstract3DSeries *current, seriesList) {
+ if (current->isVisible())
+ m_visibleSeriesList[visibleCount++].populate(current, this);
+ }
+}
+
AxisRenderCache &Abstract3DRenderer::axisCacheForOrientation(Q3DAbstractAxis::AxisOrientation orientation)
{
switch (orientation) {
@@ -309,5 +368,56 @@ AxisRenderCache &Abstract3DRenderer::axisCacheForOrientation(Q3DAbstractAxis::Ax
}
}
+void Abstract3DRenderer::lowerShadowQuality()
+{
+ QDataVis::ShadowQuality newQuality = QDataVis::ShadowQualityNone;
+
+ switch (m_cachedShadowQuality) {
+ case QDataVis::ShadowQualityHigh:
+ qWarning("Creating high quality shadows failed. Changing to medium quality.");
+ newQuality = QDataVis::ShadowQualityMedium;
+ break;
+ case QDataVis::ShadowQualityMedium:
+ qWarning("Creating medium quality shadows failed. Changing to low quality.");
+ newQuality = QDataVis::ShadowQualityLow;
+ break;
+ case QDataVis::ShadowQualityLow:
+ qWarning("Creating low quality shadows failed. Switching shadows off.");
+ newQuality = QDataVis::ShadowQualityNone;
+ break;
+ case QDataVis::ShadowQualitySoftHigh:
+ qWarning("Creating soft high quality shadows failed. Changing to soft medium quality.");
+ newQuality = QDataVis::ShadowQualitySoftMedium;
+ break;
+ case QDataVis::ShadowQualitySoftMedium:
+ qWarning("Creating soft medium quality shadows failed. Changing to soft low quality.");
+ newQuality = QDataVis::ShadowQualitySoftLow;
+ break;
+ case QDataVis::ShadowQualitySoftLow:
+ qWarning("Creating soft low quality shadows failed. Switching shadows off.");
+ newQuality = QDataVis::ShadowQualityNone;
+ break;
+ default:
+ // You'll never get here
+ break;
+ }
+
+ emit requestShadowQuality(newQuality);
+ updateShadowQuality(newQuality);
+}
+
+void Abstract3DRenderer::fixGradientAndGenerateTexture(QLinearGradient *gradient, GLuint *gradientTexture)
+{
+ // Readjust start/stop to match gradient texture size
+ gradient->setStart(qreal(gradientTextureWidth), qreal(gradientTextureHeight));
+ gradient->setFinalStop(0.0, 0.0);
+
+ if (*gradientTexture) {
+ m_textureHelper->deleteTexture(gradientTexture);
+ *gradientTexture = 0;
+ }
+
+ *gradientTexture = m_textureHelper->createGradientTexture(*gradient);
+}
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/abstract3drenderer_p.h b/src/datavisualization/engine/abstract3drenderer_p.h
index 1c61ac07..17a55ac9 100644
--- a/src/datavisualization/engine/abstract3drenderer_p.h
+++ b/src/datavisualization/engine/abstract3drenderer_p.h
@@ -37,6 +37,7 @@
#include "abstract3dcontroller_p.h"
#include "axisrendercache_p.h"
#include "qabstractdataproxy.h"
+#include "seriesrendercache_p.h"
//#define DISPLAY_RENDER_SPEED
@@ -50,90 +51,98 @@ class Abstract3DRenderer : public QObject, protected QOpenGLFunctions
{
Q_OBJECT
-private:
- Abstract3DController *m_controller;
-
protected:
- bool m_hasNegativeValues;
- Theme m_cachedTheme;
- QFont m_cachedFont;
- QDataVis::LabelStyle m_cachedLabelStyle;
- Drawer *m_drawer;
- QRect m_cachedBoundingRect;
- QDataVis::ShadowQuality m_cachedShadowQuality;
- GLfloat m_autoScaleAdjustment;
-
- QString m_cachedItemLabelFormat;
- QString m_cachedObjFile;
- QDataVis::SelectionMode m_cachedSelectionMode;
- bool m_cachedIsGridEnabled;
- bool m_cachedIsBackgroundEnabled;
-
- AxisRenderCache m_axisCacheX;
- AxisRenderCache m_axisCacheY;
- AxisRenderCache m_axisCacheZ;
- TextureHelper *m_textureHelper;
- Q3DBox m_boundingBox;
+ enum SelectionState {
+ SelectNone = 0,
+ SelectOnScene,
+ SelectOnOverview,
+ SelectOnSlice
+ };
- Q3DScene *m_cachedScene;
-
-#ifdef DISPLAY_RENDER_SPEED
- bool m_isFirstFrame;
- QTime m_lastFrameTime;
- GLint m_numFrames;
-#endif
-
- QString generateValueLabel(const QString &format, qreal value);
+ QString generateValueLabel(const QString &format, float value);
public:
virtual ~Abstract3DRenderer();
- void updateDataModel(QAbstractDataProxy *dataProxy);
+ virtual void updateData() = 0;
+ virtual void updateSeries(const QList<QAbstract3DSeries *> &seriesList, bool updateVisibility);
virtual void render(GLuint defaultFboHandle);
- virtual void updateBoundingRect(const QRect &boundingRect);
- virtual void updatePosition(const QRect &boundingRect);
-
- virtual void updateTheme(Theme theme);
- virtual void updateFont(const QFont &font);
- virtual void updateLabelStyle(QDataVis::LabelStyle style);
- virtual void updateSelectionMode(QDataVis::SelectionMode newMode);
- virtual void updateGridEnabled(bool enable);
- virtual void updateBackgroundEnabled(bool enable);
- virtual void updateMeshFileName(const QString &objFileName);
+ virtual void updateTheme(Q3DTheme *theme);
+ virtual void updateSelectionMode(QDataVis::SelectionFlags newMode);
virtual void updateScene(Q3DScene *scene);
- virtual QString itemLabelFormat() const;
virtual void updateTextures() = 0;
virtual void initSelectionBuffer() = 0;
+ virtual void updateSelectionState(SelectionState state);
+ virtual void updateInputPosition(const QPoint &position);
#if !defined(QT_OPENGL_ES_2)
virtual void updateDepthBuffer() = 0;
#endif
virtual void updateShadowQuality(QDataVis::ShadowQuality quality) = 0;
virtual void initShaders(const QString &vertexShader, const QString &fragmentShader) = 0;
+ virtual void initGradientShaders(const QString &vertexShader, const QString &fragmentShader);
virtual void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader) = 0;
virtual void updateAxisType(Q3DAbstractAxis::AxisOrientation orientation, Q3DAbstractAxis::AxisType type);
virtual void updateAxisTitle(Q3DAbstractAxis::AxisOrientation orientation, const QString &title);
virtual void updateAxisLabels(Q3DAbstractAxis::AxisOrientation orientation, const QStringList &labels);
- virtual void updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, qreal min, qreal max);
+ virtual void updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, float min, float max);
virtual void updateAxisSegmentCount(Q3DAbstractAxis::AxisOrientation orientation, int count);
virtual void updateAxisSubSegmentCount(Q3DAbstractAxis::AxisOrientation orientation, int count);
virtual void updateAxisLabelFormat(Q3DAbstractAxis::AxisOrientation orientation, const QString &format);
+ virtual void fixMeshFileName(QString &fileName, QAbstract3DSeries::Mesh mesh);
+ void fixGradientAndGenerateTexture(QLinearGradient *gradient, GLuint *gradientTexture);
+
signals:
void needRender(); // Emit this if something in renderer causes need for another render pass.
+ void requestShadowQuality(QDataVis::ShadowQuality quality); // For automatic quality adjustments
protected:
Abstract3DRenderer(Abstract3DController *controller);
virtual void initializeOpenGL();
+ void reInitShaders();
virtual void handleShadowQualityChange();
virtual void handleResize();
- virtual void loadMeshFile() = 0;
AxisRenderCache &axisCacheForOrientation(Q3DAbstractAxis::AxisOrientation orientation);
+
+ virtual void lowerShadowQuality();
+
+ void fixGradient(QLinearGradient *gradient, GLuint *gradientTexture);
+
+ bool m_hasNegativeValues;
+ Q3DTheme *m_cachedTheme;
+ Drawer *m_drawer;
+ QRect m_viewport;
+ QDataVis::ShadowQuality m_cachedShadowQuality;
+ GLfloat m_autoScaleAdjustment;
+
+ QDataVis::SelectionFlags m_cachedSelectionMode;
+
+ AxisRenderCache m_axisCacheX;
+ AxisRenderCache m_axisCacheY;
+ AxisRenderCache m_axisCacheZ;
+ TextureHelper *m_textureHelper;
+ Q3DBox m_boundingBox;
+
+ Q3DScene *m_cachedScene;
+ bool m_selectionDirty;
+ SelectionState m_selectionState;
+ QPoint m_inputPosition;
+ QVector<SeriesRenderCache> m_visibleSeriesList;
+ QRect m_primarySubViewport;
+ QRect m_secondarySubViewport;
+ float m_devicePixelRatio;
+
+#ifdef DISPLAY_RENDER_SPEED
+ bool m_isFirstFrame;
+ QTime m_lastFrameTime;
+ GLint m_numFrames;
+#endif
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/axisrendercache.cpp b/src/datavisualization/engine/axisrendercache.cpp
index 55ac0765..f7960b2b 100644
--- a/src/datavisualization/engine/axisrendercache.cpp
+++ b/src/datavisualization/engine/axisrendercache.cpp
@@ -24,8 +24,8 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
AxisRenderCache::AxisRenderCache()
: m_type(Q3DAbstractAxis::AxisTypeNone),
- m_min(0.0),
- m_max(10.0),
+ m_min(0.0f),
+ m_max(10.0f),
m_segmentCount(5),
m_subSegmentCount(1),
m_font(QFont(QStringLiteral("Arial"))),
@@ -58,8 +58,8 @@ void AxisRenderCache::setType(Q3DAbstractAxis::AxisType type)
// If type is set, it means completely new axis instance, so clear all old data
m_labels.clear();
m_title.clear();
- m_min = 0.0;
- m_max = 10.0;
+ m_min = 0.0f;
+ m_max = 10.0f;
m_segmentCount = 5;
m_subSegmentCount = 1;
m_labelFormat.clear();
@@ -109,13 +109,13 @@ void AxisRenderCache::setLabels(const QStringList &labels)
}
}
-void AxisRenderCache::setMin(qreal min)
+void AxisRenderCache::setMin(float min)
{
m_min = min;
updateSegmentStep();
}
-void AxisRenderCache::setMax(qreal max)
+void AxisRenderCache::setMax(float max)
{
m_max = max;
updateSegmentStep();
diff --git a/src/datavisualization/engine/axisrendercache_p.h b/src/datavisualization/engine/axisrendercache_p.h
index 0bb1cf92..cddc7839 100644
--- a/src/datavisualization/engine/axisrendercache_p.h
+++ b/src/datavisualization/engine/axisrendercache_p.h
@@ -51,10 +51,10 @@ public:
inline const QString &title() { return m_title; }
void setLabels(const QStringList &labels);
inline const QStringList &labels() { return m_labels; }
- void setMin(qreal min);
- inline qreal min() { return m_min; }
- void setMax(qreal max);
- inline qreal max() { return m_max; }
+ void setMin(float min);
+ inline float min() { return m_min; }
+ void setMax(float max);
+ inline float max() { return m_max; }
void setSegmentCount(int count);
inline int segmentCount() const { return m_segmentCount; }
void setSubSegmentCount(int count);
@@ -79,8 +79,8 @@ private:
Q3DAbstractAxis::AxisType m_type;
QString m_title;
QStringList m_labels;
- qreal m_min;
- qreal m_max;
+ float m_min;
+ float m_max;
int m_segmentCount;
int m_subSegmentCount;
QString m_labelFormat;
diff --git a/src/datavisualization/engine/bars3dcontroller.cpp b/src/datavisualization/engine/bars3dcontroller.cpp
index 2eea6c74..5232a566 100644
--- a/src/datavisualization/engine/bars3dcontroller.cpp
+++ b/src/datavisualization/engine/bars3dcontroller.cpp
@@ -23,6 +23,9 @@
#include "q3dvalueaxis_p.h"
#include "q3dcategoryaxis_p.h"
#include "qbardataproxy_p.h"
+#include "qbar3dseries_p.h"
+#include "thememanager_p.h"
+#include "q3dtheme_p.h"
#include <QMatrix4x4>
#include <qmath.h>
@@ -31,17 +34,13 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
Bars3DController::Bars3DController(QRect boundRect)
: Abstract3DController(boundRect),
- m_selectedBarPos(noSelectionPoint()),
+ m_selectedBar(invalidSelectionPosition()),
+ m_selectedBarSeries(0),
m_isBarSpecRelative(true),
m_barThicknessRatio(1.0f),
m_barSpacing(QSizeF(1.0, 1.0)),
m_renderer(0)
{
- // Default bar type; specific to bars
- setBarType(QDataVis::MeshStyleBevelBars, false);
-
- setActiveDataProxy(0);
-
// Setting a null axis creates a new default axis according to orientation and graph type.
// Note: these cannot be set in the Abstract3DController constructor, as they will call virtual
// functions implemented by subclasses.
@@ -65,13 +64,20 @@ void Bars3DController::initializeOpenGL()
setRenderer(m_renderer);
synchDataToRenderer();
- QObject::connect(m_renderer, &Bars3DRenderer::selectedBarPosChanged, this,
- &Bars3DController::handleSelectedBarPosChanged, Qt::QueuedConnection);
+ QObject::connect(m_renderer, &Bars3DRenderer::barClicked, this,
+ &Bars3DController::handleBarClicked, Qt::QueuedConnection);
emitNeedRender();
}
void Bars3DController::synchDataToRenderer()
{
+ // Background change requires reloading the meshes in bar graphs, so dirty the series visuals
+ if (m_themeManager->theme()->d_ptr->m_dirtyBits.backgroundEnabledDirty) {
+ m_isSeriesVisualsDirty = true;
+ foreach (QAbstract3DSeries *series, m_seriesList)
+ series->d_ptr->m_changeTracker.meshChanged = true;
+ }
+
Abstract3DController::synchDataToRenderer();
if (!isInitialized())
@@ -83,67 +89,19 @@ void Bars3DController::synchDataToRenderer()
m_changeTracker.barSpecsChanged = false;
}
- if (m_changeTracker.selectedBarPosChanged) {
- m_renderer->updateSelectedBarPos(m_selectedBarPos);
- m_changeTracker.selectedBarPosChanged = false;
- }
-
- if (m_isDataDirty) {
- m_renderer->updateDataModel(static_cast<QBarDataProxy *>(m_data));
- m_isDataDirty = false;
+ // Needs to be done after data is set, as it needs to know the visual array.
+ if (m_changeTracker.selectedBarChanged) {
+ m_renderer->updateSelectedBar(m_selectedBar, m_selectedBarSeries);
+ m_changeTracker.selectedBarChanged = false;
}
}
-void Bars3DController::setActiveDataProxy(QAbstractDataProxy *proxy)
-{
- // Setting null proxy indicates default proxy
- if (!proxy) {
- proxy = new QBarDataProxy;
- proxy->d_ptr->setDefaultProxy(true);
- }
-
- Q_ASSERT(proxy->type() == QAbstractDataProxy::DataTypeBar);
-
- Abstract3DController::setActiveDataProxy(proxy);
-
- QBarDataProxy *barDataProxy = static_cast<QBarDataProxy *>(m_data);
-
- QObject::connect(barDataProxy, &QBarDataProxy::arrayReset, this,
- &Bars3DController::handleArrayReset);
- QObject::connect(barDataProxy, &QBarDataProxy::rowsAdded, this,
- &Bars3DController::handleRowsAdded);
- QObject::connect(barDataProxy, &QBarDataProxy::rowsChanged, this,
- &Bars3DController::handleRowsChanged);
- QObject::connect(barDataProxy, &QBarDataProxy::rowsRemoved, this,
- &Bars3DController::handleRowsRemoved);
- QObject::connect(barDataProxy, &QBarDataProxy::rowsInserted, this,
- &Bars3DController::handleRowsInserted);
- QObject::connect(barDataProxy, &QBarDataProxy::itemChanged, this,
- &Bars3DController::handleItemChanged);
- QObject::connect(barDataProxy, &QBarDataProxy::rowLabelsChanged, this,
- &Bars3DController::handleDataRowLabelsChanged);
- QObject::connect(barDataProxy, &QBarDataProxy::columnLabelsChanged, this,
- &Bars3DController::handleDataColumnLabelsChanged);
-
- scene()->setSlicingActive(false);
- adjustAxisRanges();
-
- // Always clear selection on proxy change
- setSelectedBarPos(noSelectionPoint());
-
- handleDataRowLabelsChanged();
- handleDataColumnLabelsChanged();
- m_isDataDirty = true;
- emitNeedRender();
-}
-
void Bars3DController::handleArrayReset()
{
- scene()->setSlicingActive(false);
adjustAxisRanges();
m_isDataDirty = true;
// Clear selection unless still valid
- setSelectedBarPos(m_selectedBarPos);
+ setSelectedBar(m_selectedBar, m_selectedBarSeries);
emitNeedRender();
}
@@ -151,8 +109,6 @@ void Bars3DController::handleRowsAdded(int startIndex, int count)
{
Q_UNUSED(startIndex)
Q_UNUSED(count)
- // TODO should update slice instead of deactivating?
- scene()->setSlicingActive(false);
adjustAxisRanges();
m_isDataDirty = true;
emitNeedRender();
@@ -162,8 +118,6 @@ void Bars3DController::handleRowsChanged(int startIndex, int count)
{
Q_UNUSED(startIndex)
Q_UNUSED(count)
- // TODO should update slice instead of deactivating?
- scene()->setSlicingActive(false);
adjustAxisRanges();
m_isDataDirty = true;
emitNeedRender();
@@ -173,13 +127,11 @@ void Bars3DController::handleRowsRemoved(int startIndex, int count)
{
Q_UNUSED(startIndex)
Q_UNUSED(count)
- // TODO should update slice instead of deactivating?
- scene()->setSlicingActive(false);
adjustAxisRanges();
m_isDataDirty = true;
// Clear selection unless still valid
- setSelectedBarPos(m_selectedBarPos);
+ setSelectedBar(m_selectedBar, m_selectedBarSeries);
emitNeedRender();
}
@@ -188,8 +140,6 @@ void Bars3DController::handleRowsInserted(int startIndex, int count)
{
Q_UNUSED(startIndex)
Q_UNUSED(count)
- // TODO should update slice instead of deactivating?
- scene()->setSlicingActive(false);
adjustAxisRanges();
m_isDataDirty = true;
emitNeedRender();
@@ -199,8 +149,6 @@ void Bars3DController::handleItemChanged(int rowIndex, int columnIndex)
{
Q_UNUSED(rowIndex)
Q_UNUSED(columnIndex)
- // TODO should update slice instead of deactivating?
- scene()->setSlicingActive(false);
adjustAxisRanges();
m_isDataDirty = true;
emitNeedRender();
@@ -208,36 +156,39 @@ void Bars3DController::handleItemChanged(int rowIndex, int columnIndex)
void Bars3DController::handleDataRowLabelsChanged()
{
- if (m_axisX && m_data) {
+ QBar3DSeries *firstSeries = 0;
+ if (m_seriesList.size())
+ firstSeries = static_cast<QBar3DSeries *>(m_seriesList.at(0));
+ if (m_axisZ && firstSeries && firstSeries->dataProxy()) {
// Grab a sublist equal to data window (no need to have more labels in axis)
- int min = int(m_axisX->min());
- int count = int(m_axisX->max()) - min + 1;
- QStringList subList = static_cast<QBarDataProxy *>(m_data)->rowLabels().mid(min, count);
- static_cast<Q3DCategoryAxis *>(m_axisX)->dptr()->setDataLabels(subList);
+ int min = int(m_axisZ->min());
+ int count = int(m_axisZ->max()) - min + 1;
+ QStringList subList = firstSeries->dataProxy()->rowLabels().mid(min, count);
+ static_cast<Q3DCategoryAxis *>(m_axisZ)->dptr()->setDataLabels(subList);
}
}
void Bars3DController::handleDataColumnLabelsChanged()
{
- if (m_axisZ && m_data) {
+ QBar3DSeries *firstSeries = 0;
+ if (m_seriesList.size())
+ firstSeries = static_cast<QBar3DSeries *>(m_seriesList.at(0));
+ if (m_axisX && firstSeries && firstSeries->dataProxy()) {
// Grab a sublist equal to data window (no need to have more labels in axis)
- int min = int(m_axisZ->min());
- int count = int(m_axisZ->max()) - min + 1;
- QStringList subList = static_cast<QBarDataProxy *>(m_data)->columnLabels().mid(min, count);
- static_cast<Q3DCategoryAxis *>(m_axisZ)->dptr()->setDataLabels(subList);
+ int min = int(m_axisX->min());
+ int count = int(m_axisX->max()) - min + 1;
+ QStringList subList = static_cast<QBarDataProxy *>(firstSeries->dataProxy())
+ ->columnLabels().mid(min, count);
+ static_cast<Q3DCategoryAxis *>(m_axisX)->dptr()->setDataLabels(subList);
}
}
-void Bars3DController::handleSelectedBarPosChanged(const QPoint &position)
+void Bars3DController::handleBarClicked(const QPoint &position, QBar3DSeries *series)
{
- QPoint pos = position;
- if (pos == QPoint(255, 255))
- pos = noSelectionPoint();
- if (pos != m_selectedBarPos) {
- m_selectedBarPos = pos;
- emit selectedBarPosChanged(pos);
- emitNeedRender();
- }
+ setSelectedBar(position, series);
+
+ // TODO: pass clicked to parent. (QTRD-2517)
+ // TODO: Also hover needed? (QTRD-2131)
}
void Bars3DController::handleAxisAutoAdjustRangeChangedInOrientation(
@@ -248,41 +199,97 @@ void Bars3DController::handleAxisAutoAdjustRangeChangedInOrientation(
adjustAxisRanges();
}
-QPoint Bars3DController::noSelectionPoint()
+void Bars3DController::handleSeriesVisibilityChangedBySender(QObject *sender)
+{
+ Abstract3DController::handleSeriesVisibilityChangedBySender(sender);
+
+ // Visibility changes may require disabling/enabling slicing,
+ // so just reset selection to ensure everything is still valid.
+ setSelectedBar(m_selectedBar, m_selectedBarSeries);
+}
+
+QPoint Bars3DController::invalidSelectionPosition()
{
- static QPoint noSelectionPos(-1, -1);
- return noSelectionPos;
+ static QPoint invalidSelectionPos(-1, -1);
+ return invalidSelectionPos;
}
void Bars3DController::setAxisX(Q3DAbstractAxis *axis)
{
Abstract3DController::setAxisX(axis);
- handleDataRowLabelsChanged();
+ handleDataColumnLabelsChanged();
}
void Bars3DController::setAxisZ(Q3DAbstractAxis *axis)
{
Abstract3DController::setAxisZ(axis);
- handleDataColumnLabelsChanged();
+ handleDataRowLabelsChanged();
+}
+
+void Bars3DController::addSeries(QAbstract3DSeries *series)
+{
+ Q_ASSERT(series && series->type() == QAbstract3DSeries::SeriesTypeBar);
+
+ bool firstAdded = !m_seriesList.size();
+
+ Abstract3DController::addSeries(series);
+
+ if (firstAdded) {
+ adjustAxisRanges();
+
+ handleDataRowLabelsChanged();
+ handleDataColumnLabelsChanged();
+ }
+
+ QBar3DSeries *barSeries = static_cast<QBar3DSeries *>(series);
+ if (barSeries->selectedBar() != invalidSelectionPosition())
+ setSelectedBar(barSeries->selectedBar(), barSeries);
+}
+
+void Bars3DController::removeSeries(QAbstract3DSeries *series)
+{
+ bool firstRemoved = (m_seriesList.size() && m_seriesList.at(0) == series);
+
+ Abstract3DController::removeSeries(series);
+
+ if (m_selectedBarSeries == series)
+ setSelectedBar(invalidSelectionPosition(), 0);
+
+ if (firstRemoved) {
+ adjustAxisRanges();
+
+ handleDataRowLabelsChanged();
+ handleDataColumnLabelsChanged();
+ }
+}
+
+QList<QBar3DSeries *> Bars3DController::barSeriesList()
+{
+ QList<QAbstract3DSeries *> abstractSeriesList = seriesList();
+ QList<QBar3DSeries *> barSeriesList;
+ foreach (QAbstract3DSeries *abstractSeries, abstractSeriesList) {
+ QBar3DSeries *barSeries = qobject_cast<QBar3DSeries *>(abstractSeries);
+ if (barSeries)
+ barSeriesList.append(barSeries);
+ }
+
+ return barSeriesList;
}
void Bars3DController::handleAxisRangeChangedBySender(QObject *sender)
{
// Data window changed
if (sender == m_axisX || sender == m_axisZ) {
- // Disable zoom mode if we're in it (causes crash if not, as zoom selection is deleted)
- scene()->setSlicingActive(false);
-
- // Clear selection unless still valid
- setSelectedBarPos(m_selectedBarPos);
-
if (sender == m_axisX)
- handleDataRowLabelsChanged();
- if (sender == m_axisZ)
handleDataColumnLabelsChanged();
+ if (sender == m_axisZ)
+ handleDataRowLabelsChanged();
}
Abstract3DController::handleAxisRangeChangedBySender(sender);
+
+ // Update selected bar - may be moved offscreen
+ setSelectedBar(m_selectedBar, m_selectedBarSeries);
}
void Bars3DController::setBarSpecs(GLfloat thicknessRatio, const QSizeF &spacing, bool relative)
@@ -310,109 +317,182 @@ bool Bars3DController::isBarSpecRelative()
return m_isBarSpecRelative;
}
-void Bars3DController::setBarType(QDataVis::MeshStyle style, bool smooth)
-{
- QString objFile;
- if (style == QDataVis::MeshStyleBars)
- objFile = QStringLiteral(":/defaultMeshes/bar");
- else if (style == QDataVis::MeshStylePyramids)
- objFile = QStringLiteral(":/defaultMeshes/pyramid");
- else if (style == QDataVis::MeshStyleCones)
- objFile = QStringLiteral(":/defaultMeshes/cone");
- else if (style == QDataVis::MeshStyleCylinders)
- objFile = QStringLiteral(":/defaultMeshes/cylinder");
- else if (style == QDataVis::MeshStyleBevelBars)
- objFile = QStringLiteral(":/defaultMeshes/bevelbar");
-
- if (smooth)
- objFile += QStringLiteral("Smooth");
-
- Abstract3DController::setMeshFileName(objFile);
-}
-
-void Bars3DController::setSelectionMode(QDataVis::SelectionMode mode)
+void Bars3DController::setSelectionMode(QDataVis::SelectionFlags mode)
{
- // Disable zoom if selection mode changes
- scene()->setSlicingActive(false);
- Abstract3DController::setSelectionMode(mode);
+ if (mode.testFlag(QDataVis::SelectionSlice)
+ && (mode.testFlag(QDataVis::SelectionRow) == mode.testFlag(QDataVis::SelectionColumn))) {
+ qWarning("Must specify one of either row or column selection mode in conjunction with slicing mode.");
+ } else {
+ QDataVis::SelectionFlags oldMode = selectionMode();
+
+ Abstract3DController::setSelectionMode(mode);
+
+ if (mode != oldMode) {
+ // Refresh selection upon mode change to ensure slicing is correctly updated
+ // according to series the visibility.
+ setSelectedBar(m_selectedBar, m_selectedBarSeries);
+
+ // Special case: Always deactivate slicing when changing away from slice
+ // automanagement, as this can't be handled in setSelectedBar.
+ if (!mode.testFlag(QDataVis::SelectionSlice)
+ && oldMode.testFlag(QDataVis::SelectionSlice)) {
+ scene()->setSlicingActive(false);
+ }
+ }
+ }
}
-void Bars3DController::setSelectedBarPos(const QPoint &position)
+void Bars3DController::setSelectedBar(const QPoint &position, QBar3DSeries *series)
{
- // If the selection is outside data window or targets non-existent
- // bar, clear selection instead.
+ // If the selection targets non-existent bar, clear selection instead.
QPoint pos = position;
- if (pos != noSelectionPoint()) {
- int minRow = int(m_axisX->min());
- int maxRow = int(m_axisX->max());
- int minCol = int(m_axisZ->min());
- int maxCol = int(m_axisZ->max());
+ // Series may already have been removed, so check it before setting the selection.
+ if (!m_seriesList.contains(series))
+ series = 0;
+
+ adjustSelectionPosition(pos, series);
- if (pos.x() < minRow || pos.x() > maxRow || pos.y() < minCol || pos.y() > maxCol
- || pos.x() + minRow >= static_cast<QBarDataProxy *>(m_data)->rowCount()
- || pos.y() + minCol >= static_cast<QBarDataProxy *>(m_data)->rowAt(pos.x())->size()) {
- pos = noSelectionPoint();
+ if (selectionMode().testFlag(QDataVis::SelectionSlice)) {
+ // If the selected bar is outside data window, or there is no visible selected bar, disable slicing
+ if (pos.x() < m_axisZ->min() || pos.x() > m_axisZ->max()
+ || pos.y() < m_axisX->min() || pos.y() > m_axisX->max()
+ || !series->isVisible()) {
+ scene()->setSlicingActive(false);
+ } else {
+ scene()->setSlicingActive(true);
}
+ emitNeedRender();
}
- if (pos != m_selectedBarPos) {
- m_selectedBarPos = pos;
- m_changeTracker.selectedBarPosChanged = true;
- emit selectedBarPosChanged(pos);
+ if (pos != m_selectedBar || series != m_selectedBarSeries) {
+ m_selectedBar = pos;
+ m_selectedBarSeries = series;
+ m_changeTracker.selectedBarChanged = true;
+
+ // Clear selection from other series and finally set new selection to the specified series
+ foreach (QAbstract3DSeries *otherSeries, m_seriesList) {
+ QBar3DSeries *barSeries = static_cast<QBar3DSeries *>(otherSeries);
+ if (barSeries != m_selectedBarSeries)
+ barSeries->dptr()->setSelectedBar(invalidSelectionPosition());
+ }
+ if (m_selectedBarSeries)
+ m_selectedBarSeries->dptr()->setSelectedBar(m_selectedBar);
+
emitNeedRender();
}
}
-QPoint Bars3DController::selectedBarPos() const
-{
- return m_selectedBarPos;
-}
-
void Bars3DController::adjustAxisRanges()
{
- const QBarDataProxy *proxy = static_cast<QBarDataProxy *>(m_data);
- const QBarDataArray *array = proxy->array();
-
+ Q3DCategoryAxis *categoryAxisZ = static_cast<Q3DCategoryAxis *>(m_axisZ);
Q3DCategoryAxis *categoryAxisX = static_cast<Q3DCategoryAxis *>(m_axisX);
- if (categoryAxisX && categoryAxisX->isAutoAdjustRange() && proxy) {
- int rowCount = proxy->rowCount();
- if (rowCount)
- rowCount--;
- categoryAxisX->dptr()->setRange(0.0, qreal(rowCount));
- }
+ Q3DValueAxis *valueAxis = static_cast<Q3DValueAxis *>(m_axisY);
- Q3DCategoryAxis *categoryAxisZ = static_cast<Q3DCategoryAxis *>(m_axisZ);
- if (categoryAxisZ && categoryAxisZ->isAutoAdjustRange() && proxy) {
- int columnCount = 0;
- for (int i = 0; i < array->size(); i++) {
- if (columnCount < array->at(i)->size())
- columnCount = array->at(i)->size();
+ bool adjustZ = (categoryAxisZ && categoryAxisZ->isAutoAdjustRange());
+ bool adjustX = (categoryAxisX && categoryAxisX->isAutoAdjustRange());
+ bool adjustY = (valueAxis && categoryAxisX && categoryAxisZ && valueAxis->isAutoAdjustRange());
+
+ if (adjustZ || adjustX || adjustY) {
+ int maxRowCount = 1;
+ int maxColumnCount = 1;
+ float minValue = 0.0f;
+ float maxValue = 0.0f;
+
+ // First figure out row and column counts
+ int seriesCount = m_seriesList.size();
+ if (adjustZ || adjustX) {
+ for (int series = 0; series < seriesCount; series++) {
+ const QBar3DSeries *barSeries = static_cast<QBar3DSeries *>(m_seriesList.at(series));
+ if (barSeries->isVisible()) {
+ const QBarDataProxy *proxy = barSeries->dataProxy();
+
+ if (adjustZ && proxy) {
+ int rowCount = proxy->rowCount();
+ if (rowCount)
+ rowCount--;
+
+ maxRowCount = qMax(maxRowCount, rowCount);
+ }
+
+ if (adjustX && proxy) {
+ const QBarDataArray *array = proxy->array();
+ int columnCount = 0;
+ for (int i = 0; i < array->size(); i++) {
+ if (columnCount < array->at(i)->size())
+ columnCount = array->at(i)->size();
+ }
+ if (columnCount)
+ columnCount--;
+
+ maxColumnCount = qMax(maxColumnCount, columnCount);
+ }
+ }
+ }
+ // Call private implementations of setRange to avoid unsetting auto adjust flag
+ if (adjustZ)
+ categoryAxisZ->dptr()->setRange(0.0f, float(maxRowCount));
+ if (adjustX)
+ categoryAxisX->dptr()->setRange(0.0f, float(maxColumnCount));
}
- if (columnCount)
- columnCount--;
- categoryAxisZ->dptr()->setRange(0.0, qreal(columnCount));
- }
- Q3DValueAxis *valueAxis = static_cast<Q3DValueAxis *>(m_axisY);
- if (valueAxis && categoryAxisX && categoryAxisZ && valueAxis->isAutoAdjustRange() && proxy) {
- QPair<GLfloat, GLfloat> limits = proxy->dptrc()->limitValues(categoryAxisX->min(),
- categoryAxisX->max(),
- categoryAxisZ->min(),
- categoryAxisZ->max());
- if (limits.first < 0) {
- // TODO: Currently we only support symmetric y-axis for bar graph if there are negative values
- qreal maxAbs = qMax(qFabs(limits.first), qFabs(limits.second));
- // Call private implementation to avoid unsetting auto adjust flag
- valueAxis->dptr()->setRange(-maxAbs, maxAbs);
- } else if (limits.second == 0.0) {
- valueAxis->dptr()->setRange(0.0, 1.0); // Only zero value values in data set, set range to something.
- } else {
- valueAxis->dptr()->setRange(0.0, limits.second);
+ // Now that we know the row and column ranges, figure out the value axis range
+ if (adjustY) {
+ for (int series = 0; series < seriesCount; series++) {
+ const QBar3DSeries *barSeries = static_cast<QBar3DSeries *>(m_seriesList.at(series));
+ if (barSeries->isVisible()) {
+ const QBarDataProxy *proxy = barSeries->dataProxy();
+ if (adjustY && proxy) {
+ QPair<GLfloat, GLfloat> limits = proxy->dptrc()->limitValues(categoryAxisZ->min(),
+ categoryAxisZ->max(),
+ categoryAxisX->min(),
+ categoryAxisX->max());
+ if (!series) {
+ // First series initializes the values
+ minValue = limits.first;
+ maxValue = limits.second;
+ } else {
+ minValue = qMin(minValue, limits.first);
+ maxValue = qMax(maxValue, limits.second);
+ }
+ }
+ }
+ }
+
+ if (maxValue < 0.0f)
+ maxValue = 0.0f;
+ if (minValue > 0.0f)
+ minValue = 0.0f;
+ if (minValue == 0.0f && maxValue == 0.0f) {
+ // Only zero value values in data set, set range to something.
+ minValue = 0.0f;
+ maxValue = 1.0f;
+ }
+ valueAxis->dptr()->setRange(minValue, maxValue);
}
}
}
+// Invalidate selection position if outside data for the series
+void Bars3DController::adjustSelectionPosition(QPoint &pos, const QBar3DSeries *series)
+{
+ const QBarDataProxy *proxy = 0;
+ if (series)
+ proxy = series->dataProxy();
+
+ if (!proxy)
+ pos = invalidSelectionPosition();
+
+ if (pos != invalidSelectionPosition()) {
+ int maxRow = proxy->rowCount() - 1;
+ int maxCol = (pos.x() <= maxRow && pos.x() >= 0 && proxy->rowAt(pos.x()))
+ ? proxy->rowAt(pos.x())->size() - 1 : -1;
+
+ if (pos.x() < 0 || pos.x() > maxRow || pos.y() < 0 || pos.y() > maxCol)
+ pos = invalidSelectionPosition();
+ }
+}
+
Q3DAbstractAxis *Bars3DController::createDefaultAxis(Q3DAbstractAxis::AxisOrientation orientation)
{
Q3DAbstractAxis *defaultAxis = 0;
diff --git a/src/datavisualization/engine/bars3dcontroller_p.h b/src/datavisualization/engine/bars3dcontroller_p.h
index 8398dd81..54385571 100644
--- a/src/datavisualization/engine/bars3dcontroller_p.h
+++ b/src/datavisualization/engine/bars3dcontroller_p.h
@@ -37,17 +37,17 @@
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class Bars3DRenderer;
-class QBarDataProxy;
+class QBar3DSeries;
struct Bars3DChangeBitField {
bool slicingActiveChanged : 1;
bool barSpecsChanged : 1;
- bool selectedBarPosChanged : 1;
+ bool selectedBarChanged : 1;
Bars3DChangeBitField() :
slicingActiveChanged(true),
barSpecsChanged(true),
- selectedBarPosChanged(true)
+ selectedBarChanged(true)
{
}
};
@@ -60,7 +60,9 @@ private:
Bars3DChangeBitField m_changeTracker;
// Interaction
- QPoint m_selectedBarPos; // Points to row & column in data window.
+ QPoint m_selectedBar; // Points to row & column in data window.
+ QBar3DSeries *m_selectedBarSeries; // Points to the series for which the bar is selected in
+ // single series selection cases.
// Look'n'feel
bool m_isBarSpecRelative;
@@ -74,7 +76,7 @@ public:
explicit Bars3DController(QRect rect);
~Bars3DController();
- void initializeOpenGL();
+ virtual void initializeOpenGL();
virtual void synchDataToRenderer();
// bar thickness, spacing between bars, and is spacing relative to thickness or absolute
@@ -87,24 +89,21 @@ public:
QSizeF barSpacing();
bool isBarSpecRelative();
- // bar type; bars (=cubes), pyramids, cones, cylinders, etc.
- void setBarType(QDataVis::MeshStyle style, bool smooth = false);
-
- // Change selection mode; single bar, bar and row, bar and column, or all
- void setSelectionMode(QDataVis::SelectionMode mode);
-
- void setSelectedBarPos(const QPoint &position);
- QPoint selectedBarPos() const;
-
- virtual void setActiveDataProxy(QAbstractDataProxy *proxy);
+ void setSelectionMode(QDataVis::SelectionFlags mode);
+ void setSelectedBar(const QPoint &position, QBar3DSeries *series);
virtual void handleAxisAutoAdjustRangeChangedInOrientation(Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust);
+ virtual void handleSeriesVisibilityChangedBySender(QObject *sender);
- static QPoint noSelectionPoint();
+ static QPoint invalidSelectionPosition();
virtual void setAxisX(Q3DAbstractAxis *axis);
virtual void setAxisZ(Q3DAbstractAxis *axis);
+ virtual void addSeries(QAbstract3DSeries *series);
+ virtual void removeSeries(QAbstract3DSeries *series);
+ virtual QList<QBar3DSeries *> barSeriesList();
+
virtual void handleAxisRangeChangedBySender(QObject *sender);
public slots:
@@ -117,16 +116,15 @@ public slots:
void handleDataRowLabelsChanged();
void handleDataColumnLabelsChanged();
- void handleSelectedBarPosChanged(const QPoint &position);
-
-signals:
- void selectedBarPosChanged(QPoint position);
+ // Renderer callback handlers
+ void handleBarClicked(const QPoint &position, QBar3DSeries *series);
protected:
virtual Q3DAbstractAxis *createDefaultAxis(Q3DAbstractAxis::AxisOrientation orientation);
private:
void adjustAxisRanges();
+ void adjustSelectionPosition(QPoint &pos, const QBar3DSeries *series);
Q_DISABLE_COPY(Bars3DController)
diff --git a/src/datavisualization/engine/bars3drenderer.cpp b/src/datavisualization/engine/bars3drenderer.cpp
index c7c2f64c..ecdac21f 100644
--- a/src/datavisualization/engine/bars3drenderer.cpp
+++ b/src/datavisualization/engine/bars3drenderer.cpp
@@ -22,11 +22,11 @@
#include "shaderhelper_p.h"
#include "objecthelper_p.h"
#include "texturehelper_p.h"
-#include "theme_p.h"
#include "utils_p.h"
#include "drawer_p.h"
#include "qbardataitem.h"
#include "q3dlight.h"
+#include "qbar3dseries_p.h"
#include <QMatrix4x4>
#include <QMouseEvent>
@@ -42,17 +42,15 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
const GLfloat labelMargin = 0.05f;
const GLfloat gridLineWidth = 0.005f;
-static QVector3D selectionSkipColor = QVector3D(255, 255, 255); // Selection texture's background color
-const int smallerVPSize = 5;
+
+const bool sliceGridLabels = true; // TODO: Make this user controllable (QTRD-2546)
Bars3DRenderer::Bars3DRenderer(Bars3DController *controller)
: Abstract3DRenderer(controller),
- m_controller(controller),
m_cachedIsSlicingActivated(false),
m_cachedRowCount(0),
m_cachedColumnCount(0),
m_selectedBar(0),
- m_sliceSelection(0),
m_sliceCache(0),
m_sliceTitleItem(0),
m_xFlipped(false),
@@ -60,11 +58,11 @@ Bars3DRenderer::Bars3DRenderer(Bars3DController *controller)
m_yFlipped(false),
m_updateLabels(false),
m_barShader(0),
+ m_barGradientShader(0),
m_depthShader(0),
m_selectionShader(0),
m_backgroundShader(0),
m_labelShader(0),
- m_barObj(0),
m_backgroundObj(0),
m_gridLineObj(0),
m_labelObj(0),
@@ -77,7 +75,7 @@ Bars3DRenderer::Bars3DRenderer(Bars3DController *controller)
m_shadowQualityToShader(100.0f),
m_shadowQualityMultiplier(3),
m_heightNormalizer(1.0f),
- m_yAdjustment(0.0f),
+ m_negativeBackgroundAdjustment(0.0f),
m_rowWidth(0),
m_columnDepth(0),
m_maxDimension(0),
@@ -85,9 +83,15 @@ Bars3DRenderer::Bars3DRenderer(Bars3DController *controller)
m_scaleZ(0),
m_scaleFactor(0),
m_maxSceneSize(40.0f),
- m_selection(selectionSkipColor),
- m_previousSelection(selectionSkipColor),
- m_hasHeightAdjustmentChanged(true)
+ m_visualSelectedBarPos(Bars3DController::invalidSelectionPosition()),
+ m_visualSelectedBarSeriesIndex(-1),
+ m_hasHeightAdjustmentChanged(true),
+ m_selectedBarPos(Bars3DController::invalidSelectionPosition()),
+ m_selectedBarSeries(0),
+ m_noZeroInRange(false),
+ m_seriesScale(0.0f),
+ m_seriesStep(0.0f),
+ m_seriesStart(0.0f)
{
initializeOpenGLFunctions();
initializeOpenGL();
@@ -100,15 +104,12 @@ Bars3DRenderer::~Bars3DRenderer()
m_textureHelper->deleteTexture(&m_selectionTexture);
m_textureHelper->glDeleteFramebuffers(1, &m_depthFrameBuffer);
m_textureHelper->deleteTexture(&m_bgrTexture);
- if (m_sliceSelection) {
- m_sliceSelection->clear(); // Slice doesn't own its items
- delete m_sliceSelection;
- }
+
delete m_barShader;
+ delete m_barGradientShader;
delete m_depthShader;
delete m_selectionShader;
delete m_backgroundShader;
- delete m_barObj;
delete m_backgroundObj;
delete m_gridLineObj;
delete m_labelObj;
@@ -120,8 +121,6 @@ void Bars3DRenderer::initializeOpenGL()
Abstract3DRenderer::initializeOpenGL();
// Initialize shaders
- handleShadowQualityChange();
-
initLabelShaders(QStringLiteral(":/shaders/vertexLabel"),
QStringLiteral(":/shaders/fragmentLabel"));
@@ -139,34 +138,35 @@ void Bars3DRenderer::initializeOpenGL()
// Load label mesh
loadLabelMesh();
- // Set view port
- glViewport(m_sliceViewPort.x(), m_sliceViewPort.y(),
- m_sliceViewPort.width(), m_sliceViewPort.height());
-
// Load background mesh (we need to be initialized first)
loadBackgroundMesh();
}
-void Bars3DRenderer::updateDataModel(QBarDataProxy *dataProxy)
+void Bars3DRenderer::updateData()
{
- int minRow = m_axisCacheX.min();
- int maxRow = m_axisCacheX.max();
- int minCol = m_axisCacheZ.min();
- int maxCol = m_axisCacheZ.max();
+ int seriesCount = m_visibleSeriesList.size();
+ int minRow = m_axisCacheZ.min();
+ int maxRow = m_axisCacheZ.max();
+ int minCol = m_axisCacheX.min();
+ int maxCol = m_axisCacheX.max();
int newRows = maxRow - minRow + 1;
int newColumns = maxCol - minCol + 1;
- if (newRows != m_renderItemArray.size() || newColumns != m_renderItemArray.at(0).size()) {
- // Destroy old render items and reallocate new array
- m_renderItemArray.clear();
- m_renderItemArray.resize(newRows);
- for (int i = 0; i < newRows; i++)
- m_renderItemArray[i].resize(newColumns);
+ int updateSize = 0;
+ int dataRowCount = 0;
+ int maxDataRowCount = 0;
+
+ if (m_renderingArrays.size() != seriesCount) {
+ m_renderingArrays.resize(seriesCount);
+ m_seriesScale = 1.0f / float(seriesCount);
+ m_seriesStep = 1.0f / float(seriesCount);
+ m_seriesStart = -((float(seriesCount) - 1.0f) / 2.0f) * m_seriesStep;
+ }
+ if (m_cachedRowCount != newRows || m_cachedColumnCount != newColumns) {
// Force update for selection related items
m_sliceCache = 0;
m_sliceTitleItem = 0;
- if (m_sliceSelection)
- m_sliceSelection->clear();
+ m_sliceSelection.clear();
m_cachedColumnCount = newColumns;
m_cachedRowCount = newRows;
@@ -178,62 +178,81 @@ void Bars3DRenderer::updateDataModel(QBarDataProxy *dataProxy)
calculateSceneScalingFactors();
}
- // Update cached data window
- int dataRowCount = dataProxy->rowCount();
- int dataRowIndex = minRow;
- int updateSize = 0;
- for (int i = 0; i < newRows; i++) {
- int j = 0;
- if (dataRowIndex < dataRowCount) {
- const QBarDataRow *dataRow = dataProxy->rowAt(dataRowIndex);
- updateSize = qMin((dataRow->size() - minCol), m_renderItemArray[i].size());
- if (dataRow) {
- int dataColIndex = minCol;
- for (; j < updateSize ; j++) {
- qreal value = dataRow->at(dataColIndex).value();
- m_renderItemArray[i][j].setValue(value);
- m_renderItemArray[i][j].setHeight(GLfloat(value) / m_heightNormalizer);
- dataColIndex++;
+ for (int series = 0; series < seriesCount; series++) {
+ if (newRows != m_renderingArrays.at(series).size()
+ || newColumns != m_renderingArrays.at(series).at(0).size()) {
+ // Destroy old render items and reallocate new array
+ m_renderingArrays[series].resize(newRows);
+ for (int i = 0; i < newRows; i++)
+ m_renderingArrays[series][i].resize(newColumns);
+ }
+
+ // Update cached data window
+ QBarDataProxy *dataProxy =
+ static_cast<QBar3DSeries *>(m_visibleSeriesList.at(series).series())->dataProxy();
+ dataRowCount = dataProxy->rowCount();
+ if (maxDataRowCount < dataRowCount)
+ maxDataRowCount = qMin(dataRowCount, newRows);
+ int dataRowIndex = minRow;
+ GLfloat heightValue = 0.0f;
+ for (int i = 0; i < newRows; i++) {
+ int j = 0;
+ if (dataRowIndex < dataRowCount) {
+ const QBarDataRow *dataRow = dataProxy->rowAt(dataRowIndex);
+ updateSize = qMin((dataRow->size() - minCol),
+ m_renderingArrays.at(series).at(i).size());
+ if (dataRow) {
+ int dataColIndex = minCol;
+ for (; j < updateSize ; j++) {
+ float value = dataRow->at(dataColIndex).value();
+ if (!m_noZeroInRange) {
+ heightValue = GLfloat(value);
+ } else {
+ // Adjust height to range
+ if (!m_hasNegativeValues) {
+ heightValue = value - m_axisCacheY.min();
+ if (heightValue < 0.0f)
+ heightValue = 0.0f;
+ } else if (m_axisCacheY.max() < 0.0f) {
+ heightValue = value - m_axisCacheY.max();
+ if (heightValue > 0.0f)
+ heightValue = 0.0f;
+ }
+ }
+ m_renderingArrays[series][i][j].setValue(value);
+ m_renderingArrays[series][i][j].setHeight(heightValue / m_heightNormalizer);
+ dataColIndex++;
+ }
}
}
+ for (; j < m_renderingArrays.at(series).at(i).size(); j++) {
+ m_renderingArrays[series][i][j].setValue(0.0f);
+ m_renderingArrays[series][i][j].setHeight(0.0f);
+ }
+ dataRowIndex++;
}
- for (; j < m_renderItemArray[i].size(); j++) {
- m_renderItemArray[i][j].setValue(0.0);
- m_renderItemArray[i][j].setHeight(0.0f);
- }
- dataRowIndex++;
}
- m_renderColumns = updateSize;
- m_renderRows = qMin((dataRowCount - minRow), m_renderItemArray.size());
-
- Abstract3DRenderer::updateDataModel(dataProxy);
+ // Reset selected bar to update selection
+ updateSelectedBar(m_selectedBarPos, m_selectedBarSeries);
}
void Bars3DRenderer::updateScene(Q3DScene *scene)
{
- // TODO: Move these to more suitable place e.g. controller should be controlling the viewports.
- scene->setSecondarySubViewport(m_sliceViewPort);
- scene->setPrimarySubViewport(m_mainViewPort);
-
// TODO: See QTRD-2374
if (m_hasNegativeValues)
scene->activeCamera()->setMinYRotation(-90.0);
else
- scene->activeCamera()->setMinYRotation(0.0);
+ scene->activeCamera()->setMinYRotation(0.0f);
if (m_hasHeightAdjustmentChanged) {
// Set initial camera position. Also update if height adjustment has changed.
scene->activeCamera()->setBaseOrientation(cameraDistanceVector,
- QVector3D(0.0f, -m_yAdjustment, 0.0f),
+ zeroVector,
upVector);
m_hasHeightAdjustmentChanged = false;
}
- scene->activeCamera()->d_ptr->updateViewMatrix(m_autoScaleAdjustment);
- // Set light position (rotate light with camera, a bit above it (as set in defaultLightPos))
- scene->setLightPositionRelativeToCamera(defaultLightPos);
-
Abstract3DRenderer::updateScene(scene);
updateSlicingActive(scene->isSlicingActive());
@@ -241,48 +260,29 @@ void Bars3DRenderer::updateScene(Q3DScene *scene)
void Bars3DRenderer::render(GLuint defaultFboHandle)
{
- bool slicingChanged = m_cachedIsSlicingActivated != m_cachedScene->isSlicingActive();
-
// Handle GL state setup for FBO buffers and clearing of the render surface
Abstract3DRenderer::render(defaultFboHandle);
- // Draw bars scene
drawScene(defaultFboHandle);
-
- // If slice selection is on, draw the sliced scene
if (m_cachedIsSlicingActivated)
- drawSlicedScene(m_axisCacheX.titleItem(), m_axisCacheY.titleItem(), m_axisCacheZ.titleItem());
-
- // If slicing has been activated by this render pass, we need another render
- // Also trigger another render always when slicing changes in general to ensure
- // final draw is correct.
- if (m_cachedIsSlicingActivated != m_cachedScene->isSlicingActive() || slicingChanged)
- emit needRender();
+ drawSlicedScene();
}
-void Bars3DRenderer::drawSlicedScene(const LabelItem &xLabel,
- const LabelItem &yLabel,
- const LabelItem &zLabel)
+void Bars3DRenderer::drawSlicedScene()
{
GLfloat barPosX = 0;
- GLint startBar = 0;
- GLint stopBar = m_sliceSelection->size();
- GLint stepBar = 1;
QVector3D lightPos;
- GLfloat negativesComp = 1.0f;
-
- // Compensate bar scaling a bit to avoid drawing on axis titles when we have negative values
- if (m_hasNegativeValues)
- negativesComp = 0.67f;
// Specify viewport
- glViewport(m_sliceViewPort.x(), m_sliceViewPort.y(),
- m_sliceViewPort.width(), m_sliceViewPort.height());
+ glViewport(m_secondarySubViewport.x(),
+ m_secondarySubViewport.y(),
+ m_secondarySubViewport.width(),
+ m_secondarySubViewport.height());
// Set up projection matrix
QMatrix4x4 projectionMatrix;
- projectionMatrix.perspective(40.0f, (GLfloat)m_sliceViewPort.width()
- / (GLfloat)m_sliceViewPort.height(), 0.1f, 10.0f);
+ projectionMatrix.perspective(40.0f, (GLfloat)m_secondarySubViewport.width()
+ / (GLfloat)m_secondarySubViewport.height(), 0.1f, 100.0f);
// Set view matrix
QMatrix4x4 viewMatrix;
@@ -293,89 +293,276 @@ void Bars3DRenderer::drawSlicedScene(const LabelItem &xLabel,
viewMatrix.lookAt(QVector3D(0.0f, 0.0f, camZPosSliced), zeroVector, upVector);
// Set light position
- lightPos = QVector3D(0.0f, -m_yAdjustment, camZPosSliced * 2.0f);
+ lightPos = QVector3D(0.0f, 0.0f, camZPosSliced * 2.0f);
- // Bind bar shader
- m_barShader->bind();
+ const Q3DCamera *activeCamera = m_cachedScene->activeCamera();
+
+ // Draw the selected row / column
+ GLfloat barPosYAdjustment = -0.8f; // Positives only -> translate to -1.0 + 0.2 for row/column labels
+ if (m_hasNegativeValues) {
+ if (m_noZeroInRange)
+ barPosYAdjustment = 1.2f; // Negatives only -> translate to 1.0 + 0.2 for row/column labels
+ else
+ barPosYAdjustment = 0.2f; // Both -> translate to 0.0 + 0.2 for row/column labels
+ }
+ QMatrix4x4 projectionViewMatrix = projectionMatrix * viewMatrix;
+ bool rowMode = m_cachedSelectionMode.testFlag(QDataVis::SelectionRow);
+ bool itemMode = m_cachedSelectionMode.testFlag(QDataVis::SelectionItem);
+
+ // Draw grid lines
+ if (m_cachedTheme->isGridEnabled()) {
+ glDisable(GL_DEPTH_TEST);
+ ShaderHelper *lineShader = m_backgroundShader;
+ // Bind line shader
+ lineShader->bind();
+
+ // Set unchanging shader bindings
+ QVector3D lineColor = Utils::vectorFromColor(m_cachedTheme->gridLineColor());
+ lineShader->setUniformValue(lineShader->lightP(), lightPos);
+ lineShader->setUniformValue(lineShader->view(), viewMatrix);
+ lineShader->setUniformValue(lineShader->color(), lineColor);
+ lineShader->setUniformValue(lineShader->ambientS(), m_cachedTheme->ambientLightStrength() * 2.0f);
+ lineShader->setUniformValue(lineShader->lightS(), 0.25f);
+
+ GLfloat scaleFactor = 0.0f;
+ if (rowMode)
+ scaleFactor = (1.1f * m_rowWidth) / m_scaleFactor;
+ else
+ scaleFactor = (1.1f * m_columnDepth) / m_scaleFactor;
+
+ GLfloat startLine = 0.0f;
+ if (m_noZeroInRange)
+ startLine = 2.0f * (m_axisCacheY.min() - m_axisCacheY.max()) / m_heightNormalizer;
+ else
+ startLine = 2.0f * m_axisCacheY.min() / m_heightNormalizer;
+
+ GLfloat gridStep = (2.0f * m_axisCacheY.subSegmentStep()) / m_heightNormalizer;
+ GLfloat gridPos = startLine + barPosYAdjustment;
+ int lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount();
+
+ // Horizontal lines
+ if (m_axisCacheY.segmentCount() > 0) {
+ QVector3D gridLineScale(scaleFactor, gridLineWidth, gridLineWidth);
+ bool noZero = true;
+ QMatrix4x4 MVPMatrix;
+ QMatrix4x4 itModelMatrix;
+
+ for (int segment = 0; segment <= lastSegment; segment++) {
+ QMatrix4x4 modelMatrix;
+ modelMatrix.translate(0.0f, gridPos, 0.0f);
+ modelMatrix.scale(gridLineScale);
+ itModelMatrix = modelMatrix;
+ MVPMatrix = projectionViewMatrix * modelMatrix;
+
+ // Set the rest of the shader bindings
+ lineShader->setUniformValue(lineShader->model(), modelMatrix);
+ lineShader->setUniformValue(lineShader->nModel(),
+ itModelMatrix.inverted().transposed());
+ lineShader->setUniformValue(lineShader->MVP(), MVPMatrix);
+
+ // Draw the object
+ m_drawer->drawObject(lineShader, m_gridLineObj);
+
+ if (gridPos == barPosYAdjustment)
+ noZero = false;
+
+ gridPos += gridStep;
+ }
+ // Draw a line at zero, if none exists
+ if (!m_noZeroInRange && noZero) {
+ QMatrix4x4 modelMatrix;
+ modelMatrix.translate(0.0f, barPosYAdjustment, 0.0f);
+ modelMatrix.scale(gridLineScale);
+ itModelMatrix = modelMatrix;
+ MVPMatrix = projectionViewMatrix * modelMatrix;
+
+ // Set the rest of the shader bindings
+ lineShader->setUniformValue(lineShader->model(), modelMatrix);
+ lineShader->setUniformValue(lineShader->nModel(),
+ itModelMatrix.inverted().transposed());
+ lineShader->setUniformValue(lineShader->MVP(), MVPMatrix);
+ lineShader->setUniformValue(lineShader->color(),
+ Utils::vectorFromColor(m_cachedTheme->backgroundColor()));
+
+ // Draw the object
+ m_drawer->drawObject(lineShader, m_gridLineObj);
+ }
+ }
+
+ // TODO: Make user controllable (QTRD-2546)
+ if (sliceGridLabels) {
+ // Bind label shader
+ m_labelShader->bind();
+ glEnable(GL_TEXTURE_2D);
+ glCullFace(GL_BACK);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ // Draw grid labels
+ int labelNbr = 0;
+ int labelCount = m_axisCacheY.labels().size();
+ gridStep = (2.0f * m_axisCacheY.segmentStep()) / m_heightNormalizer;
+ gridPos = startLine + barPosYAdjustment;
+ QVector3D backLabelRotation(0.0f, 0.0f, 0.0f);
+ QVector3D labelTrans = QVector3D(scaleFactor + labelMargin, 0.0f, 0.0f);
+
+ for (int i = 0; i < labelCount; i++) {
+ if (m_axisCacheY.labelItems().size() > labelNbr) {
+ const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(labelNbr);
+ labelTrans.setY(gridPos);
+ m_dummyBarRenderItem.setTranslation(labelTrans);
+ m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix,
+ projectionMatrix, zeroVector, backLabelRotation, 0,
+ m_cachedSelectionMode, m_labelShader, m_labelObj,
+ activeCamera, true, true, Drawer::LabelMid, Qt::AlignRight);
+ }
+ labelNbr++;
+ gridPos += gridStep;
+ }
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_BLEND);
+ glEnable(GL_DEPTH_TEST);
+ }
+ }
+
+ // Draw bars
+ QVector3D modelMatrixScaler(m_scaleX, 0.0f, m_scaleZ);
+ if (rowMode)
+ modelMatrixScaler.setX(m_scaleX * m_seriesScale);
+ else
+ modelMatrixScaler.setZ(m_scaleZ * m_seriesScale);
// Set common bar shader bindings
+ m_barShader->bind();
m_barShader->setUniformValue(m_barShader->lightP(), lightPos);
m_barShader->setUniformValue(m_barShader->view(), viewMatrix);
m_barShader->setUniformValue(m_barShader->lightS(), 0.5f);
m_barShader->setUniformValue(m_barShader->ambientS(),
- m_cachedTheme.m_ambientStrength * 2.0f);
-
- // Draw the selected row / column
- // We need some room for labels underneath; add +0.2f
- GLfloat barPosYAdjustment = m_yAdjustment / 2.0f - 0.2f;
- QVector3D modelMatrixScaler(m_scaleX, 0.0f, m_scaleZ);
- QMatrix4x4 projectionViewMatrix = projectionMatrix * viewMatrix;
- QVector3D barHighlightColor(Utils::vectorFromColor(m_cachedTheme.m_highlightBarColor));
- QVector3D rowHighlightColor(Utils::vectorFromColor(m_cachedTheme.m_highlightRowColor));
- QVector3D columnHighlightColor(Utils::vectorFromColor(m_cachedTheme.m_highlightColumnColor));
- for (int bar = startBar; bar != stopBar; bar += stepBar) {
- BarRenderItem *item = m_sliceSelection->at(bar);
+ m_cachedTheme->ambientLightStrength() * 2.0f);
+ m_barGradientShader->bind();
+ m_barGradientShader->setUniformValue(m_barGradientShader->lightP(), lightPos);
+ m_barGradientShader->setUniformValue(m_barGradientShader->view(), viewMatrix);
+ m_barGradientShader->setUniformValue(m_barGradientShader->lightS(), 0.5f);
+ m_barGradientShader->setUniformValue(m_barGradientShader->ambientS(),
+ m_cachedTheme->ambientLightStrength() * 2.0f);
+ m_barGradientShader->setUniformValue(m_barGradientShader->gradientMin(), 0.0f);
+
+ // Default to uniform shader
+ ShaderHelper *barShader = m_barShader;
+ barShader->bind();
+
+ int currentSeriesIndex = -1;
+ Q3DTheme::ColorStyle previousColorStyle = Q3DTheme::ColorStyleUniform;
+ Q3DTheme::ColorStyle colorStyle = Q3DTheme::ColorStyleUniform;
+ ObjectHelper *barObj = 0;
+ QVector3D barHighlightColor;
+ QVector3D rowHighlightColor;
+ GLuint barGradientTexture = 0;
+ GLuint rowGradientTexture = 0;
+ const SeriesRenderCache *currentSeries = 0;
+ bool colorStyleIsUniform = true;
+
+ int sliceItemCount = m_sliceSelection.size();
+ for (int bar = 0; bar < sliceItemCount; bar++) {
+ BarRenderItem *item = m_sliceSelection.at(bar);
if (!item)
continue;
+ if (item->seriesIndex() != currentSeriesIndex) {
+ currentSeriesIndex = item->seriesIndex();
+ currentSeries = &(m_visibleSeriesList.at(currentSeriesIndex));
+ barObj = currentSeries->object();
+ colorStyle = currentSeries->colorStyle();
+ colorStyleIsUniform = (colorStyle == Q3DTheme::ColorStyleUniform);
+ if (colorStyleIsUniform) {
+ barHighlightColor = currentSeries->singleHighlightColor();
+ rowHighlightColor = currentSeries->multiHighlightColor();
+ } else {
+ barGradientTexture = currentSeries->singleHighlightGradientTexture();
+ rowGradientTexture = currentSeries->multiHighlightGradientTexture();
+ }
+
+ // Rebind shader if it has changed
+ if (colorStyleIsUniform != (previousColorStyle == Q3DTheme::ColorStyleUniform)) {
+ if (colorStyleIsUniform)
+ barShader = m_barShader;
+ else
+ barShader = m_barGradientShader;
+ barShader->bind();
+
+ }
+
+ if (!colorStyleIsUniform && (previousColorStyle != colorStyle)
+ && (colorStyle == Q3DTheme::ColorStyleObjectGradient)) {
+ m_barGradientShader->setUniformValue(m_barGradientShader->gradientHeight(), 0.5f);
+ }
+
+ previousColorStyle = colorStyle;
+ }
+
if (item->height() < 0)
glCullFace(GL_FRONT);
else
glCullFace(GL_BACK);
- QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
+ QMatrix4x4 modelMatrix;
QMatrix4x4 itModelMatrix;
+ GLfloat barRotation = 0.0f;
+ GLfloat barPosY = item->translation().y() + barPosYAdjustment;
- GLfloat barPosY = negativesComp * item->translation().y() - barPosYAdjustment;
- if (QDataVis::SelectionModeSliceRow == m_cachedSelectionMode)
+ if (rowMode) {
barPosX = item->translation().x();
- else
+ } else {
barPosX = -(item->translation().z()); // flip z; frontmost bar to the left
+ barRotation = 90.0f;
+ }
+
modelMatrix.translate(barPosX, barPosY, 0.0f);
- modelMatrixScaler.setY(negativesComp * item->height());
+ modelMatrixScaler.setY(item->height());
+ modelMatrix.rotate(barRotation, 0.0f, 1.0f, 0.0f);
+ itModelMatrix.rotate(barRotation, 0.0f, 1.0f, 0.0f);
modelMatrix.scale(modelMatrixScaler);
itModelMatrix.scale(modelMatrixScaler);
MVPMatrix = projectionViewMatrix * modelMatrix;
-#if 0
- QVector3D baseColor;
- if (m_selection.x() == item->position().x() && m_selection.y() == item->position().y())
- baseColor = barHighlightColor;
- else if (QDataVis::SelectionModeSliceRow == m_cachedSelectionMode)
- baseColor = rowHighlightColor;
- else
- baseColor = columnHighlightColor;
-
- QVector3D heightColor = Utils::vectorFromColor(m_cachedTheme.m_heightColor) * item->height();
- QVector3D barColor = baseColor + heightColor;
-#else
QVector3D barColor;
- if (m_selection.x() == item->position().x() && m_selection.y() == item->position().y())
- barColor = barHighlightColor;
- else if (QDataVis::SelectionModeSliceRow == m_cachedSelectionMode)
- barColor = rowHighlightColor;
- else
- barColor = columnHighlightColor;
-#endif
+ GLuint gradientTexture = 0;
+
+ if (itemMode && m_visualSelectedBarPos.x() == item->position().x()
+ && m_visualSelectedBarPos.y() == item->position().y()) {
+ if (colorStyleIsUniform)
+ barColor = barHighlightColor;
+ else
+ gradientTexture = barGradientTexture;
+ } else {
+ if (colorStyleIsUniform)
+ barColor = rowHighlightColor;
+ else
+ gradientTexture = rowGradientTexture;
+ }
if (item->height() != 0) {
// Set shader bindings
- m_barShader->setUniformValue(m_barShader->model(), modelMatrix);
- m_barShader->setUniformValue(m_barShader->nModel(),
- itModelMatrix.inverted().transposed());
- m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix);
- m_barShader->setUniformValue(m_barShader->color(), barColor);
+ barShader->setUniformValue(barShader->model(), modelMatrix);
+ barShader->setUniformValue(barShader->nModel(),
+ itModelMatrix.inverted().transposed());
+ barShader->setUniformValue(barShader->MVP(), MVPMatrix);
+ if (colorStyleIsUniform) {
+ barShader->setUniformValue(barShader->color(), barColor);
+ } else if (colorStyle == Q3DTheme::ColorStyleRangeGradient) {
+ barShader->setUniformValue(barShader->gradientHeight(),
+ (qAbs(item->height()) / m_gradientFraction));
+ }
// Draw the object
- m_drawer->drawObject(m_barShader, m_barObj);
+ m_drawer->drawObject(barShader,
+ barObj,
+ gradientTexture);
}
}
- // Release bar shader
- m_barShader->release();
-
// Draw labels
m_labelShader->bind();
glDisable(GL_DEPTH_TEST);
@@ -384,69 +571,106 @@ void Bars3DRenderer::drawSlicedScene(const LabelItem &xLabel,
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- // Draw labels for axes
BarRenderItem *dummyItem(0);
const LabelItem &sliceSelectionLabel = *m_sliceTitleItem;
QVector3D positionComp(0.0f, m_autoScaleAdjustment, 0.0f);
- const Q3DCamera *activeCamera = m_cachedScene->activeCamera();
- if (QDataVis::SelectionModeSliceRow == m_cachedSelectionMode) {
+
+ // Draw labels for bars
+ QVector3D valuePositionComp = zeroVector;
+ if (!m_hasNegativeValues)
+ valuePositionComp.setY(2.0f);
+ else if (m_noZeroInRange)
+ valuePositionComp.setY(-2.0f);
+ QVector3D sliceValueRotation(0.0f, 0.0f, 90.0f);
+ QVector3D sliceLabelRotation(0.0f, 0.0f, -45.0f);
+
+ for (int col = 0; col < sliceItemCount; col++) {
+ BarRenderItem *item = m_sliceSelection.at(col);
+
+ // TODO: Make user controllable (QTRD-2546)
+ if (!sliceGridLabels) {
+ // Draw values
+ if (item->height() != 0.0f || (!m_noZeroInRange && item->value() == 0.0f)) {
+ // Create label texture if we need it
+ if (item->sliceLabel().isNull()) {
+ item->setSliceLabel(generateValueLabel(m_axisCacheY.labelFormat(), item->value()));
+ m_drawer->generateLabelItem(item->sliceLabelItem(), item->sliceLabel());
+ }
+ m_drawer->drawLabel(*item, item->sliceLabelItem(), viewMatrix, projectionMatrix,
+ valuePositionComp, sliceValueRotation, item->height(),
+ m_cachedSelectionMode, m_labelShader, m_labelObj, activeCamera,
+ false, false, Drawer::LabelOver, Qt::AlignTop, true);
+ }
+ } else {
+ // Only draw value for selected item when grid labels are on
+ // TODO: Maybe use selection label instead of value? Should it be user controllable
+ // as well? (QTRD-2546)
+ if (itemMode && m_visualSelectedBarPos.x() == item->position().x()
+ && m_visualSelectedBarPos.y() == item->position().y()
+ && item->seriesIndex() == m_visualSelectedBarSeriesIndex) {
+ // Create label texture if we need it
+ if (item->sliceLabel().isNull()) {
+ item->setSliceLabel(generateValueLabel(m_axisCacheY.labelFormat(), item->value()));
+ m_drawer->generateLabelItem(item->sliceLabelItem(), item->sliceLabel());
+ }
+ m_drawer->drawLabel(*item, item->sliceLabelItem(), viewMatrix, projectionMatrix,
+ valuePositionComp, sliceValueRotation, item->height(),
+ m_cachedSelectionMode, m_labelShader, m_labelObj, activeCamera,
+ false, false, Drawer::LabelOver, Qt::AlignTop, true);
+ }
+ }
+ }
+
+ int lastLabel = m_sliceCache->labelItems().size() - 1;
+
+ for (int labelNo = 0; labelNo <= lastLabel; labelNo++) {
+ // Get labels from first series only
+ BarRenderItem *item = m_sliceSelection.at(labelNo);
+ // TODO: Make user controllable (QTRD-2546)
+ // Draw labels
+ m_drawer->drawLabel(*item, *m_sliceCache->labelItems().at(labelNo), viewMatrix,
+ projectionMatrix, positionComp, sliceLabelRotation,
+ item->height(), m_cachedSelectionMode, m_labelShader,
+ m_labelObj, activeCamera, false, false, Drawer::LabelBelow,
+ Qt::AlignCenter, true);
+ }
+
+ // TODO: Make user controllable (QTRD-2546)
+ // Draw labels for axes
+ if (rowMode) {
if (m_sliceTitleItem) {
m_drawer->drawLabel(*dummyItem, sliceSelectionLabel, viewMatrix, projectionMatrix,
positionComp, zeroVector, 0, m_cachedSelectionMode, m_labelShader,
- m_labelObj, activeCamera, false, false, Drawer::LabelTop);
+ m_labelObj, activeCamera, false, false, Drawer::LabelTop,
+ Qt::AlignCenter, true);
}
- m_drawer->drawLabel(*dummyItem, zLabel, viewMatrix, projectionMatrix,
+ m_drawer->drawLabel(*dummyItem, m_axisCacheX.titleItem(), viewMatrix, projectionMatrix,
positionComp, zeroVector, 0, m_cachedSelectionMode, m_labelShader,
- m_labelObj, activeCamera, false, false, Drawer::LabelBottom);
+ m_labelObj, activeCamera, false, false, Drawer::LabelBottom,
+ Qt::AlignCenter, true);
} else {
- m_drawer->drawLabel(*dummyItem, xLabel, viewMatrix, projectionMatrix,
+ m_drawer->drawLabel(*dummyItem, m_axisCacheZ.titleItem(), viewMatrix, projectionMatrix,
positionComp, zeroVector, 0, m_cachedSelectionMode, m_labelShader,
- m_labelObj, activeCamera, false, false, Drawer::LabelBottom);
+ m_labelObj, activeCamera, false, false, Drawer::LabelBottom,
+ Qt::AlignCenter, true);
if (m_sliceTitleItem) {
m_drawer->drawLabel(*dummyItem, sliceSelectionLabel, viewMatrix, projectionMatrix,
positionComp, zeroVector, 0, m_cachedSelectionMode, m_labelShader,
- m_labelObj, activeCamera, false, false, Drawer::LabelTop);
+ m_labelObj, activeCamera, false, false, Drawer::LabelTop,
+ Qt::AlignCenter, true);
}
}
- m_drawer->drawLabel(*dummyItem, yLabel, viewMatrix, projectionMatrix,
+ m_drawer->drawLabel(*dummyItem, m_axisCacheY.titleItem(), viewMatrix, projectionMatrix,
positionComp, QVector3D(0.0f, 0.0f, 90.0f), 0,
m_cachedSelectionMode, m_labelShader, m_labelObj, activeCamera,
- false, false, Drawer::LabelLeft);
-
- // Draw labels for bars
- QVector3D valuePositionComp(0.0f, m_yAdjustment, 0.0f);
- QVector3D negativesRotation(0.0f, 0.0f, 90.0f);
- QVector3D sliceLabelRotation(0.0f, 0.0f, -45.0f);
- GLfloat negativesCompPow2 = negativesComp * negativesComp;
- for (int col = 0; col < stopBar; col++) {
- BarRenderItem *item = m_sliceSelection->at(col);
- // Draw values
- if (!m_hasNegativeValues) {
- m_drawer->drawLabel(*item, item->sliceLabelItem(), viewMatrix, projectionMatrix,
- valuePositionComp, negativesRotation, item->height(),
- m_cachedSelectionMode, m_labelShader, m_labelObj, activeCamera,
- false, false, Drawer::LabelOver, Qt::AlignTop);
- } else {
- m_drawer->drawLabel(*item, item->sliceLabelItem(), viewMatrix, projectionMatrix,
- valuePositionComp, zeroVector, negativesCompPow2 * item->height(),
- m_cachedSelectionMode, m_labelShader, m_labelObj, activeCamera);
- }
-
- // Draw labels
- if (m_sliceCache->labelItems().size() > col) {
- m_drawer->drawLabel(*item, *m_sliceCache->labelItems().at(col), viewMatrix,
- projectionMatrix, positionComp, sliceLabelRotation,
- item->height(), m_cachedSelectionMode, m_labelShader,
- m_labelObj, activeCamera, false, false, Drawer::LabelBelow);
- }
- }
+ false, false, Drawer::LabelLeft, Qt::AlignCenter, true);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
- // Release label shader
- m_labelShader->release();
+ // Release shader
+ glUseProgram(0);
}
void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
@@ -464,15 +688,18 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
GLfloat colPos = 0;
GLfloat rowPos = 0;
+ int seriesCount = m_visibleSeriesList.size();
+
const Q3DCamera *activeCamera = m_cachedScene->activeCamera();
- // Specify viewport
- glViewport(m_mainViewPort.x(), m_mainViewPort.y(),
- m_mainViewPort.width(), m_mainViewPort.height());
+ glViewport(m_primarySubViewport.x(),
+ m_primarySubViewport.y(),
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
// Set up projection matrix
QMatrix4x4 projectionMatrix;
- GLfloat viewPortRatio = (GLfloat)m_mainViewPort.width() / (GLfloat)m_mainViewPort.height();
+ GLfloat viewPortRatio = (GLfloat)m_primarySubViewport.width() / (GLfloat)m_primarySubViewport.height();
projectionMatrix.perspective(45.0f, viewPortRatio, 0.1f, 100.0f);
// Get the view matrix
@@ -531,6 +758,8 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
QMatrix4x4 projectionViewMatrix = projectionMatrix * viewMatrix;
+ bool rowMode = m_cachedSelectionMode.testFlag(QDataVis::SelectionRow);
+
#if !defined(QT_OPENGL_ES_2)
if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
// Render scene into a depth texture for using with shadow mapping
@@ -544,15 +773,14 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
// Set viewport for depth map rendering. Must match texture size. Larger values give smoother shadows.
// Depth viewport must always start from 0, 0, as it is rendered into a texture, not screen
glViewport(0, 0,
- m_mainViewPort.width() * m_shadowQualityMultiplier,
- m_mainViewPort.height() * m_shadowQualityMultiplier);
+ m_primarySubViewport.width() * m_shadowQualityMultiplier,
+ m_primarySubViewport.height() * m_shadowQualityMultiplier);
// Get the depth view matrix
// It may be possible to hack lightPos here if we want to make some tweaks to shadow
QVector3D depthLightPos = activeCamera->calculatePositionRelativeToCamera(
zeroVector, 0.0f, 3.5f / m_autoScaleAdjustment);
- depthViewMatrix.lookAt(depthLightPos, QVector3D(0.0f, -m_yAdjustment, 0.0f),
- upVector);
+ depthViewMatrix.lookAt(depthLightPos, zeroVector, upVector);
// TODO: Why does depthViewMatrix.column(3).y() goes to zero when we're directly above?
// That causes the scene to be not drawn from above -> must be fixed
@@ -563,73 +791,73 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
depthProjectionViewMatrix = depthProjectionMatrix * depthViewMatrix;
// Draw bars to depth buffer
- QVector3D shadowScaler(m_scaleX * 0.9f, 0.0f, m_scaleZ * 0.9f);
- for (int row = startRow; row != stopRow; row += stepRow) {
- for (int bar = startBar; bar != stopBar; bar += stepBar) {
- const BarRenderItem &item = m_renderItemArray.at(row).at(bar);
- if (!item.value())
- continue;
-
- GLfloat shadowOffset = 0.0f;
-
- // Set front face culling for negative valued bars and back face culling for
- // positive valued bars to remove peter-panning issues
- if (item.height() > 0) {
- glCullFace(GL_BACK);
- if (m_yFlipped)
- shadowOffset = 0.015f;
- } else {
- glCullFace(GL_FRONT);
- if (!m_yFlipped)
- shadowOffset = -0.015f;
- }
+ QVector3D shadowScaler(m_scaleX * m_seriesScale * 0.9f, 0.0f, m_scaleZ * 0.9f);
+ float seriesPos = m_seriesStart;
+ for (int series = 0; series < seriesCount; series++) {
+ ObjectHelper *barObj = m_visibleSeriesList.at(series).object();
+ for (int row = startRow; row != stopRow; row += stepRow) {
+ for (int bar = startBar; bar != stopBar; bar += stepBar) {
+ GLfloat shadowOffset = 0.0f;
+ const BarRenderItem &item = m_renderingArrays.at(series).at(row).at(bar);
+ if (!item.value())
+ continue;
+ // Set front face culling for negative valued bars and back face culling for
+ // positive valued bars to remove peter-panning issues
+ if (item.height() > 0) {
+ glCullFace(GL_BACK);
+ if (m_yFlipped)
+ shadowOffset = 0.015f;
+ } else {
+ glCullFace(GL_FRONT);
+ if (!m_yFlipped)
+ shadowOffset = -0.015f;
+ }
- QMatrix4x4 modelMatrix;
- QMatrix4x4 MVPMatrix;
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
- colPos = (bar + 0.5f) * (m_cachedBarSpacing.width());
- rowPos = (row + 0.5f) * (m_cachedBarSpacing.height());
+ colPos = (bar + 0.5f + seriesPos) * (m_cachedBarSpacing.width());
+ rowPos = (row + 0.5f) * (m_cachedBarSpacing.height());
- // Draw shadows for bars "on the other side" a bit off ground to avoid seeing
- // shadows through the ground
- modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor,
- item.height() - m_yAdjustment + shadowOffset,
- (m_columnDepth - rowPos) / m_scaleFactor);
- // Scale the bars down in X and Z to reduce self-shadowing issues
- shadowScaler.setY(item.height());
- modelMatrix.scale(shadowScaler);
+ // Draw shadows for bars "on the other side" a bit off ground to avoid seeing
+ // shadows through the ground
+ modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor,
+ item.height() + shadowOffset,
+ (m_columnDepth - rowPos) / m_scaleFactor);
+ // Scale the bars down in X and Z to reduce self-shadowing issues
+ shadowScaler.setY(item.height());
+ modelMatrix.scale(shadowScaler);
- MVPMatrix = depthProjectionViewMatrix * modelMatrix;
+ MVPMatrix = depthProjectionViewMatrix * modelMatrix;
- m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix);
+ m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix);
- // 1st attribute buffer : vertices
- glEnableVertexAttribArray(m_depthShader->posAtt());
- glBindBuffer(GL_ARRAY_BUFFER, m_barObj->vertexBuf());
- glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0,
- (void *)0);
+ // 1st attribute buffer : vertices
+ glEnableVertexAttribArray(m_depthShader->posAtt());
+ glBindBuffer(GL_ARRAY_BUFFER, barObj->vertexBuf());
+ glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0,
+ (void *)0);
- // Index buffer
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_barObj->elementBuf());
+ // Index buffer
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, barObj->elementBuf());
- // Draw the triangles
- glDrawElements(GL_TRIANGLES, m_barObj->indexCount(), GL_UNSIGNED_SHORT,
- (void *)0);
+ // Draw the triangles
+ glDrawElements(GL_TRIANGLES, barObj->indexCount(), GL_UNSIGNED_SHORT,
+ (void *)0);
- // Free buffers
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
+ // Free buffers
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
- glDisableVertexAttribArray(m_depthShader->posAtt());
+ glDisableVertexAttribArray(m_depthShader->posAtt());
+ }
}
+ seriesPos += m_seriesStep;
}
// Disable drawing to depth framebuffer (= enable drawing to screen)
glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle);
- // Release depth shader
- m_depthShader->release();
-
#if 0 // Use this if you want to see what is being drawn to the framebuffer
// You'll also have to comment out GL_COMPARE_R_TO_TEXTURE -line in texturehelper (if using it)
m_labelShader->bind();
@@ -642,329 +870,419 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix);
m_drawer->drawObject(m_labelShader, m_labelObj, m_depthTexture);
glDisable(GL_TEXTURE_2D);
- m_labelShader->release();
#endif
// Reset culling to normal
glCullFace(GL_BACK);
// Revert to original viewport
- glViewport(m_mainViewPort.x(), m_mainViewPort.y(),
- m_mainViewPort.width(), m_mainViewPort.height());
+ glViewport(m_primarySubViewport.x(),
+ m_primarySubViewport.y(),
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
}
#endif
+ // TODO: Selection must be enabled currently to support clicked signal. (QTRD-2517)
// Skip selection mode drawing if we're slicing or have no selection mode
- if (!m_cachedIsSlicingActivated && m_cachedSelectionMode > QDataVis::SelectionModeNone) {
+ if (!m_cachedIsSlicingActivated && m_cachedSelectionMode > QDataVis::SelectionNone
+ && m_selectionState == SelectOnScene && seriesCount > 0) {
// Bind selection shader
m_selectionShader->bind();
// Draw bars to selection buffer
glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer);
+ glViewport(0, 0,
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
+
glEnable(GL_DEPTH_TEST); // Needed, otherwise the depth render buffer is not used
glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Set clear color to white (= selectionSkipColor)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Needed for clearing the frame buffer
glDisable(GL_DITHER); // disable dithering, it may affect colors if enabled
- for (int row = startRow; row != stopRow; row += stepRow) {
- for (int bar = startBar; bar != stopBar; bar += stepBar) {
- const BarRenderItem &item = m_renderItemArray.at(row).at(bar);
- if (!item.value())
- continue;
-
- if (item.height() < 0)
- glCullFace(GL_FRONT);
- else
- glCullFace(GL_BACK);
-
- QMatrix4x4 modelMatrix;
- QMatrix4x4 MVPMatrix;
-
- colPos = (bar + 0.5f) * (m_cachedBarSpacing.width());
- rowPos = (row + 0.5f) * (m_cachedBarSpacing.height());
-
- modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor,
- item.height() - m_yAdjustment,
- (m_columnDepth - rowPos) / m_scaleFactor);
- modelMatrix.scale(QVector3D(m_scaleX, item.height(), m_scaleZ));
-
- MVPMatrix = projectionViewMatrix * modelMatrix;
-
- //#if !defined(QT_OPENGL_ES_2)
- // QVector3D barColor = QVector3D((GLdouble)row / 32767.0,
- // (GLdouble)bar / 32767.0,
- // 0.0);
- //#else
- QVector3D barColor = QVector3D((GLdouble)row / 255.0,
- (GLdouble)bar / 255.0,
- 0.0);
- //#endif
-
- m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix);
- m_selectionShader->setUniformValue(m_selectionShader->color(), barColor);
-
- // 1st attribute buffer : vertices
- glEnableVertexAttribArray(m_selectionShader->posAtt());
- glBindBuffer(GL_ARRAY_BUFFER, m_barObj->vertexBuf());
- glVertexAttribPointer(m_selectionShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0,
- (void *)0);
-
- // Index buffer
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_barObj->elementBuf());
-
- // Draw the triangles
- glDrawElements(GL_TRIANGLES, m_barObj->indexCount(), GL_UNSIGNED_SHORT, (void *)0);
-
- // Free buffers
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-
- glDisableVertexAttribArray(m_selectionShader->posAtt());
+ float seriesPos = m_seriesStart;
+ for (int series = 0; series < seriesCount; series++) {
+ ObjectHelper *barObj = m_visibleSeriesList.at(series).object();
+ for (int row = startRow; row != stopRow; row += stepRow) {
+ for (int bar = startBar; bar != stopBar; bar += stepBar) {
+ const BarRenderItem &item = m_renderingArrays.at(series).at(row).at(bar);
+ if (!item.value())
+ continue;
+
+ if (item.height() < 0)
+ glCullFace(GL_FRONT);
+ else
+ glCullFace(GL_BACK);
+
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+
+ colPos = (bar + 0.5f + seriesPos) * (m_cachedBarSpacing.width());
+ rowPos = (row + 0.5f) * (m_cachedBarSpacing.height());
+
+ modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor,
+ item.height(),
+ (m_columnDepth - rowPos) / m_scaleFactor);
+ modelMatrix.scale(QVector3D(m_scaleX * m_seriesScale,
+ item.height(),
+ m_scaleZ));
+
+ MVPMatrix = projectionViewMatrix * modelMatrix;
+
+ //#if !defined(QT_OPENGL_ES_2)
+ // QVector3D barColor = QVector3D(GLfloat(row) / 32767.0f,
+ // GLfloat(bar) / 32767.0f,
+ // 0.0f);
+ //#else
+ QVector3D barColor = QVector3D(GLfloat(row) / 255.0f,
+ GLfloat(bar) / 255.0f,
+ GLfloat(series) / 255.0f);
+ //#endif
+
+ m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix);
+ m_selectionShader->setUniformValue(m_selectionShader->color(), barColor);
+
+ // 1st attribute buffer : vertices
+ glEnableVertexAttribArray(m_selectionShader->posAtt());
+ glBindBuffer(GL_ARRAY_BUFFER, barObj->vertexBuf());
+ glVertexAttribPointer(m_selectionShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0,
+ (void *)0);
+
+ // Index buffer
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, barObj->elementBuf());
+
+ // Draw the triangles
+ glDrawElements(GL_TRIANGLES, barObj->indexCount(), GL_UNSIGNED_SHORT,
+ (void *)0);
+
+ // Free buffers
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glDisableVertexAttribArray(m_selectionShader->posAtt());
+ }
}
+ seriesPos += m_seriesStep;
}
glEnable(GL_DITHER);
// Read color under cursor
- if (QDataVis::InputStateOnScene == m_controller->inputState()) {
- m_selection = Utils::getSelection(m_controller->inputPosition(),
- m_cachedBoundingRect.height());
- }
+ QVector3D clickedColor = Utils::getSelection(m_inputPosition,
+ m_viewport.height());
+ emit barClicked(selectionColorToArrayPosition(clickedColor), selectionColorToSeries(clickedColor));
+ // Revert to original render target and viewport
glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle);
-
- // Release selection shader
- m_selectionShader->release();
-
-#if 0 // Use this if you want to see what is being drawn to the framebuffer
- glCullFace(GL_BACK);
- m_labelShader->bind();
- glDisable(GL_DEPTH_TEST);
- glEnable(GL_TEXTURE_2D);
- QMatrix4x4 modelMatrix;
- QMatrix4x4 viewmatrix;
- viewmatrix.lookAt(QVector3D(0.0f, 0.0f, 2.0f), zeroVector, upVector);
- QMatrix4x4 MVPMatrix = projectionViewMatrix * modelMatrix;
- m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix);
- m_drawer->drawObject(m_labelShader, m_labelObj, m_selectionTexture);
- glDisable(GL_TEXTURE_2D);
- m_labelShader->release();
-#endif
+ glViewport(m_primarySubViewport.x(),
+ m_primarySubViewport.y(),
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
}
// Enable texturing
glEnable(GL_TEXTURE_2D);
- // Bind bar shader
- m_barShader->bind();
+ ShaderHelper *barShader = 0;
+ GLuint gradientTexture = 0;
+ Q3DTheme::ColorStyle previousColorStyle = Q3DTheme::ColorStyleUniform;
+ bool haveUniformColorSeries = false;
+ bool haveGradientSeries = false;
- // Set common bar shader bindings
- m_barShader->setUniformValue(m_barShader->lightP(), lightPos);
- m_barShader->setUniformValue(m_barShader->view(), viewMatrix);
- m_barShader->setUniformValue(m_barShader->ambientS(),
- m_cachedTheme.m_ambientStrength);
-
- bool selectionDirty = (m_selection != m_previousSelection
- || (m_selection != selectionSkipColor
- && QDataVis::InputStateOnScene == m_controller->inputState()
- && !m_cachedIsSlicingActivated));
- if (selectionDirty) {
- m_previousSelection = m_selection;
- if (m_sliceSelection) {
- if (!m_cachedIsSlicingActivated) {
- m_sliceCache = 0;
- m_sliceTitleItem = 0;
- }
- if (m_sliceSelection->size()) {
- // Slice doesn't own its items, no need to delete them - just clear
- m_sliceSelection->clear();
- }
- }
+ for (int i = 0; i < seriesCount; i++) {
+ if (m_visibleSeriesList.at(i).colorStyle() == Q3DTheme::ColorStyleUniform)
+ haveUniformColorSeries = true;
+ else
+ haveGradientSeries = true;
+ }
+
+ // Set unchanging shader bindings
+ if (haveGradientSeries) {
+ m_barGradientShader->bind();
+ m_barGradientShader->setUniformValue(m_barGradientShader->lightP(), lightPos);
+ m_barGradientShader->setUniformValue(m_barGradientShader->view(), viewMatrix);
+ m_barGradientShader->setUniformValue(m_barGradientShader->ambientS(),
+ m_cachedTheme->ambientLightStrength());
+ m_barGradientShader->setUniformValue(m_barGradientShader->gradientMin(), 0.0f);
+ }
+
+ if (haveUniformColorSeries) {
+ m_barShader->bind();
+ m_barShader->setUniformValue(m_barShader->lightP(), lightPos);
+ m_barShader->setUniformValue(m_barShader->view(), viewMatrix);
+ m_barShader->setUniformValue(m_barShader->ambientS(),
+ m_cachedTheme->ambientLightStrength());
+ barShader = m_barShader;
+ } else {
+ barShader = m_barGradientShader;
+ previousColorStyle = Q3DTheme::ColorStyleRangeGradient;
+ }
+
+ if (m_selectionDirty && m_cachedIsSlicingActivated) {
+ // Slice doesn't own its items, no need to delete them - just clear
+ m_sliceSelection.clear();
+ int reserveAmount;
+ if (rowMode)
+ reserveAmount = m_cachedColumnCount;
+ else
+ reserveAmount = m_cachedRowCount;
+ if (m_cachedSelectionMode.testFlag(QDataVis::SelectionMultiSeries))
+ reserveAmount *= m_visibleSeriesList.size();
+ m_sliceSelection.resize(reserveAmount);
+
+ // Set slice cache, i.e. axis cache from where slice labels are taken
+ if (rowMode)
+ m_sliceCache = &m_axisCacheX;
+ else
+ m_sliceCache = &m_axisCacheZ;
+ m_sliceTitleItem = 0;
}
// Draw bars
- QVector3D barHighlightColor(Utils::vectorFromColor(m_cachedTheme.m_highlightBarColor));
- QVector3D rowHighlightColor(Utils::vectorFromColor(m_cachedTheme.m_highlightRowColor));
- QVector3D columnHighlightColor(Utils::vectorFromColor(m_cachedTheme.m_highlightColumnColor));
- QVector3D baseColor(Utils::vectorFromColor(m_cachedTheme.m_baseColor));
- GLfloat adjustedLightStrength = m_cachedTheme.m_lightStrength / 10.0f;
- GLfloat adjustedHighlightStrength = m_cachedTheme.m_highlightLightStrength / 10.0f;
+ GLfloat adjustedLightStrength = m_cachedTheme->lightStrength() / 10.0f;
+ GLfloat adjustedHighlightStrength = m_cachedTheme->highlightLightStrength() / 10.0f;
bool barSelectionFound = false;
BarRenderItem *selectedBar(0);
- QVector3D modelScaler(m_scaleX, 0.0f, m_scaleZ);
- for (int row = startRow; row != stopRow; row += stepRow) {
- for (int bar = startBar; bar != stopBar; bar += stepBar) {
- BarRenderItem &item = m_renderItemArray[row][bar];
- if (item.height() < 0)
- glCullFace(GL_FRONT);
+ QVector3D baseColor;
+ QVector3D barColor;
+ QVector3D modelScaler(m_scaleX * m_seriesScale, 0.0f, m_scaleZ);
+ bool somethingSelected = (m_visualSelectedBarPos != Bars3DController::invalidSelectionPosition());
+ float seriesPos = m_seriesStart;
+ for (int series = 0; series < seriesCount; series++) {
+ const SeriesRenderCache &currentSeries = m_visibleSeriesList.at(series);
+ ObjectHelper *barObj = currentSeries.object();
+ Q3DTheme::ColorStyle colorStyle = currentSeries.colorStyle();
+ bool colorStyleIsUniform = (colorStyle == Q3DTheme::ColorStyleUniform);
+
+ // Rebind shader if it has changed
+ if (colorStyleIsUniform != (previousColorStyle == Q3DTheme::ColorStyleUniform)) {
+ if (colorStyleIsUniform)
+ barShader = m_barShader;
else
- glCullFace(GL_BACK);
+ barShader = m_barGradientShader;
+ barShader->bind();
+ }
- QMatrix4x4 modelMatrix;
- QMatrix4x4 itModelMatrix;
- QMatrix4x4 MVPMatrix;
+ if (colorStyleIsUniform) {
+ baseColor = currentSeries.baseColor();
+ } else if ((previousColorStyle != colorStyle)
+ && (colorStyle == Q3DTheme::ColorStyleObjectGradient)) {
+ m_barGradientShader->setUniformValue(m_barGradientShader->gradientHeight(), 0.5f);
+ }
- colPos = (bar + 0.5f) * (m_cachedBarSpacing.width());
- rowPos = (row + 0.5f) * (m_cachedBarSpacing.height());
+ // Always use base color when no selection mode
+ if (m_cachedSelectionMode == QDataVis::SelectionNone) {
+ if (colorStyleIsUniform)
+ barColor = baseColor;
+ else
+ gradientTexture = currentSeries.baseGradientTexture();
+ }
- modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor,
- item.height() - m_yAdjustment,
- (m_columnDepth - rowPos) / m_scaleFactor);
- modelScaler.setY(item.height());
- modelMatrix.scale(modelScaler);
- itModelMatrix.scale(modelScaler);
-#ifdef SHOW_DEPTH_TEXTURE_SCENE
- MVPMatrix = depthProjectionViewMatrix * modelMatrix;
-#else
- MVPMatrix = projectionViewMatrix * modelMatrix;
-#endif
+ previousColorStyle = colorStyle;
+ int sliceSeriesAdjust = 0;
+ if (m_selectionDirty && m_cachedIsSlicingActivated) {
+ int seriesMultiplier = 0;
+ if (m_cachedSelectionMode.testFlag(QDataVis::SelectionMultiSeries))
+ seriesMultiplier = series;
+ if (rowMode)
+ sliceSeriesAdjust = seriesMultiplier * m_cachedColumnCount;
+ else
+ sliceSeriesAdjust = seriesMultiplier * m_cachedRowCount;
+ }
+
+ for (int row = startRow; row != stopRow; row += stepRow) {
+ for (int bar = startBar; bar != stopBar; bar += stepBar) {
+ BarRenderItem &item = m_renderingArrays[series][row][bar];
+
+ if (item.height() < 0)
+ glCullFace(GL_FRONT);
+ else
+ glCullFace(GL_BACK);
-#if 0
- QVector3D heightColor = Utils::vectorFromColor(m_cachedTheme.m_heightColor)
- * item.height();
- QVector3D depthColor = Utils::vectorFromColor(m_cachedTheme.m_depthColor)
- * (float(row) / GLfloat(m_cachedRowCount));
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 itModelMatrix;
+ QMatrix4x4 MVPMatrix;
+
+ colPos = (bar + 0.5f + seriesPos) * (m_cachedBarSpacing.width());
+ rowPos = (row + 0.5f) * (m_cachedBarSpacing.height());
- QVector3D barColor = baseColor + heightColor + depthColor;
+ modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor,
+ item.height(),
+ (m_columnDepth - rowPos) / m_scaleFactor);
+ modelScaler.setY(item.height());
+ modelMatrix.scale(modelScaler);
+ itModelMatrix.scale(modelScaler);
+#ifdef SHOW_DEPTH_TEXTURE_SCENE
+ MVPMatrix = depthProjectionViewMatrix * modelMatrix;
#else
- QVector3D barColor = baseColor;
+ MVPMatrix = projectionViewMatrix * modelMatrix;
#endif
-
- GLfloat lightStrength = m_cachedTheme.m_lightStrength;
- GLfloat shadowLightStrength = adjustedLightStrength;
-
- if (m_cachedSelectionMode > QDataVis::SelectionModeNone) {
- Bars3DController::SelectionType selectionType = isSelected(row, bar);
-
- switch (selectionType) {
- case Bars3DController::SelectionItem: {
- barColor = barHighlightColor;
- lightStrength = m_cachedTheme.m_highlightLightStrength;
- shadowLightStrength = adjustedHighlightStrength;
- // Insert position data into render item. We have no ownership, don't delete the previous one
- if (!m_cachedIsSlicingActivated) {
- selectedBar = &item;
- selectedBar->setPosition(QPoint(row, bar));
- item.setTranslation(modelMatrix.column(3).toVector3D());
- barSelectionFound = true;
+ GLfloat lightStrength = m_cachedTheme->lightStrength();
+ GLfloat shadowLightStrength = adjustedLightStrength;
+
+ if (m_cachedSelectionMode > QDataVis::SelectionNone) {
+ Bars3DController::SelectionType selectionType = Bars3DController::SelectionNone;
+ if (somethingSelected)
+ selectionType = isSelected(row, bar, series);
+
+ switch (selectionType) {
+ case Bars3DController::SelectionItem: {
+ if (colorStyleIsUniform)
+ barColor = currentSeries.singleHighlightColor();
+ else
+ gradientTexture = currentSeries.singleHighlightGradientTexture();
+
+ lightStrength = m_cachedTheme->highlightLightStrength();
+ shadowLightStrength = adjustedHighlightStrength;
+ // Insert position data into render item. We have no ownership, don't delete the previous one
+ if (!m_cachedIsSlicingActivated && m_visualSelectedBarSeriesIndex == series) {
+ selectedBar = &item;
+ selectedBar->setPosition(QPoint(row, bar));
+ item.setTranslation(modelMatrix.column(3).toVector3D());
+ barSelectionFound = true;
+ }
+ if (m_selectionDirty && m_cachedIsSlicingActivated) {
+ QVector3D translation = modelMatrix.column(3).toVector3D();
+ if (m_cachedSelectionMode & QDataVis::SelectionColumn
+ && seriesCount > 1) {
+ translation.setZ((m_columnDepth - ((row + 0.5f + seriesPos)
+ * (m_cachedBarSpacing.height())))
+ / m_scaleFactor);
+ }
+ item.setTranslation(translation);
+ item.setPosition(QPoint(row, bar));
+ item.setSeriesIndex(series);
+ if (rowMode)
+ m_sliceSelection[sliceSeriesAdjust + bar] = &item;
+ else
+ m_sliceSelection[sliceSeriesAdjust + row] = &item;
+ }
+ break;
}
- if (selectionDirty && m_cachedSelectionMode >= QDataVis::SelectionModeSliceRow) {
- item.setTranslation(modelMatrix.column(3).toVector3D());
- item.setPosition(QPoint(row, bar));
- m_sliceSelection->append(&item);
- barSelectionFound = true;
- if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow) {
- if (m_axisCacheX.labelItems().size() > row)
- m_sliceTitleItem = m_axisCacheX.labelItems().at(row);
- if (!m_sliceCache) {
- // m_sliceCache is the axis for labels, while title comes from different axis.
- m_sliceCache = &m_axisCacheZ;
+ case Bars3DController::SelectionRow: {
+ // Current bar is on the same row as the selected bar
+ if (colorStyleIsUniform)
+ barColor = currentSeries.multiHighlightColor();
+ else
+ gradientTexture = currentSeries.multiHighlightGradientTexture();
+
+ lightStrength = m_cachedTheme->highlightLightStrength();
+ shadowLightStrength = adjustedHighlightStrength;
+ if (m_cachedIsSlicingActivated) {
+ item.setTranslation(modelMatrix.column(3).toVector3D());
+ item.setPosition(QPoint(row, bar));
+ if (m_selectionDirty) {
+ item.setSeriesIndex(series);
+ if (!m_sliceTitleItem && m_axisCacheZ.labelItems().size() > row)
+ m_sliceTitleItem = m_axisCacheZ.labelItems().at(row);
+ m_sliceSelection[sliceSeriesAdjust + bar] = &item;
}
- } else if (m_cachedSelectionMode == QDataVis::SelectionModeSliceColumn) {
- if (m_axisCacheZ.labelItems().size() > bar)
- m_sliceTitleItem = m_axisCacheZ.labelItems().at(bar);
- if (!m_sliceCache) {
- // m_sliceCache is the axis for labels, while title comes from different axis.
- m_sliceCache = &m_axisCacheX;
+ }
+ break;
+ }
+ case Bars3DController::SelectionColumn: {
+ // Current bar is on the same column as the selected bar
+ if (colorStyleIsUniform)
+ barColor = currentSeries.multiHighlightColor();
+ else
+ gradientTexture = currentSeries.multiHighlightGradientTexture();
+
+ lightStrength = m_cachedTheme->highlightLightStrength();
+ shadowLightStrength = adjustedHighlightStrength;
+ if (m_cachedIsSlicingActivated) {
+ QVector3D translation = modelMatrix.column(3).toVector3D();
+ if (seriesCount > 1) {
+ translation.setZ((m_columnDepth - ((row + 0.5f + seriesPos)
+ * (m_cachedBarSpacing.height())))
+ / m_scaleFactor);
+ }
+ item.setTranslation(translation);
+ item.setPosition(QPoint(row, bar));
+ if (m_selectionDirty) {
+ item.setSeriesIndex(series);
+ if (!m_sliceTitleItem && m_axisCacheX.labelItems().size() > bar)
+ m_sliceTitleItem = m_axisCacheX.labelItems().at(bar);
+ m_sliceSelection[sliceSeriesAdjust + row] = &item;
}
}
+ break;
}
- break;
- }
- case Bars3DController::SelectionRow: {
- // Current bar is on the same row as the selected bar
- barColor = rowHighlightColor;
- lightStrength = m_cachedTheme.m_highlightLightStrength;
- shadowLightStrength = adjustedHighlightStrength;
- if (QDataVis::SelectionModeSliceRow == m_cachedSelectionMode) {
- item.setTranslation(modelMatrix.column(3).toVector3D());
- item.setPosition(QPoint(row, bar));
- if (selectionDirty && bar < m_renderColumns)
- m_sliceSelection->append(&item);
+ case Bars3DController::SelectionNone: {
+ // Current bar is not selected, nor on a row or column
+ if (colorStyleIsUniform)
+ barColor = baseColor;
+ else
+ gradientTexture = currentSeries.baseGradientTexture();
+ break;
}
- break;
- }
- case Bars3DController::SelectionColumn: {
- // Current bar is on the same column as the selected bar
- barColor = columnHighlightColor;
- lightStrength = m_cachedTheme.m_highlightLightStrength;
- shadowLightStrength = adjustedHighlightStrength;
- if (QDataVis::SelectionModeSliceColumn == m_cachedSelectionMode) {
- item.setTranslation(modelMatrix.column(3).toVector3D());
- item.setPosition(QPoint(row, bar));
- if (selectionDirty && row < m_renderRows)
- m_sliceSelection->append(&item);
}
- break;
- }
- case Bars3DController::SelectionNone: {
- // Current bar is not selected, nor on a row or column
- // do nothing
- break;
- }
}
- }
- // Skip drawing of 0 -height bars
- if (item.height() != 0) {
- // Set shader bindings
- m_barShader->setUniformValue(m_barShader->model(), modelMatrix);
- m_barShader->setUniformValue(m_barShader->nModel(),
- itModelMatrix.transposed().inverted());
- m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix);
- m_barShader->setUniformValue(m_barShader->color(), barColor);
+ // Skip drawing of 0-height bars
+ if (item.height() != 0) {
+ // Set shader bindings
+ barShader->setUniformValue(barShader->model(), modelMatrix);
+ barShader->setUniformValue(barShader->nModel(),
+ itModelMatrix.transposed().inverted());
+ barShader->setUniformValue(barShader->MVP(), MVPMatrix);
+ if (colorStyleIsUniform) {
+ barShader->setUniformValue(barShader->color(), barColor);
+ } else if (colorStyle == Q3DTheme::ColorStyleRangeGradient) {
+ barShader->setUniformValue(barShader->gradientHeight(),
+ qAbs(item.height()) / m_gradientFraction);
+ }
#if !defined(QT_OPENGL_ES_2)
- if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
- // Set shadow shader bindings
- QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix;
- m_barShader->setUniformValue(m_barShader->shadowQ(), m_shadowQualityToShader);
- m_barShader->setUniformValue(m_barShader->depth(), depthMVPMatrix);
- m_barShader->setUniformValue(m_barShader->lightS(), shadowLightStrength);
-
- // Draw the object
- m_drawer->drawObject(m_barShader, m_barObj, 0, m_depthTexture);
- } else
+ if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
+ // Set shadow shader bindings
+ QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix;
+ barShader->setUniformValue(barShader->shadowQ(), m_shadowQualityToShader);
+ barShader->setUniformValue(barShader->depth(), depthMVPMatrix);
+ barShader->setUniformValue(barShader->lightS(), shadowLightStrength);
+
+ // Draw the object
+ m_drawer->drawObject(barShader, barObj, gradientTexture, m_depthTexture);
+ } else
#endif
- {
- // Set shadowless shader bindings
- m_barShader->setUniformValue(m_barShader->lightS(), lightStrength);
+ {
+ // Set shadowless shader bindings
+ barShader->setUniformValue(barShader->lightS(), lightStrength);
- // Draw the object
- m_drawer->drawObject(m_barShader, m_barObj);
+ // Draw the object
+ m_drawer->drawObject(barShader, barObj, gradientTexture);
+ }
}
}
}
+ seriesPos += m_seriesStep;
}
- if (selectionDirty)
- emit selectedBarPosChanged(QPoint(int(m_selection.x()), int(m_selection.y())));
-
- // Release bar shader
- m_barShader->release();
-
// Bind background shader
m_backgroundShader->bind();
- if (m_hasNegativeValues)
- glDisable(GL_CULL_FACE);
- else
- glCullFace(GL_BACK);
+ // Reset culling
+ glCullFace(GL_BACK);
// Draw background
GLfloat rowScaleFactor = m_rowWidth / m_scaleFactor;
GLfloat columnScaleFactor = m_columnDepth / m_scaleFactor;
- if (m_cachedIsBackgroundEnabled && m_backgroundObj) {
+ if (m_cachedTheme->isBackgroundEnabled() && m_backgroundObj) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
QVector3D backgroundScaler(rowScaleFactor, 1.0f, columnScaleFactor);
- modelMatrix.translate(0.0f, 1.0f - m_yAdjustment, 0.0f);
+ if (m_hasNegativeValues) {
+ backgroundScaler.setY(0.5f);
+ modelMatrix.translate(0.0f, m_negativeBackgroundAdjustment, 0.0f);
+ } else {
+ modelMatrix.translate(0.0f, 1.0f, 0.0f);
+ }
modelMatrix.scale(backgroundScaler);
- modelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f);
itModelMatrix.scale(backgroundScaler);
+ modelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f);
itModelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f);
#ifdef SHOW_DEPTH_TEXTURE_SCENE
@@ -972,7 +1290,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
#else
MVPMatrix = projectionViewMatrix * modelMatrix;
#endif
- QVector3D backgroundColor = Utils::vectorFromColor(m_cachedTheme.m_backgroundColor);
+ QVector3D backgroundColor = Utils::vectorFromColor(m_cachedTheme->backgroundColor());
// Set shader bindings
m_backgroundShader->setUniformValue(m_backgroundShader->lightP(), lightPos);
@@ -983,7 +1301,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
m_backgroundShader->setUniformValue(m_backgroundShader->MVP(), MVPMatrix);
m_backgroundShader->setUniformValue(m_backgroundShader->color(), backgroundColor);
m_backgroundShader->setUniformValue(m_backgroundShader->ambientS(),
- m_cachedTheme.m_ambientStrength * 2.0f);
+ m_cachedTheme->ambientLightStrength() * 2.0f);
#if !defined(QT_OPENGL_ES_2)
if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
@@ -1002,53 +1320,96 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
{
// Set shadowless shader bindings
m_backgroundShader->setUniformValue(m_backgroundShader->lightS(),
- m_cachedTheme.m_lightStrength);
+ m_cachedTheme->lightStrength());
// Draw the object
m_drawer->drawObject(m_backgroundShader, m_backgroundObj);
}
- }
- // Release background shader
- m_backgroundShader->release();
+ // Draw floor for graph with negatives
+ if (m_hasNegativeValues) {
+ modelMatrix = QMatrix4x4();
+ itModelMatrix = QMatrix4x4();
- // Disable textures
- glDisable(GL_TEXTURE_2D);
+ modelMatrix.scale(backgroundScaler);
- // Reset culling
- if (m_hasNegativeValues) {
- glEnable(GL_CULL_FACE);
- glCullFace(GL_BACK);
+ if (m_yFlipped)
+ modelMatrix.rotate(90.0f, 1.0f, 0.0f, 0.0f);
+ else
+ modelMatrix.rotate(-90.0f, 1.0f, 0.0f, 0.0f);
+
+ itModelMatrix = modelMatrix;
+
+#ifdef SHOW_DEPTH_TEXTURE_SCENE
+ MVPMatrix = depthProjectionViewMatrix * modelMatrix;
+#else
+ MVPMatrix = projectionViewMatrix * modelMatrix;
+#endif
+ // Set changed shader bindings
+ m_backgroundShader->setUniformValue(m_backgroundShader->model(), modelMatrix);
+ m_backgroundShader->setUniformValue(m_backgroundShader->nModel(),
+ itModelMatrix.inverted().transposed());
+ m_backgroundShader->setUniformValue(m_backgroundShader->MVP(), MVPMatrix);
+
+#if !defined(QT_OPENGL_ES_2)
+ if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
+ // Set shadow shader bindings
+ QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix;
+ m_backgroundShader->setUniformValue(m_backgroundShader->depth(), depthMVPMatrix);
+ // Draw the object
+ m_drawer->drawObject(m_backgroundShader, m_gridLineObj, 0, m_depthTexture);
+ } else
+#endif
+ {
+ // Draw the object
+ m_drawer->drawObject(m_backgroundShader, m_gridLineObj);
+ }
+ }
}
+ // Disable textures
+ glDisable(GL_TEXTURE_2D);
+
// Draw grid lines
- if (m_cachedIsGridEnabled && m_heightNormalizer) {
+ if (m_cachedTheme->isGridEnabled() && m_heightNormalizer) {
ShaderHelper *lineShader = m_backgroundShader;
+ QQuaternion lineRotation = QQuaternion();
// Bind bar shader
lineShader->bind();
// Set unchanging shader bindings
- QVector3D barColor = Utils::vectorFromColor(m_cachedTheme.m_gridLine);
+ QVector3D barColor = Utils::vectorFromColor(m_cachedTheme->gridLineColor());
lineShader->setUniformValue(lineShader->lightP(), lightPos);
lineShader->setUniformValue(lineShader->view(), viewMatrix);
lineShader->setUniformValue(lineShader->color(), barColor);
- lineShader->setUniformValue(lineShader->ambientS(), m_cachedTheme.m_ambientStrength);
+ lineShader->setUniformValue(lineShader->ambientS(), m_cachedTheme->ambientLightStrength());
#if !defined(QT_OPENGL_ES_2)
if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
// Set shadowed shader bindings
lineShader->setUniformValue(lineShader->shadowQ(), m_shadowQualityToShader);
lineShader->setUniformValue(lineShader->lightS(),
- m_cachedTheme.m_lightStrength / 20.0f);
+ m_cachedTheme->lightStrength() / 20.0f);
} else
#endif
{
// Set shadowless shader bindings
- lineShader->setUniformValue(lineShader->lightS(), m_cachedTheme.m_lightStrength / 2.5f);
+ lineShader->setUniformValue(lineShader->lightS(), m_cachedTheme->lightStrength() / 2.5f);
}
+ GLfloat yFloorLinePosition = 0.0f;
+ if (m_yFlipped)
+ yFloorLinePosition -= gridLineOffset;
+ else
+ yFloorLinePosition += gridLineOffset;
+
QVector3D gridLineScaler(rowScaleFactor, gridLineWidth, gridLineWidth);
+ if (m_yFlipped)
+ lineRotation = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, 90.0f);
+ else
+ lineRotation = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, -90.0f);
+
// Floor lines: rows
for (GLfloat row = 0.0f; row <= m_cachedRowCount; row++) {
QMatrix4x4 modelMatrix;
@@ -1056,15 +1417,12 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
QMatrix4x4 itModelMatrix;
rowPos = row * m_cachedBarSpacing.height();
- modelMatrix.translate(0.0f, -m_yAdjustment,
+ modelMatrix.translate(0.0f, yFloorLinePosition,
(m_columnDepth - rowPos) / m_scaleFactor);
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
- // If we're viewing from below, grid line object must be flipped
- if (m_yFlipped) {
- modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
- itModelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
- }
+ modelMatrix.rotate(lineRotation);
+ itModelMatrix.rotate(lineRotation);
MVPMatrix = projectionViewMatrix * modelMatrix;
@@ -1098,15 +1456,11 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
colPos = bar * m_cachedBarSpacing.width();
modelMatrix.translate((m_rowWidth - colPos) / m_scaleFactor,
- -m_yAdjustment, 0.0f);
+ yFloorLinePosition, 0.0f);
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
-
- // If we're viewing from below, grid line object must be flipped
- if (m_yFlipped) {
- modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
- itModelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
- }
+ modelMatrix.rotate(lineRotation);
+ itModelMatrix.rotate(lineRotation);
MVPMatrix = projectionViewMatrix * modelMatrix;
@@ -1135,28 +1489,35 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
// Wall lines: back wall
GLfloat heightStep = m_axisCacheY.subSegmentStep();
GLfloat startLine = 0.0f;
+ int segmentCount = m_axisCacheY.segmentCount() * m_axisCacheY.subSegmentCount();
- if (m_hasNegativeValues)
- startLine = -m_heightNormalizer;
+ GLfloat zWallLinePosition = -columnScaleFactor + gridLineOffset;
+ if (m_zFlipped)
+ zWallLinePosition = -zWallLinePosition;
+ if (m_hasNegativeValues) {
+ if (m_noZeroInRange)
+ startLine = m_axisCacheY.min() - m_axisCacheY.max();
+ else
+ startLine = m_axisCacheY.min();
+ }
+
+ GLfloat lineHeight = startLine;
gridLineScaler = QVector3D(rowScaleFactor, gridLineWidth, gridLineWidth);
- for (GLfloat lineHeight = startLine; lineHeight <= m_heightNormalizer;
- lineHeight += heightStep) {
+ for (int segment = 0; segment <= segmentCount; segment++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- if (m_zFlipped) {
- modelMatrix.translate(0.0f,
- 2.0f * lineHeight / m_heightNormalizer - m_yAdjustment,
- columnScaleFactor);
- } else {
- modelMatrix.translate(0.0f,
- 2.0f * lineHeight / m_heightNormalizer - m_yAdjustment,
- -columnScaleFactor);
- }
+ modelMatrix.translate(0.0f,
+ 2.0f * lineHeight / m_heightNormalizer,
+ zWallLinePosition);
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
+ if (m_zFlipped) {
+ modelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
+ itModelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
+ }
MVPMatrix = projectionViewMatrix * modelMatrix;
@@ -1179,27 +1540,33 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
+ lineHeight += heightStep;
}
// Wall lines: side wall
+ GLfloat xWallLinePosition = -rowScaleFactor + gridLineOffset;
+ if (m_xFlipped)
+ xWallLinePosition = -xWallLinePosition;
+
+ if (m_xFlipped)
+ lineRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, -90.0f);
+ else
+ lineRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, 90.0f);
+
+ lineHeight = startLine;
gridLineScaler = QVector3D(gridLineWidth, gridLineWidth, columnScaleFactor);
- for (GLfloat lineHeight = startLine; lineHeight <= m_heightNormalizer;
- lineHeight += heightStep) {
+ for (int segment = 0; segment <= segmentCount; segment++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- if (m_xFlipped) {
- modelMatrix.translate(rowScaleFactor,
- 2.0f * lineHeight / m_heightNormalizer - m_yAdjustment,
- 0.0f);
- } else {
- modelMatrix.translate(-rowScaleFactor,
- 2.0f * lineHeight / m_heightNormalizer - m_yAdjustment,
- 0.0f);
- }
+ modelMatrix.translate(xWallLinePosition,
+ 2.0f * lineHeight / m_heightNormalizer,
+ 0.0f);
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
+ modelMatrix.rotate(lineRotation);
+ itModelMatrix.rotate(lineRotation);
MVPMatrix = projectionViewMatrix * modelMatrix;
@@ -1222,27 +1589,25 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
+ lineHeight += heightStep;
}
}
- // Release bar shader
- lineShader->release();
}
- // TODO: Calculations done temporarily here. When optimizing, move to after data set addition? Keep drawing of the labels here.
// Bind label shader
m_labelShader->bind();
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_POLYGON_OFFSET_FILL);
// Calculate the positions for row and column labels and store them
- GLfloat labelYAdjustment = -m_yAdjustment + 0.005f;
+ GLfloat labelYAdjustment = 0.005f;
GLfloat scaledRowWidth = rowScaleFactor;
GLfloat scaledColumnDepth = columnScaleFactor;
GLfloat colPosValue = scaledRowWidth + labelMargin;
GLfloat rowPosValue = scaledColumnDepth + labelMargin;
- QVector3D positionComp(0.0f, m_yAdjustment, 0.0f);
QVector3D labelRotation(-90.0f, 0.0f, 0.0f);
if (m_zFlipped)
labelRotation.setY(180.0f);
@@ -1253,9 +1618,10 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
labelRotation.setY(180.0f);
labelRotation.setZ(180.0f);
}
+
Qt::AlignmentFlag alignment = m_xFlipped ? Qt::AlignLeft : Qt::AlignRight;
for (int row = 0; row != m_cachedRowCount; row++) {
- if (m_axisCacheX.labelItems().size() > row) {
+ if (m_axisCacheZ.labelItems().size() > row) {
// Go through all rows and get position of max+1 or min-1 column, depending on x flip
// We need only positions for them, labels have already been generated at QDataSetPrivate. Just add LabelItems
rowPos = (row + 0.5f) * m_cachedBarSpacing.height();
@@ -1264,18 +1630,19 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
else
colPos = colPosValue;
+ glPolygonOffset(GLfloat(row) / -10.0f, 1.0f);
+
QVector3D labelPos = QVector3D(colPos,
labelYAdjustment, // raise a bit over background to avoid depth "glimmering"
(m_columnDepth - rowPos) / m_scaleFactor);
m_dummyBarRenderItem.setTranslation(labelPos);
- const LabelItem &axisLabelItem = *m_axisCacheX.labelItems().at(row);
- //qDebug() << "labelPos, row" << row + 1 << ":" << labelPos << m_axisCacheX.labels().at(row);
+ const LabelItem &axisLabelItem = *m_axisCacheZ.labelItems().at(row);
m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- positionComp, labelRotation, 0, m_cachedSelectionMode,
+ zeroVector, labelRotation, 0, m_cachedSelectionMode,
m_labelShader, m_labelObj, activeCamera,
- true, true, Drawer::LabelMid, alignment);
+ true, true, Drawer::LabelMid, alignment, m_cachedIsSlicingActivated);
}
}
labelRotation = QVector3D(-90.0f, 90.0f, 0.0f);
@@ -1290,8 +1657,8 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
}
alignment = m_zFlipped ? Qt::AlignRight : Qt::AlignLeft;
- for (int column = 0; column != m_cachedColumnCount; column += 1) {
- if (m_axisCacheZ.labelItems().size() > column) {
+ for (int column = 0; column != m_cachedColumnCount; column++) {
+ if (m_axisCacheX.labelItems().size() > column) {
// Go through all columns and get position of max+1 or min-1 row, depending on z flip
// We need only positions for them, labels have already been generated at QDataSetPrivate. Just add LabelItems
colPos = (column + 0.5f) * m_cachedBarSpacing.width();
@@ -1300,15 +1667,17 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
else
rowPos = rowPosValue;
+ glPolygonOffset(GLfloat(column) / -10.0f, 1.0f);
+
QVector3D labelPos = QVector3D((colPos - m_rowWidth) / m_scaleFactor,
labelYAdjustment, // raise a bit over background to avoid depth "glimmering"
rowPos);
m_dummyBarRenderItem.setTranslation(labelPos);
- const LabelItem &axisLabelItem = *m_axisCacheZ.labelItems().at(column);
+ const LabelItem &axisLabelItem = *m_axisCacheX.labelItems().at(column);
m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- positionComp, labelRotation, 0, m_cachedSelectionMode,
+ zeroVector, labelRotation, 0, m_cachedSelectionMode,
m_labelShader, m_labelObj, activeCamera,
true, true, Drawer::LabelMid, alignment);
}
@@ -1319,8 +1688,12 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
GLfloat heightStep = m_axisCacheY.segmentStep();
GLfloat startLine = 0.0f;
int labelCount = m_axisCacheY.labels().size();
- if (m_hasNegativeValues)
- startLine = -m_heightNormalizer;
+ if (m_hasNegativeValues) {
+ if (m_noZeroInRange)
+ startLine = m_axisCacheY.min() - m_axisCacheY.max();
+ else
+ startLine = m_axisCacheY.min();
+ }
GLfloat labelPos = startLine;
GLfloat labelMarginXTrans = labelMargin;
GLfloat labelMarginZTrans = labelMargin;
@@ -1349,50 +1722,34 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
for (int i = 0; i < labelCount; i++) {
if (m_axisCacheY.labelItems().size() > labelNbr) {
- backLabelTrans.setY(2.0f * labelPos / m_heightNormalizer - m_yAdjustment);
+ backLabelTrans.setY(2.0f * labelPos / m_heightNormalizer);
sideLabelTrans.setY(backLabelTrans.y());
+ glPolygonOffset(GLfloat(i) / -10.0f, 1.0f);
+
const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(labelNbr);
// Back wall
m_dummyBarRenderItem.setTranslation(backLabelTrans);
m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- positionComp, backLabelRotation, 0, m_cachedSelectionMode,
+ zeroVector, backLabelRotation, 0, m_cachedSelectionMode,
m_labelShader, m_labelObj, activeCamera,
true, true, Drawer::LabelMid, backAlignment);
// Side wall
m_dummyBarRenderItem.setTranslation(sideLabelTrans);
m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- positionComp, sideLabelRotation, 0, m_cachedSelectionMode,
+ zeroVector, sideLabelRotation, 0, m_cachedSelectionMode,
m_labelShader, m_labelObj, activeCamera,
true, true, Drawer::LabelMid, sideAlignment);
}
labelNbr++;
labelPos += heightStep;
}
+ glDisable(GL_POLYGON_OFFSET_FILL);
- // Handle slice activation and selection label drawing
- if (!barSelectionFound) {
- // We have no ownership, don't delete. Just NULL the pointer.
- m_selectedBar = NULL;
- if (m_cachedIsSlicingActivated
- && (m_selection == selectionSkipColor
- || QDataVis::InputStateOnOverview == m_controller->inputState())) {
- m_cachedScene->setSlicingActive(false);
- }
- } else if (m_cachedSelectionMode >= QDataVis::SelectionModeSliceRow && selectionDirty) {
- // Activate slice mode
- m_cachedScene->setSlicingActive(true);
-
- // Create label textures
- for (int col = 0; col < m_sliceSelection->size(); col++) {
- BarRenderItem *item = m_sliceSelection->at(col);
- if (item->sliceLabel().isNull())
- item->setSliceLabel(generateValueLabel(m_axisCacheY.labelFormat(), item->value()));
- m_drawer->generateLabelItem(item->sliceLabelItem(), item->sliceLabel());
- }
- } else {
+ // Handle selected bar label generation
+ if (barSelectionFound) {
// Print value of selected bar
glDisable(GL_DEPTH_TEST);
// Draw the selection label
@@ -1410,22 +1767,24 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
static const QString valueLabelTag(QStringLiteral("@valueLabel"));
// Custom format expects printf format specifier. There is no tag for it.
- labelText = generateValueLabel(itemLabelFormat(), selectedBar->value());
-
- int selBarPosX = selectedBar->position().x();
- int selBarPosY = selectedBar->position().y();
- labelText.replace(rowIndexTag, QString::number(selBarPosX));
- if (m_axisCacheX.labels().size() > selBarPosX)
- labelText.replace(rowLabelTag, m_axisCacheX.labels().at(selBarPosX));
+ labelText = generateValueLabel(
+ m_visibleSeriesList[m_visualSelectedBarSeriesIndex].itemLabelFormat(),
+ selectedBar->value());
+
+ int selBarPosRow = selectedBar->position().x();
+ int selBarPosCol = selectedBar->position().y();
+ labelText.replace(rowIndexTag, QString::number(selBarPosRow));
+ if (m_axisCacheZ.labels().size() > selBarPosRow)
+ labelText.replace(rowLabelTag, m_axisCacheZ.labels().at(selBarPosRow));
else
labelText.replace(rowLabelTag, QString());
- labelText.replace(rowTitleTag, m_axisCacheX.title());
- labelText.replace(colIndexTag, QString::number(selBarPosY));
- if (m_axisCacheZ.labels().size() > selBarPosY)
- labelText.replace(colLabelTag, m_axisCacheZ.labels().at(selBarPosY));
+ labelText.replace(rowTitleTag, m_axisCacheZ.title());
+ labelText.replace(colIndexTag, QString::number(selBarPosCol));
+ if (m_axisCacheX.labels().size() > selBarPosCol)
+ labelText.replace(colLabelTag, m_axisCacheX.labels().at(selBarPosCol));
else
labelText.replace(colLabelTag, QString());
- labelText.replace(colTitleTag, m_axisCacheZ.title());
+ labelText.replace(colTitleTag, m_axisCacheX.title());
labelText.replace(valueTitleTag, m_axisCacheY.title());
if (labelText.contains(valueLabelTag)) {
@@ -1443,7 +1802,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
}
m_drawer->drawLabel(*selectedBar, labelItem, viewMatrix, projectionMatrix,
- positionComp, zeroVector, selectedBar->height(),
+ zeroVector, zeroVector, selectedBar->height(),
m_cachedSelectionMode, m_labelShader,
m_labelObj, activeCamera, true, false);
@@ -1451,23 +1810,17 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
m_updateLabels = false;
glEnable(GL_DEPTH_TEST);
+ } else {
+ m_selectedBar = 0;
}
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
- // Release label shader
- m_labelShader->release();
-}
+ // Release shader
+ glUseProgram(0);
-void Bars3DRenderer::handleResize()
-{
- if (m_cachedBoundingRect.width() == 0 || m_cachedBoundingRect.height() == 0)
- return;
-
- setViewPorts();
-
- Abstract3DRenderer::handleResize();
+ m_selectionDirty = false;
}
void Bars3DRenderer::updateBarSpecs(GLfloat thicknessRatio, const QSizeF &spacing, bool relative)
@@ -1477,17 +1830,24 @@ void Bars3DRenderer::updateBarSpecs(GLfloat thicknessRatio, const QSizeF &spacin
m_cachedBarThickness.setHeight(1.0f / thicknessRatio);
if (relative) {
- m_cachedBarSpacing.setWidth((m_cachedBarThickness.width() * 2) * (spacing.width() + 1.0f));
- m_cachedBarSpacing.setHeight((m_cachedBarThickness.height() * 2) * (spacing.height() + 1.0f));
+ m_cachedBarSpacing.setWidth((m_cachedBarThickness.width() * 2)
+ * (spacing.width() + 1.0f));
+ m_cachedBarSpacing.setHeight((m_cachedBarThickness.height() * 2)
+ * (spacing.height() + 1.0f));
} else {
m_cachedBarSpacing = m_cachedBarThickness * 2 + spacing * 2;
}
+ // Slice mode doesn't update correctly without this
+ if (m_cachedIsSlicingActivated)
+ m_selectionDirty = true;
+
// Calculate here and at setting sample space
calculateSceneScalingFactors();
}
-void Bars3DRenderer::updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, qreal min, qreal max)
+void Bars3DRenderer::updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, float min,
+ float max)
{
Abstract3DRenderer::updateAxisRange(orientation, min, max);
@@ -1505,44 +1865,40 @@ void Bars3DRenderer::updateAxisRange(Q3DAbstractAxis::AxisOrientation orientatio
loadBackgroundMesh();
emit needRender();
}
-
- // TODO Currently bargraph only supports zero centered or zero minimum ranges
- if (min > 0.0 || (min != 0.0 && (qFabs(min) != qFabs(max)))) {
- qWarning() << __FUNCTION__ << "Bar graph currently properly supports only "
- "zero-centered and zero minimum ranges for Y-axis.";
- }
}
}
-void Bars3DRenderer::updateSelectionMode(QDataVis::SelectionMode mode)
+void Bars3DRenderer::updateSelectedBar(const QPoint &position, const QBar3DSeries *series)
{
- Abstract3DRenderer::updateSelectionMode(mode);
+ m_selectedBarPos = position;
+ m_selectedBarSeries = series;
+ m_selectionDirty = true;
+ m_visualSelectedBarSeriesIndex = -1;
- // Create zoom selection if there isn't one
- if (mode >= QDataVis::SelectionModeSliceRow && !m_sliceSelection) {
- m_sliceSelection = new QList<BarRenderItem *>;
- if (mode == QDataVis::SelectionModeSliceRow)
- m_sliceSelection->reserve(m_cachedRowCount);
- else
- m_sliceSelection->reserve(m_cachedColumnCount);
+ if (m_renderingArrays.isEmpty()) {
+ m_visualSelectedBarPos = Bars3DController::invalidSelectionPosition();
+ return;
}
-}
-void Bars3DRenderer::updateBackgroundEnabled(bool enable)
-{
- if (enable != m_cachedIsBackgroundEnabled) {
- Abstract3DRenderer::updateBackgroundEnabled(enable);
- loadMeshFile(); // Load changed bar type
+ int adjustedZ = m_selectedBarPos.x() - int(m_axisCacheZ.min());
+ int adjustedX = m_selectedBarPos.y() - int(m_axisCacheX.min());
+ int maxZ = m_renderingArrays.at(0).size() - 1;
+ int maxX = maxZ >= 0 ? m_renderingArrays.at(0).at(0).size() - 1 : -1;
+
+ for (int i = 0; i < m_visibleSeriesList.size(); i++) {
+ if (m_visibleSeriesList.at(i).series() == series) {
+ m_visualSelectedBarSeriesIndex = i;
+ break;
+ }
}
-}
-void Bars3DRenderer::updateSelectedBarPos(const QPoint &position)
-{
- if (position == Bars3DController::noSelectionPoint())
- m_selection = selectionSkipColor;
- else
- m_selection = QVector3D(position.x(), position.y(), 0);
- emit needRender();
+ if (m_selectedBarPos == Bars3DController::invalidSelectionPosition()
+ || adjustedZ < 0 || adjustedZ > maxZ
+ || adjustedX < 0 || adjustedX > maxX) {
+ m_visualSelectedBarPos = Bars3DController::invalidSelectionPosition();
+ } else {
+ m_visualSelectedBarPos = QPoint(adjustedZ, adjustedX);
+ }
}
void Bars3DRenderer::updateShadowQuality(QDataVis::ShadowQuality quality)
@@ -1587,18 +1943,6 @@ void Bars3DRenderer::updateShadowQuality(QDataVis::ShadowQuality quality)
#endif
}
-void Bars3DRenderer::loadMeshFile()
-{
- QString objectFileName = m_cachedObjFile;
- if (m_barObj)
- delete m_barObj;
- // If background is disabled, load full version of bar mesh
- if (!m_cachedIsBackgroundEnabled)
- objectFileName.append(QStringLiteral("Full"));
- m_barObj = new ObjectHelper(objectFileName);
- m_barObj->load();
-}
-
void Bars3DRenderer::loadBackgroundMesh()
{
if (m_backgroundObj)
@@ -1614,7 +1958,7 @@ void Bars3DRenderer::loadGridLineMesh()
{
if (m_gridLineObj)
delete m_gridLineObj;
- m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/bar"));
+ m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/plane"));
m_gridLineObj->load();
}
@@ -1622,7 +1966,7 @@ void Bars3DRenderer::loadLabelMesh()
{
if (m_labelObj)
delete m_labelObj;
- m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/label"));
+ m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/plane"));
m_labelObj->load();
}
@@ -1632,6 +1976,16 @@ void Bars3DRenderer::updateTextures()
m_updateLabels = true;
}
+void Bars3DRenderer::fixMeshFileName(QString &fileName, QAbstract3DSeries::Mesh mesh)
+{
+ if (!m_cachedTheme->isBackgroundEnabled()) {
+ // Load full version of meshes that have it available
+ // Note: Minimal and Point not supported in bar charts
+ if (mesh != QAbstract3DSeries::MeshSphere)
+ fileName.append(QStringLiteral("Full"));
+ }
+}
+
void Bars3DRenderer::calculateSceneScalingFactors()
{
// Calculate scene scaling and translation factors
@@ -1642,61 +1996,81 @@ void Bars3DRenderer::calculateSceneScalingFactors()
(m_cachedRowCount * (m_maxDimension / m_maxSceneSize)));
m_scaleX = m_cachedBarThickness.width() / m_scaleFactor;
m_scaleZ = m_cachedBarThickness.height() / m_scaleFactor;
- //qDebug() << "m_scaleX" << m_scaleX << "m_scaleFactor" << m_scaleFactor;
- //qDebug() << "m_scaleZ" << m_scaleZ << "m_scaleFactor" << m_scaleFactor;
- //qDebug() << "m_rowWidth:" << m_rowWidth << "m_columnDepth:" << m_columnDepth << "m_maxDimension:" << m_maxDimension;
}
void Bars3DRenderer::calculateHeightAdjustment()
{
- m_heightNormalizer = (GLfloat)qMax(qFabs(m_axisCacheY.min()), qFabs(m_axisCacheY.max()));
+ GLfloat newAdjustment = 0.0f;
+ GLfloat maxAbs = qFabs(m_axisCacheY.max());
- // 2.0f = max difference between minimum and maximum value after scaling with m_heightNormalizer
- GLfloat newAdjustment = 2.0f - ((m_heightNormalizer - m_axisCacheY.min()) / m_heightNormalizer);
- if (newAdjustment != m_yAdjustment) {
+ if (m_axisCacheY.max() < 0.0f) {
+ m_heightNormalizer = GLfloat(qFabs(m_axisCacheY.min()) - qFabs(m_axisCacheY.max()));
+ maxAbs = qFabs(m_axisCacheY.max()) - qFabs(m_axisCacheY.min());
+ } else {
+ m_heightNormalizer = GLfloat(m_axisCacheY.max() - m_axisCacheY.min());
+ }
+
+ // Height fractions are used in gradient calculations and are therefore doubled
+ if (m_axisCacheY.max() < 0.0f || m_axisCacheY.min() > 0.0f) {
+ m_noZeroInRange = true;
+ m_gradientFraction = 2.0f;
+ } else {
+ m_noZeroInRange = false;
+ GLfloat minAbs = qFabs(m_axisCacheY.min());
+ m_gradientFraction = qMax(minAbs, maxAbs) / m_heightNormalizer * 2.0f;
+ }
+
+ // Calculate translation adjustment for negative background
+ newAdjustment = qBound(0.0f, (maxAbs / m_heightNormalizer), 1.0f) * 2.0f - 0.5f;
+
+ if (newAdjustment != m_negativeBackgroundAdjustment) {
m_hasHeightAdjustmentChanged = true;
- m_yAdjustment = newAdjustment;
+ m_negativeBackgroundAdjustment = newAdjustment;
}
- //qDebug() << m_yAdjustment;
}
-Bars3DController::SelectionType Bars3DRenderer::isSelected(GLint row, GLint bar)
+Bars3DController::SelectionType Bars3DRenderer::isSelected(int row, int bar, int seriesIndex)
{
- //static QVector3D prevSel = m_selection; // TODO: For debugging
Bars3DController::SelectionType isSelectedType = Bars3DController::SelectionNone;
- if (m_selection == selectionSkipColor)
- return isSelectedType; // skip window
-
- //#if !defined(QT_OPENGL_ES_2)
- // QVector3D current = QVector3D((GLuint)row, (GLuint)bar, 0);
- //#else
- QVector3D current = QVector3D((GLubyte)row, (GLubyte)bar, 0);
- //#endif
-
- // TODO: For debugging
- //if (selection != prevSel) {
- // qDebug() << "current" << current.x() << current .y() << current.z();
- // qDebug() << "selection" << selection.x() << selection .y() << selection.z();
- // prevSel = selection;
- //}
- if (current == m_selection) {
- isSelectedType = Bars3DController::SelectionItem;
- }
- else if (current.y() == m_selection.y()
- && (m_cachedSelectionMode == QDataVis::SelectionModeItemAndColumn
- || m_cachedSelectionMode == QDataVis::SelectionModeItemRowAndColumn
- || m_cachedSelectionMode == QDataVis::SelectionModeSliceColumn)) {
- isSelectedType = Bars3DController::SelectionColumn;
- }
- else if (current.x() == m_selection.x()
- && (m_cachedSelectionMode == QDataVis::SelectionModeItemAndRow
- || m_cachedSelectionMode == QDataVis::SelectionModeItemRowAndColumn
- || m_cachedSelectionMode == QDataVis::SelectionModeSliceRow)) {
- isSelectedType = Bars3DController::SelectionRow;
+
+ if ((m_cachedSelectionMode.testFlag(QDataVis::SelectionMultiSeries)
+ && m_visualSelectedBarSeriesIndex >= 0)
+ || seriesIndex == m_visualSelectedBarSeriesIndex) {
+ if (row == m_visualSelectedBarPos.x() && bar == m_visualSelectedBarPos.y()
+ && (m_cachedSelectionMode.testFlag(QDataVis::SelectionItem))) {
+ isSelectedType = Bars3DController::SelectionItem;
+ } else if (row == m_visualSelectedBarPos.x()
+ && (m_cachedSelectionMode.testFlag(QDataVis::SelectionRow))) {
+ isSelectedType = Bars3DController::SelectionRow;
+ } else if (bar == m_visualSelectedBarPos.y()
+ && (m_cachedSelectionMode.testFlag(QDataVis::SelectionColumn))) {
+ isSelectedType = Bars3DController::SelectionColumn;
+ }
}
+
return isSelectedType;
}
+QPoint Bars3DRenderer::selectionColorToArrayPosition(const QVector3D &selectionColor)
+{
+ QPoint position;
+ if (selectionColor == selectionSkipColor) {
+ position = Bars3DController::invalidSelectionPosition();
+ } else {
+ position = QPoint(int(selectionColor.x() + int(m_axisCacheZ.min())),
+ int(selectionColor.y()) + int(m_axisCacheX.min()));
+ }
+ return position;
+}
+
+QBar3DSeries *Bars3DRenderer::selectionColorToSeries(const QVector3D &selectionColor)
+{
+ if (selectionColor == selectionSkipColor)
+ return 0;
+ else
+ return static_cast<QBar3DSeries *>(m_visibleSeriesList.at(int(selectionColor.z())).series());
+}
+
void Bars3DRenderer::updateSlicingActive(bool isSlicing)
{
if (isSlicing == m_cachedIsSlicingActivated)
@@ -1704,35 +2078,14 @@ void Bars3DRenderer::updateSlicingActive(bool isSlicing)
m_cachedIsSlicingActivated = isSlicing;
- setViewPorts();
-
if (!m_cachedIsSlicingActivated)
initSelectionBuffer(); // We need to re-init selection buffer in case there has been a resize
#if !defined(QT_OPENGL_ES_2)
updateDepthBuffer(); // Re-init depth buffer as well
#endif
-}
-void Bars3DRenderer::setViewPorts()
-{
- // Update view ports
- if (m_cachedIsSlicingActivated) {
- m_mainViewPort = QRect(0,
- m_cachedBoundingRect.height()
- - (m_cachedBoundingRect.height() / smallerVPSize),
- m_cachedBoundingRect.width() / smallerVPSize,
- m_cachedBoundingRect.height() / smallerVPSize);
- m_sliceViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height());
- } else {
- m_mainViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height());
- m_sliceViewPort = QRect(0, 0, 0, 0);
- }
-}
-
-QRect Bars3DRenderer::mainViewPort()
-{
- return m_mainViewPort;
+ m_selectionDirty = true;
}
void Bars3DRenderer::initShaders(const QString &vertexShader, const QString &fragmentShader)
@@ -1743,12 +2096,20 @@ void Bars3DRenderer::initShaders(const QString &vertexShader, const QString &fra
m_barShader->initialize();
}
+void Bars3DRenderer::initGradientShaders(const QString &vertexShader, const QString &fragmentShader)
+{
+ if (m_barGradientShader)
+ delete m_barGradientShader;
+ m_barGradientShader = new ShaderHelper(this, vertexShader, fragmentShader);
+ m_barGradientShader->initialize();
+}
+
void Bars3DRenderer::initSelectionShader()
{
if (m_selectionShader)
delete m_selectionShader;
- m_selectionShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSelection"),
- QStringLiteral(":/shaders/fragmentSelection"));
+ m_selectionShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexPlainColor"),
+ QStringLiteral(":/shaders/fragmentPlainColor"));
m_selectionShader->initialize();
}
@@ -1759,10 +2120,10 @@ void Bars3DRenderer::initSelectionBuffer()
m_selectionTexture = 0;
}
- if (m_cachedIsSlicingActivated || m_mainViewPort.size().isEmpty())
+ if (m_cachedIsSlicingActivated || m_primarySubViewport.size().isEmpty())
return;
- m_selectionTexture = m_textureHelper->createSelectionTexture(m_mainViewPort.size(),
+ m_selectionTexture = m_textureHelper->createSelectionTexture(m_primarySubViewport.size(),
m_selectionFrameBuffer,
m_selectionDepthBuffer);
}
@@ -1784,50 +2145,15 @@ void Bars3DRenderer::updateDepthBuffer()
m_depthTexture = 0;
}
- if (m_mainViewPort.size().isEmpty())
+ if (m_primarySubViewport.size().isEmpty())
return;
if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
- m_depthTexture = m_textureHelper->createDepthTexture(m_mainViewPort.size(),
- m_depthFrameBuffer,
- m_shadowQualityMultiplier);
- if (!m_depthTexture) {
- switch (m_cachedShadowQuality) {
- case QDataVis::ShadowQualityHigh:
- qWarning("Creating high quality shadows failed. Changing to medium quality.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualityMedium);
- updateShadowQuality(QDataVis::ShadowQualityMedium);
- break;
- case QDataVis::ShadowQualityMedium:
- qWarning("Creating medium quality shadows failed. Changing to low quality.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualityLow);
- updateShadowQuality(QDataVis::ShadowQualityLow);
- break;
- case QDataVis::ShadowQualityLow:
- qWarning("Creating low quality shadows failed. Switching shadows off.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualityNone);
- updateShadowQuality(QDataVis::ShadowQualityNone);
- break;
- case QDataVis::ShadowQualitySoftHigh:
- qWarning("Creating soft high quality shadows failed. Changing to soft medium quality.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualitySoftMedium);
- updateShadowQuality(QDataVis::ShadowQualitySoftMedium);
- break;
- case QDataVis::ShadowQualitySoftMedium:
- qWarning("Creating soft medium quality shadows failed. Changing to soft low quality.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualitySoftLow);
- updateShadowQuality(QDataVis::ShadowQualitySoftLow);
- break;
- case QDataVis::ShadowQualitySoftLow:
- qWarning("Creating soft low quality shadows failed. Switching shadows off.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualityNone);
- updateShadowQuality(QDataVis::ShadowQualityNone);
- break;
- default:
- // You'll never get here
- break;
- }
- }
+ m_depthTexture = m_textureHelper->createDepthTextureFrameBuffer(m_primarySubViewport.size(),
+ m_depthFrameBuffer,
+ m_shadowQualityMultiplier);
+ if (!m_depthTexture)
+ lowerShadowQuality();
}
}
#endif
diff --git a/src/datavisualization/engine/bars3drenderer_p.h b/src/datavisualization/engine/bars3drenderer_p.h
index dd80902a..16e7a476 100644
--- a/src/datavisualization/engine/bars3drenderer_p.h
+++ b/src/datavisualization/engine/bars3drenderer_p.h
@@ -51,9 +51,6 @@ class QT_DATAVISUALIZATION_EXPORT Bars3DRenderer : public Abstract3DRenderer
Q_OBJECT
private:
- // TODO: Filter to the set of attributes to be moved to the model object.
- Bars3DController *m_controller;
-
// Cached state based on emitted signals from the controller
QSizeF m_cachedBarThickness;
QSizeF m_cachedBarSpacing;
@@ -63,21 +60,19 @@ private:
// Internal state
BarRenderItem *m_selectedBar; // points to renderitem array
- QList<BarRenderItem *> *m_sliceSelection;
+ QVector<BarRenderItem *> m_sliceSelection;
AxisRenderCache *m_sliceCache; // not owned
const LabelItem *m_sliceTitleItem; // not owned
bool m_xFlipped;
bool m_zFlipped;
bool m_yFlipped;
- QRect m_mainViewPort;
- QRect m_sliceViewPort;
bool m_updateLabels;
ShaderHelper *m_barShader;
+ ShaderHelper *m_barGradientShader;
ShaderHelper *m_depthShader;
ShaderHelper *m_selectionShader;
ShaderHelper *m_backgroundShader;
ShaderHelper *m_labelShader;
- ObjectHelper *m_barObj;
ObjectHelper *m_backgroundObj;
ObjectHelper *m_gridLineObj;
ObjectHelper *m_labelObj;
@@ -90,7 +85,8 @@ private:
GLfloat m_shadowQualityToShader;
GLint m_shadowQualityMultiplier;
GLfloat m_heightNormalizer;
- GLfloat m_yAdjustment;
+ GLfloat m_gradientFraction;
+ GLfloat m_negativeBackgroundAdjustment;
GLfloat m_rowWidth;
GLfloat m_columnDepth;
GLfloat m_maxDimension;
@@ -98,55 +94,52 @@ private:
GLfloat m_scaleZ;
GLfloat m_scaleFactor;
GLfloat m_maxSceneSize;
- QVector3D m_selection;
- QVector3D m_previousSelection;
- int m_renderRows;
- int m_renderColumns;
-
+ QPoint m_visualSelectedBarPos;
+ int m_visualSelectedBarSeriesIndex;
bool m_hasHeightAdjustmentChanged;
+ QPoint m_selectedBarPos;
+ const QBar3DSeries *m_selectedBarSeries;
BarRenderItem m_dummyBarRenderItem;
-
- BarRenderItemArray m_renderItemArray;
+ QVector<BarRenderItemArray> m_renderingArrays;
+ bool m_noZeroInRange;
+ float m_seriesScale;
+ float m_seriesStep;
+ float m_seriesStart;
public:
explicit Bars3DRenderer(Bars3DController *controller);
~Bars3DRenderer();
- void updateDataModel(QBarDataProxy *dataProxy);
+ void updateData();
void updateScene(Q3DScene *scene);
void render(GLuint defaultFboHandle = 0);
- QRect mainViewPort();
-
protected:
virtual void initializeOpenGL();
- virtual void loadMeshFile();
public slots:
void updateBarSpecs(GLfloat thicknessRatio = 1.0f,
const QSizeF &spacing = QSizeF(1.0, 1.0),
bool relative = true);
- void updateSelectionMode(QDataVis::SelectionMode newMode);
void updateSlicingActive(bool isSlicing);
- void updateBackgroundEnabled(bool enable);
- void updateSelectedBarPos(const QPoint &position);
+ void updateSelectedBar(const QPoint &position, const QBar3DSeries *series);
// Overloaded from abstract renderer
- virtual void updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, qreal min, qreal max);
+ virtual void updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, float min, float max);
signals:
- void selectedBarPosChanged(QPoint position);
+ void barClicked(QPoint position, QBar3DSeries *series);
private:
virtual void initShaders(const QString &vertexShader, const QString &fragmentShader);
+ virtual void initGradientShaders(const QString &vertexShader, const QString &fragmentShader);
virtual void updateShadowQuality(QDataVis::ShadowQuality quality);
virtual void updateTextures();
+ virtual void fixMeshFileName(QString &fileName, QAbstract3DSeries::Mesh mesh);
- void drawSlicedScene(const LabelItem &xLabel, const LabelItem &yLabel, const LabelItem &zLabel);
+ void drawSlicedScene();
void drawScene(GLuint defaultFboHandle);
- void handleResize();
- void setViewPorts();
void loadBackgroundMesh();
void loadGridLineMesh();
void loadLabelMesh();
@@ -160,7 +153,9 @@ private:
#endif
void calculateSceneScalingFactors();
void calculateHeightAdjustment();
- Abstract3DController::SelectionType isSelected(GLint row, GLint bar);
+ Abstract3DController::SelectionType isSelected(int row, int bar, int seriesIndex);
+ QPoint selectionColorToArrayPosition(const QVector3D &selectionColor);
+ QBar3DSeries *selectionColorToSeries(const QVector3D &selectionColor);
Q_DISABLE_COPY(Bars3DRenderer)
diff --git a/src/datavisualization/engine/drawer.cpp b/src/datavisualization/engine/drawer.cpp
index cf390b9d..14f0b315 100644
--- a/src/datavisualization/engine/drawer.cpp
+++ b/src/datavisualization/engine/drawer.cpp
@@ -41,17 +41,22 @@ StaticLibInitializer staticLibInitializer;
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-Drawer::Drawer(const Theme &theme, const QFont &font, QDataVis::LabelStyle style)
+// Vertex array buffer for point
+const GLfloat point_data[] = {0.0f, 0.0f, 0.0f};
+
+Drawer::Drawer(Q3DTheme *theme)
: m_theme(theme),
- m_font(font),
- m_style(style),
- m_textureHelper(0)
+ m_font(theme->font()),
+ m_labelBackground(theme->isLabelBackgroundEnabled()),
+ m_textureHelper(0),
+ m_pointbuffer(0)
{
}
Drawer::~Drawer()
{
delete m_textureHelper;
+ glDeleteBuffers(1, &m_pointbuffer);
}
void Drawer::initializeOpenGL()
@@ -62,19 +67,23 @@ void Drawer::initializeOpenGL()
}
}
-void Drawer::setTheme(const Theme &theme)
+void Drawer::setTheme(Q3DTheme *theme)
{
m_theme = theme;
+ m_font = m_theme->font();
+ m_labelBackground = m_theme->isLabelBackgroundEnabled();
emit drawerChanged();
}
-Theme Drawer::theme() const
+Q3DTheme *Drawer::theme() const
{
return m_theme;
}
void Drawer::setFont(const QFont &font)
{
+ // We need to be able to override theme's font for drawer
+ // TODO: (or do we?)
m_font = font;
emit drawerChanged();
}
@@ -84,9 +93,11 @@ QFont Drawer::font() const
return m_font;
}
-void Drawer::setStyle(QDataVis::LabelStyle style)
+void Drawer::setLabelBackground(bool enabled)
{
- m_style = style;
+ // We need to be able to override theme's label background for drawer
+ // TODO: (or do we?)
+ m_labelBackground = enabled;
emit drawerChanged();
}
@@ -137,10 +148,14 @@ void Drawer::drawObject(ShaderHelper *shader, AbstractObjectHelper *object, GLui
glDisableVertexAttribArray(shader->posAtt());
// Release textures
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, 0);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, 0);
+ if (depthTextureId) {
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+ if (textureId) {
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
}
void Drawer::drawSurfaceGrid(ShaderHelper *shader, SurfaceObject *object)
@@ -163,14 +178,36 @@ void Drawer::drawSurfaceGrid(ShaderHelper *shader, SurfaceObject *object)
glDisableVertexAttribArray(shader->posAtt());
}
+void Drawer::drawPoint(ShaderHelper *shader)
+{
+ // Generate vertex buffer for point if it does not exist
+ if (!m_pointbuffer) {
+ glGenBuffers(1, &m_pointbuffer);
+ glBindBuffer(GL_ARRAY_BUFFER, m_pointbuffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(point_data), point_data, GL_STATIC_DRAW);
+ }
+
+ // 1st attribute buffer : vertices
+ glEnableVertexAttribArray(shader->posAtt());
+ glBindBuffer(GL_ARRAY_BUFFER, m_pointbuffer);
+ glVertexAttribPointer(shader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
+
+ // Draw the point
+ glDrawArrays(GL_POINTS, 0, 1);
+
+ // Free buffers
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glDisableVertexAttribArray(shader->posAtt());
+}
+
void Drawer::drawLabel(const AbstractRenderItem &item, const LabelItem &labelItem,
const QMatrix4x4 &viewmatrix, const QMatrix4x4 &projectionmatrix,
const QVector3D &positionComp, const QVector3D &rotation,
- GLfloat itemHeight, QDataVis::SelectionMode mode,
+ GLfloat itemHeight, QDataVis::SelectionFlags mode,
ShaderHelper *shader, ObjectHelper *object,
- const Q3DCamera *camera,
- bool useDepth, bool rotateAlong,
- LabelPosition position, Qt::AlignmentFlag alignment)
+ const Q3DCamera *camera, bool useDepth, bool rotateAlong,
+ LabelPosition position, Qt::AlignmentFlag alignment, bool isSlicing)
{
// Draw label
if (!labelItem.textureId())
@@ -277,7 +314,7 @@ void Drawer::drawLabel(const AbstractRenderItem &item, const LabelItem &labelIte
xPosition = item.translation().x();
if (useDepth)
zPosition = item.translation().z();
- else if (QDataVis::SelectionModeSliceColumn == mode)
+ else if (mode.testFlag(QDataVis::SelectionColumn) && isSlicing)
xPosition = -(item.translation().z()) + positionComp.z(); // flip first to left
}
@@ -285,21 +322,17 @@ void Drawer::drawLabel(const AbstractRenderItem &item, const LabelItem &labelIte
modelMatrix.translate(xPosition + xAlignment, yPosition + yAlignment, zPosition + zAlignment);
// Rotate
- // TODO: We should convert rotations to use quaternions to avoid rotation order problems
- //QQuaternion rotQuatX = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, rotation.x());
- //QQuaternion rotQuatY = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, rotation.y());
- //QQuaternion rotQuatZ = QQuaternion::fromAxisAndAngle(0.0f, 0.0f, 1.0f, rotation.z());
- //QQuaternion rotQuaternion = rotQuatX + rotQuatY + rotQuatZ;
- //modelMatrix.rotate(rotQuaternion);
- modelMatrix.rotate(rotation.y(), 0.0f, 1.0f, 0.0f);
- modelMatrix.rotate(rotation.z(), 0.0f, 0.0f, 1.0f);
- modelMatrix.rotate(rotation.x(), 1.0f, 0.0f, 0.0f);
+ QQuaternion rotQuatX = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, rotation.x());
+ QQuaternion rotQuatY = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, rotation.y());
+ QQuaternion rotQuatZ = QQuaternion::fromAxisAndAngle(0.0f, 0.0f, 1.0f, rotation.z());
+ QQuaternion rotQuaternion = rotQuatY * rotQuatZ * rotQuatX;
+ modelMatrix.rotate(rotQuaternion);
if (useDepth && !rotateAlong) {
- qreal yComp = qreal(qRadiansToDegrees(qTan(positionComp.y() / cameraDistance)));
+ float yComp = float(qRadiansToDegrees(qTan(positionComp.y() / cameraDistance)));
// Apply negative camera rotations to keep labels facing camera
- qreal camRotationX = camera->xRotation();
- qreal camRotationY = camera->yRotation();
+ float camRotationX = camera->xRotation();
+ float camRotationY = camera->yRotation();
modelMatrix.rotate(-camRotationX, 0.0f, 1.0f, 0.0f);
modelMatrix.rotate(-camRotationY - yComp, 1.0f, 0.0f, 0.0f);
}
@@ -335,10 +368,10 @@ void Drawer::generateLabelItem(LabelItem &item, const QString &text, int widestL
// Print label into a QImage using QPainter
QImage label = Utils::printTextToImage(m_font,
text,
- m_theme.m_textBackgroundColor,
- m_theme.m_textColor,
- m_style,
- m_theme.m_labelBorders,
+ m_theme->labelBackgroundColor(),
+ m_theme->labelTextColor(),
+ m_labelBackground,
+ m_theme->isLabelBorderEnabled(),
widestLabel);
// Set label size
diff --git a/src/datavisualization/engine/drawer_p.h b/src/datavisualization/engine/drawer_p.h
index 89a4ce8c..8bc62209 100644
--- a/src/datavisualization/engine/drawer_p.h
+++ b/src/datavisualization/engine/drawer_p.h
@@ -31,7 +31,7 @@
#include "datavisualizationglobal_p.h"
#include "q3dbars.h"
-#include "theme_p.h"
+#include "q3dtheme.h"
#include "labelitem_p.h"
#include "abstractrenderitem_p.h"
#include <QFont>
@@ -63,28 +63,28 @@ public:
};
public:
- explicit Drawer(const Theme &theme, const QFont &font, QDataVis::LabelStyle style);
+ explicit Drawer(Q3DTheme *theme);
~Drawer();
void initializeOpenGL();
- void setTheme(const Theme &theme);
- Theme theme() const;
+ void setTheme(Q3DTheme *theme);
+ Q3DTheme *theme() const;
void setFont(const QFont &font);
QFont font() const;
- void setStyle(QDataVis::LabelStyle style);
+ void setLabelBackground(bool enabled);
void drawObject(ShaderHelper *shader, AbstractObjectHelper *object, GLuint textureId = 0,
GLuint depthTextureId = 0);
void drawSurfaceGrid(ShaderHelper *shader, SurfaceObject *object);
+ void drawPoint(ShaderHelper *shader);
void drawLabel(const AbstractRenderItem &item, const LabelItem &labelItem,
const QMatrix4x4 &viewmatrix, const QMatrix4x4 &projectionmatrix,
const QVector3D &positionComp, const QVector3D &rotation, GLfloat itemHeight,
- QDataVis::SelectionMode mode, ShaderHelper *shader, ObjectHelper *object,
- const Q3DCamera *camera,
- bool useDepth = false, bool rotateAlong = false,
+ QDataVis::SelectionFlags mode, ShaderHelper *shader, ObjectHelper *object,
+ const Q3DCamera *camera, bool useDepth = false, bool rotateAlong = false,
LabelPosition position = LabelOver,
- Qt::AlignmentFlag alignment = Qt::AlignCenter);
+ Qt::AlignmentFlag alignment = Qt::AlignCenter, bool isSlicing = false);
void generateSelectionLabelTexture(AbstractRenderItem *item);
void generateLabelItem(LabelItem &item, const QString &text, int widestLabel = 0);
@@ -93,10 +93,11 @@ Q_SIGNALS:
void drawerChanged();
private:
- Theme m_theme;
+ Q3DTheme *m_theme;
QFont m_font;
- QDataVis::LabelStyle m_style;
+ bool m_labelBackground;
TextureHelper *m_textureHelper;
+ GLuint m_pointbuffer;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/engine.pri b/src/datavisualization/engine/engine.pri
index 4c905fe9..899979e1 100644
--- a/src/datavisualization/engine/engine.pri
+++ b/src/datavisualization/engine/engine.pri
@@ -2,7 +2,6 @@ HEADERS += $$PWD/q3dwindow_p.h \
$$PWD/q3dwindow.h \
$$PWD/q3dbars.h \
$$PWD/q3dbars_p.h \
- $$PWD/theme_p.h \
$$PWD/drawer_p.h \
$$PWD/bars3dcontroller_p.h \
$$PWD/bars3drenderer_p.h \
@@ -16,6 +15,7 @@ HEADERS += $$PWD/q3dwindow_p.h \
$$PWD/scatter3dcontroller_p.h \
$$PWD/scatter3drenderer_p.h \
$$PWD/axisrendercache_p.h \
+ $$PWD/seriesrendercache_p.h \
$$PWD/abstract3drenderer_p.h \
$$PWD/selectionpointer_p.h \
$$PWD/q3dcamera.h \
@@ -30,7 +30,6 @@ HEADERS += $$PWD/q3dwindow_p.h \
SOURCES += $$PWD/q3dwindow.cpp \
$$PWD/q3dbars.cpp \
- $$PWD/theme.cpp \
$$PWD/drawer.cpp \
$$PWD/bars3dcontroller.cpp \
$$PWD/bars3drenderer.cpp \
@@ -42,6 +41,7 @@ SOURCES += $$PWD/q3dwindow.cpp \
$$PWD/scatter3dcontroller.cpp \
$$PWD/scatter3drenderer.cpp \
$$PWD/axisrendercache.cpp \
+ $$PWD/seriesrendercache.cpp \
$$PWD/abstract3drenderer.cpp \
$$PWD/selectionpointer.cpp \
$$PWD/q3dcamera.cpp \
diff --git a/src/datavisualization/engine/engine.qrc b/src/datavisualization/engine/engine.qrc
index 7420ae51..8fcaecec 100644
--- a/src/datavisualization/engine/engine.qrc
+++ b/src/datavisualization/engine/engine.qrc
@@ -8,14 +8,12 @@
<file alias="barSmooth">meshes/cubeSmooth.obj</file>
<file alias="cylinder">meshes/cylinderFlat.obj</file>
<file alias="cylinderSmooth">meshes/cylinderSmooth.obj</file>
- <file alias="background">meshes/backgroudFlat.obj</file>
- <file alias="backgroundSmooth">meshes/backgroudSmooth.obj</file>
- <file alias="label">meshes/plane.obj</file>
+ <file alias="background">meshes/background.obj</file>
+ <file alias="plane">meshes/plane.obj</file>
<file alias="sphere">meshes/sphere.obj</file>
<file alias="sphereSmooth">meshes/sphereSmooth.obj</file>
<file alias="bevelbar">meshes/barFlat.obj</file>
<file alias="bevelbarSmooth">meshes/barSmooth.obj</file>
- <file alias="negativeBackground">meshes/backgroudNegatives.obj</file>
<file alias="coneFull">meshes/coneFilledFlat.obj</file>
<file alias="coneSmoothFull">meshes/coneFilledSmooth.obj</file>
<file alias="cylinderFull">meshes/cylinderFilledFlat.obj</file>
@@ -26,18 +24,16 @@
<file alias="bevelbarSmoothFull">meshes/barFilledSmooth.obj</file>
<file alias="barFull">meshes/cubeFilledFlat.obj</file>
<file alias="barSmoothFull">meshes/cubeFilledSmooth.obj</file>
- <file alias="dotSmooth">meshes/scatterdot.obj</file>
- <file alias="dot">meshes/scatterdotFlat.obj</file>
+ <file alias="negativeBackground">meshes/backgroundNegatives.obj</file>
+ <file alias="minimal">meshes/minimalFlat.obj</file>
+ <file alias="minimalSmooth">meshes/minimalSmooth.obj</file>
</qresource>
<qresource prefix="/shaders">
<file alias="fragment">shaders/default.frag</file>
<file alias="vertex">shaders/default.vert</file>
- <file alias="fragmentAmbient">shaders/ambient.frag</file>
<file alias="fragmentColorOnY">shaders/colorOnY.frag</file>
- <file alias="fragmentSelection">shaders/selection.frag</file>
- <file alias="vertexSelection">shaders/selection.vert</file>
- <file alias="fragmentTexture">shaders/texture.frag</file>
- <file alias="vertexTexture">shaders/texture.vert</file>
+ <file alias="fragmentPlainColor">shaders/plainColor.frag</file>
+ <file alias="vertexPlainColor">shaders/plainColor.vert</file>
<file alias="fragmentLabel">shaders/label.frag</file>
<file alias="vertexLabel">shaders/label.vert</file>
<file alias="fragmentDepth">shaders/depth.frag</file>
@@ -48,15 +44,13 @@
<file alias="fragmentShadowNoTexColorOnY">shaders/shadowNoTexColorOnY.frag</file>
<file alias="fragmentColorOnYES2">shaders/colorOnY_ES2.frag</file>
<file alias="fragmentES2">shaders/default_ES2.frag</file>
- <file alias="vertexES2">shaders/default_ES2.vert</file>
- <file alias="fragmentTextureES2">shaders/texture_ES2.frag</file>
<file alias="fragmentSurface">shaders/surface.frag</file>
- <file alias="vertexSurface">shaders/surface.vert</file>
- <file alias="fragmentSurfaceGrid">shaders/surfaceGrid.frag</file>
- <file alias="vertexSurfaceGrid">shaders/surfaceGrid.vert</file>
<file alias="vertexSurfaceFlat">shaders/surfaceFlat.vert</file>
<file alias="fragmentSurfaceFlat">shaders/surfaceFlat.frag</file>
<file alias="fragmentSurfaceES2">shaders/surface_ES2.frag</file>
+ <file alias="vertexPointES2">shaders/point_ES2.vert</file>
+ <file alias="fragmentSurfaceShadowNoTex">shaders/surfaceShadowNoTex.frag</file>
+ <file alias="fragmentSurfaceShadowFlat">shaders/surfaceShadowFlat.frag</file>
+ <file alias="vertexSurfaceShadowFlat">shaders/surfaceShadowFlat.vert</file>
</qresource>
- <qresource prefix="/textures"/>
</RCC>
diff --git a/src/datavisualization/engine/meshes/backgroudNegatives.obj b/src/datavisualization/engine/meshes/backgroudNegatives.obj
deleted file mode 100644
index 4153bfd4..00000000
--- a/src/datavisualization/engine/meshes/backgroudNegatives.obj
+++ /dev/null
@@ -1,33 +0,0 @@
-# Blender v2.66 (sub 0) OBJ File: 'backgroudNegatives.blend'
-# www.blender.org
-o Cube
-v 1.000000 -1.000000 -1.000000
-v 1.000000 -1.000000 1.000000
-v -1.000000 -1.000000 1.000000
-v -1.000000 -1.000000 -1.000000
-v 1.000000 1.000000 1.000000
-v -1.000000 1.000000 1.000000
-v -1.000000 1.000000 -1.000000
-v 1.000000 -3.000000 1.000000
-v -1.000000 -3.000000 1.000000
-v -1.000000 -3.000000 -1.000000
-vt 0.000100 0.666700
-vt 0.333300 0.666700
-vt 0.333300 0.999900
-vt 0.000100 0.000100
-vt 0.333300 0.000100
-vt 0.333300 0.666500
-vt 0.666500 0.000100
-vt 0.666500 0.666500
-vt 0.000100 0.999900
-vt 0.000100 0.666500
-vn -0.000000 1.000000 0.000000
-vn 0.000000 -0.000000 -1.000000
-vn 1.000000 0.000000 0.000000
-s off
-f 1/1/1 4/2/1 3/3/1
-f 8/4/2 9/5/2 6/6/2
-f 9/5/3 10/7/3 7/8/3
-f 2/9/1 1/1/1 3/3/1
-f 5/10/2 8/4/2 6/6/2
-f 6/6/3 9/5/3 7/8/3
diff --git a/src/datavisualization/engine/meshes/backgroudSmooth.obj b/src/datavisualization/engine/meshes/backgroudSmooth.obj
deleted file mode 100644
index 27d06aea..00000000
--- a/src/datavisualization/engine/meshes/backgroudSmooth.obj
+++ /dev/null
@@ -1,36 +0,0 @@
-# Blender v2.66 (sub 0) OBJ File: 'backgroud.blend'
-# www.blender.org
-o Cube
-v 1.000000 -1.000000 -1.000000
-v 1.000000 -1.000000 1.000000
-v -1.000000 -1.000000 1.000000
-v -1.000000 -1.000000 -1.000000
-v 1.000000 1.000000 1.000000
-v -1.000000 1.000000 1.000000
-v -1.000000 1.000000 -1.000000
-vt 0.000000 0.501529
-vt 0.001529 1.000000
-vt 0.500000 0.998471
-vt 0.501529 0.500000
-vt 1.000000 0.498471
-vt 0.998471 0.000000
-vt 0.500000 0.498471
-vt 0.498471 0.000000
-vt 0.000000 0.001529
-vt 0.498471 0.500000
-vt 0.500000 0.001529
-vt 0.001529 0.500000
-vn 0.000000 1.000000 0.000000
-vn 0.707083 0.707083 0.000000
-vn 0.577349 0.577349 -0.577349
-vn 0.000000 0.707083 -0.707083
-vn 0.707083 0.000000 -0.707083
-vn 1.000000 0.000000 0.000000
-vn 0.000000 0.000000 -1.000000
-s 1
-f 1/1/1 4/2/2 3/3/3
-f 2/4/4 3/5/3 6/6/5
-f 3/7/3 4/8/2 7/9/6
-f 2/10/4 1/1/1 3/3/3
-f 5/11/7 2/4/4 6/6/5
-f 6/12/5 3/7/3 7/9/6
diff --git a/src/datavisualization/engine/meshes/backgroudFlat.obj b/src/datavisualization/engine/meshes/background.obj
index 5eeb1f26..5eeb1f26 100644
--- a/src/datavisualization/engine/meshes/backgroudFlat.obj
+++ b/src/datavisualization/engine/meshes/background.obj
diff --git a/src/datavisualization/engine/meshes/backgroundNegatives.obj b/src/datavisualization/engine/meshes/backgroundNegatives.obj
new file mode 100644
index 00000000..76c7c1d8
--- /dev/null
+++ b/src/datavisualization/engine/meshes/backgroundNegatives.obj
@@ -0,0 +1,22 @@
+# Blender v2.66 (sub 0) OBJ File: 'backgroudNegativesWall.blend'
+# www.blender.org
+o Cube
+v 0.999999 1.000000 1.000001
+v -1.000000 1.000000 1.000000
+v -1.000000 1.000000 -1.000000
+v 1.000000 -3.000000 1.000000
+v -1.000000 -3.000000 1.000000
+v -1.000000 -3.000000 -1.000000
+vt 0.000100 0.000100
+vt 0.500000 0.000100
+vt 0.500000 0.999900
+vt 0.999900 0.000100
+vt 0.999900 0.999900
+vt 0.000100 0.999900
+vn 0.000000 -0.000000 -1.000000
+vn 1.000000 0.000000 0.000000
+s off
+f 4/1/1 5/2/1 2/3/1
+f 5/2/2 6/4/2 3/5/2
+f 1/6/1 4/1/1 2/3/1
+f 2/3/2 5/2/2 3/5/2
diff --git a/src/datavisualization/engine/meshes/minimalFlat.obj b/src/datavisualization/engine/meshes/minimalFlat.obj
new file mode 100644
index 00000000..9ab60a21
--- /dev/null
+++ b/src/datavisualization/engine/meshes/minimalFlat.obj
@@ -0,0 +1,27 @@
+# Blender v2.66 (sub 0) OBJ File: 'scatterdot.blend'
+# www.blender.org
+o Cone
+v 0.000000 -1.000000 -1.414000
+v 1.224560 -1.000000 0.707000
+v 0.000000 1.000000 0.000000
+v -1.224560 -1.000000 0.707000
+vt 0.499966 0.866025
+vt 0.000000 1.153999
+vt 0.000590 0.577029
+vt 0.999376 0.000000
+vt 1.000000 0.577029
+vt 0.500000 0.288996
+vt 1.000000 0.866025
+vt 0.500000 1.154058
+vt 0.500624 0.577029
+vt 0.000000 0.577029
+vt 0.000624 0.000000
+vn -0.000000 -1.000000 0.000000
+vn 0.816510 0.333289 -0.471412
+vn -0.000000 0.333289 0.942825
+vn -0.816510 0.333289 -0.471413
+s off
+f 4/1/1 1/2/1 2/3/1
+f 1/4/2 3/5/2 2/6/2
+f 2/7/3 3/8/3 4/9/3
+f 4/6/4 3/10/4 1/11/4
diff --git a/src/datavisualization/engine/meshes/minimalSmooth.obj b/src/datavisualization/engine/meshes/minimalSmooth.obj
new file mode 100644
index 00000000..dd2e77d3
--- /dev/null
+++ b/src/datavisualization/engine/meshes/minimalSmooth.obj
@@ -0,0 +1,27 @@
+# Blender v2.66 (sub 0) OBJ File: 'scatterdot.blend'
+# www.blender.org
+o Cone
+v 0.000000 -1.000000 -1.414000
+v 1.224560 -1.000000 0.707000
+v 0.000000 1.000000 0.000000
+v -1.224560 -1.000000 0.707000
+vt 0.499966 0.866025
+vt 0.000000 1.153999
+vt 0.000590 0.577029
+vt 0.999376 0.000000
+vt 1.000000 0.577029
+vt 0.500000 0.288996
+vt 1.000000 0.866025
+vt 0.500000 1.154058
+vt 0.500624 0.577029
+vt 0.000000 0.577029
+vt 0.000624 0.000000
+vn -0.816462 -0.333354 0.471389
+vn 0.000000 -0.333354 -0.942778
+vn 0.816462 -0.333354 0.471389
+vn 0.000000 1.000000 0.000000
+s 1
+f 4/1/1 1/2/2 2/3/3
+f 1/4/2 3/5/4 2/6/3
+f 2/7/3 3/8/4 4/9/1
+f 4/6/1 3/10/4 1/11/2
diff --git a/src/datavisualization/engine/meshes/scatterdot.obj b/src/datavisualization/engine/meshes/scatterdot.obj
deleted file mode 100644
index d994a80f..00000000
--- a/src/datavisualization/engine/meshes/scatterdot.obj
+++ /dev/null
@@ -1,28 +0,0 @@
-# Blender v2.66 (sub 0) OBJ File: 'scatterdot.blend'
-# www.blender.org
-o Cone
-v 0.000000 -0.500000 -1.000000
-v 0.866025 -0.500000 0.500000
-v 0.000000 0.500000 0.000000
-v -0.866025 -0.500000 0.500000
-vt 0.999727 0.000000
-vt 1.000000 0.492691
-vt 0.522886 0.369782
-vt 0.477114 0.973202
-vt 0.000000 1.096111
-vt 0.000273 0.603420
-vt 0.523159 0.985382
-vt 0.522886 0.492691
-vt 1.000000 0.615600
-vt 0.000000 0.603420
-vt 0.000617 0.000000
-vt 0.522886 0.302245
-vn -0.833033 -0.273293 0.480941
-vn 0.000000 0.999969 0.000000
-vn 0.000000 -0.273293 -0.961913
-vn 0.833033 -0.273293 0.480941
-s 1
-f 4/1/1 3/2/2 1/3/3
-f 1/4/3 3/5/2 2/6/4
-f 2/7/4 3/8/2 4/9/1
-f 1/10/3 2/11/4 4/12/1
diff --git a/src/datavisualization/engine/meshes/scatterdotFlat.obj b/src/datavisualization/engine/meshes/scatterdotFlat.obj
deleted file mode 100644
index 4052738d..00000000
--- a/src/datavisualization/engine/meshes/scatterdotFlat.obj
+++ /dev/null
@@ -1,28 +0,0 @@
-# Blender v2.66 (sub 0) OBJ File: 'scatterdot.blend'
-# www.blender.org
-o Cone
-v 0.000000 -0.500000 -1.000000
-v 0.866025 -0.500000 0.500000
-v 0.000000 0.500000 0.000000
-v -0.866025 -0.500000 0.500000
-vt 0.999727 0.000000
-vt 1.000000 0.492691
-vt 0.522886 0.369782
-vt 0.477114 0.973202
-vt 0.000000 1.096111
-vt 0.000273 0.603420
-vt 0.523159 0.985382
-vt 0.522886 0.492691
-vt 1.000000 0.615600
-vt 0.000000 0.603420
-vt 0.000617 0.000000
-vt 0.522886 0.302245
-vn -0.774597 0.447214 -0.447214
-vn 0.774597 0.447214 -0.447214
-vn -0.000000 0.447214 0.894427
-vn 0.000000 -1.000000 -0.000000
-s off
-f 4/1/1 3/2/1 1/3/1
-f 1/4/2 3/5/2 2/6/2
-f 2/7/3 3/8/3 4/9/3
-f 1/10/4 2/11/4 4/12/4
diff --git a/src/datavisualization/engine/q3dbars.cpp b/src/datavisualization/engine/q3dbars.cpp
index d6b48e03..d4e97519 100644
--- a/src/datavisualization/engine/q3dbars.cpp
+++ b/src/datavisualization/engine/q3dbars.cpp
@@ -21,12 +21,11 @@
#include "bars3dcontroller_p.h"
#include "q3dvalueaxis.h"
#include "q3dcategoryaxis.h"
-#include "qbardataproxy.h"
#include "q3dcamera.h"
+#include "qbar3dseries_p.h"
#include <QMouseEvent>
-#include <QDebug>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
@@ -46,28 +45,30 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
* These default axes can be modified via axis accessors, but as soon any axis is set explicitly
* for the orientation, the default axis for that orientation is destroyed.
*
- * Data proxies work similarly: If no data proxy is set explicitly, Q3DBars creates a default
- * proxy. If any other proxy is set as active data proxy later, the default proxy and all data
- * added to it is destroyed.
+ * Q3DBars supports more than one series visible at the same time. It is not necessary for all series
+ * to have the same amount of rows and columns.
+ * Row and column labels are taken from the first added series, unless explicitly defined to
+ * row and column axes.
*
- * Methods are provided for changing bar types, themes, bar selection modes and so on. See the
+ * Methods are provided for changing themes, bar selection modes and so on. See the
* methods for more detailed descriptions.
*
* \section1 How to construct a minimal Q3DBars graph
*
- * First, construct an instance of Q3DBars:
+ * First, construct an instance of Q3DBars. Since we are running the graph as top level window
+ * in this example, we need to clear the \c Qt::FramelessWindowHint flag, which gets set by
+ * default:
*
* \snippet doc_src_q3dbars_construction.cpp 4
*
* After constructing Q3DBars, you can set the data window by changing the range on the row and
* column axes. It is not mandatory, as data window will default to showing all of the data in
- * the data proxy. If the amount of data is large, it is usually preferable to show just a
+ * the series. If the amount of data is large, it is usually preferable to show just a
* portion of it. For the example, let's set the data window to show first five rows and columns:
*
* \snippet doc_src_q3dbars_construction.cpp 0
*
- * Now Q3DBars is ready to receive data to be rendered. Add one row of 5 qreals into the data
- * set:
+ * Now Q3DBars is ready to receive data to be rendered. Create a series with one row of 5 values:
*
* \snippet doc_src_q3dbars_construction.cpp 1
*
@@ -95,99 +96,119 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*/
/*!
- * Constructs a new 3D bar window.
+ * Constructs a new 3D bar graph with optional \a parent window.
*/
-Q3DBars::Q3DBars()
- : d_ptr(new Q3DBarsPrivate(this, geometry()))
+Q3DBars::Q3DBars(QWindow *parent)
+ : Q3DWindow(new Q3DBarsPrivate(this), parent)
{
- setVisualController(d_ptr->m_shared);
- d_ptr->m_shared->initializeOpenGL();
- QObject::connect(d_ptr->m_shared, &Bars3DController::selectedBarPosChanged, this,
- &Q3DBars::selectedBarPosChanged);
- QObject::connect(d_ptr->m_shared, &Abstract3DController::needRender, this,
- &Q3DWindow::renderLater);
+ dptr()->m_shared = new Bars3DController(geometry());
+ d_ptr->setVisualController(dptr()->m_shared);
+ dptr()->m_shared->initializeOpenGL();
+ QObject::connect(dptr()->m_shared, &Abstract3DController::selectionModeChanged, this,
+ &Q3DBars::selectionModeChanged);
+ QObject::connect(dptr()->m_shared, &Abstract3DController::shadowQualityChanged, this,
+ &Q3DBars::shadowQualityChanged);
+ QObject::connect(dptr()->m_shared, &Abstract3DController::themeChanged, this,
+ &Q3DBars::themeChanged);
+ QObject::connect(dptr()->m_shared, &Abstract3DController::needRender, d_ptr.data(),
+ &Q3DWindowPrivate::renderLater);
+ QObject::connect(dptr()->m_shared, &Abstract3DController::shadowQualityChanged, dptr(),
+ &Q3DBarsPrivate::handleShadowQualityUpdate);
}
/*!
- * Destroys the 3D bar window.
+ * Destroys the 3D bar graph.
*/
Q3DBars::~Q3DBars()
{
}
/*!
- * \internal
+ * Adds the \a series to the graph. A graph can contain multiple series, but only one set of axes,
+ * so the rows and columns of all series must match for the visualized data to be meaningful.
+ * If the graph has multiple visible series, only the first one added will
+ * generate the row or column labels on the axes in cases where the labels are not explicitly set
+ * to the axes. If the newly added series has specified a selected bar, it will be highlighted and
+ * any existing selection will be cleared. Only one added series can have an active selection.
*/
-void Q3DBars::mouseDoubleClickEvent(QMouseEvent *event)
+void Q3DBars::addSeries(QBar3DSeries *series)
{
- d_ptr->m_shared->mouseDoubleClickEvent(event);
+ dptr()->m_shared->addSeries(series);
}
/*!
- * \internal
+ * Removes the \a series from the graph.
*/
-void Q3DBars::touchEvent(QTouchEvent *event)
+void Q3DBars::removeSeries(QBar3DSeries *series)
{
- d_ptr->m_shared->touchEvent(event);
+ dptr()->m_shared->removeSeries(series);
}
/*!
- * \internal
+ * \return list of series added to this graph.
*/
-void Q3DBars::mousePressEvent(QMouseEvent *event)
+QList<QBar3DSeries *> Q3DBars::seriesList()
{
- d_ptr->m_shared->mousePressEvent(event, event->pos());
+ return dptr()->m_shared->barSeriesList();
}
/*!
* \internal
*/
-void Q3DBars::mouseReleaseEvent(QMouseEvent *event)
+void Q3DBars::mouseDoubleClickEvent(QMouseEvent *event)
{
- d_ptr->m_shared->mouseReleaseEvent(event, event->pos());
+ dptr()->m_shared->mouseDoubleClickEvent(event);
}
/*!
* \internal
*/
-void Q3DBars::mouseMoveEvent(QMouseEvent *event)
+void Q3DBars::touchEvent(QTouchEvent *event)
{
- d_ptr->m_shared->mouseMoveEvent(event, event->pos());
+ dptr()->m_shared->touchEvent(event);
}
/*!
* \internal
*/
-void Q3DBars::wheelEvent(QWheelEvent *event)
+void Q3DBars::mousePressEvent(QMouseEvent *event)
{
- d_ptr->m_shared->wheelEvent(event);
+ dptr()->m_shared->mousePressEvent(event, event->pos());
}
/*!
* \internal
*/
-void Q3DBars::resizeEvent(QResizeEvent *event)
+void Q3DBars::mouseReleaseEvent(QMouseEvent *event)
{
- Q_UNUSED(event);
- d_ptr->m_shared->setSize(width(), height());
+ dptr()->m_shared->mouseReleaseEvent(event, event->pos());
}
/*!
- * Sets window \a width.
+ * \internal
*/
-void Q3DBars::setWidth(const int width)
+void Q3DBars::mouseMoveEvent(QMouseEvent *event)
{
- d_ptr->m_shared->setWidth(width);
- QWindow::setWidth(width);
+ dptr()->m_shared->mouseMoveEvent(event, event->pos());
}
/*!
- * Sets window \a height.
+ * \internal
*/
-void Q3DBars::setHeight(const int height)
+void Q3DBars::wheelEvent(QWheelEvent *event)
+{
+ dptr()->m_shared->wheelEvent(event);
+}
+
+
+Q3DBarsPrivate *Q3DBars::dptr()
{
- d_ptr->m_shared->setHeight(height);
- QWindow::setHeight(height);
+ return static_cast<Q3DBarsPrivate *>(d_ptr.data());
+}
+
+const Q3DBarsPrivate *Q3DBars::dptrc() const
+{
+ return static_cast<const Q3DBarsPrivate *>(d_ptr.data());
}
/*!
@@ -196,14 +217,17 @@ void Q3DBars::setHeight(const int height)
* Bar thickness ratio between X and Z dimensions. 1.0 means bars are as wide as they are deep, 0.5
* makes them twice as deep as they are wide. It is preset to \c 1.0 by default.
*/
-void Q3DBars::setBarThickness(qreal thicknessRatio)
+void Q3DBars::setBarThickness(float thicknessRatio)
{
- d_ptr->m_shared->setBarSpecs(GLfloat(thicknessRatio), barSpacing(), isBarSpacingRelative());
+ if (thicknessRatio != barThickness()) {
+ dptr()->m_shared->setBarSpecs(GLfloat(thicknessRatio), barSpacing(), isBarSpacingRelative());
+ emit barThicknessChanged(thicknessRatio);
+ }
}
-qreal Q3DBars::barThickness()
+float Q3DBars::barThickness()
{
- return d_ptr->m_shared->barThickness();
+ return dptr()->m_shared->barThickness();
}
/*!
@@ -216,12 +240,15 @@ qreal Q3DBars::barThickness()
*/
void Q3DBars::setBarSpacing(QSizeF spacing)
{
- d_ptr->m_shared->setBarSpecs(GLfloat(barThickness()), spacing, isBarSpacingRelative());
+ if (spacing != barSpacing()) {
+ dptr()->m_shared->setBarSpecs(GLfloat(barThickness()), spacing, isBarSpacingRelative());
+ emit barSpacingChanged(spacing);
+ }
}
QSizeF Q3DBars::barSpacing()
{
- return d_ptr->m_shared->barSpacing();
+ return dptr()->m_shared->barSpacing();
}
/*!
@@ -233,112 +260,48 @@ QSizeF Q3DBars::barSpacing()
*/
void Q3DBars::setBarSpacingRelative(bool relative)
{
- d_ptr->m_shared->setBarSpecs(GLfloat(barThickness()), barSpacing(), relative);
+ if (relative != isBarSpacingRelative()) {
+ dptr()->m_shared->setBarSpecs(GLfloat(barThickness()), barSpacing(), relative);
+ emit barSpacingRelativeChanged(relative);
+ }
}
bool Q3DBars::isBarSpacingRelative()
{
- return d_ptr->m_shared->isBarSpecRelative();
+ return dptr()->m_shared->isBarSpecRelative();
}
/*!
- * Sets the bar \a style to one of the values in \c QDataVis::MeshStyle. It is preset to
- * \c QDataVis::MeshStyleBars by default. A \a smooth flag can be used to set shading to smooth.
- * It is \c false by default.
+ * \property Q3DBars::theme
*
- * \sa setMeshFileName()
+ * A \a theme to be used for the graph. Ownership of the \a theme is transferred. Previous theme
+ * is deleted when a new one is set. Properties of the \a theme can be modified even after setting
+ * it, and the modifications take effect immediately.
*/
-void Q3DBars::setBarType(QDataVis::MeshStyle style, bool smooth)
+void Q3DBars::setTheme(Q3DTheme *theme)
{
- d_ptr->m_shared->setBarType(style, smooth);
+ dptr()->m_shared->setTheme(theme);
}
-/*!
- * Sets a predefined \a theme from \c QDataVis::Theme. It is preset to \c QDataVis::ThemeQt by
- * default. Theme affects bar colors, label colors, text color, background color, window color and
- * grid color. Lighting is also adjusted by themes.
- *
- * \sa setBarColor()
- *
- * \preliminary
- */
-void Q3DBars::setTheme(QDataVis::Theme theme)
+Q3DTheme *Q3DBars::theme() const
{
- d_ptr->m_shared->setTheme(theme);
-}
-
-/*!
- * Set bar color using your own color. \a baseColor sets the base color of a bar. The \a uniform
- * -flag is used to define if color needs to be uniform throughout bar's length, or will the colors
- * be applied by height, starting with dark at the bottom. It is \c true by default.
- *
- * Calling this method overrides colors from theme.
- *
- * \sa setTheme()
- *
- * \preliminary
- */
-void Q3DBars::setBarColor(const QColor &baseColor, bool uniform)
-{
- d_ptr->m_shared->setObjectColor(baseColor, uniform);
-}
-
-/*!
- * \return bar color in use.
- */
-QColor Q3DBars::barColor() const
-{
- return d_ptr->m_shared->objectColor();
+ return dptrc()->m_shared->theme();
}
/*!
* \property Q3DBars::selectionMode
*
- * Sets bar selection \a mode to one of \c QDataVis::SelectionMode. It is preset to
- * \c QDataVis::SelectionModeItem by default.
+ * Sets bar selection \a mode to a combination of \c QDataVis::SelectionFlags. It is preset to
+ * \c QDataVis::SelectionItem by default.
*/
-void Q3DBars::setSelectionMode(QDataVis::SelectionMode mode)
+void Q3DBars::setSelectionMode(QDataVis::SelectionFlags mode)
{
- d_ptr->m_shared->setSelectionMode(mode);
+ dptr()->m_shared->setSelectionMode(mode);
}
-QDataVis::SelectionMode Q3DBars::selectionMode() const
+QDataVis::SelectionFlags Q3DBars::selectionMode() const
{
- return d_ptr->m_shared->selectionMode();
-}
-
-/*!
- * \property Q3DBars::meshFileName
- *
- * Override bar type with a mesh object located in \a objFileName.
- * \note Object needs to be in Wavefront obj format and include vertices, normals and UVs.
- * It also needs to be in triangles.
- *
- * \sa setBarType()
- */
-void Q3DBars::setMeshFileName(const QString &objFileName)
-{
- d_ptr->m_shared->setMeshFileName(objFileName);
-}
-
-QString Q3DBars::meshFileName() const
-{
- return d_ptr->m_shared->meshFileName();
-}
-
-/*!
- * \property Q3DBars::font
- *
- * Sets the \a font for labels. It is preset to \c Arial by default.
- */
-void Q3DBars::setFont(const QFont &font)
-{
- d_ptr->m_shared->setFont(font);
-}
-
-QFont Q3DBars::font() const
-{
- return d_ptr->m_shared->font();
+ return dptrc()->m_shared->selectionMode();
}
/*!
@@ -348,70 +311,7 @@ QFont Q3DBars::font() const
*/
Q3DScene *Q3DBars::scene() const
{
- return d_ptr->m_shared->scene();
-}
-
-/*!
- * \property Q3DBars::labelStyle
- *
- * Sets label \a style to one of \c QDataVis::LabelStyle. It is preset to
- * \c QDataVis::LabelStyleFromTheme by default.
- */
-void Q3DBars::setLabelStyle(QDataVis::LabelStyle style)
-{
- d_ptr->m_shared->setLabelStyle(style);
-}
-
-QDataVis::LabelStyle Q3DBars::labelStyle() const
-{
- return d_ptr->m_shared->labelStyle();
-}
-
-/*!
- * \property Q3DBars::gridVisible
- *
- * Sets grid visibility to \a visible. It is preset to \c true by default.
- */
-void Q3DBars::setGridVisible(bool visible)
-{
- d_ptr->m_shared->setGridEnabled(visible);
-}
-
-bool Q3DBars::isGridVisible() const
-{
- return d_ptr->m_shared->gridEnabled();
-}
-
-/*!
- * \property Q3DBars::backgroundVisible
- *
- * Sets background visibility to \a visible. It is preset to \c true by default.
- */
-void Q3DBars::setBackgroundVisible(bool visible)
-{
- d_ptr->m_shared->setBackgroundEnabled(visible);
-}
-
-bool Q3DBars::isBackgroundVisible() const
-{
- return d_ptr->m_shared->backgroundEnabled();
-}
-
-/*!
- * \property Q3DBars::selectedBarPos
- *
- * Selects a bar in a \a position. The position is the position in data window.
- * Only one bar can be selected at a time.
- * To clear selection, specify an illegal \a position, e.g. (-1, -1).
- */
-void Q3DBars::setSelectedBarPos(const QPoint &position)
-{
- d_ptr->m_shared->setSelectedBarPos(position);
-}
-
-QPoint Q3DBars::selectedBarPos() const
-{
- return d_ptr->m_shared->selectedBarPos();
+ return dptrc()->m_shared->scene();
}
/*!
@@ -426,12 +326,12 @@ QPoint Q3DBars::selectedBarPos() const
*/
void Q3DBars::setShadowQuality(QDataVis::ShadowQuality quality)
{
- d_ptr->m_shared->setShadowQuality(quality);
+ dptr()->m_shared->setShadowQuality(quality);
}
QDataVis::ShadowQuality Q3DBars::shadowQuality() const
{
- return d_ptr->m_shared->shadowQuality();
+ return dptrc()->m_shared->shadowQuality();
}
/*!
@@ -445,7 +345,7 @@ QDataVis::ShadowQuality Q3DBars::shadowQuality() const
*/
void Q3DBars::setRowAxis(Q3DCategoryAxis *axis)
{
- d_ptr->m_shared->setAxisX(axis);
+ dptr()->m_shared->setAxisZ(axis);
}
/*!
@@ -453,7 +353,7 @@ void Q3DBars::setRowAxis(Q3DCategoryAxis *axis)
*/
Q3DCategoryAxis *Q3DBars::rowAxis() const
{
- return static_cast<Q3DCategoryAxis *>(d_ptr->m_shared->axisX());
+ return static_cast<Q3DCategoryAxis *>(dptrc()->m_shared->axisZ());
}
/*!
@@ -467,7 +367,7 @@ Q3DCategoryAxis *Q3DBars::rowAxis() const
*/
void Q3DBars::setColumnAxis(Q3DCategoryAxis *axis)
{
- d_ptr->m_shared->setAxisZ(axis);
+ dptr()->m_shared->setAxisX(axis);
}
/*!
@@ -475,7 +375,7 @@ void Q3DBars::setColumnAxis(Q3DCategoryAxis *axis)
*/
Q3DCategoryAxis *Q3DBars::columnAxis() const
{
- return static_cast<Q3DCategoryAxis *>(d_ptr->m_shared->axisZ());
+ return static_cast<Q3DCategoryAxis *>(dptrc()->m_shared->axisX());
}
/*!
@@ -490,7 +390,7 @@ Q3DCategoryAxis *Q3DBars::columnAxis() const
*/
void Q3DBars::setValueAxis(Q3DValueAxis *axis)
{
- d_ptr->m_shared->setAxisY(axis);
+ dptr()->m_shared->setAxisY(axis);
}
/*!
@@ -498,7 +398,7 @@ void Q3DBars::setValueAxis(Q3DValueAxis *axis)
*/
Q3DValueAxis *Q3DBars::valueAxis() const
{
- return static_cast<Q3DValueAxis *>(d_ptr->m_shared->axisY());
+ return static_cast<Q3DValueAxis *>(dptrc()->m_shared->axisY());
}
/*!
@@ -510,7 +410,7 @@ Q3DValueAxis *Q3DBars::valueAxis() const
*/
void Q3DBars::addAxis(Q3DAbstractAxis *axis)
{
- d_ptr->m_shared->addAxis(axis);
+ dptr()->m_shared->addAxis(axis);
}
/*!
@@ -523,7 +423,7 @@ void Q3DBars::addAxis(Q3DAbstractAxis *axis)
*/
void Q3DBars::releaseAxis(Q3DAbstractAxis *axis)
{
- d_ptr->m_shared->releaseAxis(axis);
+ dptr()->m_shared->releaseAxis(axis);
}
/*!
@@ -533,77 +433,12 @@ void Q3DBars::releaseAxis(Q3DAbstractAxis *axis)
*/
QList<Q3DAbstractAxis *> Q3DBars::axes() const
{
- return d_ptr->m_shared->axes();
-}
-
-/*!
- * Sets the active data \a proxy. Implicitly calls addDataProxy() to transfer ownership of
- * the \a proxy to this graph.
- *
- * If the \a proxy is null, a temporary default proxy is created and activated.
- * This temporary proxy is destroyed if another \a proxy is set explicitly active via this method.
- *
- * \sa addDataProxy(), releaseDataProxy()
- */
-void Q3DBars::setActiveDataProxy(QBarDataProxy *proxy)
-{
- d_ptr->m_shared->setActiveDataProxy(proxy);
+ return dptrc()->m_shared->axes();
}
-/*!
- * \return active data proxy.
- */
-QBarDataProxy *Q3DBars::activeDataProxy() const
+Q3DBarsPrivate::Q3DBarsPrivate(Q3DBars *q)
+ : Q3DWindowPrivate(q)
{
- return static_cast<QBarDataProxy *>(d_ptr->m_shared->activeDataProxy());
-}
-
-/*!
- * Adds data \a proxy to the graph. The proxies added via addDataProxy are not yet taken to use,
- * addDataProxy is simply used to give the ownership of the data \a proxy to the graph.
- * The \a proxy must not be null or added to another graph.
- *
- * \sa releaseDataProxy(), setActiveDataProxy()
- */
-void Q3DBars::addDataProxy(QBarDataProxy *proxy)
-{
- d_ptr->m_shared->addDataProxy(proxy);
-}
-
-/*!
- * Releases the ownership of the data \a proxy back to the caller, if it is added to this graph.
- * If the released \a proxy is in use, a new empty default proxy is created and taken to use.
- *
- * If the default \a proxy is released and added back later, it behaves as any other proxy would.
- *
- * \sa addDataProxy(), setActiveDataProxy()
- */
-void Q3DBars::releaseDataProxy(QBarDataProxy *proxy)
-{
- d_ptr->m_shared->releaseDataProxy(proxy);
-}
-
-/*!
- * \return list of all added data proxies.
- *
- * \sa addDataProxy()
- */
-QList<QBarDataProxy *> Q3DBars::dataProxies() const
-{
- QList<QBarDataProxy *> retList;
- QList<QAbstractDataProxy *> abstractList = d_ptr->m_shared->dataProxies();
- foreach (QAbstractDataProxy *proxy, abstractList)
- retList.append(static_cast<QBarDataProxy *>(proxy));
-
- return retList;
-}
-
-Q3DBarsPrivate::Q3DBarsPrivate(Q3DBars *q, QRect rect)
- : q_ptr(q),
- m_shared(new Bars3DController(rect))
-{
- QObject::connect(m_shared, &Abstract3DController::shadowQualityChanged, this,
- &Q3DBarsPrivate::handleShadowQualityUpdate);
}
Q3DBarsPrivate::~Q3DBarsPrivate()
@@ -613,7 +448,12 @@ Q3DBarsPrivate::~Q3DBarsPrivate()
void Q3DBarsPrivate::handleShadowQualityUpdate(QDataVis::ShadowQuality quality)
{
- emit q_ptr->shadowQualityChanged(quality);
+ emit qptr()->shadowQualityChanged(quality);
+}
+
+Q3DBars *Q3DBarsPrivate::qptr()
+{
+ return static_cast<Q3DBars *>(q_ptr);
}
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/q3dbars.h b/src/datavisualization/engine/q3dbars.h
index d0ddf3fb..add3b11b 100644
--- a/src/datavisualization/engine/q3dbars.h
+++ b/src/datavisualization/engine/q3dbars.h
@@ -21,7 +21,9 @@
#include <QtDataVisualization/qdatavisualizationenums.h>
#include <QtDataVisualization/q3dwindow.h>
+#include <QtDataVisualization/q3dtheme.h>
#include <QFont>
+#include <QLinearGradient>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
@@ -29,40 +31,33 @@ class Q3DBarsPrivate;
class Q3DAbstractAxis;
class Q3DCategoryAxis;
class Q3DValueAxis;
-class QBarDataProxy;
class Q3DScene;
+class QBar3DSeries;
class QT_DATAVISUALIZATION_EXPORT Q3DBars : public Q3DWindow
{
Q_OBJECT
- Q_PROPERTY(QtDataVisualization::QDataVis::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode)
- Q_PROPERTY(QtDataVisualization::QDataVis::LabelStyle labelStyle READ labelStyle WRITE setLabelStyle)
+ Q_PROPERTY(QtDataVisualization::QDataVis::SelectionFlags selectionMode READ selectionMode WRITE setSelectionMode NOTIFY selectionModeChanged)
Q_PROPERTY(QtDataVisualization::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality NOTIFY shadowQualityChanged)
- Q_PROPERTY(qreal barThickness READ barThickness WRITE setBarThickness)
- Q_PROPERTY(QSizeF barSpacing READ barSpacing WRITE setBarSpacing)
- Q_PROPERTY(bool barSpacingRelative READ isBarSpacingRelative WRITE setBarSpacingRelative)
- Q_PROPERTY(QString meshFileName READ meshFileName WRITE setMeshFileName)
- Q_PROPERTY(QFont font READ font WRITE setFont)
- Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible)
- Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible)
- Q_PROPERTY(QPoint selectedBarPos READ selectedBarPos WRITE setSelectedBarPos NOTIFY selectedBarPosChanged)
+ Q_PROPERTY(float barThickness READ barThickness WRITE setBarThickness NOTIFY barThicknessChanged)
+ Q_PROPERTY(QSizeF barSpacing READ barSpacing WRITE setBarSpacing NOTIFY barSpacingChanged)
+ Q_PROPERTY(bool barSpacingRelative READ isBarSpacingRelative WRITE setBarSpacingRelative NOTIFY barSpacingRelativeChanged)
+ Q_PROPERTY(Q3DTheme* theme READ theme WRITE setTheme NOTIFY themeChanged)
Q_PROPERTY(Q3DScene* scene READ scene)
- Q_ENUMS(QtDataVisualization::QDataVis::SelectionMode)
- Q_ENUMS(QtDataVisualization::QDataVis::ShadowQuality)
- Q_ENUMS(QtDataVisualization::QDataVis::LabelStyle)
- Q_ENUMS(QtDataVisualization::QDataVis::CameraPreset)
-
public:
- explicit Q3DBars();
- ~Q3DBars();
+ explicit Q3DBars(QWindow *parent = 0);
+ virtual ~Q3DBars();
- void setBarType(QDataVis::MeshStyle style, bool smooth = false);
+ void addSeries(QBar3DSeries *series);
+ void removeSeries(QBar3DSeries *series);
+ QList<QBar3DSeries *> seriesList();
- void setTheme(QDataVis::Theme theme);
+ void setTheme(Q3DTheme *theme);
+ Q3DTheme *theme() const;
- void setBarThickness(qreal thicknessRatio);
- qreal barThickness();
+ void setBarThickness(float thicknessRatio);
+ float barThickness();
void setBarSpacing(QSizeF spacing);
QSizeF barSpacing();
@@ -70,35 +65,11 @@ public:
void setBarSpacingRelative(bool relative);
bool isBarSpacingRelative();
- void setBarColor(const QColor &baseColor, bool uniform = true);
- QColor barColor() const;
-
- void setMeshFileName(const QString &objFileName);
- QString meshFileName() const;
-
- void setSelectionMode(QDataVis::SelectionMode mode);
- QDataVis::SelectionMode selectionMode() const;
-
- void setFont(const QFont &font);
- QFont font() const;
+ void setSelectionMode(QDataVis::SelectionFlags mode);
+ QDataVis::SelectionFlags selectionMode() const;
Q3DScene *scene() const;
- void setLabelStyle(QDataVis::LabelStyle style);
- QDataVis::LabelStyle labelStyle() const;
-
- void setGridVisible(bool visible);
- bool isGridVisible() const;
-
- void setWidth(const int width);
- void setHeight(const int height);
-
- void setBackgroundVisible(bool visible);
- bool isBackgroundVisible() const;
-
- void setSelectedBarPos(const QPoint &position);
- QPoint selectedBarPos() const;
-
void setShadowQuality(QDataVis::ShadowQuality quality);
QDataVis::ShadowQuality shadowQuality() const;
@@ -112,15 +83,13 @@ public:
void releaseAxis(Q3DAbstractAxis *axis);
QList<Q3DAbstractAxis *> axes() const;
- void setActiveDataProxy(QBarDataProxy *proxy);
- QBarDataProxy *activeDataProxy() const;
- void addDataProxy(QBarDataProxy *proxy);
- void releaseDataProxy(QBarDataProxy *proxy);
- QList<QBarDataProxy *> dataProxies() const;
-
signals:
+ void selectionModeChanged(QDataVis::SelectionFlags mode);
void shadowQualityChanged(QDataVis::ShadowQuality quality);
- void selectedBarPosChanged(QPoint position);
+ void barThicknessChanged(float thicknessRatio);
+ void barSpacingChanged(QSizeF spacing);
+ void barSpacingRelativeChanged(bool relative);
+ void themeChanged(Q3DTheme *theme);
protected:
@@ -130,10 +99,10 @@ protected:
void mouseReleaseEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void wheelEvent(QWheelEvent *event);
- void resizeEvent(QResizeEvent *event);
private:
- QScopedPointer<Q3DBarsPrivate> d_ptr;
+ Q3DBarsPrivate *dptr();
+ const Q3DBarsPrivate *dptrc() const;
Q_DISABLE_COPY(Q3DBars)
};
diff --git a/src/datavisualization/engine/q3dbars_p.h b/src/datavisualization/engine/q3dbars_p.h
index 653db606..9a059d8d 100644
--- a/src/datavisualization/engine/q3dbars_p.h
+++ b/src/datavisualization/engine/q3dbars_p.h
@@ -26,26 +26,29 @@
//
// We mean it.
-#ifndef Q3DBARS_p_H
-#define Q3DBARS_p_H
+#ifndef Q3DBARS_P_H
+#define Q3DBARS_P_H
#include "bars3dcontroller_p.h"
#include "qdatavisualizationenums.h"
+#include "q3dwindow_p.h"
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class Q3DBars;
-class Q3DBarsPrivate : public QObject
+class Q3DBarsPrivate : public Q3DWindowPrivate
{
+ Q_OBJECT
public:
- Q3DBarsPrivate(Q3DBars *q, QRect rect);
+ Q3DBarsPrivate(Q3DBars *q);
~Q3DBarsPrivate();
// Used to detect when shadow quality changes autonomously due to e.g. resizing.
void handleShadowQualityUpdate(QDataVis::ShadowQuality quality);
- Q3DBars *q_ptr;
+ Q3DBars *qptr();
+
Bars3DController *m_shared;
};
diff --git a/src/datavisualization/engine/q3dcamera.cpp b/src/datavisualization/engine/q3dcamera.cpp
index fe452739..6378051c 100644
--- a/src/datavisualization/engine/q3dcamera.cpp
+++ b/src/datavisualization/engine/q3dcamera.cpp
@@ -29,19 +29,192 @@
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
/*!
- \class Q3DCamera
- \inmodule QtDataVisualization
- \brief Representation of a camera in 3D space.
- \since Qt Data Visualization 1.0
+ * \class Q3DCamera
+ * \inmodule QtDataVisualization
+ * \brief Representation of a camera in 3D space.
+ * \since Qt Data Visualization 1.0
+ *
+ * Q3DCamera represents a basic orbit around centerpoint 3D camera that is used when rendering the
+ * data visualization. The class offers simple methods for setting the orbit point in rotations,
+ * but allows also setting the 4x4 view matrix directly in case a more customized camera behavior is
+ * needed.
+ */
+
+/*!
+ * \enum Q3DCamera::CameraPreset
+ *
+ * Predefined positions for camera.
+ *
+ * \value CameraPresetNone
+ * Used to indicate a preset has not been set, or the scene has been rotated freely.
+ * \value CameraPresetFrontLow
+ * \value CameraPresetFront
+ * \value CameraPresetFrontHigh
+ * \value CameraPresetLeftLow
+ * \value CameraPresetLeft
+ * \value CameraPresetLeftHigh
+ * \value CameraPresetRightLow
+ * \value CameraPresetRight
+ * \value CameraPresetRightHigh
+ * \value CameraPresetBehindLow
+ * \value CameraPresetBehind
+ * \value CameraPresetBehindHigh
+ * \value CameraPresetIsometricLeft
+ * \value CameraPresetIsometricLeftHigh
+ * \value CameraPresetIsometricRight
+ * \value CameraPresetIsometricRightHigh
+ * \value CameraPresetDirectlyAbove
+ * \value CameraPresetDirectlyAboveCW45
+ * \value CameraPresetDirectlyAboveCCW45
+ * \value CameraPresetFrontBelow
+ * In Q3DBars from CameraPresetFrontBelow onward these only work for graphs including negative
+ * values. They act as Preset...Low for positive-only values.
+ * \value CameraPresetLeftBelow
+ * \value CameraPresetRightBelow
+ * \value CameraPresetBehindBelow
+ * \value CameraPresetDirectlyBelow
+ * Acts as CameraPresetFrontLow for positive-only bars.
+ */
+
+/*!
+ * \qmltype Camera3D
+ * \inqmlmodule QtDataVisualization
+ * \since QtDataVisualization 1.0
+ * \ingroup datavisualization_qml
+ * \instantiates Q3DCamera
+ * \brief Representation of a camera in 3D space.
+ *
+ * Camera3D represents a basic orbit around centerpoint 3D camera that is used when rendering the
+ * data visualization. The class offers simple methods for setting the orbit point in rotations,
+ * but allows also setting the 4x4 view matrix directly in case a more customized camera behavior is
+ * needed.
+ */
+
+/*!
+ * \qmlproperty float Camera3D::xRotation
+ *
+ * This property contains the X-rotation angle of the camera around the target point in degrees
+ * starting from the current base position set by the setBaseOrientation method.
+ */
- Q3DCamera represents a basic orbit around centerpoint 3D camera that is used when rendering the data visualization.
- The class offers simple methods for setting the orbit point in rotations, but allows also setting the 4x4 viewmatrix
- directly in case a more customized camera behavior is needed.
-*/
+/*!
+ * \qmlproperty float Camera3D::yRotation
+ *
+ * This property contains the Y-rotation angle of the camera around the target point in degrees
+ * starting from the current base position set by the setBaseOrientation method.
+ */
/*!
- * Constructs a new 3D camera with position set to origo, up direction facing towards the Y-axis and looking at origo by default. An
- * optional \a parent parameter can be given and is then passed to QObject constructor.
+ * \qmlproperty float Camera3D::minXRotation
+ *
+ * This property contains the current minimum X-rotation for the camera.
+ * The full circle range is \c{[-180, 180]} and the minimum value is limited to \c -180.
+ * Also the value can't be higher than the maximum, and is adjusted if necessary.
+ *
+ * \sa wrapXRotation, maxXRotation
+ */
+
+/*!
+ * \qmlproperty float Camera3D::minYRotation
+ *
+ * This property contains the current minimum Y-rotation for the camera.
+ * The full Y angle range is \c{[-90, 90]} and the minimum value is limited to \c -90.
+ * Also the value can't be higher than the maximum, and is adjusted if necessary.
+ *
+ * \sa wrapYRotation, maxYRotation
+ */
+
+/*!
+ * \qmlproperty float Camera3D::maxXRotation
+ *
+ * This property contains the current maximum X-rotation for the camera.
+ * The full circle range is \c{[-180, 180]} and the maximum value is limited to \c 180.
+ * Also the value can't be lower than the minimum, and is adjusted if necessary.
+ *
+ * \sa wrapXRotation, minXRotation
+ */
+
+/*!
+ * \qmlproperty float Camera3D::maxYRotation
+ *
+ * This property contains the current maximum Y-rotation for the camera.
+ * The full Y angle range is \c{[-90, 90]} and the maximum value is limited to \c 90.
+ * Also the value can't be lower than the minimum, and is adjusted if necessary.
+ *
+ * \sa wrapYRotation, minYRotation
+ */
+
+/*!
+ * \qmlmethod void Camera3D::setBaseOrientation(vector3d basePosition, vector3d target, vector3d baseUp)
+ *
+ * Sets the base values for the camera that are used when calculating the camera position using the
+ * rotation values. The base position of the camera is defined by \a basePosition, expectation is
+ * that the x and y values are 0. Look at target point is defined by \a target and the camera
+ * rotates around it. Up direction for the camera is defined by \a baseUp, normally this is a
+ * vector with only y value set to 1.
+ */
+
+/*!
+ * \qmlproperty matrix4x4 Camera3D::viewMatrix
+ *
+ * This property contains the view matrix used in the 3D calculations. When the default orbiting
+ * camera behavior is sufficient, there is no need to touch this property. If the default
+ * behavior is insufficient, the view matrix can be set directly.
+ * \note When setting the view matrix directly remember to set viewMatrixAutoUpdateEnabled
+ * property to \c false.
+ */
+
+/*!
+ * \qmlproperty bool Camera3D::viewMatrixAutoUpdateEnabled
+ *
+ * This property determines if view matrix is automatically updated each render cycle using the
+ * current base orientation and rotations. If set to \c false, no automatic recalculation is done and
+ * the view matrix can be set using the viewMatrix property.
+ */
+
+/*!
+ * \qmlproperty Camera3D.CameraPreset Camera3D::cameraPreset
+ *
+ * This property contains the currently active camera preset, which is one of
+ * \l{Q3DCamera::CameraPreset}{Camera3D.CameraPreset}. If no preset is active the value
+ * is \l{Q3DCamera::CameraPresetNone}{Camera3D.CameraPresetNone}.
+ * \note The base camera orientation set by setBaseOrientation will affect the presets as all
+ * calculations are based on those values.
+ */
+
+/*!
+ * \qmlproperty float Camera3D::zoomLevel
+ *
+ * This property contains the the camera zoom level in percentage. 100.0 means there is no zoom
+ * in or out set in the camera.
+ */
+
+/*!
+ * \qmlproperty bool Camera3D::wrapXRotation
+ *
+ * This property determines the behavior of the minimum and maximum limits in the X-rotation.
+ * By default the X-rotation wraps from minimum value to maximum and from maximum to minimum.
+ *
+ * If set to \c true the X-rotation of the camera is wrapped from minimum to maximum and from maximum
+ * to minimum. If set to \c false the X-rotation of the camera is limited to the sector determined by
+ * minimum and maximum values.
+ */
+
+/*!
+ * \qmlproperty bool Camera3D::wrapYRotation
+ *
+ * This property determines the behavior of the minimum and maximum limits in the Y-rotation.
+ * By default the Y-rotation is limited between the minimum and maximum values without any wrapping.
+ *
+ * If \c true the Y-rotation of the camera is wrapped from minimum to maximum and from maximum
+ * to minimum. If \c false the Y-rotation of the camera is limited to the sector determined by minimum
+ * and maximum values.
+ */
+
+/*!
+ * Constructs a new 3D camera with position set to origin, up direction facing towards the Y-axis
+ * and looking at origin by default. An optional \a parent parameter can be given and is then passed
+ * to QObject constructor.
*/
Q3DCamera::Q3DCamera(QObject *parent) :
Q3DObject(parent),
@@ -60,59 +233,61 @@ Q3DCamera::~Q3DCamera()
* Copies the 3D camera's properties from the given source camera.
* Values are copied from the \a source to this object.
*/
-void Q3DCamera::copyValuesFrom(const Q3DCamera &source)
+void Q3DCamera::copyValuesFrom(const Q3DObject &source)
{
Q3DObject::copyValuesFrom(source);
- d_ptr->m_target.setX(source.d_ptr->m_target.x());
- d_ptr->m_target.setY(source.d_ptr->m_target.y());
- d_ptr->m_target.setZ(source.d_ptr->m_target.z());
+ const Q3DCamera &sourceCamera = static_cast<const Q3DCamera &>(source);
+
+ d_ptr->m_target.setX(sourceCamera.d_ptr->m_target.x());
+ d_ptr->m_target.setY(sourceCamera.d_ptr->m_target.y());
+ d_ptr->m_target.setZ(sourceCamera.d_ptr->m_target.z());
- d_ptr->m_up.setX(source.d_ptr->m_up.x());
- d_ptr->m_up.setY(source.d_ptr->m_up.y());
- d_ptr->m_up.setZ(source.d_ptr->m_up.z());
+ d_ptr->m_up.setX(sourceCamera.d_ptr->m_up.x());
+ d_ptr->m_up.setY(sourceCamera.d_ptr->m_up.y());
+ d_ptr->m_up.setZ(sourceCamera.d_ptr->m_up.z());
float *values = new float[16];
- source.d_ptr->m_viewMatrix.copyDataTo(values);
+ sourceCamera.d_ptr->m_viewMatrix.copyDataTo(values);
d_ptr->m_viewMatrix = QMatrix4x4(values);
delete[] values;
- d_ptr->m_xRotation = source.d_ptr->m_xRotation;
- d_ptr->m_yRotation = source.d_ptr->m_yRotation;
+ d_ptr->m_xRotation = sourceCamera.d_ptr->m_xRotation;
+ d_ptr->m_yRotation = sourceCamera.d_ptr->m_yRotation;
- d_ptr->m_minXRotation = source.d_ptr->m_minXRotation;
- d_ptr->m_minYRotation = source.d_ptr->m_minYRotation;
- d_ptr->m_maxXRotation = source.d_ptr->m_maxXRotation;
- d_ptr->m_maxYRotation = source.d_ptr->m_maxYRotation;
+ d_ptr->m_minXRotation = sourceCamera.d_ptr->m_minXRotation;
+ d_ptr->m_minYRotation = sourceCamera.d_ptr->m_minYRotation;
+ d_ptr->m_maxXRotation = sourceCamera.d_ptr->m_maxXRotation;
+ d_ptr->m_maxYRotation = sourceCamera.d_ptr->m_maxYRotation;
- d_ptr->m_wrapXRotation = source.d_ptr->m_wrapXRotation;
- d_ptr->m_wrapYRotation = source.d_ptr->m_wrapYRotation;
+ d_ptr->m_wrapXRotation = sourceCamera.d_ptr->m_wrapXRotation;
+ d_ptr->m_wrapYRotation = sourceCamera.d_ptr->m_wrapYRotation;
- d_ptr->m_zoomLevel = source.d_ptr->m_zoomLevel;
- d_ptr->m_activePreset = source.d_ptr->m_activePreset;
+ d_ptr->m_zoomLevel = sourceCamera.d_ptr->m_zoomLevel;
+ d_ptr->m_activePreset = sourceCamera.d_ptr->m_activePreset;
}
/*!
* \property Q3DCamera::xRotation
*
- * This property contains the X-rotation angle of the camera around the target point in degrees starting from
- * the current base position set by the setBaseOrientation() methods.
+ * This property contains the X-rotation angle of the camera around the target point in degrees
+ * starting from the current base position set by the setBaseOrientation() method.
*/
-qreal Q3DCamera::xRotation() const {
+float Q3DCamera::xRotation() const {
return d_ptr->m_xRotation;
}
-void Q3DCamera::setXRotation(qreal rotation)
+void Q3DCamera::setXRotation(float rotation)
{
if (d_ptr->m_wrapXRotation)
rotation = Utils::wrapValue(rotation, d_ptr->m_minXRotation, d_ptr->m_maxXRotation);
else
- rotation = qBound(qreal(d_ptr->m_minXRotation), qreal(rotation), qreal(d_ptr->m_maxXRotation));
+ rotation = qBound(float(d_ptr->m_minXRotation), float(rotation), float(d_ptr->m_maxXRotation));
if (d_ptr->m_xRotation != rotation) {
d_ptr->setXRotation(rotation);
- if (d_ptr->m_activePreset != QDataVis::CameraPresetNone) {
- d_ptr->m_activePreset = QDataVis::CameraPresetNone;
+ if (d_ptr->m_activePreset != CameraPresetNone) {
+ d_ptr->m_activePreset = CameraPresetNone;
setDirty(true);
}
@@ -123,24 +298,24 @@ void Q3DCamera::setXRotation(qreal rotation)
/*!
* \property Q3DCamera::yRotation
*
- * This property contains the Y-rotation angle of the camera around the target point in degrees starting from
- * the current base position set by the setBaseOrientation() methods.
+ * This property contains the Y-rotation angle of the camera around the target point in degrees
+ * starting from the current base position set by the setBaseOrientation() method.
*/
-qreal Q3DCamera::yRotation() const {
+float Q3DCamera::yRotation() const {
return d_ptr->m_yRotation;
}
-void Q3DCamera::setYRotation(qreal rotation)
+void Q3DCamera::setYRotation(float rotation)
{
if (d_ptr->m_wrapYRotation)
rotation = Utils::wrapValue(rotation, d_ptr->m_minYRotation, d_ptr->m_maxYRotation);
else
- rotation = qBound(qreal(d_ptr->m_minYRotation), qreal(rotation), qreal(d_ptr->m_maxYRotation));
+ rotation = qBound(float(d_ptr->m_minYRotation), float(rotation), float(d_ptr->m_maxYRotation));
if (d_ptr->m_yRotation != rotation) {
d_ptr->setYRotation(rotation);
- if (d_ptr->m_activePreset != QDataVis::CameraPresetNone) {
- d_ptr->m_activePreset = QDataVis::CameraPresetNone;
+ if (d_ptr->m_activePreset != CameraPresetNone) {
+ d_ptr->m_activePreset = CameraPresetNone;
setDirty(true);
}
@@ -152,22 +327,19 @@ void Q3DCamera::setYRotation(qreal rotation)
* \property Q3DCamera::minXRotation
*
* This property contains the current minimum X-rotation for the camera.
- * The full circle range is [-180,180] and the minimum value is limited to -180.
+ * The full circle range is \c{[-180, 180]} and the minimum value is limited to \c -180.
* Also the value can't be higher than the maximum, and is adjusted if necessary.
*
* \sa wrapXRotation, maxXRotation
*/
-qreal Q3DCamera::minXRotation() const
+float Q3DCamera::minXRotation() const
{
return d_ptr->m_minXRotation;
}
-/*!
- * \internal
- */
-void Q3DCamera::setMinXRotation(qreal minRotation)
+void Q3DCamera::setMinXRotation(float minRotation)
{
- minRotation = qBound(qreal(-180.0), minRotation, qreal(180.0));
+ minRotation = qBound(-180.0f, minRotation, 180.0f);
if (minRotation > d_ptr->m_maxXRotation)
minRotation = d_ptr->m_maxXRotation;
@@ -184,22 +356,19 @@ void Q3DCamera::setMinXRotation(qreal minRotation)
* \property Q3DCamera::minYRotation
*
* This property contains the current minimum Y-rotation for the camera.
- * The full Y angle range is [-90,90] and the minimum value is limited to -90.
+ * The full Y angle range is \c{[-90, 90]} and the minimum value is limited to \c -90.
* Also the value can't be higher than the maximum, and is adjusted if necessary.
*
* \sa wrapYRotation, maxYRotation
*/
-qreal Q3DCamera::minYRotation() const
+float Q3DCamera::minYRotation() const
{
return d_ptr->m_minYRotation;
}
-/*!
- * \internal
- */
-void Q3DCamera::setMinYRotation(qreal minRotation)
+void Q3DCamera::setMinYRotation(float minRotation)
{
- minRotation = qBound(qreal(-90.0), minRotation, qreal(90.0));
+ minRotation = qBound(-90.0f, minRotation, 90.0f);
if (minRotation > d_ptr->m_maxYRotation)
minRotation = d_ptr->m_maxYRotation;
@@ -216,22 +385,19 @@ void Q3DCamera::setMinYRotation(qreal minRotation)
* \property Q3DCamera::maxXRotation
*
* This property contains the current maximum X-rotation for the camera.
- * The full circle range is [-180,180] and the maximum value is limited to 180.
+ * The full circle range is \c{[-180, 180]} and the maximum value is limited to \c 180.
* Also the value can't be lower than the minimum, and is adjusted if necessary.
*
* \sa wrapXRotation, minXRotation
*/
-qreal Q3DCamera::maxXRotation() const
+float Q3DCamera::maxXRotation() const
{
return d_ptr->m_maxXRotation;
}
-/*!
- * \internal
- */
-void Q3DCamera::setMaxXRotation(qreal maxRotation)
+void Q3DCamera::setMaxXRotation(float maxRotation)
{
- maxRotation = qBound(qreal(-180.0), maxRotation, qreal(180.0));
+ maxRotation = qBound(-180.0f, maxRotation, 180.0f);
if (maxRotation < d_ptr->m_minXRotation)
maxRotation = d_ptr->m_minXRotation;
@@ -249,22 +415,19 @@ void Q3DCamera::setMaxXRotation(qreal maxRotation)
* \property Q3DCamera::maxYRotation
*
* This property contains the current maximum Y-rotation for the camera.
- * The full Y angle range is [-90,90] and the maximum value is limited to 90.
+ * The full Y angle range is \c{[-90, 90]} and the maximum value is limited to \c 90.
* Also the value can't be lower than the minimum, and is adjusted if necessary.
*
* \sa wrapYRotation, minYRotation
*/
-qreal Q3DCamera::maxYRotation() const
+float Q3DCamera::maxYRotation() const
{
return d_ptr->m_maxYRotation;
}
-/*!
- * \internal
- */
-void Q3DCamera::setMaxYRotation(qreal maxRotation)
+void Q3DCamera::setMaxYRotation(float maxRotation)
{
- maxRotation = qBound(qreal(-90.0), maxRotation, qreal(90.0));
+ maxRotation = qBound(-90.0f, maxRotation, 90.0f);
if (maxRotation < d_ptr->m_minYRotation)
maxRotation = d_ptr->m_minYRotation;
@@ -279,10 +442,11 @@ void Q3DCamera::setMaxYRotation(qreal maxRotation)
}
/*!
- * Sets the base values for the camera that are used when calculating the camera position using the rotation values.
- * The base position of the camera is defined by \a basePosition, expectation is that the x and y values are 0.
- * Look at target point is defined by \a target and the camera rotates around it. Up direction for the camera is
- * defined by \a baseUp, normally this is a vector with only y values set to 1.
+ * Sets the base values for the camera that are used when calculating the camera position using the
+ * rotation values. The base position of the camera is defined by \a basePosition, expectation is
+ * that the x and y values are 0. Look at target point is defined by \a target and the camera
+ * rotates around it. Up direction for the camera is defined by \a baseUp, normally this is a
+ * vector with only y value set to 1.
*/
void Q3DCamera::setBaseOrientation(const QVector3D &basePosition,
const QVector3D &target,
@@ -301,9 +465,11 @@ void Q3DCamera::setBaseOrientation(const QVector3D &basePosition,
/*!
* \property Q3DCamera::viewMatrix
*
- * This property contains the view matrix used in the 3D calculations. When the default orbiting camera behavior is sufficient,
- * there is no need to touch this property. But if the default behavior is insufficient, the view matrix can be set directly.
- * When setting the view matrix directly remember to set Q3DCamera::viewMatrixAutoUpdateEnabled to false.
+ * This property contains the view matrix used in the 3D calculations. When the default orbiting
+ * camera behavior is sufficient, there is no need to touch this property. If the default
+ * behavior is insufficient, the view matrix can be set directly.
+ * \note When setting the view matrix directly remember to set viewMatrixAutoUpdateEnabled to
+ * \c false.
*/
QMatrix4x4 Q3DCamera::viewMatrix() const
{
@@ -322,11 +488,11 @@ void Q3DCamera::setViewMatrix(const QMatrix4x4 &viewMatrix)
/*!
* \property Q3DCamera::viewMatrixAutoUpdateEnabled
*
- * This property determines if view matrix is automatically updated each render cycle using the current base orientation and
- * rotations. If set to false, no automatic recalculation is done and the view matrix can be set using the
- * Q3DMatrix::viewMatrix property.
+ * This property determines if view matrix is automatically updated each render cycle using the
+ * current base orientation and rotations. If set to \c false, no automatic recalculation is done
+ * and the view matrix can be set using the viewMatrix property.
*/
-bool Q3DCamera::isViewMatrixAutoUpdateEnabled()
+bool Q3DCamera::isViewMatrixAutoUpdateEnabled() const
{
return d_ptr->m_isViewMatrixUpdateActive;
}
@@ -340,141 +506,141 @@ void Q3DCamera::setViewMatrixAutoUpdateEnabled(bool isEnabled)
/*!
* \property Q3DCamera::cameraPreset
*
- * This property contains the currently active camera preset,
- * if no preset is active the value is QDataVis::CameraPresetNone.
+ * This property contains the currently active camera preset, if no preset is active the value
+ * is CameraPresetNone.
* \note The base camera orientation set by setBaseOrientation() will affect
* the presets as all calculations are based on those values.
*/
-QDataVis::CameraPreset Q3DCamera::cameraPreset()
+Q3DCamera::CameraPreset Q3DCamera::cameraPreset() const
{
return d_ptr->m_activePreset;
}
-void Q3DCamera::setCameraPreset(QDataVis::CameraPreset preset)
+void Q3DCamera::setCameraPreset(CameraPreset preset)
{
switch (preset) {
- case QDataVis::CameraPresetFrontLow: {
- setXRotation(0.0);
- setYRotation(0.0);
+ case CameraPresetFrontLow: {
+ setXRotation(0.0f);
+ setYRotation(0.0f);
break;
}
- case QDataVis::CameraPresetFront: {
- setXRotation(0.0);
- setYRotation(22.5);
+ case CameraPresetFront: {
+ setXRotation(0.0f);
+ setYRotation(22.5f);
break;
}
- case QDataVis::CameraPresetFrontHigh: {
- setXRotation(0.0);
- setYRotation(45.0);
+ case CameraPresetFrontHigh: {
+ setXRotation(0.0f);
+ setYRotation(45.0f);
break;
}
- case QDataVis::CameraPresetLeftLow: {
- setXRotation(90.0);
- setYRotation(0.0);
+ case CameraPresetLeftLow: {
+ setXRotation(90.0f);
+ setYRotation(0.0f);
break;
}
- case QDataVis::CameraPresetLeft: {
- setXRotation(90.0);
- setYRotation(22.5);
+ case CameraPresetLeft: {
+ setXRotation(90.0f);
+ setYRotation(22.5f);
break;
}
- case QDataVis::CameraPresetLeftHigh: {
- setXRotation(90.0);
- setYRotation(45.0);
+ case CameraPresetLeftHigh: {
+ setXRotation(90.0f);
+ setYRotation(45.0f);
break;
}
- case QDataVis::CameraPresetRightLow: {
- setXRotation(-90.0);
- setYRotation(0.0);
+ case CameraPresetRightLow: {
+ setXRotation(-90.0f);
+ setYRotation(0.0f);
break;
}
- case QDataVis::CameraPresetRight: {
- setXRotation(-90.0);
- setYRotation(22.5);
+ case CameraPresetRight: {
+ setXRotation(-90.0f);
+ setYRotation(22.5f);
break;
}
- case QDataVis::CameraPresetRightHigh: {
- setXRotation(-90.0);
- setYRotation(45.0);
+ case CameraPresetRightHigh: {
+ setXRotation(-90.0f);
+ setYRotation(45.0f);
break;
}
- case QDataVis::CameraPresetBehindLow: {
- setXRotation(180.0);
- setYRotation(0.0);
+ case CameraPresetBehindLow: {
+ setXRotation(180.0f);
+ setYRotation(0.0f);
break;
}
- case QDataVis::CameraPresetBehind: {
- setXRotation(180.0);
- setYRotation(22.5);
+ case CameraPresetBehind: {
+ setXRotation(180.0f);
+ setYRotation(22.5f);
break;
}
- case QDataVis::CameraPresetBehindHigh: {
- setXRotation(180.0);
- setYRotation(45.0);
+ case CameraPresetBehindHigh: {
+ setXRotation(180.0f);
+ setYRotation(45.0f);
break;
}
- case QDataVis::CameraPresetIsometricLeft: {
- setXRotation(45.0);
- setYRotation(22.5);
+ case CameraPresetIsometricLeft: {
+ setXRotation(45.0f);
+ setYRotation(22.5f);
break;
}
- case QDataVis::CameraPresetIsometricLeftHigh: {
- setXRotation(45.0);
- setYRotation(45.0);
+ case CameraPresetIsometricLeftHigh: {
+ setXRotation(45.0f);
+ setYRotation(45.0f);
break;
}
- case QDataVis::CameraPresetIsometricRight: {
- setXRotation(-45.0);
- setYRotation(22.5);
+ case CameraPresetIsometricRight: {
+ setXRotation(-45.0f);
+ setYRotation(22.5f);
break;
}
- case QDataVis::CameraPresetIsometricRightHigh: {
- setXRotation(-45.0);
- setYRotation(45.0);
+ case CameraPresetIsometricRightHigh: {
+ setXRotation(-45.0f);
+ setYRotation(45.0f);
break;
}
- case QDataVis::CameraPresetDirectlyAbove: {
- setXRotation(0.0);
- setYRotation(90.0);
+ case CameraPresetDirectlyAbove: {
+ setXRotation(0.0f);
+ setYRotation(90.0f);
break;
}
- case QDataVis::CameraPresetDirectlyAboveCW45: {
- setXRotation(-45.0);
- setYRotation(90.0);
+ case CameraPresetDirectlyAboveCW45: {
+ setXRotation(-45.0f);
+ setYRotation(90.0f);
break;
}
- case QDataVis::CameraPresetDirectlyAboveCCW45: {
- setXRotation(45.0);
- setYRotation(90.0);
+ case CameraPresetDirectlyAboveCCW45: {
+ setXRotation(45.0f);
+ setYRotation(90.0f);
break;
}
- case QDataVis::CameraPresetFrontBelow: {
- setXRotation(0.0);
- setYRotation(-45.0);
+ case CameraPresetFrontBelow: {
+ setXRotation(0.0f);
+ setYRotation(-45.0f);
break;
}
- case QDataVis::CameraPresetLeftBelow: {
- setXRotation(90.0);
- setYRotation(-45.0);
+ case CameraPresetLeftBelow: {
+ setXRotation(90.0f);
+ setYRotation(-45.0f);
break;
}
- case QDataVis::CameraPresetRightBelow: {
- setXRotation(-90.0);
- setYRotation(-45.0);
+ case CameraPresetRightBelow: {
+ setXRotation(-90.0f);
+ setYRotation(-45.0f);
break;
}
- case QDataVis::CameraPresetBehindBelow: {
- setXRotation(180.0);
- setYRotation(-45.0);
+ case CameraPresetBehindBelow: {
+ setXRotation(180.0f);
+ setYRotation(-45.0f);
break;
}
- case QDataVis::CameraPresetDirectlyBelow: {
- setXRotation(0.0);
- setYRotation(-90.0);
+ case CameraPresetDirectlyBelow: {
+ setXRotation(0.0f);
+ setYRotation(-90.0f);
break;
}
default:
- preset = QDataVis::CameraPresetNone;
+ preset = CameraPresetNone;
break;
}
@@ -488,10 +654,10 @@ void Q3DCamera::setCameraPreset(QDataVis::CameraPreset preset)
/*!
* \property Q3DCamera::zoomLevel
*
- * This property contains the the camera zoom level in percentages.
- * 100% means there is no zoom in or out set in the camera.
+ * This property contains the the camera zoom level in percentage. \c 100.0f means there is no zoom
+ * in or out set in the camera.
*/
-int Q3DCamera::zoomLevel()
+int Q3DCamera::zoomLevel() const
{
return d_ptr->m_zoomLevel;
}
@@ -508,14 +674,16 @@ void Q3DCamera::setZoomLevel(int zoomLevel)
/*!
* Calculates and returns a position relative to the camera using the given parameters
* and the current camera viewMatrix property.
- * \a relativePosition defines the relative 3D offset to the current camera position.
- * \a fixedRotation is optional, if given fixes rotation of the calculated point around the data visualization area to the given value in degrees.
- * \a distanceModifier is also optional, if given modifies the distance of the calculated point from the data visualization.
- * \return Calculated position relative to this camera's position.
+ * The relative 3D offset to the current camera position is defined in \a relativePosition.
+ * An optional fixed rotation of the calculated point around the data visualization area can be
+ * given in \a fixedRotation. The rotation is given in degrees.
+ * An optional \a distanceModifier modifies the distance of the calculated point from the data
+ * visualization.
+ * \return calculated position relative to this camera's position.
*/
QVector3D Q3DCamera::calculatePositionRelativeToCamera(const QVector3D &relativePosition,
- qreal fixedRotation,
- qreal distanceModifier) const
+ float fixedRotation,
+ float distanceModifier) const
{
// Move the position with camera
GLfloat radiusFactor = cameraDistance * (1.5f + distanceModifier);
@@ -545,8 +713,9 @@ QVector3D Q3DCamera::calculatePositionRelativeToCamera(const QVector3D &relative
* This property determines the behavior of the minimum and maximum limits in the X-rotation.
* By default the X-rotation wraps from minimum value to maximum and from maximum to minimum.
*
- * If set to true the X-rotation of the camera is wrapped from minimum to maximum and from maximum to minimum.
- * If set to false the X-rotation of the camera is limited to the sector determined by minimum and maximum values.
+ * If set to \c true the X-rotation of the camera is wrapped from minimum to maximum and from
+ * maximum to minimum. If set to \c false the X-rotation of the camera is limited to the sector
+ * determined by minimum and maximum values.
*/
bool Q3DCamera::wrapXRotation() const
{
@@ -564,8 +733,9 @@ void Q3DCamera::setWrapXRotation(bool isEnabled)
* This property determines the behavior of the minimum and maximum limits in the Y-rotation.
* By default the Y-rotation is limited between the minimum and maximum values without any wrapping.
*
- * If true the Y-rotation of the camera is wrapped from minimum to maximum and from maximum to minimum.
- * If false the Y-rotation of the camera is limited to the sector determined by minimum and maximum values.
+ * If \c true the Y-rotation of the camera is wrapped from minimum to maximum and from maximum to
+ * minimum. If \c false the Y-rotation of the camera is limited to the sector determined by minimum
+ * and maximum values.
*/
bool Q3DCamera::wrapYRotation() const
{
@@ -578,12 +748,14 @@ void Q3DCamera::setWrapYRotation(bool isEnabled)
}
/*!
- * Utility function that sets the camera rotations and distance.\a horizontal and \a vertical define the camera rotations to be used.
- * Optional \a zoom parameter can be given to set the zoom of the camera in range of 10-500%.
+ * Utility function that sets the camera rotations and distance.\a horizontal and \a vertical
+ * define the camera rotations to be used.
+ * Optional \a zoom parameter can be given to set the zoom percentage of the camera in range of
+ * \c{10.0f - 500.0f}.
*/
-void Q3DCamera::setCameraPosition(qreal horizontal, qreal vertical, qreal zoom)
+void Q3DCamera::setCameraPosition(float horizontal, float vertical, float zoom)
{
- setZoomLevel(qBound(qreal(10.0), zoom, qreal(500.0)));
+ setZoomLevel(qBound(10.0f, zoom, 500.0f));
setXRotation(horizontal);
setYRotation(vertical);
}
@@ -591,16 +763,16 @@ void Q3DCamera::setCameraPosition(qreal horizontal, qreal vertical, qreal zoom)
Q3DCameraPrivate::Q3DCameraPrivate(Q3DCamera *q) :
q_ptr(q),
m_isViewMatrixUpdateActive(true),
- m_xRotation(0.0),
- m_yRotation(0.0),
- m_minXRotation(-180.0),
- m_minYRotation(0.0),
- m_maxXRotation(180.0),
- m_maxYRotation(90.0),
+ m_xRotation(0.0f),
+ m_yRotation(0.0f),
+ m_minXRotation(-180.0f),
+ m_minYRotation(0.0f),
+ m_maxXRotation(180.0f),
+ m_maxYRotation(90.0f),
m_wrapXRotation(true),
m_wrapYRotation(false),
m_zoomLevel(100),
- m_activePreset(QDataVis::CameraPresetNone)
+ m_activePreset(Q3DCamera::CameraPresetNone)
{
}
@@ -619,7 +791,7 @@ void Q3DCameraPrivate::sync(Q3DCamera &other)
}
}
-void Q3DCameraPrivate::setXRotation(const qreal rotation)
+void Q3DCameraPrivate::setXRotation(const float rotation)
{
if (m_xRotation != rotation) {
m_xRotation = rotation;
@@ -627,7 +799,7 @@ void Q3DCameraPrivate::setXRotation(const qreal rotation)
}
}
-void Q3DCameraPrivate::setYRotation(const qreal rotation)
+void Q3DCameraPrivate::setYRotation(const float rotation)
{
if (m_yRotation != rotation) {
m_yRotation = rotation;
@@ -635,7 +807,7 @@ void Q3DCameraPrivate::setYRotation(const qreal rotation)
}
}
-void Q3DCameraPrivate::setMinXRotation(const qreal rotation)
+void Q3DCameraPrivate::setMinXRotation(const float rotation)
{
if (m_minXRotation != rotation) {
m_minXRotation = rotation;
@@ -643,7 +815,7 @@ void Q3DCameraPrivate::setMinXRotation(const qreal rotation)
}
}
-void Q3DCameraPrivate::setMinYRotation(const qreal rotation)
+void Q3DCameraPrivate::setMinYRotation(const float rotation)
{
if (m_minYRotation != rotation) {
m_minYRotation = rotation;
@@ -651,7 +823,7 @@ void Q3DCameraPrivate::setMinYRotation(const qreal rotation)
}
}
-void Q3DCameraPrivate::setMaxXRotation(const qreal rotation)
+void Q3DCameraPrivate::setMaxXRotation(const float rotation)
{
if (m_maxXRotation != rotation) {
m_maxXRotation = rotation;
@@ -659,7 +831,7 @@ void Q3DCameraPrivate::setMaxXRotation(const qreal rotation)
}
}
-void Q3DCameraPrivate::setMaxYRotation(const qreal rotation)
+void Q3DCameraPrivate::setMaxYRotation(const float rotation)
{
if (m_maxYRotation != rotation) {
m_maxYRotation = rotation;
@@ -669,7 +841,7 @@ void Q3DCameraPrivate::setMaxYRotation(const qreal rotation)
// Recalculates the view matrix based on the currently set base orientation, rotation and zoom level values.
// zoomAdjustment is adjustment to ensure that the 3D visualization stays inside the view area in the 100% zoom.
-void Q3DCameraPrivate::updateViewMatrix(qreal zoomAdjustment)
+void Q3DCameraPrivate::updateViewMatrix(float zoomAdjustment)
{
if (!m_isViewMatrixUpdateActive)
return;
diff --git a/src/datavisualization/engine/q3dcamera.h b/src/datavisualization/engine/q3dcamera.h
index ee750cec..9287e15a 100644
--- a/src/datavisualization/engine/q3dcamera.h
+++ b/src/datavisualization/engine/q3dcamera.h
@@ -32,34 +32,63 @@ class Q3DCameraPrivate;
class QT_DATAVISUALIZATION_EXPORT Q3DCamera : public Q3DObject
{
Q_OBJECT
- Q_PROPERTY(qreal xRotation READ xRotation WRITE setXRotation NOTIFY xRotationChanged)
- Q_PROPERTY(qreal yRotation READ yRotation WRITE setYRotation NOTIFY yRotationChanged)
- Q_PROPERTY(qreal minXRotation READ minXRotation NOTIFY minXRotationChanged)
- Q_PROPERTY(qreal minYRotation READ minYRotation NOTIFY minYRotationChanged)
- Q_PROPERTY(qreal maxXRotation READ maxXRotation NOTIFY maxXRotationChanged)
- Q_PROPERTY(qreal maxYRotation READ maxYRotation NOTIFY maxYRotationChanged)
+ Q_ENUMS(CameraPreset)
+ Q_PROPERTY(float xRotation READ xRotation WRITE setXRotation NOTIFY xRotationChanged)
+ Q_PROPERTY(float yRotation READ yRotation WRITE setYRotation NOTIFY yRotationChanged)
+ Q_PROPERTY(float minXRotation READ minXRotation NOTIFY minXRotationChanged)
+ Q_PROPERTY(float minYRotation READ minYRotation NOTIFY minYRotationChanged)
+ Q_PROPERTY(float maxXRotation READ maxXRotation NOTIFY maxXRotationChanged)
+ Q_PROPERTY(float maxYRotation READ maxYRotation NOTIFY maxYRotationChanged)
Q_PROPERTY(int zoomLevel READ zoomLevel WRITE setZoomLevel NOTIFY zoomLevelChanged)
Q_PROPERTY(QMatrix4x4 viewMatrix READ viewMatrix WRITE setViewMatrix NOTIFY viewMatrixChanged)
- Q_PROPERTY(QtDataVisualization::QDataVis::CameraPreset cameraPreset READ cameraPreset WRITE setCameraPreset NOTIFY cameraPresetChanged)
+ Q_PROPERTY(CameraPreset cameraPreset READ cameraPreset WRITE setCameraPreset NOTIFY cameraPresetChanged)
Q_PROPERTY(bool viewMatrixAutoUpdateEnabled READ isViewMatrixAutoUpdateEnabled WRITE setViewMatrixAutoUpdateEnabled NOTIFY viewMatrixAutoUpdateChanged)
- Q_PROPERTY(bool wrapXRotation READ wrapXRotation WRITE setWrapXRotation NOTIFY wrapXRotationChanged )
- Q_PROPERTY(bool wrapYRotation READ wrapYRotation WRITE setWrapYRotation NOTIFY wrapYRotationChanged )
- Q_ENUMS(QtDataVisualization::QDataVis::CameraPreset)
+ Q_PROPERTY(bool wrapXRotation READ wrapXRotation WRITE setWrapXRotation NOTIFY wrapXRotationChanged)
+ Q_PROPERTY(bool wrapYRotation READ wrapYRotation WRITE setWrapYRotation NOTIFY wrapYRotationChanged)
+
+public:
+ enum CameraPreset {
+ CameraPresetNone = -1,
+ CameraPresetFrontLow = 0,
+ CameraPresetFront,
+ CameraPresetFrontHigh,
+ CameraPresetLeftLow,
+ CameraPresetLeft,
+ CameraPresetLeftHigh,
+ CameraPresetRightLow,
+ CameraPresetRight,
+ CameraPresetRightHigh,
+ CameraPresetBehindLow,
+ CameraPresetBehind,
+ CameraPresetBehindHigh,
+ CameraPresetIsometricLeft,
+ CameraPresetIsometricLeftHigh,
+ CameraPresetIsometricRight,
+ CameraPresetIsometricRightHigh,
+ CameraPresetDirectlyAbove,
+ CameraPresetDirectlyAboveCW45,
+ CameraPresetDirectlyAboveCCW45,
+ CameraPresetFrontBelow,
+ CameraPresetLeftBelow,
+ CameraPresetRightBelow,
+ CameraPresetBehindBelow,
+ CameraPresetDirectlyBelow
+ };
public:
Q3DCamera(QObject *parent = 0);
virtual ~Q3DCamera();
- qreal xRotation() const;
- void setXRotation(qreal rotation);
- qreal yRotation() const;
- void setYRotation(qreal rotation);
+ float xRotation() const;
+ void setXRotation(float rotation);
+ float yRotation() const;
+ void setYRotation(float rotation);
- qreal minXRotation() const;
- qreal maxXRotation() const;
+ float minXRotation() const;
+ float maxXRotation() const;
- qreal minYRotation() const;
- qreal maxYRotation() const;
+ float minYRotation() const;
+ float maxYRotation() const;
bool wrapXRotation() const;
void setWrapXRotation(bool isEnabled);
@@ -67,48 +96,49 @@ public:
bool wrapYRotation() const;
void setWrapYRotation(bool isEnabled);
- void copyValuesFrom(const Q3DCamera &source);
+ virtual void copyValuesFrom(const Q3DObject &source);
QMatrix4x4 viewMatrix() const;
void setViewMatrix(const QMatrix4x4 &viewMatrix);
- bool isViewMatrixAutoUpdateEnabled();
+ bool isViewMatrixAutoUpdateEnabled() const;
void setViewMatrixAutoUpdateEnabled(bool isEnabled);
- QDataVis::CameraPreset cameraPreset();
- void setCameraPreset(QDataVis::CameraPreset preset);
+ CameraPreset cameraPreset() const;
+ void setCameraPreset(CameraPreset preset);
- int zoomLevel();
+ int zoomLevel() const;
void setZoomLevel(int zoomLevel);
- void setBaseOrientation(const QVector3D &defaultPosition,
- const QVector3D &defaultTarget,
- const QVector3D &defaultUp);
+ Q_INVOKABLE void setBaseOrientation(const QVector3D &defaultPosition,
+ const QVector3D &defaultTarget,
+ const QVector3D &defaultUp);
QVector3D calculatePositionRelativeToCamera(const QVector3D &relativePosition,
- qreal fixedRotation,
- qreal distanceModifier) const;
- void setCameraPosition(qreal horizontal, qreal vertical, qreal distance = 100.0);
+ float fixedRotation,
+ float distanceModifier) const;
+ void setCameraPosition(float horizontal, float vertical, float distance = 100.0f);
signals:
- void xRotationChanged(qreal rotation);
- void yRotationChanged(qreal rotation);
- void minXRotationChanged(qreal rotation);
- void minYRotationChanged(qreal rotation);
- void maxXRotationChanged(qreal rotation);
- void maxYRotationChanged(qreal rotation);
+ void xRotationChanged(float rotation);
+ void yRotationChanged(float rotation);
+ void minXRotationChanged(float rotation);
+ void minYRotationChanged(float rotation);
+ void maxXRotationChanged(float rotation);
+ void maxYRotationChanged(float rotation);
void zoomLevelChanged(int zoomLevel);
void viewMatrixChanged(QMatrix4x4 viewMatrix);
- void cameraPresetChanged(QDataVis::CameraPreset preset);
+ void cameraPresetChanged(CameraPreset preset);
void viewMatrixAutoUpdateChanged(bool enabled);
void wrapXRotationChanged(bool isEnabled);
void wrapYRotationChanged(bool isEnabled);
-protected:
- void setMinXRotation(qreal rotation);
- void setMinYRotation(qreal rotation);
- void setMaxXRotation(qreal rotation);
- void setMaxYRotation(qreal rotation);
+private:
+ // To be exposed in the future
+ void setMinXRotation(float rotation);
+ void setMinYRotation(float rotation);
+ void setMaxXRotation(float rotation);
+ void setMaxYRotation(float rotation);
private:
QScopedPointer<Q3DCameraPrivate> d_ptr;
@@ -117,6 +147,7 @@ private:
friend class Q3DCameraPrivate;
friend class Q3DScenePrivate;
+ friend class Abstract3DRenderer;
friend class Bars3DRenderer;
friend class Surface3DRenderer;
friend class Scatter3DRenderer;
diff --git a/src/datavisualization/engine/q3dcamera_p.h b/src/datavisualization/engine/q3dcamera_p.h
index e0528dcc..ac32248e 100644
--- a/src/datavisualization/engine/q3dcamera_p.h
+++ b/src/datavisualization/engine/q3dcamera_p.h
@@ -44,14 +44,14 @@ public:
void sync(Q3DCamera &other);
- void setXRotation(qreal rotation);
- void setYRotation(qreal rotation);
- void setMinXRotation(qreal rotation);
- void setMinYRotation(qreal rotation);
- void setMaxXRotation(qreal rotation);
- void setMaxYRotation(qreal rotation);
+ void setXRotation(float rotation);
+ void setYRotation(float rotation);
+ void setMinXRotation(float rotation);
+ void setMinYRotation(float rotation);
+ void setMaxXRotation(float rotation);
+ void setMaxYRotation(float rotation);
- void updateViewMatrix(qreal zoomAdjustment);
+ void updateViewMatrix(float zoomAdjustment);
public:
Q3DCamera *q_ptr;
@@ -71,7 +71,7 @@ public:
bool m_wrapXRotation;
bool m_wrapYRotation;
int m_zoomLevel;
- QDataVis::CameraPreset m_activePreset;
+ Q3DCamera::CameraPreset m_activePreset;
friend class Bars3DRenderer;
friend class Surface3DRenderer;
diff --git a/src/datavisualization/engine/q3dlight.cpp b/src/datavisualization/engine/q3dlight.cpp
index f1b1b4e7..bc43c3d7 100644
--- a/src/datavisualization/engine/q3dlight.cpp
+++ b/src/datavisualization/engine/q3dlight.cpp
@@ -23,16 +23,27 @@
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
/*!
- \class Q3DLight
- \inmodule QtDataVisualization
- \brief Representation of a light source in 3D space.
- \since Qt Data Visualization 1.0
+ * \class Q3DLight
+ * \inmodule QtDataVisualization
+ * \brief Representation of a light source in 3D space.
+ * \since Qt Data Visualization 1.0
+ *
+ * Q3DLight represents a monochrome non variable light source in 3D space.
+ */
- Q3DLight represents a monochrome non variable light source in 3D space.
-*/
+/*!
+ * \qmltype Light3D
+ * \inqmlmodule QtDataVisualization
+ * \since QtDataVisualization 1.0
+ * \ingroup datavisualization_qml
+ * \instantiates Q3DLight
+ * \brief Representation of a light source in 3D space.
+ *
+ * Light3D represents a monochrome non variable light source in 3D space.
+ */
/*!
- * Constructs a new 3D light located at origo. An optional \a parent parameter can be given
+ * Constructs a new 3D light located at origin. An optional \a parent parameter can be given
* and is then passed to QObject constructor.
*/
Q3DLight::Q3DLight(QObject *parent) :
@@ -42,14 +53,6 @@ Q3DLight::Q3DLight(QObject *parent) :
}
/*!
- * Copies the properties of the 3D light from the given source \a source light to this light instance.
- */
-void Q3DLight::copyValuesFrom(const Q3DLight &source)
-{
- Q3DObject::copyValuesFrom(source);
-}
-
-/*!
* Destroys the light object.
*/
Q3DLight::~Q3DLight()
diff --git a/src/datavisualization/engine/q3dlight.h b/src/datavisualization/engine/q3dlight.h
index 0a4ba174..f9109183 100644
--- a/src/datavisualization/engine/q3dlight.h
+++ b/src/datavisualization/engine/q3dlight.h
@@ -34,8 +34,6 @@ public:
Q3DLight(QObject *parent = 0);
virtual ~Q3DLight();
- void copyValuesFrom(const Q3DLight &source);
-
private:
QScopedPointer<Q3DLightPrivate> d_ptr;
diff --git a/src/datavisualization/engine/q3dobject.h b/src/datavisualization/engine/q3dobject.h
index 930bb022..b5ce7804 100644
--- a/src/datavisualization/engine/q3dobject.h
+++ b/src/datavisualization/engine/q3dobject.h
@@ -26,9 +26,10 @@
#include <QVector3D>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
class Q3DObjectPrivate;
-class Q3DObject : public QObject
+class QT_DATAVISUALIZATION_EXPORT Q3DObject : public QObject
{
Q_OBJECT
Q_PROPERTY(Q3DScene* parentScene READ parentScene)
@@ -38,7 +39,7 @@ public:
Q3DObject(QObject *parent = 0);
virtual ~Q3DObject();
- void copyValuesFrom(const Q3DObject &source);
+ virtual void copyValuesFrom(const Q3DObject &source);
Q3DScene *parentScene();
diff --git a/src/datavisualization/engine/q3dscatter.cpp b/src/datavisualization/engine/q3dscatter.cpp
index fc95842a..3c28b4a5 100644
--- a/src/datavisualization/engine/q3dscatter.cpp
+++ b/src/datavisualization/engine/q3dscatter.cpp
@@ -20,11 +20,10 @@
#include "q3dscatter_p.h"
#include "scatter3dcontroller_p.h"
#include "q3dvalueaxis.h"
-#include "qscatterdataproxy.h"
#include "q3dcamera.h"
+#include "qscatter3dseries_p.h"
#include <QMouseEvent>
-#include <QDebug>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
@@ -44,20 +43,20 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
* These default axes can be modified via axis accessors, but as soon any axis is set explicitly
* for the orientation, the default axis for that orientation is destroyed.
*
- * Data proxies work similarly: if no data proxy is set explicitly, Q3DScatter creates a default
- * proxy. If any other proxy is set as active data proxy later, the default proxy and all data
- * added to it is destroyed.
+ * Q3DScatter supports more than one series visible at the same time.
*
- * Methods are provided for changing item styles, themes, item selection modes and so on. See the
+ * Methods are provided for changing themes, item selection modes and so on. See the
* methods for more detailed descriptions.
*
* \section1 How to construct a minimal Q3DScatter graph
*
- * First, construct Q3DScatter:
+ * First, construct Q3DScatter. Since we are running the graph as top level window
+ * in this example, we need to clear the \c Qt::FramelessWindowHint flag, which gets set by
+ * default:
*
* \snippet doc_src_q3dscatter_construction.cpp 0
*
- * Now Q3DScatter is ready to receive data to be rendered. Add one set of 3 QVector3D items:
+ * Now Q3DScatter is ready to receive data to be rendered. Add one series of 3 QVector3D items:
*
* \snippet doc_src_q3dscatter_construction.cpp 1
*
@@ -81,199 +80,150 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*/
/*!
- * Constructs a new 3D scatter window.
+ * Constructs a new 3D scatter graph with optional \a parent window.
*/
-Q3DScatter::Q3DScatter()
- : d_ptr(new Q3DScatterPrivate(this, geometry()))
+Q3DScatter::Q3DScatter(QWindow *parent)
+ : Q3DWindow(new Q3DScatterPrivate(this), parent)
{
- setVisualController(d_ptr->m_shared);
- d_ptr->m_shared->initializeOpenGL();
- QObject::connect(d_ptr->m_shared, &Scatter3DController::selectedItemIndexChanged, this,
- &Q3DScatter::selectedItemIndexChanged);
- QObject::connect(d_ptr->m_shared, &Abstract3DController::needRender, this,
- &Q3DWindow::renderLater);
+ dptr()->m_shared = new Scatter3DController(geometry());
+ d_ptr->setVisualController(dptr()->m_shared);
+ dptr()->m_shared->initializeOpenGL();
+ QObject::connect(dptr()->m_shared, &Abstract3DController::selectionModeChanged, this,
+ &Q3DScatter::selectionModeChanged);
+ QObject::connect(dptr()->m_shared, &Abstract3DController::shadowQualityChanged, this,
+ &Q3DScatter::shadowQualityChanged);
+ QObject::connect(dptr()->m_shared, &Abstract3DController::themeChanged, this,
+ &Q3DScatter::themeChanged);
+ QObject::connect(dptr()->m_shared, &Abstract3DController::needRender, d_ptr.data(),
+ &Q3DWindowPrivate::renderLater);
+ QObject::connect(dptr()->m_shared, &Abstract3DController::shadowQualityChanged, dptr(),
+ &Q3DScatterPrivate::handleShadowQualityUpdate);
}
/*!
- * Destroys the 3D scatter window.
+ * Destroys the 3D scatter graph.
*/
Q3DScatter::~Q3DScatter()
{
}
/*!
- * \internal
+ * Adds the \a series to the graph. A graph can contain multiple series, but has only one set of
+ * axes. If the newly added series has specified a selected item, it will be highlighted and
+ * any existing selection will be cleared. Only one added series can have an active selection.
*/
-void Q3DScatter::mouseDoubleClickEvent(QMouseEvent *event)
+void Q3DScatter::addSeries(QScatter3DSeries *series)
{
- d_ptr->m_shared->mouseDoubleClickEvent(event);
+ dptr()->m_shared->addSeries(series);
}
/*!
- * \internal
+ * Removes the \a series from the graph.
*/
-void Q3DScatter::touchEvent(QTouchEvent *event)
+void Q3DScatter::removeSeries(QScatter3DSeries *series)
{
- d_ptr->m_shared->touchEvent(event);
+ dptr()->m_shared->removeSeries(series);
}
/*!
- * \internal
+ * \return list of series added to this graph.
*/
-void Q3DScatter::mousePressEvent(QMouseEvent *event)
+QList<QScatter3DSeries *> Q3DScatter::seriesList()
{
- d_ptr->m_shared->mousePressEvent(event, event->pos());
+ return dptr()->m_shared->scatterSeriesList();
}
/*!
* \internal
*/
-void Q3DScatter::mouseReleaseEvent(QMouseEvent *event)
+void Q3DScatter::mouseDoubleClickEvent(QMouseEvent *event)
{
- d_ptr->m_shared->mouseReleaseEvent(event, event->pos());
+ dptr()->m_shared->mouseDoubleClickEvent(event);
}
/*!
* \internal
*/
-void Q3DScatter::mouseMoveEvent(QMouseEvent *event)
+void Q3DScatter::touchEvent(QTouchEvent *event)
{
- d_ptr->m_shared->mouseMoveEvent(event, event->pos());
+ dptr()->m_shared->touchEvent(event);
}
/*!
* \internal
*/
-void Q3DScatter::wheelEvent(QWheelEvent *event)
+void Q3DScatter::mousePressEvent(QMouseEvent *event)
{
- d_ptr->m_shared->wheelEvent(event);
+ dptr()->m_shared->mousePressEvent(event, event->pos());
}
/*!
* \internal
*/
-void Q3DScatter::resizeEvent(QResizeEvent *event)
+void Q3DScatter::mouseReleaseEvent(QMouseEvent *event)
{
- Q_UNUSED(event);
- d_ptr->m_shared->setSize(width(), height());
+ dptr()->m_shared->mouseReleaseEvent(event, event->pos());
}
/*!
- * Sets window \a width.
+ * \internal
*/
-void Q3DScatter::setWidth(const int width)
+void Q3DScatter::mouseMoveEvent(QMouseEvent *event)
{
- d_ptr->m_shared->setWidth(width);
- QWindow::setWidth(width);
+ dptr()->m_shared->mouseMoveEvent(event, event->pos());
}
/*!
- * Sets window \a height.
+ * \internal
*/
-void Q3DScatter::setHeight(const int height)
+void Q3DScatter::wheelEvent(QWheelEvent *event)
{
- d_ptr->m_shared->setHeight(height);
- QWindow::setHeight(height);
+ dptr()->m_shared->wheelEvent(event);
}
-/*!
- * Sets the item \a style to one of the values in \c QDataVis::MeshStyle. It is preset to
- * \c QDataVis::MeshStyleSpheres by default. A \a smooth flag can be used to set shading to smooth.
- * It is \c false by default.
- *
- * \sa setMeshFileName()
- */
-void Q3DScatter::setObjectType(QDataVis::MeshStyle style, bool smooth)
+Q3DScatterPrivate *Q3DScatter::dptr()
{
- d_ptr->m_shared->setObjectType(style, smooth);
+ return static_cast<Q3DScatterPrivate *>(d_ptr.data());
}
-/*!
- * Sets a predefined \a theme from \c QDataVis::Theme. It is preset to \c QDataVis::ThemeQt by
- * default. Theme affects bar colors, label colors, text color, background color, window color and
- * grid color. Lighting is also adjusted by themes.
- *
- * \sa setObjectColor()
- *
- * \preliminary
- */
-void Q3DScatter::setTheme(QDataVis::Theme theme)
+const Q3DScatterPrivate *Q3DScatter::dptrc() const
{
- d_ptr->m_shared->setTheme(theme);
+ return static_cast<const Q3DScatterPrivate *>(d_ptr.data());
}
/*!
- * Set item color using your own colors. \a baseColor sets the base color of a item. The \a uniform
- * -flag is used to define if color needs to be uniform throughout item's length, or will the colors
- * be applied by height. It is \c true by default.
- *
- * Calling this method overrides colors from theme.
- *
- * \sa setTheme()
+ * \property Q3DScatter::theme
*
- * \preliminary
+ * A \a theme to be used for the graph. Ownership of the \a theme is transferred. Previous theme
+ * is deleted when a new one is set. Properties of the \a theme can be modified even after setting
+ * it, and the modifications take effect immediately.
*/
-void Q3DScatter::setObjectColor(const QColor &baseColor, bool uniform)
+void Q3DScatter::setTheme(Q3DTheme *theme)
{
- d_ptr->m_shared->setObjectColor(baseColor, uniform);
+ dptr()->m_shared->setTheme(theme);
}
-/*!
- * \return item color in use.
- */
-QColor Q3DScatter::objectColor() const
+Q3DTheme *Q3DScatter::theme() const
{
- return d_ptr->m_shared->objectColor();
+ return dptrc()->m_shared->theme();
}
/*!
* \property Q3DScatter::selectionMode
*
- * Sets item selection \a mode to one of \c QDataVis::SelectionMode. It is preset to
- * \c QDataVis::SelectionModeItem by default.
- */
-void Q3DScatter::setSelectionMode(QDataVis::SelectionMode mode)
-{
- d_ptr->m_shared->setSelectionMode(mode);
-}
-
-QDataVis::SelectionMode Q3DScatter::selectionMode() const
-{
- return d_ptr->m_shared->selectionMode();
-}
-
-/*!
- * \property Q3DScatter::meshFileName
- *
- * Override item type with a mesh object located in \a objFileName.
- * \note Object needs to be in Wavefront obj format and include vertices, normals and UVs.
- * It also needs to be in triangles.
- *
- * \sa setObjectType()
- */
-void Q3DScatter::setMeshFileName(const QString &objFileName)
-{
- d_ptr->m_shared->setMeshFileName(objFileName);
-}
-
-QString Q3DScatter::meshFileName() const
-{
- return d_ptr->m_shared->meshFileName();
-}
-
-/*!
- * \property Q3DScatter::font
+ * Sets item selection \a mode to a combination of \c QDataVis::SelectionFlags. It is preset to
+ * \c QDataVis::SelectionItem by default.
*
- * Sets the \a font for labels. It is preset to \c Arial by default.
+ * \note Only \c QDataVis::SelectionItem and \c QDataVis::SelectionNone are supported.
*/
-void Q3DScatter::setFont(const QFont &font)
+void Q3DScatter::setSelectionMode(QDataVis::SelectionFlags mode)
{
- d_ptr->m_shared->setFont(font);
+ dptr()->m_shared->setSelectionMode(mode);
}
-QFont Q3DScatter::font() const
+QDataVis::SelectionFlags Q3DScatter::selectionMode() const
{
- return d_ptr->m_shared->font();
+ return dptrc()->m_shared->selectionMode();
}
/*!
@@ -283,69 +233,7 @@ QFont Q3DScatter::font() const
*/
Q3DScene *Q3DScatter::scene() const
{
- return d_ptr->m_shared->scene();
-}
-
-/*!
- * \property Q3DScatter::labelStyle
- *
- * Sets label \a style to one of \c QDataVis::LabelStyle. It is preset to
- * \c QDataVis::LabelStyleFromTheme by default.
- */
-void Q3DScatter::setLabelStyle(QDataVis::LabelStyle style)
-{
- d_ptr->m_shared->setLabelStyle(style);
-}
-
-QDataVis::LabelStyle Q3DScatter::labelStyle() const
-{
- return d_ptr->m_shared->labelStyle();
-}
-
-/*!
- * \property Q3DScatter::gridVisible
- *
- * Sets grid visibility to \a visible. It is preset to \c true by default.
- */
-void Q3DScatter::setGridVisible(bool visible)
-{
- d_ptr->m_shared->setGridEnabled(visible);
-}
-
-bool Q3DScatter::isGridVisible() const
-{
- return d_ptr->m_shared->gridEnabled();
-}
-
-/*!
- * \property Q3DScatter::backgroundVisible
- *
- * Sets background visibility to \a visible. It is preset to \c true by default.
- */
-void Q3DScatter::setBackgroundVisible(bool visible)
-{
- d_ptr->m_shared->setBackgroundEnabled(visible);
-}
-
-bool Q3DScatter::isBackgroundVisible() const
-{
- return d_ptr->m_shared->backgroundEnabled();
-}
-
-/*!
- * \property Q3DScatter::selectedItemIndex
- *
- * Selects an item in the \a index. Only one item can be selected at a time.
- * To clear selection, specify an illegal \a index, e.g. -1.
- */
-void Q3DScatter::setSelectedItemIndex(int index)
-{
- d_ptr->m_shared->setSelectedItemIndex(index);
-}
-
-int Q3DScatter::selectedItemIndex() const
-{
- return d_ptr->m_shared->selectedItemIndex();
+ return dptrc()->m_shared->scene();
}
/*!
@@ -360,12 +248,12 @@ int Q3DScatter::selectedItemIndex() const
*/
void Q3DScatter::setShadowQuality(QDataVis::ShadowQuality quality)
{
- return d_ptr->m_shared->setShadowQuality(quality);
+ return dptr()->m_shared->setShadowQuality(quality);
}
QDataVis::ShadowQuality Q3DScatter::shadowQuality() const
{
- return d_ptr->m_shared->shadowQuality();
+ return dptrc()->m_shared->shadowQuality();
}
/*!
@@ -380,7 +268,7 @@ QDataVis::ShadowQuality Q3DScatter::shadowQuality() const
*/
void Q3DScatter::setAxisX(Q3DValueAxis *axis)
{
- d_ptr->m_shared->setAxisX(axis);
+ dptr()->m_shared->setAxisX(axis);
}
/*!
@@ -388,7 +276,7 @@ void Q3DScatter::setAxisX(Q3DValueAxis *axis)
*/
Q3DValueAxis *Q3DScatter::axisX() const
{
- return static_cast<Q3DValueAxis *>(d_ptr->m_shared->axisX());
+ return static_cast<Q3DValueAxis *>(dptrc()->m_shared->axisX());
}
/*!
@@ -403,7 +291,7 @@ Q3DValueAxis *Q3DScatter::axisX() const
*/
void Q3DScatter::setAxisY(Q3DValueAxis *axis)
{
- d_ptr->m_shared->setAxisY(axis);
+ dptr()->m_shared->setAxisY(axis);
}
/*!
@@ -411,7 +299,7 @@ void Q3DScatter::setAxisY(Q3DValueAxis *axis)
*/
Q3DValueAxis *Q3DScatter::axisY() const
{
- return static_cast<Q3DValueAxis *>(d_ptr->m_shared->axisY());
+ return static_cast<Q3DValueAxis *>(dptrc()->m_shared->axisY());
}
/*!
@@ -426,7 +314,7 @@ Q3DValueAxis *Q3DScatter::axisY() const
*/
void Q3DScatter::setAxisZ(Q3DValueAxis *axis)
{
- d_ptr->m_shared->setAxisZ(axis);
+ dptr()->m_shared->setAxisZ(axis);
}
/*!
@@ -434,7 +322,7 @@ void Q3DScatter::setAxisZ(Q3DValueAxis *axis)
*/
Q3DValueAxis *Q3DScatter::axisZ() const
{
- return static_cast<Q3DValueAxis *>(d_ptr->m_shared->axisZ());
+ return static_cast<Q3DValueAxis *>(dptrc()->m_shared->axisZ());
}
/*!
@@ -446,7 +334,7 @@ Q3DValueAxis *Q3DScatter::axisZ() const
*/
void Q3DScatter::addAxis(Q3DValueAxis *axis)
{
- d_ptr->m_shared->addAxis(axis);
+ dptr()->m_shared->addAxis(axis);
}
/*!
@@ -459,7 +347,7 @@ void Q3DScatter::addAxis(Q3DValueAxis *axis)
*/
void Q3DScatter::releaseAxis(Q3DValueAxis *axis)
{
- d_ptr->m_shared->releaseAxis(axis);
+ dptr()->m_shared->releaseAxis(axis);
}
/*!
@@ -469,7 +357,7 @@ void Q3DScatter::releaseAxis(Q3DValueAxis *axis)
*/
QList<Q3DValueAxis *> Q3DScatter::axes() const
{
- QList<Q3DAbstractAxis *> abstractAxes = d_ptr->m_shared->axes();
+ QList<Q3DAbstractAxis *> abstractAxes = dptrc()->m_shared->axes();
QList<Q3DValueAxis *> retList;
foreach (Q3DAbstractAxis *axis, abstractAxes)
retList.append(static_cast<Q3DValueAxis *>(axis));
@@ -478,90 +366,29 @@ QList<Q3DValueAxis *> Q3DScatter::axes() const
}
/*!
- * Sets the active data \a proxy. Implicitly calls addDataProxy() to transfer ownership of
- * the \a proxy to this graph.
- *
- * If the \a proxy is null, a temporary default proxy is created and activated.
- * This temporary proxy is destroyed if another \a proxy is set explicitly active via this method.
- *
- * \sa addDataProxy(), releaseDataProxy()
- */
-void Q3DScatter::setActiveDataProxy(QScatterDataProxy *proxy)
-{
- d_ptr->m_shared->setActiveDataProxy(proxy);
-}
-
-/*!
- * \return active data proxy.
- */
-QScatterDataProxy *Q3DScatter::activeDataProxy() const
-{
- return static_cast<QScatterDataProxy *>(d_ptr->m_shared->activeDataProxy());
-}
-
-/*!
- * Adds data \a proxy to the graph. The proxies added via addDataProxy are not yet taken to use,
- * addDataProxy is simply used to give the ownership of the data \a proxy to the graph.
- * The \a proxy must not be null or added to another graph.
- *
- * \sa releaseDataProxy(), setActiveDataProxy()
- */
-void Q3DScatter::addDataProxy(QScatterDataProxy *proxy)
-{
- d_ptr->m_shared->addDataProxy(proxy);
-}
-
-/*!
- * Releases the ownership of the data \a proxy back to the caller, if it is added to this graph.
- * If the released \a proxy is in use, a new empty default proxy is created and taken to use.
- *
- * If the default \a proxy is released and added back later, it behaves as any other proxy would.
- *
- * \sa addDataProxy(), setActiveDataProxy()
- */
-void Q3DScatter::releaseDataProxy(QScatterDataProxy *proxy)
-{
- d_ptr->m_shared->releaseDataProxy(proxy);
-}
-
-/*!
- * \return list of all added data proxies.
- *
- * \sa addDataProxy()
- */
-QList<QScatterDataProxy *> Q3DScatter::dataProxies() const
-{
- QList<QScatterDataProxy *> retList;
- QList<QAbstractDataProxy *> abstractList = d_ptr->m_shared->dataProxies();
- foreach (QAbstractDataProxy *proxy, abstractList)
- retList.append(static_cast<QScatterDataProxy *>(proxy));
-
- return retList;
-}
-
-/*!
* \fn void Q3DScatter::shadowQualityChanged(QDataVis::ShadowQuality quality)
*
* This signal is emitted when shadow \a quality changes.
*/
-Q3DScatterPrivate::Q3DScatterPrivate(Q3DScatter *q, QRect rect)
- : q_ptr(q),
- m_shared(new Scatter3DController(rect))
+Q3DScatterPrivate::Q3DScatterPrivate(Q3DScatter *q)
+ : Q3DWindowPrivate(q)
{
- QObject::connect(m_shared, &Abstract3DController::shadowQualityChanged, this,
- &Q3DScatterPrivate::handleShadowQualityUpdate);
}
Q3DScatterPrivate::~Q3DScatterPrivate()
{
- qDebug() << "Destroying Q3DScatterPrivate";
delete m_shared;
}
void Q3DScatterPrivate::handleShadowQualityUpdate(QDataVis::ShadowQuality quality)
{
- emit q_ptr->shadowQualityChanged(quality);
+ emit qptr()->shadowQualityChanged(quality);
+}
+
+Q3DScatter *Q3DScatterPrivate::qptr()
+{
+ return static_cast<Q3DScatter *>(q_ptr);
}
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/q3dscatter.h b/src/datavisualization/engine/q3dscatter.h
index fdea604e..e58146a1 100644
--- a/src/datavisualization/engine/q3dscatter.h
+++ b/src/datavisualization/engine/q3dscatter.h
@@ -22,7 +22,9 @@
#include <QtDataVisualization/qdatavisualizationenums.h>
#include <QtDataVisualization/q3dwindow.h>
#include <QtDataVisualization/q3dscene.h>
+#include <QtDataVisualization/q3dtheme.h>
#include <QFont>
+#include <QLinearGradient>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
@@ -30,62 +32,33 @@ class Q3DScatterPrivate;
class LabelItem;
class Q3DValueAxis;
class Q3DCategoryAxis;
-class QScatterDataProxy;
+class QScatter3DSeries;
+class Q3DTheme;
class QT_DATAVISUALIZATION_EXPORT Q3DScatter : public Q3DWindow
{
Q_OBJECT
- Q_PROPERTY(QtDataVisualization::QDataVis::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode)
- Q_PROPERTY(QtDataVisualization::QDataVis::LabelStyle labelStyle READ labelStyle WRITE setLabelStyle)
- Q_PROPERTY(QtDataVisualization::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality)
- Q_PROPERTY(QString meshFileName READ meshFileName WRITE setMeshFileName)
- Q_PROPERTY(QFont font READ font WRITE setFont)
- Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible)
- Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible)
- Q_PROPERTY(int selectedItemIndex READ selectedItemIndex WRITE setSelectedItemIndex NOTIFY selectedItemIndexChanged)
+ Q_PROPERTY(QtDataVisualization::QDataVis::SelectionFlags selectionMode READ selectionMode WRITE setSelectionMode NOTIFY selectionModeChanged)
+ Q_PROPERTY(QtDataVisualization::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality NOTIFY shadowQualityChanged)
+ Q_PROPERTY(Q3DTheme* theme READ theme WRITE setTheme NOTIFY themeChanged)
Q_PROPERTY(Q3DScene* scene READ scene)
- Q_ENUMS(QtDataVisualization::QDataVis::SelectionMode)
- Q_ENUMS(QtDataVisualization::QDataVis::ShadowQuality)
- Q_ENUMS(QtDataVisualization::QDataVis::LabelStyle)
- Q_ENUMS(QtDataVisualization::QDataVis::CameraPreset)
public:
- explicit Q3DScatter();
- ~Q3DScatter();
+ explicit Q3DScatter(QWindow *parent = 0);
+ virtual ~Q3DScatter();
- void setObjectType(QDataVis::MeshStyle style, bool smooth = false);
+ void addSeries(QScatter3DSeries *series);
+ void removeSeries(QScatter3DSeries *series);
+ QList<QScatter3DSeries *> seriesList();
- void setTheme(QDataVis::Theme theme);
+ void setTheme(Q3DTheme *theme);
+ Q3DTheme *theme() const;
- void setObjectColor(const QColor &baseColor, bool uniform = true);
- QColor objectColor() const;
-
- void setMeshFileName(const QString &objFileName);
- QString meshFileName() const;
-
- void setSelectionMode(QDataVis::SelectionMode mode);
- QDataVis::SelectionMode selectionMode() const;
-
- void setFont(const QFont &font);
- QFont font() const;
+ void setSelectionMode(QDataVis::SelectionFlags mode);
+ QDataVis::SelectionFlags selectionMode() const;
Q3DScene *scene() const;
- void setLabelStyle(QDataVis::LabelStyle style);
- QDataVis::LabelStyle labelStyle() const;
-
- void setGridVisible(bool visible);
- bool isGridVisible() const;
-
- void setWidth(const int width);
- void setHeight(const int height);
-
- void setBackgroundVisible(bool visible);
- bool isBackgroundVisible() const;
-
- void setSelectedItemIndex(int index);
- int selectedItemIndex() const;
-
void setShadowQuality(QDataVis::ShadowQuality quality);
QDataVis::ShadowQuality shadowQuality() const;
@@ -99,15 +72,10 @@ public:
void releaseAxis(Q3DValueAxis *axis);
QList<Q3DValueAxis *> axes() const;
- void setActiveDataProxy(QScatterDataProxy *proxy);
- QScatterDataProxy *activeDataProxy() const;
- void addDataProxy(QScatterDataProxy *proxy);
- void releaseDataProxy(QScatterDataProxy *proxy);
- QList<QScatterDataProxy *> dataProxies() const;
-
signals:
+ void selectionModeChanged(QDataVis::SelectionFlags mode);
void shadowQualityChanged(QDataVis::ShadowQuality quality);
- void selectedItemIndexChanged(int index);
+ void themeChanged(Q3DTheme* theme);
protected:
void mouseDoubleClickEvent(QMouseEvent *event);
@@ -116,10 +84,10 @@ protected:
void mouseReleaseEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void wheelEvent(QWheelEvent *event);
- void resizeEvent(QResizeEvent *event);
private:
- QScopedPointer<Q3DScatterPrivate> d_ptr;
+ Q3DScatterPrivate *dptr();
+ const Q3DScatterPrivate *dptrc() const;
Q_DISABLE_COPY(Q3DScatter)
};
diff --git a/src/datavisualization/engine/q3dscatter_p.h b/src/datavisualization/engine/q3dscatter_p.h
index 775344d0..d65776c5 100644
--- a/src/datavisualization/engine/q3dscatter_p.h
+++ b/src/datavisualization/engine/q3dscatter_p.h
@@ -26,26 +26,29 @@
//
// We mean it.
-#ifndef Q3DSCATTER_p_H
-#define Q3DSCATTER_p_H
+#ifndef Q3DSCATTER_P_H
+#define Q3DSCATTER_P_H
#include "scatter3dcontroller_p.h"
#include "qdatavisualizationenums.h"
+#include "q3dwindow_p.h"
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class Q3DScatter;
-class Q3DScatterPrivate : public QObject
+class Q3DScatterPrivate : public Q3DWindowPrivate
{
+ Q_OBJECT
public:
- Q3DScatterPrivate(Q3DScatter *q, QRect rect);
+ Q3DScatterPrivate(Q3DScatter *q);
~Q3DScatterPrivate();
// Used to detect when shadow quality changes autonomously due to e.g. resizing.
void handleShadowQualityUpdate(QDataVis::ShadowQuality quality);
- Q3DScatter *q_ptr;
+ Q3DScatter *qptr();
+
Scatter3DController *m_shared;
};
diff --git a/src/datavisualization/engine/q3dscene.cpp b/src/datavisualization/engine/q3dscene.cpp
index 3789ea9f..d8104b3a 100644
--- a/src/datavisualization/engine/q3dscene.cpp
+++ b/src/datavisualization/engine/q3dscene.cpp
@@ -26,6 +26,7 @@
#include "q3dlight_p.h"
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
/*!
* \class Q3DScene
* \inmodule QtDataVisualization
@@ -37,6 +38,27 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*
* The 3D scene also keeps track of the viewport in which visualization rendering is done,
* the primary subviewport inside the viewport where the main 3D data visualization view resides
+ * and the secondary subviewport where the 2D sliced view of the data resides. The subviewports are
+ * by default resized by the \a Q3DScene. To override the resize behavior you need to listen to both
+ * \l viewportChanged() and \l slicingActiveChanged() signals and recalculate the subviewports accordingly.
+ *
+ * Also the scene has flag for tracking if the secondary 2D slicing view is currently active or not.
+ * \note Not all visualizations support the secondary 2D slicing view.
+ */
+
+/*!
+ * \qmltype Scene3D
+ * \inqmlmodule QtDataVisualization
+ * \since QtDataVisualization 1.0
+ * \ingroup datavisualization_qml
+ * \instantiates Q3DScene
+ * \brief Scene3D type provides description of the 3D scene being visualized.
+ *
+ * The 3D scene contains a single active camera and a single active light source.
+ * Visualized data is assumed to be at a fixed location.
+ *
+ * The 3D scene also keeps track of the viewport in which visualization rendering is done,
+ * the primary subviewport inside the viewport where the main 3D data visualization view resides
* and the secondary subviewport where the 2D sliced view of the data resides.
*
* Also the scene has flag for tracking if the secondary 2D slicing view is currently active or not.
@@ -44,6 +66,71 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*/
/*!
+ * \qmlproperty rect Scene3D::viewport
+ *
+ * This property contains the current viewport rectangle where all 3D rendering
+ * is targeted.
+ */
+
+/*!
+ * \qmlproperty rect Scene3D::primarySubViewport
+ *
+ * This property contains the current subviewport rectangle inside the viewport where the
+ * primary view of the data visualization is targeted to.
+ */
+
+/*!
+ * \qmlproperty rect Scene3D::secondarySubViewport
+ *
+ * This property contains the secondary viewport rectangle inside the viewport. The secondary
+ * viewport is used for drawing the 2D slice view in some visualizations.
+ */
+
+/*!
+ * \qmlproperty point Scene3D::selectionQueryPosition
+ *
+ * This property contains the coordinates for the user input that should be processed
+ * by the scene as selection. If this is set to value other than \c{(-1, -1)} the
+ * graph tries to select a data item at the given point within the primary viewport.
+ * After the rendering pass the property is returned to its default state of \c{(-1, -1)}.
+ */
+
+/*!
+ * \qmlproperty bool Scene3D::slicingActive
+ *
+ * This property contains whether 2D slicing view is currently active or not.
+ * \note Not all visualizations support the 2D slicing view.
+ */
+
+/*!
+ * \qmlproperty bool Scene3D::secondarySubviewOnTop
+ *
+ * This property contains whether 2D slicing view is currently drawn on top or if the 3D view is
+ * drawn on top.
+ */
+
+/*!
+ * \qmlproperty Camera3D Scene3D::activeCamera
+ *
+ * This property contains the currently active camera in the 3D scene.
+ * When a Camera3D is set in the property it gets automatically added as child of the scene.
+ */
+
+/*!
+ * \qmlproperty Light3D Scene3D::activeLight
+ *
+ * This property contains the currently active light in the 3D scene.
+ * When a Light3D is set in the property it gets automatically added as child of the scene.
+ */
+
+/*!
+ * \qmlproperty float Scene3D::devicePixelRatio
+ *
+ * This property contains the current device pixel ratio that is used when mapping input
+ * coordinates to pixel coordinates.
+ */
+
+/*!
* Constructs a basic scene with one light and one camera in it. An
* optional \a parent parameter can be given and is then passed to QObject constructor.
*/
@@ -65,7 +152,7 @@ Q3DScene::~Q3DScene()
/*!
* \property Q3DScene::viewport
*
- * This property contains the current viewport rectangle where all 3D rendering
+ * This read only property contains the current viewport rectangle where all 3D rendering
* is targeted.
*/
QRect Q3DScene::viewport() const
@@ -73,36 +160,10 @@ QRect Q3DScene::viewport() const
return d_ptr->m_viewport;
}
-void Q3DScene::setViewport(const QRect &viewport)
-{
- if (d_ptr->m_viewport.width() != viewport.width()
- || d_ptr->m_viewport.height() != viewport.height()) {
- d_ptr->m_viewport = viewport;
- d_ptr->m_viewport.setX(0);
- d_ptr->m_viewport.setY(0);
- d_ptr->m_changeTracker.viewportChanged = true;
- emit viewportChanged(viewport);
- }
-}
-
-/*!
- * Sets the \a width and \a height of the viewport only, without changing its location.
- */
-void Q3DScene::setViewportSize(int width, int height)
-{
- if (d_ptr->m_viewport.width() != width
- || d_ptr->m_viewport.height() != height) {
- d_ptr->m_viewport.setWidth(width);
- d_ptr->m_viewport.setHeight(height);
- d_ptr->m_changeTracker.viewportChanged = true;
- emit viewportChanged(d_ptr->m_viewport);
- }
-}
-
/*!
* \property Q3DScene::primarySubViewport
*
- * This property contains the current main viewport rectangle inside the viewport where the
+ * This property contains the current subviewport rectangle inside the viewport where the
* primary view of the data visualization is targeted to.
*/
QRect Q3DScene::primarySubViewport() const
@@ -112,10 +173,14 @@ QRect Q3DScene::primarySubViewport() const
void Q3DScene::setPrimarySubViewport(const QRect &primarySubViewport)
{
- if (d_ptr->m_primarySubViewport != primarySubViewport) {
- d_ptr->m_primarySubViewport = primarySubViewport;
+ QRect clipRect = QRect(0, 0, d_ptr->m_viewport.width(), d_ptr->m_viewport.height());
+ QRect intersectedViewport = primarySubViewport.intersected(clipRect);
+ if (d_ptr->m_primarySubViewport != intersectedViewport) {
+ d_ptr->m_primarySubViewport = intersectedViewport;
+ d_ptr->updateGLSubViewports();
d_ptr->m_changeTracker.primarySubViewportChanged = true;
- emit primarySubViewportChanged(primarySubViewport);
+ emit primarySubViewportChanged(intersectedViewport);
+ emit d_ptr->needRender();
}
}
@@ -123,7 +188,7 @@ void Q3DScene::setPrimarySubViewport(const QRect &primarySubViewport)
* Returns whether the given \a point resides inside the primary subview or not.
* The method takes care of correctly mapping between OpenGL coordinates used in the
* viewport definitions and the Qt event coordinate system used in the input system.
- * \return true if the point is inside the primary subview.
+ * \return \c true if the point is inside the primary subview.
*/
bool Q3DScene::isPointInPrimarySubView(const QPoint &point)
{
@@ -131,9 +196,9 @@ bool Q3DScene::isPointInPrimarySubView(const QPoint &point)
int x = point.x();
int y = point.y();
int areaMinX = d_ptr->m_primarySubViewport.x();
- int areaMaxX = d_ptr->m_primarySubViewport.x() + d_ptr->m_primarySubViewport.width();
- int areaMaxY = d_ptr->m_viewport.height() - d_ptr->m_primarySubViewport.y();
- int areaMinY = d_ptr->m_viewport.height() - (d_ptr->m_primarySubViewport.y() + d_ptr->m_primarySubViewport.height());
+ int areaMaxX = d_ptr->m_viewport.x() + d_ptr->m_primarySubViewport.x() + d_ptr->m_primarySubViewport.width();
+ int areaMaxY = d_ptr->m_viewport.y() + d_ptr->m_primarySubViewport.y() + d_ptr->m_primarySubViewport.height();
+ int areaMinY = d_ptr->m_viewport.y() + d_ptr->m_primarySubViewport.y();
return ( x > areaMinX && x < areaMaxX && y > areaMinY && y < areaMaxY );
}
@@ -142,7 +207,7 @@ bool Q3DScene::isPointInPrimarySubView(const QPoint &point)
* Returns whether the given \a point resides inside the secondary subview or not.
* The method takes care of correctly mapping between OpenGL coordinates used in the
* viewport definitions and the Qt event coordinate system used in the input system.
- * \return true if the point is inside the secondary subview.
+ * \return \c true if the point is inside the secondary subview.
*/
bool Q3DScene::isPointInSecondarySubView(const QPoint &point)
{
@@ -150,9 +215,9 @@ bool Q3DScene::isPointInSecondarySubView(const QPoint &point)
int x = point.x();
int y = point.y();
int areaMinX = d_ptr->m_secondarySubViewport.x();
- int areaMaxX = d_ptr->m_secondarySubViewport.x() + d_ptr->m_secondarySubViewport.width();
- int areaMaxY = d_ptr->m_viewport.height() - d_ptr->m_secondarySubViewport.y();
- int areaMinY = d_ptr->m_viewport.height() - (d_ptr->m_secondarySubViewport.y() + d_ptr->m_secondarySubViewport.height());
+ int areaMaxX = d_ptr->m_viewport.x() + d_ptr->m_secondarySubViewport.x() + d_ptr->m_secondarySubViewport.width();
+ int areaMaxY = d_ptr->m_viewport.y() + d_ptr->m_secondarySubViewport.y() + d_ptr->m_secondarySubViewport.height();
+ int areaMinY = d_ptr->m_viewport.y() + d_ptr->m_secondarySubViewport.y();
return ( x > areaMinX && x < areaMaxX && y > areaMinY && y < areaMaxY );
}
@@ -170,14 +235,50 @@ QRect Q3DScene::secondarySubViewport() const
void Q3DScene::setSecondarySubViewport(const QRect &secondarySubViewport)
{
- if (d_ptr->m_secondarySubViewport != secondarySubViewport) {
- d_ptr->m_secondarySubViewport = secondarySubViewport;
+ QRect clipRect = QRect(0, 0, d_ptr->m_viewport.width(), d_ptr->m_viewport.height());
+ QRect intersectedViewport = secondarySubViewport.intersected(clipRect);
+ if (d_ptr->m_secondarySubViewport != intersectedViewport) {
+ d_ptr->m_secondarySubViewport = intersectedViewport;
+ d_ptr->updateGLSubViewports();
d_ptr->m_changeTracker.secondarySubViewportChanged = true;
- emit secondarySubViewportChanged(secondarySubViewport);
+ emit secondarySubViewportChanged(intersectedViewport);
+ emit d_ptr->needRender();
}
}
/*!
+ * \property Q3DScene::selectionQueryPosition
+ *
+ * This property contains the coordinates for the user input that should be processed
+ * by the scene as selection. If this is set to value other than invalidSelectionPoint() the
+ * graph tries to select a data item at the given \a point within the primary viewport.
+ * After the rendering pass the property is returned to its default state of invalidSelectionPoint().
+ */
+void Q3DScene::setSelectionQueryPosition(const QPoint &point)
+{
+ if (point != d_ptr->m_selectionQueryPosition) {
+ d_ptr->m_selectionQueryPosition = point;
+ d_ptr->m_changeTracker.selectionQueryPositionChanged = true;
+ emit selectionQueryPositionChanged(point);
+ emit d_ptr->needRender();
+ }
+}
+
+QPoint Q3DScene::selectionQueryPosition() const
+{
+ return d_ptr->m_selectionQueryPosition;
+}
+
+/*!
+ * \return a QPoint signifying an invalid selection position.
+ */
+const QPoint Q3DScene::invalidSelectionPoint()
+{
+ static const QPoint invalidSelectionPos(-1, -1);
+ return invalidSelectionPos;
+}
+
+/*!
* \property Q3DScene::slicingActive
*
* This property contains whether 2D slicing view is currently active or not.
@@ -193,8 +294,30 @@ void Q3DScene::setSlicingActive(bool isSlicing)
if (d_ptr->m_isSlicingActive != isSlicing) {
d_ptr->m_isSlicingActive = isSlicing;
d_ptr->m_changeTracker.slicingActivatedChanged = true;
+ d_ptr->calculateSubViewports();
emit slicingActiveChanged(isSlicing);
- emitNeedRender();
+ emit d_ptr->needRender();
+ }
+}
+
+/*!
+ * \property Q3DScene::secondarySubviewOnTop
+ *
+ * This property contains whether 2D slicing view is currently drawn on top or if the 3D view is
+ * drawn on top.
+ */
+bool Q3DScene::isSecondarySubviewOnTop() const
+{
+ return d_ptr->m_isSecondarySubviewOnTop;
+}
+
+void Q3DScene::setSecondarySubviewOnTop(bool isSecondaryOnTop)
+{
+ if (d_ptr->m_isSecondarySubviewOnTop != isSecondaryOnTop) {
+ d_ptr->m_isSecondarySubviewOnTop = isSecondaryOnTop;
+ d_ptr->m_changeTracker.subViewportOrderChanged = true;
+ emit secondarySubviewOnTopChanged(isSecondaryOnTop);
+ emit d_ptr->needRender();
}
}
@@ -202,7 +325,8 @@ void Q3DScene::setSlicingActive(bool isSlicing)
* \property Q3DScene::activeCamera
*
* This property contains the currently active camera in the 3D scene.
- * When a new Q3DCamera objects is set in the property it gets automatically added as child of the scene.
+ * When a new Q3DCamera objects is set in the property it gets automatically added as child of
+ * the scene.
*/
Q3DCamera *Q3DScene::activeCamera() const
{
@@ -219,37 +343,37 @@ void Q3DScene::setActiveCamera(Q3DCamera *camera)
if (camera != d_ptr->m_camera) {
if (d_ptr->m_camera) {
- disconnect(d_ptr->m_camera, &Q3DCamera::xRotationChanged, this,
- &Q3DScene::emitNeedRender);
- disconnect(d_ptr->m_camera, &Q3DCamera::yRotationChanged, this,
- &Q3DScene::emitNeedRender);
+ disconnect(d_ptr->m_camera, &Q3DCamera::xRotationChanged, d_ptr.data(),
+ &Q3DScenePrivate::needRender);
+ disconnect(d_ptr->m_camera, &Q3DCamera::yRotationChanged, d_ptr.data(),
+ &Q3DScenePrivate::needRender);
+ disconnect(d_ptr->m_camera, &Q3DCamera::zoomLevelChanged, d_ptr.data(),
+ &Q3DScenePrivate::needRender);
}
d_ptr->m_camera = camera;
d_ptr->m_changeTracker.cameraChanged = true;
if (camera) {
- connect(camera, &Q3DCamera::xRotationChanged, this,
- &Q3DScene::emitNeedRender);
- connect(camera, &Q3DCamera::yRotationChanged, this,
- &Q3DScene::emitNeedRender);
+ connect(camera, &Q3DCamera::xRotationChanged, d_ptr.data(),
+ &Q3DScenePrivate::needRender);
+ connect(camera, &Q3DCamera::yRotationChanged, d_ptr.data(),
+ &Q3DScenePrivate::needRender);
+ connect(camera, &Q3DCamera::zoomLevelChanged, d_ptr.data(),
+ &Q3DScenePrivate::needRender);
}
emit activeCameraChanged(camera);
- emitNeedRender();
+ emit d_ptr->needRender();
}
}
-void Q3DScene::emitNeedRender()
-{
- emit needRender();
-}
-
/*!
* \property Q3DScene::activeLight
*
* This property contains the currently active light in the 3D scene.
- * When a new Q3DLight objects is set in the property it gets automatically added as child of the scene.
+ * When a new Q3DLight objects is set in the property it gets automatically added as child of
+ * the scene.
*/
Q3DLight *Q3DScene::activeLight() const
{
@@ -277,27 +401,32 @@ void Q3DScene::setActiveLight(Q3DLight *light)
* This property contains the current device pixel ratio that is used when mapping input
* coordinates to pixel coordinates.
*/
-qreal Q3DScene::devicePixelRatio() const
+float Q3DScene::devicePixelRatio() const
{
return d_ptr->m_devicePixelRatio;
}
-void Q3DScene::setDevicePixelRatio(qreal pixelRatio)
+void Q3DScene::setDevicePixelRatio(float pixelRatio)
{
if (d_ptr->m_devicePixelRatio != pixelRatio) {
d_ptr->m_devicePixelRatio = pixelRatio;
+ d_ptr->m_changeTracker.devicePixelRatioChanged = true;
emit devicePixelRatioChanged(pixelRatio);
+ d_ptr->updateGLViewport();
+ emit d_ptr->needRender();
}
}
/*!
- * Calculates and sets the light position relative to the currently active camera using the given parameters.
- * \a relativePosition defines the relative 3D offset to the current camera position.
- * Optional \a fixedRotation fixes the light rotation around the data visualization area to the given value in degrees.
+ * Calculates and sets the light position relative to the currently active camera using the given
+ * parameters.
+ * The relative 3D offset to the current camera position is defined in \a relativePosition.
+ * Optional \a fixedRotation fixes the light rotation around the data visualization area to the
+ * given value in degrees.
* Optional \a distanceModifier modifies the distance of the light from the data visualization.
*/
void Q3DScene::setLightPositionRelativeToCamera(const QVector3D &relativePosition,
- qreal fixedRotation, qreal distanceModifier)
+ float fixedRotation, float distanceModifier)
{
d_ptr->m_light->setPosition(
d_ptr->m_camera->calculatePositionRelativeToCamera(relativePosition,
@@ -305,18 +434,16 @@ void Q3DScene::setLightPositionRelativeToCamera(const QVector3D &relativePositio
distanceModifier));
}
-/*!
- * \fn Q3DScene::needRender()
- * \internal
- */
-
Q3DScenePrivate::Q3DScenePrivate(Q3DScene *q) :
+ QObject(0),
q_ptr(q),
+ m_isSecondarySubviewOnTop(true),
m_devicePixelRatio(1.f),
m_camera(),
m_light(),
m_isUnderSideCameraEnabled(false),
- m_isSlicingActive(false)
+ m_isSlicingActive(false),
+ m_selectionQueryPosition(Q3DScene::invalidSelectionPoint())
{
}
@@ -330,11 +457,21 @@ Q3DScenePrivate::~Q3DScenePrivate()
// those changes are discarded.
void Q3DScenePrivate::sync(Q3DScenePrivate &other)
{
+ if (m_changeTracker.windowSizeChanged) {
+ other.setWindowSize(windowSize());
+ m_changeTracker.windowSizeChanged = false;
+ other.m_changeTracker.windowSizeChanged = false;
+ }
if (m_changeTracker.viewportChanged) {
- other.q_ptr->setViewport(q_ptr->viewport());
+ other.setViewport(m_viewport);
m_changeTracker.viewportChanged = false;
other.m_changeTracker.viewportChanged = false;
}
+ if (m_changeTracker.subViewportOrderChanged) {
+ other.q_ptr->setSecondarySubviewOnTop(q_ptr->isSecondarySubviewOnTop());
+ m_changeTracker.subViewportOrderChanged = false;
+ other.m_changeTracker.subViewportOrderChanged = false;
+ }
if (m_changeTracker.primarySubViewportChanged) {
other.q_ptr->setPrimarySubViewport(q_ptr->primarySubViewport());
m_changeTracker.primarySubViewportChanged = false;
@@ -345,6 +482,11 @@ void Q3DScenePrivate::sync(Q3DScenePrivate &other)
m_changeTracker.secondarySubViewportChanged = false;
other.m_changeTracker.secondarySubViewportChanged = false;
}
+ if (m_changeTracker.selectionQueryPositionChanged) {
+ other.q_ptr->setSelectionQueryPosition(q_ptr->selectionQueryPosition());
+ m_changeTracker.selectionQueryPositionChanged = false;
+ other.m_changeTracker.selectionQueryPositionChanged = false;
+ }
if (m_changeTracker.cameraChanged) {
m_camera->setDirty(true);
m_changeTracker.cameraChanged = false;
@@ -372,4 +514,107 @@ void Q3DScenePrivate::sync(Q3DScenePrivate &other)
}
}
+void Q3DScenePrivate::setViewport(const QRect &viewport)
+{
+ if (m_viewport != viewport) {
+ m_viewport = viewport;
+ calculateSubViewports();
+ emit needRender();
+ }
+}
+
+void Q3DScenePrivate::setViewportSize(int width, int height)
+{
+ if (m_viewport.width() != width
+ || m_viewport.height() != height) {
+ m_viewport.setWidth(width);
+ m_viewport.setHeight(height);
+ calculateSubViewports();
+ emit needRender();
+ }
+}
+
+/*!
+ * \internal
+ * Sets the size of the window being rendered to. With widget based graphs, this
+ * is equal to the size of the QWindow and is same as the bounding rectangle.
+ * With declarative graphs this is equal to the size of the QQuickWindow and
+ * can be different from the bounding rectangle.
+ */
+void Q3DScenePrivate::setWindowSize(const QSize &size)
+{
+ if (m_windowSize != size) {
+ m_windowSize = size;
+ updateGLViewport();
+ m_changeTracker.windowSizeChanged = true;
+ emit needRender();
+ }
+}
+
+QSize Q3DScenePrivate::windowSize() const
+{
+ return m_windowSize;
+}
+
+void Q3DScenePrivate::calculateSubViewports()
+{
+ // Calculates the default subviewport layout
+ const float smallerViewPortRatio = 0.2f;
+ if (m_isSlicingActive) {
+ q_ptr->setPrimarySubViewport(QRect(0,
+ 0,
+ m_viewport.width() * smallerViewPortRatio,
+ m_viewport.height() * smallerViewPortRatio));
+ q_ptr->setSecondarySubViewport(QRect(0, 0, m_viewport.width(), m_viewport.height()));
+ } else {
+ q_ptr->setPrimarySubViewport(QRect(0, 0, m_viewport.width(), m_viewport.height()));
+ q_ptr->setSecondarySubViewport(QRect(0, 0, 0, 0));
+ }
+
+ updateGLViewport();
+}
+
+void Q3DScenePrivate::updateGLViewport()
+{
+ // Update GL viewport
+ m_glViewport.setX(m_viewport.x() * m_devicePixelRatio);
+ m_glViewport.setY((m_windowSize.height() - (m_viewport.y() + m_viewport.height())) * m_devicePixelRatio);
+ m_glViewport.setWidth(m_viewport.width() * m_devicePixelRatio);
+ m_glViewport.setHeight(m_viewport.height() * m_devicePixelRatio);
+
+ m_changeTracker.viewportChanged = true;
+
+ // Do default subviewport changes first, then allow signal listeners to override.
+ updateGLSubViewports();
+ emit q_ptr->viewportChanged(m_viewport);
+}
+
+void Q3DScenePrivate::updateGLSubViewports()
+{
+ m_glPrimarySubViewport.setX((m_primarySubViewport.x() + m_viewport.x()) * m_devicePixelRatio);
+ m_glPrimarySubViewport.setY((m_windowSize.height() - (m_primarySubViewport.y() + m_viewport.y() + m_primarySubViewport.height())) * m_devicePixelRatio);
+ m_glPrimarySubViewport.setWidth(m_primarySubViewport.width() * m_devicePixelRatio);
+ m_glPrimarySubViewport.setHeight(m_primarySubViewport.height() * m_devicePixelRatio);
+
+ m_glSecondarySubViewport.setX(m_secondarySubViewport.x() * m_devicePixelRatio);
+ m_glSecondarySubViewport.setY((m_windowSize.height() - (m_secondarySubViewport.y() + m_viewport.y() + m_secondarySubViewport.height())) * m_devicePixelRatio);
+ m_glSecondarySubViewport.setWidth(m_secondarySubViewport.width() * m_devicePixelRatio);
+ m_glSecondarySubViewport.setHeight(m_secondarySubViewport.height() * m_devicePixelRatio);
+}
+
+QRect Q3DScenePrivate::glViewport()
+{
+ return m_glViewport;
+}
+
+QRect Q3DScenePrivate::glPrimarySubViewport()
+{
+ return m_glPrimarySubViewport;
+}
+
+QRect Q3DScenePrivate::glSecondarySubViewport()
+{
+ return m_glSecondarySubViewport;
+}
+
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/q3dscene.h b/src/datavisualization/engine/q3dscene.h
index 745cef72..b0dadff9 100644
--- a/src/datavisualization/engine/q3dscene.h
+++ b/src/datavisualization/engine/q3dscene.h
@@ -33,21 +33,21 @@ class Q3DScenePrivate;
class QT_DATAVISUALIZATION_EXPORT Q3DScene : public QObject
{
Q_OBJECT
- Q_PROPERTY(QRect viewport READ viewport WRITE setViewport NOTIFY viewportChanged)
+ Q_PROPERTY(QRect viewport READ viewport NOTIFY viewportChanged)
Q_PROPERTY(QRect primarySubViewport READ primarySubViewport WRITE setPrimarySubViewport NOTIFY primarySubViewportChanged)
Q_PROPERTY(QRect secondarySubViewport READ secondarySubViewport WRITE setSecondarySubViewport NOTIFY secondarySubViewportChanged)
+ Q_PROPERTY(QPoint selectionQueryPosition READ selectionQueryPosition WRITE setSelectionQueryPosition NOTIFY selectionQueryPositionChanged)
+ Q_PROPERTY(bool secondarySubviewOnTop READ isSecondarySubviewOnTop WRITE setSecondarySubviewOnTop NOTIFY secondarySubviewOnTopChanged)
Q_PROPERTY(bool slicingActive READ isSlicingActive WRITE setSlicingActive NOTIFY slicingActiveChanged)
Q_PROPERTY(Q3DCamera* activeCamera READ activeCamera WRITE setActiveCamera NOTIFY activeCameraChanged)
Q_PROPERTY(Q3DLight* activeLight READ activeLight WRITE setActiveLight NOTIFY activeLightChanged)
- Q_PROPERTY(qreal devicePixelRatio READ devicePixelRatio WRITE setDevicePixelRatio NOTIFY devicePixelRatioChanged)
+ Q_PROPERTY(float devicePixelRatio READ devicePixelRatio WRITE setDevicePixelRatio NOTIFY devicePixelRatioChanged)
public:
Q3DScene(QObject *parent = 0);
~Q3DScene();
QRect viewport() const;
- void setViewport(const QRect &viewport);
- void setViewportSize(int width, int height);
QRect primarySubViewport() const;
void setPrimarySubViewport(const QRect &primarySubViewport);
@@ -57,39 +57,47 @@ public:
void setSecondarySubViewport(const QRect &secondarySubViewport);
bool isPointInSecondarySubView(const QPoint &point);
+ void setSelectionQueryPosition(const QPoint &point);
+ QPoint selectionQueryPosition() const;
+ static const QPoint invalidSelectionPoint();
+
void setSlicingActive(bool isSlicing);
bool isSlicingActive() const;
+ void setSecondarySubviewOnTop(bool isSecondaryOnTop);
+ bool isSecondarySubviewOnTop() const;
+
Q3DCamera *activeCamera() const;
void setActiveCamera(Q3DCamera *camera);
Q3DLight *activeLight() const;
void setActiveLight(Q3DLight *light);
- qreal devicePixelRatio() const;
- void setDevicePixelRatio(qreal pixelRatio);
-
- void setLightPositionRelativeToCamera(const QVector3D &relativePosition,
- qreal fixedRotation = 0.0,
- qreal distanceModifier = 0.0);
-private:
- void emitNeedRender();
+ float devicePixelRatio() const;
+ void setDevicePixelRatio(float pixelRatio);
+ Q_INVOKABLE void setLightPositionRelativeToCamera(const QVector3D &relativePosition,
+ float fixedRotation = 0.0f,
+ float distanceModifier = 0.0f);
signals:
void viewportChanged(QRect viewport);
void primarySubViewportChanged(QRect subViewport);
void secondarySubViewportChanged(QRect subViewport);
+ void secondarySubviewOnTopChanged(bool isSecondaryOnTop);
void slicingActiveChanged(bool isSlicingActive);
void activeCameraChanged(const Q3DCamera *camera);
void activeLightChanged(const Q3DLight *light);
- void devicePixelRatioChanged(qreal pixelRatio);
- void needRender();
+ void devicePixelRatioChanged(float pixelRatio);
+ void selectionQueryPositionChanged(const QPoint position);
private:
QScopedPointer<Q3DScenePrivate> d_ptr;
Q_DISABLE_COPY(Q3DScene)
+ friend class AbstractDeclarative;
+ friend class Q3DWindow;
+ friend class Abstract3DController;
friend class Q3DScenePrivate;
friend class Abstract3DRenderer;
friend class Bars3DRenderer;
diff --git a/src/datavisualization/engine/q3dscene_p.h b/src/datavisualization/engine/q3dscene_p.h
index b28baaae..c9d9d1f6 100644
--- a/src/datavisualization/engine/q3dscene_p.h
+++ b/src/datavisualization/engine/q3dscene_p.h
@@ -42,42 +42,71 @@ struct Q3DSceneChangeBitField {
bool viewportChanged : 1;
bool primarySubViewportChanged : 1;
bool secondarySubViewportChanged : 1;
+ bool subViewportOrderChanged : 1;
bool cameraChanged : 1;
bool lightChanged : 1;
bool slicingActivatedChanged : 1;
bool devicePixelRatioChanged : 1;
+ bool selectionQueryPositionChanged : 1;
+ bool windowSizeChanged : 1;
Q3DSceneChangeBitField()
: viewportChanged(true),
primarySubViewportChanged(true),
secondarySubViewportChanged(true),
+ subViewportOrderChanged(true),
cameraChanged(true),
lightChanged(true),
slicingActivatedChanged(true),
- devicePixelRatioChanged(true)
+ devicePixelRatioChanged(true),
+ selectionQueryPositionChanged(false),
+ windowSizeChanged(true)
{
}
};
-class Q3DScenePrivate
+class QT_DATAVISUALIZATION_EXPORT Q3DScenePrivate : public QObject
{
+ Q_OBJECT
public:
Q3DScenePrivate(Q3DScene *q);
~Q3DScenePrivate();
void sync(Q3DScenePrivate &other);
+ void setViewport(const QRect &viewport);
+ void setViewportSize(int width, int height);
+ void setWindowSize(const QSize &size);
+ QSize windowSize() const;
+ void calculateSubViewports();
+ void updateGLViewport();
+ void updateGLSubViewports();
+
+ QRect glViewport();
+ QRect glPrimarySubViewport();
+ QRect glSecondarySubViewport();
+
+signals:
+ void needRender();
+
+public:
Q3DScene *q_ptr;
Q3DSceneChangeBitField m_changeTracker;
QRect m_viewport;
QRect m_primarySubViewport;
QRect m_secondarySubViewport;
- qreal m_devicePixelRatio;
+ bool m_isSecondarySubviewOnTop;
+ float m_devicePixelRatio;
Q3DCamera *m_camera;
Q3DLight *m_light;
bool m_isUnderSideCameraEnabled;
bool m_isSlicingActive;
+ QPoint m_selectionQueryPosition;
+ QSize m_windowSize;
+ QRect m_glViewport;
+ QRect m_glPrimarySubViewport;
+ QRect m_glSecondarySubViewport;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/q3dsurface.cpp b/src/datavisualization/engine/q3dsurface.cpp
index 42260e8b..ce738685 100644
--- a/src/datavisualization/engine/q3dsurface.cpp
+++ b/src/datavisualization/engine/q3dsurface.cpp
@@ -21,6 +21,7 @@
#include "q3dvalueaxis.h"
#include "qsurfacedataproxy.h"
#include "q3dcamera.h"
+#include "qsurface3dseries_p.h"
#include <QMouseEvent>
@@ -33,17 +34,15 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
* \since Qt Data Visualization 1.0
*
* This class enables developers to render 3D surface plots and to view them by rotating the scene
- * freely. The class provides configurable gradient texture to illustrate the height on the data. The
- * surface plotting includes also gridline that can be set on or off. The visual appearance of the
- * surface can be changed by controlling the smooth status.
+ * freely. The surface plotting includes also gridline that can be set on or off.
+ * The visual appearance of the surface can be changed by controlling the smooth status.
*
* The Q3DSurface supports selection by showing a highlighted ball on the data point where the user has clicked
- * with left mouse button (when default input handler is in use). The selection pointer is accompanied with
- * a label which in default case shows the value of the data point and the coordinates of the point.
+ * with left mouse button (when default input handler is in use) or selected via QSurface3DSeries.
+ * The selection pointer is accompanied with a label which in default case shows the value of the
+ * data point and the coordinates of the point.
*
* The value range and the label format shown on the axis can be controlled through Q3DValueAxis.
- * The Q3DSurface supports only a grid with fixed steps, so when setting ranges set a value that matches
- * the grid step. To calculate the steps divide the whole data range with the number of segments.
*
* To rotate the graph, hold down the right mouse button and move the mouse. Zooming is done using mouse
* wheel. Both assume the default input handler is in use.
@@ -52,13 +51,13 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
* These default axes can be modified via axis accessors, but as soon any axis is set explicitly
* for the orientation, the default axis for that orientation is destroyed.
*
- * Data proxies work similarly: if no data proxy is set explicitly, Q3DSurface creates a default
- * proxy. If any other proxy is set as active data proxy later, the default proxy and all data
- * added to it is destroyed.
+ * Q3DSurface supports only single series at a time.
*
* \section1 How to construct a minimal Q3DSurface graph
*
- * First, construct Q3DSurface:
+ * First, construct Q3DSurface. Since we are running the graph as top level window
+ * in this example, we need to clear the \c Qt::FramelessWindowHint flag, which gets set by
+ * default:
*
* \snippet doc_src_q3dsurface_construction.cpp 0
*
@@ -70,7 +69,7 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*
* \snippet doc_src_q3dsurface_construction.cpp 2
*
- * For the active data proxy set pointer of the data element:
+ * Create a new series and set data to it:
*
* \snippet doc_src_q3dsurface_construction.cpp 3
*
@@ -94,129 +93,132 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*/
/*!
- * Constructs a new 3D surface window.
+ * Constructs a new 3D surface graph with optional \a parent window.
*/
-Q3DSurface::Q3DSurface()
- : d_ptr(new Q3DSurfacePrivate(this, geometry()))
+Q3DSurface::Q3DSurface(QWindow *parent)
+ : Q3DWindow(new Q3DSurfacePrivate(this), parent)
{
- setVisualController(d_ptr->m_shared);
- d_ptr->m_shared->initializeOpenGL();
- QObject::connect(d_ptr->m_shared, &Abstract3DController::needRender, this,
- &Q3DWindow::renderLater);
+ dptr()->m_shared = new Surface3DController(geometry());
+ d_ptr->setVisualController(dptr()->m_shared);
+ dptr()->m_shared->initializeOpenGL();
+ QObject::connect(dptr()->m_shared, &Abstract3DController::selectionModeChanged, this,
+ &Q3DSurface::selectionModeChanged);
+ QObject::connect(dptr()->m_shared, &Abstract3DController::themeChanged, this,
+ &Q3DSurface::themeChanged);
+ QObject::connect(dptr()->m_shared, &Abstract3DController::shadowQualityChanged, this,
+ &Q3DSurface::shadowQualityChanged);
+ QObject::connect(dptr()->m_shared, &Abstract3DController::needRender, d_ptr.data(),
+ &Q3DWindowPrivate::renderLater);
}
/*!
- * Destroys the 3D surface window.
+ * Destroys the 3D surface graph.
*/
Q3DSurface::~Q3DSurface()
{
}
/*!
- * \internal
+ * Adds the \a series to the graph.
+ *
+ * \note The surface graph currently supports only a single series at a time.
*/
-void Q3DSurface::mouseDoubleClickEvent(QMouseEvent *event)
+void Q3DSurface::addSeries(QSurface3DSeries *series)
{
- d_ptr->m_shared->mouseDoubleClickEvent(event);
+ dptr()->m_shared->addSeries(series);
}
/*!
- * \internal
+ * Removes the \a series from the graph.
*/
-void Q3DSurface::touchEvent(QTouchEvent *event)
+void Q3DSurface::removeSeries(QSurface3DSeries *series)
{
- d_ptr->m_shared->touchEvent(event);
+ dptr()->m_shared->removeSeries(series);
}
/*!
- * \internal
+ * \return list of series added to this graph.
+ *
+ * \note The surface graph currently supports only a single series at a time.
*/
-void Q3DSurface::mousePressEvent(QMouseEvent *event)
+QList<QSurface3DSeries *> Q3DSurface::seriesList()
{
- d_ptr->m_shared->mousePressEvent(event, event->pos());
+ return dptr()->m_shared->surfaceSeriesList();
}
/*!
* \internal
*/
-void Q3DSurface::mouseReleaseEvent(QMouseEvent *event)
+void Q3DSurface::mouseDoubleClickEvent(QMouseEvent *event)
{
- d_ptr->m_shared->mouseReleaseEvent(event, event->pos());
+ dptr()->m_shared->mouseDoubleClickEvent(event);
}
/*!
* \internal
*/
-void Q3DSurface::mouseMoveEvent(QMouseEvent *event)
+void Q3DSurface::touchEvent(QTouchEvent *event)
{
- d_ptr->m_shared->mouseMoveEvent(event, event->pos());
+ dptr()->m_shared->touchEvent(event);
}
/*!
* \internal
*/
-void Q3DSurface::wheelEvent(QWheelEvent *event)
+void Q3DSurface::mousePressEvent(QMouseEvent *event)
{
- d_ptr->m_shared->wheelEvent(event);
+ dptr()->m_shared->mousePressEvent(event, event->pos());
}
/*!
* \internal
*/
-void Q3DSurface::resizeEvent(QResizeEvent *event)
+void Q3DSurface::mouseReleaseEvent(QMouseEvent *event)
{
- Q_UNUSED(event);
- d_ptr->m_shared->setWidth(width());
- d_ptr->m_shared->setHeight(height());
+ dptr()->m_shared->mouseReleaseEvent(event, event->pos());
}
/*!
- * \property Q3DSurface::gridVisible
- *
- * Sets grid visibility to \a visible. It is preset to \c true by default.
+ * \internal
*/
-void Q3DSurface::setGridVisible(bool visible)
+void Q3DSurface::mouseMoveEvent(QMouseEvent *event)
{
- d_ptr->m_shared->setGridEnabled(visible);
+ dptr()->m_shared->mouseMoveEvent(event, event->pos());
}
-bool Q3DSurface::isGridVisible() const
+/*!
+ * \internal
+ */
+void Q3DSurface::wheelEvent(QWheelEvent *event)
{
- return d_ptr->m_shared->gridEnabled();
+ dptr()->m_shared->wheelEvent(event);
}
-/*!
- * \property Q3DSurface::backgroundVisible
- *
- * Sets background visibility to \a visible. It is preset to \c true by default.
- */
-void Q3DSurface::setBackgroundVisible(bool visible)
+Q3DSurfacePrivate *Q3DSurface::dptr()
{
- d_ptr->m_shared->setBackgroundEnabled(visible);
+ return static_cast<Q3DSurfacePrivate *>(d_ptr.data());
}
-bool Q3DSurface::isBackgroundVisible() const
+const Q3DSurfacePrivate *Q3DSurface::dptrc() const
{
- return d_ptr->m_shared->backgroundEnabled();
+ return static_cast<const Q3DSurfacePrivate *>(d_ptr.data());
}
/*!
* \property Q3DSurface::theme
*
- * A predefined \a theme from \c QDataVis::Theme. It is preset to \c QDataVis::ThemeQt by
- * default. Theme affects label colors, text color, background color, window color and
- * grid color. Lighting is also adjusted by themes.
- *
- * \preliminary
+ * A \a theme to be used for the graph. Ownership of the \a theme is transferred. Previous theme
+ * is deleted when a new one is set. Properties of the \a theme can be modified even after setting
+ * it, and the modifications take effect immediately.
*/
-void Q3DSurface::setTheme(QDataVis::Theme theme)
+void Q3DSurface::setTheme(Q3DTheme *theme)
{
- d_ptr->m_shared->setTheme(theme);
+ dptr()->m_shared->setTheme(theme);
}
-QDataVis::Theme Q3DSurface::theme() const
+Q3DTheme *Q3DSurface::theme() const
{
- return d_ptr->m_shared->theme().theme();
+ return dptrc()->m_shared->theme();
}
/*!
@@ -231,93 +233,29 @@ QDataVis::Theme Q3DSurface::theme() const
*/
void Q3DSurface::setShadowQuality(QDataVis::ShadowQuality quality)
{
- return d_ptr->m_shared->setShadowQuality(quality);
+ return dptr()->m_shared->setShadowQuality(quality);
}
QDataVis::ShadowQuality Q3DSurface::shadowQuality() const
{
- return d_ptr->m_shared->shadowQuality();
-}
-
-/*!
- * \property Q3DSurface::smoothSurfaceEnabled
- *
- * Sets surface smoothing to \a enabled. It is preset to \c false by default.
- * When enabled the normals on the surface are interpolated making edges looking round. If turned
- * off the normals are kept same on a triangle making the color of the triangle solid. This makes
- * the data more readable from the model.
- */
-void Q3DSurface::setSmoothSurfaceEnabled(bool enabled)
-{
- d_ptr->m_shared->setSmoothSurface(enabled);
-}
-
-bool Q3DSurface::isSmoothSurfaceEnabled() const
-{
- return d_ptr->m_shared->smoothSurface();
+ return dptrc()->m_shared->shadowQuality();
}
/*!
* \property Q3DSurface::selectionMode
*
- * Sets point selection \a mode to one of \c QDataVis::SelectionMode. Surface supports SelectionModeItem,
- * SelectionModeSliceRow and SelectionModeSliceColumn. It is preset to \c QDataVis::SelectionModeItem by default.
- */
-void Q3DSurface::setSelectionMode(QDataVis::SelectionMode mode)
-{
- d_ptr->m_shared->setSelectionMode(mode);
-}
-
-QDataVis::SelectionMode Q3DSurface::selectionMode() const
-{
- return d_ptr->m_shared->selectionMode();
-}
-
-
-/*!
- * \property Q3DSurface::surfaceGridEnabled
- *
- * Sets surface grid to \a enabled. It is preset to \c true by default.
- */
-void Q3DSurface::setSurfaceGridEnabled(bool enabled)
-{
- d_ptr->m_shared->setSurfaceGrid(enabled);
-}
-
-bool Q3DSurface::isSurfaceGridEnabled() const
-{
- return d_ptr->m_shared->surfaceGrid();
-}
-
-/*!
- * \property Q3DSurface::gradient
- *
- * The current surface gradient. Setting this property replaces the previous gradient with
- * the given \a gradient.
- */
-void Q3DSurface::setGradient(const QLinearGradient &gradient)
-{
- d_ptr->m_shared->setGradient(gradient);
-}
-
-QLinearGradient Q3DSurface::gradient() const
-{
- return d_ptr->m_shared->gradient();
-}
-
-/*!
- * \property Q3DSurface::font
- *
- * Sets the \a font for labels. It is preset to \c Arial by default.
+ * Sets point selection \a mode to a combination of \c QDataVis::SelectionFlags. Surface supports
+ * \c SelectionItem and \c SelectionSlice with either \c SelectionRow or \c SelectionColumn.
+ * It is preset to \c SelectionItem by default.
*/
-void Q3DSurface::setFont(const QFont &font)
+void Q3DSurface::setSelectionMode(QDataVis::SelectionFlags mode)
{
- d_ptr->m_shared->setFont(font);
+ dptr()->m_shared->setSelectionMode(mode);
}
-QFont Q3DSurface::font() const
+QDataVis::SelectionFlags Q3DSurface::selectionMode() const
{
- return d_ptr->m_shared->font();
+ return dptrc()->m_shared->selectionMode();
}
/*!
@@ -327,23 +265,7 @@ QFont Q3DSurface::font() const
*/
Q3DScene *Q3DSurface::scene() const
{
- return d_ptr->m_shared->scene();
-}
-
-/*!
- * \property Q3DSurface::labelStyle
- *
- * Sets label \a style to one of \c QDataVis::LabelStyle. It is preset to
- * \c QDataVis::LabelStyleFromTheme by default.
- */
-void Q3DSurface::setLabelStyle(QDataVis::LabelStyle style)
-{
- d_ptr->m_shared->setLabelStyle(style);
-}
-
-QDataVis::LabelStyle Q3DSurface::labelStyle() const
-{
- return d_ptr->m_shared->labelStyle();
+ return dptrc()->m_shared->scene();
}
/*!
@@ -358,7 +280,7 @@ QDataVis::LabelStyle Q3DSurface::labelStyle() const
*/
void Q3DSurface::setAxisX(Q3DValueAxis *axis)
{
- d_ptr->m_shared->setAxisX(axis);
+ dptr()->m_shared->setAxisX(axis);
}
/*!
@@ -366,7 +288,7 @@ void Q3DSurface::setAxisX(Q3DValueAxis *axis)
*/
Q3DValueAxis *Q3DSurface::axisX() const
{
- return static_cast<Q3DValueAxis *>(d_ptr->m_shared->axisX());
+ return static_cast<Q3DValueAxis *>(dptrc()->m_shared->axisX());
}
/*!
@@ -381,7 +303,7 @@ Q3DValueAxis *Q3DSurface::axisX() const
*/
void Q3DSurface::setAxisY(Q3DValueAxis *axis)
{
- d_ptr->m_shared->setAxisY(axis);
+ dptr()->m_shared->setAxisY(axis);
}
/*!
@@ -389,7 +311,7 @@ void Q3DSurface::setAxisY(Q3DValueAxis *axis)
*/
Q3DValueAxis *Q3DSurface::axisY() const
{
- return static_cast<Q3DValueAxis *>(d_ptr->m_shared->axisY());
+ return static_cast<Q3DValueAxis *>(dptrc()->m_shared->axisY());
}
/*!
@@ -404,7 +326,7 @@ Q3DValueAxis *Q3DSurface::axisY() const
*/
void Q3DSurface::setAxisZ(Q3DValueAxis *axis)
{
- d_ptr->m_shared->setAxisZ(axis);
+ dptr()->m_shared->setAxisZ(axis);
}
/*!
@@ -412,7 +334,7 @@ void Q3DSurface::setAxisZ(Q3DValueAxis *axis)
*/
Q3DValueAxis *Q3DSurface::axisZ() const
{
- return static_cast<Q3DValueAxis *>(d_ptr->m_shared->axisZ());
+ return static_cast<Q3DValueAxis *>(dptrc()->m_shared->axisZ());
}
/*!
@@ -424,7 +346,7 @@ Q3DValueAxis *Q3DSurface::axisZ() const
*/
void Q3DSurface::addAxis(Q3DValueAxis *axis)
{
- d_ptr->m_shared->addAxis(axis);
+ dptr()->m_shared->addAxis(axis);
}
/*!
@@ -437,7 +359,7 @@ void Q3DSurface::addAxis(Q3DValueAxis *axis)
*/
void Q3DSurface::releaseAxis(Q3DValueAxis *axis)
{
- d_ptr->m_shared->releaseAxis(axis);
+ dptr()->m_shared->releaseAxis(axis);
}
/*!
@@ -447,7 +369,7 @@ void Q3DSurface::releaseAxis(Q3DValueAxis *axis)
*/
QList<Q3DValueAxis *> Q3DSurface::axes() const
{
- QList<Q3DAbstractAxis *> abstractAxes = d_ptr->m_shared->axes();
+ QList<Q3DAbstractAxis *> abstractAxes = dptrc()->m_shared->axes();
QList<Q3DValueAxis *> retList;
foreach (Q3DAbstractAxis *axis, abstractAxes)
retList.append(static_cast<Q3DValueAxis *>(axis));
@@ -455,82 +377,10 @@ QList<Q3DValueAxis *> Q3DSurface::axes() const
return retList;
}
-/*!
- * Sets the active data \a proxy. Implicitly calls addDataProxy() to transfer ownership of
- * the \a proxy to this graph.
- *
- * If the \a proxy is null, a temporary default proxy is created and activated.
- * This temporary proxy is destroyed if another \a proxy is set explicitly active via this method.
- *
- * \sa addDataProxy(), releaseDataProxy()
- */
-void Q3DSurface::setActiveDataProxy(QSurfaceDataProxy *proxy)
-{
- d_ptr->m_shared->setActiveDataProxy(proxy);
-}
-
-/*!
- * \return active data proxy.
- */
-QSurfaceDataProxy *Q3DSurface::activeDataProxy() const
-{
- return static_cast<QSurfaceDataProxy *>(d_ptr->m_shared->activeDataProxy());
-}
-
-/*!
- * Adds data \a proxy to the graph. The proxies added via addDataProxy are not yet taken to use,
- * addDataProxy is simply used to give the ownership of the data \a proxy to the graph.
- * The \a proxy must not be null or added to another graph.
- *
- * \sa releaseDataProxy(), setActiveDataProxy()
- */
-void Q3DSurface::addDataProxy(QSurfaceDataProxy *proxy)
-{
- d_ptr->m_shared->addDataProxy(proxy);
-}
-
-/*!
- * Releases the ownership of the data \a proxy back to the caller, if it is added to this graph.
- * If the released \a proxy is in use, a new empty default proxy is created and taken to use.
- *
- * If the default \a proxy is released and added back later, it behaves as any other proxy would.
- *
- * \sa addDataProxy(), setActiveDataProxy()
- */
-void Q3DSurface::releaseDataProxy(QSurfaceDataProxy *proxy)
-{
- d_ptr->m_shared->releaseDataProxy(proxy);
-}
-
-/*!
- * \return list of all added data proxies.
- *
- * \sa addDataProxy()
- */
-QList<QSurfaceDataProxy *> Q3DSurface::dataProxies() const
-{
- QList<QSurfaceDataProxy *> retList;
- QList<QAbstractDataProxy *> abstractList = d_ptr->m_shared->dataProxies();
- foreach (QAbstractDataProxy *proxy, abstractList)
- retList.append(static_cast<QSurfaceDataProxy *>(proxy));
-
- return retList;
-}
-
-
-/*!
- * Modifies the current surface gradient. Sets gradient color to \a color at \a pos.
- */
-void Q3DSurface::setGradientColorAt(qreal pos, const QColor &color)
-{
- d_ptr->m_shared->setGradientColorAt(pos, color);
-}
-
/////////////////// PRIVATE ///////////////////////////////////
-Q3DSurfacePrivate::Q3DSurfacePrivate(Q3DSurface *q, QRect rect)
- : q_ptr(q),
- m_shared(new Surface3DController(rect))
+Q3DSurfacePrivate::Q3DSurfacePrivate(Q3DSurface *q)
+ : Q3DWindowPrivate(q)
{
}
@@ -539,4 +389,9 @@ Q3DSurfacePrivate::~Q3DSurfacePrivate()
delete m_shared;
}
+Q3DSurface *Q3DSurfacePrivate::qptr()
+{
+ return static_cast<Q3DSurface *>(q_ptr);
+}
+
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/q3dsurface.h b/src/datavisualization/engine/q3dsurface.h
index 1b572a36..bdbe65f5 100644
--- a/src/datavisualization/engine/q3dsurface.h
+++ b/src/datavisualization/engine/q3dsurface.h
@@ -23,61 +23,38 @@
#include <QtDataVisualization/q3dwindow.h>
#include <QtDataVisualization/q3dscene.h>
#include <QFont>
-#include <QLinearGradient>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class Q3DSurfacePrivate;
class Q3DValueAxis;
-class QSurfaceDataProxy;
+class QSurface3DSeries;
+class Q3DTheme;
class QT_DATAVISUALIZATION_EXPORT Q3DSurface : public Q3DWindow
{
Q_OBJECT
- Q_PROPERTY(QtDataVisualization::QDataVis::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode)
- Q_PROPERTY(QtDataVisualization::QDataVis::LabelStyle labelStyle READ labelStyle WRITE setLabelStyle)
- Q_PROPERTY(QtDataVisualization::QDataVis::Theme theme READ theme WRITE setTheme)
- Q_PROPERTY(QtDataVisualization::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality)
- Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible)
- Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible)
- Q_PROPERTY(bool smoothSurfaceEnabled READ isSmoothSurfaceEnabled WRITE setSmoothSurfaceEnabled)
- Q_PROPERTY(bool surfaceGridEnabled READ isSurfaceGridEnabled WRITE setSurfaceGridEnabled)
- Q_PROPERTY(QLinearGradient gradient READ gradient WRITE setGradient)
- Q_PROPERTY(QFont font READ font WRITE setFont)
+ Q_PROPERTY(QtDataVisualization::QDataVis::SelectionFlags selectionMode READ selectionMode WRITE setSelectionMode NOTIFY selectionModeChanged)
+ Q_PROPERTY(Q3DTheme* theme READ theme WRITE setTheme NOTIFY themeChanged)
+ Q_PROPERTY(QtDataVisualization::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality NOTIFY shadowQualityChanged)
Q_PROPERTY(Q3DScene* scene READ scene)
- Q_ENUMS(QtDataVisualization::QDataVis::SelectionMode)
- Q_ENUMS(QtDataVisualization::QDataVis::ShadowQuality)
- Q_ENUMS(QtDataVisualization::QDataVis::LabelStyle)
- Q_ENUMS(QtDataVisualization::QDataVis::CameraPreset)
public:
- explicit Q3DSurface();
- ~Q3DSurface();
+ explicit Q3DSurface(QWindow *parent = 0);
+ virtual ~Q3DSurface();
- void setGridVisible(bool visible);
- bool isGridVisible() const;
+ void addSeries(QSurface3DSeries *series);
+ void removeSeries(QSurface3DSeries *series);
+ QList<QSurface3DSeries *> seriesList();
- void setBackgroundVisible(bool visible);
- bool isBackgroundVisible() const;
-
- void setTheme(QDataVis::Theme theme);
- QDataVis::Theme theme() const;
+ void setTheme(Q3DTheme *theme);
+ Q3DTheme *theme() const;
void setShadowQuality(QDataVis::ShadowQuality quality);
QDataVis::ShadowQuality shadowQuality() const;
- void setSmoothSurfaceEnabled(bool enabled);
- bool isSmoothSurfaceEnabled() const;
-
- void setSelectionMode(QDataVis::SelectionMode mode);
- QDataVis::SelectionMode selectionMode() const;
- void setSurfaceGridEnabled(bool enabled);
- bool isSurfaceGridEnabled() const;
-
- void setGradient(const QLinearGradient &gradient);
- QLinearGradient gradient() const;
-
- void setGradientColorAt(qreal pos, const QColor &color);
+ void setSelectionMode(QDataVis::SelectionFlags mode);
+ QDataVis::SelectionFlags selectionMode() const;
// Axes
void setAxisX(Q3DValueAxis *axis);
@@ -90,19 +67,12 @@ public:
void releaseAxis(Q3DValueAxis *axis);
QList<Q3DValueAxis *> axes() const;
- void setActiveDataProxy(QSurfaceDataProxy *proxy);
- QSurfaceDataProxy *activeDataProxy() const;
- void addDataProxy(QSurfaceDataProxy *proxy);
- void releaseDataProxy(QSurfaceDataProxy *proxy);
- QList<QSurfaceDataProxy *> dataProxies() const;
-
- void setFont(const QFont &font);
- QFont font() const;
-
Q3DScene *scene() const;
- void setLabelStyle(QDataVis::LabelStyle style);
- QDataVis::LabelStyle labelStyle() const;
+signals:
+ void selectionModeChanged(QDataVis::SelectionFlags mode);
+ void themeChanged(Q3DTheme *theme);
+ void shadowQualityChanged(QDataVis::ShadowQuality quality);
protected:
void mouseDoubleClickEvent(QMouseEvent *event);
@@ -111,10 +81,10 @@ protected:
void mouseReleaseEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void wheelEvent(QWheelEvent *event);
- void resizeEvent(QResizeEvent *event);
private:
- QScopedPointer<Q3DSurfacePrivate> d_ptr;
+ Q3DSurfacePrivate *dptr();
+ const Q3DSurfacePrivate *dptrc() const;
Q_DISABLE_COPY(Q3DSurface)
};
diff --git a/src/datavisualization/engine/q3dsurface_p.h b/src/datavisualization/engine/q3dsurface_p.h
index 7c70d08c..de2a518c 100644
--- a/src/datavisualization/engine/q3dsurface_p.h
+++ b/src/datavisualization/engine/q3dsurface_p.h
@@ -31,6 +31,7 @@
#include "surface3dcontroller_p.h"
#include "qdatavisualizationenums.h"
+#include "q3dwindow_p.h"
#include <QList>
@@ -38,13 +39,15 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class Q3DSurface;
-class Q3DSurfacePrivate : public QObject
+class Q3DSurfacePrivate : public Q3DWindowPrivate
{
+ Q_OBJECT
public:
- Q3DSurfacePrivate(Q3DSurface *q, QRect rect);
+ Q3DSurfacePrivate(Q3DSurface *q);
~Q3DSurfacePrivate();
- Q3DSurface *q_ptr;
+ Q3DSurface *qptr();
+
Surface3DController *m_shared;
};
diff --git a/src/datavisualization/engine/q3dwindow.cpp b/src/datavisualization/engine/q3dwindow.cpp
index 2c0729ba..5285b585 100644
--- a/src/datavisualization/engine/q3dwindow.cpp
+++ b/src/datavisualization/engine/q3dwindow.cpp
@@ -19,13 +19,14 @@
#include "q3dwindow.h"
#include "q3dwindow_p.h"
#include "abstract3dcontroller_p.h"
-#include <QGuiApplication>
+#include "qabstract3dinputhandler_p.h"
+#include "q3dscene_p.h"
+#include <QGuiApplication>
#include <QOpenGLContext>
#include <QOpenGLPaintDevice>
#include <QPainter>
-#include <QDebug>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
@@ -36,19 +37,31 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
* \since Qt Data Visualization 1.0
*
* This class creates a QWindow and provides render loop for visualization types inheriting it.
- * \warning This class is not intended to be used directly by developers.
+ *
+ * You should not need to use this class directly, but one of its subclasses instead.
+ *
+ * \note Q3DWindow sets window flag \c{Qt::FramelessWindowHint} on by default. If you want to display
+ * graph windows as standalone windows with regular window frame, clear this flag after constructing
+ * the graph. For example:
+ *
+ * \code
+ * Q3DBars *graphWindow = new Q3DBars;
+ * graphWindow->setFlags(graphWindow->flags() ^ Qt::FramelessWindowHint);
+ * \endcode
*
* \sa Q3DBars, Q3DScatter, Q3DSurface, {Qt Data Visualization C++ Classes}
*/
/*!
- * Constructs Q3DWindow with \a parent. It creates a QWindow and an OpenGL context. It also sets
- * surface format and initializes OpenGL functions for use.
+ * \internal
*/
-Q3DWindow::Q3DWindow(QWindow *parent)
+Q3DWindow::Q3DWindow(Q3DWindowPrivate *d, QWindow *parent)
: QWindow(parent),
- d_ptr(new Q3DWindowPrivate(this))
+ d_ptr(d)
{
+ d_ptr->m_context = new QOpenGLContext(this);
+
+ setFlags(flags() | Qt::FramelessWindowHint);
setSurfaceType(QWindow::OpenGLSurface);
QSurfaceFormat surfaceFormat;
surfaceFormat.setDepthBufferSize(24);
@@ -67,7 +80,6 @@ Q3DWindow::Q3DWindow(QWindow *parent)
d_ptr->m_context->create();
d_ptr->m_context->makeCurrent(this);
- qDebug() << "initializeOpenGLFunctions()";
initializeOpenGLFunctions();
const GLubyte *version = glGetString(GL_VERSION);
@@ -80,7 +92,7 @@ Q3DWindow::Q3DWindow(QWindow *parent)
if (splitversionstr[0].toFloat() < 1.2)
qFatal("GLSL version must be 1.20 or higher. Try installing latest display drivers.");
#endif
- renderLater();
+ d_ptr->renderLater();
}
/*!
@@ -91,46 +103,49 @@ Q3DWindow::~Q3DWindow()
}
/*!
- * \internal
+ * Adds the given \a inputHandler to the graph. The input handlers added via addInputHandler
+ * are not taken in to use directly. Only the ownership of the a\ inputHandler is given to the graph.
+ * The \a inputHandler must not be null or already added to another graph.
+ *
+ * \sa releaseInputHandler(), setActiveInputHandler()
*/
-void Q3DWindow::setVisualController(Abstract3DController *controller)
+void Q3DWindow::addInputHandler(QAbstract3DInputHandler *inputHandler)
{
- d_ptr->m_visualController = controller;
+ d_ptr->m_visualController->addInputHandler(inputHandler);
}
/*!
- * \internal
+ * Releases the ownership of the \a inputHandler back to the caller, if it was added to this graph.
+ * If the released \a inputHandler is in use there will be no input handler active after this call.
+ *
+ * If the default input handler is released and added back later, it behaves as any other input handler would.
+ *
+ * \sa addInputHandler(), setActiveInputHandler()
*/
-void Q3DWindow::handleDevicePixelRatioChange()
+void Q3DWindow::releaseInputHandler(QAbstract3DInputHandler *inputHandler)
{
- if (QWindow::devicePixelRatio() == d_ptr->m_devicePixelRatio || !d_ptr->m_visualController)
- return;
-
- // Device pixel ratio changed, resize accordingly and inform the scene
- d_ptr->m_devicePixelRatio = QWindow::devicePixelRatio();
- d_ptr->m_visualController->updateDevicePixelRatio(d_ptr->m_devicePixelRatio);
-
+ d_ptr->m_visualController->releaseInputHandler(inputHandler);
}
/*!
- * \internal
+ * Sets the active \a inputHandler. Implicitly calls addInputHandler() to transfer ownership of
+ * the \a inputHandler to this graph.
+ *
+ * If the \a inputHandler is null, no input handler will be active after this call.
+ *
+ * \sa addInputHandler(), releaseInputHandler()
*/
-void Q3DWindow::render()
+void Q3DWindow::setActiveInputHandler(QAbstract3DInputHandler *inputHandler)
{
- handleDevicePixelRatioChange();
- d_ptr->m_visualController->synchDataToRenderer();
- d_ptr->m_visualController->render();
+ d_ptr->m_visualController->setActiveInputHandler(inputHandler);
}
/*!
- * \internal
+ * \return currently active input handler.
*/
-void Q3DWindow::renderLater()
+QAbstract3DInputHandler *Q3DWindow::activeInputHandler()
{
- if (!d_ptr->m_updatePending) {
- d_ptr->m_updatePending = true;
- QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
- }
+ return d_ptr->m_visualController->activeInputHandler();
}
/*!
@@ -140,7 +155,7 @@ bool Q3DWindow::event(QEvent *event)
{
switch (event->type()) {
case QEvent::UpdateRequest:
- renderNow();
+ d_ptr->renderNow();
return true;
case QEvent::TouchBegin:
case QEvent::TouchCancel:
@@ -156,35 +171,30 @@ bool Q3DWindow::event(QEvent *event)
/*!
* \internal
*/
-void Q3DWindow::exposeEvent(QExposeEvent *event)
+void Q3DWindow::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event);
- if (isExposed())
- renderNow();
+ Q3DScene *scene = d_ptr->m_visualController->scene();
+ scene->d_ptr->setWindowSize(QSize(width(), height()));
+ scene->d_ptr->setViewport(QRect(0, 0, width(), height()));
}
/*!
* \internal
*/
-void Q3DWindow::renderNow()
+void Q3DWindow::exposeEvent(QExposeEvent *event)
{
- if (!isExposed())
- return;
-
- d_ptr->m_updatePending = false;
-
- d_ptr->m_context->makeCurrent(this);
-
- render();
+ Q_UNUSED(event);
- d_ptr->m_context->swapBuffers(this);
+ if (isExposed())
+ d_ptr->renderNow();
}
Q3DWindowPrivate::Q3DWindowPrivate(Q3DWindow *q)
- : q_ptr(q),
+ : QObject(0),
+ q_ptr(q),
m_updatePending(false),
- m_context(new QOpenGLContext(q)),
m_visualController(0),
m_devicePixelRatio(1.f)
{
@@ -194,4 +204,47 @@ Q3DWindowPrivate::~Q3DWindowPrivate()
{
}
+void Q3DWindowPrivate::render()
+{
+ handleDevicePixelRatioChange();
+ m_visualController->synchDataToRenderer();
+ m_visualController->render();
+}
+
+void Q3DWindowPrivate::renderLater()
+{
+ if (!m_updatePending) {
+ m_updatePending = true;
+ QCoreApplication::postEvent(q_ptr, new QEvent(QEvent::UpdateRequest));
+ }
+}
+
+void Q3DWindowPrivate::renderNow()
+{
+ if (!q_ptr->isExposed())
+ return;
+
+ m_updatePending = false;
+
+ m_context->makeCurrent(q_ptr);
+
+ render();
+
+ m_context->swapBuffers(q_ptr);
+}
+
+void Q3DWindowPrivate::setVisualController(Abstract3DController *controller)
+{
+ m_visualController = controller;
+}
+
+void Q3DWindowPrivate::handleDevicePixelRatioChange()
+{
+ if (q_ptr->devicePixelRatio() == m_devicePixelRatio || !m_visualController)
+ return;
+
+ m_devicePixelRatio = q_ptr->devicePixelRatio();
+ m_visualController->scene()->setDevicePixelRatio(m_devicePixelRatio);
+}
+
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/q3dwindow.h b/src/datavisualization/engine/q3dwindow.h
index 1848ff29..cdffc6b9 100644
--- a/src/datavisualization/engine/q3dwindow.h
+++ b/src/datavisualization/engine/q3dwindow.h
@@ -31,26 +31,26 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class Q3DWindowPrivate;
class Abstract3DController;
+class QAbstract3DInputHandler;
class QT_DATAVISUALIZATION_EXPORT Q3DWindow : public QWindow, protected QOpenGLFunctions
{
Q_OBJECT
+protected:
+ explicit Q3DWindow(Q3DWindowPrivate *d, QWindow *parent = 0);
public:
- explicit Q3DWindow(QWindow *parent = 0);
virtual ~Q3DWindow();
-protected slots:
- void renderLater();
- void renderNow();
+ void addInputHandler(QAbstract3DInputHandler *inputHandler);
+ void releaseInputHandler(QAbstract3DInputHandler *inputHandler);
+ void setActiveInputHandler(QAbstract3DInputHandler *inputHandler);
+ QAbstract3DInputHandler *activeInputHandler();
protected:
- virtual void render();
-
bool event(QEvent *event);
+ void resizeEvent(QResizeEvent *event);
void exposeEvent(QExposeEvent *event);
- void setVisualController(Abstract3DController *controller);
- void handleDevicePixelRatioChange();
private:
QScopedPointer<Q3DWindowPrivate> d_ptr;
diff --git a/src/datavisualization/engine/q3dwindow_p.h b/src/datavisualization/engine/q3dwindow_p.h
index 6bef7e10..ba8c67da 100644
--- a/src/datavisualization/engine/q3dwindow_p.h
+++ b/src/datavisualization/engine/q3dwindow_p.h
@@ -26,11 +26,13 @@
//
// We mean it.
-#ifndef Q3DWINDOW_p_H
-#define Q3DWINDOW_p_H
+#ifndef Q3DWINDOW_P_H
+#define Q3DWINDOW_P_H
#include "datavisualizationglobal_p.h"
+#include <QObject>
+
class QOpenGLContext;
class QOpenGLPaintDevice;
@@ -39,19 +41,29 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class Q3DWindow;
class Abstract3DController;
-class Q3DWindowPrivate
+class Q3DWindowPrivate : public QObject
{
+ Q_OBJECT
public:
Q3DWindowPrivate(Q3DWindow *q);
~Q3DWindowPrivate();
+ void render();
+
+ void setVisualController(Abstract3DController *controller);
+ void handleDevicePixelRatioChange();
+
+public slots:
+ void renderLater();
+ void renderNow();
+
public:
Q3DWindow *q_ptr;
bool m_updatePending;
QOpenGLContext *m_context;
Abstract3DController *m_visualController;
- qreal m_devicePixelRatio;
+ float m_devicePixelRatio;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/scatter3dcontroller.cpp b/src/datavisualization/engine/scatter3dcontroller.cpp
index 9f43d94e..0a506f19 100644
--- a/src/datavisualization/engine/scatter3dcontroller.cpp
+++ b/src/datavisualization/engine/scatter3dcontroller.cpp
@@ -22,6 +22,7 @@
#include "q3dabstractaxis_p.h"
#include "q3dvalueaxis_p.h"
#include "qscatterdataproxy_p.h"
+#include "qscatter3dseries_p.h"
#include <QMatrix4x4>
#include <qmath.h>
@@ -31,13 +32,9 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
Scatter3DController::Scatter3DController(QRect boundRect)
: Abstract3DController(boundRect),
m_renderer(0),
- m_selectedItemIndex(noSelectionIndex())
+ m_selectedItem(invalidSelectionIndex()),
+ m_selectedItemSeries(0)
{
- // Default object type; specific to scatter
- setObjectType(QDataVis::MeshStyleSpheres, false);
-
- setActiveDataProxy(new QScatterDataProxy);
-
// Setting a null axis creates a new default axis according to orientation and graph type.
// Note: These cannot be set in Abstract3DController constructor, as they will call virtual
// functions implemented by subclasses.
@@ -60,8 +57,8 @@ void Scatter3DController::initializeOpenGL()
setRenderer(m_renderer);
synchDataToRenderer();
- QObject::connect(m_renderer, &Scatter3DRenderer::selectedItemIndexChanged, this,
- &Scatter3DController::handleSelectedItemIndexChanged, Qt::QueuedConnection);
+ QObject::connect(m_renderer, &Scatter3DRenderer::itemClicked, this,
+ &Scatter3DController::handleItemClicked, Qt::QueuedConnection);
emitNeedRender();
}
@@ -73,61 +70,59 @@ void Scatter3DController::synchDataToRenderer()
return;
// Notify changes to renderer
- if (m_changeTracker.slicingActiveChanged) {
- // TODO: Add notification.
- m_changeTracker.slicingActiveChanged = false;
+ if (m_changeTracker.selectedItemChanged) {
+ m_renderer->updateSelectedItem(m_selectedItem, m_selectedItemSeries);
+ m_changeTracker.selectedItemChanged = false;
}
+}
- if (m_changeTracker.selectedItemIndexChanged) {
- m_renderer->updateSelectedItemIndex(m_selectedItemIndex);
- m_changeTracker.selectedItemIndexChanged = false;
- }
+void Scatter3DController::addSeries(QAbstract3DSeries *series)
+{
+ Q_ASSERT(series && series->type() == QAbstract3DSeries::SeriesTypeScatter);
- if (m_isDataDirty) {
- m_renderer->updateDataModel(static_cast<QScatterDataProxy *>(m_data));
- m_isDataDirty = false;
- }
-}
+ bool firstAdded = !m_seriesList.size();
+
+ Abstract3DController::addSeries(series);
+ if (firstAdded)
+ adjustValueAxisRange();
+
+ QScatter3DSeries *scatterSeries = static_cast<QScatter3DSeries *>(series);
+ if (scatterSeries->selectedItem() != invalidSelectionIndex())
+ setSelectedItem(scatterSeries->selectedItem(), scatterSeries);
+}
-void Scatter3DController::setActiveDataProxy(QAbstractDataProxy *proxy)
+void Scatter3DController::removeSeries(QAbstract3DSeries *series)
{
- // Setting null proxy indicates default proxy
- if (!proxy) {
- proxy = new QScatterDataProxy;
- proxy->d_ptr->setDefaultProxy(true);
- }
+ bool firstRemoved = (m_seriesList.size() && m_seriesList.at(0) == series);
- Q_ASSERT(proxy->type() == QAbstractDataProxy::DataTypeScatter);
+ Abstract3DController::removeSeries(series);
- Abstract3DController::setActiveDataProxy(proxy);
+ if (m_selectedItemSeries == series)
+ setSelectedItem(invalidSelectionIndex(), 0);
- QScatterDataProxy *scatterDataProxy = static_cast<QScatterDataProxy *>(m_data);
+ if (firstRemoved)
+ adjustValueAxisRange();
+}
- QObject::connect(scatterDataProxy, &QScatterDataProxy::arrayReset,
- this, &Scatter3DController::handleArrayReset);
- QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsAdded,
- this, &Scatter3DController::handleItemsAdded);
- QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsChanged,
- this, &Scatter3DController::handleItemsChanged);
- QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsRemoved,
- this, &Scatter3DController::handleItemsRemoved);
- QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsInserted,
- this, &Scatter3DController::handleItemsInserted);
+QList<QScatter3DSeries *> Scatter3DController::scatterSeriesList()
+{
+ QList<QAbstract3DSeries *> abstractSeriesList = seriesList();
+ QList<QScatter3DSeries *> scatterSeriesList;
+ foreach (QAbstract3DSeries *abstractSeries, abstractSeriesList) {
+ QScatter3DSeries *scatterSeries = qobject_cast<QScatter3DSeries *>(abstractSeries);
+ if (scatterSeries)
+ scatterSeriesList.append(scatterSeries);
+ }
- adjustValueAxisRange();
- setSelectedItemIndex(noSelectionIndex());
- setSlicingActive(false);
- m_isDataDirty = true;
- emitNeedRender();
+ return scatterSeriesList;
}
void Scatter3DController::handleArrayReset()
{
- setSlicingActive(false);
adjustValueAxisRange();
m_isDataDirty = true;
- setSelectedItemIndex(noSelectionIndex());
+ setSelectedItem(m_selectedItem, m_selectedItemSeries);
emitNeedRender();
}
@@ -158,8 +153,10 @@ void Scatter3DController::handleItemsRemoved(int startIndex, int count)
// TODO should dirty only affected values?
adjustValueAxisRange();
m_isDataDirty = true;
- if (startIndex >= static_cast<QScatterDataProxy *>(m_data)->itemCount())
- setSelectedItemIndex(noSelectionIndex());
+
+ // Clear selection unless it is still valid
+ setSelectedItem(m_selectedItem, m_selectedItemSeries);
+
emitNeedRender();
}
@@ -173,13 +170,12 @@ void Scatter3DController::handleItemsInserted(int startIndex, int count)
emitNeedRender();
}
-void Scatter3DController::handleSelectedItemIndexChanged(int index)
+void Scatter3DController::handleItemClicked(int index, QScatter3DSeries *series)
{
- if (index != m_selectedItemIndex) {
- m_selectedItemIndex = index;
- emit selectedItemIndexChanged(index);
- emitNeedRender();
- }
+ setSelectedItem(index, series);
+
+ // TODO: pass clicked to parent. (QTRD-2517)
+ // TODO: Also hover needed? (QTRD-2131)
}
void Scatter3DController::handleAxisAutoAdjustRangeChangedInOrientation(
@@ -190,80 +186,163 @@ void Scatter3DController::handleAxisAutoAdjustRangeChangedInOrientation(
adjustValueAxisRange();
}
-void Scatter3DController::setObjectType(QDataVis::MeshStyle style, bool smooth)
+void Scatter3DController::handleAxisRangeChangedBySender(QObject *sender)
{
- QString objFile;
- if (style == QDataVis::MeshStyleSpheres) {
- if (smooth)
- objFile = QStringLiteral(":/defaultMeshes/sphereSmooth");
- else
- objFile = QStringLiteral(":/defaultMeshes/sphere");
- } else {
- if (smooth)
- objFile = QStringLiteral(":/defaultMeshes/dotSmooth");
- else
- objFile = QStringLiteral(":/defaultMeshes/dot");
- }
- Abstract3DController::setMeshFileName(objFile);
+ Abstract3DController::handleAxisRangeChangedBySender(sender);
+
+ // Update selected index - may be moved offscreen
+ setSelectedItem(m_selectedItem, m_selectedItemSeries);
}
-void Scatter3DController::setSelectionMode(QDataVis::SelectionMode mode)
+void Scatter3DController::setSelectionMode(QDataVis::SelectionFlags mode)
{
- if (mode > QDataVis::SelectionModeItem) {
- qWarning("Unsupported selection mode.");
+ // We only support single item selection mode and no selection mode
+ if (mode != QDataVis::SelectionItem && mode != QDataVis::SelectionNone) {
+ qWarning("Unsupported selection mode - only none and item selection modes are supported.");
return;
}
- // Disable zoom if selection mode changes
- setSlicingActive(false);
+
Abstract3DController::setSelectionMode(mode);
}
-void Scatter3DController::setSelectedItemIndex(int index)
+void Scatter3DController::setSelectedItem(int index, QScatter3DSeries *series)
{
- // TODO If items not within axis ranges are culled from drawing, should they be
- // TODO unselectable as well?
- if (index < 0 || index >= static_cast<QScatterDataProxy *>(m_data)->itemCount())
- index = noSelectionIndex();
-
- if (index != m_selectedItemIndex) {
- m_selectedItemIndex = index;
- m_changeTracker.selectedItemIndexChanged = true;
- emit selectedItemIndexChanged(index);
+ const QScatterDataProxy *proxy = 0;
+
+ // Series may already have been removed, so check it before setting the selection.
+ if (!m_seriesList.contains(series))
+ series = 0;
+
+ if (series)
+ proxy = series->dataProxy();
+
+ if (!proxy || index < 0 || index >= proxy->itemCount())
+ index = invalidSelectionIndex();
+
+ if (index != m_selectedItem || series != m_selectedItemSeries) {
+ m_selectedItem = index;
+ m_selectedItemSeries = series;
+ m_changeTracker.selectedItemChanged = true;
+
+ // Clear selection from other series and finally set new selection to the specified series
+ foreach (QAbstract3DSeries *otherSeries, m_seriesList) {
+ QScatter3DSeries *scatterSeries = static_cast<QScatter3DSeries *>(otherSeries);
+ if (scatterSeries != m_selectedItemSeries)
+ scatterSeries->dptr()->setSelectedItem(invalidSelectionIndex());
+ }
+ if (m_selectedItemSeries)
+ m_selectedItemSeries->dptr()->setSelectedItem(m_selectedItem);
+
emitNeedRender();
}
}
-int Scatter3DController::selectedItemIndex() const
-{
- return m_selectedItemIndex;
-}
-
void Scatter3DController::adjustValueAxisRange()
{
- if (m_data) {
- QVector3D limits = static_cast<QScatterDataProxy *>(m_data)->dptr()->limitValues();
- Q3DValueAxis *valueAxis = static_cast<Q3DValueAxis *>(m_axisX);
- if (valueAxis && valueAxis->isAutoAdjustRange()) {
- if (limits.x() > 0)
- valueAxis->dptr()->setRange(-limits.x(), limits.x());
- else
- valueAxis->dptr()->setRange(-1.0, 1.0); // Only zero value values in data set, set range to default.
+ Q3DValueAxis *valueAxisX = static_cast<Q3DValueAxis *>(m_axisX);
+ Q3DValueAxis *valueAxisY = static_cast<Q3DValueAxis *>(m_axisY);
+ Q3DValueAxis *valueAxisZ = static_cast<Q3DValueAxis *>(m_axisZ);
+ bool adjustX = (valueAxisX && valueAxisX->isAutoAdjustRange());
+ bool adjustY = (valueAxisY && valueAxisY->isAutoAdjustRange());
+ bool adjustZ = (valueAxisZ && valueAxisZ->isAutoAdjustRange());
+
+ if (adjustX || adjustY || adjustZ) {
+ float minValueX = 0.0f;
+ float maxValueX = 0.0f;
+ float minValueY = 0.0f;
+ float maxValueY = 0.0f;
+ float minValueZ = 0.0f;
+ float maxValueZ = 0.0f;
+ int seriesCount = m_seriesList.size();
+ for (int series = 0; series < seriesCount; series++) {
+ const QScatter3DSeries *scatterSeries =
+ static_cast<QScatter3DSeries *>(m_seriesList.at(series));
+ const QScatterDataProxy *proxy = scatterSeries->dataProxy();
+ if (scatterSeries->isVisible() && proxy) {
+ QVector3D minLimits;
+ QVector3D maxLimits;
+ proxy->dptrc()->limitValues(minLimits, maxLimits);
+ if (adjustX) {
+ if (!series) {
+ // First series initializes the values
+ minValueX = minLimits.x();
+ maxValueX = maxLimits.x();
+ } else {
+ minValueX = qMin(minValueX, minLimits.x());
+ maxValueX = qMax(maxValueX, maxLimits.x());
+ }
+ }
+ if (adjustY) {
+ if (!series) {
+ // First series initializes the values
+ minValueY = minLimits.y();
+ maxValueY = maxLimits.y();
+ } else {
+ minValueY = qMin(minValueY, minLimits.y());
+ maxValueY = qMax(maxValueY, maxLimits.y());
+ }
+ }
+ if (adjustZ) {
+ if (!series) {
+ // First series initializes the values
+ minValueZ = minLimits.z();
+ maxValueZ = maxLimits.z();
+ } else {
+ minValueZ = qMin(minValueZ, minLimits.z());
+ maxValueZ = qMax(maxValueZ, maxLimits.z());
+ }
+ }
+ }
}
- valueAxis = static_cast<Q3DValueAxis *>(m_axisY);
- if (valueAxis && valueAxis->isAutoAdjustRange()) {
- if (limits.y() > 0)
- valueAxis->dptr()->setRange(-limits.y(), limits.y());
- else
- valueAxis->dptr()->setRange(-1.0, 1.0); // Only zero value values in data set, set range to default.
+ static const float adjustmentRatio = 20.0f;
+ static const float defaultAdjustment = 1.0f;
+
+ if (adjustX) {
+ // If all points at same coordinate, need to default to some valid range
+ float adjustment = 0.0f;
+ if (minValueX == maxValueX) {
+ if (adjustZ) {
+ // X and Z are linked to have similar unit size, so choose the valid range based on it
+ if (minValueZ == maxValueZ)
+ adjustment = defaultAdjustment;
+ else
+ adjustment = qAbs(maxValueZ - minValueZ) / adjustmentRatio;
+ } else {
+ if (valueAxisZ)
+ adjustment = qAbs(valueAxisZ->max() - valueAxisZ->min()) / adjustmentRatio;
+ else
+ adjustment = defaultAdjustment;
+ }
+ }
+ valueAxisX->dptr()->setRange(minValueX - adjustment, maxValueX + adjustment);
}
-
- valueAxis = static_cast<Q3DValueAxis *>(m_axisZ);
- if (valueAxis && valueAxis->isAutoAdjustRange()) {
- if (limits.z() > 0)
- valueAxis->dptr()->setRange(-limits.z(), limits.z());
- else
- valueAxis->dptr()->setRange(-1.0, 1.0); // Only zero value values in data set, set range to default.
+ if (adjustY) {
+ // If all points at same coordinate, need to default to some valid range
+ // Y-axis unit is not dependent on other axes, so simply adjust +-1.0f
+ float adjustment = 0.0f;
+ if (minValueY == maxValueY)
+ adjustment = defaultAdjustment;
+ valueAxisY->dptr()->setRange(minValueY - adjustment, maxValueY + adjustment);
+ }
+ if (adjustZ) {
+ // If all points at same coordinate, need to default to some valid range
+ float adjustment = 0.0f;
+ if (minValueZ == maxValueZ) {
+ if (adjustX) {
+ // X and Z are linked to have similar unit size, so choose the valid range based on it
+ if (minValueX == maxValueX)
+ adjustment = defaultAdjustment;
+ else
+ adjustment = qAbs(maxValueX - minValueX) / adjustmentRatio;
+ } else {
+ if (valueAxisX)
+ adjustment = qAbs(valueAxisX->max() - valueAxisX->min()) / adjustmentRatio;
+ else
+ adjustment = defaultAdjustment;
+ }
+ }
+ valueAxisZ->dptr()->setRange(minValueZ - adjustment, maxValueZ + adjustment);
}
}
}
diff --git a/src/datavisualization/engine/scatter3dcontroller_p.h b/src/datavisualization/engine/scatter3dcontroller_p.h
index 63735aca..00c87d4f 100644
--- a/src/datavisualization/engine/scatter3dcontroller_p.h
+++ b/src/datavisualization/engine/scatter3dcontroller_p.h
@@ -38,14 +38,13 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class Scatter3DRenderer;
class QScatterDataProxy;
+class QScatter3DSeries;
struct Scatter3DChangeBitField {
- bool slicingActiveChanged : 1;
- bool selectedItemIndexChanged : 1;
+ bool selectedItemChanged : 1;
Scatter3DChangeBitField() :
- slicingActiveChanged(true),
- selectedItemIndexChanged(true)
+ selectedItemChanged(true)
{
}
};
@@ -59,29 +58,30 @@ private:
// Rendering
Scatter3DRenderer *m_renderer;
- int m_selectedItemIndex;
+ int m_selectedItem;
+ QScatter3DSeries *m_selectedItemSeries; // Points to the series for which the bar is selected
+ // in single series selection cases.
public:
explicit Scatter3DController(QRect rect);
~Scatter3DController();
- void initializeOpenGL();
-
- // Object type
- void setObjectType(QDataVis::MeshStyle style, bool smooth = false);
+ virtual void initializeOpenGL();
// Change selection mode
- void setSelectionMode(QDataVis::SelectionMode mode);
-
- void setSelectedItemIndex(int index);
- int selectedItemIndex() const;
- static inline int noSelectionIndex() { return -1; }
+ void setSelectionMode(QDataVis::SelectionFlags mode);
- virtual void setActiveDataProxy(QAbstractDataProxy *proxy);
+ void setSelectedItem(int index, QScatter3DSeries *series);
+ static inline int invalidSelectionIndex() { return -1; }
void synchDataToRenderer();
+ virtual void addSeries(QAbstract3DSeries *series);
+ virtual void removeSeries(QAbstract3DSeries *series);
+ virtual QList<QScatter3DSeries *> scatterSeriesList();
+
virtual void handleAxisAutoAdjustRangeChangedInOrientation(Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust);
+ virtual void handleAxisRangeChangedBySender(QObject *sender);
public slots:
void handleArrayReset();
@@ -89,10 +89,9 @@ public slots:
void handleItemsChanged(int startIndex, int count);
void handleItemsRemoved(int startIndex, int count);
void handleItemsInserted(int startIndex, int count);
- void handleSelectedItemIndexChanged(int index);
-signals:
- void selectedItemIndexChanged(int index);
+ // Renderer callback handlers
+ void handleItemClicked(int index, QScatter3DSeries *series);
private:
void adjustValueAxisRange();
diff --git a/src/datavisualization/engine/scatter3drenderer.cpp b/src/datavisualization/engine/scatter3drenderer.cpp
index a457b545..00452cf7 100644
--- a/src/datavisualization/engine/scatter3drenderer.cpp
+++ b/src/datavisualization/engine/scatter3drenderer.cpp
@@ -25,6 +25,7 @@
#include "texturehelper_p.h"
#include "utils_p.h"
#include "q3dlight.h"
+#include "qscatter3dseries_p.h"
#include <QMatrix4x4>
#include <QMouseEvent>
@@ -46,25 +47,28 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
const GLfloat aspectRatio = 2.0f; // Forced ratio of x and z to y. Dynamic will make it look odd.
const GLfloat labelMargin = 0.05f;
-// TODO: Make margin modifiable?
-const GLfloat backgroundMargin = 1.1f; // Margin for background (1.1f = make it 10% larger to avoid items being drawn inside background)
+const GLfloat defaultMinSize = 0.01f;
+const GLfloat defaultMaxSize = 0.1f;
+const GLfloat defaultMargin = 1.0f + defaultMaxSize; // Default margin for background
+const GLfloat itemScaler = 3.0f;
const GLfloat gridLineWidth = 0.005f;
-static QVector3D selectionSkipColor = QVector3D(255, 255, 255); // Selection texture's background color
Scatter3DRenderer::Scatter3DRenderer(Scatter3DController *controller)
: Abstract3DRenderer(controller),
- m_controller(controller),
m_selectedItem(0),
m_xFlipped(false),
m_zFlipped(false),
m_yFlipped(false),
m_updateLabels(false),
m_dotShader(0),
+ m_dotGradientShader(0),
+ #if defined(QT_OPENGL_ES_2)
+ m_pointShader(0),
+ #endif
m_depthShader(0),
m_selectionShader(0),
m_backgroundShader(0),
m_labelShader(0),
- m_dotObj(0),
m_backgroundObj(0),
m_gridLineObj(0),
m_labelObj(0),
@@ -78,11 +82,15 @@ Scatter3DRenderer::Scatter3DRenderer(Scatter3DController *controller)
m_shadowQualityMultiplier(3),
m_heightNormalizer(1.0f),
m_scaleFactor(0),
- m_selection(selectionSkipColor),
- m_previousSelection(selectionSkipColor),
+ m_selectedItemIndex(Scatter3DController::invalidSelectionIndex()),
+ m_selectedItemTotalIndex(Scatter3DController::invalidSelectionIndex()),
+ m_selectedItemSeriesIndex(Scatter3DController::invalidSelectionIndex()),
+ m_selectedSeries(0),
m_areaSize(QSizeF(0.0, 0.0)),
m_dotSizeScale(1.0f),
- m_hasHeightAdjustmentChanged(true)
+ m_hasHeightAdjustmentChanged(true),
+ m_backgroundMargin(defaultMargin),
+ m_maxItemSize(0.0f)
{
initializeOpenGLFunctions();
initializeOpenGL();
@@ -96,11 +104,11 @@ Scatter3DRenderer::~Scatter3DRenderer()
m_textureHelper->glDeleteFramebuffers(1, &m_depthFrameBuffer);
m_textureHelper->deleteTexture(&m_bgrTexture);
delete m_dotShader;
+ delete m_dotGradientShader;
delete m_depthShader;
delete m_selectionShader;
delete m_backgroundShader;
delete m_labelShader;
- delete m_dotObj;
delete m_backgroundObj;
delete m_gridLineObj;
delete m_labelObj;
@@ -111,14 +119,15 @@ void Scatter3DRenderer::initializeOpenGL()
Abstract3DRenderer::initializeOpenGL();
// Initialize shaders
- handleShadowQualityChange();
-
initLabelShaders(QStringLiteral(":/shaders/vertexLabel"),
QStringLiteral(":/shaders/fragmentLabel"));
#if !defined(QT_OPENGL_ES_2)
// Init depth shader (for shadows). Init in any case, easier to handle shadow activation if done via api.
initDepthShader();
+#else
+ // Init point shader
+ initPointShader();
#endif
// Init selection shader
@@ -131,52 +140,81 @@ void Scatter3DRenderer::initializeOpenGL()
loadLabelMesh();
// Set view port
- glViewport(m_mainViewPort.x(), m_mainViewPort.y(),
- m_mainViewPort.width(), m_mainViewPort.height());
+ glViewport(m_primarySubViewport.x(),
+ m_primarySubViewport.y(),
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
// Load background mesh (we need to be initialized first)
loadBackgroundMesh();
}
-void Scatter3DRenderer::updateDataModel(QScatterDataProxy *dataProxy)
+void Scatter3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList,
+ bool updateVisibility)
{
- const QScatterDataArray &dataArray = *dataProxy->array();
+ Abstract3DRenderer::updateSeries(seriesList, updateVisibility);
+
+ int seriesCount = m_visibleSeriesList.size();
+ float maxItemSize = 0.0f;
+ float itemSize = 0.0f;
+
+ for (int series = 0; series < seriesCount; series++) {
+ itemSize = static_cast<QScatter3DSeries *>(m_visibleSeriesList.at(series).series())->itemSize();
+ if (maxItemSize < itemSize)
+ maxItemSize = itemSize;
+ }
+ m_backgroundMargin = defaultMargin;
+ m_maxItemSize = maxItemSize;
+ if (maxItemSize > defaultMaxSize)
+ m_backgroundMargin += maxItemSize / itemScaler;
+}
+
+void Scatter3DRenderer::updateData()
+{
+ int seriesCount = m_visibleSeriesList.size();
calculateSceneScalingFactors();
- int dataSize = dataArray.size();
float minX = float(m_axisCacheX.min());
float maxX = float(m_axisCacheX.max());
float minY = float(m_axisCacheY.min());
float maxY = float(m_axisCacheY.max());
float minZ = float(m_axisCacheZ.min());
float maxZ = float(m_axisCacheZ.max());
-
- if (dataSize != m_renderItemArray.size())
- m_renderItemArray.resize(dataSize);
- for (int i = 0; i < dataSize ; i++) {
- QVector3D dotPos = dataArray.at(i).position();
- // TODO: Check if this still works always when ranges are no longer required to be zero centered
- // TODO: qreal -> float conversion for axis min/max may cause issues like in surface
- if ((dotPos.x() >= minX && dotPos.x() <= maxX )
- && (dotPos.y() >= minY && dotPos.y() <= maxY)
- && (dotPos.z() >= minZ && dotPos.z() <= maxZ)) {
- m_renderItemArray[i].setPosition(dotPos);
- m_renderItemArray[i].setVisible(true);
- calculateTranslation(m_renderItemArray[i]);
- } else {
- m_renderItemArray[i].setVisible(false);
+ int totalDataSize = 0;
+
+ if (m_renderingArrays.size() != seriesCount)
+ m_renderingArrays.resize(seriesCount);
+
+ for (int series = 0; series < seriesCount; series++) {
+ QScatterDataProxy *dataProxy =
+ static_cast<QScatter3DSeries *>(m_visibleSeriesList.at(series).series())->dataProxy();
+ const QScatterDataArray &dataArray = *dataProxy->array();
+ int dataSize = dataArray.size();
+ totalDataSize += dataSize;
+
+ if (dataSize != m_renderingArrays.at(series).size())
+ m_renderingArrays[series].resize(dataSize);
+
+ for (int i = 0; i < dataSize; i++) {
+ QVector3D dotPos = dataArray.at(i).position();
+ if ((dotPos.x() >= minX && dotPos.x() <= maxX )
+ && (dotPos.y() >= minY && dotPos.y() <= maxY)
+ && (dotPos.z() >= minZ && dotPos.z() <= maxZ)) {
+ m_renderingArrays[series][i].setPosition(dotPos);
+ m_renderingArrays[series][i].setVisible(true);
+ calculateTranslation(m_renderingArrays[series][i]);
+ } else {
+ m_renderingArrays[series][i].setVisible(false);
+ }
}
}
- m_dotSizeScale = (GLfloat)qBound(0.01, (2.0 / qSqrt((qreal)dataSize)), 0.1);
- m_selectedItem = 0;
+ m_dotSizeScale = GLfloat(qBound(defaultMinSize, 2.0f / float(qSqrt(qreal(totalDataSize))),
+ defaultMaxSize));
- Abstract3DRenderer::updateDataModel(dataProxy);
+ updateSelectedItem(m_selectedItemIndex, m_selectedSeries);
}
void Scatter3DRenderer::updateScene(Q3DScene *scene)
{
- // TODO: Move these to more suitable place e.g. controller should be controlling the viewports.
- scene->setPrimarySubViewport(m_mainViewPort);
-
// TODO: See QTRD-2374
scene->activeCamera()->setMinYRotation(-90.0f);
@@ -186,10 +224,6 @@ void Scatter3DRenderer::updateScene(Q3DScene *scene)
m_hasHeightAdjustmentChanged = false;
}
- scene->activeCamera()->d_ptr->updateViewMatrix(m_autoScaleAdjustment);
- // Set light position (rotate light with m_cachedScene->activeCamera(), a bit above it (as set in defaultLightPos))
- scene->setLightPositionRelativeToCamera(defaultLightPos);
-
Abstract3DRenderer::updateScene(scene);
}
@@ -209,19 +243,22 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
const Q3DCamera *activeCamera = m_cachedScene->activeCamera();
// Specify viewport
- glViewport(m_mainViewPort.x(), m_mainViewPort.y(),
- m_mainViewPort.width(), m_mainViewPort.height());
+ glViewport(m_primarySubViewport.x(),
+ m_primarySubViewport.y(),
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
// Set up projection matrix
QMatrix4x4 projectionMatrix;
- GLfloat viewPortRatio = (GLfloat)m_mainViewPort.width() / (GLfloat)m_mainViewPort.height();
+ GLfloat viewPortRatio = (GLfloat)m_primarySubViewport.width() / (GLfloat)m_primarySubViewport.height();
projectionMatrix.perspective(45.0f, viewPortRatio, 0.1f, 100.0f);
// Calculate view matrix
QMatrix4x4 viewMatrix = activeCamera->viewMatrix();
-
QMatrix4x4 projectionViewMatrix = projectionMatrix * viewMatrix;
+ int seriesCount = m_visibleSeriesList.size();
+
// Calculate label flipping
if (viewMatrix.row(0).x() > 0)
m_zFlipped = false;
@@ -249,25 +286,36 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
backgroundRotation = 0.0f;
// Get light position from the scene
- QVector3D lightPos = m_cachedScene->activeLight()->position();
-
- // Map adjustment direction to model matrix scaling
- // TODO: Let's use these for testing the autoscaling of dots based on their number
- GLfloat heightMultiplier = m_dotSizeScale; //1.0f;
- GLfloat widthMultiplier = m_dotSizeScale; //1.0f;
- GLfloat depthMultiplier = m_dotSizeScale; //1.0f;
- GLfloat heightScaler = 0.0f;
- GLfloat widthScaler = 0.0f;
- GLfloat depthScaler = 0.0f;
- QVector3D modelScaler(widthMultiplier + widthScaler,
- heightMultiplier + heightScaler,
- depthMultiplier + depthScaler);
+ QVector3D lightPos = m_cachedScene->activeLight()->position();
+
// Introduce regardless of shadow quality to simplify logic
QMatrix4x4 depthViewMatrix;
QMatrix4x4 depthProjectionMatrix;
QMatrix4x4 depthProjectionViewMatrix;
+ // Check if we have any series with points
+ bool havePointSeries = false;
+ bool haveMeshSeries = false;
+ bool haveUniformColorMeshSeries = false;
+ bool haveGradientMeshSeries = false;
+ for (int i = 0; i < seriesCount; i++) {
+ if (m_visibleSeriesList.at(i).mesh() == QAbstract3DSeries::MeshPoint) {
+ havePointSeries = true;
+ } else {
+ haveMeshSeries = true;
+ if (m_visibleSeriesList.at(i).colorStyle() == Q3DTheme::ColorStyleUniform)
+ haveUniformColorMeshSeries = true;
+ else
+ haveGradientMeshSeries = true;
+ }
+ }
+
#if !defined(QT_OPENGL_ES_2)
+ if (havePointSeries) {
+ glEnable(GL_POINT_SMOOTH);
+ glEnable(GL_PROGRAM_POINT_SIZE);
+ }
+
if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
// Render scene into a depth texture for using with shadow mapping
// Bind depth shader
@@ -275,8 +323,8 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
// Set viewport for depth map rendering. Must match texture size. Larger values give smoother shadows.
glViewport(0, 0,
- m_mainViewPort.width() * m_shadowQualityMultiplier,
- m_mainViewPort.height() * m_shadowQualityMultiplier);
+ m_primarySubViewport.width() * m_shadowQualityMultiplier,
+ m_primarySubViewport.height() * m_shadowQualityMultiplier);
// Enable drawing to framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, m_depthFrameBuffer);
@@ -310,40 +358,61 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
depthProjectionViewMatrix = depthProjectionMatrix * depthViewMatrix;
// Draw dots to depth buffer
- for (int dot = 0; dot < m_renderItemArray.size(); dot++) {
- const ScatterRenderItem &item = m_renderItemArray.at(dot);
- if (!item.isVisible())
- continue;
+ for (int series = 0; series < seriesCount; series++) {
+ ObjectHelper *dotObj = m_visibleSeriesList.at(series).object();
+ bool drawingPoints = (m_visibleSeriesList.at(series).mesh() == QAbstract3DSeries::MeshPoint);
+
+ // TODO: Accessing series directly during rendering
+ float itemSize =
+ static_cast<QScatter3DSeries *>(m_visibleSeriesList.at(series).series())->itemSize()
+ / itemScaler;
+ if (itemSize == 0.0f)
+ itemSize = m_dotSizeScale;
+ if (drawingPoints) {
+ // Scale points based on shadow quality for shadows, not by zoom level
+ glPointSize(itemSize * 100.0f * m_shadowQualityMultiplier);
+ }
+ QVector3D modelScaler(itemSize, itemSize, itemSize);
- QMatrix4x4 modelMatrix;
- QMatrix4x4 MVPMatrix;
+ for (int dot = 0; dot < m_renderingArrays.at(series).size(); dot++) {
+ const ScatterRenderItem &item = m_renderingArrays.at(series).at(dot);
+ if (!item.isVisible())
+ continue;
- modelMatrix.translate(item.translation());
- modelMatrix.scale(modelScaler);
- //modelMatrix.scale(QVector3D(widthMultiplier * item.size() + widthScaler,
- // heightMultiplier * item.size() + heightScaler,
- // depthMultiplier * item.size() + depthScaler));
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
- MVPMatrix = depthProjectionViewMatrix * modelMatrix;
+ modelMatrix.translate(item.translation());
+ if (!drawingPoints)
+ modelMatrix.scale(modelScaler);
- m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix);
+ MVPMatrix = depthProjectionViewMatrix * modelMatrix;
- // 1st attribute buffer : vertices
- glEnableVertexAttribArray(m_depthShader->posAtt());
- glBindBuffer(GL_ARRAY_BUFFER, m_dotObj->vertexBuf());
- glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void *)0);
+ m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix);
- // Index buffer
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_dotObj->elementBuf());
+ if (drawingPoints) {
+ m_drawer->drawPoint(m_depthShader);
+ } else {
+ // 1st attribute buffer : vertices
+ glEnableVertexAttribArray(m_depthShader->posAtt());
+ glBindBuffer(GL_ARRAY_BUFFER, dotObj->vertexBuf());
+ glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0,
+ (void *)0);
- // Draw the triangles
- glDrawElements(GL_TRIANGLES, m_dotObj->indexCount(), GL_UNSIGNED_SHORT, (void *)0);
+ // Index buffer
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dotObj->elementBuf());
- // Free buffers
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
+ // Draw the triangles
+ glDrawElements(GL_TRIANGLES, dotObj->indexCount(), GL_UNSIGNED_SHORT,
+ (void *)0);
- glDisableVertexAttribArray(m_depthShader->posAtt());
+ // Free buffers
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glDisableVertexAttribArray(m_depthShader->posAtt());
+ }
+ }
}
// Disable drawing to framebuffer (= enable drawing to screen)
@@ -352,12 +421,11 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
// Reset culling to normal
glCullFace(GL_BACK);
- // Release depth shader
- m_depthShader->release();
-
// Revert to original viewport
- glViewport(m_mainViewPort.x(), m_mainViewPort.y(),
- m_mainViewPort.width(), m_mainViewPort.height());
+ glViewport(m_primarySubViewport.x(),
+ m_primarySubViewport.y(),
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
#if 0 // Use this if you want to see what is being drawn to the framebuffer
// You'll also have to comment out GL_COMPARE_R_TO_TEXTURE -line in texturehelper (if using it)
@@ -370,16 +438,18 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix);
m_drawer->drawObject(m_labelShader, m_labelObj, m_depthTexture);
glDisable(GL_TEXTURE_2D);
- m_labelShader->release();
#endif
}
+
+ ShaderHelper *pointSelectionShader = m_selectionShader;
+#else
+ ShaderHelper *pointSelectionShader = m_pointShader;
#endif
+ ShaderHelper *selectionShader = m_selectionShader;
// Skip selection mode drawing if we have no selection mode
- if (m_cachedSelectionMode > QDataVis::SelectionModeNone) {
- // Bind selection shader
- m_selectionShader->bind();
-
+ if (m_cachedSelectionMode > QDataVis::SelectionNone
+ && SelectOnScene == m_selectionState && seriesCount > 0) {
// Draw dots to selection buffer
glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer);
glEnable(GL_DEPTH_TEST); // Needed, otherwise the depth render buffer is not used
@@ -387,62 +457,101 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Needed for clearing the frame buffer
glDisable(GL_DITHER); // disable dithering, it may affect colors if enabled
- int arraySize = m_renderItemArray.size();
- if (arraySize > 0xfffffe) // Max possible different selection colors, 0xffffff being skipColor
- qFatal("Too many objects");
+ int arraySize = 0;
+ int totalArraySize = 0;
+ int dotNo = 0;
+
+ // Init previous to opposite of first to ensure we change binding for first series
+ bool previousDrawingPoints = (m_visibleSeriesList.at(0).mesh() != QAbstract3DSeries::MeshPoint);
+ for (int series = 0; series < seriesCount; series++) {
+ ObjectHelper *dotObj = m_visibleSeriesList.at(series).object();
+ bool drawingPoints = (m_visibleSeriesList.at(series).mesh() == QAbstract3DSeries::MeshPoint);
+
+ // TODO: Accessing series directly during rendering
+ float itemSize =
+ static_cast<QScatter3DSeries *>(m_visibleSeriesList.at(series).series())->itemSize()
+ / itemScaler;
+ if (itemSize == 0.0f)
+ itemSize = m_dotSizeScale;
+#if !defined(QT_OPENGL_ES_2)
+ if (drawingPoints)
+ glPointSize(itemSize * activeCamera->zoomLevel()); // Scale points based on zoom
+#endif
+ QVector3D modelScaler(itemSize, itemSize, itemSize);
- for (int dot = 0; dot < arraySize; dot++) {
- const ScatterRenderItem &item = m_renderItemArray.at(dot);
- if (!item.isVisible())
- continue;
+ // Rebind selection shader if it has changed
+ if (drawingPoints != previousDrawingPoints) {
+ previousDrawingPoints = drawingPoints;
+ if (drawingPoints)
+ selectionShader = pointSelectionShader;
+ else
+ selectionShader = m_selectionShader;
- QMatrix4x4 modelMatrix;
- QMatrix4x4 MVPMatrix;
+ selectionShader->bind();
+ }
+ arraySize = m_renderingArrays.at(series).size();
+ totalArraySize += arraySize;
- modelMatrix.translate(item.translation());
- modelMatrix.scale(modelScaler);
- //modelMatrix.scale(QVector3D(widthMultiplier * item.size() + widthScaler,
- // heightMultiplier * item.size() + heightScaler,
- // depthMultiplier * item.size() + depthScaler));
+ if (totalArraySize > 0xfffffe) // Max possible different selection colors, 0xffffff being skipColor
+ qFatal("Too many objects");
- MVPMatrix = projectionViewMatrix * modelMatrix;
+ for (int dot = 0; dot < arraySize; dot++) {
+ const ScatterRenderItem &item = m_renderingArrays.at(series).at(dot);
+ if (!item.isVisible())
+ continue;
- QVector3D dotColor = indexToSelectionColor(dot);
- dotColor /= 255.0f;
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+
+ modelMatrix.translate(item.translation());
+ if (!drawingPoints)
+ modelMatrix.scale(modelScaler);
+
+ MVPMatrix = projectionViewMatrix * modelMatrix;
- m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix);
- m_selectionShader->setUniformValue(m_selectionShader->color(), dotColor);
+ QVector3D dotColor = indexToSelectionColor(dotNo);
+ dotColor /= 255.0f;
- // 1st attribute buffer : vertices
- glEnableVertexAttribArray(m_selectionShader->posAtt());
- glBindBuffer(GL_ARRAY_BUFFER, m_dotObj->vertexBuf());
- glVertexAttribPointer(m_selectionShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void *)0);
+ selectionShader->setUniformValue(selectionShader->MVP(), MVPMatrix);
+ selectionShader->setUniformValue(selectionShader->color(), dotColor);
- // Index buffer
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_dotObj->elementBuf());
+ if (drawingPoints) {
+ m_drawer->drawPoint(selectionShader);
+ } else {
+ // 1st attribute buffer : vertices
+ glEnableVertexAttribArray(selectionShader->posAtt());
+ glBindBuffer(GL_ARRAY_BUFFER, dotObj->vertexBuf());
+ glVertexAttribPointer(selectionShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0,
+ (void *)0);
- // Draw the triangles
- glDrawElements(GL_TRIANGLES, m_dotObj->indexCount(), GL_UNSIGNED_SHORT, (void *)0);
+ // Index buffer
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dotObj->elementBuf());
- // Free buffers
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
+ // Draw the triangles
+ glDrawElements(GL_TRIANGLES, dotObj->indexCount(), GL_UNSIGNED_SHORT,
+ (void *)0);
- glDisableVertexAttribArray(m_selectionShader->posAtt());
+ // Free buffers
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glDisableVertexAttribArray(selectionShader->posAtt());
+ }
+ dotNo++;
+ }
}
glEnable(GL_DITHER);
// Read color under cursor
- if (QDataVis::InputStateOnScene == m_controller->inputState()) {
- m_selection = Utils::getSelection(m_controller->inputPosition(),
- m_cachedBoundingRect.height());
- }
+ QVector3D clickedColor = Utils::getSelection(m_inputPosition,
+ m_viewport.height());
+ int clickedIndex = 0;
+ QScatter3DSeries *clickedSeries = 0;
+ selectionColorToSeriesAndIndex(clickedColor, clickedIndex, clickedSeries);
+ emit itemClicked(clickedIndex, clickedSeries);
glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle);
- // Release selection shader
- m_selectionShader->release();
-
#if 0 // Use this if you want to see what is being drawn to the framebuffer
m_labelShader->bind();
glDisable(GL_DEPTH_TEST);
@@ -454,114 +563,189 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix);
m_drawer->drawObject(m_labelShader, m_labelObj, m_selectionTexture);
glDisable(GL_TEXTURE_2D);
- m_labelShader->release();
#endif
}
- // Bind dot shader
- m_dotShader->bind();
-
- // Set unchanging shader bindings
- m_dotShader->setUniformValue(m_dotShader->lightP(), lightPos);
- m_dotShader->setUniformValue(m_dotShader->view(), viewMatrix);
- m_dotShader->setUniformValue(m_dotShader->ambientS(), m_cachedTheme.m_ambientStrength);
-
- // Enable texture
- glEnable(GL_TEXTURE_2D);
-
// Draw dots
+ ShaderHelper *dotShader = 0;
+ GLuint gradientTexture = 0;
bool dotSelectionFound = false;
- int selectedIndex;
- if (m_selection == selectionSkipColor) {
- selectedIndex = Scatter3DController::noSelectionIndex();
+ ScatterRenderItem *selectedItem(0);
+ int dotNo = 0;
+ QVector3D baseColor;
+ QVector3D dotColor;
+
+ bool previousDrawingPoints = false;
+ Q3DTheme::ColorStyle previousMeshColorStyle = Q3DTheme::ColorStyleUniform;
+ if (haveMeshSeries) {
+ // Set unchanging shader bindings
+ if (haveGradientMeshSeries) {
+ m_dotGradientShader->bind();
+ m_dotGradientShader->setUniformValue(m_dotGradientShader->lightP(), lightPos);
+ m_dotGradientShader->setUniformValue(m_dotGradientShader->view(), viewMatrix);
+ m_dotGradientShader->setUniformValue(m_dotGradientShader->ambientS(), m_cachedTheme->ambientLightStrength());
+ }
+ if (haveUniformColorMeshSeries) {
+ m_dotShader->bind();
+ m_dotShader->setUniformValue(m_dotShader->lightP(), lightPos);
+ m_dotShader->setUniformValue(m_dotShader->view(), viewMatrix);
+ m_dotShader->setUniformValue(m_dotShader->ambientS(), m_cachedTheme->ambientLightStrength());
+ dotShader = m_dotShader;
+ } else {
+ dotShader = m_dotGradientShader;
+ previousMeshColorStyle = Q3DTheme::ColorStyleRangeGradient;
+ m_dotGradientShader->setUniformValue(m_dotGradientShader->gradientHeight(), 0.0f);
+ }
+ glEnable(GL_TEXTURE_2D);
} else {
- selectedIndex = int(m_selection.x())
- + (int(m_selection.y()) << 8)
- + (int(m_selection.z()) << 16);
+ dotShader = pointSelectionShader;
+ previousDrawingPoints = true;
+ dotShader->bind();
}
- if (m_selection != m_previousSelection) {
- emit selectedItemIndexChanged(selectedIndex);
- m_previousSelection = m_selection;
- }
+ for (int series = 0; series < seriesCount; series++) {
+ const SeriesRenderCache &currentSeries = m_visibleSeriesList.at(series);
+ ObjectHelper *dotObj = currentSeries.object();
+ bool drawingPoints = (currentSeries.mesh() == QAbstract3DSeries::MeshPoint);
+ Q3DTheme::ColorStyle colorStyle = currentSeries.colorStyle();
+ bool colorStyleIsUniform = (colorStyle == Q3DTheme::ColorStyleUniform);
+ bool useColor = colorStyleIsUniform || drawingPoints;
+
+ // TODO: Accessing series directly during rendering
+ float itemSize =
+ static_cast<QScatter3DSeries *>(currentSeries.series())->itemSize()
+ / itemScaler;
+ if (itemSize == 0.0f)
+ itemSize = m_dotSizeScale;
+#if !defined(QT_OPENGL_ES_2)
+ if (drawingPoints)
+ glPointSize(itemSize * activeCamera->zoomLevel()); // Scale points based on zoom
+#endif
+ QVector3D modelScaler(itemSize, itemSize, itemSize);
+
+ // Rebind shader if it has changed
+ if (drawingPoints != previousDrawingPoints
+ || (!drawingPoints &&
+ (colorStyleIsUniform != (previousMeshColorStyle == Q3DTheme::ColorStyleUniform)))) {
+ previousDrawingPoints = drawingPoints;
+ if (drawingPoints) {
+ dotShader = pointSelectionShader;
+ } else {
+ if (colorStyleIsUniform)
+ dotShader = m_dotShader;
+ else
+ dotShader = m_dotGradientShader;
+ }
+ dotShader->bind();
+ }
- ScatterRenderItem *selectedItem(0);
+ if (!drawingPoints && !colorStyleIsUniform && previousMeshColorStyle != colorStyle) {
+ if (colorStyle == Q3DTheme::ColorStyleObjectGradient) {
+ m_dotGradientShader->setUniformValue(m_dotGradientShader->gradientMin(), 0.0f);
+ m_dotGradientShader->setUniformValue(m_dotGradientShader->gradientHeight(), 0.5f);
+ } else {
+ // Each ball is of uniform color according to its Y-coordinate
+ m_dotGradientShader->setUniformValue(m_dotGradientShader->gradientHeight(), 0.0f);
+ }
+ }
- QVector3D baseColor = Utils::vectorFromColor(m_cachedTheme.m_baseColor);
+ if (!drawingPoints)
+ previousMeshColorStyle = colorStyle;
- for (int dot = 0; dot < m_renderItemArray.size(); dot++) {
- ScatterRenderItem &item = m_renderItemArray[dot];
- if (!item.isVisible())
- continue;
+ if (useColor) {
+ baseColor = currentSeries.baseColor();
+ dotColor = baseColor;
+ }
- QMatrix4x4 modelMatrix;
- QMatrix4x4 MVPMatrix;
- QMatrix4x4 itModelMatrix;
+ int seriesSize = m_renderingArrays.at(series).size();
+ for (int dot = 0; dot < seriesSize; dot++) {
+ ScatterRenderItem &item = m_renderingArrays[series][dot];
+ if (!item.isVisible())
+ continue;
- modelMatrix.translate(item.translation());
- modelMatrix.scale(modelScaler);
- //modelMatrix.scale(QVector3D(widthMultiplier * item.size() + widthScaler,
- // heightMultiplier * item.size() + heightScaler,
- // depthMultiplier * item.size() + depthScaler));
- itModelMatrix.scale(modelScaler);
- //itModelMatrix.scale(QVector3D(widthMultiplier * item.size() + widthScaler,
- // heightMultiplier * item.size() + heightScaler,
- // depthMultiplier * item.size() + depthScaler));
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+ QMatrix4x4 itModelMatrix;
+ modelMatrix.translate(item.translation());
+ if (!drawingPoints) {
+ modelMatrix.scale(modelScaler);
+ itModelMatrix.scale(modelScaler);
+ }
#ifdef SHOW_DEPTH_TEXTURE_SCENE
- MVPMatrix = depthProjectionViewMatrix * modelMatrix;
-#else
- MVPMatrix = projectionViewMatrix * modelMatrix;
-#endif
-
-#if 0
- QVector3D heightColor =
- Utils::vectorFromColor(m_cachedTheme.m_heightColor) * item.translation().y();
-
- QVector3D dotColor = baseColor + heightColor;
+ MVPMatrix = depthProjectionViewMatrix * modelMatrix;
#else
- QVector3D dotColor = baseColor;
+ MVPMatrix = projectionViewMatrix * modelMatrix;
#endif
- GLfloat lightStrength = m_cachedTheme.m_lightStrength;
- if (m_cachedSelectionMode > QDataVis::SelectionModeNone && (selectedIndex == dot)) {
- dotColor = Utils::vectorFromColor(m_cachedTheme.m_highlightBarColor);
- lightStrength = m_cachedTheme.m_highlightLightStrength;
- // Insert data to ScatterRenderItem. We have no ownership, don't delete the previous one
- selectedItem = &item;
- dotSelectionFound = true;
- }
+ if (useColor)
+ dotColor = baseColor;
+ else
+ gradientTexture = currentSeries.baseGradientTexture();
- // Set shader bindings
- m_dotShader->setUniformValue(m_dotShader->model(), modelMatrix);
- m_dotShader->setUniformValue(m_dotShader->nModel(),
- itModelMatrix.inverted().transposed());
- m_dotShader->setUniformValue(m_dotShader->MVP(), MVPMatrix);
- m_dotShader->setUniformValue(m_dotShader->color(), dotColor);
+ GLfloat lightStrength = m_cachedTheme->lightStrength();
+ if (m_cachedSelectionMode > QDataVis::SelectionNone && (m_selectedItemTotalIndex == dotNo)) {
+ if (useColor)
+ dotColor = currentSeries.singleHighlightColor();
+ else
+ gradientTexture = currentSeries.singleHighlightGradientTexture();
+ lightStrength = m_cachedTheme->highlightLightStrength();
+ // Insert data to ScatterRenderItem. We have no ownership, don't delete the previous one
+ selectedItem = &item;
+ dotSelectionFound = true;
+ }
+ if (!drawingPoints) {
+ // Set shader bindings
+ dotShader->setUniformValue(dotShader->model(), modelMatrix);
+ dotShader->setUniformValue(dotShader->nModel(),
+ itModelMatrix.inverted().transposed());
+ }
+ dotShader->setUniformValue(dotShader->MVP(), MVPMatrix);
+ if (useColor) {
+ dotShader->setUniformValue(dotShader->color(), dotColor);
+ } else if (colorStyle == Q3DTheme::ColorStyleRangeGradient) {
+ dotShader->setUniformValue(dotShader->gradientMin(),
+ (item.position().y() + 1.0f) / 2.0f);
+ }
#if !defined(QT_OPENGL_ES_2)
- if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
- // Set shadow shader bindings
- QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix;
- m_dotShader->setUniformValue(m_dotShader->shadowQ(), m_shadowQualityToShader);
- m_dotShader->setUniformValue(m_dotShader->depth(), depthMVPMatrix);
- m_dotShader->setUniformValue(m_dotShader->lightS(), lightStrength / 10.0f);
+ if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
+ if (!drawingPoints) {
+ // Set shadow shader bindings
+ QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix;
+ dotShader->setUniformValue(dotShader->shadowQ(), m_shadowQualityToShader);
+ dotShader->setUniformValue(dotShader->depth(), depthMVPMatrix);
+ dotShader->setUniformValue(dotShader->lightS(), lightStrength / 10.0f);
- // Draw the object
- m_drawer->drawObject(m_dotShader, m_dotObj, 0, m_depthTexture);
- } else
+ // Draw the object
+ m_drawer->drawObject(dotShader, dotObj, gradientTexture, m_depthTexture);
+ } else {
+ // Draw the object
+ m_drawer->drawPoint(dotShader);
+ }
+ } else
#endif
- {
- // Set shadowless shader bindings
- m_dotShader->setUniformValue(m_dotShader->lightS(), lightStrength);
-
- // Draw the object
- m_drawer->drawObject(m_dotShader, m_dotObj);
+ {
+ if (!drawingPoints) {
+ // Set shadowless shader bindings
+ dotShader->setUniformValue(dotShader->lightS(), lightStrength);
+ // Draw the object
+ m_drawer->drawObject(dotShader, dotObj, gradientTexture);
+ } else {
+ // Draw the object
+ m_drawer->drawPoint(dotShader);
+ }
+ }
+ dotNo++;
}
}
- // Release dot shader
- m_dotShader->release();
+#if !defined(QT_OPENGL_ES_2)
+ if (havePointSeries) {
+ glDisable(GL_POINT_SMOOTH);
+ glDisable(GL_PROGRAM_POINT_SIZE);
+ }
+#endif
// Bind background shader
m_backgroundShader->bind();
@@ -569,19 +753,23 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
glCullFace(GL_BACK);
// Draw background
- if (m_cachedIsBackgroundEnabled && m_backgroundObj) {
+ if (m_cachedTheme->isBackgroundEnabled() && m_backgroundObj) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z
- QVector3D bgScale((aspectRatio * backgroundMargin * m_areaSize.width()) / m_scaleFactor,
- backgroundMargin,
- (aspectRatio * backgroundMargin * m_areaSize.height()) / m_scaleFactor);
+ GLfloat xScale = (aspectRatio * m_backgroundMargin * m_areaSize.width()) / m_scaleFactor;
+ GLfloat zScale = (aspectRatio * m_backgroundMargin * m_areaSize.height()) / m_scaleFactor;
+ if (m_maxItemSize > xScale)
+ xScale = m_maxItemSize;
+ if (m_maxItemSize > zScale)
+ zScale = m_maxItemSize;
+ QVector3D bgScale(xScale, m_backgroundMargin, zScale);
#else // ..and this if we want uniform scaling based on largest dimension
- QVector3D bgScale((aspectRatio * backgroundMargin),
- backgroundMargin,
- (aspectRatio * backgroundMargin));
+ QVector3D bgScale((aspectRatio * m_backgroundMargin),
+ m_backgroundMargin,
+ (aspectRatio * m_backgroundMargin));
#endif
modelMatrix.scale(bgScale);
// If we're viewing from below, background object must be flipped
@@ -598,7 +786,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
#else
MVPMatrix = projectionViewMatrix * modelMatrix;
#endif
- QVector3D backgroundColor = Utils::vectorFromColor(m_cachedTheme.m_backgroundColor);
+ QVector3D backgroundColor = Utils::vectorFromColor(m_cachedTheme->backgroundColor());
// Set shader bindings
m_backgroundShader->setUniformValue(m_backgroundShader->lightP(), lightPos);
@@ -609,7 +797,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
m_backgroundShader->setUniformValue(m_backgroundShader->MVP(), MVPMatrix);
m_backgroundShader->setUniformValue(m_backgroundShader->color(), backgroundColor);
m_backgroundShader->setUniformValue(m_backgroundShader->ambientS(),
- m_cachedTheme.m_ambientStrength * 2.0f);
+ m_cachedTheme->ambientLightStrength() * 2.0f);
#if !defined(QT_OPENGL_ES_2)
if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
@@ -619,7 +807,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
m_shadowQualityToShader);
m_backgroundShader->setUniformValue(m_backgroundShader->depth(), depthMVPMatrix);
m_backgroundShader->setUniformValue(m_backgroundShader->lightS(),
- m_cachedTheme.m_lightStrength / 10.0f);
+ m_cachedTheme->lightStrength() / 10.0f);
// Draw the object
m_drawer->drawObject(m_backgroundShader, m_backgroundObj, 0, m_depthTexture);
@@ -628,16 +816,13 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
{
// Set shadowless shader bindings
m_backgroundShader->setUniformValue(m_backgroundShader->lightS(),
- m_cachedTheme.m_lightStrength);
+ m_cachedTheme->lightStrength());
// Draw the object
m_drawer->drawObject(m_backgroundShader, m_backgroundObj);
}
}
- // Release background shader
- m_backgroundShader->release();
-
// Disable textures
glDisable(GL_TEXTURE_2D);
@@ -650,37 +835,54 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
axisCacheMax = &m_axisCacheX;
#endif
- if (m_cachedIsGridEnabled && m_heightNormalizer) {
+ if (m_cachedTheme->isGridEnabled() && m_heightNormalizer) {
ShaderHelper *lineShader = m_backgroundShader;
// Bind line shader
lineShader->bind();
// Set unchanging shader bindings
- QVector3D lineColor = Utils::vectorFromColor(m_cachedTheme.m_gridLine);
+ QVector3D lineColor = Utils::vectorFromColor(m_cachedTheme->gridLineColor());
lineShader->setUniformValue(lineShader->lightP(), lightPos);
lineShader->setUniformValue(lineShader->view(), viewMatrix);
lineShader->setUniformValue(lineShader->color(), lineColor);
- lineShader->setUniformValue(lineShader->ambientS(), m_cachedTheme.m_ambientStrength);
+ lineShader->setUniformValue(lineShader->ambientS(), m_cachedTheme->ambientLightStrength());
#if !defined(QT_OPENGL_ES_2)
if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
// Set shadowed shader bindings
lineShader->setUniformValue(lineShader->shadowQ(), m_shadowQualityToShader);
lineShader->setUniformValue(lineShader->lightS(),
- m_cachedTheme.m_lightStrength / 20.0f);
+ m_cachedTheme->lightStrength() / 20.0f);
} else
#endif
{
// Set shadowless shader bindings
- lineShader->setUniformValue(lineShader->lightS(), m_cachedTheme.m_lightStrength / 2.5f);
+ lineShader->setUniformValue(lineShader->lightS(), m_cachedTheme->lightStrength() / 2.5f);
}
+ QQuaternion lineYRotation = QQuaternion();
+ QQuaternion lineXRotation = QQuaternion();
+
+ if (m_xFlipped)
+ lineYRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, -90.0f);
+ else
+ lineYRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, 90.0f);
+
+ if (m_yFlipped)
+ lineXRotation = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, 90.0f);
+ else
+ lineXRotation = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, -90.0f);
+
+ GLfloat yFloorLinePosition = -m_backgroundMargin + gridLineOffset;
+ if (m_yFlipped)
+ yFloorLinePosition = -yFloorLinePosition;
+
// Rows (= Z)
if (m_axisCacheZ.segmentCount() > 0) {
// Floor lines
#ifndef USE_UNIFORM_SCALING
GLfloat lineStep = aspectRatio * m_axisCacheZ.subSegmentStep();
- GLfloat linePos = -aspectRatio * m_axisCacheZ.min(); // Start line
+ GLfloat linePos = -aspectRatio * (m_axisCacheZ.min() - m_translationOffset.z()); // Start line
int lastSegment = m_axisCacheZ.subSegmentCount() * m_axisCacheZ.segmentCount();
#else
GLfloat lineStep = aspectRatio * axisCacheMax->subSegmentStep();
@@ -689,11 +891,12 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
#endif
#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z
- QVector3D gridLineScaler(
- (aspectRatio * backgroundMargin * m_areaSize.width()) / m_scaleFactor,
- gridLineWidth, gridLineWidth);
+ GLfloat xScale = (aspectRatio * m_backgroundMargin * m_areaSize.width()) / m_scaleFactor;
+ if (m_maxItemSize > xScale)
+ xScale = m_maxItemSize;
+ QVector3D gridLineScaler(xScale, gridLineWidth, gridLineWidth);
#else // ..and this if we want uniform scaling based on largest dimension
- QVector3D gridLineScaler((aspectRatio * backgroundMargin),
+ QVector3D gridLineScaler((aspectRatio * m_backgroundMargin),
gridLineWidth, gridLineWidth);
#endif
@@ -702,19 +905,13 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- if (m_yFlipped)
- modelMatrix.translate(0.0f, backgroundMargin, linePos / m_scaleFactor);
- else
- modelMatrix.translate(0.0f, -backgroundMargin, linePos / m_scaleFactor);
+ modelMatrix.translate(0.0f, yFloorLinePosition, linePos / m_scaleFactor);
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
- // If we're viewing from below, grid line object must be flipped
- if (m_yFlipped) {
- modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
- itModelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
- }
+ modelMatrix.rotate(lineXRotation);
+ itModelMatrix.rotate(lineXRotation);
MVPMatrix = projectionViewMatrix * modelMatrix;
@@ -741,13 +938,15 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
}
// Side wall lines
- gridLineScaler = QVector3D(gridLineWidth, backgroundMargin, gridLineWidth);
+ gridLineScaler = QVector3D(gridLineWidth, m_backgroundMargin, gridLineWidth);
#ifndef USE_UNIFORM_SCALING
- GLfloat lineXTrans = (aspectRatio * backgroundMargin * m_areaSize.width())
- / m_scaleFactor;
- linePos = -aspectRatio * m_axisCacheZ.min(); // Start line
+ GLfloat lineXTrans = (aspectRatio * m_backgroundMargin * m_areaSize.width())
+ / m_scaleFactor - gridLineOffset;
+ if (m_maxItemSize > lineXTrans)
+ lineXTrans = m_maxItemSize - gridLineOffset;
+ linePos = -aspectRatio * (m_axisCacheZ.min() - m_translationOffset.z()); // Start line
#else
- GLfloat lineXTrans = aspectRatio * backgroundMargin;
+ GLfloat lineXTrans = aspectRatio * m_backgroundMargin - gridLineOffset;
linePos = -aspectRatio * m_scaleFactor; // Start line
#endif
if (!m_xFlipped)
@@ -759,9 +958,13 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
QMatrix4x4 itModelMatrix;
modelMatrix.translate(lineXTrans, 0.0f, linePos / m_scaleFactor);
+
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
+ modelMatrix.rotate(lineYRotation);
+ itModelMatrix.rotate(lineYRotation);
+
MVPMatrix = projectionViewMatrix * modelMatrix;
// Set the rest of the shader bindings
@@ -792,17 +995,18 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
// Floor lines
#ifndef USE_UNIFORM_SCALING
GLfloat lineStep = aspectRatio * m_axisCacheX.subSegmentStep();
- GLfloat linePos = aspectRatio * m_axisCacheX.min();
+ GLfloat linePos = aspectRatio * (m_axisCacheX.min() - m_translationOffset.x());
int lastSegment = m_axisCacheX.subSegmentCount() * m_axisCacheX.segmentCount();
- QVector3D gridLineScaler(
- gridLineWidth, gridLineWidth,
- (aspectRatio * backgroundMargin * m_areaSize.height()) / m_scaleFactor);
+ GLfloat zScale = (aspectRatio * m_backgroundMargin * m_areaSize.height()) / m_scaleFactor;
+ if (m_maxItemSize > zScale)
+ zScale = m_maxItemSize;
+ QVector3D gridLineScaler(gridLineWidth, gridLineWidth, zScale);
#else
GLfloat lineStep = aspectRatio * axisCacheMax->subSegmentStep();
GLfloat linePos = -aspectRatio * m_scaleFactor;
int lastSegment = axisCacheMax->subSegmentCount() * axisCacheMax->segmentCount();
QVector3D gridLineScaler(gridLineWidth, gridLineWidth,
- aspectRatio * backgroundMargin);
+ aspectRatio * m_backgroundMargin);
#endif
for (int segment = 0; segment <= lastSegment; segment++) {
@@ -810,18 +1014,13 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- if (m_yFlipped)
- modelMatrix.translate(linePos / m_scaleFactor, backgroundMargin, 0.0f);
- else
- modelMatrix.translate(linePos / m_scaleFactor, -backgroundMargin, 0.0f);
+ modelMatrix.translate(linePos / m_scaleFactor, yFloorLinePosition, 0.0f);
+
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
- // If we're viewing from below, grid line object must be flipped
- if (m_yFlipped) {
- modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
- itModelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
- }
+ modelMatrix.rotate(lineXRotation);
+ itModelMatrix.rotate(lineXRotation);
MVPMatrix = projectionViewMatrix * modelMatrix;
@@ -849,17 +1048,19 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
// Back wall lines
#ifndef USE_UNIFORM_SCALING
- GLfloat lineZTrans = (aspectRatio * backgroundMargin * m_areaSize.height())
- / m_scaleFactor;
- linePos = aspectRatio * m_axisCacheX.min();
+ GLfloat lineZTrans = (aspectRatio * m_backgroundMargin * m_areaSize.height())
+ / m_scaleFactor - gridLineOffset;
+ if (m_maxItemSize > lineZTrans)
+ lineZTrans = m_maxItemSize - gridLineOffset;
+ linePos = aspectRatio * (m_axisCacheX.min() - m_translationOffset.x());
#else
- GLfloat lineZTrans = aspectRatio * backgroundMargin;
+ GLfloat lineZTrans = aspectRatio * m_backgroundMargin - gridLineOffset;
linePos = -aspectRatio * m_scaleFactor;
#endif
if (!m_zFlipped)
lineZTrans = -lineZTrans;
- gridLineScaler = QVector3D(gridLineWidth, backgroundMargin, gridLineWidth);
+ gridLineScaler = QVector3D(gridLineWidth, m_backgroundMargin, gridLineWidth);
for (int segment = 0; segment <= lastSegment; segment++) {
QMatrix4x4 modelMatrix;
@@ -867,9 +1068,15 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
QMatrix4x4 itModelMatrix;
modelMatrix.translate(linePos / m_scaleFactor, 0.0f, lineZTrans);
+
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
+ if (m_zFlipped) {
+ modelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
+ itModelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
+ }
+
MVPMatrix = projectionViewMatrix * modelMatrix;
// Set the rest of the shader bindings
@@ -899,18 +1106,21 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
if (m_axisCacheY.segmentCount() > 0) {
// Back wall
GLfloat lineStep = m_axisCacheY.subSegmentStep();
- GLfloat linePos = m_axisCacheY.min();
+ GLfloat linePos = m_axisCacheY.min() - m_translationOffset.y();
int lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount();
#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z
- GLfloat lineZTrans = (aspectRatio * backgroundMargin * m_areaSize.height())
- / m_scaleFactor;
- QVector3D gridLineScaler(
- (aspectRatio * backgroundMargin * m_areaSize.width() / m_scaleFactor),
- gridLineWidth, gridLineWidth);
+ GLfloat lineZTrans = (aspectRatio * m_backgroundMargin * m_areaSize.height())
+ / m_scaleFactor - gridLineOffset;
+ if (m_maxItemSize > lineZTrans)
+ lineZTrans = m_maxItemSize - gridLineOffset;
+ GLfloat xScale = (aspectRatio * m_backgroundMargin * m_areaSize.width()) / m_scaleFactor;
+ if (m_maxItemSize > xScale)
+ xScale = m_maxItemSize;
+ QVector3D gridLineScaler(xScale, gridLineWidth, gridLineWidth);
#else // ..and this if we want uniform scaling based on largest dimension
- GLfloat lineZTrans = aspectRatio * backgroundMargin;
- QVector3D gridLineScaler((aspectRatio * backgroundMargin),
+ GLfloat lineZTrans = aspectRatio * m_backgroundMargin - gridLineOffset;
+ QVector3D gridLineScaler((aspectRatio * m_backgroundMargin),
gridLineWidth, gridLineWidth);
#endif
if (!m_zFlipped)
@@ -926,6 +1136,11 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
+ if (m_zFlipped) {
+ modelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
+ itModelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
+ }
+
MVPMatrix = projectionViewMatrix * modelMatrix;
// Set the rest of the shader bindings
@@ -951,18 +1166,22 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
}
// Side wall
- linePos = m_axisCacheY.min();
+ linePos = m_axisCacheY.min() - m_translationOffset.y();
lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount();
#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z
- GLfloat lineXTrans = (aspectRatio * backgroundMargin * m_areaSize.width())
+ GLfloat lineXTrans = (aspectRatio * m_backgroundMargin * m_areaSize.width())
+ / m_scaleFactor - gridLineOffset;
+ if (m_maxItemSize > lineXTrans)
+ lineXTrans = m_maxItemSize - gridLineOffset;
+ GLfloat zScale = (aspectRatio * m_backgroundMargin * m_areaSize.height())
/ m_scaleFactor;
- gridLineScaler = QVector3D(
- gridLineWidth, gridLineWidth,
- (aspectRatio * backgroundMargin * m_areaSize.height()) / m_scaleFactor);
+ if (m_maxItemSize > zScale)
+ zScale = m_maxItemSize;
+ gridLineScaler = QVector3D(gridLineWidth, gridLineWidth, zScale);
#else // ..and this if we want uniform scaling based on largest dimension
- GLfloat lineXTrans = aspectRatio * backgroundMargin;
+ GLfloat lineXTrans = aspectRatio * m_backgroundMargin - gridLineOffset;
gridLineScaler = QVector3D(gridLineWidth, gridLineWidth,
- aspectRatio * backgroundMargin);
+ aspectRatio * m_backgroundMargin);
#endif
if (!m_xFlipped)
lineXTrans = -lineXTrans;
@@ -977,6 +1196,9 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
+ modelMatrix.rotate(lineYRotation);
+ itModelMatrix.rotate(lineYRotation);
+
MVPMatrix = projectionViewMatrix * modelMatrix;
// Set the rest of the shader bindings
@@ -1001,9 +1223,6 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
linePos += lineStep;
}
}
-
- // Release line shader
- lineShader->release();
}
// Draw axis labels
@@ -1015,23 +1234,26 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_POLYGON_OFFSET_FILL);
// Z Labels
if (m_axisCacheZ.segmentCount() > 0) {
#ifndef USE_UNIFORM_SCALING
GLfloat posStep = aspectRatio * m_axisCacheZ.segmentStep();
- GLfloat labelPos = -aspectRatio * m_axisCacheZ.min();
+ GLfloat labelPos = -aspectRatio * (m_axisCacheZ.min() - m_translationOffset.z());
int lastSegment = m_axisCacheZ.segmentCount();
- GLfloat labelXTrans = (aspectRatio * backgroundMargin * m_areaSize.width())
+ GLfloat labelXTrans = (aspectRatio * m_backgroundMargin * m_areaSize.width())
/ m_scaleFactor + labelMargin;
+ if (m_maxItemSize > labelXTrans)
+ labelXTrans = m_maxItemSize + labelMargin;
#else
GLfloat posStep = aspectRatio * axisCacheMax->segmentStep();
GLfloat labelPos = aspectRatio * m_scaleFactor;
int lastSegment = axisCacheMax->segmentCount();
- GLfloat labelXTrans = aspectRatio * backgroundMargin + labelMargin;
+ GLfloat labelXTrans = aspectRatio * m_backgroundMargin + labelMargin;
#endif
int labelNbr = 0;
- GLfloat labelYTrans = -backgroundMargin;
+ GLfloat labelYTrans = -m_backgroundMargin;
GLfloat rotLabelX = -90.0f;
GLfloat rotLabelY = 0.0f;
GLfloat rotLabelZ = 0.0f;
@@ -1057,6 +1279,8 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
#endif
labelTrans.setZ(labelPos / m_scaleFactor);
+ glPolygonOffset(GLfloat(segment) / -10.0f, 1.0f);
+
// Draw the label here
m_dummyRenderItem.setTranslation(labelTrans);
#ifndef USE_UNIFORM_SCALING
@@ -1078,18 +1302,20 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
if (m_axisCacheX.segmentCount() > 0) {
#ifndef USE_UNIFORM_SCALING
GLfloat posStep = aspectRatio * m_axisCacheX.segmentStep();
- GLfloat labelPos = aspectRatio * m_axisCacheX.min();
+ GLfloat labelPos = aspectRatio * (m_axisCacheX.min() - m_translationOffset.x());
int lastSegment = m_axisCacheX.segmentCount();
- GLfloat labelZTrans = (aspectRatio * backgroundMargin * m_areaSize.height())
+ GLfloat labelZTrans = (aspectRatio * m_backgroundMargin * m_areaSize.height())
/ m_scaleFactor + labelMargin;
+ if (m_maxItemSize > labelZTrans)
+ labelZTrans = m_maxItemSize + labelMargin;
#else
GLfloat posStep = aspectRatio * axisCacheMax->segmentStep();
GLfloat labelPos = -aspectRatio * m_scaleFactor;
int lastSegment = axisCacheMax->segmentCount();
- GLfloat labelZTrans = aspectRatio * backgroundMargin + labelMargin;
+ GLfloat labelZTrans = aspectRatio * m_backgroundMargin + labelMargin;
#endif
int labelNbr = 0;
- GLfloat labelYTrans = -backgroundMargin;
+ GLfloat labelYTrans = -m_backgroundMargin;
GLfloat rotLabelX = -90.0f;
GLfloat rotLabelY = 90.0f;
GLfloat rotLabelZ = 0.0f;
@@ -1115,6 +1341,8 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
#endif
labelTrans.setX(labelPos / m_scaleFactor);
+ glPolygonOffset(GLfloat(segment) / -10.0f, 1.0f);
+
// Draw the label here
m_dummyRenderItem.setTranslation(labelTrans);
#ifndef USE_UNIFORM_SCALING
@@ -1135,15 +1363,19 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
// Y Labels
if (m_axisCacheY.segmentCount() > 0) {
GLfloat posStep = m_axisCacheY.segmentStep();
- GLfloat labelPos = m_axisCacheY.min();
+ GLfloat labelPos = m_axisCacheY.min() - m_translationOffset.y();
int labelNbr = 0;
#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z
- GLfloat labelXTrans = (aspectRatio * backgroundMargin * m_areaSize.width())
+ GLfloat labelXTrans = (aspectRatio * m_backgroundMargin * m_areaSize.width())
/ m_scaleFactor;
- GLfloat labelZTrans = (aspectRatio * backgroundMargin * m_areaSize.height())
+ GLfloat labelZTrans = (aspectRatio * m_backgroundMargin * m_areaSize.height())
/ m_scaleFactor;
+ if (m_maxItemSize > labelXTrans)
+ labelXTrans = m_maxItemSize;
+ if (m_maxItemSize > labelZTrans)
+ labelZTrans = m_maxItemSize;
#else // ..and this if we want uniform scaling based on largest dimension
- GLfloat labelXTrans = aspectRatio * backgroundMargin;
+ GLfloat labelXTrans = aspectRatio * m_backgroundMargin;
GLfloat labelZTrans = labelXTrans;
#endif
// Back wall init
@@ -1185,6 +1417,8 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(labelNbr);
const GLfloat labelYTrans = labelPos / m_heightNormalizer;
+ glPolygonOffset(GLfloat(segment) / -10.0f, 1.0f);
+
// Back wall
labelTransBack.setY(labelYTrans);
m_dummyRenderItem.setTranslation(labelTransBack);
@@ -1205,6 +1439,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
labelPos += posStep;
}
}
+ glDisable(GL_POLYGON_OFFSET_FILL);
// Handle selection clearing and selection label drawing
if (!dotSelectionFound) {
@@ -1225,7 +1460,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
static const QString yLabelTag(QStringLiteral("@yLabel"));
static const QString zLabelTag(QStringLiteral("@zLabel"));
- labelText = itemLabelFormat();
+ labelText = m_visibleSeriesList[m_selectedItemSeriesIndex].itemLabelFormat();
labelText.replace(xTitleTag, m_axisCacheX.title());
labelText.replace(yTitleTag, m_axisCacheY.title());
@@ -1274,34 +1509,31 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
- // Release label shader
- m_labelShader->release();
-}
+ // Release shader
+ glUseProgram(0);
-void Scatter3DRenderer::updateSelectedItemIndex(int index)
-{
- if (index == Scatter3DController::noSelectionIndex())
- m_selection = selectionSkipColor;
- else
- m_selection = indexToSelectionColor(index);
+ m_selectionDirty = false;
}
-void Scatter3DRenderer::handleResize()
+void Scatter3DRenderer::updateSelectedItem(int index, const QScatter3DSeries *series)
{
- if (m_cachedBoundingRect.width() == 0 || m_cachedBoundingRect.height() == 0)
- return;
-
- // Set view port
- m_mainViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height());
-
- Abstract3DRenderer::handleResize();
-}
-
-void Scatter3DRenderer::updateBackgroundEnabled(bool enable)
-{
- if (enable != m_cachedIsBackgroundEnabled) {
- Abstract3DRenderer::updateBackgroundEnabled(enable);
- loadMeshFile(); // Load changed dot type
+ m_selectionDirty = true;
+ m_selectedSeries = series;
+ m_selectedItemIndex = Scatter3DController::invalidSelectionIndex();
+ m_selectedItemTotalIndex = Scatter3DController::invalidSelectionIndex();
+ m_selectedItemSeriesIndex = Scatter3DController::invalidSelectionIndex();
+
+ if (!m_renderingArrays.isEmpty() && index != Scatter3DController::invalidSelectionIndex()) {
+ int totalIndex = 0;
+ for (int i = 0; i < m_visibleSeriesList.size(); i++) {
+ if (m_visibleSeriesList.at(i).series() == series) {
+ m_selectedItemSeriesIndex = i;
+ m_selectedItemIndex = index;
+ m_selectedItemTotalIndex = index + totalIndex;
+ break;
+ }
+ totalIndex += m_renderingArrays.at(i).size();
+ }
}
}
@@ -1347,15 +1579,6 @@ void Scatter3DRenderer::updateShadowQuality(QDataVis::ShadowQuality quality)
#endif
}
-void Scatter3DRenderer::loadMeshFile()
-{
- QString objectFileName = m_cachedObjFile;
- if (m_dotObj)
- delete m_dotObj;
- m_dotObj = new ObjectHelper(objectFileName);
- m_dotObj->load();
-}
-
void Scatter3DRenderer::loadBackgroundMesh()
{
if (m_backgroundObj)
@@ -1368,7 +1591,7 @@ void Scatter3DRenderer::loadGridLineMesh()
{
if (m_gridLineObj)
delete m_gridLineObj;
- m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/bar"));
+ m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/plane"));
m_gridLineObj->load();
}
@@ -1376,7 +1599,7 @@ void Scatter3DRenderer::loadLabelMesh()
{
if (m_labelObj)
delete m_labelObj;
- m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/label"));
+ m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/plane"));
m_labelObj->load();
}
@@ -1386,37 +1609,44 @@ void Scatter3DRenderer::updateTextures()
m_updateLabels = true;
}
+void Scatter3DRenderer::fixMeshFileName(QString &fileName, QAbstract3DSeries::Mesh mesh)
+{
+ // Load full version of meshes that have it available
+ if (mesh != QAbstract3DSeries::MeshSphere
+ && mesh != QAbstract3DSeries::MeshMinimal
+ && mesh != QAbstract3DSeries::MeshPoint) {
+ fileName.append(QStringLiteral("Full"));
+ }
+}
+
void Scatter3DRenderer::updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation,
- qreal min, qreal max)
+ float min, float max)
{
Abstract3DRenderer::updateAxisRange(orientation, min, max);
}
void Scatter3DRenderer::calculateTranslation(ScatterRenderItem &item)
{
- // Origin should be in the center of scene, ie. both positive and negative values are drawn
- // above background
-
// We need to normalize translations
- GLfloat xTrans = (aspectRatio * item.position().x()) / m_scaleFactor;
- GLfloat zTrans = -(aspectRatio * item.position().z()) / m_scaleFactor;
- GLfloat yTrans = item.position().y() / m_heightNormalizer;
+ GLfloat xTrans = (aspectRatio * (item.position().x() - m_translationOffset.x()))
+ / m_scaleFactor;
+ GLfloat zTrans = -(aspectRatio * (item.position().z() - m_translationOffset.z()))
+ / m_scaleFactor;
+ GLfloat yTrans = (item.position().y() - m_translationOffset.y()) / m_heightNormalizer;
item.setTranslation(QVector3D(xTrans, yTrans, zTrans));
- //qDebug() << item.translation();
}
void Scatter3DRenderer::calculateSceneScalingFactors()
{
- m_heightNormalizer = (GLfloat)qMax(qAbs(m_axisCacheY.max()), qAbs(m_axisCacheY.min()));
- m_areaSize.setHeight(qMax(qAbs(m_axisCacheZ.max()), qAbs(m_axisCacheZ.min())));
- m_areaSize.setWidth(qMax(qAbs(m_axisCacheX.max()), qAbs(m_axisCacheX.min())));
+ m_heightNormalizer = GLfloat(m_axisCacheY.max() - m_axisCacheY.min()) / 2.0f;
+ m_areaSize.setHeight((m_axisCacheZ.max() - m_axisCacheZ.min()) / 2.0f);
+ m_areaSize.setWidth((m_axisCacheX.max() - m_axisCacheX.min()) / 2.0f);
m_scaleFactor = qMax(m_areaSize.width(), m_areaSize.height());
- //qDebug() << m_heightNormalizer << m_areaSize << m_scaleFactor << m_axisCacheY.max() << m_axisCacheX.max() << m_axisCacheZ.max();
-}
-QRect Scatter3DRenderer::mainViewPort()
-{
- return m_mainViewPort;
+ // Calculate translation offsets
+ m_translationOffset = QVector3D((m_axisCacheX.max() + m_axisCacheX.min()) / 2.0f,
+ (m_axisCacheY.max() + m_axisCacheY.min()) / 2.0f,
+ (m_axisCacheZ.max() + m_axisCacheZ.min()) / 2.0f);
}
void Scatter3DRenderer::initShaders(const QString &vertexShader, const QString &fragmentShader)
@@ -1427,12 +1657,20 @@ void Scatter3DRenderer::initShaders(const QString &vertexShader, const QString &
m_dotShader->initialize();
}
+void Scatter3DRenderer::initGradientShaders(const QString &vertexShader, const QString &fragmentShader)
+{
+ if (m_dotGradientShader)
+ delete m_dotGradientShader;
+ m_dotGradientShader = new ShaderHelper(this, vertexShader, fragmentShader);
+ m_dotGradientShader->initialize();
+}
+
void Scatter3DRenderer::initSelectionShader()
{
if (m_selectionShader)
delete m_selectionShader;
- m_selectionShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSelection"),
- QStringLiteral(":/shaders/fragmentSelection"));
+ m_selectionShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexPlainColor"),
+ QStringLiteral(":/shaders/fragmentPlainColor"));
m_selectionShader->initialize();
}
@@ -1443,10 +1681,10 @@ void Scatter3DRenderer::initSelectionBuffer()
m_selectionTexture = 0;
}
- if (m_mainViewPort.size().isEmpty())
+ if (m_primarySubViewport.size().isEmpty())
return;
- m_selectionTexture = m_textureHelper->createSelectionTexture(m_mainViewPort.size(),
+ m_selectionTexture = m_textureHelper->createSelectionTexture(m_primarySubViewport.size(),
m_selectionFrameBuffer,
m_selectionDepthBuffer);
}
@@ -1468,52 +1706,26 @@ void Scatter3DRenderer::updateDepthBuffer()
m_depthTexture = 0;
}
- if (m_mainViewPort.size().isEmpty())
+ if (m_primarySubViewport.size().isEmpty())
return;
if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
- m_depthTexture = m_textureHelper->createDepthTexture(m_mainViewPort.size(),
- m_depthFrameBuffer,
- m_shadowQualityMultiplier);
- if (!m_depthTexture) {
- switch (m_cachedShadowQuality) {
- case QDataVis::ShadowQualityHigh:
- qWarning("Creating high quality shadows failed. Changing to medium quality.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualityMedium);
- updateShadowQuality(QDataVis::ShadowQualityMedium);
- break;
- case QDataVis::ShadowQualityMedium:
- qWarning("Creating medium quality shadows failed. Changing to low quality.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualityLow);
- updateShadowQuality(QDataVis::ShadowQualityLow);
- break;
- case QDataVis::ShadowQualityLow:
- qWarning("Creating low quality shadows failed. Switching shadows off.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualityNone);
- updateShadowQuality(QDataVis::ShadowQualityNone);
- break;
- case QDataVis::ShadowQualitySoftHigh:
- qWarning("Creating soft high quality shadows failed. Changing to soft medium quality.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualitySoftMedium);
- updateShadowQuality(QDataVis::ShadowQualitySoftMedium);
- break;
- case QDataVis::ShadowQualitySoftMedium:
- qWarning("Creating soft medium quality shadows failed. Changing to soft low quality.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualitySoftLow);
- updateShadowQuality(QDataVis::ShadowQualitySoftLow);
- break;
- case QDataVis::ShadowQualitySoftLow:
- qWarning("Creating soft low quality shadows failed. Switching shadows off.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualityNone);
- updateShadowQuality(QDataVis::ShadowQualityNone);
- break;
- default:
- // You'll never get here
- break;
- }
- }
+ m_depthTexture = m_textureHelper->createDepthTextureFrameBuffer(m_primarySubViewport.size(),
+ m_depthFrameBuffer,
+ m_shadowQualityMultiplier);
+ if (!m_depthTexture)
+ lowerShadowQuality();
}
}
+#else
+void Scatter3DRenderer::initPointShader()
+{
+ if (m_pointShader)
+ delete m_pointShader;
+ m_pointShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexPointES2"),
+ QStringLiteral(":/shaders/fragmentPlainColor"));
+ m_pointShader->initialize();
+}
#endif
void Scatter3DRenderer::initBackgroundShaders(const QString &vertexShader,
@@ -1542,4 +1754,26 @@ QVector3D Scatter3DRenderer::indexToSelectionColor(GLint index)
return QVector3D(dotIdxRed, dotIdxGreen, dotIdxBlue);
}
+void Scatter3DRenderer::selectionColorToSeriesAndIndex(const QVector3D &color, int &index, QScatter3DSeries *&series)
+{
+ if (color != selectionSkipColor) {
+ index = int(color.x())
+ + (int(color.y()) << 8)
+ + (int(color.z()) << 16);
+ // Find the series and adjust the index accordingly
+ for (int i = 0; i < m_renderingArrays.size(); i++) {
+ if (index < m_renderingArrays.at(i).size()) {
+ series = static_cast<QScatter3DSeries *>(m_visibleSeriesList.at(i).series());
+ return; // Valid found and already set to return parameters, so we can return
+ } else {
+ index -= m_renderingArrays.at(i).size();
+ }
+ }
+ }
+
+ // No valid match found
+ index = Scatter3DController::invalidSelectionIndex();
+ series = 0;
+}
+
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/scatter3drenderer_p.h b/src/datavisualization/engine/scatter3drenderer_p.h
index f444f891..30ec7489 100644
--- a/src/datavisualization/engine/scatter3drenderer_p.h
+++ b/src/datavisualization/engine/scatter3drenderer_p.h
@@ -52,25 +52,21 @@ class QT_DATAVISUALIZATION_EXPORT Scatter3DRenderer : public Abstract3DRenderer
Q_OBJECT
private:
- // TODO: Filter to the set of attributes to be moved to the model object.
- // * All GL rendering only related attribs should be moved out of this public set.
- // * All attribs that are modifiable from QML need to e in this set.
-
- Scatter3DController *m_controller;
-
// Internal state
ScatterRenderItem *m_selectedItem; // points to renderitem array
bool m_xFlipped;
bool m_zFlipped;
bool m_yFlipped;
- QRect m_mainViewPort;
bool m_updateLabels;
ShaderHelper *m_dotShader;
+ ShaderHelper *m_dotGradientShader;
+#if defined(QT_OPENGL_ES_2)
+ ShaderHelper *m_pointShader;
+#endif
ShaderHelper *m_depthShader;
ShaderHelper *m_selectionShader;
ShaderHelper *m_backgroundShader;
ShaderHelper *m_labelShader;
- ObjectHelper *m_dotObj;
ObjectHelper *m_backgroundObj;
ObjectHelper *m_gridLineObj;
ObjectHelper *m_labelObj;
@@ -84,37 +80,40 @@ private:
GLint m_shadowQualityMultiplier;
GLfloat m_heightNormalizer;
GLfloat m_scaleFactor;
- QVector3D m_selection;
- QVector3D m_previousSelection;
+ int m_selectedItemIndex;
+ int m_selectedItemTotalIndex;
+ int m_selectedItemSeriesIndex;
+ const QScatter3DSeries *m_selectedSeries;
QSizeF m_areaSize;
GLfloat m_dotSizeScale;
-
+ QVector3D m_translationOffset;
bool m_hasHeightAdjustmentChanged;
ScatterRenderItem m_dummyRenderItem;
-
- ScatterRenderItemArray m_renderItemArray;
+ QVector<ScatterRenderItemArray> m_renderingArrays;
+ GLfloat m_backgroundMargin;
+ GLfloat m_maxItemSize;
public:
explicit Scatter3DRenderer(Scatter3DController *controller);
~Scatter3DRenderer();
- void updateDataModel(QScatterDataProxy *dataProxy);
+ void updateSeries(const QList<QAbstract3DSeries *> &seriesList, bool updateVisibility);
+ void updateData();
void updateScene(Q3DScene *scene);
- void render(GLuint defaultFboHandle);
- QRect mainViewPort();
+ void render(GLuint defaultFboHandle);
protected:
virtual void initializeOpenGL();
- virtual void loadMeshFile();
private:
virtual void initShaders(const QString &vertexShader, const QString &fragmentShader);
+ virtual void initGradientShaders(const QString &vertexShader, const QString &fragmentShader);
virtual void updateShadowQuality(QDataVis::ShadowQuality quality);
virtual void updateTextures();
+ virtual void fixMeshFileName(QString &fileName, QAbstract3DSeries::Mesh mesh);
void drawScene(GLuint defaultFboHandle);
- void handleResize();
void loadBackgroundMesh();
void loadGridLineMesh();
@@ -126,6 +125,8 @@ private:
#if !defined(QT_OPENGL_ES_2)
void initDepthShader();
void updateDepthBuffer();
+#else
+ void initPointShader();
#endif
void calculateTranslation(ScatterRenderItem &item);
void calculateSceneScalingFactors();
@@ -135,19 +136,17 @@ private:
friend class ScatterRenderItem;
public slots:
- void updateBackgroundEnabled(bool enable);
-
// Overloaded from abstract renderer
- virtual void updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, qreal min, qreal max);
+ virtual void updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, float min, float max);
- void updateSelectedItemIndex(int index);
+ void updateSelectedItem(int index, const QScatter3DSeries *series);
signals:
- void selectionUpdated(QVector3D selection);
- void selectedItemIndexChanged(int index);
+ void itemClicked(int index, QScatter3DSeries *series);
private:
QVector3D indexToSelectionColor(GLint index);
+ void selectionColorToSeriesAndIndex(const QVector3D &color, int &index, QScatter3DSeries *&series);
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/selectionpointer.cpp b/src/datavisualization/engine/selectionpointer.cpp
index 19294ac8..c4eced30 100644
--- a/src/datavisualization/engine/selectionpointer.cpp
+++ b/src/datavisualization/engine/selectionpointer.cpp
@@ -43,9 +43,8 @@ SelectionPointer::SelectionPointer(Drawer *drawer)
m_labelObj(0),
m_pointObj(0),
m_textureHelper(0),
- m_isInitialized(false),
m_cachedTheme(drawer->theme()),
- m_labelStyle(QDataVis::LabelStyleFromTheme),
+ m_labelBackground(false),
m_drawer(drawer),
m_cachedScene(0)
{
@@ -60,27 +59,18 @@ SelectionPointer::~SelectionPointer()
delete m_labelShader;
delete m_pointShader;
delete m_labelObj;
- delete m_pointObj;
delete m_textureHelper;
}
void SelectionPointer::initializeOpenGL()
{
- if (m_isInitialized)
- return;
-
initializeOpenGLFunctions();
m_textureHelper = new TextureHelper();
m_drawer->initializeOpenGL();
initShaders();
-
loadLabelMesh();
- loadPointMesh();
-
- // Set initialized -flag
- m_isInitialized = true;
}
void SelectionPointer::updateScene(Q3DScene *scene)
@@ -142,16 +132,13 @@ void SelectionPointer::render(GLuint defaultFboHandle)
m_pointShader->setUniformValue(m_pointShader->view(), viewMatrix);
m_pointShader->setUniformValue(m_pointShader->model(), modelMatrix);
m_pointShader->setUniformValue(m_pointShader->nModel(), itModelMatrix.inverted().transposed());
- m_pointShader->setUniformValue(m_pointShader->color(),
- Utils::vectorFromColor(m_cachedTheme.m_highlightBarColor));
+ m_pointShader->setUniformValue(m_pointShader->color(), m_highlightColor);
m_pointShader->setUniformValue(m_pointShader->MVP(), MVPMatrix);
- m_pointShader->setUniformValue(m_pointShader->ambientS(), m_cachedTheme.m_ambientStrength);
- m_pointShader->setUniformValue(m_pointShader->lightS(), m_cachedTheme.m_lightStrength * 2.0f);
+ m_pointShader->setUniformValue(m_pointShader->ambientS(), m_cachedTheme->ambientLightStrength());
+ m_pointShader->setUniformValue(m_pointShader->lightS(), m_cachedTheme->lightStrength() * 2.0f);
m_drawer->drawObject(m_pointShader, m_pointObj);
- m_pointShader->release();
-
//
// Draw the label
//
@@ -162,8 +149,8 @@ void SelectionPointer::render(GLuint defaultFboHandle)
modelMatrixLabel.translate(m_position + labelAlign);
// Position the label towards the camera
- qreal camRotationsX = camera->xRotation();
- qreal camRotationsY = camera->yRotation();
+ float camRotationsX = camera->xRotation();
+ float camRotationsY = camera->yRotation();
if (!m_cachedIsSlicingActivated) {
modelMatrixLabel.rotate(-camRotationsX, 0.0f, 1.0f, 0.0f);
modelMatrixLabel.rotate(-camRotationsY, 1.0f, 0.0f, 0.0f);
@@ -190,7 +177,8 @@ void SelectionPointer::render(GLuint defaultFboHandle)
// Draw the object
m_drawer->drawObject(m_labelShader, m_labelObj, m_labelItem.textureId());
- m_labelShader->release();
+ // Release shader
+ glUseProgram(0);
// Disable textures
glDisable(GL_TEXTURE_2D);
@@ -213,13 +201,22 @@ void SelectionPointer::updateSliceData(bool sliceActivated, GLfloat autoScaleAdj
m_autoScaleAdjustment = autoScaleAdjustment;
}
-void SelectionPointer::setLabel(QString label)
+void SelectionPointer::setHighlightColor(QVector3D colorVector)
{
- m_label = label;
+ m_highlightColor = colorVector;
+}
+void SelectionPointer::setLabel(const QString &label)
+{
+ m_label = label;
m_drawer->generateLabelItem(m_labelItem, m_label);
}
+void SelectionPointer::setPointerObject(ObjectHelper *object)
+{
+ m_pointObj = object;
+}
+
void SelectionPointer::handleDrawerChange()
{
m_cachedTheme = m_drawer->theme();
@@ -247,7 +244,7 @@ void SelectionPointer::initShaders()
m_pointShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
QStringLiteral(":/shaders/fragment"));
#else
- m_pointShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexES2"),
+ m_pointShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
QStringLiteral(":/shaders/fragmentES2"));
#endif
m_pointShader->initialize();
@@ -258,16 +255,8 @@ void SelectionPointer::loadLabelMesh()
{
if (m_labelObj)
delete m_labelObj;
- m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/label"));
+ m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/plane"));
m_labelObj->load();
}
-void SelectionPointer::loadPointMesh()
-{
- if (m_pointObj)
- delete m_pointObj;
- m_pointObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/sphereSmooth"));
- m_pointObj->load();
-}
-
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/selectionpointer_p.h b/src/datavisualization/engine/selectionpointer_p.h
index 0e766035..8faeb9ac 100644
--- a/src/datavisualization/engine/selectionpointer_p.h
+++ b/src/datavisualization/engine/selectionpointer_p.h
@@ -51,7 +51,7 @@ class Theme;
class Drawer;
class Q3DCamera;
-class QT_DATAVISUALIZATION_EXPORT SelectionPointer : public QObject, protected QOpenGLFunctions
+class SelectionPointer : public QObject, protected QOpenGLFunctions
{
Q_OBJECT
@@ -59,29 +59,29 @@ public:
explicit SelectionPointer(Drawer *drawer);
~SelectionPointer();
- void initializeOpenGL();
void render(GLuint defaultFboHandle = 0);
void setPosition(QVector3D position);
- void setLabel(QString label);
+ void setLabel(const QString &label);
+ void setPointerObject(ObjectHelper *object);
void handleDrawerChange();
void updateBoundingRect(QRect rect);
void updateScene(Q3DScene *scene);
void updateSliceData(bool sliceActivated, GLfloat autoScaleAdjustment);
+ void setHighlightColor(QVector3D colorVector);
private:
+ void initializeOpenGL();
void initShaders();
void loadLabelMesh();
- void loadPointMesh();
private:
ShaderHelper *m_labelShader;
ShaderHelper *m_pointShader;
ObjectHelper *m_labelObj;
- ObjectHelper *m_pointObj;
+ ObjectHelper *m_pointObj; // Not owned
TextureHelper *m_textureHelper;
- bool m_isInitialized;
- Theme m_cachedTheme;
- QDataVis::LabelStyle m_labelStyle;
+ Q3DTheme *m_cachedTheme;
+ bool m_labelBackground;
LabelItem m_labelItem;
Drawer *m_drawer;
QRect m_mainViewPort;
@@ -90,6 +90,7 @@ private:
QString m_label;
bool m_cachedIsSlicingActivated;
GLfloat m_autoScaleAdjustment;
+ QVector3D m_highlightColor;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/seriesrendercache.cpp b/src/datavisualization/engine/seriesrendercache.cpp
new file mode 100644
index 00000000..04b2249d
--- /dev/null
+++ b/src/datavisualization/engine/seriesrendercache.cpp
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#include "seriesrendercache_p.h"
+#include "objecthelper_p.h"
+#include "abstract3drenderer_p.h"
+#include "texturehelper_p.h"
+#include "utils_p.h"
+
+QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
+const QString smoothString(QStringLiteral("Smooth"));
+
+SeriesRenderCache::SeriesRenderCache()
+ : m_series(0),
+ m_object(0),
+ m_mesh(QAbstract3DSeries::MeshCube),
+ m_baseGradientTexture(0),
+ m_singleHighlightGradientTexture(0),
+ m_multiHighlightGradientTexture(0)
+{
+}
+
+SeriesRenderCache::~SeriesRenderCache()
+{
+}
+
+void SeriesRenderCache::populate(QAbstract3DSeries *series, Abstract3DRenderer *renderer)
+{
+ Q_ASSERT(series);
+
+ bool seriesChanged = false;
+
+ if (m_series != series) {
+ m_series = series;
+ seriesChanged = true;
+ }
+
+ QAbstract3DSeriesChangeBitField &changeTracker = series->d_ptr->m_changeTracker;
+
+ if (seriesChanged || changeTracker.itemLabelFormatChanged) {
+ m_itemLabelFormat = series->itemLabelFormat();
+ changeTracker.itemLabelFormatChanged = false;
+ }
+
+ if (seriesChanged || changeTracker.meshChanged || changeTracker.meshSmoothChanged
+ || changeTracker.userDefinedMeshChanged) {
+ m_mesh = series->mesh();
+ changeTracker.meshChanged = false;
+ changeTracker.meshSmoothChanged = false;
+ changeTracker.userDefinedMeshChanged = false;
+
+ QString meshFileName;
+
+ // Compose mesh filename
+ if (m_mesh == QAbstract3DSeries::MeshUserDefined) {
+ // Always use the supplied mesh directly
+ meshFileName = series->userDefinedMesh();
+ } else {
+ switch (m_mesh) {
+ case QAbstract3DSeries::MeshBar:
+ case QAbstract3DSeries::MeshCube:
+ meshFileName = QStringLiteral(":/defaultMeshes/bar");
+ break;
+ case QAbstract3DSeries::MeshPyramid:
+ meshFileName = QStringLiteral(":/defaultMeshes/pyramid");
+ break;
+ case QAbstract3DSeries::MeshCone:
+ meshFileName = QStringLiteral(":/defaultMeshes/cone");
+ break;
+ case QAbstract3DSeries::MeshCylinder:
+ meshFileName = QStringLiteral(":/defaultMeshes/cylinder");
+ break;
+ case QAbstract3DSeries::MeshBevelBar:
+ case QAbstract3DSeries::MeshBevelCube:
+ meshFileName = QStringLiteral(":/defaultMeshes/bevelbar");
+ break;
+ case QAbstract3DSeries::MeshSphere:
+ meshFileName = QStringLiteral(":/defaultMeshes/sphere");
+ break;
+ case QAbstract3DSeries::MeshMinimal:
+ meshFileName = QStringLiteral(":/defaultMeshes/minimal");
+ break;
+ case QAbstract3DSeries::MeshPoint:
+#if defined(QT_OPENGL_ES_2)
+ qWarning("QAbstract3DSeries::MeshPoint is not fully supported on OpenGL ES2");
+#endif
+ break;
+ default:
+ // Default to cube
+ meshFileName = QStringLiteral(":/defaultMeshes/bar");
+ break;
+ }
+
+ if (series->isMeshSmooth() && m_mesh != QAbstract3DSeries::MeshPoint)
+ meshFileName += smoothString;
+
+ // Give renderer an opportunity to customize the mesh
+ renderer->fixMeshFileName(meshFileName, m_mesh);
+ }
+
+ // TODO: Optimize by having some kind of object cache in renderer instead of having separate ObjectHelper for each series?
+ delete m_object;
+ if (meshFileName.isEmpty()) {
+ m_object = 0;
+ } else {
+ m_object = new ObjectHelper(meshFileName);
+ m_object->load();
+ }
+ }
+
+ if (seriesChanged || changeTracker.colorStyleChanged) {
+ m_colorStyle = series->colorStyle();
+ changeTracker.colorStyleChanged = false;
+ }
+
+ if (seriesChanged || changeTracker.baseColorChanged) {
+ m_baseColor = Utils::vectorFromColor(series->baseColor());
+ changeTracker.baseColorChanged = false;
+ }
+
+ if (seriesChanged || changeTracker.baseGradientChanged) {
+ QLinearGradient gradient = series->baseGradient();
+ renderer->fixGradientAndGenerateTexture(&gradient, &m_baseGradientTexture);
+ changeTracker.baseGradientChanged = false;
+ }
+
+ if (seriesChanged || changeTracker.singleHighlightColorChanged) {
+ m_singleHighlightColor = Utils::vectorFromColor(series->singleHighlightColor());
+ changeTracker.singleHighlightColorChanged = false;
+ }
+
+ if (seriesChanged || changeTracker.singleHighlightGradientChanged) {
+ QLinearGradient gradient = series->singleHighlightGradient();
+ renderer->fixGradientAndGenerateTexture(&gradient, &m_singleHighlightGradientTexture);
+ changeTracker.singleHighlightGradientChanged = false;
+ }
+
+ if (seriesChanged || changeTracker.multiHighlightColorChanged) {
+ m_multiHighlightColor = Utils::vectorFromColor(series->multiHighlightColor());
+ changeTracker.multiHighlightColorChanged = false;
+ }
+
+ if (seriesChanged || changeTracker.multiHighlightGradientChanged) {
+ QLinearGradient gradient = series->multiHighlightGradient();
+ renderer->fixGradientAndGenerateTexture(&gradient, &m_multiHighlightGradientTexture);
+ changeTracker.multiHighlightGradientChanged = false;
+ }
+}
+
+void SeriesRenderCache::cleanup(TextureHelper *texHelper)
+{
+ delete m_object;
+ texHelper->deleteTexture(&m_baseGradientTexture);
+ texHelper->deleteTexture(&m_singleHighlightGradientTexture);
+ texHelper->deleteTexture(&m_multiHighlightGradientTexture);
+}
+
+QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/seriesrendercache_p.h b/src/datavisualization/engine/seriesrendercache_p.h
new file mode 100644
index 00000000..906a6c0d
--- /dev/null
+++ b/src/datavisualization/engine/seriesrendercache_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the QtDataVisualization API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef SERIESRENDERCACHE_P_H
+#define SERIESRENDERCACHE_P_H
+
+#include "datavisualizationglobal_p.h"
+#include "qabstract3dseries_p.h"
+
+QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
+class Abstract3DRenderer;
+class ObjectHelper;
+class TextureHelper;
+
+class SeriesRenderCache
+{
+public:
+ SeriesRenderCache();
+ virtual ~SeriesRenderCache();
+
+ void populate(QAbstract3DSeries *series, Abstract3DRenderer *renderer);
+ void cleanup(TextureHelper *texHelper);
+
+ // NOTE: Series pointer can only be used to access the series when syncing with controller.
+ // It is not guaranteed to be valid while rendering and should only be used as an identifier.
+ inline QAbstract3DSeries *series() const { return m_series; }
+
+ inline const QString &itemLabelFormat() const { return m_itemLabelFormat; }
+ inline const QAbstract3DSeries::Mesh &mesh() const { return m_mesh; }
+ inline ObjectHelper *object() const { return m_object; }
+ inline const Q3DTheme::ColorStyle &colorStyle() const { return m_colorStyle; }
+ inline const QVector3D &baseColor() const { return m_baseColor; }
+ inline const GLuint &baseGradientTexture() const { return m_baseGradientTexture; }
+ inline const QVector3D &singleHighlightColor() const { return m_singleHighlightColor; }
+ inline const GLuint &singleHighlightGradientTexture() const { return m_singleHighlightGradientTexture; }
+ inline const QVector3D &multiHighlightColor() const { return m_multiHighlightColor; }
+ inline const GLuint &multiHighlightGradientTexture() const { return m_multiHighlightGradientTexture; }
+
+protected:
+ QAbstract3DSeries *m_series;
+ QString m_itemLabelFormat;
+ ObjectHelper *m_object;
+ QAbstract3DSeries::Mesh m_mesh;
+
+ Q3DTheme::ColorStyle m_colorStyle;
+ QVector3D m_baseColor;
+ GLuint m_baseGradientTexture;
+ QVector3D m_singleHighlightColor;
+ GLuint m_singleHighlightGradientTexture;
+ QVector3D m_multiHighlightColor;
+ GLuint m_multiHighlightGradientTexture;
+};
+
+QT_DATAVISUALIZATION_END_NAMESPACE
+
+#endif
+
diff --git a/src/datavisualization/engine/shaders/ambient.frag b/src/datavisualization/engine/shaders/ambient.frag
deleted file mode 100644
index 88f850f3..00000000
--- a/src/datavisualization/engine/shaders/ambient.frag
+++ /dev/null
@@ -1,32 +0,0 @@
-#version 120
-
-uniform highp vec3 lightPosition_wrld;
-uniform highp vec3 color_mdl;
-
-varying highp vec3 position_wrld;
-varying highp vec3 normal_cmr;
-varying highp vec3 eyeDirection_cmr;
-varying highp vec3 lightDirection_cmr;
-
-void main() {
- highp vec3 lightColor = vec3(1.0, 1.0, 1.0);
- highp float lightPower = 10.0;
- highp vec3 materialAmbientColor = vec3(0.5, 0.5, 0.5) * color_mdl;
- highp vec3 materialSpecularColor = vec3(0.3, 0.3, 0.3) * color_mdl;
-
- highp float distance = length(lightPosition_wrld - position_wrld);
-
- highp vec3 n = normalize(normal_cmr);
- highp vec3 l = normalize(lightDirection_cmr);
- highp float cosTheta = clamp(dot(n, l), 0.0, 1.0);
-
- highp vec3 E = normalize(eyeDirection_cmr);
- highp vec3 R = reflect(-l, n);
- highp float cosAlpha = clamp(dot(E, R), 0.0, 1.0);
-
- gl_FragColor.rgb =
- materialAmbientColor +
- materialSpecularColor * lightColor * lightPower * pow(cosAlpha, 5) / (distance * distance);
- gl_FragColor.a = 1.0;
-}
-
diff --git a/src/datavisualization/engine/shaders/colorOnY.frag b/src/datavisualization/engine/shaders/colorOnY.frag
index 80e54a61..caea959b 100644
--- a/src/datavisualization/engine/shaders/colorOnY.frag
+++ b/src/datavisualization/engine/shaders/colorOnY.frag
@@ -1,9 +1,11 @@
#version 120
uniform highp vec3 lightPosition_wrld;
-uniform highp vec3 color_mdl;
uniform highp float lightStrength;
uniform highp float ambientStrength;
+uniform sampler2D textureSampler;
+uniform highp float gradMin;
+uniform highp float gradHeight;
varying highp vec3 position_wrld;
varying highp vec3 normal_cmr;
@@ -12,8 +14,8 @@ varying highp vec3 lightDirection_cmr;
varying highp vec2 coords_mdl;
void main() {
- highp float heightMod = (coords_mdl.y * 0.3) + 0.7; // Add 30% black to the bottom
- highp vec3 materialDiffuseColor = heightMod * color_mdl;
+ highp vec2 gradientUV = vec2(0.0, gradMin + ((coords_mdl.y + 1.0) * gradHeight));
+ highp vec3 materialDiffuseColor = texture2D(textureSampler, gradientUV).xyz;
highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor;
highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0);
diff --git a/src/datavisualization/engine/shaders/colorOnY_ES2.frag b/src/datavisualization/engine/shaders/colorOnY_ES2.frag
index aba52cfe..bb6e28c7 100644
--- a/src/datavisualization/engine/shaders/colorOnY_ES2.frag
+++ b/src/datavisualization/engine/shaders/colorOnY_ES2.frag
@@ -1,7 +1,9 @@
uniform highp vec3 lightPosition_wrld;
-uniform highp vec3 color_mdl;
uniform highp float lightStrength;
uniform highp float ambientStrength;
+uniform sampler2D textureSampler;
+uniform highp float gradMin;
+uniform highp float gradHeight;
varying highp vec3 position_wrld;
varying highp vec3 normal_cmr;
@@ -10,8 +12,8 @@ varying highp vec3 lightDirection_cmr;
varying highp vec2 coords_mdl;
void main() {
- highp float heightMod = (coords_mdl.y * 0.3) + 0.7; // Add 30% black to the bottom
- highp vec3 materialDiffuseColor = heightMod * color_mdl;
+ highp vec2 gradientUV = vec2(0.0, gradMin + ((coords_mdl.y + 1.0) * gradHeight));
+ highp vec3 materialDiffuseColor = texture2D(textureSampler, gradientUV).xyz;
highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor;
highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0);
diff --git a/src/datavisualization/engine/shaders/default.vert b/src/datavisualization/engine/shaders/default.vert
index 14f77773..efb40862 100644
--- a/src/datavisualization/engine/shaders/default.vert
+++ b/src/datavisualization/engine/shaders/default.vert
@@ -1,5 +1,3 @@
-#version 120
-
attribute highp vec3 vertexPosition_mdl;
attribute highp vec2 vertexUV;
attribute highp vec3 vertexNormal_mdl;
diff --git a/src/datavisualization/engine/shaders/default_ES2.vert b/src/datavisualization/engine/shaders/default_ES2.vert
deleted file mode 100644
index efb40862..00000000
--- a/src/datavisualization/engine/shaders/default_ES2.vert
+++ /dev/null
@@ -1,26 +0,0 @@
-attribute highp vec3 vertexPosition_mdl;
-attribute highp vec2 vertexUV;
-attribute highp vec3 vertexNormal_mdl;
-
-uniform highp mat4 MVP;
-uniform highp mat4 V;
-uniform highp mat4 M;
-uniform highp mat4 itM;
-uniform highp vec3 lightPosition_wrld;
-
-varying highp vec3 position_wrld;
-varying highp vec3 normal_cmr;
-varying highp vec3 eyeDirection_cmr;
-varying highp vec3 lightDirection_cmr;
-varying highp vec2 coords_mdl;
-
-void main() {
- gl_Position = MVP * vec4(vertexPosition_mdl, 1.0);
- coords_mdl = vertexPosition_mdl.xy;
- position_wrld = (M * vec4(vertexPosition_mdl, 1.0)).xyz;
- vec3 vertexPosition_cmr = (V * M * vec4(vertexPosition_mdl, 1.0)).xyz;
- eyeDirection_cmr = vec3(0.0, 0.0, 0.0) - vertexPosition_cmr;
- vec3 lightPosition_cmr = (V * vec4(lightPosition_wrld, 1.0)).xyz;
- lightDirection_cmr = lightPosition_cmr + eyeDirection_cmr;
- normal_cmr = (V * itM * vec4(vertexNormal_mdl, 0.0)).xyz;
-}
diff --git a/src/datavisualization/engine/shaders/selection.frag b/src/datavisualization/engine/shaders/plainColor.frag
index 099c87a1..099c87a1 100644
--- a/src/datavisualization/engine/shaders/selection.frag
+++ b/src/datavisualization/engine/shaders/plainColor.frag
diff --git a/src/datavisualization/engine/shaders/selection.vert b/src/datavisualization/engine/shaders/plainColor.vert
index 64d17e15..64d17e15 100644
--- a/src/datavisualization/engine/shaders/selection.vert
+++ b/src/datavisualization/engine/shaders/plainColor.vert
diff --git a/src/datavisualization/engine/shaders/surfaceGrid.vert b/src/datavisualization/engine/shaders/point_ES2.vert
index 5582d633..b2dfdd7b 100644
--- a/src/datavisualization/engine/shaders/surfaceGrid.vert
+++ b/src/datavisualization/engine/shaders/point_ES2.vert
@@ -1,6 +1,8 @@
-attribute highp vec3 vertexPosition_mdl;
uniform highp mat4 MVP;
+attribute highp vec3 vertexPosition_mdl;
+
void main() {
+ gl_PointSize = 5.0;
gl_Position = MVP * vec4(vertexPosition_mdl, 1.0);
}
diff --git a/src/datavisualization/engine/shaders/shadowNoTexColorOnY.frag b/src/datavisualization/engine/shaders/shadowNoTexColorOnY.frag
index 68ba2368..9882cd92 100644
--- a/src/datavisualization/engine/shaders/shadowNoTexColorOnY.frag
+++ b/src/datavisualization/engine/shaders/shadowNoTexColorOnY.frag
@@ -3,8 +3,10 @@
uniform highp float lightStrength;
uniform highp float ambientStrength;
uniform highp float shadowQuality;
-uniform highp vec3 color_mdl;
uniform highp sampler2DShadow shadowMap;
+uniform sampler2D textureSampler;
+uniform highp float gradMin;
+uniform highp float gradHeight;
varying highp vec4 shadowCoord;
varying highp vec3 position_wrld;
@@ -37,8 +39,8 @@ highp vec2 poissonDisk[16] = vec2[16](vec2(-0.94201624, -0.39906216),
}*/
void main() {
- highp float heightMod = (coords_mdl.y * 0.3) + 0.7; // Add 30% black to the bottom
- highp vec3 materialDiffuseColor = heightMod * color_mdl;
+ highp vec2 gradientUV = vec2(0.0, gradMin + ((coords_mdl.y + 1.0) * gradHeight));
+ highp vec3 materialDiffuseColor = texture2D(textureSampler, gradientUV).xyz;
highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor;
highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0);
diff --git a/src/datavisualization/engine/shaders/surface.frag b/src/datavisualization/engine/shaders/surface.frag
index 4b1357b1..576cc51f 100644
--- a/src/datavisualization/engine/shaders/surface.frag
+++ b/src/datavisualization/engine/shaders/surface.frag
@@ -1,6 +1,6 @@
#version 120
-varying highp vec3 coords_mdl;
+varying highp vec2 coords_mdl;
varying highp vec3 position_wrld;
varying highp vec3 normal_cmr;
varying highp vec3 eyeDirection_cmr;
@@ -12,7 +12,7 @@ uniform highp float lightStrength;
uniform highp float ambientStrength;
void main() {
- highp vec2 gradientUV = vec2(0.0, (coords_mdl.y + 1.001) / 2.0); // 1000 pixel texture, we need a margin for 1/1000 rounding error
+ highp vec2 gradientUV = vec2(0.0, (coords_mdl.y + 1.0) / 2.0);
highp vec3 materialDiffuseColor = texture2D(textureSampler, gradientUV).xyz;
highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor;
highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0);
diff --git a/src/datavisualization/engine/shaders/surfaceFlat.frag b/src/datavisualization/engine/shaders/surfaceFlat.frag
index 1f2a3822..fd42a289 100644
--- a/src/datavisualization/engine/shaders/surfaceFlat.frag
+++ b/src/datavisualization/engine/shaders/surfaceFlat.frag
@@ -14,7 +14,7 @@ uniform highp float lightStrength;
uniform highp float ambientStrength;
void main() {
- highp vec2 gradientUV = vec2(0.0, (coords_mdl.y + 1.001) / 2.0); // 1000 pixel texture, we need a margin for 1/1000 rounding error
+ highp vec2 gradientUV = vec2(0.0, (coords_mdl.y + 1.0) / 2.0);
highp vec3 materialDiffuseColor = texture2D(textureSampler, gradientUV).xyz;
highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor;
highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0);
diff --git a/src/datavisualization/engine/shaders/surfaceGrid.frag b/src/datavisualization/engine/shaders/surfaceGrid.frag
deleted file mode 100644
index 1658b316..00000000
--- a/src/datavisualization/engine/shaders/surfaceGrid.frag
+++ /dev/null
@@ -1,6 +0,0 @@
-uniform highp vec3 color_mdl;
-
-void main() {
- gl_FragColor.rgb = color_mdl;
-}
-
diff --git a/src/datavisualization/engine/shaders/surfaceShadowFlat.frag b/src/datavisualization/engine/shaders/surfaceShadowFlat.frag
new file mode 100644
index 00000000..6341136e
--- /dev/null
+++ b/src/datavisualization/engine/shaders/surfaceShadowFlat.frag
@@ -0,0 +1,70 @@
+#version 120
+
+#extension GL_EXT_gpu_shader4 : require
+
+varying highp vec3 coords_mdl;
+varying highp vec3 position_wrld;
+flat varying highp vec3 normal_cmr;
+varying highp vec3 eyeDirection_cmr;
+varying highp vec3 lightDirection_cmr;
+
+uniform highp sampler2DShadow shadowMap;
+uniform sampler2D textureSampler;
+varying highp vec4 shadowCoord;
+uniform highp vec3 lightPosition_wrld;
+uniform highp float lightStrength;
+uniform highp float ambientStrength;
+uniform highp float shadowQuality;
+
+highp vec2 poissonDisk[16] = vec2[16](vec2(-0.94201624, -0.39906216),
+ vec2(0.94558609, -0.76890725),
+ vec2(-0.094184101, -0.92938870),
+ vec2(0.34495938, 0.29387760),
+ vec2(-0.91588581, 0.45771432),
+ vec2(-0.81544232, -0.87912464),
+ vec2(-0.38277543, 0.27676845),
+ vec2(0.97484398, 0.75648379),
+ vec2(0.44323325, -0.97511554),
+ vec2(0.53742981, -0.47373420),
+ vec2(-0.26496911, -0.41893023),
+ vec2(0.79197514, 0.19090188),
+ vec2(-0.24188840, 0.99706507),
+ vec2(-0.81409955, 0.91437590),
+ vec2(0.19984126, 0.78641367),
+ vec2(0.14383161, -0.14100790));
+
+void main() {
+ highp vec2 gradientUV = vec2(0.0, (coords_mdl.y + 1.0) / 2.0);
+ highp vec3 materialDiffuseColor = texture2D(textureSampler, gradientUV).xyz;
+ highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor;
+ highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0);
+
+ highp vec3 n = normalize(normal_cmr);
+ highp vec3 l = normalize(lightDirection_cmr);
+ highp float cosTheta = clamp(dot(n, l), 0.0, 1.0);
+
+ highp vec3 E = normalize(eyeDirection_cmr);
+ highp vec3 R = reflect(-l, n);
+ highp float cosAlpha = clamp(dot(E, R), 0.0, 1.0);
+
+ highp float bias = 0.005 * tan(acos(cosTheta));
+ bias = clamp(bias, 0.0, 0.01);
+
+ vec4 shadCoords = shadowCoord;
+ shadCoords.z -= bias;
+
+ highp float visibility = 0.6;
+ for (int i = 0; i < 15; i++) {
+ vec4 shadCoordsPD = shadCoords;
+ shadCoordsPD.x += cos(poissonDisk[i].x) / shadowQuality;
+ shadCoordsPD.y += sin(poissonDisk[i].y) / shadowQuality;
+ visibility += 0.025 * shadow2DProj(shadowMap, shadCoordsPD).r;
+ }
+
+ gl_FragColor.rgb =
+ visibility * (materialAmbientColor +
+ materialDiffuseColor * lightStrength * cosTheta +
+ materialSpecularColor * lightStrength * pow(cosAlpha, 10));
+ gl_FragColor.a = 1.0;
+}
+
diff --git a/src/datavisualization/engine/shaders/surface.vert b/src/datavisualization/engine/shaders/surfaceShadowFlat.vert
index 28152abc..0a6e967f 100644
--- a/src/datavisualization/engine/shaders/surface.vert
+++ b/src/datavisualization/engine/shaders/surfaceShadowFlat.vert
@@ -1,3 +1,7 @@
+#version 120
+
+#extension GL_EXT_gpu_shader4 : require
+
attribute highp vec3 vertexPosition_mdl;
attribute highp vec3 vertexNormal_mdl;
@@ -5,17 +9,25 @@ uniform highp mat4 MVP;
uniform highp mat4 V;
uniform highp mat4 M;
uniform highp mat4 itM;
+uniform highp mat4 depthMVP;
uniform highp vec3 lightPosition_wrld;
varying highp vec3 position_wrld;
-varying highp vec3 normal_cmr;
+flat varying highp vec3 normal_cmr;
varying highp vec3 eyeDirection_cmr;
varying highp vec3 lightDirection_cmr;
+varying highp vec4 shadowCoord;
varying highp vec3 coords_mdl;
+const highp mat4 bias = mat4(0.5, 0.0, 0.0, 0.0,
+ 0.0, 0.5, 0.0, 0.0,
+ 0.0, 0.0, 0.5, 0.0,
+ 0.5, 0.5, 0.5, 1.0);
+
void main() {
gl_Position = MVP * vec4(vertexPosition_mdl, 1.0);
coords_mdl = vertexPosition_mdl;
+ shadowCoord = bias * depthMVP * vec4(vertexPosition_mdl, 1.0);
position_wrld = (M * vec4(vertexPosition_mdl, 1.0)).xyz;
vec3 vertexPosition_cmr = (V * M * vec4(vertexPosition_mdl, 1.0)).xyz;
eyeDirection_cmr = vec3(0.0, 0.0, 0.0) - vertexPosition_cmr;
diff --git a/src/datavisualization/engine/shaders/surfaceShadowNoTex.frag b/src/datavisualization/engine/shaders/surfaceShadowNoTex.frag
new file mode 100644
index 00000000..755be3f1
--- /dev/null
+++ b/src/datavisualization/engine/shaders/surfaceShadowNoTex.frag
@@ -0,0 +1,68 @@
+#version 120
+
+varying highp vec2 coords_mdl;
+varying highp vec3 position_wrld;
+varying highp vec3 normal_cmr;
+varying highp vec3 eyeDirection_cmr;
+varying highp vec3 lightDirection_cmr;
+
+uniform highp sampler2DShadow shadowMap;
+uniform sampler2D textureSampler;
+varying highp vec4 shadowCoord;
+uniform highp vec3 lightPosition_wrld;
+uniform highp float lightStrength;
+uniform highp float ambientStrength;
+uniform highp float shadowQuality;
+
+highp vec2 poissonDisk[16] = vec2[16](vec2(-0.94201624, -0.39906216),
+ vec2(0.94558609, -0.76890725),
+ vec2(-0.094184101, -0.92938870),
+ vec2(0.34495938, 0.29387760),
+ vec2(-0.91588581, 0.45771432),
+ vec2(-0.81544232, -0.87912464),
+ vec2(-0.38277543, 0.27676845),
+ vec2(0.97484398, 0.75648379),
+ vec2(0.44323325, -0.97511554),
+ vec2(0.53742981, -0.47373420),
+ vec2(-0.26496911, -0.41893023),
+ vec2(0.79197514, 0.19090188),
+ vec2(-0.24188840, 0.99706507),
+ vec2(-0.81409955, 0.91437590),
+ vec2(0.19984126, 0.78641367),
+ vec2(0.14383161, -0.14100790));
+
+void main() {
+ highp vec2 gradientUV = vec2(0.0, (coords_mdl.y + 1.0) / 2.0);
+ highp vec3 materialDiffuseColor = texture2D(textureSampler, gradientUV).xyz;
+ highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor;
+ highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0);
+
+ highp vec3 n = normalize(normal_cmr);
+ highp vec3 l = normalize(lightDirection_cmr);
+ highp float cosTheta = clamp(dot(n, l), 0.0, 1.0);
+
+ highp vec3 E = normalize(eyeDirection_cmr);
+ highp vec3 R = reflect(-l, n);
+ highp float cosAlpha = clamp(dot(E, R), 0.0, 1.0);
+
+ highp float bias = 0.005 * tan(acos(cosTheta));
+ bias = clamp(bias, 0.0, 0.01);
+
+ vec4 shadCoords = shadowCoord;
+ shadCoords.z -= bias;
+
+ highp float visibility = 0.6;
+ for (int i = 0; i < 15; i++) {
+ vec4 shadCoordsPD = shadCoords;
+ shadCoordsPD.x += cos(poissonDisk[i].x) / shadowQuality;
+ shadCoordsPD.y += sin(poissonDisk[i].y) / shadowQuality;
+ visibility += 0.025 * shadow2DProj(shadowMap, shadCoordsPD).r;
+ }
+
+ gl_FragColor.rgb =
+ visibility * (materialAmbientColor +
+ materialDiffuseColor * lightStrength * cosTheta +
+ materialSpecularColor * lightStrength * pow(cosAlpha, 10));
+ gl_FragColor.a = 1.0;
+}
+
diff --git a/src/datavisualization/engine/shaders/surface_ES2.frag b/src/datavisualization/engine/shaders/surface_ES2.frag
index 7f40ba4d..c7e75594 100644
--- a/src/datavisualization/engine/shaders/surface_ES2.frag
+++ b/src/datavisualization/engine/shaders/surface_ES2.frag
@@ -1,5 +1,5 @@
varying highp vec2 UV;
-varying highp vec3 coords_mdl;
+varying highp vec2 coords_mdl;
varying highp vec3 position_wrld;
varying highp vec3 normal_cmr;
varying highp vec3 eyeDirection_cmr;
@@ -11,7 +11,7 @@ uniform highp float lightStrength;
uniform highp float ambientStrength;
void main() {
- highp vec2 gradientUV = vec2(0.0, (coords_mdl.y + 1.001) / 2.0); // ~1000 pixel texture, we need a margin for 1/1000 rounding error
+ highp vec2 gradientUV = vec2(0.0, (coords_mdl.y + 1.0) / 2.0);
highp vec3 materialDiffuseColor = texture2D(textureSampler, gradientUV).xyz;
highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor;
highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0);
diff --git a/src/datavisualization/engine/shaders/texture.frag b/src/datavisualization/engine/shaders/texture.frag
deleted file mode 100644
index a6d7b2eb..00000000
--- a/src/datavisualization/engine/shaders/texture.frag
+++ /dev/null
@@ -1,35 +0,0 @@
-#version 120
-
-uniform highp vec3 lightPosition_wrld;
-uniform highp vec3 color_mdl;
-uniform highp float lightStrength;
-uniform highp float ambientStrength;
-uniform sampler2D textureSampler;
-
-varying highp vec2 UV;
-varying highp vec3 position_wrld;
-varying highp vec3 normal_cmr;
-varying highp vec3 eyeDirection_cmr;
-varying highp vec3 lightDirection_cmr;
-
-void main() {
- highp vec3 materialDiffuseColor = texture2D(textureSampler, UV).rgb;
- highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor;
- highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0);
-
- highp float distance = length(lightPosition_wrld - position_wrld);
- highp vec3 n = normalize(normal_cmr);
- highp vec3 l = normalize(lightDirection_cmr);
- highp float cosTheta = clamp(dot(n, l), 0.0, 1.0);
-
- highp vec3 E = normalize(eyeDirection_cmr);
- highp vec3 R = reflect(-l, n);
- highp float cosAlpha = clamp(dot(E, R), 0.0, 1.0);
-
- gl_FragColor.rgb =
- materialAmbientColor +
- materialDiffuseColor * lightStrength * (cosTheta * cosTheta) / distance +
- materialSpecularColor * lightStrength * pow(cosAlpha, 10) / distance;
- gl_FragColor.a = texture2D(textureSampler, UV).a;
-}
-
diff --git a/src/datavisualization/engine/shaders/texture.vert b/src/datavisualization/engine/shaders/texture.vert
deleted file mode 100644
index 01f922e0..00000000
--- a/src/datavisualization/engine/shaders/texture.vert
+++ /dev/null
@@ -1,26 +0,0 @@
-uniform highp mat4 MVP;
-uniform highp mat4 V;
-uniform highp mat4 M;
-uniform highp mat4 itM;
-uniform highp vec3 lightPosition_wrld;
-
-attribute highp vec3 vertexPosition_mdl;
-attribute highp vec2 vertexUV;
-attribute highp vec3 vertexNormal_mdl;
-
-varying highp vec2 UV;
-varying highp vec3 position_wrld;
-varying highp vec3 normal_cmr;
-varying highp vec3 eyeDirection_cmr;
-varying highp vec3 lightDirection_cmr;
-
-void main() {
- gl_Position = MVP * vec4(vertexPosition_mdl, 1.0);
- position_wrld = (M * vec4(vertexPosition_mdl, 1.0)).xyz;
- vec3 vertexPosition_cmr = (V * M * vec4(vertexPosition_mdl, 1.0)).xyz;
- eyeDirection_cmr = vec3(0.0, 0.0, 0.0) - vertexPosition_cmr;
- vec3 lightPosition_cmr = (V * vec4(lightPosition_wrld, 1.0)).xyz;
- lightDirection_cmr = lightPosition_cmr + eyeDirection_cmr;
- normal_cmr = (V * itM * vec4(vertexNormal_mdl, 0.0)).xyz;
- UV = vertexUV;
-}
diff --git a/src/datavisualization/engine/shaders/texture_ES2.frag b/src/datavisualization/engine/shaders/texture_ES2.frag
deleted file mode 100644
index 58097ba5..00000000
--- a/src/datavisualization/engine/shaders/texture_ES2.frag
+++ /dev/null
@@ -1,37 +0,0 @@
-uniform highp vec3 lightPosition_wrld;
-uniform highp vec3 color_mdl;
-uniform highp float lightStrength;
-uniform highp float ambientStrength;
-uniform sampler2D textureSampler;
-
-varying highp vec2 UV;
-varying highp vec3 position_wrld;
-varying highp vec3 normal_cmr;
-varying highp vec3 eyeDirection_cmr;
-varying highp vec3 lightDirection_cmr;
-
-void main() {
- highp vec3 materialDiffuseColor = texture2D(textureSampler, UV).rgb;
- highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor;
- highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0);
-
- highp float distance = length(lightPosition_wrld - position_wrld);
- highp vec3 n = normalize(normal_cmr);
- highp vec3 l = normalize(lightDirection_cmr);
- highp float cosTheta = dot(n, l);
- if (cosTheta < 0.0) cosTheta = 0.0;
- else if (cosTheta > 1.0) cosTheta = 1.0;
-
- highp vec3 E = normalize(eyeDirection_cmr);
- highp vec3 R = reflect(-l, n);
- highp float cosAlpha = dot(E, R);
- if (cosAlpha < 0.0) cosAlpha = 0.0;
- else if (cosAlpha > 1.0) cosAlpha = 1.0;
-
- gl_FragColor.rgb =
- materialAmbientColor +
- materialDiffuseColor * lightStrength * (cosTheta * cosTheta) / distance +
- materialSpecularColor * lightStrength * (cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha) / distance;
- gl_FragColor.a = texture2D(textureSampler, UV).a;
-}
-
diff --git a/src/datavisualization/engine/surface3dcontroller.cpp b/src/datavisualization/engine/surface3dcontroller.cpp
index 8d1bcf85..3cec72d1 100644
--- a/src/datavisualization/engine/surface3dcontroller.cpp
+++ b/src/datavisualization/engine/surface3dcontroller.cpp
@@ -23,6 +23,8 @@
#include "q3dvalueaxis_p.h"
#include "q3dcategoryaxis.h"
#include "qsurfacedataproxy_p.h"
+#include "qsurface3dseries_p.h"
+#include "shaderhelper_p.h"
#include <QMatrix4x4>
@@ -33,20 +35,16 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
Surface3DController::Surface3DController(QRect rect)
: Abstract3DController(rect),
m_renderer(0),
- m_isSmoothSurfaceEnabled(false),
- m_isSurfaceGridEnabled(true)
+ m_selectedPoint(invalidSelectionPosition()),
+ m_selectedSeries(0),
+ m_flatShadingSupported(true)
{
- setActiveDataProxy(0);
-
// Setting a null axis creates a new default axis according to orientation and graph type.
// Note: these cannot be set in the Abstract3DController constructor, as they will call virtual
// functions implemented by subclasses.
setAxisX(0);
setAxisY(0);
setAxisZ(0);
-
- // Set the default from the theme
- m_userDefinedGradient = theme().m_surfaceGradient;
}
Surface3DController::~Surface3DController()
@@ -62,38 +60,34 @@ void Surface3DController::initializeOpenGL()
m_renderer = new Surface3DRenderer(this);
setRenderer(m_renderer);
synchDataToRenderer();
+ QObject::connect(m_renderer, &Surface3DRenderer::pointClicked, this,
+ &Surface3DController::handlePointClicked, Qt::QueuedConnection);
emitNeedRender();
}
void Surface3DController::synchDataToRenderer()
{
- Abstract3DController::synchDataToRenderer();
-
if (!isInitialized())
return;
- // Notify changes to renderer
- if (m_changeTracker.gradientColorChanged) {
- m_renderer->updateSurfaceGradient(m_userDefinedGradient);
- m_changeTracker.gradientColorChanged = false;
- }
+ Abstract3DController::synchDataToRenderer();
- if (m_changeTracker.smoothStatusChanged) {
- bool oldSmoothStatus = m_isSmoothSurfaceEnabled;
- m_isSmoothSurfaceEnabled = m_renderer->updateSmoothStatus(m_isSmoothSurfaceEnabled);
- m_changeTracker.smoothStatusChanged = false;
- if (oldSmoothStatus != m_isSmoothSurfaceEnabled)
- emit smoothSurfaceEnabledChanged(m_isSmoothSurfaceEnabled);
+ // Notify changes to renderer
+ if (m_changeTracker.rowsChanged) {
+ m_renderer->updateRows(m_changedRows);
+ m_changeTracker.rowsChanged = false;
+ m_changedRows.clear();
}
- if (m_changeTracker.surfaceGridChanged) {
- m_renderer->updateSurfaceGridStatus(m_isSurfaceGridEnabled);
- m_changeTracker.surfaceGridChanged = false;
+ if (m_changeTracker.itemChanged) {
+ m_renderer->updateItem(m_changedItems);
+ m_changeTracker.itemChanged = false;
+ m_changedItems.clear();
}
- if (m_isDataDirty) {
- m_renderer->updateDataModel(static_cast<QSurfaceDataProxy *>(m_data));
- m_isDataDirty = false;
+ if (m_changeTracker.selectedPointChanged) {
+ m_renderer->updateSelectedPoint(m_selectedPoint, m_selectedSeries);
+ m_changeTracker.selectedPointChanged = false;
}
}
@@ -107,132 +101,392 @@ void Surface3DController::handleAxisAutoAdjustRangeChangedInOrientation(Q3DAbstr
void Surface3DController::handleAxisRangeChangedBySender(QObject *sender)
{
- scene()->setSlicingActive(false);
Abstract3DController::handleAxisRangeChangedBySender(sender);
+
+ // Update selected point - may be moved offscreen
+ setSelectedPoint(m_selectedPoint, m_selectedSeries);
}
-void Surface3DController::setSmoothSurface(bool enable)
+void Surface3DController::handleSeriesVisibilityChangedBySender(QObject *sender)
{
- bool changed = m_isSmoothSurfaceEnabled != enable;
- m_isSmoothSurfaceEnabled = enable;
- m_changeTracker.smoothStatusChanged = true;
- emitNeedRender();
+ Abstract3DController::handleSeriesVisibilityChangedBySender(sender);
- if (changed)
- emit smoothSurfaceEnabledChanged(m_isSmoothSurfaceEnabled);
+ // Visibility changes may require disabling/enabling slicing,
+ // so just reset selection to ensure everything is still valid.
+ setSelectedPoint(m_selectedPoint, m_selectedSeries);
}
-bool Surface3DController::smoothSurface()
+QPoint Surface3DController::invalidSelectionPosition()
{
- return m_isSmoothSurfaceEnabled;
+ static QPoint invalidSelectionPoint(-1, -1);
+ return invalidSelectionPoint;
}
-void Surface3DController::setSurfaceGrid(bool enable)
+bool Surface3DController::isFlatShadingSupported()
{
- m_isSurfaceGridEnabled = enable;
- m_changeTracker.surfaceGridChanged = true;
- emitNeedRender();
+ return m_flatShadingSupported;
}
-bool Surface3DController::surfaceGrid()
+void Surface3DController::addSeries(QAbstract3DSeries *series)
{
- return m_isSurfaceGridEnabled;
-}
+ Q_ASSERT(series && series->type() == QAbstract3DSeries::SeriesTypeSurface);
-void Surface3DController::setGradient(const QLinearGradient &gradient)
-{
- m_userDefinedGradient = gradient;
- m_userDefinedGradient.setStart(2, 1024);
- m_userDefinedGradient.setFinalStop(0, 0);
- m_changeTracker.gradientColorChanged = true;
- emitNeedRender();
+ if (!m_seriesList.size()) {
+ Abstract3DController::addSeries(series);
+
+ adjustValueAxisRange();
+ } else {
+ qWarning("Surface graph only supports a single series.");
+ }
+
+ QSurface3DSeries *surfaceSeries = static_cast<QSurface3DSeries *>(series);
+ if (surfaceSeries->selectedPoint() != invalidSelectionPosition())
+ setSelectedPoint(surfaceSeries->selectedPoint(), surfaceSeries);
}
-QLinearGradient Surface3DController::gradient() const
+void Surface3DController::removeSeries(QAbstract3DSeries *series)
{
- return m_userDefinedGradient;
+ if (series && series->d_ptr->m_controller == this) {
+ Abstract3DController::removeSeries(series);
+
+ if (m_selectedSeries == series)
+ setSelectedPoint(invalidSelectionPosition(), 0);
+
+ adjustValueAxisRange();
+ }
}
-void Surface3DController::setGradientColorAt(qreal pos, const QColor &color)
+QList<QSurface3DSeries *> Surface3DController::surfaceSeriesList()
{
- m_userDefinedGradient.setColorAt(pos, color);
- m_changeTracker.gradientColorChanged = true;
- emitNeedRender();
+ QList<QAbstract3DSeries *> abstractSeriesList = seriesList();
+ QList<QSurface3DSeries *> surfaceSeriesList;
+ foreach (QAbstract3DSeries *abstractSeries, abstractSeriesList) {
+ QSurface3DSeries *surfaceSeries = qobject_cast<QSurface3DSeries *>(abstractSeries);
+ if (surfaceSeries)
+ surfaceSeriesList.append(surfaceSeries);
+ }
+
+ return surfaceSeriesList;
}
-void Surface3DController::setSelectionMode(QDataVis::SelectionMode mode)
+void Surface3DController::setSelectionMode(QDataVis::SelectionFlags mode)
{
- if (!(mode == QDataVis::SelectionModeNone || mode == QDataVis::SelectionModeItem
- || mode == QDataVis::SelectionModeSliceRow
- || mode == QDataVis::SelectionModeSliceColumn)) {
+ // Currently surface only supports row and column modes when also slicing
+ if ((mode.testFlag(QDataVis::SelectionRow) || mode.testFlag(QDataVis::SelectionColumn))
+ && !mode.testFlag(QDataVis::SelectionSlice)) {
qWarning("Unsupported selection mode.");
return;
+ } else if (mode.testFlag(QDataVis::SelectionSlice)
+ && (mode.testFlag(QDataVis::SelectionRow) == mode.testFlag(QDataVis::SelectionColumn))) {
+ qWarning("Must specify one of either row or column selection mode in conjunction with slicing mode.");
+ } else {
+ QDataVis::SelectionFlags oldMode = selectionMode();
+
+ Abstract3DController::setSelectionMode(mode);
+
+ if (mode != oldMode) {
+ // Refresh selection upon mode change to ensure slicing is correctly updated
+ // according to series the visibility.
+ setSelectedPoint(m_selectedPoint, m_selectedSeries);
+
+ // Special case: Always deactivate slicing when changing away from slice
+ // automanagement, as this can't be handled in setSelectedBar.
+ if (!mode.testFlag(QDataVis::SelectionSlice)
+ && oldMode.testFlag(QDataVis::SelectionSlice)) {
+ scene()->setSlicingActive(false);
+ }
+ }
}
- // Disable zoom if selection mode changes
- setSlicingActive(false);
- Abstract3DController::setSelectionMode(mode);
}
+void Surface3DController::setSelectedPoint(const QPoint &position, QSurface3DSeries *series)
+{
+ // If the selection targets non-existent point, clear selection instead.
+ QPoint pos = position;
+
+ // Series may already have been removed, so check it before setting the selection.
+ if (!m_seriesList.contains(series))
+ series = 0;
+
+ const QSurfaceDataProxy *proxy = 0;
+ if (series)
+ proxy = series->dataProxy();
+
+ if (!proxy)
+ pos = invalidSelectionPosition();
+
+ if (pos != invalidSelectionPosition()) {
+ int maxRow = proxy->rowCount() - 1;
+ int maxCol = proxy->columnCount() - 1;
+
+ if (pos.x() < 0 || pos.x() > maxRow || pos.y() < 0 || pos.y() > maxCol)
+ pos = invalidSelectionPosition();
+ }
+
+ if (selectionMode().testFlag(QDataVis::SelectionSlice)) {
+ if (pos == invalidSelectionPosition() || !series->isVisible()) {
+ scene()->setSlicingActive(false);
+ } else {
+ // If the selected point is outside data window, or there is no selected point, disable slicing
+ // TODO: (QTRD-2351) This logic doesn't match the renderer logic for non straight surfaces,
+ // but that logic needs to change anyway, so this is good for now.
+ float axisMinX = m_axisX->min();
+ float axisMaxX = m_axisX->max();
+ float axisMinZ = m_axisZ->min();
+ float axisMaxZ = m_axisZ->max();
+
+ QSurfaceDataItem item = proxy->array()->at(pos.x())->at(pos.y());
+ if (item.x() < axisMinX || item.x() > axisMaxX
+ || item.z() < axisMinZ || item.z() > axisMaxZ) {
+ scene()->setSlicingActive(false);
+ } else {
+ scene()->setSlicingActive(true);
+ }
+ }
+ emitNeedRender();
+ }
+
+ if (pos != m_selectedPoint) {
+ m_selectedPoint = pos;
+ m_selectedSeries = series;
+ m_changeTracker.selectedPointChanged = true;
+
+ // Clear selection from other series and finally set new selection to the specified series
+ foreach (QAbstract3DSeries *otherSeries, m_seriesList) {
+ QSurface3DSeries *surfaceSeries = static_cast<QSurface3DSeries *>(otherSeries);
+ if (surfaceSeries != m_selectedSeries)
+ surfaceSeries->dptr()->setSelectedPoint(invalidSelectionPosition());
+ }
+ if (m_selectedSeries)
+ m_selectedSeries->dptr()->setSelectedPoint(m_selectedPoint);
-void Surface3DController::setActiveDataProxy(QAbstractDataProxy *proxy)
+ emitNeedRender();
+ }
+}
+
+void Surface3DController::handleArrayReset()
+{
+ adjustValueAxisRange();
+ m_isDataDirty = true;
+ // Clear selection unless still valid
+ setSelectedPoint(m_selectedPoint, m_selectedSeries);
+ emitNeedRender();
+}
+
+void Surface3DController::handlePointClicked(const QPoint &position, QSurface3DSeries *series)
{
- // Setting null proxy indicates default proxy
- if (!proxy) {
- proxy = new QSurfaceDataProxy;
- proxy->d_ptr->setDefaultProxy(true);
+ setSelectedPoint(position, series);
+ // TODO: pass clicked to parent. (QTRD-2517)
+ // TODO: Also hover needed? (QTRD-2131)
+}
+
+void Surface3DController::handleFlatShadingSupportedChange(bool supported)
+{
+ // Handle renderer flat surface support indicator signal. This happens exactly once per renderer.
+ if (m_flatShadingSupported != supported) {
+ m_flatShadingSupported = supported;
+ // Emit the change for all added surfaces
+ foreach (QAbstract3DSeries *series, m_seriesList) {
+ QSurface3DSeries *surfaceSeries = static_cast<QSurface3DSeries *>(series);
+ emit surfaceSeries->flatShadingSupportedChanged(m_flatShadingSupported);
+ }
}
+}
- Q_ASSERT(proxy->type() == QAbstractDataProxy::DataTypeSurface);
+void Surface3DController::handleRowsChanged(int startIndex, int count)
+{
+ QSurfaceDataProxy *sender = static_cast<QSurfaceDataProxy *>(QObject::sender());
+ if (m_changedRows.size() == 0)
+ m_changedRows.reserve(sender->rowCount());
+
+ if (static_cast<QSurface3DSeries *>(m_seriesList.at(0)) == sender->series()) {
+ // Change is for the visible series, put the change to queue
+ int oldChangeCount = m_changedRows.size();
+ for (int i = 0; i < count; i++) {
+ bool newItem = true;
+ int candidate = startIndex + i;
+ for (int i = 0; i < oldChangeCount; i++) {
+ if (m_changedRows.at(i) == candidate) {
+ newItem = false;
+ break;
+ }
+ }
+ if (newItem)
+ m_changedRows.append(candidate);
+ }
+ if (m_changedRows.size()) {
+ m_changeTracker.rowsChanged = true;
- Abstract3DController::setActiveDataProxy(proxy);
+ adjustValueAxisRange();
+ // Clear selection unless still valid
+ setSelectedPoint(m_selectedPoint, m_selectedSeries);
+ emitNeedRender();
+ }
+ }
+}
- QSurfaceDataProxy *surfaceDataProxy = static_cast<QSurfaceDataProxy *>(m_data);
+void Surface3DController::handleItemChanged(int rowIndex, int columnIndex)
+{
+ QSurfaceDataProxy *sender = static_cast<QSurfaceDataProxy *>(QObject::sender());
+ if (static_cast<QSurface3DSeries *>(m_seriesList.at(0)) == sender->series()) {
+ // Change is for the visible series, put the change to queue
+ bool newItem = true;
+ QPoint candidate(columnIndex, rowIndex);
+ foreach (QPoint item, m_changedItems) {
+ if (item == candidate) {
+ newItem = false;
+ break;
+ }
+ }
+ if (newItem) {
+ m_changedItems.append(candidate);
+ m_changeTracker.itemChanged = true;
+
+ adjustValueAxisRange();
+ // Clear selection unless still valid
+ setSelectedPoint(m_selectedPoint, m_selectedSeries);
+ emitNeedRender();
+ }
+ }
+}
- QObject::connect(surfaceDataProxy, &QSurfaceDataProxy::arrayReset,
- this, &Surface3DController::handleArrayReset);
+void Surface3DController::handleRowsAdded(int startIndex, int count)
+{
+ Q_UNUSED(startIndex)
+ Q_UNUSED(count)
+ adjustValueAxisRange();
+ m_isDataDirty = true;
+ emitNeedRender();
+}
- scene()->setSlicingActive(false);
+void Surface3DController::handleRowsInserted(int startIndex, int count)
+{
+ Q_UNUSED(startIndex)
+ Q_UNUSED(count)
adjustValueAxisRange();
m_isDataDirty = true;
emitNeedRender();
}
-void Surface3DController::handleArrayReset()
+void Surface3DController::handleRowsRemoved(int startIndex, int count)
{
- scene()->setSlicingActive(false);
+ Q_UNUSED(startIndex)
+ Q_UNUSED(count)
adjustValueAxisRange();
m_isDataDirty = true;
+
+ // Clear selection unless still valid
+ setSelectedPoint(m_selectedPoint, m_selectedSeries);
+
emitNeedRender();
}
void Surface3DController::adjustValueAxisRange()
{
- if (m_data) {
- QVector3D minLimits;
- QVector3D maxLimits;
- static_cast<QSurfaceDataProxy *>(m_data)->dptr()->limitValues(minLimits, maxLimits);
- Q3DValueAxis *valueAxis = static_cast<Q3DValueAxis *>(m_axisX);
- if (valueAxis && valueAxis->isAutoAdjustRange()) {
- if (minLimits.x() != maxLimits.x())
- valueAxis->dptr()->setRange(minLimits.x(), maxLimits.x());
- else
- valueAxis->dptr()->setRange(minLimits.x() - 1.0f, minLimits.x() + 1.0f); // Default to some valid range
+ Q3DValueAxis *valueAxisX = static_cast<Q3DValueAxis *>(m_axisX);
+ Q3DValueAxis *valueAxisY = static_cast<Q3DValueAxis *>(m_axisY);
+ Q3DValueAxis *valueAxisZ = static_cast<Q3DValueAxis *>(m_axisZ);
+ bool adjustX = (valueAxisX && valueAxisX->isAutoAdjustRange());
+ bool adjustY = (valueAxisY && valueAxisY->isAutoAdjustRange());
+ bool adjustZ = (valueAxisZ && valueAxisZ->isAutoAdjustRange());
+
+ if (adjustX || adjustY || adjustZ) {
+ float minValueX = 0.0f;
+ float maxValueX = 0.0f;
+ float minValueY = 0.0f;
+ float maxValueY = 0.0f;
+ float minValueZ = 0.0f;
+ float maxValueZ = 0.0f;
+ int seriesCount = m_seriesList.size();
+ for (int series = 0; series < seriesCount; series++) {
+ const QSurface3DSeries *surfaceSeries =
+ static_cast<QSurface3DSeries *>(m_seriesList.at(series));
+ const QSurfaceDataProxy *proxy = surfaceSeries->dataProxy();
+ if (surfaceSeries->isVisible() && proxy) {
+ QVector3D minLimits;
+ QVector3D maxLimits;
+ proxy->dptrc()->limitValues(minLimits, maxLimits);
+ if (adjustX) {
+ if (!series) {
+ // First series initializes the values
+ minValueX = minLimits.x();
+ maxValueX = maxLimits.x();
+ } else {
+ minValueX = qMin(minValueX, minLimits.x());
+ maxValueX = qMax(maxValueX, maxLimits.x());
+ }
+ }
+ if (adjustY) {
+ if (!series) {
+ // First series initializes the values
+ minValueY = minLimits.y();
+ maxValueY = maxLimits.y();
+ } else {
+ minValueY = qMin(minValueY, minLimits.y());
+ maxValueY = qMax(maxValueY, maxLimits.y());
+ }
+ }
+ if (adjustZ) {
+ if (!series) {
+ // First series initializes the values
+ minValueZ = minLimits.z();
+ maxValueZ = maxLimits.z();
+ } else {
+ minValueZ = qMin(minValueZ, minLimits.z());
+ maxValueZ = qMax(maxValueZ, maxLimits.z());
+ }
+ }
+ }
}
- valueAxis = static_cast<Q3DValueAxis *>(m_axisY);
- if (valueAxis && valueAxis->isAutoAdjustRange()) {
- if (minLimits.y() != maxLimits.y())
- valueAxis->dptr()->setRange(minLimits.y(), maxLimits.y());
- else
- valueAxis->dptr()->setRange(minLimits.y() - 1.0f, minLimits.y() + 1.0f); // Default to some valid range
+ static const float adjustmentRatio = 20.0f;
+ static const float defaultAdjustment = 1.0f;
+
+ if (adjustX) {
+ // If all points at same coordinate, need to default to some valid range
+ float adjustment = 0.0f;
+ if (minValueX == maxValueX) {
+ if (adjustZ) {
+ // X and Z are linked to have similar unit size, so choose the valid range based on it
+ if (minValueZ == maxValueZ)
+ adjustment = defaultAdjustment;
+ else
+ adjustment = qAbs(maxValueZ - minValueZ) / adjustmentRatio;
+ } else {
+ if (valueAxisZ)
+ adjustment = qAbs(valueAxisZ->max() - valueAxisZ->min()) / adjustmentRatio;
+ else
+ adjustment = defaultAdjustment;
+ }
+ }
+ valueAxisX->dptr()->setRange(minValueX - adjustment, maxValueX + adjustment);
}
-
- valueAxis = static_cast<Q3DValueAxis *>(m_axisZ);
- if (valueAxis && valueAxis->isAutoAdjustRange()) {
- if (minLimits.z() != maxLimits.z())
- valueAxis->dptr()->setRange(minLimits.z(), maxLimits.z());
- else
- valueAxis->dptr()->setRange(minLimits.z() - 1.0f, minLimits.z() + 1.0f); // Default to some valid range
+ if (adjustY) {
+ // If all points at same coordinate, need to default to some valid range
+ // Y-axis unit is not dependent on other axes, so simply adjust +-1.0f
+ float adjustment = 0.0f;
+ if (minValueY == maxValueY)
+ adjustment = defaultAdjustment;
+ valueAxisY->dptr()->setRange(minValueY - adjustment, maxValueY + adjustment);
+ }
+ if (adjustZ) {
+ // If all points at same coordinate, need to default to some valid range
+ float adjustment = 0.0f;
+ if (minValueZ == maxValueZ) {
+ if (adjustX) {
+ // X and Z are linked to have similar unit size, so choose the valid range based on it
+ if (minValueX == maxValueX)
+ adjustment = defaultAdjustment;
+ else
+ adjustment = qAbs(maxValueX - minValueX) / adjustmentRatio;
+ } else {
+ if (valueAxisX)
+ adjustment = qAbs(valueAxisX->max() - valueAxisX->min()) / adjustmentRatio;
+ else
+ adjustment = defaultAdjustment;
+ }
+ }
+ valueAxisZ->dptr()->setRange(minValueZ - adjustment, maxValueZ + adjustment);
}
}
}
diff --git a/src/datavisualization/engine/surface3dcontroller_p.h b/src/datavisualization/engine/surface3dcontroller_p.h
index 0698c291..714420a4 100644
--- a/src/datavisualization/engine/surface3dcontroller_p.h
+++ b/src/datavisualization/engine/surface3dcontroller_p.h
@@ -32,21 +32,25 @@
#include "abstract3dcontroller_p.h"
#include "datavisualizationglobal_p.h"
-#include <QLinearGradient>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class Surface3DRenderer;
+class QSurface3DSeries;
struct Surface3DChangeBitField {
- bool gradientColorChanged : 1;
bool smoothStatusChanged : 1;
bool surfaceGridChanged : 1;
+ bool selectedPointChanged : 1;
+ bool rowsChanged : 1;
+ bool itemChanged : 1;
Surface3DChangeBitField() :
- gradientColorChanged(true),
smoothStatusChanged(true),
- surfaceGridChanged(true)
+ surfaceGridChanged(true),
+ selectedPointChanged(true),
+ rowsChanged(false),
+ itemChanged(false)
{
}
};
@@ -57,43 +61,47 @@ class QT_DATAVISUALIZATION_EXPORT Surface3DController : public Abstract3DControl
private:
Surface3DChangeBitField m_changeTracker;
-
- // Rendering
Surface3DRenderer *m_renderer;
- bool m_isSmoothSurfaceEnabled;
- bool m_isSurfaceGridEnabled;
- QLinearGradient m_userDefinedGradient;
+ QPoint m_selectedPoint;
+ QSurface3DSeries *m_selectedSeries; // Points to the series for which the point is selected in
+ // single series selection cases.
+ bool m_flatShadingSupported;
+ QVector<QPoint> m_changedItems;
+ QVector<int> m_changedRows;
public:
explicit Surface3DController(QRect rect);
~Surface3DController();
- void initializeOpenGL();
+ virtual void initializeOpenGL();
virtual void synchDataToRenderer();
- void setSmoothSurface(bool enable);
- bool smoothSurface();
-
- void setSurfaceGrid(bool enable);
- bool surfaceGrid();
-
- void setGradient(const QLinearGradient &gradient);
- QLinearGradient gradient() const;
-
- void setGradientColorAt(qreal pos, const QColor &color);
-
- void setSelectionMode(QDataVis::SelectionMode mode);
-
- virtual void setActiveDataProxy(QAbstractDataProxy *proxy);
+ void setSelectionMode(QDataVis::SelectionFlags mode);
+ void setSelectedPoint(const QPoint &position, QSurface3DSeries *series);
virtual void handleAxisAutoAdjustRangeChangedInOrientation(Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust);
virtual void handleAxisRangeChangedBySender(QObject *sender);
+ virtual void handleSeriesVisibilityChangedBySender(QObject *sender);
+
+ static QPoint invalidSelectionPosition();
+ bool isFlatShadingSupported();
+
+ virtual void addSeries(QAbstract3DSeries *series);
+ virtual void removeSeries(QAbstract3DSeries *series);
+ virtual QList<QSurface3DSeries *> surfaceSeriesList();
public slots:
void handleArrayReset();
+ void handleRowsAdded(int startIndex, int count);
+ void handleRowsChanged(int startIndex, int count);
+ void handleRowsRemoved(int startIndex, int count);
+ void handleRowsInserted(int startIndex, int count);
+ void handleItemChanged(int rowIndex, int columnIndex);
+
+ // Renderer callback handlers
+ void handlePointClicked(const QPoint &position, QSurface3DSeries *series);
-signals:
- void smoothSurfaceEnabledChanged(bool enable);
+ void handleFlatShadingSupportedChange(bool supported);
private:
void adjustValueAxisRange();
diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp
index 63bd93a7..7049632d 100644
--- a/src/datavisualization/engine/surface3drenderer.cpp
+++ b/src/datavisualization/engine/surface3drenderer.cpp
@@ -25,18 +25,15 @@
#include "surfaceobject_p.h"
#include "texturehelper_p.h"
#include "selectionpointer_p.h"
-#include "theme_p.h"
#include "utils_p.h"
#include "drawer_p.h"
#include "q3dlight.h"
+#include "qsurface3dseries_p.h"
#include <QMatrix4x4>
#include <QMouseEvent>
#include <qmath.h>
-#include <QLinearGradient>
-#include <QPainter>
-
#include <QDebug>
static const int ID_TO_RGBA_MASK = 0xff;
@@ -56,13 +53,14 @@ const GLfloat gridLineWidth = 0.005f;
const GLfloat sliceZScale = 0.1f;
const GLfloat sliceUnits = 2.5f;
const int subViewDivider = 5;
+const uint invalidSelectionId = uint(-1);
Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
: Abstract3DRenderer(controller),
- m_controller(controller),
- m_labelStyle(QDataVis::LabelStyleFromTheme),
+ m_labelBackground(false),
m_font(QFont(QStringLiteral("Arial"))),
m_isGridEnabled(true),
+ m_cachedIsSlicingActivated(false),
m_shader(0),
m_depthShader(0),
m_backgroundShader(0),
@@ -95,11 +93,13 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
m_depthFrameBuffer(0),
m_selectionFrameBuffer(0),
m_selectionDepthBuffer(0),
- m_gradientTexture(0),
m_selectionTexture(0),
m_selectionResultTexture(0),
m_shadowQualityToShader(33.3f),
+ m_cachedFlatShading(false),
m_flatSupported(true),
+ m_cachedSurfaceVisible(true),
+ m_cachedSurfaceGridOn(true),
m_selectionPointer(0),
m_selectionActive(false),
m_xFlipped(false),
@@ -107,28 +107,29 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
m_yFlipped(false),
m_sampleSpace(QRect(0, 0, 0, 0)),
m_shadowQualityMultiplier(3),
- m_cachedSelectionId(0),
- m_selectionModeChanged(false),
- m_hasHeightAdjustmentChanged(true)
+ m_clickedPointId(invalidSelectionId),
+ m_hasHeightAdjustmentChanged(true),
+ m_selectedPoint(Surface3DController::invalidSelectionPosition()),
+ m_selectedSeries(0),
+ m_uniformGradientTexture(0)
{
// Check if flat feature is supported
ShaderHelper tester(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
QStringLiteral(":/shaders/fragmentSurfaceFlat"));
if (!tester.testCompile()) {
m_flatSupported = false;
- m_controller->setSmoothSurface(true);
+ connect(this, &Surface3DRenderer::flatShadingSupportedChanged,
+ controller, &Surface3DController::handleFlatShadingSupportedChange);
+ emit flatShadingSupportedChanged(m_flatSupported);
qWarning() << "Warning: Flat qualifier not supported on your platform's GLSL language."
" Requires at least GLSL version 1.2 with GL_EXT_gpu_shader4 extension.";
}
- m_cachedSmoothSurface = m_controller->smoothSurface();
- updateSurfaceGridStatus(m_controller->surfaceGrid());
-
- // Shadows are disabled for Q3DSurface in Tech Preview
- updateShadowQuality(QDataVis::ShadowQualityNone);
-
initializeOpenGLFunctions();
initializeOpenGL();
+
+ // Create initial uniform gradient
+ generateUniformGradient(m_uniformGradientTextureColor);
}
Surface3DRenderer::~Surface3DRenderer()
@@ -138,9 +139,10 @@ Surface3DRenderer::~Surface3DRenderer()
m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer);
m_textureHelper->deleteTexture(&m_depthTexture);
- m_textureHelper->deleteTexture(&m_gradientTexture);
+ m_textureHelper->deleteTexture(&m_depthModelTexture);
m_textureHelper->deleteTexture(&m_selectionTexture);
m_textureHelper->deleteTexture(&m_selectionResultTexture);
+ m_textureHelper->deleteTexture(&m_uniformGradientTexture);
delete m_shader;
delete m_depthShader;
@@ -172,10 +174,7 @@ void Surface3DRenderer::initializeOpenGL()
Abstract3DRenderer::initializeOpenGL();
// Initialize shaders
- handleShadowQualityChange();
-
initSurfaceShaders();
-
initLabelShaders(QStringLiteral(":/shaders/vertexLabel"),
QStringLiteral(":/shaders/fragmentLabel"));
@@ -201,15 +200,22 @@ void Surface3DRenderer::initializeOpenGL()
loadBackgroundMesh();
}
-void Surface3DRenderer::updateDataModel(QSurfaceDataProxy *dataProxy)
+void Surface3DRenderer::updateData()
{
- calculateSceneScalingFactors();
+ // Surface only supports single series for now, so we are only interested in the first series
+ const QSurfaceDataArray *array = 0;
+ if (m_visibleSeriesList.size()) {
+ QSurface3DSeries *firstSeries = static_cast<QSurface3DSeries *>(m_visibleSeriesList.at(0).series());
+ QSurfaceDataProxy *dataProxy = firstSeries->dataProxy();
+ if (dataProxy)
+ array = dataProxy->array();
+ }
- const QSurfaceDataArray &array = *dataProxy->array();
+ calculateSceneScalingFactors();
// Need minimum of 2x2 array to draw a surface
- if (array.size() >= 2 && array.at(0)->size() >= 2) {
- QRect sampleSpace = calculateSampleRect(array);
+ if (array && array->size() >= 2 && array->at(0)->size() >= 2) {
+ QRect sampleSpace = calculateSampleRect(*array);
bool dimensionChanged = false;
if (m_sampleSpace != sampleSpace) {
@@ -230,7 +236,7 @@ void Surface3DRenderer::updateDataModel(QSurfaceDataProxy *dataProxy)
}
for (int i = 0; i < sampleSpace.height(); i++) {
for (int j = 0; j < sampleSpace.width(); j++)
- (*(m_dataArray.at(i)))[j] = array.at(i + sampleSpace.y())->at(j + sampleSpace.x());
+ (*(m_dataArray.at(i)))[j] = array->at(i + sampleSpace.y())->at(j + sampleSpace.x());
}
if (m_dataArray.size() > 0) {
@@ -238,7 +244,7 @@ void Surface3DRenderer::updateDataModel(QSurfaceDataProxy *dataProxy)
loadSurfaceObj();
// Note: Data setup can change sample space (as min width/height is 1)
- if (m_cachedSmoothSurface) {
+ if (!m_cachedFlatShading) {
m_surfaceObj->setUpSmoothData(m_dataArray, m_sampleSpace, m_heightNormalizer,
m_axisCacheY.min(), dimensionChanged);
} else {
@@ -250,21 +256,134 @@ void Surface3DRenderer::updateDataModel(QSurfaceDataProxy *dataProxy)
updateSelectionTexture();
}
}
+ } else {
+ for (int i = 0; i < m_dataArray.size(); i++)
+ delete m_dataArray.at(i);
+ m_dataArray.clear();
+ m_sampleSpace = QRect();
+
+ delete m_surfaceObj;
+ m_surfaceObj = 0;
}
- m_selectionActive = false;
- m_cachedSelectionId = 0;
for (int i = 0; i < m_sliceDataArray.size(); i++)
delete m_sliceDataArray.at(i);
m_sliceDataArray.clear();
- Abstract3DRenderer::updateDataModel(dataProxy);
+ updateSelectedPoint(m_selectedPoint, m_selectedSeries);
+}
+
+void Surface3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList, bool updateVisibility)
+{
+ Abstract3DRenderer::updateSeries(seriesList, updateVisibility);
+
+ // TODO: move to render cache when multiseries support implemented QTRD-2657
+ // TODO: until then just update them always.
+ if (m_visibleSeriesList.size()) {
+ QSurface3DSeries *series = static_cast<QSurface3DSeries *>(m_visibleSeriesList.at(0).series());
+ updateFlatStatus(series->isFlatShadingEnabled());
+
+ QSurface3DSeries::DrawFlags drawMode = series->drawMode();
+ m_cachedSurfaceVisible = drawMode.testFlag(QSurface3DSeries::DrawSurface);
+ m_cachedSurfaceGridOn = drawMode.testFlag(QSurface3DSeries::DrawWireframe);
+
+ QVector3D seriesColor = Utils::vectorFromColor(series->baseColor());
+ if (m_uniformGradientTextureColor != seriesColor)
+ generateUniformGradient(seriesColor);
+ if (m_selectionPointer) {
+ m_selectionPointer->setHighlightColor(Utils::vectorFromColor(series->singleHighlightColor()));
+ // Make sure selection pointer object reference is still good
+ m_selectionPointer->setPointerObject(m_visibleSeriesList.at(0).object());
+ }
+ }
+}
+
+void Surface3DRenderer::updateRows(const QVector<int> &rows)
+{
+ // Surface only supports single series for now, so we are only interested in the first series
+ const QSurfaceDataArray *array = 0;
+ if (m_visibleSeriesList.size()) {
+ QSurface3DSeries *firstSeries = static_cast<QSurface3DSeries *>(m_visibleSeriesList.at(0).series());
+ if (m_cachedSurfaceGridOn || m_cachedSurfaceVisible) {
+ QSurfaceDataProxy *dataProxy = firstSeries->dataProxy();
+ if (dataProxy)
+ array = dataProxy->array();
+ }
+ }
+
+ if (array && array->size() >= 2 && array->at(0)->size() >= 2 &&
+ m_sampleSpace.width() >= 2 && m_sampleSpace.height() >= 2) {
+ bool updateBuffers = false;
+ int sampleSpaceTop = m_sampleSpace.y() + m_sampleSpace.height();
+ foreach (int row, rows) {
+ if (row >= m_sampleSpace.y() && row <= sampleSpaceTop) {
+ updateBuffers = true;
+ for (int j = 0; j < m_sampleSpace.width(); j++)
+ (*(m_dataArray.at(row - m_sampleSpace.y())))[j] =
+ array->at(row)->at(j + m_sampleSpace.x());
+
+ if (m_cachedFlatShading) {
+ m_surfaceObj->updateCoarseRow(m_dataArray, row - m_sampleSpace.y(), m_heightNormalizer,
+ m_axisCacheY.min());
+ } else {
+ m_surfaceObj->updateSmoothRow(m_dataArray, row - m_sampleSpace.y(), m_heightNormalizer,
+ m_axisCacheY.min());
+ }
+ }
+ }
+ if (updateBuffers)
+ m_surfaceObj->uploadBuffers();
+ }
+
+ updateSelectedPoint(m_selectedPoint, m_selectedSeries);
}
-void Surface3DRenderer::updateSliceDataModel(int selectionId)
+void Surface3DRenderer::updateItem(const QVector<QPoint> &points)
{
- int column = (selectionId - 1) % m_sampleSpace.width();
- int row = (selectionId - 1) / m_sampleSpace.width();
+ // TODO: Properly support non-straight rows and columns (QTRD-2643)
+
+ // Surface only supports single series for now, so we are only interested in the first series
+ const QSurfaceDataArray *array = 0;
+ if (m_visibleSeriesList.size()) {
+ QSurface3DSeries *firstSeries = static_cast<QSurface3DSeries *>(m_visibleSeriesList.at(0).series());
+ if (m_cachedSurfaceGridOn || m_cachedSurfaceVisible) {
+ QSurfaceDataProxy *dataProxy = firstSeries->dataProxy();
+ if (dataProxy)
+ array = dataProxy->array();
+ }
+ }
+
+ if (array && array->size() >= 2 && array->at(0)->size() >= 2 &&
+ m_sampleSpace.width() >= 2 && m_sampleSpace.height() >= 2) {
+ int sampleSpaceTop = m_sampleSpace.y() + m_sampleSpace.height();
+ int sampleSpaceRight = m_sampleSpace.x() + m_sampleSpace.width();
+ bool updateBuffers = false;
+ foreach (QPoint item, points) {
+ if (item.y() <= sampleSpaceTop && item.y() >= m_sampleSpace.y() &&
+ item.x() <= sampleSpaceRight && item.x() >= m_sampleSpace.x()) {
+ updateBuffers = true;
+ int x = item.x() - m_sampleSpace.x();
+ int y = item.y() - m_sampleSpace.y();
+ (*(m_dataArray.at(y)))[x] = array->at(item.y())->at(item.x());
+
+ if (m_cachedFlatShading) {
+ m_surfaceObj->updateCoarseItem(m_dataArray, y, x, m_heightNormalizer, m_axisCacheY.min());
+ } else {
+ m_surfaceObj->updateSmoothItem(m_dataArray, y, x, m_heightNormalizer, m_axisCacheY.min());
+ }
+ }
+ }
+ if (updateBuffers)
+ m_surfaceObj->uploadBuffers();
+ }
+
+ updateSelectedPoint(m_selectedPoint, m_selectedSeries);
+}
+
+void Surface3DRenderer::updateSliceDataModel(const QPoint &point)
+{
+ int column = point.y();
+ int row = point.x();
for (int i = 0; i < m_sliceDataArray.size(); i++)
delete m_sliceDataArray.at(i);
@@ -273,19 +392,19 @@ void Surface3DRenderer::updateSliceDataModel(int selectionId)
m_sliceDataArray.reserve(2);
QSurfaceDataRow *sliceRow;
- qreal adjust = (0.025 * m_heightNormalizer) / 2.0;
- qreal stepDown = 2.0 * adjust;
- if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow) {
+ float adjust = (0.025f * m_heightNormalizer) / 2.0f;
+ float stepDown = 2.0f * adjust;
+ if (m_cachedSelectionMode.testFlag(QDataVis::SelectionRow)) {
QSurfaceDataRow *src = m_dataArray.at(row);
sliceRow = new QSurfaceDataRow(src->size());
for (int i = 0; i < sliceRow->size(); i++)
- (*sliceRow)[i].setPosition(QVector3D(src->at(i).x(), src->at(i).y() + adjust, -1.0));
+ (*sliceRow)[i].setPosition(QVector3D(src->at(i).x(), src->at(i).y() + adjust, -1.0f));
} else {
sliceRow = new QSurfaceDataRow(m_sampleSpace.height());
for (int i = 0; i < m_sampleSpace.height(); i++) {
(*sliceRow)[i].setPosition(QVector3D(m_dataArray.at(i)->at(column).z(),
m_dataArray.at(i)->at(column).y() + adjust,
- -1.0));
+ -1.0f));
}
}
@@ -294,7 +413,7 @@ void Surface3DRenderer::updateSliceDataModel(int selectionId)
// Make a duplicate, so that we get a little bit depth
QSurfaceDataRow *duplicateRow = new QSurfaceDataRow(*sliceRow);
for (int i = 0; i < sliceRow->size(); i++)
- (*sliceRow)[i].setPosition(QVector3D(sliceRow->at(i).x(), sliceRow->at(i).y() - stepDown, 1.0));
+ (*sliceRow)[i].setPosition(QVector3D(sliceRow->at(i).x(), sliceRow->at(i).y() - stepDown, 1.0f));
m_sliceDataArray << duplicateRow;
@@ -304,7 +423,7 @@ void Surface3DRenderer::updateSliceDataModel(int selectionId)
if (!m_sliceSurfaceObj)
loadSliceSurfaceObj();
- if (m_cachedSmoothSurface) {
+ if (!m_cachedFlatShading) {
m_sliceSurfaceObj->setUpSmoothData(m_sliceDataArray, sliceRect, m_heightNormalizer,
m_axisCacheY.min(), true);
} else {
@@ -323,20 +442,10 @@ QRect Surface3DRenderer::calculateSampleRect(const QSurfaceDataArray &array)
int i;
bool found;
- float axisMinX = float(m_axisCacheX.min());
- float axisMaxX = float(m_axisCacheX.max());
- float axisMinZ = float(m_axisCacheZ.min());
- float axisMaxZ = float(m_axisCacheZ.max());
-
- // Comparisons between float and double are not accurate, so fudge our comparison values
- //a little to get all rows and columns into view that need to be visible.
- const float fudgeFactor = 0.00001f;
- float fudgedAxisXRange = (axisMaxX - axisMinX) * fudgeFactor;
- float fudgedAxisZRange = (axisMaxZ - axisMinZ) * fudgeFactor;
- axisMinX -= fudgedAxisXRange;
- axisMinZ -= fudgedAxisZRange;
- axisMaxX += fudgedAxisXRange;
- axisMaxZ += fudgedAxisZRange;
+ float axisMinX = m_axisCacheX.min();
+ float axisMaxX = m_axisCacheX.max();
+ float axisMinZ = m_axisCacheZ.min();
+ float axisMaxZ = m_axisCacheZ.max();
// m_minVisibleColumnValue
for (i = 0, found = false; i < columnCount; i++) {
@@ -414,10 +523,6 @@ QRect Surface3DRenderer::calculateSampleRect(const QSurfaceDataArray &array)
void Surface3DRenderer::updateScene(Q3DScene *scene)
{
- // TODO: Move these to more suitable place e.g. controller should be controlling the viewports.
- scene->setSecondarySubViewport(m_sliceViewPort);
- scene->setPrimarySubViewport(m_mainViewPort);
-
// Set initial camera position
// X must be 0 for rotation to work - we can use "setCameraRotation" for setting it later
if (m_hasHeightAdjustmentChanged) {
@@ -426,41 +531,28 @@ void Surface3DRenderer::updateScene(Q3DScene *scene)
m_hasHeightAdjustmentChanged = false;
}
- scene->activeCamera()->d_ptr->updateViewMatrix(m_autoScaleAdjustment);
- scene->setLightPositionRelativeToCamera(defaultLightPos);
-
Abstract3DRenderer::updateScene(scene);
if (m_selectionPointer)
m_selectionPointer->updateScene(m_cachedScene);
+
+ updateSlicingActive(scene->isSlicingActive());
}
void Surface3DRenderer::render(GLuint defaultFboHandle)
{
- bool slicingActivated = m_cachedScene->isSlicingActive();
- bool slicingChanged = m_cachedIsSlicingActivated != slicingActivated;
-
- updateSlicingActive(slicingActivated);
-
// Handle GL state setup for FBO buffers and clearing of the render surface
Abstract3DRenderer::render(defaultFboHandle);
- // Draw the surface scene
drawScene(defaultFboHandle);
-
- // In slice mode; draw slice and render selection ball
if (m_cachedIsSlicingActivated)
drawSlicedScene();
- // Render selection ball if not in slice mode
- if (m_selectionPointer && m_selectionActive)
+ // Render selection ball
+ if (m_selectionPointer && m_selectionActive
+ && m_cachedSelectionMode.testFlag(QDataVis::SelectionItem)) {
m_selectionPointer->render(defaultFboHandle);
-
- // If slicing has been activated by this render pass, we need another render
- // Also trigger another render always when slicing changes in general to ensure
- // final draw is correct.
- if (slicingActivated != m_cachedScene->isSlicingActive() || slicingChanged)
- emit needRender();
+ }
}
void Surface3DRenderer::drawSlicedScene()
@@ -468,13 +560,15 @@ void Surface3DRenderer::drawSlicedScene()
QVector3D lightPos;
// Specify viewport
- glViewport(m_sliceViewPort.x(), m_sliceViewPort.y(),
- m_sliceViewPort.width(), m_sliceViewPort.height());
+ glViewport(m_secondarySubViewport.x(),
+ m_secondarySubViewport.y(),
+ m_secondarySubViewport.width(),
+ m_secondarySubViewport.height());
// Set up projection matrix
QMatrix4x4 projectionMatrix;
- GLfloat aspect = (GLfloat)m_mainViewPort.width() / (GLfloat)m_mainViewPort.height();
+ GLfloat aspect = (GLfloat)m_secondarySubViewport.width() / (GLfloat)m_secondarySubViewport.height();
projectionMatrix.ortho(-sliceUnits * aspect, sliceUnits * aspect,
-sliceUnits, sliceUnits, -1.0f, 4.0f);
@@ -487,30 +581,24 @@ void Surface3DRenderer::drawSlicedScene()
QMatrix4x4 projectionViewMatrix = projectionMatrix * viewMatrix;
+ bool rowMode = m_cachedSelectionMode.testFlag(QDataVis::SelectionRow);
+
GLfloat scaleX = 0.0f;
GLfloat scaleXBackground = 0.0f;
GLfloat offset = 0.0f;
- if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow) {
+ if (rowMode) {
scaleX = m_surfaceScaleX;
scaleXBackground = m_scaleXWithBackground;
offset = m_surfaceOffsetX;
- } else if (m_cachedSelectionMode == QDataVis::SelectionModeSliceColumn) {
+ } else {
scaleX = m_surfaceScaleZ;
scaleXBackground = m_scaleZWithBackground;
offset = -m_surfaceOffsetZ;
}
if (m_surfaceObj) {
- ShaderHelper *surfaceShader = m_shader;
- surfaceShader->bind();
-
- if (m_cachedSurfaceGridOn) {
- glEnable(GL_POLYGON_OFFSET_FILL);
- glPolygonOffset(0.5f, 1.0f);
- }
-
- QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
+ QMatrix4x4 modelMatrix;
QMatrix4x4 itModelMatrix;
modelMatrix.translate(offset, 0.0f, 0.0f);
@@ -520,36 +608,40 @@ void Surface3DRenderer::drawSlicedScene()
MVPMatrix = projectionViewMatrix * modelMatrix;
- QVector3D color;
- if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow)
- color = Utils::vectorFromColor(m_cachedTheme.m_highlightRowColor);
- else
- color = Utils::vectorFromColor(m_cachedTheme.m_highlightColumnColor);
-
- // Set shader bindings
- surfaceShader->setUniformValue(surfaceShader->lightP(), lightPos);
- surfaceShader->setUniformValue(surfaceShader->view(), viewMatrix);
- surfaceShader->setUniformValue(surfaceShader->model(), modelMatrix);
- surfaceShader->setUniformValue(surfaceShader->nModel(),
- itModelMatrix.inverted().transposed());
- surfaceShader->setUniformValue(surfaceShader->MVP(), MVPMatrix);
- surfaceShader->setUniformValue(surfaceShader->color(), color);
- surfaceShader->setUniformValue(surfaceShader->lightS(), 0.25f);
- surfaceShader->setUniformValue(surfaceShader->ambientS(),
- m_cachedTheme.m_ambientStrength * 2.0f);
-
- m_drawer->drawObject(surfaceShader, m_sliceSurfaceObj);
+ if (m_cachedSurfaceVisible) {
+ if (m_cachedSurfaceGridOn) {
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ glPolygonOffset(0.5f, 1.0f);
+ }
- surfaceShader->release();
+ ShaderHelper *surfaceShader = m_shader;
+ surfaceShader->bind();
+
+ QVector3D color;
+ color = Utils::vectorFromColor(m_cachedTheme->multiHighlightColor());
+
+ // Set shader bindings
+ surfaceShader->setUniformValue(surfaceShader->lightP(), lightPos);
+ surfaceShader->setUniformValue(surfaceShader->view(), viewMatrix);
+ surfaceShader->setUniformValue(surfaceShader->model(), modelMatrix);
+ surfaceShader->setUniformValue(surfaceShader->nModel(),
+ itModelMatrix.inverted().transposed());
+ surfaceShader->setUniformValue(surfaceShader->MVP(), MVPMatrix);
+ surfaceShader->setUniformValue(surfaceShader->color(), color);
+ surfaceShader->setUniformValue(surfaceShader->lightS(), 0.25f);
+ surfaceShader->setUniformValue(surfaceShader->ambientS(),
+ m_cachedTheme->ambientLightStrength() * 2.0f);
+
+ m_drawer->drawObject(surfaceShader, m_sliceSurfaceObj);
+ }
// Draw surface grid
if (m_cachedSurfaceGridOn) {
m_surfaceGridShader->bind();
m_surfaceGridShader->setUniformValue(m_surfaceGridShader->color(),
- Utils::vectorFromColor(m_cachedTheme.m_gridLine));
+ Utils::vectorFromColor(m_cachedTheme->gridLineColor()));
m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), MVPMatrix);
m_drawer->drawSurfaceGrid(m_surfaceGridShader, m_sliceSurfaceObj);
- m_surfaceGridShader->release();
glDisable(GL_POLYGON_OFFSET_FILL);
}
@@ -559,17 +651,17 @@ void Surface3DRenderer::drawSlicedScene()
glDisable(GL_TEXTURE_2D);
// Grid lines
- if (m_cachedIsGridEnabled && m_heightNormalizer) {
+ if (m_cachedTheme->isGridEnabled() && m_heightNormalizer) {
ShaderHelper *lineShader = m_backgroundShader;
// Bind line shader
lineShader->bind();
// Set unchanging shader bindings
- QVector3D lineColor = Utils::vectorFromColor(m_cachedTheme.m_gridLine);
+ QVector3D lineColor = Utils::vectorFromColor(m_cachedTheme->gridLineColor());
lineShader->setUniformValue(lineShader->lightP(), lightPos);
lineShader->setUniformValue(lineShader->view(), viewMatrix);
lineShader->setUniformValue(lineShader->color(), lineColor);
- lineShader->setUniformValue(lineShader->ambientS(), m_cachedTheme.m_ambientStrength * 2.0f);
+ lineShader->setUniformValue(lineShader->ambientS(), m_cachedTheme->ambientLightStrength() * 2.0f);
lineShader->setUniformValue(lineShader->lightS(), 0.25f);
// Horizontal lines
@@ -611,7 +703,7 @@ void Surface3DRenderer::drawSlicedScene()
int lastSegment;
GLfloat lineStep;
GLfloat linePos;
- if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow) {
+ if (rowMode) {
lineStep = -2.0f * aspectRatio * m_axisCacheX.subSegmentStep() / m_scaleFactor;
lastSegment = m_axisCacheX.subSegmentCount() * m_axisCacheX.segmentCount();
linePos = m_scaleX;
@@ -643,9 +735,6 @@ void Surface3DRenderer::drawSlicedScene()
linePos += lineStep;
}
-
- // Release line shader
- lineShader->release();
}
// Draw axis labels
@@ -653,10 +742,8 @@ void Surface3DRenderer::drawSlicedScene()
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glCullFace(GL_BACK);
- if (m_cachedLabelStyle > QDataVis::LabelStyleOpaque) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Y Labels to back wall
GLfloat posStep = 2.0f * m_axisCacheY.segmentStep() / m_heightNormalizer;
@@ -676,7 +763,7 @@ void Surface3DRenderer::drawSlicedScene()
m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
positionComp, rotation, 0, m_cachedSelectionMode, m_labelShader,
m_labelObj, m_cachedScene->activeCamera(),
- true, true, Drawer::LabelMid, Qt::AlignRight);
+ true, true, Drawer::LabelMid, Qt::AlignRight, true);
}
labelNbr++;
labelPos += posStep;
@@ -685,7 +772,7 @@ void Surface3DRenderer::drawSlicedScene()
// X Labels to ground
int countLabelItems;
int lastSegment;
- if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow) {
+ if (rowMode) {
posStep = 2.0f * aspectRatio * m_axisCacheX.segmentStep() / m_scaleFactor;
labelPos = -m_scaleX;
lastSegment = m_axisCacheX.segmentCount();
@@ -709,15 +796,15 @@ void Surface3DRenderer::drawSlicedScene()
m_dummyRenderItem.setTranslation(labelTrans);
LabelItem *axisLabelItem;
- if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow)
+ if (rowMode)
axisLabelItem = m_axisCacheX.labelItems().at(labelNbr);
else
axisLabelItem = m_axisCacheZ.labelItems().at(labelNbr);
m_drawer->drawLabel(m_dummyRenderItem, *axisLabelItem, viewMatrix, projectionMatrix,
- positionComp, rotation, 0, QDataVis::SelectionModeSliceRow,
+ positionComp, rotation, 0, QDataVis::SelectionRow,
m_labelShader, m_labelObj, m_cachedScene->activeCamera(),
- false, false, Drawer::LabelBelow, Qt::AlignTop);
+ false, false, Drawer::LabelBelow, Qt::AlignTop, true);
}
labelNbr++;
labelPos += posStep;
@@ -725,26 +812,26 @@ void Surface3DRenderer::drawSlicedScene()
glDisable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
- if (m_cachedLabelStyle > QDataVis::LabelStyleOpaque)
- glDisable(GL_BLEND);
+ glDisable(GL_BLEND);
- // Release label shader
- m_labelShader->release();
+ // Release shader
+ glUseProgram(0);
}
void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
{
GLfloat backgroundRotation = 0;
- uint selectionId = 0;
+ glViewport(m_primarySubViewport.x(),
+ m_primarySubViewport.y(),
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
// Specify viewport
- glViewport(m_mainViewPort.x(), m_mainViewPort.y(),
- m_mainViewPort.width(), m_mainViewPort.height());
// Set up projection matrix
QMatrix4x4 projectionMatrix;
- projectionMatrix.perspective(45.0f, (GLfloat)m_mainViewPort.width()
- / (GLfloat)m_mainViewPort.height(), 0.1f, 100.0f);
+ projectionMatrix.perspective(45.0f, (GLfloat)m_primarySubViewport.width()
+ / (GLfloat)m_primarySubViewport.height(), 0.1f, 100.0f);
// Calculate view matrix
QMatrix4x4 viewMatrix = m_cachedScene->activeCamera()->viewMatrix();
@@ -782,11 +869,13 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
// Draw depth buffer
#if !defined(QT_OPENGL_ES_2)
- GLfloat adjustedLightStrength = m_cachedTheme.m_lightStrength / 10.0f;
- if (m_cachedShadowQuality > QDataVis::ShadowQualityNone && m_surfaceObj) {
+ GLfloat adjustedLightStrength = m_cachedTheme->lightStrength() / 10.0f;
+ if (m_cachedShadowQuality > QDataVis::ShadowQualityNone && m_surfaceObj && m_cachedSurfaceVisible) {
// Render scene into a depth texture for using with shadow mapping
// Enable drawing to depth framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, m_depthFrameBuffer);
+ // Attach texture to depth attachment
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthTexture, 0);
glClear(GL_DEPTH_BUFFER_BIT);
// Bind depth shader
@@ -794,8 +883,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
// Set viewport for depth map rendering. Must match texture size. Larger values give smoother shadows.
glViewport(0, 0,
- m_mainViewPort.width() * m_shadowQualityMultiplier,
- m_mainViewPort.height() * m_shadowQualityMultiplier);
+ m_primarySubViewport.width() * m_shadowQualityMultiplier,
+ m_primarySubViewport.height() * m_shadowQualityMultiplier);
// Get the depth view matrix
// It may be possible to hack lightPos here if we want to make some tweaks to shadow
@@ -809,8 +898,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
// Set the depth projection matrix
#ifndef USE_WIDER_SHADOWS
// Use this for perspective shadows
- depthProjectionMatrix.perspective(10.0f, (GLfloat)m_mainViewPort.width()
- / (GLfloat)m_mainViewPort.height(), 3.0f, 100.0f);
+ depthProjectionMatrix.perspective(10.0f, (GLfloat)m_primarySubViewport.width()
+ / (GLfloat)m_primarySubViewport.height(), 3.0f, 100.0f);
#else
// Use these for orthographic shadows
depthProjectionMatrix.ortho(-2.0f * 2.0f, 2.0f * 2.0f,
@@ -819,7 +908,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
#endif
depthProjectionViewMatrix = depthProjectionMatrix * depthViewMatrix;
- glCullFace(GL_FRONT);
+ glDisable(GL_CULL_FACE);
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
@@ -841,7 +930,17 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_surfaceObj->elementBuf());
// Draw the triangles
- glDrawElements(GL_TRIANGLES, m_surfaceObj->indexCount(), GL_UNSIGNED_SHORT,
+ glDrawElements(GL_TRIANGLES, m_surfaceObj->indexCount(), m_surfaceObj->indicesType(),
+ (void *)0);
+
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_FRONT);
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthModelTexture, 0);
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ // Draw the triangles
+ glDrawElements(GL_TRIANGLES, m_surfaceObj->indexCount(), m_surfaceObj->indicesType(),
(void *)0);
// Free buffers
@@ -853,14 +952,14 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
// Disable drawing to depth framebuffer (= enable drawing to screen)
glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle);
- // Release depth shader
- m_depthShader->release();
-
// Revert to original viewport
- glViewport(m_mainViewPort.x(), m_mainViewPort.y(),
- m_mainViewPort.width(), m_mainViewPort.height());
+ glViewport(m_primarySubViewport.x(),
+ m_primarySubViewport.y(),
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
// Reset culling to normal
+ glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
#if 0 // Use this if you want to see what is being drawn to the framebuffer
@@ -875,24 +974,27 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix);
m_drawer->drawObject(m_labelShader, m_labelObj, m_depthTexture);
glDisable(GL_TEXTURE_2D);
- m_labelShader->release();
}
#endif
}
#endif
-
- bool selectionDirty = false;
-
// Enable texturing
glEnable(GL_TEXTURE_2D);
// Draw selection buffer
- if (!m_cachedIsSlicingActivated && m_controller->inputState() == QDataVis::InputStateOnScene
- && m_surfaceObj && m_cachedSelectionMode > QDataVis::SelectionModeNone) {
+ if (!m_cachedIsSlicingActivated && m_surfaceObj && m_selectionState == SelectOnScene
+ && m_cachedSelectionMode > QDataVis::SelectionNone
+ && (m_cachedSurfaceVisible || m_cachedSurfaceGridOn)
+ && m_visibleSeriesList.size() > 0) {
m_selectionShader->bind();
glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer);
+ glViewport(0,
+ 0,
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
+
glEnable(GL_DEPTH_TEST); // Needed, otherwise the depth render buffer is not used
- glClearColor(0, 0, 0, 0);
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Needed for clearing the frame buffer
glDisable(GL_DITHER); // disable dithering, it may affect colors if enabled
@@ -912,30 +1014,32 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glEnable(GL_DITHER);
- QPoint point = m_controller->inputPosition();
- GLubyte pixel[4] = {0};
- glReadPixels(point.x(), m_cachedBoundingRect.height() - point.y(), 1, 1,
- GL_RGBA, GL_UNSIGNED_BYTE, (void *)pixel);
+ GLubyte pixel[4] = {0, 0, 0, 0};
+ glReadPixels(m_inputPosition.x(), m_viewport.height() - m_inputPosition.y(),
+ 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void *)pixel);
glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle);
- // Release selection shader
- m_selectionShader->release();
-
// Put the RGBA value back to uint
#if !defined(QT_OPENGL_ES_2)
- selectionId = pixel[0] + pixel[1] * 256 + pixel[2] * 65536 + pixel[3] * 16777216;
+ uint selectionId = pixel[0] + pixel[1] * 256 + pixel[2] * 65536 + pixel[3] * 16777216;
#else
- selectionId = pixel[0] + pixel[1] * 256 + pixel[2] * 65536;
+ uint selectionId = pixel[0] + pixel[1] * 256 + pixel[2] * 65536;
#endif
- selectionDirty = true;
+ emit pointClicked(QPoint(selectionIdToSurfacePoint(selectionId)),
+ static_cast<QSurface3DSeries *>(m_visibleSeriesList.at(0).series()));
+
+ // Revert to original viewport
+ glViewport(m_primarySubViewport.x(),
+ m_primarySubViewport.y(),
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
}
// Draw the surface
if (m_surfaceObj && m_sampleSpace.width() >= 2 && m_sampleSpace.height() >= 2) {
m_surfaceShader->bind();
-
// For surface we can see climpses from underneath
glDisable(GL_CULL_FACE);
if (m_cachedSurfaceGridOn) {
@@ -956,49 +1060,55 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
#else
MVPMatrix = projectionViewMatrix * modelMatrix;
#endif
- // Set shader bindings
- m_surfaceShader->setUniformValue(m_surfaceShader->lightP(), lightPos);
- m_surfaceShader->setUniformValue(m_surfaceShader->view(), viewMatrix);
- m_surfaceShader->setUniformValue(m_surfaceShader->model(), modelMatrix);
- m_surfaceShader->setUniformValue(m_surfaceShader->nModel(),
- itModelMatrix.inverted().transposed());
- m_surfaceShader->setUniformValue(m_surfaceShader->MVP(), MVPMatrix);
- m_surfaceShader->setUniformValue(m_surfaceShader->ambientS(),
- m_cachedTheme.m_ambientStrength);
+
+ if (m_cachedSurfaceVisible) {
+ // Set shader bindings
+ m_surfaceShader->setUniformValue(m_surfaceShader->lightP(), lightPos);
+ m_surfaceShader->setUniformValue(m_surfaceShader->view(), viewMatrix);
+ m_surfaceShader->setUniformValue(m_surfaceShader->model(), modelMatrix);
+ m_surfaceShader->setUniformValue(m_surfaceShader->nModel(),
+ itModelMatrix.inverted().transposed());
+ m_surfaceShader->setUniformValue(m_surfaceShader->MVP(), MVPMatrix);
+ m_surfaceShader->setUniformValue(m_surfaceShader->ambientS(),
+ m_cachedTheme->ambientLightStrength());
+
+ // TODO: Do properly when multiseries support implemented QTRD-2657
+ GLuint gradientTexture;
+ if (m_visibleSeriesList.at(0).colorStyle() == Q3DTheme::ColorStyleUniform)
+ gradientTexture = m_uniformGradientTexture;
+ else
+ gradientTexture = m_visibleSeriesList.at(0).baseGradientTexture();
#if !defined(QT_OPENGL_ES_2)
- if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
- // Set shadow shader bindings
- QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix;
- m_surfaceShader->setUniformValue(m_surfaceShader->shadowQ(), m_shadowQualityToShader);
- m_surfaceShader->setUniformValue(m_surfaceShader->depth(), depthMVPMatrix);
- m_surfaceShader->setUniformValue(m_surfaceShader->lightS(), adjustedLightStrength);
+ if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
+ // Set shadow shader bindings
+ QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix;
+ m_surfaceShader->setUniformValue(m_surfaceShader->shadowQ(), m_shadowQualityToShader);
+ m_surfaceShader->setUniformValue(m_surfaceShader->depth(), depthMVPMatrix);
+ m_surfaceShader->setUniformValue(m_surfaceShader->lightS(), adjustedLightStrength);
- // Draw the object
- m_drawer->drawObject(m_surfaceShader, m_surfaceObj, m_gradientTexture, m_depthTexture);
- } else
+ // Draw the object
+ m_drawer->drawObject(m_surfaceShader, m_surfaceObj, gradientTexture, m_depthModelTexture);
+ } else
#endif
- {
- // Set shadowless shader bindings
- m_surfaceShader->setUniformValue(m_surfaceShader->lightS(),
- m_cachedTheme.m_lightStrength);
+ {
+ // Set shadowless shader bindings
+ m_surfaceShader->setUniformValue(m_surfaceShader->lightS(),
+ m_cachedTheme->lightStrength());
- // Draw the object
- m_drawer->drawObject(m_surfaceShader, m_surfaceObj, m_gradientTexture);
+ // Draw the object
+ m_drawer->drawObject(m_surfaceShader, m_surfaceObj, gradientTexture);
+ }
+ glEnable(GL_CULL_FACE);
}
- m_surfaceShader->release();
-
- glEnable(GL_CULL_FACE);
-
// Draw surface grid
if (m_cachedSurfaceGridOn) {
m_surfaceGridShader->bind();
m_surfaceGridShader->setUniformValue(m_surfaceGridShader->color(),
- Utils::vectorFromColor(m_cachedTheme.m_gridLine));
+ Utils::vectorFromColor(m_cachedTheme->gridLineColor()));
m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), MVPMatrix);
m_drawer->drawSurfaceGrid(m_surfaceGridShader, m_surfaceObj);
- m_surfaceGridShader->release();
glDisable(GL_POLYGON_OFFSET_FILL);
}
@@ -1009,7 +1119,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glCullFace(GL_BACK);
// Draw background
- if (m_cachedIsBackgroundEnabled && m_backgroundObj) {
+ if (m_cachedTheme->isBackgroundEnabled() && m_backgroundObj) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
@@ -1019,7 +1129,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
// If we're viewing from below, background object must be flipped
if (m_yFlipped) {
- modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
+ modelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
modelMatrix.rotate(270.0f - backgroundRotation, 0.0f, 1.0f, 0.0f);
} else {
modelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f);
@@ -1033,7 +1143,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
MVPMatrix = projectionViewMatrix * modelMatrix;
#endif
- QVector3D backgroundColor = Utils::vectorFromColor(m_cachedTheme.m_backgroundColor);
+ QVector3D backgroundColor = Utils::vectorFromColor(m_cachedTheme->backgroundColor());
// Set shader bindings
m_backgroundShader->setUniformValue(m_backgroundShader->lightP(), lightPos);
@@ -1044,7 +1154,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
m_backgroundShader->setUniformValue(m_backgroundShader->MVP(), MVPMatrix);
m_backgroundShader->setUniformValue(m_backgroundShader->color(), backgroundColor);
m_backgroundShader->setUniformValue(m_backgroundShader->ambientS(),
- m_cachedTheme.m_ambientStrength * 2.0f);
+ m_cachedTheme->ambientLightStrength() * 2.0f);
#if !defined(QT_OPENGL_ES_2)
if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
@@ -1063,46 +1173,60 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
{
// Set shadowless shader bindings
m_backgroundShader->setUniformValue(m_backgroundShader->lightS(),
- m_cachedTheme.m_lightStrength);
+ m_cachedTheme->lightStrength());
// Draw the object
m_drawer->drawObject(m_backgroundShader, m_backgroundObj);
}
}
- // Release background shader
- m_backgroundShader->release();
-
// Draw grid lines
QVector3D gridLineScaleX(m_scaleXWithBackground, gridLineWidth, gridLineWidth);
QVector3D gridLineScaleZ(gridLineWidth, gridLineWidth, m_scaleZWithBackground);
QVector3D gridLineScaleY(gridLineWidth, backgroundMargin, gridLineWidth);
- if (m_cachedIsGridEnabled && m_heightNormalizer) {
+ if (m_cachedTheme->isGridEnabled() && m_heightNormalizer) {
ShaderHelper *lineShader = m_backgroundShader;
// Bind line shader
lineShader->bind();
// Set unchanging shader bindings
- QVector3D lineColor = Utils::vectorFromColor(m_cachedTheme.m_gridLine);
+ QVector3D lineColor = Utils::vectorFromColor(m_cachedTheme->gridLineColor());
lineShader->setUniformValue(lineShader->lightP(), lightPos);
lineShader->setUniformValue(lineShader->view(), viewMatrix);
lineShader->setUniformValue(lineShader->color(), lineColor);
- lineShader->setUniformValue(lineShader->ambientS(), m_cachedTheme.m_ambientStrength);
+ lineShader->setUniformValue(lineShader->ambientS(), m_cachedTheme->ambientLightStrength());
#if !defined(QT_OPENGL_ES_2)
if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
// Set shadowed shader bindings
lineShader->setUniformValue(lineShader->shadowQ(), m_shadowQualityToShader);
lineShader->setUniformValue(lineShader->lightS(),
- m_cachedTheme.m_lightStrength / 20.0f);
+ m_cachedTheme->lightStrength() / 20.0f);
} else
#endif
{
// Set shadowless shader bindings
- lineShader->setUniformValue(lineShader->lightS(), m_cachedTheme.m_lightStrength / 2.5f);
+ lineShader->setUniformValue(lineShader->lightS(), m_cachedTheme->lightStrength() / 2.5f);
}
+ QQuaternion lineYRotation = QQuaternion();
+ QQuaternion lineXRotation = QQuaternion();
+
+ if (m_xFlipped)
+ lineYRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, -90.0f);
+ else
+ lineYRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, 90.0f);
+
+ if (m_yFlipped)
+ lineXRotation = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, 90.0f);
+ else
+ lineXRotation = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, -90.0f);
+
+ GLfloat yFloorLinePosition = -backgroundMargin + gridLineOffset;
+ if (m_yFlipped)
+ yFloorLinePosition = -yFloorLinePosition;
+
// Rows (= Z)
if (m_axisCacheZ.segmentCount() > 0) {
// Floor lines
@@ -1115,19 +1239,13 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- if (m_yFlipped)
- modelMatrix.translate(0.0f, backgroundMargin, linePos);
- else
- modelMatrix.translate(0.0f, -backgroundMargin, linePos);
+ modelMatrix.translate(0.0f, yFloorLinePosition, linePos);
modelMatrix.scale(gridLineScaleX);
itModelMatrix.scale(gridLineScaleX);
- // If we're viewing from below, grid line object must be flipped
- if (m_yFlipped) {
- modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
- itModelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
- }
+ modelMatrix.rotate(lineXRotation);
+ itModelMatrix.rotate(lineXRotation);
MVPMatrix = projectionViewMatrix * modelMatrix;
@@ -1154,7 +1272,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
}
// Side wall lines
- GLfloat lineXTrans = m_scaleXWithBackground;
+ GLfloat lineXTrans = m_scaleXWithBackground - gridLineOffset;
linePos = m_scaleZ; // Start line
if (!m_xFlipped)
@@ -1166,9 +1284,13 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
QMatrix4x4 itModelMatrix;
modelMatrix.translate(lineXTrans, 0.0f, linePos);
+
modelMatrix.scale(gridLineScaleY);
itModelMatrix.scale(gridLineScaleY);
+ modelMatrix.rotate(lineYRotation);
+ itModelMatrix.rotate(lineYRotation);
+
MVPMatrix = projectionViewMatrix * modelMatrix;
// Set the rest of the shader bindings
@@ -1206,19 +1328,13 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- if (m_yFlipped)
- modelMatrix.translate(linePos, backgroundMargin, 0.0f);
- else
- modelMatrix.translate(linePos, -backgroundMargin, 0.0f);
+ modelMatrix.translate(linePos, yFloorLinePosition, 0.0f);
modelMatrix.scale(gridLineScaleZ);
itModelMatrix.scale(gridLineScaleZ);
- // If we're viewing from below, grid line object must be flipped
- if (m_yFlipped) {
- modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
- itModelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
- }
+ modelMatrix.rotate(lineXRotation);
+ itModelMatrix.rotate(lineXRotation);
MVPMatrix = projectionViewMatrix * modelMatrix;
@@ -1245,7 +1361,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
}
// Back wall lines
- GLfloat lineZTrans = m_scaleZWithBackground;
+ GLfloat lineZTrans = m_scaleZWithBackground - gridLineOffset;
linePos = m_scaleX;
if (!m_zFlipped)
@@ -1257,9 +1373,15 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
QMatrix4x4 itModelMatrix;
modelMatrix.translate(linePos, 0.0f, lineZTrans);
+
modelMatrix.scale(gridLineScaleY);
itModelMatrix.scale(gridLineScaleY);
+ if (m_zFlipped) {
+ modelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
+ itModelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
+ }
+
MVPMatrix = projectionViewMatrix * modelMatrix;
// Set the rest of the shader bindings
@@ -1292,7 +1414,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
GLfloat linePos = -1.0f;
int lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount();
- GLfloat lineZTrans = m_scaleZWithBackground;
+ GLfloat lineZTrans = m_scaleZWithBackground - gridLineOffset;
if (!m_zFlipped)
lineZTrans = -lineZTrans;
@@ -1307,6 +1429,11 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
modelMatrix.scale(gridLineScaleX);
itModelMatrix.scale(gridLineScaleX);
+ if (m_zFlipped) {
+ modelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
+ itModelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
+ }
+
MVPMatrix = projectionViewMatrix * modelMatrix;
// Set the rest of the shader bindings
@@ -1334,7 +1461,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
// Side wall
linePos = -1.0f;
lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount();
- GLfloat lineXTrans = m_scaleXWithBackground;
+ GLfloat lineXTrans = m_scaleXWithBackground - gridLineOffset;
if (!m_xFlipped)
lineXTrans = -lineXTrans;
@@ -1349,6 +1476,9 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
modelMatrix.scale(gridLineScaleZ);
itModelMatrix.scale(gridLineScaleZ);
+ modelMatrix.rotate(lineYRotation);
+ itModelMatrix.rotate(lineYRotation);
+
MVPMatrix = projectionViewMatrix * modelMatrix;
// Set the rest of the shader bindings
@@ -1373,9 +1503,6 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
linePos += lineStep;
}
}
-
- // Release line shader
- lineShader->release();
}
// Draw axis labels
@@ -1383,6 +1510,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_POLYGON_OFFSET_FILL);
// Z Labels
QVector3D positionZComp(0.0f, 0.0f, 0.0f);
@@ -1415,9 +1543,9 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
for (int segment = 0; segment <= lastSegment; segment++) {
if (m_axisCacheZ.labelItems().size() > labelNbr) {
- labelTrans.setZ(labelPos);
-
+ glPolygonOffset(GLfloat(segment) / -10.0f, 1.0f);
// Draw the label here
+ labelTrans.setZ(labelPos);
m_dummyRenderItem.setTranslation(labelTrans);
const LabelItem &axisLabelItem = *m_axisCacheZ.labelItems().at(labelNbr);
@@ -1461,6 +1589,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
for (int segment = 0; segment <= lastSegment; segment++) {
if (m_axisCacheX.labelItems().size() > labelNbr) {
+ glPolygonOffset(GLfloat(segment) / -10.0f, 1.0f);
// Draw the label here
labelTrans.setX(labelPos);
m_dummyRenderItem.setTranslation(labelTrans);
@@ -1521,6 +1650,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
if (m_axisCacheY.labelItems().size() > labelNbr) {
const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(labelNbr);
+ glPolygonOffset(GLfloat(segment) / -10.0f, 1.0f);
+
// Back wall
labelTransBack.setY(labelPos);
m_dummyRenderItem.setTranslation(labelTransBack);
@@ -1541,65 +1672,40 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
labelPos += posStep;
}
}
+ glDisable(GL_POLYGON_OFFSET_FILL);
glDisable(GL_TEXTURE_2D);
-
glDisable(GL_BLEND);
- // Release label shader
- m_labelShader->release();
+ // Release shader
+ glUseProgram(0);
// Selection handling
- if (m_selectionModeChanged || selectionDirty) {
- if (selectionDirty)
- m_cachedSelectionId = selectionId;
- if (m_cachedSelectionMode == QDataVis::SelectionModeNone) {
- m_cachedSelectionId = 0;
- m_selectionActive = false;
- }
- if (m_cachedSelectionMode == QDataVis::SelectionModeItem) {
- if (m_cachedSelectionId)
- surfacePointSelected(m_cachedSelectionId);
- else
- m_selectionActive = false;
- }
- if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow
- || m_cachedSelectionMode == QDataVis::SelectionModeSliceColumn) {
- if (m_cachedSelectionId) {
- updateSliceDataModel(m_cachedSelectionId);
- m_cachedScene->setSlicingActive(true);
-
- surfacePointSelected(m_cachedSelectionId);
-
- emit needRender();
+ if (m_selectionDirty) {
+ QPoint visiblePoint = Surface3DController::invalidSelectionPosition();
+ if (m_selectedPoint != Surface3DController::invalidSelectionPosition()) {
+ int x = m_selectedPoint.x() - m_sampleSpace.y();
+ int y = m_selectedPoint.y() - m_sampleSpace.x();
+ if (x >= 0 && y >= 0 && x < m_sampleSpace.height() && y < m_sampleSpace.width()
+ && m_dataArray.size()) {
+ visiblePoint = QPoint(x, y);
}
}
- m_selectionModeChanged = false;
- }
- if (m_controller->inputState() == QDataVis::InputStateOnOverview) {
- if (m_cachedIsSlicingActivated) {
- m_cachedScene->setSlicingActive(false);
+ if (m_cachedSelectionMode == QDataVis::SelectionNone
+ || visiblePoint == Surface3DController::invalidSelectionPosition()) {
m_selectionActive = false;
- m_cachedSelectionId = 0;
+ } else {
+ // TODO: Need separate selection ball for slice and main surface view QTRD-2515
+ if (m_cachedIsSlicingActivated)
+ updateSliceDataModel(visiblePoint);
+ if (m_cachedSelectionMode.testFlag(QDataVis::SelectionItem))
+ surfacePointSelected(visiblePoint);
+ m_selectionActive = true;
}
- }
-}
-void Surface3DRenderer::updateSurfaceGradient(const QLinearGradient &gradient)
-{
- QImage image(QSize(2, 1024), QImage::Format_RGB32);
- QPainter pmp(&image);
- pmp.setBrush(QBrush(gradient));
- pmp.setPen(Qt::NoPen);
- pmp.drawRect(0, 0, 2, 1024);
-
- if (m_gradientTexture) {
- m_textureHelper->deleteTexture(&m_gradientTexture);
- m_gradientTexture = 0;
+ m_selectionDirty = false;
}
-
- m_gradientTexture = m_textureHelper->create2DTexture(image, false, true);
}
// This one needs to be called when the data size changes
@@ -1656,7 +1762,7 @@ void Surface3DRenderer::initSelectionBuffer()
m_selectionResultTexture = 0;
}
- m_selectionResultTexture = m_textureHelper->createSelectionTexture(m_mainViewPort.size(),
+ m_selectionResultTexture = m_textureHelper->createSelectionTexture(m_primarySubViewport.size(),
m_selectionFrameBuffer,
m_selectionDepthBuffer);
}
@@ -1689,11 +1795,6 @@ void Surface3DRenderer::idToRGBA(uint id, uchar *r, uchar *g, uchar *b, uchar *a
*a = (id >> 24) & ID_TO_RGBA_MASK;
}
-void Surface3DRenderer::updateTextures()
-{
- updateSurfaceGradient(m_cachedTheme.m_surfaceGradient);
-}
-
void Surface3DRenderer::calculateSceneScalingFactors()
{
// Calculate scene scaling and translation factors
@@ -1714,24 +1815,24 @@ void Surface3DRenderer::calculateSceneScalingFactors()
#endif
}
-bool Surface3DRenderer::updateSmoothStatus(bool enable)
+bool Surface3DRenderer::updateFlatStatus(bool enable)
{
- if (!enable && !m_flatSupported) {
+ if (enable && !m_flatSupported) {
qWarning() << "Warning: Flat qualifier not supported on your platform's GLSL language."
" Requires at least GLSL version 1.2 with GL_EXT_gpu_shader4 extension.";
- enable = true;
+ enable = false;
}
bool changed = false;
- if (enable != m_cachedSmoothSurface) {
- m_cachedSmoothSurface = enable;
+ if (enable != m_cachedFlatShading) {
+ m_cachedFlatShading = enable;
changed = true;
initSurfaceShaders();
}
// If no surface object created yet, don't try to update the object
if (m_surfaceObj && changed && m_sampleSpace.width() >= 2 && m_sampleSpace.height() >= 2) {
- if (m_cachedSmoothSurface) {
+ if (!m_cachedFlatShading) {
m_surfaceObj->setUpSmoothData(m_dataArray, m_sampleSpace, m_heightNormalizer,
m_axisCacheY.min(), true);
} else {
@@ -1740,15 +1841,14 @@ bool Surface3DRenderer::updateSmoothStatus(bool enable)
}
}
- return m_cachedSmoothSurface;
+ return m_cachedFlatShading;
}
-void Surface3DRenderer::updateSelectionMode(QDataVis::SelectionMode mode)
+void Surface3DRenderer::updateSelectedPoint(const QPoint &position, const QSurface3DSeries *series)
{
- if (mode != m_cachedSelectionMode)
- m_selectionModeChanged = true;
-
- Abstract3DRenderer::updateSelectionMode(mode);
+ m_selectedPoint = position;
+ m_selectedSeries = series;
+ m_selectionDirty = true;
}
void Surface3DRenderer::updateSurfaceGridStatus(bool enable)
@@ -1782,65 +1882,63 @@ void Surface3DRenderer::loadGridLineMesh()
{
if (m_gridLineObj)
delete m_gridLineObj;
- m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/bar"));
+ m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/plane"));
m_gridLineObj->load();
}
-void Surface3DRenderer::handleResize()
+void Surface3DRenderer::surfacePointSelected(const QPoint &point)
{
- if (m_cachedBoundingRect.width() == 0 || m_cachedBoundingRect.height() == 0)
- return;
+ int row = point.x();
+ int column = point.y();
- setViewPorts();
-
- Abstract3DRenderer::handleResize();
-}
-
-void Surface3DRenderer::surfacePointSelected(int id)
-{
- int column = (id - 1) % m_sampleSpace.width();
- int row = (id - 1) / m_sampleSpace.width();
-
- if (row < 0 || column < 0 || m_dataArray.size() < row || m_dataArray.at(row)->size() < column)
- return;
-
- qreal value = qreal(m_dataArray.at(row)->at(column).y());
+ float value = m_dataArray.at(row)->at(column).y();
if (!m_selectionPointer)
m_selectionPointer = new SelectionPointer(m_drawer);
QVector3D pos;
- if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow) {
- pos = m_sliceSurfaceObj->vertexAt(column, 0);
- pos *= QVector3D(m_surfaceScaleX, 1.0f, 0.0f);
- pos += QVector3D(m_surfaceOffsetX, 0.0f, 0.0f);
- m_selectionPointer->updateBoundingRect(m_sliceViewPort);
- m_selectionPointer->updateSliceData(true, m_autoScaleAdjustment);
- } else if (m_cachedSelectionMode == QDataVis::SelectionModeSliceColumn) {
- pos = m_sliceSurfaceObj->vertexAt(row, 0);
- pos *= QVector3D(m_surfaceScaleZ, 1.0f, 0.0f);
- pos += QVector3D(-m_surfaceOffsetZ, 0.0f, 0.0f);
- m_selectionPointer->updateBoundingRect(m_sliceViewPort);
- m_selectionPointer->updateSliceData(true, m_autoScaleAdjustment);
+ if (m_cachedIsSlicingActivated) {
+ if (m_cachedSelectionMode.testFlag(QDataVis::SelectionRow)) {
+ pos = m_sliceSurfaceObj->vertexAt(column, 0);
+ pos *= QVector3D(m_surfaceScaleX, 1.0f, 0.0f);
+ pos += QVector3D(m_surfaceOffsetX, 0.0f, 0.0f);
+ m_selectionPointer->updateBoundingRect(m_secondarySubViewport);
+ m_selectionPointer->updateSliceData(true, m_autoScaleAdjustment);
+ } else if (m_cachedSelectionMode.testFlag(QDataVis::SelectionColumn)) {
+ pos = m_sliceSurfaceObj->vertexAt(row, 0);
+ pos *= QVector3D(m_surfaceScaleZ, 1.0f, 0.0f);
+ pos += QVector3D(-m_surfaceOffsetZ, 0.0f, 0.0f);
+ m_selectionPointer->updateBoundingRect(m_secondarySubViewport);
+ m_selectionPointer->updateSliceData(true, m_autoScaleAdjustment);
+ }
} else {
pos = m_surfaceObj->vertexAt(column, row);
pos *= QVector3D(m_surfaceScaleX, 1.0f, m_surfaceScaleZ);;
pos += QVector3D(m_surfaceOffsetX, 0.0f, m_surfaceOffsetZ);
- m_selectionPointer->updateBoundingRect(m_mainViewPort);
+ m_selectionPointer->updateBoundingRect(m_primarySubViewport);
m_selectionPointer->updateSliceData(false, m_autoScaleAdjustment);
}
m_selectionPointer->setPosition(pos);
m_selectionPointer->setLabel(createSelectionLabel(value, column, row));
+ // TODO: Get pointer object from correct series once multiseries support implemented
+ m_selectionPointer->setPointerObject(m_visibleSeriesList.at(0).object());
+ m_selectionPointer->setHighlightColor(m_visibleSeriesList.at(0).singleHighlightColor());
m_selectionPointer->updateScene(m_cachedScene);
+}
- //Put the selection pointer flag active
- m_selectionActive = true;
+// Maps selection Id to surface point in data array
+QPoint Surface3DRenderer::selectionIdToSurfacePoint(uint id)
+{
+ int column = ((id - 1) % m_sampleSpace.width()) + m_sampleSpace.x();
+ int row = ((id - 1) / m_sampleSpace.width()) + m_sampleSpace.y();
+ return QPoint(row, column);
}
-QString Surface3DRenderer::createSelectionLabel(qreal value, int column, int row)
+QString Surface3DRenderer::createSelectionLabel(float value, int column, int row)
{
- QString labelText = itemLabelFormat();
+ // TODO: Get from correct series once multiple series supported
+ QString labelText = m_visibleSeriesList[0].itemLabelFormat();
static const QString xTitleTag(QStringLiteral("@xTitle"));
static const QString yTitleTag(QStringLiteral("@yTitle"));
static const QString zTitleTag(QStringLiteral("@zTitle"));
@@ -1879,16 +1977,10 @@ QString Surface3DRenderer::createSelectionLabel(qreal value, int column, int row
return labelText;
}
-void Surface3DRenderer::loadMeshFile()
-{
- // Do nothing, not yet supported by this renderer
- // TODO: To be used for overriding the selection ball mesh after technology preview
-}
-
void Surface3DRenderer::updateShadowQuality(QDataVis::ShadowQuality quality)
{
- qWarning() << "Shadows have been disabled for Q3DSurface in technology preview";
- m_cachedShadowQuality = QDataVis::ShadowQualityNone; //quality;
+ m_cachedShadowQuality = quality;
+
switch (quality) {
case QDataVis::ShadowQualityLow:
m_shadowQualityToShader = 33.3f;
@@ -1920,11 +2012,18 @@ void Surface3DRenderer::updateShadowQuality(QDataVis::ShadowQuality quality)
break;
}
+ handleShadowQualityChange();
+
#if !defined(QT_OPENGL_ES_2)
updateDepthBuffer();
#endif
}
+void Surface3DRenderer::updateTextures()
+{
+ // Do nothing, but required as it is pure virtual on parent
+}
+
void Surface3DRenderer::updateSlicingActive(bool isSlicing)
{
if (m_cachedIsSlicingActivated == isSlicing)
@@ -1932,50 +2031,58 @@ void Surface3DRenderer::updateSlicingActive(bool isSlicing)
m_cachedIsSlicingActivated = isSlicing;
- setViewPorts();
-
if (!m_cachedIsSlicingActivated)
initSelectionBuffer(); // We need to re-init selection buffer in case there has been a resize
#if !defined(QT_OPENGL_ES_2)
updateDepthBuffer(); // Re-init depth buffer as well
#endif
-}
-void Surface3DRenderer::setViewPorts()
-{
- // Update view ports
- if (m_cachedIsSlicingActivated) {
- m_mainViewPort = QRect(0,
- m_cachedBoundingRect.height()
- - (m_cachedBoundingRect.height() / subViewDivider),
- m_cachedBoundingRect.width() / subViewDivider,
- m_cachedBoundingRect.height() / subViewDivider);
- m_sliceViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height());
- if (m_selectionPointer)
- m_selectionPointer->updateBoundingRect(m_sliceViewPort);
- } else {
- m_mainViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height());
- m_sliceViewPort = QRect(0, 0, 0, 0);
- if (m_selectionPointer)
- m_selectionPointer->updateBoundingRect(m_mainViewPort);
- }
+ m_selectionDirty = true;
}
void Surface3DRenderer::loadLabelMesh()
{
if (m_labelObj)
delete m_labelObj;
- m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/label"));
+ m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/plane"));
m_labelObj->load();
}
void Surface3DRenderer::initShaders(const QString &vertexShader, const QString &fragmentShader)
{
+ // m_shader is used slice view surface only.
if (m_shader)
delete m_shader;
m_shader = new ShaderHelper(this, vertexShader, fragmentShader);
m_shader->initialize();
+
+ // draw the shader for the surface according to smooth status, shadow and uniform color
+ if (m_surfaceShader)
+ delete m_surfaceShader;
+#if !defined(QT_OPENGL_ES_2)
+ if (!m_cachedFlatShading) {
+ if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
+ m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexShadow"),
+ QStringLiteral(":/shaders/fragmentSurfaceShadowNoTex"));
+ } else {
+ m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragmentSurface"));
+ }
+ } else {
+ if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
+ m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceShadowFlat"),
+ QStringLiteral(":/shaders/fragmentSurfaceShadowFlat"));
+ } else {
+ m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
+ QStringLiteral(":/shaders/fragmentSurfaceFlat"));
+ }
+ }
+#else
+ m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragmentSurfaceES2"));
+#endif
+ m_surfaceShader->initialize();
}
void Surface3DRenderer::initBackgroundShaders(const QString &vertexShader,
@@ -1998,30 +2105,15 @@ void Surface3DRenderer::initSelectionShaders()
void Surface3DRenderer::initSurfaceShaders()
{
- if (m_surfaceShader)
- delete m_surfaceShader;
-
-#if !defined(QT_OPENGL_ES_2)
- if (m_cachedSmoothSurface) {
- m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurface"),
- QStringLiteral(":/shaders/fragmentSurface"));
- } else {
- m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
- QStringLiteral(":/shaders/fragmentSurfaceFlat"));
- }
-#else
- m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurface"),
- QStringLiteral(":/shaders/fragmentSurfaceES2"));
-#endif
- m_surfaceShader->initialize();
-
+ // Gridline shader
if (m_surfaceGridShader)
delete m_surfaceGridShader;
-
- m_surfaceGridShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceGrid"),
- QStringLiteral(":/shaders/fragmentSurfaceGrid"));
-
+ m_surfaceGridShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexPlainColor"),
+ QStringLiteral(":/shaders/fragmentPlainColor"));
m_surfaceGridShader->initialize();
+
+ // Triggers surface shader selection by shadow setting
+ handleShadowQualityChange();
}
void Surface3DRenderer::initLabelShaders(const QString &vertexShader, const QString &fragmentShader)
@@ -2035,7 +2127,6 @@ void Surface3DRenderer::initLabelShaders(const QString &vertexShader, const QStr
#if !defined(QT_OPENGL_ES_2)
void Surface3DRenderer::initDepthShader()
{
- // TODO: Implement a depth shader for surface after technology preview
if (m_depthShader)
delete m_depthShader;
m_depthShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexDepth"),
@@ -2050,52 +2141,33 @@ void Surface3DRenderer::updateDepthBuffer()
m_depthTexture = 0;
}
- if (m_mainViewPort.size().isEmpty())
+ if (m_primarySubViewport.size().isEmpty())
return;
if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
- m_depthTexture = m_textureHelper->createDepthTexture(m_mainViewPort.size(),
- m_depthFrameBuffer,
- m_shadowQualityMultiplier);
- if (!m_depthTexture) {
- switch (m_cachedShadowQuality) {
- case QDataVis::ShadowQualityHigh:
- qWarning("Creating high quality shadows failed. Changing to medium quality.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualityMedium);
- updateShadowQuality(QDataVis::ShadowQualityMedium);
- break;
- case QDataVis::ShadowQualityMedium:
- qWarning("Creating medium quality shadows failed. Changing to low quality.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualityLow);
- updateShadowQuality(QDataVis::ShadowQualityLow);
- break;
- case QDataVis::ShadowQualityLow:
- qWarning("Creating low quality shadows failed. Switching shadows off.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualityNone);
- updateShadowQuality(QDataVis::ShadowQualityNone);
- break;
- case QDataVis::ShadowQualitySoftHigh:
- qWarning("Creating soft high quality shadows failed. Changing to soft medium quality.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualitySoftMedium);
- updateShadowQuality(QDataVis::ShadowQualitySoftMedium);
- break;
- case QDataVis::ShadowQualitySoftMedium:
- qWarning("Creating soft medium quality shadows failed. Changing to soft low quality.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualitySoftLow);
- updateShadowQuality(QDataVis::ShadowQualitySoftLow);
- break;
- case QDataVis::ShadowQualitySoftLow:
- qWarning("Creating soft low quality shadows failed. Switching shadows off.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualityNone);
- updateShadowQuality(QDataVis::ShadowQualityNone);
- break;
- default:
- // You'll never get here
- break;
- }
- }
+ m_depthTexture = m_textureHelper->createDepthTextureFrameBuffer(m_primarySubViewport.size(),
+ m_depthFrameBuffer,
+ m_shadowQualityMultiplier);
+ m_textureHelper->fillDepthTexture(m_depthTexture, m_primarySubViewport.size(), m_shadowQualityMultiplier, 1.0f);
+ m_depthModelTexture = m_textureHelper->createDepthTexture(m_primarySubViewport.size(),
+ m_shadowQualityMultiplier);
+ if (!m_depthTexture || !m_depthModelTexture)
+ lowerShadowQuality();
}
}
#endif
+void Surface3DRenderer::generateUniformGradient(const QVector3D newColor)
+{
+ if (m_visibleSeriesList.size()) {
+ // TODO: move uniform gradient to render cache when multiseries support implemented QTRD-2657
+ QColor newQColor = Utils::colorFromVector(newColor);
+ m_uniformGradientTextureColor = newColor;
+ QLinearGradient newGradient;
+ newGradient.setColorAt(0.0, newQColor);
+ newGradient.setColorAt(1.0, newQColor);
+ fixGradientAndGenerateTexture(&newGradient, &m_uniformGradientTexture);
+ }
+}
+
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/surface3drenderer_p.h b/src/datavisualization/engine/surface3drenderer_p.h
index c805e508..f70fde9b 100644
--- a/src/datavisualization/engine/surface3drenderer_p.h
+++ b/src/datavisualization/engine/surface3drenderer_p.h
@@ -33,7 +33,6 @@
#include <QtCore/QObject>
#include <QtGui/QOpenGLFunctions>
#include <QtGui/QFont>
-#include <QLinearGradient>
#include <QWindow>
#include "datavisualizationglobal_p.h"
@@ -60,11 +59,9 @@ class QT_DATAVISUALIZATION_EXPORT Surface3DRenderer : public Abstract3DRenderer
Q_OBJECT
public:
- Surface3DController *m_controller;
-
// Visual parameters
QRect m_boundingRect;
- QDataVis::LabelStyle m_labelStyle;
+ bool m_labelBackground;
QFont m_font;
bool m_isGridEnabled;
@@ -72,8 +69,6 @@ private:
bool m_cachedIsSlicingActivated;
// Internal attributes purely related to how the scene is drawn with GL.
- QRect m_mainViewPort;
- QRect m_sliceViewPort;
ShaderHelper *m_shader;
ShaderHelper *m_depthShader;
ShaderHelper *m_backgroundShader;
@@ -103,15 +98,16 @@ private:
SurfaceObject *m_surfaceObj;
SurfaceObject *m_sliceSurfaceObj;
GLuint m_depthTexture;
+ GLuint m_depthModelTexture;
GLuint m_depthFrameBuffer;
GLuint m_selectionFrameBuffer;
GLuint m_selectionDepthBuffer;
- GLuint m_gradientTexture;
GLuint m_selectionTexture;
GLuint m_selectionResultTexture;
GLfloat m_shadowQualityToShader;
- bool m_cachedSmoothSurface;
+ bool m_cachedFlatShading;
bool m_flatSupported;
+ bool m_cachedSurfaceVisible;
bool m_cachedSurfaceGridOn;
SelectionPointer *m_selectionPointer;
bool m_selectionActive;
@@ -124,36 +120,42 @@ private:
QRect m_sampleSpace;
GLint m_shadowQualityMultiplier;
QSizeF m_areaSize;
- uint m_cachedSelectionId;
- bool m_selectionModeChanged;
+ uint m_clickedPointId;
bool m_hasHeightAdjustmentChanged;
+ QPoint m_selectedPoint;
+ const QSurface3DSeries *m_selectedSeries;
+ GLuint m_uniformGradientTexture;
+ QVector3D m_uniformGradientTextureColor;
public:
explicit Surface3DRenderer(Surface3DController *controller);
~Surface3DRenderer();
- void updateDataModel(QSurfaceDataProxy *dataProxy);
+ void updateData();
+ void updateSeries(const QList<QAbstract3DSeries *> &seriesList, bool updateVisibility);
+ void updateRows(const QVector<int> &rows);
+ void updateItem(const QVector<QPoint> &points);
void updateScene(Q3DScene *scene);
+ bool updateFlatStatus(bool enable);
+ void updateSurfaceGridStatus(bool enable);
+ void updateSlicingActive(bool isSlicing);
+ void updateSelectedPoint(const QPoint &position, const QSurface3DSeries *series);
+
void drawSlicedScene();
void render(GLuint defaultFboHandle = 0);
protected:
void initializeOpenGL();
- virtual void loadMeshFile();
-public slots:
- bool updateSmoothStatus(bool enable);
- void updateSurfaceGridStatus(bool enable);
- void updateSurfaceGradient(const QLinearGradient &gradient);
- void updateSlicingActive(bool isSlicing);
- void updateSelectionMode(QDataVis::SelectionMode mode);
+signals:
+ void pointClicked(QPoint position, QSurface3DSeries *series);
+ void flatShadingSupportedChanged(bool supported);
private:
- void setViewPorts();
- void updateSliceDataModel(int selectionId);
- virtual void updateShadowQuality(QDataVis::ShadowQuality quality);
- virtual void updateTextures();
- virtual void initShaders(const QString &vertexShader, const QString &fragmentShader);
+ void updateSliceDataModel(const QPoint &point);
+ void updateShadowQuality(QDataVis::ShadowQuality quality);
+ void updateTextures();
+ void initShaders(const QString &vertexShader, const QString &fragmentShader);
QRect calculateSampleRect(const QSurfaceDataArray &array);
void loadBackgroundMesh();
void loadGridLineMesh();
@@ -161,7 +163,6 @@ private:
void loadSurfaceObj();
void loadSliceSurfaceObj();
void drawScene(GLuint defaultFboHandle);
- void handleResize();
void calculateSceneScalingFactors();
void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader);
void initLabelShaders(const QString &vertexShader, const QString &fragmentShader);
@@ -172,11 +173,14 @@ private:
void updateSelectionTexture();
void idToRGBA(uint id, uchar *r, uchar *g, uchar *b, uchar *a);
void fillIdCorner(uchar *p, uchar r, uchar g, uchar b, uchar a, int stride);
- void surfacePointSelected(int id);
- QString createSelectionLabel(qreal value, int column, int row);
+ void surfacePointSelected(const QPoint &point);
+ QPoint selectionIdToSurfacePoint(uint id);
+ QString createSelectionLabel(float value, int column, int row);
#if !defined(QT_OPENGL_ES_2)
void updateDepthBuffer();
#endif
+ void emitSelectedPointChanged(QPoint position);
+ void generateUniformGradient(const QVector3D newColor);
Q_DISABLE_COPY(Surface3DRenderer)
};
diff --git a/src/datavisualization/engine/theme.cpp b/src/datavisualization/engine/theme.cpp
deleted file mode 100644
index 387540b1..00000000
--- a/src/datavisualization/engine/theme.cpp
+++ /dev/null
@@ -1,250 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use contact form at http://qt.digia.com
-**
-** This file is part of the QtDataVisualization module.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** contact form at http://qt.digia.com
-**
-****************************************************************************/
-
-#include "theme_p.h"
-
-#ifdef Q_OS_WIN
-#include <windows.h>
-#include <stdio.h>
-#endif
-
-QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-
-Theme::Theme()
- : m_baseColor(QColor(Qt::gray)),
- m_heightColor(QColor(Qt::black)),
- m_depthColor(QColor(Qt::black)),
- m_backgroundColor(QColor(Qt::gray)),
- m_windowColor(QColor(Qt::gray)),
- m_textColor(QColor(Qt::white)),
- m_textBackgroundColor(QColor(0x00, 0x00, 0x00, 0xa0)),
- m_gridLine(QColor(Qt::black)),
- m_highlightBarColor(QColor(Qt::red)),
- m_highlightRowColor(QColor(Qt::darkRed)),
- m_highlightColumnColor(QColor(Qt::darkMagenta)),
- m_surfaceGradient(QLinearGradient(2, 1024, 0, 0)),
- m_lightStrength(4.0f),
- m_ambientStrength(0.3f),
- m_highlightLightStrength(8.0f),
- m_uniformColor(true),
- m_labelBorders(false)
-{
- // Default values for surface gradient
-}
-
-Theme::~Theme()
-{
-}
-
-QDataVis::Theme Theme::theme()
-{
- return m_theme;
-}
-
-void Theme::useTheme(QDataVis::Theme theme)
-{
- m_theme = theme;
- switch (theme) {
- case QDataVis::ThemeQt: {
- m_baseColor = QColor(QRgb(0x80c342));
- //m_heightColor = QColor(QRgb(0x));
- //m_depthColor = QColor(QRgb(0x));
- m_backgroundColor = QColor(QRgb(0xffffff));
- m_windowColor = QColor(QRgb(0xffffff));
- m_textColor = QColor(QRgb(0x35322f));
- m_textBackgroundColor = QColor(0xff, 0xff, 0xff, 0x99);
- m_gridLine = QColor(QRgb(0xd7d6d5));
- m_highlightBarColor = QColor(QRgb(0x14aaff));
- m_highlightRowColor = QColor(QRgb(0x6400aa));
- m_highlightColumnColor = QColor(QRgb(0x6400aa));
- m_lightStrength = 5.0f;
- m_ambientStrength = 0.5f;
- m_highlightLightStrength = 5.0f;
- m_uniformColor = true;
- m_labelBorders = true;
- break;
- }
- case QDataVis::ThemePrimaryColors: {
- m_baseColor = QColor(QRgb(0xffe400));
- //m_heightColor = QColor(QRgb(0x));
- //m_depthColor = QColor(QRgb(0x));
- m_backgroundColor = QColor(QRgb(0xffffff));
- m_windowColor = QColor(QRgb(0xffffff));
- m_textColor = QColor(QRgb(0x000000));
- m_textBackgroundColor = QColor(0xff, 0xff, 0xff, 0x99);
- m_gridLine = QColor(QRgb(0xd7d6d5));
- m_highlightBarColor = QColor(QRgb(0x27beee));
- m_highlightRowColor = QColor(QRgb(0xee1414));
- m_highlightColumnColor = QColor(QRgb(0xee1414));
- m_lightStrength = 5.0f;
- m_ambientStrength = 0.5f;
- m_highlightLightStrength = 5.0f;
- m_uniformColor = true;
- m_labelBorders = false;
- break;
- }
- case QDataVis::ThemeDigia: {
- m_baseColor = QColor(QRgb(0xcccccc));
- //m_heightColor = QColor(QRgb(0x));
- //m_depthColor = QColor(QRgb(0x));
- m_backgroundColor = QColor(QRgb(0xffffff));
- m_windowColor = QColor(QRgb(0xffffff));
- m_textColor = QColor(QRgb(0x000000));
- m_textBackgroundColor = QColor(0xff, 0xff, 0xff, 0x80);
- m_gridLine = QColor(QRgb(0xd7d6d5));
- m_highlightBarColor = QColor(QRgb(0xfa0000));
- m_highlightRowColor = QColor(QRgb(0x555555));
- m_highlightColumnColor = QColor(QRgb(0x555555));
- m_lightStrength = 5.0f;
- m_ambientStrength = 0.5f;
- m_highlightLightStrength = 5.0f;
- m_uniformColor = false;
- m_labelBorders = false;
- break;
- }
- case QDataVis::ThemeStoneMoss: {
- m_baseColor = QColor(QRgb(0xbeb32b));
- //m_heightColor = QColor(QRgb(0x));
- //m_depthColor = QColor(QRgb(0x));
- m_backgroundColor = QColor(QRgb(0x4d4d4f));
- m_windowColor = QColor(QRgb(0x4d4d4f));
- m_textColor = QColor(QRgb(0xffffff));
- m_textBackgroundColor = QColor(0x4d, 0x4d, 0x4f, 0xcd);
- m_gridLine = QColor(QRgb(0x3e3e40));
- m_highlightBarColor = QColor(QRgb(0xfbf6d6));
- m_highlightRowColor = QColor(QRgb(0x442f20));
- m_highlightColumnColor = QColor(QRgb(0x442f20));
- m_lightStrength = 5.0f;
- m_ambientStrength = 0.5f;
- m_highlightLightStrength = 5.0f;
- m_uniformColor = true;
- m_labelBorders = true;
- break;
- }
- case QDataVis::ThemeArmyBlue: {
- m_baseColor = QColor(QRgb(0x495f76));
- //m_heightColor = QColor(QRgb(0x));
- //m_depthColor = QColor(QRgb(0x));
- m_backgroundColor = QColor(QRgb(0xd5d6d7));
- m_windowColor = QColor(QRgb(0xd5d6d7));
- m_textColor = QColor(QRgb(0x000000));
- m_textBackgroundColor = QColor(0xd5, 0xd6, 0xd7, 0xcd);
- m_gridLine = QColor(QRgb(0xaeadac));
- m_highlightBarColor = QColor(QRgb(0x2aa2f9));
- m_highlightRowColor = QColor(QRgb(0x103753));
- m_highlightColumnColor = QColor(QRgb(0x103753));
- m_lightStrength = 5.0f;
- m_ambientStrength = 0.5f;
- m_highlightLightStrength = 5.0f;
- m_uniformColor = false;
- m_labelBorders = false;
- break;
- }
- case QDataVis::ThemeRetro: {
- m_baseColor = QColor(QRgb(0x533b23));
- //m_heightColor = QColor(QRgb(0x));
- //m_depthColor = QColor(QRgb(0x));
- m_backgroundColor = QColor(QRgb(0xe9e2ce));
- m_windowColor = QColor(QRgb(0xe9e2ce));
- m_textColor = QColor(QRgb(0x000000));
- m_textBackgroundColor = QColor(0xe9, 0xe2, 0xce, 0xc0);
- m_gridLine = QColor(QRgb(0xd0c0b0));
- m_highlightBarColor = QColor(QRgb(0x8ea317));
- m_highlightRowColor = QColor(QRgb(0xc25708));
- m_highlightColumnColor = QColor(QRgb(0xc25708));
- m_lightStrength = 5.0f;
- m_ambientStrength = 0.5f;
- m_highlightLightStrength = 5.0f;
- m_uniformColor = false;
- m_labelBorders = false;
- break;
- }
- case QDataVis::ThemeEbony: {
- m_baseColor = QColor(QRgb(0xffffff));
- //m_heightColor = QColor(QRgb(0x));
- //m_depthColor = QColor(QRgb(0x));
- m_backgroundColor = QColor(QRgb(0x000000));
- m_windowColor = QColor(QRgb(0x000000));
- m_textColor = QColor(QRgb(0xaeadac));
- m_textBackgroundColor = QColor(0x00, 0x00, 0x00, 0xcd);
- m_gridLine = QColor(QRgb(0x35322f));
- m_highlightBarColor = QColor(QRgb(0xf5dc0d));
- m_highlightRowColor = QColor(QRgb(0xd72222));
- m_highlightColumnColor = QColor(QRgb(0xd72222));
- m_lightStrength = 5.0f;
- m_ambientStrength = 0.5f;
- m_highlightLightStrength = 5.0f;
- m_uniformColor = true;
- m_labelBorders = false;
- break;
- }
- case QDataVis::ThemeIsabelle: {
- m_baseColor = QColor(QRgb(0xf9d900));
- //m_heightColor = QColor(QRgb(0x));
- //m_depthColor = QColor(QRgb(0x));
- m_backgroundColor = QColor(QRgb(0x000000));
- m_windowColor = QColor(QRgb(0x000000));
- m_textColor = QColor(QRgb(0xaeadac));
- m_textBackgroundColor = QColor(0x00, 0x00, 0x00, 0xc0);
- m_gridLine = QColor(QRgb(0x35322f));
- m_highlightBarColor = QColor(QRgb(0xfff7cc));
- m_highlightRowColor = QColor(QRgb(0xde0a0a));
- m_highlightColumnColor = QColor(QRgb(0xde0a0a));
- m_lightStrength = 5.0f;
- m_ambientStrength = 0.5f;
- m_highlightLightStrength = 5.0f;
- m_uniformColor = true;
- m_labelBorders = false;
- break;
- }
- default:
- break;
- }
- if (m_uniformColor) {
- m_surfaceGradient.setColorAt(0.0, m_baseColor);
- } else {
- m_surfaceGradient.setColorAt(0.0, QColor(m_baseColor.redF() * 0.7,
- m_baseColor.greenF() * 0.7,
- m_baseColor.blueF() * 0.7));
- }
- m_surfaceGradient.setColorAt(1.0, m_baseColor);
-}
-
-void Theme::setFromTheme(Theme &theme)
-{
- m_theme = theme.m_theme;
- m_baseColor = theme.m_baseColor;
- m_heightColor = theme.m_heightColor;
- m_depthColor = theme.m_depthColor;
- m_backgroundColor = theme.m_backgroundColor;
- m_windowColor = theme.m_windowColor;
- m_textColor = theme.m_textColor;
- m_textBackgroundColor = theme.m_textBackgroundColor;
- m_gridLine = theme.m_gridLine;
- m_highlightBarColor = theme.m_highlightBarColor;
- m_highlightRowColor = theme.m_highlightRowColor;
- m_highlightColumnColor = theme.m_highlightColumnColor;
- m_surfaceGradient = theme.m_surfaceGradient;
- m_lightStrength = theme.m_lightStrength;
- m_ambientStrength = theme.m_ambientStrength;
- m_highlightLightStrength = theme.m_highlightLightStrength;
- m_uniformColor = theme.m_uniformColor;
- m_labelBorders = theme.m_labelBorders;
-}
-
-QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/theme_p.h b/src/datavisualization/engine/theme_p.h
deleted file mode 100644
index ec689f63..00000000
--- a/src/datavisualization/engine/theme_p.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use contact form at http://qt.digia.com
-**
-** This file is part of the QtDataVisualization module.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** contact form at http://qt.digia.com
-**
-****************************************************************************/
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the QtDataVisualization API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-
-#ifndef THEME_P_H
-#define THEME_P_H
-
-#include "datavisualizationglobal_p.h"
-#include "q3dbars.h"
-#include <QLinearGradient>
-
-class QColor;
-
-QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-
-class QT_DATAVISUALIZATION_EXPORT Theme
-{
-public:
- explicit Theme();
- ~Theme();
-
- void useTheme(QDataVis::Theme theme);
- QDataVis::Theme theme();
- void setFromTheme(Theme &theme);
-
-private:
- friend class Abstract3DController;
- friend class Abstract3DRenderer;
- friend class Bars3DRenderer;
- friend class Surface3DRenderer;
- friend class Surface3DController;
- friend class Scatter3DRenderer;
- friend class SelectionPointer;
- friend class Drawer;
-
- QDataVis::Theme m_theme;
- QColor m_baseColor;
- QColor m_heightColor;
- QColor m_depthColor;
- QColor m_backgroundColor;
- QColor m_windowColor;
- QColor m_textColor;
- QColor m_textBackgroundColor;
- QColor m_gridLine;
- QColor m_highlightBarColor;
- QColor m_highlightRowColor;
- QColor m_highlightColumnColor;
- QLinearGradient m_surfaceGradient;
- float m_lightStrength;
- float m_ambientStrength;
- float m_highlightLightStrength;
- bool m_uniformColor;
- bool m_labelBorders;
-};
-
-QT_DATAVISUALIZATION_END_NAMESPACE
-
-#endif
diff --git a/src/datavisualization/global/datavisualizationglobal_p.h b/src/datavisualization/global/datavisualizationglobal_p.h
index b37dbf91..86b454c9 100644
--- a/src/datavisualization/global/datavisualizationglobal_p.h
+++ b/src/datavisualization/global/datavisualizationglobal_p.h
@@ -39,16 +39,23 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
// Constants used in several files
// Distance from camera to origin
-const GLfloat cameraDistance = 6.0f;
+static const GLfloat cameraDistance = 6.0f;
// Size of font to be used in label texture rendering. Doesn't affect the actual font size.
-const int textureFontSize = 50;
-const GLfloat defaultRatio = 1.0f / 1.6f; // default aspect ratio 16:10
+static const int textureFontSize = 50;
+static const GLfloat defaultRatio = 1.0f / 1.6f; // default aspect ratio 16:10
+static const float gridLineOffset = 0.0001f; // Offset for lifting grid lines off background
// Default light position. To have shadows working correctly, light should be as far as camera, or a bit further
// y position is added to the minimum height (or can be thought to be that much above or below the camera)
-const QVector3D defaultLightPos(0.0f, 0.5f, 0.0f);
-const QVector3D zeroVector(0.0f, 0.0f, 0.0f);
-const QVector3D upVector(0.0f, 1.0f, 0.0f);
-const QVector3D cameraDistanceVector(0.0f, 0.0f, cameraDistance);
+static const QVector3D defaultLightPos(0.0f, 0.5f, 0.0f);
+static const QVector3D zeroVector(0.0f, 0.0f, 0.0f);
+static const QVector3D upVector(0.0f, 1.0f, 0.0f);
+static const QVector3D cameraDistanceVector(0.0f, 0.0f, cameraDistance);
+
+// Skip color == selection texture's background color
+static const QVector3D selectionSkipColor = QVector3D(255.0f, 255.0f, 255.0f);
+static const QVector3D invalidColorVector = QVector3D(-1.0f, -1.0f, -1.0f);
+static const GLfloat gradientTextureHeight = 1024.0f;
+static const GLfloat gradientTextureWidth = 2.0f;
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/global/qdatavisualizationenums.h b/src/datavisualization/global/qdatavisualizationenums.h
index 3d765ff2..fcbf63a9 100644
--- a/src/datavisualization/global/qdatavisualizationenums.h
+++ b/src/datavisualization/global/qdatavisualizationenums.h
@@ -28,82 +28,23 @@ namespace QtDataVisualization {
class QT_DATAVISUALIZATION_EXPORT QDataVis : public QObject
{
Q_OBJECT
- Q_ENUMS(MeshStyle)
- Q_ENUMS(CameraPreset)
- Q_ENUMS(Theme)
- Q_ENUMS(SelectionMode)
Q_ENUMS(ShadowQuality)
- Q_ENUMS(LabelStyle)
+ Q_FLAGS(SelectionFlag SelectionFlags)
public:
- enum InputState {
- InputStateNone = 0,
- InputStateOnScene,
- InputStateOnOverview,
- InputStateOnSlice,
- InputStateRotating,
- InputStateOnPinch
- };
-
- enum MeshStyle {
- MeshStyleBars = 0,
- MeshStylePyramids,
- MeshStyleCones,
- MeshStyleCylinders,
- MeshStyleBevelBars,
- MeshStyleSpheres,
- MeshStyleDots
- };
-
- enum CameraPreset {
- CameraPresetNone = -1,
- CameraPresetFrontLow = 0,
- CameraPresetFront,
- CameraPresetFrontHigh,
- CameraPresetLeftLow,
- CameraPresetLeft,
- CameraPresetLeftHigh,
- CameraPresetRightLow,
- CameraPresetRight,
- CameraPresetRightHigh,
- CameraPresetBehindLow,
- CameraPresetBehind,
- CameraPresetBehindHigh,
- CameraPresetIsometricLeft,
- CameraPresetIsometricLeftHigh,
- CameraPresetIsometricRight,
- CameraPresetIsometricRightHigh,
- CameraPresetDirectlyAbove,
- CameraPresetDirectlyAboveCW45,
- CameraPresetDirectlyAboveCCW45,
- CameraPresetFrontBelow,
- CameraPresetLeftBelow,
- CameraPresetRightBelow,
- CameraPresetBehindBelow,
- CameraPresetDirectlyBelow
- };
-
- enum Theme {
- ThemeDefault = -1,
- ThemeQt,
- ThemePrimaryColors,
- ThemeDigia,
- ThemeStoneMoss,
- ThemeArmyBlue,
- ThemeRetro,
- ThemeEbony,
- ThemeIsabelle
- };
-
- enum SelectionMode {
- SelectionModeNone = 0,
- SelectionModeItem,
- SelectionModeItemAndRow,
- SelectionModeItemAndColumn,
- SelectionModeItemRowAndColumn,
- SelectionModeSliceRow,
- SelectionModeSliceColumn
+ enum SelectionFlag {
+ SelectionNone = 0,
+ SelectionItem = 1,
+ SelectionRow = 2,
+ SelectionItemAndRow = SelectionItem | SelectionRow,
+ SelectionColumn = 4,
+ SelectionItemAndColumn = SelectionItem | SelectionColumn,
+ SelectionRowAndColumn = SelectionRow | SelectionColumn,
+ SelectionItemRowAndColumn = SelectionItem | SelectionRow | SelectionColumn,
+ SelectionSlice = 8,
+ SelectionMultiSeries = 16
};
+ Q_DECLARE_FLAGS(SelectionFlags, SelectionFlag)
enum ShadowQuality {
ShadowQualityNone = 0,
@@ -114,13 +55,9 @@ public:
ShadowQualitySoftMedium,
ShadowQualitySoftHigh
};
-
- enum LabelStyle {
- LabelStyleOpaque = 0,
- LabelStyleFromTheme,
- LabelStyleTransparent
- };
};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QDataVis::SelectionFlags)
}
#endif
diff --git a/src/datavisualization/global/qdatavisualizationglobal.h b/src/datavisualization/global/qdatavisualizationglobal.h
index eefa2888..1c118664 100644
--- a/src/datavisualization/global/qdatavisualizationglobal.h
+++ b/src/datavisualization/global/qdatavisualizationglobal.h
@@ -21,11 +21,11 @@
#include <qglobal.h>
-#define QT_DATAVISUALIZATION_VERSION_STR "0.1.0"
+#define QT_DATAVISUALIZATION_VERSION_STR "1.0.0"
/*
QT_DATAVISUALIZATION_VERSION is (major << 16) + (minor << 8) + patch.
*/
-#define QT_DATAVISUALIZATION_VERSION 0x000100
+#define QT_DATAVISUALIZATION_VERSION 0x010000
/*
can be used like #if (QT_DATAVISUALIZATION_VERSION >= QT_DATAVISUALIZATION_VERSION_CHECK(1, 0, 0))
*/
diff --git a/src/datavisualization/global/qtdatavisualizationenums.qdoc b/src/datavisualization/global/qtdatavisualizationenums.qdoc
index d448953d..f3fa406c 100644
--- a/src/datavisualization/global/qtdatavisualizationenums.qdoc
+++ b/src/datavisualization/global/qtdatavisualizationenums.qdoc
@@ -37,122 +37,35 @@
*/
/*!
- \enum QtDataVisualization::QDataVis::InputState
+ \enum QtDataVisualization::QDataVis::SelectionFlag
- Predefined input states for mouse and touch based input handlers. All states are not valid with all input handlers.
+ Item selection modes. Values of this enumeration can be combined with OR operator.
- \value InputStateNone
- Default "no input received" state.
- \value InputStateOnScene
- Mouse or touch input received on the 3D scene.
- \value InputStateOnOverview
- Mouse or touch input received on the overview area.
- \value InputStateOnSlice
- Mouse or touch input received on the slice view area.
- \value InputStateRotating
- Rotation of the 3D geometry ongoing.
- \value InputStateOnPinch
- Pinch/punch multitouch input received.
-*/
-
-/*!
- \enum QtDataVisualization::QDataVis::MeshStyle
-
- Predefined mesh types. All styles are not usable with all visualization types.
-
- \value MeshStyleBars
- Basic cubic bar.
- \value MeshStylePyramids
- Four-sided pyramid.
- \value MeshStyleCones
- Basic cone.
- \value MeshStyleCylinders
- Basic cylinder.
- \value MeshStyleBevelBars
- Slightly beveled (rounded) cubic bar.
- \value MeshStyleSpheres
- Sphere. Not usable in Q3DBars.
- \value MeshStyleDots
- Triangular pyramid. Usable only with Q3DScatter.
-*/
-
-/*!
- \enum QtDataVisualization::QDataVis::CameraPreset
-
- Predefined positions for camera.
-
- \value CameraPresetNone
- Used to indicate a preset has not been set, or the scene has been rotated freely.
- \value CameraPresetFrontLow
- \value CameraPresetFront
- \value CameraPresetFrontHigh
- \value CameraPresetLeftLow
- \value CameraPresetLeft
- \value CameraPresetLeftHigh
- \value CameraPresetRightLow
- \value CameraPresetRight
- \value CameraPresetRightHigh
- \value CameraPresetBehindLow
- \value CameraPresetBehind
- \value CameraPresetBehindHigh
- \value CameraPresetIsometricLeft
- \value CameraPresetIsometricLeftHigh
- \value CameraPresetIsometricRight
- \value CameraPresetIsometricRightHigh
- \value CameraPresetDirectlyAbove
- \value CameraPresetDirectlyAboveCW45
- \value CameraPresetDirectlyAboveCCW45
- \value CameraPresetFrontBelow
- In Q3DBars from CameraPresetFrontBelow onward these only work for graphs including negative
- values. They act as Preset...Low for positive-only values.
- \value CameraPresetLeftBelow
- \value CameraPresetRightBelow
- \value CameraPresetBehindBelow
- \value CameraPresetDirectlyBelow
- Acts as CameraPresetFrontLow for positive -only bars.
-*/
-
-/*!
- \enum QtDataVisualization::QDataVis::Theme
-
- Predefined themes.
-
- \value ThemeDefault
- Used only in QML to indicate a theme has not been set.
- \value ThemeQt
- \value ThemePrimaryColors
- \value ThemeDigia
- \value ThemeStoneMoss
- \value ThemeArmyBlue
- \value ThemeRetro
- \value ThemeEbony
- \value ThemeIsabelle
-*/
-
-/*!
- \enum QtDataVisualization::QDataVis::SelectionMode
-
- Item selection modes.
-
- \value SelectionModeNone
+ \value SelectionNone
Selection mode disabled.
- \value SelectionModeItem
- Selection selects a single item.
- \value SelectionModeItemAndRow
- Selection selects a single item and highlights the row it is on. In Q3DBars only.
- \value SelectionModeItemAndColumn
- Selection selects a single item and highlights the column it is on. In Q3DBars only.
- \value SelectionModeItemRowAndColumn
- Selection selects a single item and highlights the row and the column it is on. In
- Q3DBars only.
- \value SelectionModeSliceRow
- Selection selects a single item and displays the row it is on in a separate view. The
- original view is shrunk into upper left corner. Original view is restored by clicking
- on it. In Q3DBars only.
- \value SelectionModeSliceColumn
- Selection selects a single item and displays the column it is on in a separate view. The
- original view is shrunk into upper left corner. Original view is restored by clicking
- on it. In Q3DBars only.
+ \value SelectionItem
+ Selection highlights a single item.
+ \value SelectionRow
+ Selection highlights a single row.
+ \value SelectionItemAndRow
+ Combination flag for highlighting both item and row with different colors.
+ \value SelectionColumn
+ Selection highlights a single column.
+ \value SelectionItemAndColumn
+ Combination flag for highlighting both item and column with different colors.
+ \value SelectionRowAndColumn
+ Combination flag for highlighting both row and column.
+ \value SelectionItemRowAndColumn
+ Combination flag for highlighting item, row, and column.
+ \value SelectionSlice
+ Setting this mode flag indicates that the graph should take care of the slice view handling
+ automatically. If you wish to control the slice view yourself via Q3DScene, do not set this
+ flag. When setting this mode flag, either \c SelectionRow or \c SelectionColumn must also
+ be set, but not both. Slicing is supported by Q3DBars and Q3DSurface only.
+ \value SelectionMultiSeries
+ Setting this mode means that items for all series at same position are highlighted, instead
+ of just the selected item. The actual selection in the other series doesn't change.
+ Multi-series selection is only supported for Q3DBars.
*/
/*!
@@ -175,16 +88,3 @@
\value ShadowQualitySoftHigh
Shadows are rendered in high quality with softened edges.
*/
-
-/*!
- \enum QtDataVisualization::QDataVis::LabelStyle
-
- Label styles.
-
- \value LabelStyleOpaque
- Fully opaque background, using colors and borders from theme.
- \value LabelStyleFromTheme
- Use transparencies, colors and borders from theme.
- \value LabelStyleTransparent
- Fully transparent background, using text color from theme.
-*/
diff --git a/src/datavisualization/input/q3dinputhandler.cpp b/src/datavisualization/input/q3dinputhandler.cpp
index 357c97d3..5d730c47 100644
--- a/src/datavisualization/input/q3dinputhandler.cpp
+++ b/src/datavisualization/input/q3dinputhandler.cpp
@@ -91,16 +91,17 @@ void Q3DInputHandler::mousePressEvent(QMouseEvent *event, const QPoint &mousePos
if (Qt::LeftButton == event->button()) {
if (scene()->isSlicingActive()) {
if (scene()->isPointInPrimarySubView(mousePos)) {
- setInputState(QDataVis::InputStateOnOverview);
+ setInputState(InputStateOnPrimaryView);
} else if (scene()->isPointInSecondarySubView(mousePos)) {
- setInputState(QDataVis::InputStateOnSlice);
+ setInputState(InputStateOnSecondaryView);
} else {
- setInputState(QDataVis::InputStateNone);
+ setInputState(InputStateNone);
}
} else {
- setInputState(QDataVis::InputStateOnScene);
+ setInputState(InputStateOnScene);
// update mouse positions to prevent jumping when releasing or repressing a button
setInputPosition(mousePos);
+ scene()->setSelectionQueryPosition(mousePos);
}
} else if (Qt::MiddleButton == event->button()) {
// reset rotations
@@ -108,7 +109,7 @@ void Q3DInputHandler::mousePressEvent(QMouseEvent *event, const QPoint &mousePos
} else if (Qt::RightButton == event->button()) {
// disable rotating when in slice view
if (!scene()->isSlicingActive())
- setInputState(QDataVis::InputStateRotating);
+ setInputState(InputStateRotating);
// update mouse positions to prevent jumping when releasing or repressing a button
setInputPosition(mousePos);
}
@@ -125,11 +126,11 @@ void Q3DInputHandler::mouseReleaseEvent(QMouseEvent *event, const QPoint &mouseP
#if defined (Q_OS_ANDROID)
Q_UNUSED(mousePos);
#else
- if (QDataVis::InputStateRotating == inputState()) {
+ if (InputStateRotating == inputState()) {
// update mouse positions to prevent jumping when releasing or repressing a button
setInputPosition(mousePos);
}
- setInputState(QDataVis::InputStateNone);
+ setInputState(InputStateNone);
#endif
}
@@ -143,10 +144,10 @@ void Q3DInputHandler::mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos)
#if defined (Q_OS_ANDROID)
Q_UNUSED(mousePos);
#else
- if (QDataVis::InputStateRotating == inputState()) {
+ if (InputStateRotating == inputState()) {
// Calculate mouse movement since last frame
- qreal xRotation = scene()->activeCamera()->xRotation();
- qreal yRotation = scene()->activeCamera()->yRotation();
+ float xRotation = scene()->activeCamera()->xRotation();
+ float yRotation = scene()->activeCamera()->yRotation();
float mouseMoveX = float(inputPosition().x() - mousePos.x())
/ (scene()->viewport().width() / rotationSpeed);
float mouseMoveY = float(inputPosition().y() - mousePos.y())
@@ -156,7 +157,6 @@ void Q3DInputHandler::mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos)
yRotation -= mouseMoveY;
scene()->activeCamera()->setXRotation(xRotation);
scene()->activeCamera()->setYRotation(yRotation);
- scene()->activeCamera()->d_ptr->updateViewMatrix(1.0f);
setPreviousInputPos(inputPosition());
setInputPosition(mousePos);
diff --git a/src/datavisualization/input/qabstract3dinputhandler.cpp b/src/datavisualization/input/qabstract3dinputhandler.cpp
index b84711a4..0aa8372c 100644
--- a/src/datavisualization/input/qabstract3dinputhandler.cpp
+++ b/src/datavisualization/input/qabstract3dinputhandler.cpp
@@ -20,15 +20,46 @@
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
/*!
- \class QAbstract3DInputHandler
- \inmodule QtDataVisualization
- \brief The base class for implementations of input handlers.
- \since Qt Data Visualization 1.0
+ * \class QAbstract3DInputHandler
+ * \inmodule QtDataVisualization
+ * \brief The base class for implementations of input handlers.
+ * \since Qt Data Visualization 1.0
+ *
+ * QAbstract3DInputHandler is the base class that is subclassed by different input handling implementations
+ * that take input events and translate those to camera and light movements. Input handlers also translate
+ * raw input events to slicing and selection events in the scene.
+ */
- QAbstract3DInputHandler is the base class that is subclassed by different input handling implementations
- that take input events and translate those to camera and light movements. Input handlers also translate
- raw input events to slicing and selection events in the scene.
-*/
+/*!
+ * \enum QAbstract3DInputHandler::InputState
+ *
+ * Predefined input states for mouse and touch based input handlers. All states are not valid
+ * with all input handlers.
+ *
+ * \value InputStateNone
+ * Default "no input received" state.
+ * \value InputStateOnScene
+ * Mouse or touch input received on the 3D scene.
+ * \value InputStateOnPrimaryView
+ * Mouse or touch input received on the primary view area.
+ * \value InputStateOnSecondaryView
+ * Mouse or touch input received on the secondary view area.
+ * \value InputStateRotating
+ * Rotation of the 3D geometry ongoing.
+ * \value InputStatePinching
+ * Pinch/punch multitouch input ongoing.
+ */
+
+/*!
+ * \qmltype AbstractInputHandler3D
+ * \inqmlmodule QtDataVisualization
+ * \since QtDataVisualization 1.0
+ * \ingroup datavisualization_qml
+ * \instantiates QAbstract3DInputHandler
+ * \brief Base type for all QtDataVisualization input handlers.
+ *
+ * This type is uncreatable.
+ */
/*!
* Constructs the base class. An optional \a parent parameter can be given
@@ -112,12 +143,12 @@ void QAbstract3DInputHandler::wheelEvent(QWheelEvent *event)
* Current enumerated input state based on the processed input events.
* When the state changes inputStateChanged() is emitted.
*/
-QDataVis::InputState QAbstract3DInputHandler::inputState()
+QAbstract3DInputHandler::InputState QAbstract3DInputHandler::inputState()
{
return d_ptr->m_inputState;
}
-void QAbstract3DInputHandler::setInputState(QDataVis::InputState inputState)
+void QAbstract3DInputHandler::setInputState(InputState inputState)
{
if (inputState != d_ptr->m_inputState) {
d_ptr->m_inputState = inputState;
@@ -173,7 +204,10 @@ Q3DScene *QAbstract3DInputHandler::scene() const
void QAbstract3DInputHandler::setScene(Q3DScene *scene)
{
- d_ptr->m_scene = scene;
+ if (scene != d_ptr->m_scene) {
+ d_ptr->m_scene = scene;
+ emit sceneChanged(scene);
+ }
}
/*!
@@ -198,7 +232,7 @@ QAbstract3DInputHandlerPrivate::QAbstract3DInputHandlerPrivate(QAbstract3DInputH
q_ptr(q),
m_prevDistance(0),
m_previousInputPos(QPoint(0,0)),
- m_inputState(QDataVis::InputStateNone),
+ m_inputState(QAbstract3DInputHandler::InputStateNone),
m_inputPosition(QPoint(0,0)),
m_scene(0)
{
diff --git a/src/datavisualization/input/qabstract3dinputhandler.h b/src/datavisualization/input/qabstract3dinputhandler.h
index d7bf3aee..313abef3 100644
--- a/src/datavisualization/input/qabstract3dinputhandler.h
+++ b/src/datavisualization/input/qabstract3dinputhandler.h
@@ -30,11 +30,22 @@ class QAbstract3DInputHandlerPrivate;
class QT_DATAVISUALIZATION_EXPORT QAbstract3DInputHandler : public QObject
{
Q_OBJECT
- Q_PROPERTY(QtDataVisualization::QDataVis::InputState inputState READ inputState WRITE setInputState NOTIFY inputStateChanged)
+ Q_ENUMS(InputState)
+ Q_PROPERTY(InputState inputState READ inputState WRITE setInputState NOTIFY inputStateChanged)
Q_PROPERTY(QPoint inputPosition READ inputPosition WRITE setInputPosition NOTIFY positionChanged)
Q_PROPERTY(Q3DScene *scene READ scene WRITE setScene NOTIFY sceneChanged)
public:
+ enum InputState {
+ InputStateNone = 0,
+ InputStateOnScene,
+ InputStateOnPrimaryView,
+ InputStateOnSecondaryView,
+ InputStateRotating,
+ InputStatePinching
+ };
+
+public:
explicit QAbstract3DInputHandler(QObject *parent = 0);
virtual ~QAbstract3DInputHandler();
@@ -48,8 +59,8 @@ public:
public:
// TODO: Check if the inputState needs to be visible outside of subclasses in the final architecture
- QDataVis::InputState inputState();
- void setInputState(QDataVis::InputState inputState);
+ InputState inputState();
+ void setInputState(InputState inputState);
QPoint inputPosition() const;
void setInputPosition(const QPoint &position);
@@ -58,8 +69,8 @@ public:
void setScene(Q3DScene *scene);
signals:
- void positionChanged(const QPoint &position);
- void inputStateChanged(QDataVis::InputState state);
+ void positionChanged(QPoint position);
+ void inputStateChanged(InputState state);
void sceneChanged(const Q3DScene *scene);
protected:
diff --git a/src/datavisualization/input/qabstract3dinputhandler_p.h b/src/datavisualization/input/qabstract3dinputhandler_p.h
index cad1c667..205abf66 100644
--- a/src/datavisualization/input/qabstract3dinputhandler_p.h
+++ b/src/datavisualization/input/qabstract3dinputhandler_p.h
@@ -53,7 +53,7 @@ public:
GLfloat m_defaultYRotation;
private:
- QDataVis::InputState m_inputState;
+ QAbstract3DInputHandler::InputState m_inputState;
QPoint m_inputPosition;
QRect m_mainViewPort;
diff --git a/src/datavisualization/input/qtouch3dinputhandler.cpp b/src/datavisualization/input/qtouch3dinputhandler.cpp
index 1d8bd929..42769562 100644
--- a/src/datavisualization/input/qtouch3dinputhandler.cpp
+++ b/src/datavisualization/input/qtouch3dinputhandler.cpp
@@ -23,7 +23,7 @@
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-const qreal maxTapAndHoldJitter = 20;
+const float maxTapAndHoldJitter = 20.0f;
const int maxPinchJitter = 10;
#if defined (Q_OS_ANDROID)
const int maxSelectionJitter = 10;
@@ -99,18 +99,18 @@ void QTouch3DInputHandler::touchEvent(QTouchEvent *event)
if (event->type() == QEvent::TouchBegin) {
if (scene()->isSlicingActive()) {
if (scene()->isPointInPrimarySubView(pointerPos.toPoint()))
- setInputState(QDataVis::InputStateOnOverview);
+ setInputState(InputStateOnPrimaryView);
else if (scene()->isPointInSecondarySubView(pointerPos.toPoint()))
- setInputState(QDataVis::InputStateOnSlice);
+ setInputState(InputStateOnSecondaryView);
else
- setInputState(QDataVis::InputStateNone);
+ setInputState(InputStateNone);
} else {
// Handle possible tap-and-hold selection
d_ptr->m_startHoldPos = pointerPos;
d_ptr->m_touchHoldPos = d_ptr->m_startHoldPos;
d_ptr->m_holdTimer->start();
// Start rotating
- setInputState(QDataVis::InputStateRotating);
+ setInputState(InputStateRotating);
setInputPosition(pointerPos.toPoint());
}
} else if (event->type() == QEvent::TouchEnd) {
@@ -145,16 +145,16 @@ QTouch3DInputHandlerPrivate::~QTouch3DInputHandlerPrivate()
delete m_holdTimer;
}
-void QTouch3DInputHandlerPrivate::handlePinchZoom(qreal distance)
+void QTouch3DInputHandlerPrivate::handlePinchZoom(float distance)
{
int newDistance = distance;
int prevDist = q_ptr->prevDistance();
if (prevDist > 0 && qAbs(prevDist - newDistance) < maxPinchJitter)
return;
- q_ptr->setInputState(QDataVis::InputStateOnPinch);
+ q_ptr->setInputState(QAbstract3DInputHandler::InputStatePinching);
Q3DCamera *camera = q_ptr->scene()->activeCamera();
int zoomLevel = camera->zoomLevel();
- qreal zoomRate = qSqrt(qSqrt(zoomLevel));
+ float zoomRate = qSqrt(qSqrt(zoomLevel));
if (newDistance > prevDist)
zoomLevel += zoomRate;
else
@@ -172,7 +172,7 @@ void QTouch3DInputHandlerPrivate::handleTapAndHold()
QPointF distance = m_startHoldPos - m_touchHoldPos;
if (distance.manhattanLength() < maxTapAndHoldJitter) {
q_ptr->setInputPosition(m_touchHoldPos.toPoint());
- q_ptr->setInputState(QDataVis::InputStateOnScene);
+ q_ptr->setInputState(QAbstract3DInputHandler::InputStateOnScene);
}
}
@@ -180,15 +180,16 @@ void QTouch3DInputHandlerPrivate::handleSelection(const QPointF &position)
{
QPointF distance = m_startHoldPos - position;
if (distance.manhattanLength() < maxSelectionJitter)
- q_ptr->setInputState(QDataVis::InputStateOnScene);
+ q_ptr->setInputState(QAbstract3DInputHandler::InputStateOnScene);
else
- q_ptr->setInputState(QDataVis::InputStateNone);
+ q_ptr->setInputState(QAbstract3DInputHandler::InputStateNone);
q_ptr->setPreviousInputPos(position.toPoint());
+ q_ptr->scene()->setSelectionQueryPosition(position.toPoint());
}
void QTouch3DInputHandlerPrivate::handleRotation(const QPointF &position)
{
- if (QDataVis::InputStateRotating == q_ptr->inputState()) {
+ if (QAbstract3DInputHandler::InputStateRotating == q_ptr->inputState()) {
Q3DScene *scene = q_ptr->scene();
Q3DCamera *camera = scene->activeCamera();
float xRotation = camera->xRotation();
@@ -202,7 +203,6 @@ void QTouch3DInputHandlerPrivate::handleRotation(const QPointF &position)
yRotation -= mouseMoveY;
camera->setXRotation(xRotation);
camera->setYRotation(yRotation);
- camera->d_ptr->updateViewMatrix(1.0f);
q_ptr->setPreviousInputPos(inputPos.toPoint());
q_ptr->setInputPosition(position.toPoint());
diff --git a/src/datavisualization/input/qtouch3dinputhandler_p.h b/src/datavisualization/input/qtouch3dinputhandler_p.h
index 1c5b81c7..11163140 100644
--- a/src/datavisualization/input/qtouch3dinputhandler_p.h
+++ b/src/datavisualization/input/qtouch3dinputhandler_p.h
@@ -33,7 +33,7 @@ public:
QTouch3DInputHandlerPrivate(QTouch3DInputHandler *q);
~QTouch3DInputHandlerPrivate();
- void handlePinchZoom(qreal distance);
+ void handlePinchZoom(float distance);
void handleTapAndHold();
void handleSelection(const QPointF &position);
void handleRotation(const QPointF &position);
diff --git a/src/datavisualization/theme/builtin3dthemes.cpp b/src/datavisualization/theme/builtin3dthemes.cpp
new file mode 100644
index 00000000..9848e6e5
--- /dev/null
+++ b/src/datavisualization/theme/builtin3dthemes.cpp
@@ -0,0 +1,230 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#include "builtin3dthemes_p.h"
+
+QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
+BuiltIn3DThemeQt::BuiltIn3DThemeQt()
+ : Q3DTheme(QDataVis::ThemeQt)
+{
+ setBaseColor(QColor(QRgb(0x80c342)));
+ setBackgroundColor(QColor(QRgb(0xffffff)));
+ setWindowColor(QColor(QRgb(0xffffff)));
+ setTextColor(QColor(QRgb(0x35322f)));
+ setTextBackgroundColor(QColor(0xff, 0xff, 0xff, 0x99));
+ setGridLineColor(QColor(QRgb(0xd7d6d5)));
+ setSingleHighlightColor(QColor(QRgb(0x14aaff)));
+ setMultiHighlightColor(QColor(QRgb(0x6400aa)));
+ setLightStrength(5.0f);
+ setAmbientLightStrength(0.5f);
+ setHighlightLightStrength(5.0f);
+ setLabelBorderEnabled(true);
+ setColorStyle(QDataVis::ColorStyleUniform);
+}
+
+BuiltIn3DThemePrimaryColors::BuiltIn3DThemePrimaryColors()
+ : Q3DTheme(QDataVis::ThemePrimaryColors)
+{
+ setBaseColor(QColor(QRgb(0xffe400)));
+ setBackgroundColor(QColor(QRgb(0xffffff)));
+ setWindowColor(QColor(QRgb(0xffffff)));
+ setTextColor(QColor(QRgb(0x000000)));
+ setTextBackgroundColor(QColor(0xff, 0xff, 0xff, 0x99));
+ setGridLineColor(QColor(QRgb(0xd7d6d5)));
+ setSingleHighlightColor(QColor(QRgb(0x27beee)));
+ setMultiHighlightColor(QColor(QRgb(0xee1414)));
+ setLightStrength(5.0f);
+ setAmbientLightStrength(0.5f);
+ setHighlightLightStrength(5.0f);
+ setLabelBorderEnabled(false);
+ setColorStyle(QDataVis::ColorStyleUniform);
+}
+
+BuiltIn3DThemeDigia::BuiltIn3DThemeDigia()
+ : Q3DTheme(QDataVis::ThemeDigia)
+{
+ setBackgroundColor(QColor(QRgb(0xffffff)));
+ setWindowColor(QColor(QRgb(0xffffff)));
+ setTextColor(QColor(QRgb(0x000000)));
+ setTextBackgroundColor(QColor(0xff, 0xff, 0xff, 0x80));
+ setGridLineColor(QColor(QRgb(0xd7d6d5)));
+ setSingleHighlightColor(QColor(QRgb(0xfa0000)));
+ setMultiHighlightColor(QColor(QRgb(0x555555)));
+ setLightStrength(5.0f);
+ setAmbientLightStrength(0.5f);
+ setHighlightLightStrength(5.0f);
+ setLabelBorderEnabled(false);
+ setColorStyle(QDataVis::ColorStyleObjectGradient);
+ QLinearGradient gradient = QLinearGradient(qreal(gradientTextureWidth),
+ qreal(gradientTextureHeight),
+ 0.0, 0.0);
+ QColor color;
+ color.setRed(0xcc * 0.7);
+ color.setGreen(0xcc * 0.7);
+ color.setBlue(0xcc * 0.7);
+ gradient.setColorAt(0.0, color);
+ gradient.setColorAt(1.0, QColor(QRgb(0xcccccc)));
+ setBaseGradient(gradient);
+ color.setRed(0xfa * 0.7);
+ color.setGreen(0x00);
+ color.setBlue(0x00);
+ gradient.setColorAt(0.0, color);
+ gradient.setColorAt(1.0, QColor(QRgb(0xfa0000)));
+ setSingleHighlightGradient(gradient);
+ color.setRed(0x55 * 0.7);
+ color.setGreen(0x55 * 0.7);
+ color.setBlue(0x55 * 0.7);
+ gradient.setColorAt(0.0, color);
+ gradient.setColorAt(1.0, QColor(QRgb(0x555555)));
+ setMultiHighlightGradient(gradient);
+}
+
+BuiltIn3DThemeStoneMoss::BuiltIn3DThemeStoneMoss()
+ : Q3DTheme(QDataVis::ThemeStoneMoss)
+{
+ setBaseColor(QColor(QRgb(0xbeb32b)));
+ setBackgroundColor(QColor(QRgb(0x4d4d4f)));
+ setWindowColor(QColor(QRgb(0x4d4d4f)));
+ setTextColor(QColor(QRgb(0xffffff)));
+ setTextBackgroundColor(QColor(0x4d, 0x4d, 0x4f, 0xcd));
+ setGridLineColor(QColor(QRgb(0x3e3e40)));
+ setSingleHighlightColor(QColor(QRgb(0xfbf6d6)));
+ setMultiHighlightColor(QColor(QRgb(0x442f20)));
+ setLightStrength(5.0f);
+ setAmbientLightStrength(0.5f);
+ setHighlightLightStrength(5.0f);
+ setLabelBorderEnabled(true);
+ setColorStyle(QDataVis::ColorStyleUniform);
+}
+
+BuiltIn3DThemeArmyBlue::BuiltIn3DThemeArmyBlue()
+ : Q3DTheme(QDataVis::ThemeArmyBlue)
+{
+ setBackgroundColor(QColor(QRgb(0xd5d6d7)));
+ setWindowColor(QColor(QRgb(0xd5d6d7)));
+ setTextColor(QColor(QRgb(0x000000)));
+ setTextBackgroundColor(QColor(0xd5, 0xd6, 0xd7, 0xcd));
+ setGridLineColor(QColor(QRgb(0xaeadac)));
+ setSingleHighlightColor(QColor(QRgb(0x2aa2f9)));
+ setMultiHighlightColor(QColor(QRgb(0x103753)));
+ setLightStrength(5.0f);
+ setAmbientLightStrength(0.5f);
+ setHighlightLightStrength(5.0f);
+ setLabelBorderEnabled(false);
+ setColorStyle(QDataVis::ColorStyleObjectGradient);
+ QLinearGradient gradient = QLinearGradient(qreal(gradientTextureWidth),
+ qreal(gradientTextureHeight),
+ 0.0, 0.0);
+ QColor color;
+ color.setRed(0x49 * 0.7);
+ color.setGreen(0x5f * 0.7);
+ color.setBlue(0x76 * 0.7);
+ gradient.setColorAt(0.0, color);
+ gradient.setColorAt(1.0, QColor(QRgb(0x495f76)));
+ setBaseGradient(gradient);
+ color.setRed(0x2a * 0.7);
+ color.setGreen(0xa2 * 0.7);
+ color.setBlue(0xf9 * 0.7);
+ gradient.setColorAt(0.0, color);
+ gradient.setColorAt(1.0, QColor(QRgb(0x2aa2f9)));
+ setSingleHighlightGradient(gradient);
+ color.setRed(0x10 * 0.7);
+ color.setGreen(0x37 * 0.7);
+ color.setBlue(0x53 * 0.7);
+ gradient.setColorAt(0.0, color);
+ gradient.setColorAt(1.0, QColor(QRgb(0x103753)));
+ setMultiHighlightGradient(gradient);
+}
+
+BuiltIn3DThemeRetro::BuiltIn3DThemeRetro()
+ : Q3DTheme(QDataVis::ThemeRetro)
+{
+ setBackgroundColor(QColor(QRgb(0xe9e2ce)));
+ setWindowColor(QColor(QRgb(0xe9e2ce)));
+ setTextColor(QColor(QRgb(0x000000)));
+ setTextBackgroundColor(QColor(0xe9, 0xe2, 0xce, 0xc0));
+ setGridLineColor(QColor(QRgb(0xd0c0b0)));
+ setSingleHighlightColor(QColor(QRgb(0x8ea317)));
+ setMultiHighlightColor(QColor(QRgb(0xc25708)));
+ setLightStrength(5.0f);
+ setAmbientLightStrength(0.5f);
+ setHighlightLightStrength(5.0f);
+ setLabelBorderEnabled(false);
+ setColorStyle(QDataVis::ColorStyleObjectGradient);
+ QLinearGradient gradient = QLinearGradient(qreal(gradientTextureWidth),
+ qreal(gradientTextureHeight),
+ 0.0, 0.0);
+ QColor color;
+ color.setRed(0x53 * 0.7);
+ color.setGreen(0x3b * 0.7);
+ color.setBlue(0x23 * 0.7);
+ gradient.setColorAt(0.0, color);
+ gradient.setColorAt(1.0, QColor(QRgb(0x533b23)));
+ setBaseGradient(gradient);
+ color.setRed(0x8e * 0.7);
+ color.setGreen(0xa3 * 0.7);
+ color.setBlue(0x17 * 0.7);
+ gradient.setColorAt(0.0, color);
+ gradient.setColorAt(1.0, QColor(QRgb(0x8ea317)));
+ setSingleHighlightGradient(gradient);
+ color.setRed(0xc2 * 0.7);
+ color.setGreen(0x57 * 0.7);
+ color.setBlue(0x08 * 0.7);
+ gradient.setColorAt(0.0, color);
+ gradient.setColorAt(1.0, QColor(QRgb(0xc25708)));
+ setMultiHighlightGradient(gradient);
+}
+
+BuiltIn3DThemeEbony::BuiltIn3DThemeEbony()
+ : Q3DTheme(QDataVis::ThemeEbony)
+{
+ setBaseColor(QColor(QRgb(0xffffff)));
+ setBackgroundColor(QColor(QRgb(0x000000)));
+ setWindowColor(QColor(QRgb(0x000000)));
+ setTextColor(QColor(QRgb(0xaeadac)));
+ setTextBackgroundColor(QColor(0x00, 0x00, 0x00, 0xcd));
+ setGridLineColor(QColor(QRgb(0x35322f)));
+ setSingleHighlightColor(QColor(QRgb(0xf5dc0d)));
+ setMultiHighlightColor(QColor(QRgb(0xd72222)));
+ setLightStrength(5.0f);
+ setAmbientLightStrength(0.5f);
+ setHighlightLightStrength(5.0f);
+ setLabelBorderEnabled(false);
+ setColorStyle(QDataVis::ColorStyleUniform);
+}
+
+BuiltIn3DThemeIsabelle::BuiltIn3DThemeIsabelle()
+ : Q3DTheme(QDataVis::ThemeIsabelle)
+{
+ setBaseColor(QColor(QRgb(0xf9d900)));
+ setBackgroundColor(QColor(QRgb(0x000000)));
+ setWindowColor(QColor(QRgb(0x000000)));
+ setTextColor(QColor(QRgb(0xaeadac)));
+ setTextBackgroundColor(QColor(0x00, 0x00, 0x00, 0xc0));
+ setGridLineColor(QColor(QRgb(0x35322f)));
+ setSingleHighlightColor(QColor(QRgb(0xfff7cc)));
+ setMultiHighlightColor(QColor(QRgb(0xde0a0a)));
+ setLightStrength(5.0f);
+ setAmbientLightStrength(0.5f);
+ setHighlightLightStrength(5.0f);
+ setLabelBorderEnabled(false);
+ setColorStyle(QDataVis::ColorStyleUniform);
+}
+
+QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualizationqml2/declarativebarsrenderer_p.h b/src/datavisualization/theme/builtin3dthemes_p.h
index 3be9b911..8f2c3d04 100644
--- a/src/datavisualizationqml2/declarativebarsrenderer_p.h
+++ b/src/datavisualization/theme/builtin3dthemes_p.h
@@ -26,38 +26,60 @@
//
// We mean it.
-#ifndef DECLARATIVEBARSRENDERER_H
-#define DECLARATIVEBARSRENDERER_H
+#ifndef BUILTIN3DTHEMES_P_H
+#define BUILTIN3DTHEMES_P_H
#include "datavisualizationglobal_p.h"
-#include "bars3dcontroller_p.h"
-#include <qsgsimpletexturenode.h>
-
-class QOpenGLFramebufferObject;
-class QSGTexture;
-class QQuickWindow;
+#include "q3dtheme_p.h"
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-class DeclarativeBarsRenderer : public QObject, public QSGSimpleTextureNode
+class BuiltIn3DThemeQt : public Q3DTheme
+{
+public:
+ BuiltIn3DThemeQt();
+};
+
+class BuiltIn3DThemePrimaryColors : public Q3DTheme
+{
+public:
+ BuiltIn3DThemePrimaryColors();
+};
+
+class BuiltIn3DThemeDigia : public Q3DTheme
+{
+public:
+ BuiltIn3DThemeDigia();
+};
+
+class BuiltIn3DThemeStoneMoss : public Q3DTheme
{
- Q_OBJECT
+public:
+ BuiltIn3DThemeStoneMoss();
+};
+class BuiltIn3DThemeArmyBlue : public Q3DTheme
+{
public:
- DeclarativeBarsRenderer(QQuickWindow *window, Bars3DController *shared);
- ~DeclarativeBarsRenderer();
+ BuiltIn3DThemeArmyBlue();
+};
-public slots:
- // Used to synch up data model from controller to renderer while main thread is locked
- void synchDataToRenderer();
- // Renders view to FBO before render cycle starts.
- void renderFBO();
+class BuiltIn3DThemeRetro : public Q3DTheme
+{
+public:
+ BuiltIn3DThemeRetro();
+};
-private:
- QOpenGLFramebufferObject *m_fbo;
- QSGTexture *m_texture;
- QQuickWindow *m_window;
- Bars3DController *m_barsRenderer;
+class BuiltIn3DThemeEbony : public Q3DTheme
+{
+public:
+ BuiltIn3DThemeEbony();
+};
+
+class BuiltIn3DThemeIsabelle : public Q3DTheme
+{
+public:
+ BuiltIn3DThemeIsabelle();
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/theme/q3dtheme.cpp b/src/datavisualization/theme/q3dtheme.cpp
new file mode 100644
index 00000000..3d85b9fa
--- /dev/null
+++ b/src/datavisualization/theme/q3dtheme.cpp
@@ -0,0 +1,1064 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#include "q3dtheme_p.h"
+
+QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
+/*!
+ * \class Q3DTheme
+ * \inmodule QtDataVisualization
+ * \brief Q3DTheme class provides a visual style for graphs.
+ * \since Qt Data Visualization 1.0
+ *
+ * Q3DTheme is used to specify visual properties that affect the whole graph. There are several
+ * built-in themes that can be used directly, or be modified freely. User can also create a theme
+ * from scratch using \c ThemeUserDefined. Creating a theme using the default constructor
+ * produces a new user-defined theme.
+ *
+ * \section1 Properties controlled by theme
+ * \table
+ * \header
+ * \li Property
+ * \li Effect
+ * \li Default in ThemeUserDefined
+ * \row
+ * \li ambientLightStrength
+ * \li The strength of the ambient light in the graph. This affects how evenly and brightly the
+ * colors are shown throughout the graph regardless of light position.
+ * \li 0.25
+ * \row
+ * \li backgroundColor
+ * \li Color of the graph background.
+ * \li Qt::black
+ * \row
+ * \li backgroundEnabled
+ * \li Is the graph background drawn or not.
+ * \li true
+ * \row
+ * \li baseColors
+ * \li List of colors for the objects in the graph. Colors are applied to series one by one.
+ * If there are more series than colors, the color list is reused from the start.
+ * The colors in this property are used if colorStyle is ColorStyleUniform. This can be
+ * overridden by setting the baseColor explicitly in series.
+ * \li Qt::black
+ * \row
+ * \li baseGradients
+ * \li List of gradients for the objects in the graph. Gradients are applied to series one by
+ * one. If there are more series than gradients, the gradient list is reused from the start.
+ * The gradients in this property are used if colorStyle is ColorStyleObjectGradient or
+ * ColorStyleRangeGradient. This can be overridden by setting the baseGradient explicitly
+ * in series.
+ * \li QLinearGradient(). Essentially fully black.
+ * \row
+ * \li colorStyle
+ * \li The color style of the objects in the graph. See ColorStyle for detailed description of
+ * the styles. This can be overridden by setting the colorStyle explicitly in series.
+ * \li ColorStyleUniform
+ * \row
+ * \li \l font
+ * \li The font to be used for labels.
+ * \li QFont()
+ * \row
+ * \li gridEnabled
+ * \li Is the grid on the background drawn or not. This affects all grid lines.
+ * \li true
+ * \row
+ * \li gridLineColor
+ * \li The color for the grid lines.
+ * \li Qt::white
+ * \row
+ * \li highlightLightStrength
+ * \li The specular light strength for highlighted objects.
+ * \li 7.5
+ * \row
+ * \li labelBackgroundColor
+ * \li The color of the label background. This property has no effect if labelBackgroundEnabled
+ * is \c false.
+ * \li Qt::gray
+ * \row
+ * \li labelBackgroundEnabled
+ * \li Are the labels to be drawn with a background using labelBackgroundColor (including alpha),
+ * or with a fully transparent background. Labels with background are drawn to equal sizes
+ * per axis based on the longest label, and the text is centered in it. Labels without
+ * background are drawn as is and are left/right aligned based on their position in the
+ * graph.
+ * \li true
+ * \row
+ * \li labelBorderEnabled
+ * \li Are the labels to be drawn with a border or not. This property affects only labels with
+ * a background.
+ * \li true
+ * \row
+ * \li labelTextColor
+ * \li The color for the font used in labels.
+ * \li Qt::white
+ * \row
+ * \li lightColor
+ * \li The color of the specular light. Doesn't affect ambient light. \note Not yet supported
+ * in alpha release.
+ * \li Qt::white
+ * \row
+ * \li lightStrength
+ * \li The strength of the specular light in the graph. This affects the light specified in
+ * Q3DScene.
+ * \li 5.0
+ * \row
+ * \li multiHighlightColor
+ * \li The color to be used for highlighted objects, if \l{Q3DBars::selectionMode}{selectionMode}
+ * of the graph has \c QDataVis::SelectionRow or \c QDataVis::SelectionColumn flag set.
+ * \li Qt::blue
+ * \row
+ * \li multiHighlightGradient
+ * \li The gradient to be used for highlighted objects, if \l{Q3DBars::selectionMode}{selectionMode}
+ * of the graph has \c QDataVis::SelectionRow or \c QDataVis::SelectionColumn flag set.
+ * \li QLinearGradient(). Essentially fully black.
+ * \row
+ * \li singleHighlightColor
+ * \li The color to be used for a highlighted object, if \l{Q3DBars::selectionMode}{selectionMode}
+ * of the graph has \c QDataVis::SelectionItem flag set.
+ * \li Qt::red
+ * \row
+ * \li singleHighlightGradient
+ * \li The gradient to be used for a highlighted object, if \l{Q3DBars::selectionMode}{selectionMode}
+ * of the graph has \c QDataVis::SelectionItem flag set.
+ * \li QLinearGradient(). Essentially fully black.
+ * \row
+ * \li windowColor
+ * \li The color of the window the graph is drawn into.
+ * \li Qt::black
+ * \endtable
+ *
+ * \section1 Usage examples
+ *
+ * Creating a built-in theme without any modifications:
+ *
+ * \snippet doc_src_q3dtheme.cpp 0
+ *
+ * Creating a built-in theme and modifying some properties:
+ *
+ * \snippet doc_src_q3dtheme.cpp 1
+ *
+ * Creating a user-defined theme:
+ *
+ * \snippet doc_src_q3dtheme.cpp 2
+ *
+ * Creating a built-in theme and modifying some properties after it has been set:
+ *
+ * \snippet doc_src_q3dtheme.cpp 3
+ *
+ */
+
+/*!
+ * \enum Q3DTheme::ColorStyle
+ *
+ * Color styles.
+ *
+ * \value ColorStyleUniform
+ * Objects are rendered in a single color. The color used is specified in baseColor,
+ * singleHighlightColor and multiHighlightColor properties.
+ * \value ColorStyleObjectGradient
+ * Objects are colored using a full gradient for each object regardless of object height. The
+ * gradient used is specified in baseGradient, singleHighlightGradient and
+ * multiHighlightGradient properties.
+ * \value ColorStyleRangeGradient
+ * Objects are colored using a portion of the full gradient determined by the object's
+ * height and its position on the Y-axis. The gradient used is specified in baseGradient,
+ * singleHighlightGradient and multiHighlightGradient properties.
+ */
+
+/*!
+ * \enum Q3DTheme::Theme
+ *
+ * Built-in themes.
+ *
+ * \value ThemeQt
+ * A light theme with green as the base color.
+ * \value ThemePrimaryColors
+ * A light theme with yellow as the base color.
+ * \value ThemeDigia
+ * A light theme with gray as the base color.
+ * \value ThemeStoneMoss
+ * A medium dark theme with yellow as the base color.
+ * \value ThemeArmyBlue
+ * A medium light theme with blue as the base color.
+ * \value ThemeRetro
+ * A medium light theme with brown as the base color.
+ * \value ThemeEbony
+ * A dark theme with white as the base color.
+ * \value ThemeIsabelle
+ * A dark theme with yellow as the base color.
+ * \value ThemeUserDefined
+ * A user-defined theme. See \l {Properties controlled by theme} for theme defaults.
+ */
+
+/*!
+ * \qmltype Theme3D
+ * \inqmlmodule QtDataVisualization
+ * \since QtDataVisualization 1.0
+ * \ingroup datavisualization_qml
+ * \instantiates Q3DTheme
+ * \brief A visual style for graphs.
+ *
+ * This type is used to specify visual properties that affect the whole graph. There are several
+ * built-in themes that can be used directly, or be modified freely. User can also create a theme
+ * from scratch using \c Theme3D.ThemeUserDefined.
+ *
+ * For a more complete description, see Q3DTheme.
+ *
+ * \section1 Usage examples
+ *
+ * Using a built-in theme without any modifications:
+ *
+ * \snippet doc_src_q3dtheme.cpp 4
+ *
+ * Using a built-in theme and modifying some properties:
+ *
+ * \snippet doc_src_q3dtheme.cpp 5
+ *
+ * Using a user-defined theme:
+ *
+ * \snippet doc_src_q3dtheme.cpp 6
+ */
+
+/*!
+ * \qmlproperty Color Theme3D::baseColors
+ *
+ * List of base colors to be used for all the objects in the graph, series by series. If there
+ * are more series than colors, color list wraps and starts again with the first color in the list.
+ * Has no immediate effect if colorStyle is not \c Theme3D.ColorStyleUniform.
+ */
+
+/*!
+ * \qmlproperty Color Theme3D::backgroundColor
+ *
+ * Color for the graph background.
+ */
+
+/*!
+ * \qmlproperty Color Theme3D::windowColor
+ *
+ * Color for the application window.
+ */
+
+/*!
+ * \qmlproperty Color Theme3D::labelTextColor
+ *
+ * Color for the font used for labels.
+ */
+
+/*!
+ * \qmlproperty Color Theme3D::labelBackgroundColor
+ *
+ * Color for the label backgrounds. Has no effect if labelBackgroundEnabled is \c false.
+ */
+
+/*!
+ * \qmlproperty Color Theme3D::gridLineColor
+ *
+ * Color for the grid lines.
+ */
+
+/*!
+ * \qmlproperty Color Theme3D::singleHighlightColor
+ *
+ * Highlight color for a highlighted object. Used if \l{AbstractGraph3D::selectionMode}{selectionMode}
+ * has \c AbstractGraph3D.SelectionItem flag set.
+ */
+
+/*!
+ * \qmlproperty Color Theme3D::multiHighlightColor
+ *
+ * Highlight color for highlighted objects. Used if \l{AbstractGraph3D::selectionMode}{selectionMode}
+ * has \c AbstractGraph3D.SelectionRow or \c AbstractGraph3D.SelectionColumn flag set.
+ */
+
+/*!
+ * \qmlproperty Color Theme3D::lightColor
+ *
+ * Color for the specular light defined in Scene3D.
+ *
+ * \warning Not supported in alpha release.
+ */
+
+/*!
+ * \qmlproperty ColorGradient Theme3D::baseGradients
+ *
+ * List of base gradients to be used for all the objects in the graph, series by series. If there
+ * are more series than gradients, gradient list wraps and starts again with the first gradient in
+ * the list
+ * Has no immediate effect if colorStyle is \c Theme3D.ColorStyleUniform.
+ */
+
+/*!
+ * \qmlproperty ColorGradient Theme3D::singleHighlightGradient
+ *
+ * Highlight gradient for a highlighted object. Used if \l{AbstractGraph3D::selectionMode}{selectionMode}
+ * has \c AbstractGraph3D.SelectionItem flag set.
+ */
+
+/*!
+ * \qmlproperty ColorGradient Theme3D::multiHighlightGradient
+ *
+ * Highlight gradient for highlighted objects. Used if \l{AbstractGraph3D::selectionMode}{selectionMode}
+ * has \c AbstractGraph3D.SelectionRow or \c AbstractGraph3D.SelectionColumn flag set.
+ */
+
+/*!
+ * \qmlproperty float Theme3D::lightStrength
+ *
+ * Specular light strength for the whole graph. Value must be between 0.0 and 1.0.
+ */
+
+/*!
+ * \qmlproperty float Theme3D::ambientLightStrength
+ *
+ * Ambient light strength for the whole graph. Value must be between 0.0 and 1.0.
+ */
+
+/*!
+ * \qmlproperty float Theme3D::highlightLightStrength
+ *
+ * Specular light strength for highlighted objects. Value must be between 0.0 and 1.0.
+ */
+
+/*!
+ * \qmlproperty bool Theme3D::labelBorderEnabled
+ *
+ * Set label borders enabled or disabled. Has no effect if labelBackgroundEnabled is \c false.
+ */
+
+/*!
+ * \qmlproperty Font Theme3D::font
+ *
+ * Set \a font to be used for labels.
+ */
+
+/*!
+ * \qmlproperty bool Theme3D::backgroundEnabled
+ *
+ * Set background enabled or disabled.
+ */
+
+/*!
+ * \qmlproperty bool Theme3D::gridEnabled
+ *
+ * Set grid lines enabled or disabled.
+ */
+
+/*!
+ * \qmlproperty bool Theme3D::labelBackgroundEnabled
+ *
+ * Set label backgrounds enabled or disabled.
+ */
+
+/*!
+ * \qmlproperty Theme3D.ColorStyle Theme3D::colorStyle
+ *
+ * The \a style of the graph colors. One of \c Theme3D.ColorStyle.
+ */
+
+/*!
+ * \qmlproperty Theme3D.Theme Theme3D::type
+ *
+ * The type of the theme. If no type is set, the type is \c Theme3D.ThemeUserDefined.
+ */
+
+/*!
+ * Constructs a new theme of type ThemeUserDefined. An optional \a parent parameter
+ * can be given and is then passed to QObject constructor.
+ */
+Q3DTheme::Q3DTheme(QObject *parent)
+ : QObject(parent),
+ d_ptr(new Q3DThemePrivate(this, ThemeUserDefined))
+{
+}
+
+/*!
+ * Constructs a new theme with \a themeType, which can be one of the built-in themes from
+ * \l Theme. An optional \a parent parameter can be given and is then passed to QObject
+ * constructor.
+ */
+Q3DTheme::Q3DTheme(Theme themeType, QObject *parent)
+ : QObject(parent),
+ d_ptr(new Q3DThemePrivate(this, themeType))
+{
+}
+
+/*!
+ * \internal
+ */
+Q3DTheme::Q3DTheme(Q3DThemePrivate *d, Theme themeType,
+ QObject *parent) :
+ QObject(parent),
+ d_ptr(d)
+{
+ d_ptr->m_themeId = themeType;
+}
+
+/*!
+ * Destroys the theme.
+ */
+Q3DTheme::~Q3DTheme()
+{
+}
+
+// TODO: Add needRenders if necessary after color api has been added to series (QTRD-2200/2557)
+/*!
+ * \property Q3DTheme::baseColors
+ *
+ * List of base colors to be used for all the objects in the graph, series by series. If there
+ * are more series than colors, color list wraps and starts again with the first color in the list.
+ * Has no immediate effect if colorStyle is not ColorStyleUniform.
+ */
+void Q3DTheme::setBaseColors(const QList<QColor> &colors)
+{
+ if (colors.size()) {
+ d_ptr->m_dirtyBits.baseColorDirty = true;
+ if (d_ptr->m_baseColors != colors) {
+ d_ptr->m_baseColors.clear();
+ d_ptr->m_baseColors = colors;
+ emit baseColorsChanged(colors);
+ }
+ } else {
+ d_ptr->m_baseColors.clear();
+ }
+}
+
+QList<QColor> Q3DTheme::baseColors() const
+{
+ return d_ptr->m_baseColors;
+}
+
+/*!
+ * \property Q3DTheme::backgroundColor
+ *
+ * Color for the graph background.
+ */
+void Q3DTheme::setBackgroundColor(const QColor &color)
+{
+ d_ptr->m_dirtyBits.backgroundColorDirty = true;
+ if (d_ptr->m_backgroundColor != color) {
+ d_ptr->m_backgroundColor = color;
+ emit backgroundColorChanged(color);
+ emit d_ptr->needRender();
+ }
+}
+
+QColor Q3DTheme::backgroundColor() const
+{
+ return d_ptr->m_backgroundColor;
+}
+
+/*!
+ * \property Q3DTheme::windowColor
+ *
+ * Color for the application window.
+ */
+void Q3DTheme::setWindowColor(const QColor &color)
+{
+ d_ptr->m_dirtyBits.windowColorDirty = true;
+ if (d_ptr->m_windowColor != color) {
+ d_ptr->m_windowColor = color;
+ emit windowColorChanged(color);
+ emit d_ptr->needRender();
+ }
+}
+
+QColor Q3DTheme::windowColor() const
+{
+ return d_ptr->m_windowColor;
+}
+
+/*!
+ * \property Q3DTheme::labelTextColor
+ *
+ * Color for the font used for labels.
+ */
+void Q3DTheme::setLabelTextColor(const QColor &color)
+{
+ d_ptr->m_dirtyBits.labelTextColorDirty = true;
+ if (d_ptr->m_textColor != color) {
+ d_ptr->m_textColor = color;
+ emit labelTextColorChanged(color);
+ emit d_ptr->needRender();
+ }
+}
+
+QColor Q3DTheme::labelTextColor() const
+{
+ return d_ptr->m_textColor;
+}
+
+/*!
+ * \property Q3DTheme::labelBackgroundColor
+ *
+ * Color for the label backgrounds. Has no effect if labelBackgroundEnabled is \c false.
+ */
+void Q3DTheme::setLabelBackgroundColor(const QColor &color)
+{
+ d_ptr->m_dirtyBits.labelBackgroundColorDirty = true;
+ if (d_ptr->m_textBackgroundColor != color) {
+ d_ptr->m_textBackgroundColor = color;
+ emit labelBackgroundColorChanged(color);
+ emit d_ptr->needRender();
+ }
+}
+
+QColor Q3DTheme::labelBackgroundColor() const
+{
+ return d_ptr->m_textBackgroundColor;
+}
+
+/*!
+ * \property Q3DTheme::gridLineColor
+ *
+ * Color for the grid lines.
+ */
+void Q3DTheme::setGridLineColor(const QColor &color)
+{
+ d_ptr->m_dirtyBits.gridLineColorDirty = true;
+ if (d_ptr->m_gridLineColor != color) {
+ d_ptr->m_gridLineColor = color;
+ emit gridLineColorChanged(color);
+ emit d_ptr->needRender();
+ }
+}
+
+QColor Q3DTheme::gridLineColor() const
+{
+ return d_ptr->m_gridLineColor;
+}
+
+/*!
+ * \property Q3DTheme::singleHighlightColor
+ *
+ * Highlight color for a highlighted object. Used if \l{Q3DBars::selectionMode}{selectionMode} has
+ * \c QDataVis::SelectionItem flag set.
+ */
+void Q3DTheme::setSingleHighlightColor(const QColor &color)
+{
+ d_ptr->m_dirtyBits.singleHighlightColorDirty = true;
+ if (d_ptr->m_singleHighlightColor != color) {
+ d_ptr->m_singleHighlightColor = color;
+ emit singleHighlightColorChanged(color);
+ }
+}
+
+QColor Q3DTheme::singleHighlightColor() const
+{
+ return d_ptr->m_singleHighlightColor;
+}
+
+/*!
+ * \property Q3DTheme::multiHighlightColor
+ *
+ * Highlight color for highlighted objects. Used if \l{Q3DBars::selectionMode}{selectionMode} has
+ * \c QDataVis::SelectionRow or \c QDataVis::SelectionColumn flag set.
+ */
+void Q3DTheme::setMultiHighlightColor(const QColor &color)
+{
+ d_ptr->m_dirtyBits.multiHighlightColorDirty = true;
+ if (d_ptr->m_multiHighlightColor != color) {
+ d_ptr->m_multiHighlightColor = color;
+ emit multiHighlightColorChanged(color);
+ }
+}
+
+QColor Q3DTheme::multiHighlightColor() const
+{
+ return d_ptr->m_multiHighlightColor;
+}
+
+/*!
+ * \property Q3DTheme::lightColor
+ *
+ * Color for the specular light defined in Q3DScene.
+ *
+ * \warning Not supported in alpha release.
+ */
+void Q3DTheme::setLightColor(const QColor &color)
+{
+ d_ptr->m_dirtyBits.lightColorDirty = true;
+ if (d_ptr->m_lightColor != color) {
+ d_ptr->m_lightColor = color;
+ emit lightColorChanged(color);
+ emit d_ptr->needRender();
+ }
+}
+
+QColor Q3DTheme::lightColor() const
+{
+ return d_ptr->m_lightColor;
+}
+
+/*!
+ * \property Q3DTheme::baseGradients
+ *
+ * List of base gradients to be used for all the objects in the graph, series by series. If there
+ * are more series than gradients, gradient list wraps and starts again with the first gradient in
+ * the list
+ * Has no immediate effect if colorStyle is ColorStyleUniform.
+ */
+void Q3DTheme::setBaseGradients(const QList<QLinearGradient> &gradients)
+{
+ if (gradients.size()) {
+ d_ptr->m_dirtyBits.baseGradientDirty = true;
+ if (d_ptr->m_baseGradients != gradients) {
+ d_ptr->m_baseGradients.clear();
+ d_ptr->m_baseGradients = gradients;
+ emit baseGradientsChanged(gradients);
+ }
+ } else {
+ d_ptr->m_baseGradients.clear();
+ }
+}
+
+QList<QLinearGradient> Q3DTheme::baseGradients() const
+{
+ return d_ptr->m_baseGradients;
+}
+
+/*!
+ * \property Q3DTheme::singleHighlightGradient
+ *
+ * Highlight gradient for a highlighted object. Used if \l{Q3DBars::selectionMode}{selectionMode}
+ * has \c QDataVis::SelectionItem flag set.
+ */
+void Q3DTheme::setSingleHighlightGradient(const QLinearGradient &gradient)
+{
+ d_ptr->m_dirtyBits.singleHighlightGradientDirty = true;
+ if (d_ptr->m_singleHighlightGradient != gradient) {
+ d_ptr->m_singleHighlightGradient = gradient;
+ emit singleHighlightGradientChanged(gradient);
+ }
+}
+
+QLinearGradient Q3DTheme::singleHighlightGradient() const
+{
+ return d_ptr->m_singleHighlightGradient;
+}
+
+/*!
+ * \property Q3DTheme::multiHighlightGradient
+ *
+ * Highlight gradient for highlighted objects. Used if \l{Q3DBars::selectionMode}{selectionMode}
+ * has \c QDataVis::SelectionRow or \c QDataVis::SelectionColumn flag set.
+ */
+void Q3DTheme::setMultiHighlightGradient(const QLinearGradient &gradient)
+{
+ d_ptr->m_dirtyBits.multiHighlightGradientDirty = true;
+ if (d_ptr->m_multiHighlightGradient != gradient) {
+ d_ptr->m_multiHighlightGradient = gradient;
+ emit multiHighlightGradientChanged(gradient);
+ }
+}
+
+QLinearGradient Q3DTheme::multiHighlightGradient() const
+{
+ return d_ptr->m_multiHighlightGradient;
+}
+
+/*!
+ * \property Q3DTheme::lightStrength
+ *
+ * Specular light strength for the whole graph. Value must be 0.0f and 10.0f.
+ */
+void Q3DTheme::setLightStrength(float strength)
+{
+ d_ptr->m_dirtyBits.lightStrengthDirty = true;
+ if (strength < 0.0f || strength > 10.0f) {
+ qWarning("Invalid value. Valid range for lightStrength is between 0.0f and 10.0f");
+ } else if (d_ptr->m_lightStrength != strength) {
+ d_ptr->m_lightStrength = strength;
+ emit lightStrengthChanged(strength);
+ emit d_ptr->needRender();
+ }
+}
+
+float Q3DTheme::lightStrength() const
+{
+ return d_ptr->m_lightStrength;
+}
+
+/*!
+ * \property Q3DTheme::ambientLightStrength
+ *
+ * Ambient light strength for the whole graph. Value must be between 0.0f and 1.0f.
+ */
+void Q3DTheme::setAmbientLightStrength(float strength)
+{
+ d_ptr->m_dirtyBits.ambientLightStrengthDirty = true;
+ if (strength < 0.0f || strength > 1.0f) {
+ qWarning("Invalid value. Valid range for ambientLightStrength is between 0.0f and 1.0f");
+ } else if (d_ptr->m_ambientLightStrength != strength) {
+ d_ptr->m_ambientLightStrength = strength;
+ emit ambientLightStrengthChanged(strength);
+ emit d_ptr->needRender();
+ }
+}
+
+float Q3DTheme::ambientLightStrength() const
+{
+ return d_ptr->m_ambientLightStrength;
+}
+
+/*!
+ * \property Q3DTheme::highlightLightStrength
+ *
+ * Specular light strength for highlighted objects. Value must be between 0.0f and 10.0f.
+ */
+void Q3DTheme::setHighlightLightStrength(float strength)
+{
+ d_ptr->m_dirtyBits.highlightLightStrengthDirty = true;
+ if (strength < 0.0f || strength > 10.0f) {
+ qWarning("Invalid value. Valid range for highlightLightStrength is between 0.0f and 10.0f");
+ } else if (d_ptr->m_highlightLightStrength != strength) {
+ d_ptr->m_highlightLightStrength = strength;
+ emit highlightLightStrengthChanged(strength);
+ emit d_ptr->needRender();
+ }
+}
+
+float Q3DTheme::highlightLightStrength() const
+{
+ return d_ptr->m_highlightLightStrength;
+}
+
+/*!
+ * \property Q3DTheme::labelBorderEnabled
+ *
+ * Set label borders enabled or disabled. Has no effect if labelBackgroundEnabled is \c false.
+ */
+void Q3DTheme::setLabelBorderEnabled(bool enabled)
+{
+ d_ptr->m_dirtyBits.labelBorderEnabledDirty = true;
+ if (d_ptr->m_labelBorders != enabled) {
+ d_ptr->m_labelBorders = enabled;
+ emit labelBorderEnabledChanged(enabled);
+ emit d_ptr->needRender();
+ }
+}
+
+bool Q3DTheme::isLabelBorderEnabled() const
+{
+ return d_ptr->m_labelBorders;
+}
+
+/*!
+ * \property Q3DTheme::font
+ *
+ * Set \a font to be used for labels.
+ */
+void Q3DTheme::setFont(const QFont &font)
+{
+ d_ptr->m_dirtyBits.fontDirty = true;
+ if (d_ptr->m_font != font) {
+ d_ptr->m_font = font;
+ emit fontChanged(font);
+ emit d_ptr->needRender();
+ }
+}
+
+QFont Q3DTheme::font() const
+{
+ return d_ptr->m_font;
+}
+
+/*!
+ * \property Q3DTheme::backgroundEnabled
+ *
+ * Set background enabled or disabled.
+ */
+void Q3DTheme::setBackgroundEnabled(bool enabled)
+{
+ d_ptr->m_dirtyBits.backgroundEnabledDirty = true;
+ if (d_ptr->m_backgoundEnabled != enabled) {
+ d_ptr->m_backgoundEnabled = enabled;
+ emit backgroundEnabledChanged(enabled);
+ emit d_ptr->needRender();
+ }
+}
+
+bool Q3DTheme::isBackgroundEnabled() const
+{
+ return d_ptr->m_backgoundEnabled;
+}
+
+/*!
+ * \property Q3DTheme::gridEnabled
+ *
+ * Set grid lines enabled or disabled.
+ */
+void Q3DTheme::setGridEnabled(bool enabled)
+{
+ d_ptr->m_dirtyBits.gridEnabledDirty = true;
+ if (d_ptr->m_gridEnabled != enabled) {
+ d_ptr->m_gridEnabled = enabled;
+ emit gridEnabledChanged(enabled);
+ emit d_ptr->needRender();
+ }
+}
+
+bool Q3DTheme::isGridEnabled() const
+{
+ return d_ptr->m_gridEnabled;
+}
+
+/*!
+ * \property Q3DTheme::labelBackgroundEnabled
+ *
+ * Set label backgrounds enabled or disabled.
+ */
+void Q3DTheme::setLabelBackgroundEnabled(bool enabled)
+{
+ d_ptr->m_dirtyBits.labelBackgroundEnabledDirty = true;
+ if (d_ptr->m_labelBackground != enabled) {
+ d_ptr->m_labelBackground = enabled;
+ emit labelBackgroundEnabledChanged(enabled);
+ emit d_ptr->needRender();
+ }
+}
+
+bool Q3DTheme::isLabelBackgroundEnabled() const
+{
+ return d_ptr->m_labelBackground;
+}
+
+/*!
+ * \property Q3DTheme::colorStyle
+ *
+ * The \a style of the graph colors. One of ColorStyle.
+ */
+void Q3DTheme::setColorStyle(ColorStyle style)
+{
+ d_ptr->m_dirtyBits.colorStyleDirty = true;
+ if (d_ptr->m_colorStyle != style) {
+ d_ptr->m_colorStyle = style;
+ emit colorStyleChanged(style);
+ }
+}
+
+Q3DTheme::ColorStyle Q3DTheme::colorStyle() const
+{
+ return d_ptr->m_colorStyle;
+}
+
+/*!
+ * \property Q3DTheme::type
+ *
+ * The type of the theme. Type is automatically set when constructing a theme. User should not
+ * need to use this when using C++ API.
+ */
+void Q3DTheme::setType(Theme themeType)
+{
+ d_ptr->m_dirtyBits.themeIdDirty = true;
+ if (d_ptr->m_themeId != themeType) {
+ d_ptr->m_themeId = themeType;
+ emit typeChanged(themeType);
+ }
+}
+
+Q3DTheme::Theme Q3DTheme::type() const
+{
+ return d_ptr->m_themeId;
+}
+
+// Q3DThemePrivate
+
+Q3DThemePrivate::Q3DThemePrivate(Q3DTheme *q, Q3DTheme::Theme theme_id)
+ : QObject(0),
+ m_themeId(theme_id),
+ m_backgroundColor(Qt::black),
+ m_windowColor(Qt::black),
+ m_textColor(Qt::white),
+ m_textBackgroundColor(Qt::gray),
+ m_gridLineColor(Qt::white),
+ m_singleHighlightColor(Qt::red),
+ m_multiHighlightColor(Qt::blue),
+ m_lightColor(Qt::white),
+ m_singleHighlightGradient(QLinearGradient(qreal(gradientTextureWidth),
+ qreal(gradientTextureHeight),
+ 0.0, 0.0)),
+ m_multiHighlightGradient(QLinearGradient(qreal(gradientTextureWidth),
+ qreal(gradientTextureHeight),
+ 0.0, 0.0)),
+ m_lightStrength(5.0f),
+ m_ambientLightStrength(0.25f),
+ m_highlightLightStrength(7.5f),
+ m_labelBorders(true),
+ m_colorStyle(Q3DTheme::ColorStyleUniform),
+ m_font(QFont()),
+ m_backgoundEnabled(true),
+ m_gridEnabled(true),
+ m_labelBackground(true),
+ q_ptr(q)
+{
+ m_baseColors.append(QColor(Qt::black));
+ m_baseGradients.append(QLinearGradient(qreal(gradientTextureWidth),
+ qreal(gradientTextureHeight),
+ 0.0, 0.0));
+}
+
+Q3DThemePrivate::~Q3DThemePrivate()
+{
+}
+
+void Q3DThemePrivate::resetDirtyBits()
+{
+ m_dirtyBits.ambientLightStrengthDirty = true;
+ m_dirtyBits.backgroundColorDirty = true;
+ m_dirtyBits.backgroundEnabledDirty = true;
+ m_dirtyBits.baseColorDirty = true;
+ m_dirtyBits.baseGradientDirty = true;
+ m_dirtyBits.colorStyleDirty = true;
+ m_dirtyBits.fontDirty = true;
+ m_dirtyBits.gridEnabledDirty = true;
+ m_dirtyBits.gridLineColorDirty = true;
+ m_dirtyBits.highlightLightStrengthDirty = true;
+ m_dirtyBits.labelBackgroundColorDirty = true;
+ m_dirtyBits.labelBackgroundEnabledDirty = true;
+ m_dirtyBits.labelBorderEnabledDirty = true;
+ m_dirtyBits.labelTextColorDirty = true;
+ m_dirtyBits.lightColorDirty = true;
+ m_dirtyBits.lightStrengthDirty = true;
+ m_dirtyBits.multiHighlightColorDirty = true;
+ m_dirtyBits.multiHighlightGradientDirty = true;
+ m_dirtyBits.singleHighlightColorDirty = true;
+ m_dirtyBits.singleHighlightGradientDirty = true;
+ m_dirtyBits.themeIdDirty = true;
+ m_dirtyBits.windowColorDirty = true;
+}
+
+bool Q3DThemePrivate::sync(Q3DThemePrivate &other)
+{
+ bool changed = false;
+ if (m_dirtyBits.ambientLightStrengthDirty) {
+ other.q_ptr->setAmbientLightStrength(m_ambientLightStrength);
+ m_dirtyBits.ambientLightStrengthDirty = false;
+ changed = true;
+ }
+ if (m_dirtyBits.backgroundColorDirty) {
+ other.q_ptr->setBackgroundColor(m_backgroundColor);
+ m_dirtyBits.backgroundColorDirty = false;
+ changed = true;
+ }
+ if (m_dirtyBits.backgroundEnabledDirty) {
+ other.q_ptr->setBackgroundEnabled(m_backgoundEnabled);
+ m_dirtyBits.backgroundEnabledDirty = false;
+ changed = true;
+ }
+ if (m_dirtyBits.baseColorDirty) {
+ other.q_ptr->setBaseColors(m_baseColors);
+ m_dirtyBits.baseColorDirty = false;
+ changed = true;
+ }
+ if (m_dirtyBits.baseGradientDirty) {
+ other.q_ptr->setBaseGradients(m_baseGradients);
+ m_dirtyBits.baseGradientDirty = false;
+ changed = true;
+ }
+ if (m_dirtyBits.colorStyleDirty) {
+ other.q_ptr->setColorStyle(m_colorStyle);
+ m_dirtyBits.colorStyleDirty = false;
+ changed = true;
+ }
+ if (m_dirtyBits.fontDirty) {
+ other.q_ptr->setFont(m_font);
+ m_dirtyBits.fontDirty = false;
+ changed = true;
+ }
+ if (m_dirtyBits.gridEnabledDirty) {
+ other.q_ptr->setGridEnabled(m_gridEnabled);
+ m_dirtyBits.gridEnabledDirty = false;
+ changed = true;
+ }
+ if (m_dirtyBits.gridLineColorDirty) {
+ other.q_ptr->setGridLineColor(m_gridLineColor);
+ m_dirtyBits.gridLineColorDirty = false;
+ changed = true;
+ }
+ if (m_dirtyBits.highlightLightStrengthDirty) {
+ other.q_ptr->setHighlightLightStrength(m_highlightLightStrength);
+ m_dirtyBits.highlightLightStrengthDirty = false;
+ changed = true;
+ }
+ if (m_dirtyBits.labelBackgroundColorDirty) {
+ other.q_ptr->setLabelBackgroundColor(m_textBackgroundColor);
+ m_dirtyBits.labelBackgroundColorDirty = false;
+ changed = true;
+ }
+ if (m_dirtyBits.labelBackgroundEnabledDirty) {
+ other.q_ptr->setLabelBackgroundEnabled(m_labelBackground);
+ m_dirtyBits.labelBackgroundEnabledDirty = false;
+ changed = true;
+ }
+ if (m_dirtyBits.labelBorderEnabledDirty) {
+ other.q_ptr->setLabelBorderEnabled(m_labelBorders);
+ m_dirtyBits.labelBorderEnabledDirty = false;
+ changed = true;
+ }
+ if (m_dirtyBits.labelTextColorDirty) {
+ other.q_ptr->setLabelTextColor(m_textColor);
+ m_dirtyBits.labelTextColorDirty = false;
+ changed = true;
+ }
+ if (m_dirtyBits.lightColorDirty) {
+ other.q_ptr->setLightColor(m_lightColor);
+ m_dirtyBits.lightColorDirty = false;
+ changed = true;
+ }
+ if (m_dirtyBits.lightStrengthDirty) {
+ other.q_ptr->setLightStrength(m_lightStrength);
+ m_dirtyBits.lightStrengthDirty = false;
+ changed = true;
+ }
+ if (m_dirtyBits.multiHighlightColorDirty) {
+ other.q_ptr->setMultiHighlightColor(m_multiHighlightColor);
+ m_dirtyBits.multiHighlightColorDirty = false;
+ changed = true;
+ }
+ if (m_dirtyBits.multiHighlightGradientDirty) {
+ other.q_ptr->setMultiHighlightGradient(m_multiHighlightGradient);
+ m_dirtyBits.multiHighlightGradientDirty = false;
+ changed = true;
+ }
+ if (m_dirtyBits.singleHighlightColorDirty) {
+ other.q_ptr->setSingleHighlightColor(m_singleHighlightColor);
+ m_dirtyBits.singleHighlightColorDirty = false;
+ changed = true;
+ }
+ if (m_dirtyBits.singleHighlightGradientDirty) {
+ other.q_ptr->setSingleHighlightGradient(m_singleHighlightGradient);
+ m_dirtyBits.singleHighlightGradientDirty = false;
+ changed = true;
+ }
+ if (m_dirtyBits.themeIdDirty) {
+ other.m_themeId = m_themeId; // Set directly to avoid a call to ThemeManager's useTheme()
+ m_dirtyBits.themeIdDirty = false;
+ changed = true;
+ }
+ if (m_dirtyBits.windowColorDirty) {
+ other.q_ptr->setWindowColor(m_windowColor);
+ m_dirtyBits.windowColorDirty = false;
+ changed = true;
+ }
+ return changed;
+}
+
+QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/theme/q3dtheme.h b/src/datavisualization/theme/q3dtheme.h
new file mode 100644
index 00000000..44e58e5d
--- /dev/null
+++ b/src/datavisualization/theme/q3dtheme.h
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#ifndef Q3DTHEME_H
+#define Q3DTHEME_H
+
+#include <QtDataVisualization/qdatavisualizationenums.h>
+#include <QLinearGradient>
+#include <QFont>
+#include <QColor>
+
+QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
+class Q3DThemePrivate;
+
+class QT_DATAVISUALIZATION_EXPORT Q3DTheme : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(ColorStyle)
+ Q_ENUMS(Theme)
+ Q_PROPERTY(Theme type READ type WRITE setType NOTIFY typeChanged)
+ Q_PROPERTY(QList<QColor> baseColors READ baseColors WRITE setBaseColors NOTIFY baseColorsChanged)
+ Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor NOTIFY backgroundColorChanged)
+ Q_PROPERTY(QColor windowColor READ windowColor WRITE setWindowColor NOTIFY windowColorChanged)
+ Q_PROPERTY(QColor labelTextColor READ labelTextColor WRITE setLabelTextColor NOTIFY labelTextColorChanged)
+ Q_PROPERTY(QColor labelBackgroundColor READ labelBackgroundColor WRITE setLabelBackgroundColor NOTIFY labelBackgroundColorChanged)
+ Q_PROPERTY(QColor gridLineColor READ gridLineColor WRITE setGridLineColor NOTIFY gridLineColorChanged)
+ Q_PROPERTY(QColor singleHighlightColor READ singleHighlightColor WRITE setSingleHighlightColor NOTIFY singleHighlightColorChanged)
+ Q_PROPERTY(QColor multiHighlightColor READ multiHighlightColor WRITE setMultiHighlightColor NOTIFY multiHighlightColorChanged)
+ Q_PROPERTY(QColor lightColor READ lightColor WRITE setLightColor NOTIFY lightColorChanged) // TODO: Not used yet
+ Q_PROPERTY(QList<QLinearGradient> baseGradients READ baseGradients WRITE setBaseGradients NOTIFY baseGradientsChanged)
+ Q_PROPERTY(QLinearGradient singleHighlightGradient READ singleHighlightGradient WRITE setSingleHighlightGradient NOTIFY singleHighlightGradientChanged)
+ Q_PROPERTY(QLinearGradient multiHighlightGradient READ multiHighlightGradient WRITE setMultiHighlightGradient NOTIFY multiHighlightGradientChanged)
+ Q_PROPERTY(float lightStrength READ lightStrength WRITE setLightStrength NOTIFY lightStrengthChanged)
+ Q_PROPERTY(float ambientLightStrength READ ambientLightStrength WRITE setAmbientLightStrength NOTIFY ambientLightStrengthChanged)
+ Q_PROPERTY(float highlightLightStrength READ highlightLightStrength WRITE setHighlightLightStrength NOTIFY highlightLightStrengthChanged)
+ Q_PROPERTY(bool labelBorderEnabled READ isLabelBorderEnabled WRITE setLabelBorderEnabled NOTIFY labelBorderEnabledChanged)
+ Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
+ Q_PROPERTY(bool backgroundEnabled READ isBackgroundEnabled WRITE setBackgroundEnabled NOTIFY backgroundEnabledChanged)
+ Q_PROPERTY(bool gridEnabled READ isGridEnabled WRITE setGridEnabled NOTIFY gridEnabledChanged)
+ Q_PROPERTY(bool labelBackgroundEnabled READ isLabelBackgroundEnabled WRITE setLabelBackgroundEnabled NOTIFY labelBackgroundEnabledChanged)
+ Q_PROPERTY(ColorStyle colorStyle READ colorStyle WRITE setColorStyle NOTIFY colorStyleChanged)
+ // TODO: Add everything we need (specularIntensity, lightDegradation, shaders?)
+
+public:
+ enum ColorStyle {
+ ColorStyleUniform = 0,
+ ColorStyleObjectGradient,
+ ColorStyleRangeGradient
+ };
+
+ enum Theme {
+ ThemeQt,
+ ThemePrimaryColors,
+ ThemeDigia,
+ ThemeStoneMoss,
+ ThemeArmyBlue,
+ ThemeRetro,
+ ThemeEbony,
+ ThemeIsabelle,
+ ThemeUserDefined
+ };
+
+public:
+ explicit Q3DTheme(QObject *parent = 0);
+ explicit Q3DTheme(Theme themeType, QObject *parent = 0);
+ virtual ~Q3DTheme();
+
+ void setType(Theme themeType);
+ Theme type() const;
+
+ void setBaseColors(const QList<QColor> &colors);
+ QList<QColor> baseColors() const;
+
+ void setBackgroundColor(const QColor &color);
+ QColor backgroundColor() const;
+
+ void setWindowColor(const QColor &color);
+ QColor windowColor() const;
+
+ void setLabelTextColor(const QColor &color);
+ QColor labelTextColor() const;
+
+ void setLabelBackgroundColor(const QColor &color);
+ QColor labelBackgroundColor() const;
+
+ void setGridLineColor(const QColor &color);
+ QColor gridLineColor() const;
+
+ void setSingleHighlightColor(const QColor &color);
+ QColor singleHighlightColor() const;
+
+ void setMultiHighlightColor(const QColor &color);
+ QColor multiHighlightColor() const;
+
+ void setLightColor(const QColor &color);
+ QColor lightColor() const;
+
+ void setBaseGradients(const QList<QLinearGradient> &gradients);
+ QList<QLinearGradient> baseGradients() const;
+
+ void setSingleHighlightGradient(const QLinearGradient &gradient);
+ QLinearGradient singleHighlightGradient() const;
+
+ void setMultiHighlightGradient(const QLinearGradient &gradient);
+ QLinearGradient multiHighlightGradient() const;
+
+ void setLightStrength(float strength);
+ float lightStrength() const;
+
+ void setAmbientLightStrength(float strength);
+ float ambientLightStrength() const;
+
+ void setHighlightLightStrength(float strength);
+ float highlightLightStrength() const;
+
+ void setLabelBorderEnabled(bool enabled);
+ bool isLabelBorderEnabled() const;
+
+ void setFont(const QFont &font);
+ QFont font() const;
+
+ void setBackgroundEnabled(bool enabled);
+ bool isBackgroundEnabled() const;
+
+ void setGridEnabled(bool enabled);
+ bool isGridEnabled() const;
+
+ void setLabelBackgroundEnabled(bool enabled);
+ bool isLabelBackgroundEnabled() const;
+
+ void setColorStyle(ColorStyle style);
+ ColorStyle colorStyle() const;
+
+signals:
+ void typeChanged(Theme themeType);
+ void baseColorsChanged(QList<QColor> colors);
+ void backgroundColorChanged(QColor color);
+ void windowColorChanged(QColor color);
+ void labelTextColorChanged(QColor color);
+ void labelBackgroundColorChanged(QColor color);
+ void gridLineColorChanged(QColor color);
+ void singleHighlightColorChanged(QColor color);
+ void multiHighlightColorChanged(QColor color);
+ void lightColorChanged(QColor color);
+ void baseGradientsChanged(QList<QLinearGradient> gradients);
+ void singleHighlightGradientChanged(QLinearGradient gradient);
+ void multiHighlightGradientChanged(QLinearGradient gradient);
+ void lightStrengthChanged(float strength);
+ void ambientLightStrengthChanged(float strength);
+ void highlightLightStrengthChanged(float strength);
+ void labelBorderEnabledChanged(bool enabled);
+ void fontChanged(QFont font);
+ void backgroundEnabledChanged(bool enabled);
+ void gridEnabledChanged(bool enabled);
+ void labelBackgroundEnabledChanged(bool enabled);
+ void colorStyleChanged(ColorStyle style);
+
+protected:
+ explicit Q3DTheme(Q3DThemePrivate *d, Theme themeType, QObject *parent = 0);
+ QScopedPointer<Q3DThemePrivate> d_ptr;
+
+ friend class ThemeManager;
+ friend class Abstract3DRenderer;
+ friend class Bars3DController;
+
+private:
+ Q_DISABLE_COPY(Q3DTheme)
+};
+
+QT_DATAVISUALIZATION_END_NAMESPACE
+
+#endif
diff --git a/src/datavisualization/theme/q3dtheme_p.h b/src/datavisualization/theme/q3dtheme_p.h
new file mode 100644
index 00000000..c9f59d99
--- /dev/null
+++ b/src/datavisualization/theme/q3dtheme_p.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the QtDataVisualization API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Q3DTHEME_P_H
+#define Q3DTHEME_P_H
+
+#include "datavisualizationglobal_p.h"
+#include "q3dtheme.h"
+
+QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
+struct Q3DThemeDirtyBitField {
+ bool baseColorDirty : 1;
+ bool backgroundColorDirty : 1;
+ bool windowColorDirty : 1;
+ bool labelTextColorDirty : 1;
+ bool labelBackgroundColorDirty : 1;
+ bool gridLineColorDirty : 1;
+ bool singleHighlightColorDirty : 1;
+ bool multiHighlightColorDirty : 1;
+ bool lightColorDirty : 1;
+ bool baseGradientDirty : 1;
+ bool singleHighlightGradientDirty : 1;
+ bool multiHighlightGradientDirty : 1;
+ bool lightStrengthDirty : 1;
+ bool ambientLightStrengthDirty : 1;
+ bool highlightLightStrengthDirty : 1;
+ bool labelBorderEnabledDirty : 1;
+ bool colorStyleDirty : 1;
+ bool fontDirty : 1;
+ bool backgroundEnabledDirty : 1;
+ bool gridEnabledDirty : 1;
+ bool labelBackgroundEnabledDirty : 1;
+ bool themeIdDirty : 1;
+
+ Q3DThemeDirtyBitField()
+ : baseColorDirty(false),
+ backgroundColorDirty(false),
+ windowColorDirty(false),
+ labelTextColorDirty(false),
+ labelBackgroundColorDirty(false),
+ gridLineColorDirty(false),
+ singleHighlightColorDirty(false),
+ multiHighlightColorDirty(false),
+ lightColorDirty(false),
+ baseGradientDirty(false),
+ singleHighlightGradientDirty(false),
+ multiHighlightGradientDirty(false),
+ lightStrengthDirty(false),
+ ambientLightStrengthDirty(false),
+ highlightLightStrengthDirty(false),
+ labelBorderEnabledDirty(false),
+ colorStyleDirty(false),
+ fontDirty(false),
+ backgroundEnabledDirty(false),
+ gridEnabledDirty(false),
+ labelBackgroundEnabledDirty(false),
+ themeIdDirty(false)
+ {
+ }
+};
+
+class Q3DThemePrivate : public QObject
+{
+ Q_OBJECT
+public:
+ Q3DThemePrivate(Q3DTheme *q,
+ Q3DTheme::Theme theme_id = Q3DTheme::ThemeUserDefined);
+ virtual ~Q3DThemePrivate();
+
+ void resetDirtyBits();
+
+ bool sync(Q3DThemePrivate &other);
+
+signals:
+ void needRender();
+
+public:
+ Q3DTheme::Theme m_themeId;
+
+ Q3DThemeDirtyBitField m_dirtyBits;
+
+ QList<QColor> m_baseColors;
+ QColor m_backgroundColor;
+ QColor m_windowColor;
+ QColor m_textColor;
+ QColor m_textBackgroundColor;
+ QColor m_gridLineColor;
+ QColor m_singleHighlightColor;
+ QColor m_multiHighlightColor;
+ QColor m_lightColor;
+ QList<QLinearGradient> m_baseGradients;
+ QLinearGradient m_singleHighlightGradient;
+ QLinearGradient m_multiHighlightGradient;
+ float m_lightStrength;
+ float m_ambientLightStrength;
+ float m_highlightLightStrength;
+ bool m_labelBorders;
+ Q3DTheme::ColorStyle m_colorStyle;
+ QFont m_font;
+ bool m_backgoundEnabled;
+ bool m_gridEnabled;
+ bool m_labelBackground;
+
+protected:
+ Q3DTheme *q_ptr;
+};
+
+QT_DATAVISUALIZATION_END_NAMESPACE
+
+#endif
diff --git a/src/datavisualization/theme/theme.pri b/src/datavisualization/theme/theme.pri
new file mode 100644
index 00000000..1de3035a
--- /dev/null
+++ b/src/datavisualization/theme/theme.pri
@@ -0,0 +1,8 @@
+HEADERS += \
+ $$PWD/q3dtheme.h \
+ $$PWD/q3dtheme_p.h \
+ $$PWD/thememanager_p.h
+
+SOURCES += \
+ $$PWD/q3dtheme.cpp \
+ $$PWD/thememanager.cpp
diff --git a/src/datavisualization/theme/thememanager.cpp b/src/datavisualization/theme/thememanager.cpp
new file mode 100644
index 00000000..cc5362ef
--- /dev/null
+++ b/src/datavisualization/theme/thememanager.cpp
@@ -0,0 +1,552 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#include "thememanager_p.h"
+#include "q3dtheme_p.h"
+
+QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
+const float defaultBuiltInColorLevel = 0.7f; // for built-in gradient themes
+const float defaultColorLevel = 0.5f; // for built-in uniform themes
+
+ThemeManager::ThemeManager(Abstract3DController *controller)
+ : m_theme(0),
+ m_controller(controller)
+{
+}
+
+ThemeManager::~ThemeManager()
+{
+}
+
+void ThemeManager::setTheme(Q3DTheme *theme)
+{
+ if (!theme)
+ return;
+
+ if (m_theme.data() != theme) {
+ // Disconnect old theme signal connections
+ if (m_theme) {
+ disconnect(m_theme->d_ptr.data(), 0, m_controller, 0);
+ disconnect(m_theme.data(), 0, m_controller, 0);
+ disconnect(m_theme.data(), 0, this, 0);
+ }
+
+ m_theme.reset(theme);
+
+ Q3DTheme::Theme type = m_theme->type();
+
+ if (type != Q3DTheme::ThemeUserDefined) {
+ useTheme(type);
+ // Reset all bits to dirty for sync
+ m_theme->d_ptr->resetDirtyBits();
+ }
+
+ // Connect signals from new one
+ connectThemeSignals();
+ }
+}
+
+Q3DTheme *ThemeManager::theme() const
+{
+ return m_theme.data();
+}
+
+void ThemeManager::connectThemeSignals()
+{
+ connect(m_theme.data(), &Q3DTheme::colorStyleChanged,
+ m_controller, &Abstract3DController::handleThemeColorStyleChanged);
+ connect(m_theme.data(), &Q3DTheme::baseColorsChanged,
+ m_controller, &Abstract3DController::handleThemeBaseColorsChanged);
+ connect(m_theme.data(), &Q3DTheme::singleHighlightColorChanged,
+ m_controller, &Abstract3DController::handleThemeSingleHighlightColorChanged);
+ connect(m_theme.data(), &Q3DTheme::multiHighlightColorChanged,
+ m_controller, &Abstract3DController::handleThemeMultiHighlightColorChanged);
+ connect(m_theme.data(), &Q3DTheme::baseGradientsChanged,
+ m_controller, &Abstract3DController::handleThemeBaseGradientsChanged);
+ connect(m_theme.data(), &Q3DTheme::singleHighlightGradientChanged,
+ m_controller, &Abstract3DController::handleThemeSingleHighlightGradientChanged);
+ connect(m_theme.data(), &Q3DTheme::multiHighlightGradientChanged,
+ m_controller, &Abstract3DController::handleThemeMultiHighlightGradientChanged);
+
+ connect(m_theme->d_ptr.data(), &Q3DThemePrivate::needRender,
+ m_controller, &Abstract3DController::needRender);
+
+ connect(m_theme.data(), &Q3DTheme::typeChanged, this, &ThemeManager::useTheme);
+}
+
+void ThemeManager::useTheme(Q3DTheme::Theme type)
+{
+ switch (type) {
+ case Q3DTheme::ThemeQt: {
+ QList<QColor> baseColors;
+ baseColors.append(QColor(QRgb(0x80c342)));
+ baseColors.append(QColor(QRgb(0x469835)));
+ baseColors.append(QColor(QRgb(0x006325)));
+ baseColors.append(QColor(QRgb(0x5caa15)));
+ baseColors.append(QColor(QRgb(0x328930)));
+
+ QList<QLinearGradient> baseGradients;
+ baseGradients.append(createGradient(baseColors.at(0), defaultColorLevel));
+ baseGradients.append(createGradient(baseColors.at(1), defaultColorLevel));
+ baseGradients.append(createGradient(baseColors.at(2), defaultColorLevel));
+ baseGradients.append(createGradient(baseColors.at(3), defaultColorLevel));
+ baseGradients.append(createGradient(baseColors.at(4), defaultColorLevel));
+
+ setBackgroundEnabled(true);
+ setGridEnabled(true);
+ setFont(QFont(QStringLiteral("Arial")));
+ setLabelBackgroundEnabled(true);
+ setLightColor(Qt::white);
+ setBaseColors(baseColors);
+ setBackgroundColor(QColor(QRgb(0xffffff)));
+ setWindowColor(QColor(QRgb(0xffffff)));
+ setTextColor(QColor(QRgb(0x35322f)));
+ setTextBackgroundColor(QColor(0xff, 0xff, 0xff, 0x99));
+ setGridLineColor(QColor(QRgb(0xd7d6d5)));
+ setSingleHighlightColor(QColor(QRgb(0x14aaff)));
+ setMultiHighlightColor(QColor(QRgb(0x6400aa)));
+ setLightStrength(5.0f);
+ setAmbientLightStrength(0.5f);
+ setHighlightLightStrength(5.0f);
+ setLabelBorderEnabled(true);
+ setColorStyle(Q3DTheme::ColorStyleUniform);
+ setBaseGradients(baseGradients);
+ setSingleHighlightGradient(createGradient(QColor(QRgb(0x14aaff)), defaultColorLevel));
+ setMultiHighlightGradient(createGradient(QColor(QRgb(0x6400aa)), defaultColorLevel));
+ break;
+ }
+
+ case Q3DTheme::ThemePrimaryColors: {
+ QList<QColor> baseColors;
+ baseColors.append(QColor(QRgb(0xffe400)));
+ baseColors.append(QColor(QRgb(0xfaa106)));
+ baseColors.append(QColor(QRgb(0xf45f0d)));
+ baseColors.append(QColor(QRgb(0xfcba04)));
+ baseColors.append(QColor(QRgb(0xf7800a)));
+
+ QList<QLinearGradient> baseGradients;
+ baseGradients.append(createGradient(baseColors.at(0), defaultColorLevel));
+ baseGradients.append(createGradient(baseColors.at(1), defaultColorLevel));
+ baseGradients.append(createGradient(baseColors.at(2), defaultColorLevel));
+ baseGradients.append(createGradient(baseColors.at(3), defaultColorLevel));
+ baseGradients.append(createGradient(baseColors.at(4), defaultColorLevel));
+
+ setBackgroundEnabled(true);
+ setGridEnabled(true);
+ setFont(QFont(QStringLiteral("Arial")));
+ setLabelBackgroundEnabled(true);
+ setLightColor(Qt::white);
+ setBaseColors(baseColors);
+ setBackgroundColor(QColor(QRgb(0xffffff)));
+ setWindowColor(QColor(QRgb(0xffffff)));
+ setTextColor(QColor(QRgb(0x000000)));
+ setTextBackgroundColor(QColor(0xff, 0xff, 0xff, 0x99));
+ setGridLineColor(QColor(QRgb(0xd7d6d5)));
+ setSingleHighlightColor(QColor(QRgb(0x27beee)));
+ setMultiHighlightColor(QColor(QRgb(0xee1414)));
+ setLightStrength(5.0f);
+ setAmbientLightStrength(0.5f);
+ setHighlightLightStrength(5.0f);
+ setLabelBorderEnabled(false);
+ setColorStyle(Q3DTheme::ColorStyleUniform);
+ setBaseGradients(baseGradients);
+ setSingleHighlightGradient(createGradient(QColor(QRgb(0x27beee)), defaultColorLevel));
+ setMultiHighlightGradient(createGradient(QColor(QRgb(0xee1414)), defaultColorLevel));
+ break;
+ }
+
+ case Q3DTheme::ThemeDigia: {
+ QList<QColor> baseColors;
+ baseColors.append(QColor(QRgb(0xeaeaea)));
+ baseColors.append(QColor(QRgb(0xa0a0a0)));
+ baseColors.append(QColor(QRgb(0x626262)));
+ baseColors.append(QColor(QRgb(0xbebebe)));
+ baseColors.append(QColor(QRgb(0x818181)));
+
+ QList<QLinearGradient> baseGradients;
+ baseGradients.append(createGradient(baseColors.at(0), defaultBuiltInColorLevel));
+ baseGradients.append(createGradient(baseColors.at(1), defaultBuiltInColorLevel));
+ baseGradients.append(createGradient(baseColors.at(2), defaultBuiltInColorLevel));
+ baseGradients.append(createGradient(baseColors.at(3), defaultBuiltInColorLevel));
+ baseGradients.append(createGradient(baseColors.at(4), defaultBuiltInColorLevel));
+
+ setBackgroundEnabled(true);
+ setGridEnabled(true);
+ setFont(QFont(QStringLiteral("Arial")));
+ setLabelBackgroundEnabled(true);
+ setLightColor(Qt::white);
+ setBaseColors(baseColors);
+ setBackgroundColor(QColor(QRgb(0xffffff)));
+ setWindowColor(QColor(QRgb(0xffffff)));
+ setTextColor(QColor(QRgb(0x000000)));
+ setTextBackgroundColor(QColor(0xff, 0xff, 0xff, 0x80));
+ setGridLineColor(QColor(QRgb(0xd7d6d5)));
+ setSingleHighlightColor(QColor(QRgb(0xfa0000)));
+ setMultiHighlightColor(QColor(QRgb(0x333333)));
+ setLightStrength(5.0f);
+ setAmbientLightStrength(0.5f);
+ setHighlightLightStrength(5.0f);
+ setLabelBorderEnabled(false);
+ setColorStyle(Q3DTheme::ColorStyleObjectGradient);
+ setBaseGradients(baseGradients);
+ setSingleHighlightGradient(createGradient(QColor(QRgb(0xfa0000)), defaultBuiltInColorLevel));
+ setMultiHighlightGradient(createGradient(QColor(QRgb(0x333333)), defaultBuiltInColorLevel));
+ break;
+ }
+
+ case Q3DTheme::ThemeStoneMoss: {
+ QList<QColor> baseColors;
+ baseColors.append(QColor(QRgb(0xbeb32b)));
+ baseColors.append(QColor(QRgb(0x928327)));
+ baseColors.append(QColor(QRgb(0x665423)));
+ baseColors.append(QColor(QRgb(0xa69929)));
+ baseColors.append(QColor(QRgb(0x7c6c25)));
+
+ QList<QLinearGradient> baseGradients;
+ baseGradients.append(createGradient(baseColors.at(0), defaultColorLevel));
+ baseGradients.append(createGradient(baseColors.at(1), defaultColorLevel));
+ baseGradients.append(createGradient(baseColors.at(2), defaultColorLevel));
+ baseGradients.append(createGradient(baseColors.at(3), defaultColorLevel));
+ baseGradients.append(createGradient(baseColors.at(4), defaultColorLevel));
+
+ setBackgroundEnabled(true);
+ setGridEnabled(true);
+ setFont(QFont(QStringLiteral("Arial")));
+ setLabelBackgroundEnabled(true);
+ setLightColor(Qt::white);
+ setBaseColors(baseColors);
+ setBackgroundColor(QColor(QRgb(0x4d4d4f)));
+ setWindowColor(QColor(QRgb(0x4d4d4f)));
+ setTextColor(QColor(QRgb(0xffffff)));
+ setTextBackgroundColor(QColor(0x4d, 0x4d, 0x4f, 0xcd));
+ setGridLineColor(QColor(QRgb(0x3e3e40)));
+ setSingleHighlightColor(QColor(QRgb(0xfbf6d6)));
+ setMultiHighlightColor(QColor(QRgb(0x442f20)));
+ setLightStrength(5.0f);
+ setAmbientLightStrength(0.5f);
+ setHighlightLightStrength(5.0f);
+ setLabelBorderEnabled(true);
+ setColorStyle(Q3DTheme::ColorStyleUniform);
+ setBaseGradients(baseGradients);
+ setSingleHighlightGradient(createGradient(QColor(QRgb(0xfbf6d6)), defaultColorLevel));
+ setMultiHighlightGradient(createGradient(QColor(QRgb(0x442f20)), defaultColorLevel));
+ break;
+ }
+
+ case Q3DTheme::ThemeArmyBlue: {
+ QList<QColor> baseColors;
+ baseColors.append(QColor(QRgb(0x495f76)));
+ baseColors.append(QColor(QRgb(0x81909f)));
+ baseColors.append(QColor(QRgb(0xbec5cd)));
+ baseColors.append(QColor(QRgb(0x687a8d)));
+ baseColors.append(QColor(QRgb(0xa3aeb9)));
+
+ QList<QLinearGradient> baseGradients;
+ baseGradients.append(createGradient(baseColors.at(0), defaultBuiltInColorLevel));
+ baseGradients.append(createGradient(baseColors.at(1), defaultBuiltInColorLevel));
+ baseGradients.append(createGradient(baseColors.at(2), defaultBuiltInColorLevel));
+ baseGradients.append(createGradient(baseColors.at(3), defaultBuiltInColorLevel));
+ baseGradients.append(createGradient(baseColors.at(4), defaultBuiltInColorLevel));
+
+ setBackgroundEnabled(true);
+ setGridEnabled(true);
+ setFont(QFont(QStringLiteral("Arial")));
+ setLabelBackgroundEnabled(true);
+ setLightColor(Qt::white);
+ setBaseColors(baseColors);
+ setBackgroundColor(QColor(QRgb(0xd5d6d7)));
+ setWindowColor(QColor(QRgb(0xd5d6d7)));
+ setTextColor(QColor(QRgb(0x000000)));
+ setTextBackgroundColor(QColor(0xd5, 0xd6, 0xd7, 0xcd));
+ setGridLineColor(QColor(QRgb(0xaeadac)));
+ setSingleHighlightColor(QColor(QRgb(0x2aa2f9)));
+ setMultiHighlightColor(QColor(QRgb(0x103753)));
+ setLightStrength(5.0f);
+ setAmbientLightStrength(0.5f);
+ setHighlightLightStrength(5.0f);
+ setLabelBorderEnabled(false);
+ setColorStyle(Q3DTheme::ColorStyleObjectGradient);
+ setBaseGradients(baseGradients);
+ setSingleHighlightGradient(createGradient(QColor(QRgb(0x2aa2f9)), defaultBuiltInColorLevel));
+ setMultiHighlightGradient(createGradient(QColor(QRgb(0x103753)), defaultBuiltInColorLevel));
+ break;
+ }
+
+ case Q3DTheme::ThemeRetro: {
+ QList<QColor> baseColors;
+ baseColors.append(QColor(QRgb(0x533b23)));
+ baseColors.append(QColor(QRgb(0x83715a)));
+ baseColors.append(QColor(QRgb(0xb3a690)));
+ baseColors.append(QColor(QRgb(0x6b563e)));
+ baseColors.append(QColor(QRgb(0x9b8b75)));
+
+ QList<QLinearGradient> baseGradients;
+ baseGradients.append(createGradient(baseColors.at(0), defaultBuiltInColorLevel));
+ baseGradients.append(createGradient(baseColors.at(1), defaultBuiltInColorLevel));
+ baseGradients.append(createGradient(baseColors.at(2), defaultBuiltInColorLevel));
+ baseGradients.append(createGradient(baseColors.at(3), defaultBuiltInColorLevel));
+ baseGradients.append(createGradient(baseColors.at(4), defaultBuiltInColorLevel));
+
+ setBackgroundEnabled(true);
+ setGridEnabled(true);
+ setFont(QFont(QStringLiteral("Arial")));
+ setLabelBackgroundEnabled(true);
+ setLightColor(Qt::white);
+ setBaseColors(baseColors);
+ setBackgroundColor(QColor(QRgb(0xe9e2ce)));
+ setWindowColor(QColor(QRgb(0xe9e2ce)));
+ setTextColor(QColor(QRgb(0x000000)));
+ setTextBackgroundColor(QColor(0xe9, 0xe2, 0xce, 0xc0));
+ setGridLineColor(QColor(QRgb(0xd0c0b0)));
+ setSingleHighlightColor(QColor(QRgb(0x8ea317)));
+ setMultiHighlightColor(QColor(QRgb(0xc25708)));
+ setLightStrength(5.0f);
+ setAmbientLightStrength(0.5f);
+ setHighlightLightStrength(5.0f);
+ setLabelBorderEnabled(false);
+ setColorStyle(Q3DTheme::ColorStyleObjectGradient);
+ setBaseGradients(baseGradients);
+ setSingleHighlightGradient(createGradient(QColor(QRgb(0x8ea317)), defaultBuiltInColorLevel));
+ setMultiHighlightGradient(createGradient(QColor(QRgb(0xc25708)), defaultBuiltInColorLevel));
+ break;
+ }
+
+ case Q3DTheme::ThemeEbony: {
+ QList<QColor> baseColors;
+ baseColors.append(QColor(QRgb(0xffffff)));
+ baseColors.append(QColor(QRgb(0x999999)));
+ baseColors.append(QColor(QRgb(0x474747)));
+ baseColors.append(QColor(QRgb(0xc7c7c7)));
+ baseColors.append(QColor(QRgb(0x6b6b6b)));
+
+ QList<QLinearGradient> baseGradients;
+ baseGradients.append(createGradient(baseColors.at(0), defaultColorLevel));
+ baseGradients.append(createGradient(baseColors.at(1), defaultColorLevel));
+ baseGradients.append(createGradient(baseColors.at(2), defaultColorLevel));
+ baseGradients.append(createGradient(baseColors.at(3), defaultColorLevel));
+ baseGradients.append(createGradient(baseColors.at(4), defaultColorLevel));
+
+ setBackgroundEnabled(true);
+ setGridEnabled(true);
+ setFont(QFont(QStringLiteral("Arial")));
+ setLabelBackgroundEnabled(true);
+ setLightColor(Qt::white);
+ setBaseColors(baseColors);
+ setBackgroundColor(QColor(QRgb(0x000000)));
+ setWindowColor(QColor(QRgb(0x000000)));
+ setTextColor(QColor(QRgb(0xaeadac)));
+ setTextBackgroundColor(QColor(0x00, 0x00, 0x00, 0xcd));
+ setGridLineColor(QColor(QRgb(0x35322f)));
+ setSingleHighlightColor(QColor(QRgb(0xf5dc0d)));
+ setMultiHighlightColor(QColor(QRgb(0xd72222)));
+ setLightStrength(5.0f);
+ setAmbientLightStrength(0.5f);
+ setHighlightLightStrength(5.0f);
+ setLabelBorderEnabled(false);
+ setColorStyle(Q3DTheme::ColorStyleUniform);
+ setBaseGradients(baseGradients);
+ setSingleHighlightGradient(createGradient(QColor(QRgb(0xf5dc0d)), defaultColorLevel));
+ setMultiHighlightGradient(createGradient(QColor(QRgb(0xd72222)), defaultColorLevel));
+ break;
+ }
+
+ case Q3DTheme::ThemeIsabelle: {
+ QList<QColor> baseColors;
+ baseColors.append(QColor(QRgb(0xf9d900)));
+ baseColors.append(QColor(QRgb(0xf09603)));
+ baseColors.append(QColor(QRgb(0xe85506)));
+ baseColors.append(QColor(QRgb(0xf5b802)));
+ baseColors.append(QColor(QRgb(0xec7605)));
+
+ QList<QLinearGradient> baseGradients;
+ baseGradients.append(createGradient(baseColors.at(0), defaultColorLevel));
+ baseGradients.append(createGradient(baseColors.at(1), defaultColorLevel));
+ baseGradients.append(createGradient(baseColors.at(2), defaultColorLevel));
+ baseGradients.append(createGradient(baseColors.at(3), defaultColorLevel));
+ baseGradients.append(createGradient(baseColors.at(4), defaultColorLevel));
+
+ setBackgroundEnabled(true);
+ setGridEnabled(true);
+ setFont(QFont(QStringLiteral("Arial")));
+ setLabelBackgroundEnabled(true);
+ setLightColor(Qt::white);
+ setBaseColors(baseColors);
+ setBackgroundColor(QColor(QRgb(0x000000)));
+ setWindowColor(QColor(QRgb(0x000000)));
+ setTextColor(QColor(QRgb(0xaeadac)));
+ setTextBackgroundColor(QColor(0x00, 0x00, 0x00, 0xc0));
+ setGridLineColor(QColor(QRgb(0x35322f)));
+ setSingleHighlightColor(QColor(QRgb(0xfff7cc)));
+ setMultiHighlightColor(QColor(QRgb(0xde0a0a)));
+ setLightStrength(5.0f);
+ setAmbientLightStrength(0.5f);
+ setHighlightLightStrength(5.0f);
+ setLabelBorderEnabled(false);
+ setColorStyle(Q3DTheme::ColorStyleUniform);
+ setBaseGradients(baseGradients);
+ setSingleHighlightGradient(createGradient(QColor(QRgb(0xfff7cc)), defaultColorLevel));
+ setMultiHighlightGradient(createGradient(QColor(QRgb(0xde0a0a)), defaultColorLevel));
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+QLinearGradient ThemeManager::createGradient(const QColor &color, float colorLevel)
+{
+ QColor startColor;
+ QLinearGradient gradient = QLinearGradient(qreal(gradientTextureWidth),
+ qreal(gradientTextureHeight),
+ 0.0, 0.0);;
+ startColor.setRed(color.red() * colorLevel);
+ startColor.setGreen(color.green() * colorLevel);
+ startColor.setBlue(color.blue() * colorLevel);
+ gradient.setColorAt(0.0, startColor);
+ gradient.setColorAt(1.0, color);
+ return gradient;
+}
+
+void ThemeManager::setBaseColors(const QList<QColor> &colors)
+{
+ if (!m_theme->d_ptr->m_dirtyBits.baseColorDirty)
+ m_theme->setBaseColors(colors);
+}
+
+void ThemeManager::setBackgroundColor(const QColor &color)
+{
+ if (!m_theme->d_ptr->m_dirtyBits.backgroundColorDirty)
+ m_theme->setBackgroundColor(color);
+}
+
+void ThemeManager::setWindowColor(const QColor &color)
+{
+ if (!m_theme->d_ptr->m_dirtyBits.windowColorDirty)
+ m_theme->setWindowColor(color);
+}
+
+void ThemeManager::setTextColor(const QColor &color)
+{
+ if (!m_theme->d_ptr->m_dirtyBits.labelTextColorDirty)
+ m_theme->setLabelTextColor(color);
+}
+
+void ThemeManager::setTextBackgroundColor(const QColor &color)
+{
+ if (!m_theme->d_ptr->m_dirtyBits.labelBackgroundColorDirty)
+ m_theme->setLabelBackgroundColor(color);
+}
+
+void ThemeManager::setGridLineColor(const QColor &color)
+{
+ if (!m_theme->d_ptr->m_dirtyBits.gridLineColorDirty)
+ m_theme->setGridLineColor(color);
+}
+
+void ThemeManager::setSingleHighlightColor(const QColor &color)
+{
+ if (!m_theme->d_ptr->m_dirtyBits.singleHighlightColorDirty)
+ m_theme->setSingleHighlightColor(color);
+}
+
+void ThemeManager::setMultiHighlightColor(const QColor &color)
+{
+ if (!m_theme->d_ptr->m_dirtyBits.multiHighlightColorDirty)
+ m_theme->setMultiHighlightColor(color);
+}
+
+void ThemeManager::setLightColor(const QColor &color)
+{
+ if (!m_theme->d_ptr->m_dirtyBits.lightColorDirty)
+ m_theme->setLightColor(color);
+}
+
+void ThemeManager::setBaseGradients(const QList<QLinearGradient> &gradients)
+{
+ if (!m_theme->d_ptr->m_dirtyBits.baseGradientDirty)
+ m_theme->setBaseGradients(gradients);
+}
+
+void ThemeManager::setSingleHighlightGradient(const QLinearGradient &gradient)
+{
+ if (!m_theme->d_ptr->m_dirtyBits.singleHighlightGradientDirty)
+ m_theme->setSingleHighlightGradient(gradient);
+}
+
+void ThemeManager::setMultiHighlightGradient(const QLinearGradient &gradient)
+{
+ if (!m_theme->d_ptr->m_dirtyBits.multiHighlightGradientDirty)
+ m_theme->setMultiHighlightGradient(gradient);
+}
+
+void ThemeManager::setLightStrength(float strength)
+{
+ if (!m_theme->d_ptr->m_dirtyBits.lightStrengthDirty)
+ m_theme->setLightStrength(strength);
+}
+
+void ThemeManager::setAmbientLightStrength(float strength)
+{
+ if (!m_theme->d_ptr->m_dirtyBits.ambientLightStrengthDirty)
+ m_theme->setAmbientLightStrength(strength);
+}
+
+void ThemeManager::setHighlightLightStrength(float strength)
+{
+ if (!m_theme->d_ptr->m_dirtyBits.highlightLightStrengthDirty)
+ m_theme->setHighlightLightStrength(strength);
+}
+
+void ThemeManager::setLabelBorderEnabled(bool enabled)
+{
+ if (!m_theme->d_ptr->m_dirtyBits.labelBorderEnabledDirty)
+ m_theme->setLabelBorderEnabled(enabled);
+}
+
+void ThemeManager::setFont(const QFont &font)
+{
+ if (!m_theme->d_ptr->m_dirtyBits.fontDirty)
+ m_theme->setFont(font);
+}
+
+void ThemeManager::setBackgroundEnabled(bool enabled)
+{
+ if (!m_theme->d_ptr->m_dirtyBits.backgroundEnabledDirty)
+ m_theme->setBackgroundEnabled(enabled);
+}
+
+void ThemeManager::setGridEnabled(bool enabled)
+{
+ if (!m_theme->d_ptr->m_dirtyBits.gridEnabledDirty)
+ m_theme->setGridEnabled(enabled);
+}
+
+void ThemeManager::setLabelBackgroundEnabled(bool enabled)
+{
+ if (!m_theme->d_ptr->m_dirtyBits.labelBackgroundEnabledDirty)
+ m_theme->setLabelBackgroundEnabled(enabled);
+}
+
+void ThemeManager::setColorStyle(Q3DTheme::ColorStyle style)
+{
+ if (!m_theme->d_ptr->m_dirtyBits.colorStyleDirty)
+ m_theme->setColorStyle(style);
+}
+
+QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/theme/thememanager_p.h b/src/datavisualization/theme/thememanager_p.h
new file mode 100644
index 00000000..c6e6a107
--- /dev/null
+++ b/src/datavisualization/theme/thememanager_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the QtDataVisualization API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef THEMEMANAGER_P_H
+#define THEMEMANAGER_P_H
+
+#include "datavisualizationglobal_p.h"
+#include "abstract3dcontroller_p.h"
+#include "q3dtheme.h"
+
+QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
+class ThemeManager : public QObject
+{
+ Q_OBJECT
+public:
+ ThemeManager(Abstract3DController *controller);
+ ~ThemeManager();
+
+ void setTheme(Q3DTheme *theme);
+ Q3DTheme *theme() const;
+
+protected:
+ void connectThemeSignals();
+ void useTheme(Q3DTheme::Theme type);
+ QLinearGradient createGradient(const QColor &color, float colorLevel);
+ void setBaseColors(const QList<QColor> &colors);
+ void setBackgroundColor(const QColor &color);
+ void setWindowColor(const QColor &color);
+ void setTextColor(const QColor &color);
+ void setTextBackgroundColor(const QColor &color);
+ void setGridLineColor(const QColor &color);
+ void setSingleHighlightColor(const QColor &color);
+ void setMultiHighlightColor(const QColor &color);
+ void setLightColor(const QColor &color);
+ void setBaseGradients(const QList<QLinearGradient> &gradients);
+ void setSingleHighlightGradient(const QLinearGradient &gradient);
+ void setMultiHighlightGradient(const QLinearGradient &gradient);
+ void setLightStrength(float strength);
+ void setAmbientLightStrength(float strength);
+ void setHighlightLightStrength(float strength);
+ void setLabelBorderEnabled(bool enabled);
+ void setFont(const QFont &font);
+ void setBackgroundEnabled(bool enabled);
+ void setGridEnabled(bool enabled);
+ void setLabelBackgroundEnabled(bool enabled);
+ void setColorStyle(Q3DTheme::ColorStyle style);
+
+private:
+ QScopedPointer<Q3DTheme> m_theme;
+ Abstract3DController *m_controller;
+};
+
+QT_DATAVISUALIZATION_END_NAMESPACE
+
+#endif
diff --git a/src/datavisualization/utils/camerahelper.cpp b/src/datavisualization/utils/camerahelper.cpp
index 29ed4d57..9e7e58aa 100644
--- a/src/datavisualization/utils/camerahelper.cpp
+++ b/src/datavisualization/utils/camerahelper.cpp
@@ -155,125 +155,125 @@ QPointF CameraHelper::getCameraRotations()
return rotations;
}
-void CameraHelper::setCameraPreset(QDataVis::CameraPreset preset)
+void CameraHelper::setCameraPreset(Q3DCamera::CameraPreset preset)
{
switch (preset) {
- case QDataVis::CameraPresetFrontLow: {
+ case Q3DCamera::CameraPresetFrontLow: {
qDebug("CameraPresetFrontLow");
CameraHelper::setCameraRotation(QPointF(0.0f, 0.0f));
break;
}
- case QDataVis::CameraPresetFront: {
+ case Q3DCamera::CameraPresetFront: {
qDebug("CameraPresetFront");
CameraHelper::setCameraRotation(QPointF(0.0f, 22.5f));
break;
}
- case QDataVis::CameraPresetFrontHigh: {
+ case Q3DCamera::CameraPresetFrontHigh: {
qDebug("CameraPresetFrontHigh");
CameraHelper::setCameraRotation(QPointF(0.0f, 45.0f));
break;
}
- case QDataVis::CameraPresetLeftLow: {
+ case Q3DCamera::CameraPresetLeftLow: {
qDebug("CameraPresetLeftLow");
CameraHelper::setCameraRotation(QPointF(90.0f, 0.0f));
break;
}
- case QDataVis::CameraPresetLeft: {
+ case Q3DCamera::CameraPresetLeft: {
qDebug("CameraPresetLeft");
CameraHelper::setCameraRotation(QPointF(90.0f, 22.5f));
break;
}
- case QDataVis::CameraPresetLeftHigh: {
+ case Q3DCamera::CameraPresetLeftHigh: {
qDebug("CameraPresetLeftHigh");
CameraHelper::setCameraRotation(QPointF(90.0f, 45.0f));
break;
}
- case QDataVis::CameraPresetRightLow: {
+ case Q3DCamera::CameraPresetRightLow: {
qDebug("CameraPresetRightLow");
CameraHelper::setCameraRotation(QPointF(-90.0f, 0.0f));
break;
}
- case QDataVis::CameraPresetRight: {
+ case Q3DCamera::CameraPresetRight: {
qDebug("CameraPresetRight");
CameraHelper::setCameraRotation(QPointF(-90.0f, 22.5f));
break;
}
- case QDataVis::CameraPresetRightHigh: {
+ case Q3DCamera::CameraPresetRightHigh: {
qDebug("CameraPresetRightHigh");
CameraHelper::setCameraRotation(QPointF(-90.0f, 45.0f));
break;
}
- case QDataVis::CameraPresetBehindLow: {
+ case Q3DCamera::CameraPresetBehindLow: {
qDebug("CameraPresetBehindLow");
CameraHelper::setCameraRotation(QPointF(180.0f, 0.0f));
break;
}
- case QDataVis::CameraPresetBehind: {
+ case Q3DCamera::CameraPresetBehind: {
qDebug("CameraPresetBehind");
CameraHelper::setCameraRotation(QPointF(180.0f, 22.5f));
break;
}
- case QDataVis::CameraPresetBehindHigh: {
+ case Q3DCamera::CameraPresetBehindHigh: {
qDebug("CameraPresetBehindHigh");
CameraHelper::setCameraRotation(QPointF(180.0f, 45.0f));
break;
}
- case QDataVis::CameraPresetIsometricLeft: {
+ case Q3DCamera::CameraPresetIsometricLeft: {
qDebug("CameraPresetIsometricLeft");
CameraHelper::setCameraRotation(QPointF(45.0f, 22.5f));
break;
}
- case QDataVis::CameraPresetIsometricLeftHigh: {
+ case Q3DCamera::CameraPresetIsometricLeftHigh: {
qDebug("CameraPresetIsometricLeftHigh");
CameraHelper::setCameraRotation(QPointF(45.0f, 45.0f));
break;
}
- case QDataVis::CameraPresetIsometricRight: {
+ case Q3DCamera::CameraPresetIsometricRight: {
qDebug("CameraPresetIsometricRight");
CameraHelper::setCameraRotation(QPointF(-45.0f, 22.5f));
break;
}
- case QDataVis::CameraPresetIsometricRightHigh: {
+ case Q3DCamera::CameraPresetIsometricRightHigh: {
qDebug("CameraPresetIsometricRightHigh");
CameraHelper::setCameraRotation(QPointF(-45.0f, 45.0f));
break;
}
- case QDataVis::CameraPresetDirectlyAbove: {
+ case Q3DCamera::CameraPresetDirectlyAbove: {
qDebug("CameraPresetDirectlyAbove");
CameraHelper::setCameraRotation(QPointF(0.0f, 90.0f));
break;
}
- case QDataVis::CameraPresetDirectlyAboveCW45: {
+ case Q3DCamera::CameraPresetDirectlyAboveCW45: {
qDebug("CameraPresetDirectlyAboveCW45");
CameraHelper::setCameraRotation(QPointF(-45.0f, 90.0f));
break;
}
- case QDataVis::CameraPresetDirectlyAboveCCW45: {
+ case Q3DCamera::CameraPresetDirectlyAboveCCW45: {
qDebug("CameraPresetDirectlyAboveCCW45");
CameraHelper::setCameraRotation(QPointF(45.0f, 90.0f));
break;
}
- case QDataVis::CameraPresetFrontBelow: {
+ case Q3DCamera::CameraPresetFrontBelow: {
qDebug("CameraPresetFrontBelow");
CameraHelper::setCameraRotation(QPointF(0.0f, -45.0f));
break;
}
- case QDataVis::CameraPresetLeftBelow: {
+ case Q3DCamera::CameraPresetLeftBelow: {
qDebug("CameraPresetLeftBelow");
CameraHelper::setCameraRotation(QPointF(90.0f, -45.0f));
break;
}
- case QDataVis::CameraPresetRightBelow: {
+ case Q3DCamera::CameraPresetRightBelow: {
qDebug("CameraPresetRightBelow");
CameraHelper::setCameraRotation(QPointF(-90.0f, -45.0f));
break;
}
- case QDataVis::CameraPresetBehindBelow: {
+ case Q3DCamera::CameraPresetBehindBelow: {
qDebug("CameraPresetBehindBelow");
CameraHelper::setCameraRotation(QPointF(180.0f, -45.0f));
break;
}
- case QDataVis::CameraPresetDirectlyBelow: {
+ case Q3DCamera::CameraPresetDirectlyBelow: {
qDebug("CameraPresetDirectlyBelow");
CameraHelper::setCameraRotation(QPointF(0.0f, -90.0f));
break;
diff --git a/src/datavisualization/utils/camerahelper_p.h b/src/datavisualization/utils/camerahelper_p.h
index 1ef4d257..50de93a8 100644
--- a/src/datavisualization/utils/camerahelper_p.h
+++ b/src/datavisualization/utils/camerahelper_p.h
@@ -30,6 +30,7 @@
#define CAMERAPOSITIONER_P_H
#include "datavisualizationglobal_p.h"
+#include "q3dcamera.h"
#include "q3dbars.h"
#include <QObject>
@@ -82,7 +83,7 @@ public:
GLfloat fixedRotation = 0.0f,
GLfloat distanceModifier = 0.0f);
void updateMousePos(const QPoint &mousePos);
- void setCameraPreset(QDataVis::CameraPreset preset);
+ void setCameraPreset(Q3DCamera::CameraPreset preset);
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/utils/objecthelper.cpp b/src/datavisualization/utils/objecthelper.cpp
index 9660c215..180ce009 100644
--- a/src/datavisualization/utils/objecthelper.cpp
+++ b/src/datavisualization/utils/objecthelper.cpp
@@ -57,8 +57,6 @@ void ObjectHelper::load()
if (!loadOk)
qFatal("loading failed");
- //qDebug() << "vertex count" << vertices.size();;
-
// Index vertices
QVector<unsigned short> indices;
QVector<QVector3D> indexed_vertices;
@@ -68,7 +66,6 @@ void ObjectHelper::load()
indexed_normals);
m_indexCount = indices.size();
- //qDebug() << "index count" << m_indexCount;
glGenBuffers(1, &m_vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexbuffer);
diff --git a/src/datavisualization/utils/shaderhelper.cpp b/src/datavisualization/utils/shaderhelper.cpp
index e27103af..b4d2ee76 100644
--- a/src/datavisualization/utils/shaderhelper.cpp
+++ b/src/datavisualization/utils/shaderhelper.cpp
@@ -90,22 +90,25 @@ void ShaderHelper::initialize()
m_colorUniform = m_program->uniformLocation("color_mdl");
m_textureUniform = m_program->uniformLocation("textureSampler");
m_shadowUniform = m_program->uniformLocation("shadowMap");
-
+ m_gradientMinUniform = m_program->uniformLocation("gradMin");
+ m_gradientHeightUniform = m_program->uniformLocation("gradHeight");
m_initialized = true;
}
bool ShaderHelper::testCompile()
{
bool result = true;
+
// Discard warnings, we only need the result
QtMessageHandler handler = qInstallMessageHandler(discardDebugMsgs);
if (m_program)
delete m_program;
- m_program = new QOpenGLShaderProgram(m_caller);
+ m_program = new QOpenGLShaderProgram();
if (!m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, m_vertexShaderFile))
result = false;
if (!m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, m_fragmentShaderFile))
result = false;
+
// Restore actual message handler
qInstallMessageHandler(handler);
return result;
@@ -230,6 +233,20 @@ GLuint ShaderHelper::shadow()
return m_shadowUniform;
}
+GLuint ShaderHelper::gradientMin()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_gradientMinUniform;
+}
+
+GLuint ShaderHelper::gradientHeight()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_gradientHeightUniform;
+}
+
GLuint ShaderHelper::posAtt()
{
if (!m_initialized)
diff --git a/src/datavisualization/utils/shaderhelper_p.h b/src/datavisualization/utils/shaderhelper_p.h
index 73e5b9ee..191b7bf6 100644
--- a/src/datavisualization/utils/shaderhelper_p.h
+++ b/src/datavisualization/utils/shaderhelper_p.h
@@ -71,6 +71,8 @@ class ShaderHelper
GLuint color();
GLuint texture();
GLuint shadow();
+ GLuint gradientMin();
+ GLuint gradientHeight();
GLuint posAtt();
GLuint uvAtt();
@@ -102,6 +104,8 @@ class ShaderHelper
GLuint m_shadowQualityUniform;
GLuint m_textureUniform;
GLuint m_shadowUniform;
+ GLuint m_gradientMinUniform;
+ GLuint m_gradientHeightUniform;
GLboolean m_initialized;
};
diff --git a/src/datavisualization/utils/surfaceobject.cpp b/src/datavisualization/utils/surfaceobject.cpp
index d9a32ec6..605376e2 100644
--- a/src/datavisualization/utils/surfaceobject.cpp
+++ b/src/datavisualization/utils/surfaceobject.cpp
@@ -53,8 +53,8 @@ void SurfaceObject::setUpSmoothData(const QSurfaceDataArray &dataArray, const QR
GLfloat xNormalizer = (dataArray.at(0)->last().x() - xMin) / 2.0f;
GLfloat yNormalizer = yRange / 2.0f;
GLfloat zNormalizer = (dataArray.last()->at(0).z() - zMin) / -2.0f;
- GLfloat uvX = 1.0 / GLfloat(m_columns - 1);
- GLfloat uvY = 1.0 / GLfloat(m_rows - 1);
+ GLfloat uvX = 1.0f / GLfloat(m_columns - 1);
+ GLfloat uvY = 1.0f / GLfloat(m_rows - 1);
m_surfaceType = SurfaceSmooth;
@@ -105,58 +105,216 @@ void SurfaceObject::setUpSmoothData(const QSurfaceDataArray &dataArray, const QR
m_vertices.at(j - m_columns),
m_vertices.at(j + 1));
}
- int p = m_rows * colLimit;
- m_normals[totalIndex++] = normal(m_vertices.at(p),
- m_vertices.at(p - 1),
- m_vertices.at(p - m_columns - 1));
+ m_normals[totalIndex++] = normal(m_vertices.at(totalLimit),
+ m_vertices.at(totalLimit - 1),
+ m_vertices.at(totalLimit - m_columns));
// Create indices table
- GLint *indices = 0;
- if (changeGeometry) {
- m_indexCount = 6 * colLimit * rowLimit;
- indices = new GLint[m_indexCount];
- p = 0;
- for (int row = 0; row < rowLimit * m_columns; row += m_columns) {
- for (int j = 0; j < colLimit; j++) {
- // Left triangle
- indices[p++] = row + j + 1;
- indices[p++] = row + m_columns + j;
- indices[p++] = row + j;
+ if (changeGeometry)
+ createSmoothIndices(0, 0, colLimit, rowLimit);
- // Right triangle
- indices[p++] = row + m_columns + j + 1;
- indices[p++] = row + m_columns + j;
- indices[p++] = row + j + 1;
- }
+ // Create line element indices
+ if (changeGeometry)
+ createSmoothGridlineIndices(0, 0, colLimit, rowLimit);
+
+ createBuffers(m_vertices, uvs, m_normals, 0, changeGeometry);
+}
+
+void SurfaceObject::updateSmoothRow(const QSurfaceDataArray &dataArray, int rowIndex,
+ GLfloat yRange, GLfloat yMin)
+{
+ GLfloat xMin = dataArray.at(0)->at(0).x();
+ GLfloat zMin = dataArray.at(0)->at(0).z();
+ GLfloat xNormalizer = (dataArray.at(0)->last().x() - xMin) / 2.0f;
+ GLfloat yNormalizer = yRange / 2.0f;
+ GLfloat zNormalizer = (dataArray.last()->at(0).z() - zMin) / -2.0f;
+
+ // Update vertices
+ int p = rowIndex * m_columns;
+ const QSurfaceDataRow &dataRow = *dataArray.at(rowIndex);
+ for (int j = 0; j < m_columns; j++) {
+ const QSurfaceDataItem &data = dataRow.at(j);
+ float normalizedX = ((data.x() - xMin) / xNormalizer);
+ float normalizedY = ((data.y() - yMin) / yNormalizer);
+ float normalizedZ = ((data.z() - zMin) / zNormalizer);
+ m_vertices[p++] = QVector3D(normalizedX - 1.0f, normalizedY - 1.0f, normalizedZ + 1.0f);
+ }
+
+ // Create normals
+ int colLimit = m_columns - 1;
+ int startRow = rowIndex;
+ if (startRow > 0)
+ startRow--;
+ int totalIndex = startRow * m_columns;
+ int rowLimit = (rowIndex + 1) * m_columns;
+ if (rowIndex == m_rows - 1)
+ rowLimit = rowIndex * m_columns; // The rowIndex is top most row, special handling
+
+ for (int row = totalIndex; row < rowLimit; row += m_columns) {
+ for (int j = 0; j < colLimit; j++) {
+ // One right and one up
+ m_normals[totalIndex++] = normal(m_vertices.at(row + j),
+ m_vertices.at(row + j + 1),
+ m_vertices.at(row + m_columns + j));
}
+ int p = row + colLimit;
+ // One up and one left
+ m_normals[totalIndex++] = normal(m_vertices.at(p),
+ m_vertices.at(p + m_columns),
+ m_vertices.at(p - 1));
}
+ if (rowIndex == m_rows - 1) {
+ // Top most line, nothing above, must have different handling.
+ // Take from one down and one right. Read till second-to-last
+ rowLimit = (rowIndex + 1) * m_columns - 1;
+ for (int j = rowIndex * m_columns; j < rowLimit; j++) {
+ m_normals[totalIndex++] = normal(m_vertices.at(j),
+ m_vertices.at(j - m_columns),
+ m_vertices.at(j + 1));
+ }
- // Create line element indices
- GLint *gridIndices = 0;
- if (changeGeometry) {
- m_gridIndexCount = 2 * m_columns * rowLimit + 2 * m_rows * colLimit;
- gridIndices = new GLint[m_gridIndexCount];
- p = 0;
- for (int i = 0, row = 0; i < m_rows; i++, row += m_columns) {
- for (int j = 0; j < colLimit; j++) {
- gridIndices[p++] = row + j;
- gridIndices[p++] = row + j + 1;
+ // Top left corner. Take from one left and one down
+ m_normals[totalIndex++] = normal(m_vertices.at(rowLimit),
+ m_vertices.at(rowLimit - 1),
+ m_vertices.at(rowLimit - m_columns));
+ }
+}
+
+void SurfaceObject::updateSmoothItem(const QSurfaceDataArray &dataArray, int row,
+ int column, GLfloat yRange, GLfloat yMin)
+{
+ GLfloat xMin = dataArray.at(0)->at(0).x();
+ GLfloat zMin = dataArray.at(0)->at(0).z();
+ GLfloat xNormalizer = (dataArray.at(0)->last().x() - xMin) / 2.0f;
+ GLfloat yNormalizer = yRange / 2.0f;
+ GLfloat zNormalizer = (dataArray.last()->at(0).z() - zMin) / -2.0f;
+
+ // Update a vertice
+ const QSurfaceDataItem &data = dataArray.at(row)->at(column);
+ float normalizedX = ((data.x() - xMin) / xNormalizer);
+ float normalizedY = ((data.y() - yMin) / yNormalizer);
+ float normalizedZ = ((data.z() - zMin) / zNormalizer);
+ m_vertices[row * m_columns + column] = QVector3D(normalizedX - 1.0f, normalizedY - 1.0f, normalizedZ + 1.0f);
+
+ // Create normals
+ int startRow = row;
+ if (startRow > 0)
+ startRow--; // Change the normal for previous row also
+ int startCol = column;
+ if (startCol > 0)
+ startCol--;
+ int rightCol = m_columns - 1;
+ int topRow = m_rows - 1;
+
+ for (int i = startRow; i <= row; i++) {
+ for (int j = startCol; j <= column; j++) {
+ int p = i * m_columns + j;
+ if (i < topRow) {
+ if (j < rightCol) {
+ // One right and one up
+ m_normals[p] = normal(m_vertices.at(p),
+ m_vertices.at(p + 1),
+ m_vertices.at(p + m_columns));
+ } else {
+ // Last item, nothing on the right. One up and one left
+ m_normals[p] = normal(m_vertices.at(p),
+ m_vertices.at(p + m_columns),
+ m_vertices.at(p - 1));
+ }
+ } else {
+ // Top most line, nothing above, must have different handling.
+ if (j < rightCol) {
+ // Take from one down and one right. Read till second-to-last
+ m_normals[p] = normal(m_vertices.at(p),
+ m_vertices.at(p - m_columns),
+ m_vertices.at(p + 1));
+ } else {
+ // Top left corner. Take from one left and one down
+ m_normals[p] = normal(m_vertices.at(p),
+ m_vertices.at(p - 1),
+ m_vertices.at(p - m_columns));
+ }
}
}
- for (int i = 0, row = 0; i < rowLimit; i++, row += m_columns) {
- for (int j = 0; j < m_columns; j++) {
- gridIndices[p++] = row + j;
- gridIndices[p++] = row + j + m_columns;
- }
+ }
+}
+
+
+void SurfaceObject::createSmoothIndices(int x, int y, int endX, int endY)
+{
+ if (endX >= m_columns)
+ endX = m_columns - 1;
+ if (endY >= m_rows)
+ endY = m_rows - 1;
+ if (x > endX)
+ x = endX - 1;
+ if (y > endY)
+ y = endY - 1;
+
+ m_indexCount = 6 * (endX - x) * (endY - y);
+ GLint *indices = new GLint[m_indexCount];
+ int p = 0;
+ int rowEnd = endY * m_columns;
+ for (int row = y * m_columns; row < rowEnd; row += m_columns) {
+ for (int j = x; j < endX; j++) {
+ // Left triangle
+ indices[p++] = row + j + 1;
+ indices[p++] = row + m_columns + j;
+ indices[p++] = row + j;
+
+ // Right triangle
+ indices[p++] = row + m_columns + j + 1;
+ indices[p++] = row + m_columns + j;
+ indices[p++] = row + j + 1;
}
}
- createBuffers(m_vertices, uvs, m_normals, indices, gridIndices, changeGeometry);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementbuffer);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indexCount * sizeof(GLint),
+ indices, GL_STATIC_DRAW);
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
delete[] indices;
- delete[] gridIndices;
}
+void SurfaceObject::createSmoothGridlineIndices(int x, int y, int endX, int endY)
+{
+ if (endX >= m_columns)
+ endX = m_columns - 1;
+ if (endY >= m_rows)
+ endY = m_rows - 1;
+ if (x > endX)
+ x = endX - 1;
+ if (y > endY)
+ y = endY - 1;
+
+ int nColumns = endX - x + 1;
+ int nRows = endY - y + 1;
+ m_gridIndexCount = 2 * nColumns * (nRows - 1) + 2 * nRows * (nColumns - 1);
+ GLint *gridIndices = new GLint[m_gridIndexCount];
+ int p = 0;
+ for (int i = y, row = m_columns * y; i <= endY; i++, row += m_columns) {
+ for (int j = x; j < endX; j++) {
+ gridIndices[p++] = row + j;
+ gridIndices[p++] = row + j + 1;
+ }
+ }
+ for (int i = y, row = m_columns * y; i < endY; i++, row += m_columns) {
+ for (int j = x; j <= endX; j++) {
+ gridIndices[p++] = row + j;
+ gridIndices[p++] = row + j + m_columns;
+ }
+ }
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_gridElementbuffer);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_gridIndexCount * sizeof(GLint),
+ gridIndices, GL_STATIC_DRAW);
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ delete[] gridIndices;
+}
void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &space,
GLfloat yRange, GLfloat yMin, bool changeGeometry)
@@ -169,8 +327,8 @@ void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &s
GLfloat xNormalizer = (dataArray.at(0)->last().x() - xMin) / 2.0f;
GLfloat yNormalizer = yRange / 2.0f;
GLfloat zNormalizer = (dataArray.last()->at(0).z() - zMin) / -2.0f;
- GLfloat uvX = 1.0 / GLfloat(m_columns - 1);
- GLfloat uvY = 1.0 / GLfloat(m_rows - 1);
+ GLfloat uvX = 1.0f / GLfloat(m_columns - 1);
+ GLfloat uvY = 1.0f / GLfloat(m_rows - 1);
m_surfaceType = SurfaceFlat;
@@ -250,38 +408,220 @@ void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &s
}
// Create grid line element indices
- GLint *gridIndices = 0;
- if (changeGeometry) {
- m_gridIndexCount = 2 * m_columns * rowLimit + 2 * m_rows * colLimit;
- gridIndices = new GLint[m_gridIndexCount];
- p = 0;
- int fullRowLimit = m_rows * doubleColumns;
- for (int row = 0; row < fullRowLimit; row += doubleColumns) {
- for (int j = 0; j < doubleColumns; j += 2) {
- gridIndices[p++] = row + j;
- gridIndices[p++] = row + j + 1;
+ if (changeGeometry)
+ createCoarseGridlineIndices(0, 0, colLimit, rowLimit);
- if (row < rowColLimit) {
- gridIndices[p++] = row + j;
- gridIndices[p++] = row + j + doubleColumns;
- }
- }
+ createBuffers(m_vertices, uvs, m_normals, indices, changeGeometry);
+
+ delete[] indices;
+}
+
+void SurfaceObject::updateCoarseRow(const QSurfaceDataArray &dataArray, int rowIndex,
+ GLfloat yRange, GLfloat yMin)
+{
+ GLfloat xMin = dataArray.at(0)->at(0).x();
+ GLfloat zMin = dataArray.at(0)->at(0).z();
+ GLfloat xNormalizer = (dataArray.at(0)->last().x() - xMin) / 2.0f;
+ GLfloat yNormalizer = yRange / 2.0f;
+ GLfloat zNormalizer = (dataArray.last()->at(0).z() - zMin) / -2.0f;
+
+ int colLimit = m_columns - 1;
+ int doubleColumns = m_columns * 2 - 2;
+
+ int p = rowIndex * doubleColumns;
+ const QSurfaceDataRow &dataRow = *dataArray.at(rowIndex);
+ for (int j = 0; j < m_columns; j++) {
+ const QSurfaceDataItem &data = dataRow.at(j);
+ float normalizedX = ((data.x() - xMin) / xNormalizer);
+ float normalizedY = ((data.y() - yMin) / yNormalizer);
+ float normalizedZ = ((data.z() - zMin) / zNormalizer);
+ m_vertices[p++] = QVector3D(normalizedX - 1.0f, normalizedY - 1.0f, normalizedZ + 1.0f);
+
+ if (j > 0 && j < colLimit) {
+ m_vertices[p] = m_vertices[p - 1];
+ p++;
+ }
+ }
+
+ // Create normals
+ p = rowIndex * doubleColumns;
+ if (p > 0)
+ p -= doubleColumns;
+ int rowLimit = (rowIndex + 1) * doubleColumns;
+ if (rowIndex == m_rows - 1)
+ rowLimit = rowIndex * doubleColumns; //Topmost row, no normals
+ for (int row = p, upperRow = p + doubleColumns;
+ row < rowLimit;
+ row += doubleColumns, upperRow += doubleColumns) {
+ for (int j = 0; j < doubleColumns; j += 2) {
+ // Normal for the left triangle
+ m_normals[p++] = normal(m_vertices.at(row + j),
+ m_vertices.at(row + j + 1),
+ m_vertices.at(upperRow + j));
+
+ // Normal for the right triangle
+ m_normals[p++] = normal(m_vertices.at(row + j + 1),
+ m_vertices.at(upperRow + j + 1),
+ m_vertices.at(upperRow + j));
+ }
+ }
+}
+
+void SurfaceObject::updateCoarseItem(const QSurfaceDataArray &dataArray, int row,
+ int column, GLfloat yRange, GLfloat yMin)
+{
+ GLfloat xMin = dataArray.at(0)->at(0).x();
+ GLfloat zMin = dataArray.at(0)->at(0).z();
+ GLfloat xNormalizer = (dataArray.at(0)->last().x() - xMin) / 2.0f;
+ GLfloat yNormalizer = yRange / 2.0f;
+ GLfloat zNormalizer = (dataArray.last()->at(0).z() - zMin) / -2.0f;
+
+ int colLimit = m_columns - 1;
+ int doubleColumns = m_columns * 2 - 2;
+
+ // Update a vertice
+ int p = row * doubleColumns + column * 2 - (column > 0);
+ const QSurfaceDataItem &data = dataArray.at(row)->at(column);
+ float normalizedX = ((data.x() - xMin) / xNormalizer);
+ float normalizedY = ((data.y() - yMin) / yNormalizer);
+ float normalizedZ = ((data.z() - zMin) / zNormalizer);
+ m_vertices[p] = QVector3D(normalizedX - 1.0f, normalizedY - 1.0f, normalizedZ + 1.0f);
+ p++;
+
+ if (column > 0 && column < colLimit)
+ m_vertices[p] = m_vertices[p - 1];
+
+ // Create normals
+ int startRow = row;
+ if (startRow > 0)
+ startRow--; // Change the normal for previous row also
+ int startCol = column;
+ if (startCol > 0)
+ startCol--;
+ if (row == m_rows - 1)
+ row--;
+ if (column == m_columns - 1)
+ column--;
+
+ for (int i = startRow; i <= row; i++) {
+ for (int j = startCol; j <= column; j++) {
+ p = i * doubleColumns + j * 2;
+ // Normal for the left triangle
+ m_normals[p] = normal(m_vertices.at(p),
+ m_vertices.at(p + 1),
+ m_vertices.at(p + doubleColumns));
+ p++;
+
+ // Normal for the right triangle
+ m_normals[p] = normal(m_vertices.at(p),
+ m_vertices.at(p + doubleColumns),
+ m_vertices.at(p + doubleColumns - 1));
}
- for (int i = doubleColumns - 1; i < rowColLimit; i += doubleColumns) {
- gridIndices[p++] = i;
- gridIndices[p++] = i + doubleColumns;
+ }
+}
+
+void SurfaceObject::createCoarseIndices(int x, int y, int columns, int rows)
+{
+ if (columns > m_columns)
+ columns = m_columns;
+ if (rows > m_rows)
+ rows = m_rows;
+ if (x > columns)
+ x = columns - 1;
+ if (y > rows)
+ y = rows - 1;
+
+ int rowLimit = rows - 1;
+ int doubleColumns = m_columns * 2 - 2;
+ int doubleColumnsLimit = columns * 2 - 2;
+ int rowColLimit = rowLimit * doubleColumns;
+ m_indexCount = 6 * (columns - 1 - x) * (rowLimit - y);
+
+ int p = 0;
+ GLint *indices = new GLint[m_indexCount];
+ for (int row = y * doubleColumns, upperRow = (y + 1) * doubleColumns;
+ row < rowColLimit;
+ row += doubleColumns, upperRow += doubleColumns) {
+ for (int j = 2 * x; j < doubleColumnsLimit; j += 2) {
+ // Left triangle
+ indices[p++] = row + j + 1;
+ indices[p++] = upperRow + j;
+ indices[p++] = row + j;
+
+ // Right triangle
+ indices[p++] = upperRow + j + 1;
+ indices[p++] = upperRow + j;
+ indices[p++] = row + j + 1;
}
}
- createBuffers(m_vertices, uvs, m_normals, indices, gridIndices, changeGeometry);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementbuffer);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indexCount * sizeof(GLint),
+ indices, GL_STATIC_DRAW);
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
delete[] indices;
+}
+
+void SurfaceObject::createCoarseGridlineIndices(int x, int y, int endX, int endY)
+{
+ if (endX >= m_columns)
+ endX = m_columns - 1;
+ if (endY >= m_rows)
+ endY = m_rows - 1;
+ if (x > endX)
+ x = endX - 1;
+ if (y > endY)
+ y = endY - 1;
+
+ int nColumns = endX - x + 1;
+ int nRows = endY - y + 1;
+ int doubleEndX = endX * 2;
+ int doubleColumns = m_columns * 2 - 2;
+ int rowColLimit = endY * doubleColumns;
+
+ m_gridIndexCount = 2 * nColumns * (nRows - 1) + 2 * nRows * (nColumns - 1);
+ GLint *gridIndices = new GLint[m_gridIndexCount];
+ int p = 0;
+
+ for (int row = y * doubleColumns; row <= rowColLimit; row += doubleColumns) {
+ for (int j = x * 2; j < doubleEndX; j += 2) {
+ // Horizontal line
+ gridIndices[p++] = row + j;
+ gridIndices[p++] = row + j + 1;
+
+ if (row < rowColLimit) {
+ // Vertical line
+ gridIndices[p++] = row + j;
+ gridIndices[p++] = row + j + doubleColumns;
+ }
+ }
+ }
+ // The rightmost line separately, since there isn't double vertice
+ for (int i = y * doubleColumns + doubleEndX - 1; i < rowColLimit; i += doubleColumns) {
+ gridIndices[p++] = i;
+ gridIndices[p++] = i + doubleColumns;
+ }
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_gridElementbuffer);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_gridIndexCount * sizeof(GLint),
+ gridIndices, GL_STATIC_DRAW);
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
delete[] gridIndices;
}
+void SurfaceObject::uploadBuffers()
+{
+ QVector<QVector2D> uvs; // Empty dummy
+ createBuffers(m_vertices, uvs, m_normals, 0, false);
+}
+
void SurfaceObject::createBuffers(const QVector<QVector3D> &vertices, const QVector<QVector2D> &uvs,
const QVector<QVector3D> &normals, const GLint *indices,
- const GLint *gridIndices, bool changeGeometry)
+ bool changeGeometry)
{
// Move to buffers
glBindBuffer(GL_ARRAY_BUFFER, m_vertexbuffer);
@@ -293,18 +633,15 @@ void SurfaceObject::createBuffers(const QVector<QVector3D> &vertices, const QVec
&normals.at(0), GL_DYNAMIC_DRAW);
if (changeGeometry) {
- if (uvs.size()) {
- glBindBuffer(GL_ARRAY_BUFFER, m_uvbuffer);
- glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(QVector2D),
- &uvs.at(0), GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, m_uvbuffer);
+ glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(QVector2D),
+ &uvs.at(0), GL_STATIC_DRAW);
+
+ if (indices) {
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementbuffer);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indexCount * sizeof(GLint),
+ indices, GL_STATIC_DRAW);
}
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementbuffer);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indexCount * sizeof(GLint),
- indices, GL_STATIC_DRAW);
-
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_gridElementbuffer);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_gridIndexCount * sizeof(GLint),
- gridIndices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
diff --git a/src/datavisualization/utils/surfaceobject_p.h b/src/datavisualization/utils/surfaceobject_p.h
index 4f30f7c0..e035d905 100644
--- a/src/datavisualization/utils/surfaceobject_p.h
+++ b/src/datavisualization/utils/surfaceobject_p.h
@@ -48,6 +48,19 @@ public:
GLfloat yMin, bool changeGeometry);
void setUpSmoothData(const QSurfaceDataArray &dataArray, const QRect &space, GLfloat yRange,
GLfloat yMin, bool changeGeometry);
+ void updateCoarseRow(const QSurfaceDataArray &dataArray, int rowIndex,
+ GLfloat yRange, GLfloat yMin);
+ void updateSmoothRow(const QSurfaceDataArray &dataArray, int startRow,
+ GLfloat yRange, GLfloat yMin);
+ void updateSmoothItem(const QSurfaceDataArray &dataArray, int row,
+ int column, GLfloat yRange, GLfloat yMin);
+ void updateCoarseItem(const QSurfaceDataArray &dataArray, int row,
+ int column, GLfloat yRange, GLfloat yMin);
+ void createSmoothIndices(int x, int y, int endX, int endY);
+ void createCoarseIndices(int x, int y, int columns, int rows);
+ void createSmoothGridlineIndices(int x, int y, int endX, int endY);
+ void createCoarseGridlineIndices(int x, int y, int endX, int endY);
+ void uploadBuffers();
GLuint gridElementBuf();
GLuint gridIndexCount();
QVector3D vertexAt(int column, int row);
@@ -56,7 +69,7 @@ private:
QVector3D normal(const QVector3D &a, const QVector3D &b, const QVector3D &c);
void createBuffers(const QVector<QVector3D> &vertices, const QVector<QVector2D> &uvs,
const QVector<QVector3D> &normals, const GLint *indices,
- const GLint *gridIndices, bool changeGeometry);
+ bool changeGeometry);
private:
enum SurfaceType {
diff --git a/src/datavisualization/utils/texturehelper.cpp b/src/datavisualization/utils/texturehelper.cpp
index 9e2b9811..c88fc8dc 100644
--- a/src/datavisualization/utils/texturehelper.cpp
+++ b/src/datavisualization/utils/texturehelper.cpp
@@ -20,6 +20,7 @@
#include "utils_p.h"
#include <QImage>
+#include <QPainter>
#include <QDebug>
@@ -35,7 +36,7 @@ TextureHelper::~TextureHelper()
}
GLuint TextureHelper::create2DTexture(const QImage &image, bool useTrilinearFiltering,
- bool convert, bool smoothScale)
+ bool convert, bool smoothScale, bool clampY)
{
if (image.isNull())
return 0;
@@ -73,6 +74,8 @@ GLuint TextureHelper::create2DTexture(const QImage &image, bool useTrilinearFilt
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
+ if (clampY)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D, 0);
return textureId;
}
@@ -152,8 +155,20 @@ GLuint TextureHelper::createSelectionTexture(const QSize &size, GLuint &frameBuf
return textureid;
}
+GLuint TextureHelper::createGradientTexture(const QLinearGradient &gradient)
+{
+ QImage image(QSize(int(gradientTextureWidth), int(gradientTextureHeight)),
+ QImage::Format_RGB32);
+ QPainter pmp(&image);
+ pmp.setBrush(QBrush(gradient));
+ pmp.setPen(Qt::NoPen);
+ pmp.drawRect(0, 0, int(gradientTextureWidth), int(gradientTextureHeight));
+
+ return create2DTexture(image, false, true, false, true);
+}
+
#if !defined(QT_OPENGL_ES_2)
-GLuint TextureHelper::createDepthTexture(const QSize &size, GLuint &frameBuffer, GLuint textureSize)
+GLuint TextureHelper::createDepthTexture(const QSize &size, GLuint textureSize)
{
GLuint depthtextureid;
@@ -167,9 +182,18 @@ GLuint TextureHelper::createDepthTexture(const QSize &size, GLuint &frameBuffer,
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, size.width() * textureSize,
- size.height() * textureSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
+ size.height() * textureSize, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
+ return depthtextureid;
+}
+#endif
+
+#if !defined(QT_OPENGL_ES_2)
+GLuint TextureHelper::createDepthTextureFrameBuffer(const QSize &size, GLuint &frameBuffer, GLuint textureSize)
+{
+ GLuint depthtextureid = createDepthTexture(size, textureSize);
+
// Create frame buffer
if (!frameBuffer)
glGenFramebuffers(1, &frameBuffer);
@@ -195,6 +219,23 @@ GLuint TextureHelper::createDepthTexture(const QSize &size, GLuint &frameBuffer,
}
#endif
+#if !defined(QT_OPENGL_ES_2)
+void TextureHelper::fillDepthTexture(GLuint texture,const QSize &size, GLuint textureSize, GLfloat value)
+{
+ int nItems = size.width() * textureSize * size.height() * textureSize;
+ GLfloat *bits = new GLfloat[nItems];
+ for (int i = 0; i < nItems; i++)
+ bits[i] = value;
+
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, size.width() * textureSize,
+ size.height() * textureSize, 0, GL_DEPTH_COMPONENT, GL_FLOAT, bits);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ delete[] bits;
+}
+#endif
+
void TextureHelper::deleteTexture(const GLuint *texture)
{
glDeleteTextures(1, texture);
@@ -216,8 +257,8 @@ void TextureHelper::convertToGLFormatHelper(QImage &dstImage, const QImage &srcI
if (dstImage.size() != srcImage.size()) {
int target_width = dstImage.width();
int target_height = dstImage.height();
- qreal sx = target_width / qreal(srcImage.width());
- qreal sy = target_height / qreal(srcImage.height());
+ float sx = target_width / float(srcImage.width());
+ float sy = target_height / float(srcImage.height());
quint32 *dest = (quint32 *) dstImage.scanLine(0); // NB! avoid detach here
uchar *srcPixels = (uchar *) srcImage.scanLine(srcImage.height() - 1);
diff --git a/src/datavisualization/utils/texturehelper_p.h b/src/datavisualization/utils/texturehelper_p.h
index 8371825e..11022495 100644
--- a/src/datavisualization/utils/texturehelper_p.h
+++ b/src/datavisualization/utils/texturehelper_p.h
@@ -32,6 +32,7 @@
#include "datavisualizationglobal_p.h"
#include <QOpenGLFunctions>
#include <QRgb>
+#include <QLinearGradient>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
@@ -43,13 +44,16 @@ class TextureHelper : protected QOpenGLFunctions
// Ownership of created texture is transferred to caller
GLuint create2DTexture(const QImage &image, bool useTrilinearFiltering = false,
- bool convert = true, bool smoothScale = true);
+ bool convert = true, bool smoothScale = true, bool clampY = false);
GLuint createCubeMapTexture(const QImage &image, bool useTrilinearFiltering = false);
// Returns selection texture and inserts generated framebuffers to framebuffer parameters
GLuint createSelectionTexture(const QSize &size, GLuint &frameBuffer, GLuint &depthBuffer);
+ GLuint createGradientTexture(const QLinearGradient &gradient);
#if !defined(QT_OPENGL_ES_2)
+ GLuint createDepthTexture(const QSize &size, GLuint textureSize);
// Returns depth texture and inserts generated framebuffer to parameter
- GLuint createDepthTexture(const QSize &size, GLuint &frameBuffer, GLuint textureSize = 1);
+ GLuint createDepthTextureFrameBuffer(const QSize &size, GLuint &frameBuffer, GLuint textureSize);
+ void fillDepthTexture(GLuint texture, const QSize &size, GLuint textureSize, GLfloat value);
#endif
void deleteTexture(const GLuint *texture);
diff --git a/src/datavisualization/utils/utils.cpp b/src/datavisualization/utils/utils.cpp
index eb74d1a3..e6f33032 100644
--- a/src/datavisualization/utils/utils.cpp
+++ b/src/datavisualization/utils/utils.cpp
@@ -44,8 +44,13 @@ QVector3D Utils::vectorFromColor(const QColor &color)
return QVector3D(color.redF(), color.greenF(), color.blueF());
}
+QColor Utils::colorFromVector(const QVector3D &colorVector)
+{
+ return QColor(colorVector.x() * 255.0f, colorVector.y() * 255.0f, colorVector.z() * 255.0f);
+}
+
QImage Utils::printTextToImage(const QFont &font, const QString &text, const QColor &bgrColor,
- const QColor &txtColor, QDataVis::LabelStyle style,
+ const QColor &txtColor, bool labelBackground,
bool borders, int maxLabelWidth)
{
GLuint paddingWidth = 20;
@@ -55,7 +60,7 @@ QImage Utils::printTextToImage(const QFont &font, const QString &text, const QCo
valueFont.setPointSize(textureFontSize);
QFontMetrics valueFM(valueFont);
int valueStrWidth = valueFM.width(text);
- if (maxLabelWidth && QDataVis::LabelStyleTransparent != style)
+ if (maxLabelWidth && labelBackground)
valueStrWidth = maxLabelWidth;
int valueStrHeight = valueFM.height();
valueStrWidth += paddingWidth / 2; // Fix clipping problem with skewed fonts (italic or italic-style)
@@ -74,7 +79,7 @@ QImage Utils::printTextToImage(const QFont &font, const QString &text, const QCo
labelSize.setHeight(getNearestPowerOfTwo(labelSize.height(), paddingHeight));
//qDebug() << "label size after padding" << labelSize << paddingWidth << paddingHeight;
#else
- if (QDataVis::LabelStyleTransparent == style)
+ if (!labelBackground)
labelSize = QSize(valueStrWidth, valueStrHeight);
else
labelSize = QSize(valueStrWidth + paddingWidth * 2, valueStrHeight + paddingHeight * 2);
@@ -90,8 +95,7 @@ QImage Utils::printTextToImage(const QFont &font, const QString &text, const QCo
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setCompositionMode(QPainter::CompositionMode_Source);
painter.setFont(valueFont);
- switch (style) {
- case QDataVis::LabelStyleTransparent: {
+ if (!labelBackground) {
painter.setPen(txtColor);
#if defined(Q_OS_ANDROID)
painter.drawText((labelSize.width() - valueStrWidth) / 2.0f,
@@ -105,9 +109,7 @@ QImage Utils::printTextToImage(const QFont &font, const QString &text, const QCo
Qt::AlignCenter | Qt::AlignVCenter,
text);
#endif
- break;
- }
- case QDataVis::LabelStyleFromTheme: {
+ } else {
painter.setBrush(QBrush(bgrColor));
if (borders) {
painter.setPen(QPen(QBrush(txtColor), 5, Qt::SolidLine, Qt::SquareCap, Qt::RoundJoin));
@@ -123,39 +125,16 @@ QImage Utils::printTextToImage(const QFont &font, const QString &text, const QCo
valueStrWidth, valueStrHeight,
Qt::AlignCenter | Qt::AlignVCenter,
text);
- break;
- }
- case QDataVis::LabelStyleOpaque: {
- QColor labelColor = QColor(bgrColor);
- labelColor.setAlphaF(1.0);
- painter.setBrush(QBrush(labelColor));
- if (borders) {
- painter.setPen(QPen(QBrush(txtColor), 7, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin));
- painter.drawRect(7, 7, labelSize.width() - 14, labelSize.height() - 14);
- } else {
- painter.setPen(labelColor);
- painter.drawRect(0, 0, labelSize.width(), labelSize.height());
- }
- painter.setPen(txtColor);
- painter.drawText((labelSize.width() - valueStrWidth) / 2.0f,
- (labelSize.height() - valueStrHeight) / 2.0f,
- valueStrWidth, valueStrHeight,
- Qt::AlignCenter | Qt::AlignVCenter,
- text);
- break;
- }
}
return image;
}
QVector3D Utils::getSelection(QPoint mousepos, int height)
{
- QVector3D selectedColor;
-
//#if defined(QT_OPENGL_ES_2)
// This is the only one that works with ANGLE (ES 2.0)
// Item count will be limited to 256*256*256
- GLubyte pixel[4];
+ GLubyte pixel[4] = {255, 255, 255, 0};
glReadPixels(mousepos.x(), height - mousepos.y(), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
(void *)pixel);
@@ -174,7 +153,7 @@ QVector3D Utils::getSelection(QPoint mousepos, int height)
// GL_RGB, GL_FLOAT, (void *)pixel3);
//qDebug() << "rgba" << pixel3[0] << pixel3[1] << pixel3[2];// << pixel[3];
//#endif
- selectedColor = QVector3D(pixel[0], pixel[1], pixel[2]);
+ QVector3D selectedColor(pixel[0], pixel[1], pixel[2]);
//qDebug() << selectedColor;
return selectedColor;
@@ -219,7 +198,7 @@ Utils::ParamType Utils::findFormatParamType(const QString &format)
return ParamTypeUnknown;
}
-QString Utils::formatLabel(const QByteArray &format, ParamType paramType, qreal value)
+QString Utils::formatLabel(const QByteArray &format, ParamType paramType, float value)
{
switch (paramType) {
case ParamTypeInt:
@@ -239,7 +218,7 @@ QString Utils::defaultLabelFormat()
return defaultFormat;
}
-qreal Utils::wrapValue(qreal value, qreal min, qreal max)
+float Utils::wrapValue(float value, float min, float max)
{
if (value > max) {
value = min + (value - max);
diff --git a/src/datavisualization/utils/utils_p.h b/src/datavisualization/utils/utils_p.h
index e74b590d..3142e4c2 100644
--- a/src/datavisualization/utils/utils_p.h
+++ b/src/datavisualization/utils/utils_p.h
@@ -53,22 +53,23 @@ public:
static GLuint getNearestPowerOfTwo(GLuint value, GLuint &padding);
static QVector3D vectorFromColor(const QColor &color);
+ static QColor colorFromVector(const QVector3D &colorVector);
static void printText(QPainter *painter, const QString &text, const QSize &position,
- bool absoluteCoords = true, qreal rotation = 0, qreal scale = 1.0f);
+ bool absoluteCoords = true, float rotation = 0.0f, float scale = 1.0f);
static QImage printTextToImage(const QFont &font,
const QString &text,
const QColor &bgrColor,
const QColor &txtColor,
- QDataVis::LabelStyle style,
+ bool labelBackground,
bool borders = false,
int maxLabelWidth = 0);
static QVector3D getSelection(QPoint mousepos, int height);
static ParamType findFormatParamType(const QString &format);
- static QString formatLabel(const QByteArray &format, ParamType paramType, qreal value);
+ static QString formatLabel(const QByteArray &format, ParamType paramType, float value);
static QString defaultLabelFormat();
- static qreal wrapValue(qreal value, qreal min, qreal max);
+ static float wrapValue(float value, float min, float max);
private:
static ParamType mapFormatCharToParamType(const QChar &formatChar);
diff --git a/src/datavisualizationqml2/abstractdeclarative.cpp b/src/datavisualizationqml2/abstractdeclarative.cpp
index e853ff9c..587ea879 100644
--- a/src/datavisualizationqml2/abstractdeclarative.cpp
+++ b/src/datavisualizationqml2/abstractdeclarative.cpp
@@ -18,13 +18,18 @@
#include "abstractdeclarative_p.h"
#include "q3dvalueaxis.h"
-#include "theme_p.h"
+#include <QThread>
+#include <QGuiApplication>
+#include <QSGSimpleRectNode>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
AbstractDeclarative::AbstractDeclarative(QQuickItem *parent) :
- QQuickItem(parent)
+ QQuickItem(parent),
+ m_controller(0)
{
+ connect(this, &QQuickItem::windowChanged, this, &AbstractDeclarative::handleWindowChanged);
+ setAntialiasing(true);
}
AbstractDeclarative::~AbstractDeclarative()
@@ -36,97 +41,133 @@ Q3DScene* AbstractDeclarative::scene() const
return m_controller->scene();
}
-void AbstractDeclarative::setTheme(QDataVis::Theme theme)
+void AbstractDeclarative::setTheme(Q3DTheme *theme)
{
- // TODO: Implement correctly once "user-modifiable themes" (QTRD-2120) is implemented
m_controller->setTheme(theme);
}
-QDataVis::Theme AbstractDeclarative::theme() const
+Q3DTheme *AbstractDeclarative::theme() const
{
- return m_controller->theme().theme();
+ return m_controller->theme();
}
-void AbstractDeclarative::setSelectionMode(QDataVis::SelectionMode mode)
+void AbstractDeclarative::setSelectionMode(QDataVis::SelectionFlags mode)
{
m_controller->setSelectionMode(mode);
}
-QDataVis::SelectionMode AbstractDeclarative::selectionMode() const
+QDataVis::SelectionFlags AbstractDeclarative::selectionMode() const
{
return m_controller->selectionMode();
}
-void AbstractDeclarative::setFont(const QFont &font)
+void AbstractDeclarative::setShadowQuality(QDataVis::ShadowQuality quality)
{
- m_controller->setFont(font);
+ m_controller->setShadowQuality(quality);
}
-QFont AbstractDeclarative::font() const
+QDataVis::ShadowQuality AbstractDeclarative::shadowQuality() const
{
- return m_controller->font();
+ return m_controller->shadowQuality();
}
-void AbstractDeclarative::setLabelStyle(QDataVis::LabelStyle style)
+void AbstractDeclarative::setSharedController(Abstract3DController *controller)
{
- m_controller->setLabelStyle(style);
+ Q_ASSERT(controller);
+ m_controller = controller;
+ QObject::connect(m_controller, &Abstract3DController::shadowQualityChanged, this,
+ &AbstractDeclarative::shadowQualityChanged);
+ QObject::connect(m_controller, &Abstract3DController::activeInputHandlerChanged, this,
+ &AbstractDeclarative::inputHandlerChanged);
+ QObject::connect(m_controller, &Abstract3DController::themeChanged, this,
+ &AbstractDeclarative::themeChanged);
+ QObject::connect(m_controller, &Abstract3DController::selectionModeChanged, this,
+ &AbstractDeclarative::selectionModeChanged);
}
-QDataVis::LabelStyle AbstractDeclarative::labelStyle() const
+void AbstractDeclarative::synchDataToRenderer()
{
- return m_controller->labelStyle();
+ m_controller->initializeOpenGL();
+ m_controller->synchDataToRenderer();
}
-void AbstractDeclarative::setGridVisible(bool visible)
+void AbstractDeclarative::handleWindowChanged(QQuickWindow *window)
{
- m_controller->setGridEnabled(visible);
-}
+ if (!window)
+ return;
-bool AbstractDeclarative::isGridVisible() const
-{
- return m_controller->gridEnabled();
-}
+ // Disable clearing of the window as we render underneath
+ window->setClearBeforeRendering(false);
-void AbstractDeclarative::setBackgroundVisible(bool visible)
-{
- m_controller->setBackgroundEnabled(visible);
-}
+ connect(window, &QQuickWindow::beforeSynchronizing, this,
+ &AbstractDeclarative::synchDataToRenderer, Qt::DirectConnection);
+ connect(window, &QQuickWindow::beforeRendering, this,
+ &AbstractDeclarative::render, Qt::DirectConnection);
+ connect(m_controller, &Abstract3DController::needRender, window,
+ &QQuickWindow::update);
-bool AbstractDeclarative::isBackgroundVisible() const
-{
- return m_controller->backgroundEnabled();
+ updateWindowParameters();
}
-void AbstractDeclarative::setShadowQuality(QDataVis::ShadowQuality quality)
+void AbstractDeclarative::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
- m_controller->setShadowQuality(quality);
-}
+ QQuickItem::geometryChanged(newGeometry, oldGeometry);
-QDataVis::ShadowQuality AbstractDeclarative::shadowQuality() const
-{
- return m_controller->shadowQuality();
+ m_cachedGeometry = newGeometry;
+
+ updateWindowParameters();
}
-void AbstractDeclarative::setItemLabelFormat(const QString &format)
+void AbstractDeclarative::itemChange(ItemChange change, const ItemChangeData & value)
{
- m_controller->activeDataProxy()->setItemLabelFormat(format);
+ QQuickItem::itemChange(change, value);
+ updateWindowParameters();
}
-QString AbstractDeclarative::itemLabelFormat() const
+void AbstractDeclarative::updateWindowParameters()
{
- return m_controller->activeDataProxy()->itemLabelFormat();
+ // Update the device pixel ratio, window size and bounding box
+ QQuickWindow *win = window();
+ Q3DScene *scene = m_controller->scene();
+ if (win) {
+ if (win->devicePixelRatio() != scene->devicePixelRatio()) {
+ scene->setDevicePixelRatio(win->devicePixelRatio());
+ win->update();
+ }
+
+ if (win->size() != scene->d_ptr->windowSize()) {
+ scene->d_ptr->setWindowSize(QSize(win->width(), win->height()));
+ win->update();
+ }
+
+ QPointF point = QQuickItem::mapToScene(QPointF(m_cachedGeometry.x(), m_cachedGeometry.y()));
+ if (m_controller) {
+ scene->d_ptr->setViewport(QRect(point.x(), point.y(), m_cachedGeometry.width(), m_cachedGeometry.height()));
+ }
+ }
}
-void AbstractDeclarative::setSharedController(Abstract3DController *controller)
+void AbstractDeclarative::render()
{
- Q_ASSERT(controller);
- m_controller = controller;
- QObject::connect(m_controller, &Abstract3DController::shadowQualityChanged, this,
- &AbstractDeclarative::handleShadowQualityUpdate);
- emit sceneChanged(m_controller->scene());
- QObject::connect(m_controller, &Abstract3DController::activeInputHandlerChanged, this,
- &AbstractDeclarative::handleInputHandlerUpdate);
- emit inputHandlerChanged(m_controller->activeInputHandler());
+ updateWindowParameters();
+
+ // Clear the background as that is not done by default
+ glViewport(0, 0, window()->width(), window()->height());
+ QColor clearColor = window()->color();
+ glClearColor(clearColor.redF(), clearColor.greenF(), clearColor.blueF(), 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ // TODO: Store the state of these and restore before returning
+ glDepthMask(GL_TRUE);
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+ glDisable(GL_BLEND);
+
+ m_controller->render();
+
+ glEnable(GL_BLEND);
}
QAbstract3DInputHandler* AbstractDeclarative::inputHandler() const
@@ -147,27 +188,24 @@ void AbstractDeclarative::mouseDoubleClickEvent(QMouseEvent *event)
void AbstractDeclarative::touchEvent(QTouchEvent *event)
{
m_controller->touchEvent(event);
- update();
+ window()->update();
}
void AbstractDeclarative::mousePressEvent(QMouseEvent *event)
{
QPoint mousePos = event->pos();
- //mousePos.setY(height() - mousePos.y());
m_controller->mousePressEvent(event, mousePos);
}
void AbstractDeclarative::mouseReleaseEvent(QMouseEvent *event)
{
QPoint mousePos = event->pos();
- //mousePos.setY(height() - mousePos.y());
m_controller->mouseReleaseEvent(event, mousePos);
}
void AbstractDeclarative::mouseMoveEvent(QMouseEvent *event)
{
QPoint mousePos = event->pos();
- //mousePos.setY(height() - mousePos.y());
m_controller->mouseMoveEvent(event, mousePos);
}
@@ -176,14 +214,4 @@ void AbstractDeclarative::wheelEvent(QWheelEvent *event)
m_controller->wheelEvent(event);
}
-void AbstractDeclarative::handleShadowQualityUpdate(QDataVis::ShadowQuality quality)
-{
- emit shadowQualityChanged(quality);
-}
-
-void AbstractDeclarative::handleInputHandlerUpdate(QAbstract3DInputHandler *inputHandler)
-{
- emit inputHandlerChanged(inputHandler);
-}
-
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualizationqml2/abstractdeclarative_p.h b/src/datavisualizationqml2/abstractdeclarative_p.h
index 41d4a4da..42cf13a4 100644
--- a/src/datavisualizationqml2/abstractdeclarative_p.h
+++ b/src/datavisualizationqml2/abstractdeclarative_p.h
@@ -36,27 +36,18 @@
#include <QAbstractItemModel>
#include <QQuickItem>
#include <QObject>
+#include <QQuickWindow>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class AbstractDeclarative : public QQuickItem
{
Q_OBJECT
- Q_PROPERTY(QtDataVisualization::QDataVis::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode)
- Q_PROPERTY(QtDataVisualization::QDataVis::LabelStyle labelStyle READ labelStyle WRITE setLabelStyle)
- Q_PROPERTY(QtDataVisualization::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality)
+ Q_PROPERTY(QtDataVisualization::QDataVis::SelectionFlags selectionMode READ selectionMode WRITE setSelectionMode NOTIFY selectionModeChanged)
+ Q_PROPERTY(QtDataVisualization::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality NOTIFY shadowQualityChanged)
Q_PROPERTY(Q3DScene* scene READ scene NOTIFY sceneChanged)
Q_PROPERTY(QAbstract3DInputHandler* inputHandler READ inputHandler WRITE setInputHandler NOTIFY inputHandlerChanged)
- Q_PROPERTY(QtDataVisualization::QDataVis::Theme theme READ theme WRITE setTheme)
- Q_PROPERTY(QFont font READ font WRITE setFont)
- Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible)
- Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible)
- Q_PROPERTY(QString itemLabelFormat READ itemLabelFormat WRITE setItemLabelFormat)
- Q_ENUMS(QtDataVisualization::QDataVis::SelectionMode)
- Q_ENUMS(QtDataVisualization::QDataVis::ShadowQuality)
- Q_ENUMS(QtDataVisualization::QDataVis::LabelStyle)
- Q_ENUMS(QtDataVisualization::QDataVis::CameraPreset)
- Q_ENUMS(QtDataVisualization::QDataVis::Theme)
+ Q_PROPERTY(Q3DTheme* theme READ theme WRITE setTheme NOTIFY themeChanged)
public:
explicit AbstractDeclarative(QQuickItem *parent = 0);
@@ -67,31 +58,21 @@ public:
virtual QAbstract3DInputHandler *inputHandler() const;
virtual void setInputHandler(QAbstract3DInputHandler *inputHandler);
- virtual void setTheme(QDataVis::Theme theme);
- virtual QDataVis::Theme theme() const;
+ virtual void setTheme(Q3DTheme *theme);
+ virtual Q3DTheme *theme() const;
- virtual void setSelectionMode(QDataVis::SelectionMode mode);
- virtual QDataVis::SelectionMode selectionMode() const;
+ virtual void setSelectionMode(QDataVis::SelectionFlags mode);
+ virtual QDataVis::SelectionFlags selectionMode() const;
- virtual void setFont(const QFont &font);
- virtual QFont font() const;
-
- virtual void setLabelStyle(QDataVis::LabelStyle style);
- virtual QDataVis::LabelStyle labelStyle() const;
-
- virtual void setGridVisible(bool visible);
- virtual bool isGridVisible() const;
-
- virtual void setBackgroundVisible(bool visible);
- virtual bool isBackgroundVisible() const;
+ virtual void geometryChanged(const QRectF & newGeometry, const QRectF & oldGeometry);
virtual void setShadowQuality(QDataVis::ShadowQuality quality);
virtual QDataVis::ShadowQuality shadowQuality() const;
- virtual void setItemLabelFormat(const QString &format);
- virtual QString itemLabelFormat() const;
-
void setSharedController(Abstract3DController *controller);
+ // Used to synch up data model from controller to renderer while main thread is locked
+ void synchDataToRenderer();
+ void render();
protected:
virtual void mouseDoubleClickEvent(QMouseEvent *event);
@@ -100,18 +81,22 @@ protected:
virtual void mouseReleaseEvent(QMouseEvent *event);
virtual void mouseMoveEvent(QMouseEvent *event);
virtual void wheelEvent(QWheelEvent *event);
+ virtual void handleWindowChanged(QQuickWindow *win);
+ virtual void itemChange(ItemChange change, const ItemChangeData &value);
+ virtual void updateWindowParameters();
- // Used to detect when shadow quality changes autonomously due to e.g. resizing.
- virtual void handleShadowQualityUpdate(QDataVis::ShadowQuality quality);
- virtual void handleInputHandlerUpdate(QAbstract3DInputHandler *inputHandler);
signals:
// Signals shadow quality changes.
void shadowQualityChanged(QDataVis::ShadowQuality quality);
- void sceneChanged(Q3DScene *scene);
void inputHandlerChanged(QAbstract3DInputHandler *inputHandler);
+ void themeChanged(Q3DTheme *theme);
+ void selectionModeChanged(QDataVis::SelectionFlags mode);
+ void itemLabelFormatChanged(QString format);
+ void sceneChanged(Q3DScene *scene);
private:
Abstract3DController *m_controller;
+ QRectF m_cachedGeometry;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualizationqml2/colorgradient.cpp b/src/datavisualizationqml2/colorgradient.cpp
index 43efbd1c..e4c16ebe 100644
--- a/src/datavisualizationqml2/colorgradient.cpp
+++ b/src/datavisualizationqml2/colorgradient.cpp
@@ -34,6 +34,7 @@ void ColorGradientStop::setPosition(qreal position)
{
m_position = position;
updateGradient();
+ emit positionChanged(position);
}
QColor ColorGradientStop::color() const
@@ -45,6 +46,7 @@ void ColorGradientStop::setColor(const QColor &color)
{
m_color = color;
updateGradient();
+ emit colorChanged(color);
}
void ColorGradientStop::updateGradient()
diff --git a/src/datavisualizationqml2/colorgradient_p.h b/src/datavisualizationqml2/colorgradient_p.h
index 37d3e407..59653331 100644
--- a/src/datavisualizationqml2/colorgradient_p.h
+++ b/src/datavisualizationqml2/colorgradient_p.h
@@ -39,8 +39,8 @@ class ColorGradientStop : public QObject
{
Q_OBJECT
- Q_PROPERTY(qreal position READ position WRITE setPosition)
- Q_PROPERTY(QColor color READ color WRITE setColor)
+ Q_PROPERTY(qreal position READ position WRITE setPosition NOTIFY positionChanged)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
public:
ColorGradientStop(QObject *parent = 0);
@@ -51,6 +51,10 @@ public:
QColor color() const;
void setColor(const QColor &color);
+signals:
+ void positionChanged(qreal position);
+ void colorChanged(QColor color);
+
private:
void updateGradient();
@@ -72,17 +76,11 @@ public:
QQmlListProperty<ColorGradientStop> stops();
-Q_SIGNALS:
- void updated();
-
-private:
void doUpdate();
-
-private:
QList<ColorGradientStop *> m_stops;
- friend class ColorGradientStop;
- friend class DeclarativeSurface;
+Q_SIGNALS:
+ void updated();
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualizationqml2/datavisualizationqml2.pro b/src/datavisualizationqml2/datavisualizationqml2.pro
index db684988..989b52b9 100644
--- a/src/datavisualizationqml2/datavisualizationqml2.pro
+++ b/src/datavisualizationqml2/datavisualizationqml2.pro
@@ -15,29 +15,30 @@ INCLUDEPATH += ../../include \
../../include/QtDataVisualization \
../datavisualization/engine \
../datavisualization/global \
- ../datavisualization/data
+ ../datavisualization/data \
+ ../datavisualization/theme
SOURCES += \
datavisualizationqml2_plugin.cpp \
declarativebars.cpp \
- declarativebarsrenderer.cpp \
declarativescatter.cpp \
- declarativescatterrenderer.cpp \
declarativesurface.cpp \
- declarativesurfacerenderer.cpp \
abstractdeclarative.cpp \
- colorgradient.cpp
+ colorgradient.cpp \
+ declarativeseries.cpp \
+ declarativetheme.cpp \
+ declarativecolor.cpp
HEADERS += \
datavisualizationqml2_plugin.h \
declarativebars_p.h \
- declarativebarsrenderer_p.h \
declarativescatter_p.h \
- declarativescatterrenderer_p.h \
declarativesurface_p.h \
- declarativesurfacerenderer_p.h \
abstractdeclarative_p.h \
- colorgradient_p.h
+ colorgradient_p.h \
+ declarativeseries_p.h \
+ declarativetheme_p.h \
+ declarativecolor_p.h
OTHER_FILES = qmldir
diff --git a/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp b/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp
index be50982d..8dcdfbcc 100644
--- a/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp
+++ b/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp
@@ -40,13 +40,21 @@ void Datavis3Dqml2Plugin::registerTypes(const char *uri)
qmlRegisterUncreatableType<QSurfaceDataProxy>(uri, 1, 0, "SurfaceDataProxy",
QLatin1String("Trying to create uncreatable: SurfaceDataProxy."));
qmlRegisterUncreatableType<AbstractDeclarative>(uri, 1, 0, "AbstractGraph3D",
- QLatin1String("Trying to create uncreatable: AbstractGraph3D."));
+ QLatin1String("Trying to create uncreatable: AbstractGraph3D."));
qmlRegisterUncreatableType<Q3DScene>(uri, 1, 0, "Scene3D",
- QLatin1String("Trying to create uncreatable: Scene3D."));
-
- qmlRegisterType<QItemModelBarDataMapping>(uri, 1, 0, "BarDataMapping");
- qmlRegisterType<QItemModelScatterDataMapping>(uri, 1, 0, "ScatterDataMapping");
- qmlRegisterType<QItemModelSurfaceDataMapping>(uri, 1, 0, "SurfaceDataMapping");
+ QLatin1String("Trying to create uncreatable: Scene3D."));
+ qmlRegisterUncreatableType<QAbstract3DSeries>(uri, 1, 0, "Abstract3DSeries",
+ QLatin1String("Trying to create uncreatable: Abstract3DSeries."));
+ qmlRegisterUncreatableType<QBar3DSeries>(uri, 1, 0, "QBar3DSeries",
+ QLatin1String("Trying to create uncreatable: QBar3DSeries, use Bar3DSeries instead."));
+ qmlRegisterUncreatableType<QScatter3DSeries>(uri, 1, 0, "QScatter3DSeries",
+ QLatin1String("Trying to create uncreatable: QScatter3DSeries, use Scatter3DSeries instead."));
+ qmlRegisterUncreatableType<QSurface3DSeries>(uri, 1, 0, "QSurface3DSeries",
+ QLatin1String("Trying to create uncreatable: QSurface3DSeries, use Surface3DSeries instead."));
+ qmlRegisterUncreatableType<Q3DTheme>(uri, 1, 0, "Q3DTheme",
+ QLatin1String("Trying to create uncreatable: Q3DTheme, use Theme3D instead."));
+ qmlRegisterUncreatableType<QAbstract3DInputHandler>(uri, 1, 0, "AbstractInputHandler3D",
+ QLatin1String("Trying to create uncreatable: AbstractInputHandler3D."));
qmlRegisterType<DeclarativeBars>(uri, 1, 0, "Bars3D");
qmlRegisterType<DeclarativeScatter>(uri, 1, 0, "Scatter3D");
@@ -56,6 +64,7 @@ void Datavis3Dqml2Plugin::registerTypes(const char *uri)
qmlRegisterType<Q3DCategoryAxis>(uri, 1, 0, "CategoryAxis3D");
qmlRegisterType<Q3DCamera>(uri, 1, 0, "Camera3D");
+ qmlRegisterType<Q3DLight>(uri, 1, 0, "Light3D");
qmlRegisterType<QItemModelBarDataProxy>(uri, 1, 0, "ItemModelBarDataProxy");
qmlRegisterType<QItemModelScatterDataProxy>(uri, 1, 0, "ItemModelScatterDataProxy");
@@ -64,6 +73,13 @@ void Datavis3Dqml2Plugin::registerTypes(const char *uri)
qmlRegisterType<ColorGradientStop>(uri, 1, 0, "ColorGradientStop");
qmlRegisterType<ColorGradient>(uri, 1, 0, "ColorGradient");
+
+ qmlRegisterType<DeclarativeColor>(uri, 1, 0, "ThemeColor");
+ qmlRegisterType<DeclarativeTheme3D>(uri, 1, 0, "Theme3D");
+
+ qmlRegisterType<DeclarativeBar3DSeries>(uri, 1, 0, "Bar3DSeries");
+ qmlRegisterType<DeclarativeScatter3DSeries>(uri, 1, 0, "Scatter3DSeries");
+ qmlRegisterType<DeclarativeSurface3DSeries>(uri, 1, 0, "Surface3DSeries");
}
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualizationqml2/datavisualizationqml2_plugin.h b/src/datavisualizationqml2/datavisualizationqml2_plugin.h
index c0d7c4b8..25c06364 100644
--- a/src/datavisualizationqml2/datavisualizationqml2_plugin.h
+++ b/src/datavisualizationqml2/datavisualizationqml2_plugin.h
@@ -23,9 +23,6 @@
#include "declarativebars_p.h"
#include "declarativescatter_p.h"
#include "declarativesurface_p.h"
-#include "qitemmodelbardatamapping.h"
-#include "qitemmodelscatterdatamapping.h"
-#include "qitemmodelsurfacedatamapping.h"
#include "qitemmodelbardataproxy.h"
#include "qitemmodelscatterdataproxy.h"
#include "qitemmodelsurfacedataproxy.h"
@@ -35,6 +32,16 @@
#include "q3dobject.h"
#include "q3dcamera.h"
#include "q3dscene.h"
+#include "q3dlight.h"
+#include "qabstract3dseries.h"
+#include "qbar3dseries.h"
+#include "qscatter3dseries.h"
+#include "qsurface3dseries.h"
+#include "declarativeseries_p.h"
+#include "q3dtheme.h"
+#include "declarativetheme_p.h"
+#include "qabstract3dinputhandler.h"
+#include "declarativecolor_p.h"
#include <QQmlExtensionPlugin>
@@ -45,10 +52,6 @@ QML_DECLARE_TYPE(DeclarativeBars)
QML_DECLARE_TYPE(DeclarativeScatter)
QML_DECLARE_TYPE(DeclarativeSurface)
-QML_DECLARE_TYPE(QItemModelBarDataMapping)
-QML_DECLARE_TYPE(QItemModelScatterDataMapping)
-QML_DECLARE_TYPE(QItemModelSurfaceDataMapping)
-
QML_DECLARE_TYPE(const QAbstractItemModel)
QML_DECLARE_TYPE(QDataVis)
@@ -57,7 +60,9 @@ QML_DECLARE_TYPE(Q3DCategoryAxis)
QML_DECLARE_TYPE(Q3DValueAxis)
QML_DECLARE_TYPE(Q3DScene)
+QML_DECLARE_TYPE(Q3DObject)
QML_DECLARE_TYPE(Q3DCamera)
+QML_DECLARE_TYPE(Q3DLight)
QML_DECLARE_TYPE(QAbstractDataProxy)
QML_DECLARE_TYPE(QBarDataProxy)
@@ -68,9 +73,24 @@ QML_DECLARE_TYPE(QSurfaceDataProxy)
QML_DECLARE_TYPE(QItemModelSurfaceDataProxy)
QML_DECLARE_TYPE(QHeightMapSurfaceDataProxy)
+QML_DECLARE_TYPE(QAbstract3DSeries)
+QML_DECLARE_TYPE(QBar3DSeries)
+QML_DECLARE_TYPE(QScatter3DSeries)
+QML_DECLARE_TYPE(QSurface3DSeries)
+QML_DECLARE_TYPE(DeclarativeBar3DSeries)
+QML_DECLARE_TYPE(DeclarativeScatter3DSeries)
+QML_DECLARE_TYPE(DeclarativeSurface3DSeries)
+
QML_DECLARE_TYPE(ColorGradientStop)
QML_DECLARE_TYPE(ColorGradient)
+QML_DECLARE_TYPE(DeclarativeColor)
+
+QML_DECLARE_TYPE(Q3DTheme)
+QML_DECLARE_TYPE(DeclarativeTheme3D)
+
+QML_DECLARE_TYPE(QAbstract3DInputHandler)
+
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class Datavis3Dqml2Plugin : public QQmlExtensionPlugin
diff --git a/src/datavisualizationqml2/declarativebars.cpp b/src/datavisualizationqml2/declarativebars.cpp
index 9ed80106..7eab8886 100644
--- a/src/datavisualizationqml2/declarativebars.cpp
+++ b/src/datavisualizationqml2/declarativebars.cpp
@@ -17,21 +17,15 @@
****************************************************************************/
#include "declarativebars_p.h"
-#include "declarativebarsrenderer_p.h"
#include "q3dvalueaxis.h"
#include "qitemmodelbardataproxy.h"
-#include "theme_p.h"
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-const QString smoothString(QStringLiteral("Smooth"));
-
DeclarativeBars::DeclarativeBars(QQuickItem *parent)
: AbstractDeclarative(parent),
- m_shared(0),
- m_initialisedSize(0, 0)
+ m_barsController(0)
{
- setFlags(QQuickItem::ItemHasContents);
setAcceptedMouseButtons(Qt::AllButtons);
// TODO: These seem to have no effect; find a way to activate anti-aliasing
@@ -39,176 +33,134 @@ DeclarativeBars::DeclarativeBars(QQuickItem *parent)
setSmooth(true);
// Create the shared component on the main GUI thread.
- m_shared = new Bars3DController(boundingRect().toRect());
- AbstractDeclarative::setSharedController(m_shared);
- QObject::connect(m_shared, &Bars3DController::selectedBarPosChanged, this,
- &DeclarativeBars::selectedBarPosChanged);
+ m_barsController = new Bars3DController(boundingRect().toRect());
+ AbstractDeclarative::setSharedController(m_barsController);
- QItemModelBarDataProxy *proxy = new QItemModelBarDataProxy;
- m_shared->setActiveDataProxy(proxy);
+ // TODO: Uncomment when doing QTRD-2669
+// connect(m_barsController, &Bars3DController::rowAxisChanged,
+// this, &DeclarativeBars::rowAxisChanged);
+// connect(m_barsController, &Bars3DController::valueAxisChanged,
+// this, &DeclarativeBars::valueAxisChanged);
+// connect(m_barsController, &Bars3DController::columnAxisChanged,
+// this, &DeclarativeBars::columnAxisChanged);
}
DeclarativeBars::~DeclarativeBars()
{
- delete m_shared;
-}
-
-
-QSGNode *DeclarativeBars::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
-{
- // If old node exists and has right size, reuse it.
- if (oldNode && m_initialisedSize == boundingRect().size().toSize()) {
- // Update bounding rectangle (that has same size as before).
- static_cast<DeclarativeBarsRenderer *>( oldNode )->setRect(boundingRect());
- return oldNode;
- }
-
- // Create a new render node when size changes or if there is no node yet
- m_initialisedSize = boundingRect().size().toSize();
-
- // Delete old node
- if (oldNode)
- delete oldNode;
-
- // Create a new one and set it's bounding rectangle
- DeclarativeBarsRenderer *node = new DeclarativeBarsRenderer(window(), m_shared);
- node->setRect(boundingRect());
- m_shared->setBoundingRect(boundingRect().toRect());
- return node;
-}
-
-void DeclarativeBars::setBarColor(const QColor &baseColor, bool uniform)
-{
- m_shared->setObjectColor(baseColor, uniform);
-}
-
-void DeclarativeBars::setDataProxy(QBarDataProxy *dataProxy)
-{
- m_shared->setActiveDataProxy(dataProxy);
-}
-
-QBarDataProxy *DeclarativeBars::dataProxy() const
-{
- return static_cast<QBarDataProxy *>(m_shared->activeDataProxy());
+ delete m_barsController;
}
Q3DCategoryAxis *DeclarativeBars::rowAxis() const
{
- return static_cast<Q3DCategoryAxis *>(m_shared->axisX());
+ return static_cast<Q3DCategoryAxis *>(m_barsController->axisZ());
}
void DeclarativeBars::setRowAxis(Q3DCategoryAxis *axis)
{
- m_shared->setAxisX(axis);
+ m_barsController->setAxisZ(axis);
}
Q3DValueAxis *DeclarativeBars::valueAxis() const
{
- return static_cast<Q3DValueAxis *>(m_shared->axisY());
+ return static_cast<Q3DValueAxis *>(m_barsController->axisY());
}
void DeclarativeBars::setValueAxis(Q3DValueAxis *axis)
{
- m_shared->setAxisY(axis);
+ m_barsController->setAxisY(axis);
}
Q3DCategoryAxis *DeclarativeBars::columnAxis() const
{
- return static_cast<Q3DCategoryAxis *>(m_shared->axisZ());
+ return static_cast<Q3DCategoryAxis *>(m_barsController->axisX());
}
void DeclarativeBars::setColumnAxis(Q3DCategoryAxis *axis)
{
- m_shared->setAxisZ(axis);
+ m_barsController->setAxisX(axis);
}
-void DeclarativeBars::setBarThickness(qreal thicknessRatio)
+void DeclarativeBars::setBarThickness(float thicknessRatio)
{
- m_shared->setBarSpecs(GLfloat(thicknessRatio), barSpacing(), isBarSpacingRelative());
+ if (thicknessRatio != barThickness()) {
+ m_barsController->setBarSpecs(GLfloat(thicknessRatio), barSpacing(), isBarSpacingRelative());
+ emit barThicknessChanged(thicknessRatio);
+ }
}
-qreal DeclarativeBars::barThickness() const
+float DeclarativeBars::barThickness() const
{
- return m_shared->barThickness();
+ return m_barsController->barThickness();
}
void DeclarativeBars::setBarSpacing(QSizeF spacing)
{
- m_shared->setBarSpecs(GLfloat(barThickness()), spacing, isBarSpacingRelative());
+ if (spacing != barSpacing()) {
+ m_barsController->setBarSpecs(GLfloat(barThickness()), spacing, isBarSpacingRelative());
+ emit barSpacingChanged(spacing);
+ }
}
QSizeF DeclarativeBars::barSpacing() const
{
- return m_shared->barSpacing();
+ return m_barsController->barSpacing();
}
void DeclarativeBars::setBarSpacingRelative(bool relative)
{
- m_shared->setBarSpecs(GLfloat(barThickness()), barSpacing(), relative);
+ if (relative != isBarSpacingRelative()) {
+ m_barsController->setBarSpecs(GLfloat(barThickness()), barSpacing(), relative);
+ emit barSpacingRelativeChanged(relative);
+ }
}
bool DeclarativeBars::isBarSpacingRelative() const
{
- return m_shared->isBarSpecRelative();
-}
-
-void DeclarativeBars::setBarType(QDataVis::MeshStyle style)
-{
- QString objFile = m_shared->meshFileName();
- bool smooth = objFile.endsWith(smoothString);
- m_shared->setBarType(style, smooth);
+ return m_barsController->isBarSpecRelative();
}
-QDataVis::MeshStyle DeclarativeBars::barType() const
+QQmlListProperty<QBar3DSeries> DeclarativeBars::seriesList()
{
- QString objFile = m_shared->meshFileName();
- if (objFile.contains("/sphere"))
- return QDataVis::MeshStyleSpheres;
- else
- return QDataVis::MeshStyleDots;
+ return QQmlListProperty<QBar3DSeries>(this, this,
+ &DeclarativeBars::appendSeriesFunc,
+ &DeclarativeBars::countSeriesFunc,
+ &DeclarativeBars::atSeriesFunc,
+ &DeclarativeBars::clearSeriesFunc);
}
-void DeclarativeBars::setBarSmoothingEnabled(bool enabled)
+void DeclarativeBars::appendSeriesFunc(QQmlListProperty<QBar3DSeries> *list, QBar3DSeries *series)
{
- QString objFile = m_shared->meshFileName();
- if (objFile.endsWith(smoothString)) {
- if (enabled)
- return; // Already smooth; do nothing
- else // Rip Smooth off the end
- objFile.resize(objFile.indexOf(smoothString));
- } else {
- if (!enabled) // Already flat; do nothing
- return;
- else // Append Smooth to the end
- objFile.append(smoothString);
- }
- m_shared->setMeshFileName(objFile);
+ reinterpret_cast<DeclarativeBars *>(list->data)->addSeries(series);
}
-bool DeclarativeBars::isBarSmoothingEnabled() const
+int DeclarativeBars::countSeriesFunc(QQmlListProperty<QBar3DSeries> *list)
{
- QString objFile = m_shared->meshFileName();
- return objFile.endsWith(smoothString);
+ return reinterpret_cast<DeclarativeBars *>(list->data)->m_barsController->barSeriesList().size();
}
-void DeclarativeBars::setMeshFileName(const QString &objFileName)
+QBar3DSeries *DeclarativeBars::atSeriesFunc(QQmlListProperty<QBar3DSeries> *list, int index)
{
- m_shared->setMeshFileName(objFileName);
+ return reinterpret_cast<DeclarativeBars *>(list->data)->m_barsController->barSeriesList().at(index);
}
-QString DeclarativeBars::meshFileName() const
+void DeclarativeBars::clearSeriesFunc(QQmlListProperty<QBar3DSeries> *list)
{
- return m_shared->meshFileName();
+ DeclarativeBars *declBars = reinterpret_cast<DeclarativeBars *>(list->data);
+ QList<QBar3DSeries *> realList = declBars->m_barsController->barSeriesList();
+ int count = realList.size();
+ for (int i = 0; i < count; i++)
+ declBars->removeSeries(realList.at(i));
}
-void DeclarativeBars::setSelectedBarPos(const QPointF &position)
+void DeclarativeBars::addSeries(QBar3DSeries *series)
{
- m_shared->setSelectedBarPos(position.toPoint());
+ m_barsController->addSeries(series);
}
-QPointF DeclarativeBars::selectedBarPos() const
+void DeclarativeBars::removeSeries(QBar3DSeries *series)
{
- return QPointF(m_shared->selectedBarPos());
+ m_barsController->removeSeries(series);
+ series->setParent(this); // Reparent as removing will leave series parentless
}
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualizationqml2/declarativebars_p.h b/src/datavisualizationqml2/declarativebars_p.h
index dfbf9934..29d9dc91 100644
--- a/src/datavisualizationqml2/declarativebars_p.h
+++ b/src/datavisualizationqml2/declarativebars_p.h
@@ -36,6 +36,7 @@
#include "q3dvalueaxis.h"
#include "q3dcategoryaxis.h"
#include "qbardataproxy.h"
+#include "qbar3dseries.h"
#include <QAbstractItemModel>
#include <QQuickItem>
@@ -47,28 +48,19 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class DeclarativeBars : public AbstractDeclarative
{
Q_OBJECT
- Q_PROPERTY(QBarDataProxy *dataProxy READ dataProxy WRITE setDataProxy)
- Q_PROPERTY(Q3DCategoryAxis *rowAxis READ rowAxis WRITE setRowAxis)
- Q_PROPERTY(Q3DValueAxis *valueAxis READ valueAxis WRITE setValueAxis)
- Q_PROPERTY(Q3DCategoryAxis *columnAxis READ columnAxis WRITE setColumnAxis)
- Q_PROPERTY(QtDataVisualization::QDataVis::MeshStyle barType READ barType WRITE setBarType)
- Q_PROPERTY(qreal barThickness READ barThickness WRITE setBarThickness)
- Q_PROPERTY(QSizeF barSpacing READ barSpacing WRITE setBarSpacing)
- Q_PROPERTY(bool barSpacingRelative READ isBarSpacingRelative WRITE setBarSpacingRelative)
- Q_PROPERTY(bool barSmoothingEnabled READ isBarSmoothingEnabled WRITE setBarSmoothingEnabled)
- Q_PROPERTY(QString meshFileName READ meshFileName WRITE setMeshFileName)
- Q_PROPERTY(QPointF selectedBarPos READ selectedBarPos WRITE setSelectedBarPos NOTIFY selectedBarPosChanged)
- Q_ENUMS(QtDataVisualization::QDataVis::MeshStyle)
+ Q_PROPERTY(Q3DCategoryAxis *rowAxis READ rowAxis WRITE setRowAxis NOTIFY rowAxisChanged)
+ Q_PROPERTY(Q3DValueAxis *valueAxis READ valueAxis WRITE setValueAxis NOTIFY valueAxisChanged)
+ Q_PROPERTY(Q3DCategoryAxis *columnAxis READ columnAxis WRITE setColumnAxis NOTIFY columnAxisChanged)
+ Q_PROPERTY(float barThickness READ barThickness WRITE setBarThickness NOTIFY barThicknessChanged)
+ Q_PROPERTY(QSizeF barSpacing READ barSpacing WRITE setBarSpacing NOTIFY barSpacingChanged)
+ Q_PROPERTY(bool barSpacingRelative READ isBarSpacingRelative WRITE setBarSpacingRelative NOTIFY barSpacingRelativeChanged)
+ Q_PROPERTY(QQmlListProperty<QBar3DSeries> seriesList READ seriesList)
+ Q_CLASSINFO("DefaultProperty", "seriesList")
public:
explicit DeclarativeBars(QQuickItem *parent = 0);
~DeclarativeBars();
- Q_INVOKABLE void setBarColor(const QColor &baseColor, bool uniform = true);
-
- QBarDataProxy *dataProxy() const;
- void setDataProxy(QBarDataProxy *dataProxy);
-
Q3DCategoryAxis *rowAxis() const;
void setRowAxis(Q3DCategoryAxis *axis);
Q3DValueAxis *valueAxis() const;
@@ -76,8 +68,8 @@ public:
Q3DCategoryAxis *columnAxis() const;
void setColumnAxis(Q3DCategoryAxis *axis);
- void setBarThickness(qreal thicknessRatio);
- qreal barThickness() const;
+ void setBarThickness(float thicknessRatio);
+ float barThickness() const;
void setBarSpacing(QSizeF spacing);
QSizeF barSpacing() const;
@@ -85,27 +77,25 @@ public:
void setBarSpacingRelative(bool relative);
bool isBarSpacingRelative() const;
- void setBarType(QDataVis::MeshStyle style);
- QDataVis::MeshStyle barType() const;
-
- void setBarSmoothingEnabled(bool enabled);
- bool isBarSmoothingEnabled() const;
-
- void setMeshFileName(const QString &objFileName);
- QString meshFileName() const;
-
- void setSelectedBarPos(const QPointF &position);
- QPointF selectedBarPos() const;
+ QQmlListProperty<QBar3DSeries> seriesList();
+ static void appendSeriesFunc(QQmlListProperty<QBar3DSeries> *list, QBar3DSeries *series);
+ static int countSeriesFunc(QQmlListProperty<QBar3DSeries> *list);
+ static QBar3DSeries *atSeriesFunc(QQmlListProperty<QBar3DSeries> *list, int index);
+ static void clearSeriesFunc(QQmlListProperty<QBar3DSeries> *list);
+ Q_INVOKABLE void addSeries(QBar3DSeries *series);
+ Q_INVOKABLE void removeSeries(QBar3DSeries *series);
signals:
- void selectedBarPosChanged(const QPointF &position);
-
-protected:
- QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *);
+ void rowAxisChanged(Q3DCategoryAxis *axis);
+ void valueAxisChanged(Q3DValueAxis *axis);
+ void columnAxisChanged(Q3DCategoryAxis *axis);
+ void barThicknessChanged(float thicknessRatio);
+ void barSpacingChanged(QSizeF spacing);
+ void barSpacingRelativeChanged(bool relative);
+ void meshFileNameChanged(QString filename);
private:
- Bars3DController *m_shared;
- QSize m_initialisedSize;
+ Bars3DController *m_barsController;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualizationqml2/declarativebarsrenderer.cpp b/src/datavisualizationqml2/declarativebarsrenderer.cpp
deleted file mode 100644
index 3925e062..00000000
--- a/src/datavisualizationqml2/declarativebarsrenderer.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use contact form at http://qt.digia.com
-**
-** This file is part of the QtDataVisualization module.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** contact form at http://qt.digia.com
-**
-****************************************************************************/
-
-#include "declarativebarsrenderer_p.h"
-
-#include <QtQuick/QQuickWindow>
-#include <QtGui/QOpenGLFramebufferObject>
-
-QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-
-DeclarativeBarsRenderer::DeclarativeBarsRenderer(QQuickWindow *window, Bars3DController *renderer)
- : m_fbo(0),
- m_texture(0),
- m_window(window),
- m_barsRenderer(renderer)
-{
- connect(m_window, &QQuickWindow::beforeSynchronizing, this,
- &DeclarativeBarsRenderer::synchDataToRenderer, Qt::DirectConnection);
- connect(m_window, &QQuickWindow::beforeRendering, this,
- &DeclarativeBarsRenderer::renderFBO, Qt::DirectConnection);
- connect(m_barsRenderer, &Abstract3DController::needRender, m_window,
- &QQuickWindow::update);
-}
-
-DeclarativeBarsRenderer::~DeclarativeBarsRenderer()
-{
- delete m_texture;
- delete m_fbo;
-}
-
-void DeclarativeBarsRenderer::synchDataToRenderer()
-{
- m_barsRenderer->initializeOpenGL();
- m_barsRenderer->synchDataToRenderer();
-}
-
-void DeclarativeBarsRenderer::renderFBO()
-{
- QSize size = rect().size().toSize();
-
- // Create FBO
- if (!m_fbo) {
- QOpenGLFramebufferObjectFormat format;
- format.setAttachment(QOpenGLFramebufferObject::Depth);
- m_fbo = new QOpenGLFramebufferObject(size, format);
- m_texture = m_window->createTextureFromId(m_fbo->texture(), size);
-
- setTexture(m_texture);
-
- // Flip texture
- // TODO: Can be gotten rid of once support for texture flipping becomes available (in Qt5.2)
- QSize ts = m_texture->textureSize();
- QRectF sourceRect(0, 0, ts.width(), ts.height());
- float tmp = sourceRect.top();
- sourceRect.setTop(sourceRect.bottom());
- sourceRect.setBottom(tmp);
- QSGGeometry *geometry = this->geometry();
- QSGGeometry::updateTexturedRectGeometry(geometry, rect(),
- m_texture->convertToNormalizedSourceRect(sourceRect));
- markDirty(DirtyMaterial);
- //qDebug() << "create node" << m_fbo->handle() << m_texture->textureId() << m_fbo->size();
- }
-
- // Call the shared rendering function
- m_fbo->bind();
-
- m_barsRenderer->render(m_fbo->handle());
-
- m_fbo->release();
-}
-
-QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/data/qabstractdatamapping.h b/src/datavisualizationqml2/declarativecolor.cpp
index eb892cb7..5c1ff8c5 100644
--- a/src/datavisualization/data/qabstractdatamapping.h
+++ b/src/datavisualizationqml2/declarativecolor.cpp
@@ -16,38 +16,26 @@
**
****************************************************************************/
-#ifndef QABSTRACTDATAMAPPING_H
-#define QABSTRACTDATAMAPPING_H
-
-#include <QtDataVisualization/qdatavisualizationenums.h>
-#include <QtDataVisualization/qabstractdataproxy.h>
+#include "declarativecolor_p.h"
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-class QAbstractDataMappingPrivate;
-
-class QT_DATAVISUALIZATION_EXPORT QAbstractDataMapping : public QObject
+DeclarativeColor::DeclarativeColor(QObject *parent)
+ : QObject(parent)
{
- Q_OBJECT
-
-public:
- explicit QAbstractDataMapping(QAbstractDataMappingPrivate *d, QObject *parent = 0);
- virtual ~QAbstractDataMapping();
-
-signals:
- void mappingChanged();
-
-private:
- QScopedPointer<QAbstractDataMappingPrivate> d_ptr;
+}
- Q_DISABLE_COPY(QAbstractDataMapping)
-
- friend class QItemModelBarDataMapping;
- friend class QItemModelScatterDataMapping;
- friend class QItemModelSurfaceDataMapping;
-};
+void DeclarativeColor::setColor(const QColor &color)
+{
+ if (m_color != color) {
+ m_color = color;
+ emit colorChanged(color);
+ }
+}
+QColor DeclarativeColor::color() const
+{
+ return m_color;
+}
QT_DATAVISUALIZATION_END_NAMESPACE
-
-#endif
diff --git a/src/datavisualization/data/qabstractdatamapping_p.h b/src/datavisualizationqml2/declarativecolor_p.h
index 39012237..755652b4 100644
--- a/src/datavisualization/data/qabstractdatamapping_p.h
+++ b/src/datavisualizationqml2/declarativecolor_p.h
@@ -26,23 +26,30 @@
//
// We mean it.
-#include "qabstractdatamapping.h"
+#ifndef DECLARATIVECOLOR_P_H
+#define DECLARATIVECOLOR_P_H
-#ifndef QABSTRACTDATAMAPPING_P_H
-#define QABSTRACTDATAMAPPING_P_H
+#include "datavisualizationglobal_p.h"
+#include <QColor>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-class QAbstractDataMappingPrivate : public QObject
+class DeclarativeColor : public QObject
{
Q_OBJECT
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+
public:
- QAbstractDataMappingPrivate(QAbstractDataMapping *q, QAbstractDataProxy::DataType type);
- virtual ~QAbstractDataMappingPrivate();
+ DeclarativeColor(QObject *parent = 0);
+
+ void setColor(const QColor &color);
+ QColor color() const;
+
+signals:
+ void colorChanged(QColor color);
private:
- QAbstractDataMapping *q_ptr;
- QAbstractDataProxy::DataType m_type;
+ QColor m_color;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualizationqml2/declarativescatter.cpp b/src/datavisualizationqml2/declarativescatter.cpp
index 346abec2..5aaa19b6 100644
--- a/src/datavisualizationqml2/declarativescatter.cpp
+++ b/src/datavisualizationqml2/declarativescatter.cpp
@@ -17,20 +17,14 @@
****************************************************************************/
#include "declarativescatter_p.h"
-#include "declarativescatterrenderer_p.h"
#include "qitemmodelscatterdataproxy.h"
-#include "theme_p.h"
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-const QString smoothString(QStringLiteral("Smooth"));
-
DeclarativeScatter::DeclarativeScatter(QQuickItem *parent)
: AbstractDeclarative(parent),
- m_shared(0),
- m_initialisedSize(0, 0)
+ m_scatterController(0)
{
- setFlags(QQuickItem::ItemHasContents);
setAcceptedMouseButtons(Qt::AllButtons);
// TODO: These seem to have no effect; find a way to activate anti-aliasing
@@ -38,131 +32,95 @@ DeclarativeScatter::DeclarativeScatter(QQuickItem *parent)
setSmooth(true);
// Create the shared component on the main GUI thread.
- m_shared = new Scatter3DController(boundingRect().toRect());
- setSharedController(m_shared);
- m_shared->setActiveDataProxy(new QItemModelScatterDataProxy);
-}
+ m_scatterController = new Scatter3DController(boundingRect().toRect());
+ setSharedController(m_scatterController);
-DeclarativeScatter::~DeclarativeScatter()
-{
- delete m_shared;
+ // TODO: Uncomment when doing QTRD-2669
+// connect(m_scatterController, &Scatter3DController::axisXChanged,
+// this, &DeclarativeBars::axisXChanged);
+// connect(m_scatterController, &Scatter3DController::axisYChanged,
+// this, &DeclarativeBars::axisYChanged);
+// connect(m_scatterController, &Scatter3DController::axisZChanged,
+// this, &DeclarativeBars::axisZChanged);
}
-QSGNode *DeclarativeScatter::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
-{
- // If old node exists and has right size, reuse it.
- if (oldNode && m_initialisedSize == boundingRect().size().toSize()) {
- // Update bounding rectangle (that has same size as before).
- static_cast<DeclarativeScatterRenderer *>( oldNode )->setRect(boundingRect());
- return oldNode;
- }
-
- // Create a new render node when size changes or if there is no node yet
- m_initialisedSize = boundingRect().size().toSize();
-
- // Delete old node
- if (oldNode)
- delete oldNode;
-
- // Create a new one and set it's bounding rectangle
- DeclarativeScatterRenderer *node = new DeclarativeScatterRenderer(window(), m_shared);
- node->setRect(boundingRect());
- m_shared->setBoundingRect(boundingRect().toRect());
- return node;
-}
-
-void DeclarativeScatter::setObjectColor(const QColor &baseColor, bool uniform)
-{
- m_shared->setObjectColor(baseColor, uniform);
-}
-
-QScatterDataProxy *DeclarativeScatter::dataProxy() const
-{
- return static_cast<QScatterDataProxy *>(m_shared->activeDataProxy());
-}
-
-void DeclarativeScatter::setDataProxy(QScatterDataProxy *dataProxy)
+DeclarativeScatter::~DeclarativeScatter()
{
- m_shared->setActiveDataProxy(dataProxy);
+ delete m_scatterController;
}
Q3DValueAxis *DeclarativeScatter::axisX() const
{
- return static_cast<Q3DValueAxis *>(m_shared->axisX());
+ return static_cast<Q3DValueAxis *>(m_scatterController->axisX());
}
void DeclarativeScatter::setAxisX(Q3DValueAxis *axis)
{
- m_shared->setAxisX(axis);
+ m_scatterController->setAxisX(axis);
}
Q3DValueAxis *DeclarativeScatter::axisY() const
{
- return static_cast<Q3DValueAxis *>(m_shared->axisY());
+ return static_cast<Q3DValueAxis *>(m_scatterController->axisY());
}
void DeclarativeScatter::setAxisY(Q3DValueAxis *axis)
{
- m_shared->setAxisY(axis);
+ m_scatterController->setAxisY(axis);
}
Q3DValueAxis *DeclarativeScatter::axisZ() const
{
- return static_cast<Q3DValueAxis *>(m_shared->axisZ());
+ return static_cast<Q3DValueAxis *>(m_scatterController->axisZ());
}
void DeclarativeScatter::setAxisZ(Q3DValueAxis *axis)
{
- m_shared->setAxisZ(axis);
+ m_scatterController->setAxisZ(axis);
+}
+
+QQmlListProperty<QScatter3DSeries> DeclarativeScatter::seriesList()
+{
+ return QQmlListProperty<QScatter3DSeries>(this, this,
+ &DeclarativeScatter::appendSeriesFunc,
+ &DeclarativeScatter::countSeriesFunc,
+ &DeclarativeScatter::atSeriesFunc,
+ &DeclarativeScatter::clearSeriesFunc);
}
-void DeclarativeScatter::setObjectType(QDataVis::MeshStyle style)
+void DeclarativeScatter::appendSeriesFunc(QQmlListProperty<QScatter3DSeries> *list, QScatter3DSeries *series)
{
- QString objFile = m_shared->meshFileName();
- bool smooth = objFile.endsWith(smoothString);
- m_shared->setObjectType(style, smooth);
+ reinterpret_cast<DeclarativeScatter *>(list->data)->addSeries(series);
}
-QDataVis::MeshStyle DeclarativeScatter::objectType() const
+int DeclarativeScatter::countSeriesFunc(QQmlListProperty<QScatter3DSeries> *list)
{
- QString objFile = m_shared->meshFileName();
- if (objFile.contains("/sphere"))
- return QDataVis::MeshStyleSpheres;
- else
- return QDataVis::MeshStyleDots;
+ return reinterpret_cast<DeclarativeScatter *>(list->data)->m_scatterController->scatterSeriesList().size();
}
-void DeclarativeScatter::setObjectSmoothingEnabled(bool enabled)
+QScatter3DSeries *DeclarativeScatter::atSeriesFunc(QQmlListProperty<QScatter3DSeries> *list, int index)
{
- QString objFile = m_shared->meshFileName();
- if (objFile.endsWith(smoothString)) {
- if (enabled)
- return; // Already smooth; do nothing
- else // Rip Smooth off the end
- objFile.resize(objFile.indexOf(smoothString));
- } else {
- if (!enabled) // Already flat; do nothing
- return;
- else // Append Smooth to the end
- objFile.append(smoothString);
- }
- m_shared->setMeshFileName(objFile);
+ return reinterpret_cast<DeclarativeScatter *>(list->data)->m_scatterController->scatterSeriesList().at(index);
}
-bool DeclarativeScatter::isObjectSmoothingEnabled() const
+void DeclarativeScatter::clearSeriesFunc(QQmlListProperty<QScatter3DSeries> *list)
{
- QString objFile = m_shared->meshFileName();
- return objFile.endsWith(smoothString);
+ DeclarativeScatter *declScatter = reinterpret_cast<DeclarativeScatter *>(list->data);
+ QList<QScatter3DSeries *> realList = declScatter->m_scatterController->scatterSeriesList();
+ int count = realList.size();
+ for (int i = 0; i < count; i++)
+ declScatter->removeSeries(realList.at(i));
}
-void DeclarativeScatter::setMeshFileName(const QString &objFileName)
+void DeclarativeScatter::addSeries(QScatter3DSeries *series)
{
- m_shared->setMeshFileName(objFileName);
+ m_scatterController->addSeries(series);
}
-QString DeclarativeScatter::meshFileName() const
+void DeclarativeScatter::removeSeries(QScatter3DSeries *series)
{
- return m_shared->meshFileName();
+ m_scatterController->removeSeries(series);
+ series->setParent(this); // Reparent as removing will leave series parentless
}
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualizationqml2/declarativescatter_p.h b/src/datavisualizationqml2/declarativescatter_p.h
index cc16e770..b9f5a3b7 100644
--- a/src/datavisualizationqml2/declarativescatter_p.h
+++ b/src/datavisualizationqml2/declarativescatter_p.h
@@ -35,6 +35,7 @@
#include "declarativescatter_p.h"
#include "q3dvalueaxis.h"
#include "qscatterdataproxy.h"
+#include "qscatter3dseries.h"
#include <QAbstractItemModel>
#include <QQuickItem>
@@ -45,25 +46,16 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class DeclarativeScatter : public AbstractDeclarative
{
Q_OBJECT
- Q_PROPERTY(QScatterDataProxy *dataProxy READ dataProxy WRITE setDataProxy)
- Q_PROPERTY(Q3DValueAxis *axisX READ axisX WRITE setAxisX)
- Q_PROPERTY(Q3DValueAxis *axisY READ axisY WRITE setAxisY)
- Q_PROPERTY(Q3DValueAxis *axisZ READ axisZ WRITE setAxisZ)
- Q_PROPERTY(QtDataVisualization::QDataVis::MeshStyle objectType READ objectType WRITE setObjectType)
- Q_PROPERTY(bool objectSmoothingEnabled READ isObjectSmoothingEnabled WRITE setObjectSmoothingEnabled)
- Q_PROPERTY(QString meshFileName READ meshFileName WRITE setMeshFileName)
- Q_PROPERTY(QString itemLabelFormat READ itemLabelFormat WRITE setItemLabelFormat)
- Q_ENUMS(QtDataVisualization::QDataVis::MeshStyle)
+ Q_PROPERTY(Q3DValueAxis *axisX READ axisX WRITE setAxisX NOTIFY axisXChanged)
+ Q_PROPERTY(Q3DValueAxis *axisY READ axisY WRITE setAxisY NOTIFY axisYChanged)
+ Q_PROPERTY(Q3DValueAxis *axisZ READ axisZ WRITE setAxisZ NOTIFY axisZChanged)
+ Q_PROPERTY(QQmlListProperty<QScatter3DSeries> seriesList READ seriesList)
+ Q_CLASSINFO("DefaultProperty", "seriesList")
public:
explicit DeclarativeScatter(QQuickItem *parent = 0);
~DeclarativeScatter();
- Q_INVOKABLE void setObjectColor(const QColor &baseColor, bool uniform = true);
-
- QScatterDataProxy *dataProxy() const;
- void setDataProxy(QScatterDataProxy *dataProxy);
-
Q3DValueAxis *axisX() const;
void setAxisX(Q3DValueAxis *axis);
Q3DValueAxis *axisY() const;
@@ -71,21 +63,21 @@ public:
Q3DValueAxis *axisZ() const;
void setAxisZ(Q3DValueAxis *axis);
- void setObjectType(QDataVis::MeshStyle style);
- QDataVis::MeshStyle objectType() const;
+ QQmlListProperty<QScatter3DSeries> seriesList();
+ static void appendSeriesFunc(QQmlListProperty<QScatter3DSeries> *list, QScatter3DSeries *series);
+ static int countSeriesFunc(QQmlListProperty<QScatter3DSeries> *list);
+ static QScatter3DSeries *atSeriesFunc(QQmlListProperty<QScatter3DSeries> *list, int index);
+ static void clearSeriesFunc(QQmlListProperty<QScatter3DSeries> *list);
+ Q_INVOKABLE void addSeries(QScatter3DSeries *series);
+ Q_INVOKABLE void removeSeries(QScatter3DSeries *series);
- void setObjectSmoothingEnabled(bool enabled);
- bool isObjectSmoothingEnabled() const;
-
- void setMeshFileName(const QString &objFileName);
- QString meshFileName() const;
+signals:
+ void axisXChanged(Q3DValueAxis *axis);
+ void axisYChanged(Q3DValueAxis *axis);
+ void axisZChanged(Q3DValueAxis *axis);
protected:
- Scatter3DController *m_shared;
- QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *);
-
-private:
- QSize m_initialisedSize;
+ Scatter3DController *m_scatterController;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualizationqml2/declarativescatterrenderer.cpp b/src/datavisualizationqml2/declarativescatterrenderer.cpp
deleted file mode 100644
index 39aaa22e..00000000
--- a/src/datavisualizationqml2/declarativescatterrenderer.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use contact form at http://qt.digia.com
-**
-** This file is part of the QtDataVisualization module.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** contact form at http://qt.digia.com
-**
-****************************************************************************/
-
-#include "declarativescatterrenderer_p.h"
-
-#include <QtQuick/QQuickWindow>
-#include <QtGui/QOpenGLFramebufferObject>
-
-QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-
-DeclarativeScatterRenderer::DeclarativeScatterRenderer(QQuickWindow *window,
- Scatter3DController *renderer)
- : m_fbo(0),
- m_texture(0),
- m_window(window),
- m_scatterRenderer(renderer)
-{
- connect(m_window, &QQuickWindow::beforeSynchronizing, this,
- &DeclarativeScatterRenderer::synchDataToRenderer, Qt::DirectConnection);
- connect(m_window, &QQuickWindow::beforeRendering, this,
- &DeclarativeScatterRenderer::renderFBO, Qt::DirectConnection);
- connect(m_scatterRenderer, &Abstract3DController::needRender, m_window,
- &QQuickWindow::update);
-}
-
-DeclarativeScatterRenderer::~DeclarativeScatterRenderer()
-{
- delete m_texture;
- delete m_fbo;
-}
-
-void DeclarativeScatterRenderer::synchDataToRenderer()
-{
- m_scatterRenderer->initializeOpenGL();
- m_scatterRenderer->synchDataToRenderer();
-}
-
-void DeclarativeScatterRenderer::renderFBO()
-{
- QSize size = rect().size().toSize();
-
- // Create FBO
- if (!m_fbo) {
- QOpenGLFramebufferObjectFormat format;
- format.setAttachment(QOpenGLFramebufferObject::Depth);
- m_fbo = new QOpenGLFramebufferObject(size, format);
- m_texture = m_window->createTextureFromId(m_fbo->texture(), size);
-
- setTexture(m_texture);
-
- // Flip texture
- // TODO: Can be gotten rid of once support for texture flipping becomes available (in Qt5.2)
- QSize ts = m_texture->textureSize();
- QRectF sourceRect(0, 0, ts.width(), ts.height());
- float tmp = sourceRect.top();
- sourceRect.setTop(sourceRect.bottom());
- sourceRect.setBottom(tmp);
- QSGGeometry *geometry = this->geometry();
- QSGGeometry::updateTexturedRectGeometry(geometry, rect(),
- m_texture->convertToNormalizedSourceRect(sourceRect));
- markDirty(DirtyMaterial);
- //qDebug() << "create node" << m_fbo->handle() << m_texture->textureId() << m_fbo->size();
- }
-
- // Call the shared rendering function
- m_fbo->bind();
-
- m_scatterRenderer->render(m_fbo->handle());
-
- m_fbo->release();
-}
-
-QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualizationqml2/declarativescatterrenderer_p.h b/src/datavisualizationqml2/declarativescatterrenderer_p.h
deleted file mode 100644
index 0bbd01ec..00000000
--- a/src/datavisualizationqml2/declarativescatterrenderer_p.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use contact form at http://qt.digia.com
-**
-** This file is part of the QtDataVisualization module.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** contact form at http://qt.digia.com
-**
-****************************************************************************/
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the QtDataVisualization API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-
-#ifndef DECLARATIVESCATTERRENDERER_P_H
-#define DECLARATIVESCATTERRENDERER_P_H
-
-#include "datavisualizationglobal_p.h"
-#include "scatter3dcontroller_p.h"
-#include <qsgsimpletexturenode.h>
-
-class QOpenGLFramebufferObject;
-class QSGTexture;
-class QQuickWindow;
-
-QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-
-class DeclarativeScatterRenderer : public QObject, public QSGSimpleTextureNode
-{
- Q_OBJECT
-
-public:
- DeclarativeScatterRenderer(QQuickWindow *window, Scatter3DController *shared);
- ~DeclarativeScatterRenderer();
-
-public slots:
- // Used to synch up data model from controller to renderer while main thread is locked
- void synchDataToRenderer();
- // Renders view to FBO before render cycle starts.
- void renderFBO();
-
-private:
- QOpenGLFramebufferObject *m_fbo;
- QSGTexture *m_texture;
- QQuickWindow *m_window;
- Scatter3DController *m_scatterRenderer;
-};
-
-QT_DATAVISUALIZATION_END_NAMESPACE
-
-#endif
diff --git a/src/datavisualizationqml2/declarativeseries.cpp b/src/datavisualizationqml2/declarativeseries.cpp
new file mode 100644
index 00000000..35f6e315
--- /dev/null
+++ b/src/datavisualizationqml2/declarativeseries.cpp
@@ -0,0 +1,346 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#include "declarativeseries_p.h"
+#include "qbardataproxy.h"
+#include "qscatterdataproxy.h"
+#include "qsurfacedataproxy.h"
+#include <QMetaMethod>
+
+QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
+static void setSeriesGradient(QAbstract3DSeries *series, const ColorGradient &gradient, GradientType type)
+{
+ QLinearGradient newGradient;
+ QGradientStops stops;
+ QList<ColorGradientStop *> qmlstops = gradient.m_stops;
+
+ // Get sorted gradient stops
+ for (int i = 0; i < qmlstops.size(); i++) {
+ int j = 0;
+ while (j < stops.size() && stops.at(j).first < qmlstops[i]->position())
+ j++;
+ stops.insert(j, QGradientStop(qmlstops.at(i)->position(), qmlstops.at(i)->color()));
+ }
+
+ newGradient.setStops(stops);
+ switch (type) {
+ case GradientTypeBase:
+ series->setBaseGradient(newGradient);
+ break;
+ case GradientTypeSingle:
+ series->setSingleHighlightGradient(newGradient);
+ break;
+ case GradientTypeMulti:
+ series->setMultiHighlightGradient(newGradient);
+ break;
+ default: // Never goes here
+ break;
+ }
+}
+
+static void connectSeriesGradient(QAbstract3DSeries *series, ColorGradient *newGradient,
+ GradientType type, ColorGradient **memberGradient)
+{
+ // connect new / disconnect old
+ if (newGradient != *memberGradient) {
+ if (*memberGradient)
+ QObject::disconnect(*memberGradient, 0, series, 0);
+
+ *memberGradient = newGradient;
+
+ int updatedIndex = newGradient->metaObject()->indexOfSignal("updated()");
+ QMetaMethod updateFunction = newGradient->metaObject()->method(updatedIndex);
+ int handleIndex = -1;
+ switch (type) {
+ case GradientTypeBase:
+ handleIndex = series->metaObject()->indexOfSlot("handleBaseGradientUpdate()");
+ break;
+ case GradientTypeSingle:
+ handleIndex = series->metaObject()->indexOfSlot("handleSingleHighlightGradientUpdate()");
+ break;
+ case GradientTypeMulti:
+ handleIndex = series->metaObject()->indexOfSlot("handleMultiHighlightGradientUpdate()");
+ break;
+ default: // Never goes here
+ break;
+ }
+ QMetaMethod handleFunction = series->metaObject()->method(handleIndex);
+
+ if (*memberGradient)
+ QObject::connect(*memberGradient, updateFunction, series, handleFunction);
+ }
+
+ if (*memberGradient)
+ setSeriesGradient(series, **memberGradient, type);
+}
+
+DeclarativeBar3DSeries::DeclarativeBar3DSeries(QObject *parent)
+ : QBar3DSeries(parent),
+ m_baseGradient(0),
+ m_singleHighlightGradient(0),
+ m_multiHighlightGradient(0)
+{
+ QObject::connect(this, &QBar3DSeries::selectedBarChanged, this,
+ &DeclarativeBar3DSeries::selectedBarChanged);
+}
+
+DeclarativeBar3DSeries::~DeclarativeBar3DSeries()
+{
+}
+
+QQmlListProperty<QObject> DeclarativeBar3DSeries::seriesChildren()
+{
+ return QQmlListProperty<QObject>(this, this, &DeclarativeBar3DSeries::appendSeriesChildren
+ , 0, 0, 0);
+}
+
+void DeclarativeBar3DSeries::appendSeriesChildren(QQmlListProperty<QObject> *list, QObject *element)
+{
+ QBarDataProxy *proxy = qobject_cast<QBarDataProxy *>(element);
+ if (proxy)
+ reinterpret_cast<DeclarativeBar3DSeries *>(list->data)->setDataProxy(proxy);
+}
+
+void DeclarativeBar3DSeries::setSelectedBar(const QPointF &position)
+{
+ QBar3DSeries::setSelectedBar(position.toPoint());
+}
+
+QPointF DeclarativeBar3DSeries::selectedBar() const
+{
+ return QPointF(QBar3DSeries::selectedBar());
+}
+
+QPointF DeclarativeBar3DSeries::invalidSelectionPosition() const
+{
+ return QPointF(QBar3DSeries::invalidSelectionPosition());
+}
+
+void DeclarativeBar3DSeries::setBaseGradient(ColorGradient *gradient)
+{
+ connectSeriesGradient(this, gradient, GradientTypeBase, &m_baseGradient);
+}
+
+ColorGradient *DeclarativeBar3DSeries::baseGradient() const
+{
+ return m_baseGradient;
+}
+
+void DeclarativeBar3DSeries::setSingleHighlightGradient(ColorGradient *gradient)
+{
+ connectSeriesGradient(this, gradient, GradientTypeSingle, &m_singleHighlightGradient);
+}
+
+ColorGradient *DeclarativeBar3DSeries::singleHighlightGradient() const
+{
+ return m_singleHighlightGradient;
+}
+
+void DeclarativeBar3DSeries::setMultiHighlightGradient(ColorGradient *gradient)
+{
+ connectSeriesGradient(this, gradient, GradientTypeMulti, &m_multiHighlightGradient);
+}
+
+ColorGradient *DeclarativeBar3DSeries::multiHighlightGradient() const
+{
+ return m_multiHighlightGradient;
+}
+
+void DeclarativeBar3DSeries::handleBaseGradientUpdate()
+{
+ if (m_baseGradient)
+ setSeriesGradient(this, *m_baseGradient, GradientTypeBase);
+}
+
+void DeclarativeBar3DSeries::handleSingleHighlightGradientUpdate()
+{
+ if (m_singleHighlightGradient)
+ setSeriesGradient(this, *m_singleHighlightGradient, GradientTypeSingle);
+}
+
+void DeclarativeBar3DSeries::handleMultiHighlightGradientUpdate()
+{
+ if (m_multiHighlightGradient)
+ setSeriesGradient(this, *m_multiHighlightGradient, GradientTypeMulti);
+}
+
+DeclarativeScatter3DSeries::DeclarativeScatter3DSeries(QObject *parent)
+ : QScatter3DSeries(parent),
+ m_baseGradient(0),
+ m_singleHighlightGradient(0),
+ m_multiHighlightGradient(0)
+{
+}
+
+DeclarativeScatter3DSeries::~DeclarativeScatter3DSeries()
+{
+}
+
+QQmlListProperty<QObject> DeclarativeScatter3DSeries::seriesChildren()
+{
+ return QQmlListProperty<QObject>(this, this, &DeclarativeScatter3DSeries::appendSeriesChildren
+ , 0, 0, 0);
+}
+
+void DeclarativeScatter3DSeries::appendSeriesChildren(QQmlListProperty<QObject> *list, QObject *element)
+{
+ QScatterDataProxy *proxy = qobject_cast<QScatterDataProxy *>(element);
+ if (proxy)
+ reinterpret_cast<DeclarativeScatter3DSeries *>(list->data)->setDataProxy(proxy);
+}
+
+void DeclarativeScatter3DSeries::setBaseGradient(ColorGradient *gradient)
+{
+ connectSeriesGradient(this, gradient, GradientTypeBase, &m_baseGradient);
+}
+
+ColorGradient *DeclarativeScatter3DSeries::baseGradient() const
+{
+ return m_baseGradient;
+}
+
+void DeclarativeScatter3DSeries::setSingleHighlightGradient(ColorGradient *gradient)
+{
+ connectSeriesGradient(this, gradient, GradientTypeSingle, &m_singleHighlightGradient);
+}
+
+ColorGradient *DeclarativeScatter3DSeries::singleHighlightGradient() const
+{
+ return m_singleHighlightGradient;
+}
+
+void DeclarativeScatter3DSeries::setMultiHighlightGradient(ColorGradient *gradient)
+{
+ connectSeriesGradient(this, gradient, GradientTypeMulti, &m_multiHighlightGradient);
+}
+
+ColorGradient *DeclarativeScatter3DSeries::multiHighlightGradient() const
+{
+ return m_multiHighlightGradient;
+}
+
+void DeclarativeScatter3DSeries::handleBaseGradientUpdate()
+{
+ if (m_baseGradient)
+ setSeriesGradient(this, *m_baseGradient, GradientTypeBase);
+}
+
+void DeclarativeScatter3DSeries::handleSingleHighlightGradientUpdate()
+{
+ if (m_singleHighlightGradient)
+ setSeriesGradient(this, *m_singleHighlightGradient, GradientTypeSingle);
+}
+
+void DeclarativeScatter3DSeries::handleMultiHighlightGradientUpdate()
+{
+ if (m_multiHighlightGradient)
+ setSeriesGradient(this, *m_multiHighlightGradient, GradientTypeMulti);
+}
+
+DeclarativeSurface3DSeries::DeclarativeSurface3DSeries(QObject *parent)
+ : QSurface3DSeries(parent),
+ m_baseGradient(0),
+ m_singleHighlightGradient(0),
+ m_multiHighlightGradient(0)
+{
+ QObject::connect(this, &QSurface3DSeries::selectedPointChanged, this,
+ &DeclarativeSurface3DSeries::selectedPointChanged);
+}
+
+DeclarativeSurface3DSeries::~DeclarativeSurface3DSeries()
+{
+}
+
+void DeclarativeSurface3DSeries::setSelectedPoint(const QPointF &position)
+{
+ QSurface3DSeries::setSelectedPoint(position.toPoint());
+}
+
+QPointF DeclarativeSurface3DSeries::selectedPoint() const
+{
+ return QPointF(QSurface3DSeries::selectedPoint());
+}
+
+QPointF DeclarativeSurface3DSeries::invalidSelectionPosition() const
+{
+ return QPointF(QSurface3DSeries::invalidSelectionPosition());
+}
+
+QQmlListProperty<QObject> DeclarativeSurface3DSeries::seriesChildren()
+{
+ return QQmlListProperty<QObject>(this, this, &DeclarativeSurface3DSeries::appendSeriesChildren
+ , 0, 0, 0);
+}
+
+void DeclarativeSurface3DSeries::appendSeriesChildren(QQmlListProperty<QObject> *list, QObject *element)
+{
+ QSurfaceDataProxy *proxy = qobject_cast<QSurfaceDataProxy *>(element);
+ if (proxy)
+ reinterpret_cast<DeclarativeSurface3DSeries *>(list->data)->setDataProxy(proxy);
+}
+
+void DeclarativeSurface3DSeries::setBaseGradient(ColorGradient *gradient)
+{
+ connectSeriesGradient(this, gradient, GradientTypeBase, &m_baseGradient);
+}
+
+ColorGradient *DeclarativeSurface3DSeries::baseGradient() const
+{
+ return m_baseGradient;
+}
+
+void DeclarativeSurface3DSeries::setSingleHighlightGradient(ColorGradient *gradient)
+{
+ connectSeriesGradient(this, gradient, GradientTypeSingle, &m_singleHighlightGradient);
+}
+
+ColorGradient *DeclarativeSurface3DSeries::singleHighlightGradient() const
+{
+ return m_singleHighlightGradient;
+}
+
+void DeclarativeSurface3DSeries::setMultiHighlightGradient(ColorGradient *gradient)
+{
+ connectSeriesGradient(this, gradient, GradientTypeMulti, &m_multiHighlightGradient);
+}
+
+ColorGradient *DeclarativeSurface3DSeries::multiHighlightGradient() const
+{
+ return m_multiHighlightGradient;
+}
+
+void DeclarativeSurface3DSeries::handleBaseGradientUpdate()
+{
+ if (m_baseGradient)
+ setSeriesGradient(this, *m_baseGradient, GradientTypeBase);
+}
+
+void DeclarativeSurface3DSeries::handleSingleHighlightGradientUpdate()
+{
+ if (m_singleHighlightGradient)
+ setSeriesGradient(this, *m_singleHighlightGradient, GradientTypeSingle);
+}
+
+void DeclarativeSurface3DSeries::handleMultiHighlightGradientUpdate()
+{
+ if (m_multiHighlightGradient)
+ setSeriesGradient(this, *m_multiHighlightGradient, GradientTypeMulti);
+}
+
+QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualizationqml2/declarativeseries_p.h b/src/datavisualizationqml2/declarativeseries_p.h
new file mode 100644
index 00000000..c9c3dc7a
--- /dev/null
+++ b/src/datavisualizationqml2/declarativeseries_p.h
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the QtDataVisualization API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef DECLARATIVESERIES_P_H
+#define DECLARATIVESERIES_P_H
+
+#include "datavisualizationglobal_p.h"
+#include "qbar3dseries.h"
+#include "qscatter3dseries.h"
+#include "qsurface3dseries.h"
+#include "colorgradient_p.h"
+#include <QQmlListProperty>
+
+QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
+enum GradientType {
+ GradientTypeBase,
+ GradientTypeSingle,
+ GradientTypeMulti
+};
+
+class DeclarativeBar3DSeries : public QBar3DSeries
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<QObject> seriesChildren READ seriesChildren)
+ // selectedBar property is overloaded to use QPointF instead of QPoint to work around qml bug
+ // where Qt.point(0, 0) can't be assigned due to error "Cannot assign QPointF to QPoint".
+ Q_PROPERTY(QPointF selectedBar READ selectedBar WRITE setSelectedBar NOTIFY selectedBarChanged)
+ Q_PROPERTY(ColorGradient *baseGradient READ baseGradient WRITE setBaseGradient NOTIFY baseGradientChanged)
+ Q_PROPERTY(ColorGradient *singleHighlightGradient READ singleHighlightGradient WRITE setSingleHighlightGradient NOTIFY singleHighlightGradientChanged)
+ Q_PROPERTY(ColorGradient *multiHighlightGradient READ multiHighlightGradient WRITE setMultiHighlightGradient NOTIFY multiHighlightGradientChanged)
+ Q_CLASSINFO("DefaultProperty", "seriesChildren")
+public:
+ DeclarativeBar3DSeries(QObject *parent = 0);
+ virtual ~DeclarativeBar3DSeries();
+
+ QQmlListProperty<QObject> seriesChildren();
+ static void appendSeriesChildren(QQmlListProperty<QObject> *list, QObject *element);
+
+ void setSelectedBar(const QPointF &position);
+ QPointF selectedBar() const;
+ Q_INVOKABLE QPointF invalidSelectionPosition() const;
+
+ void setBaseGradient(ColorGradient *gradient);
+ ColorGradient *baseGradient() const;
+ void setSingleHighlightGradient(ColorGradient *gradient);
+ ColorGradient *singleHighlightGradient() const;
+ void setMultiHighlightGradient(ColorGradient *gradient);
+ ColorGradient *multiHighlightGradient() const;
+
+public slots:
+ void handleBaseGradientUpdate();
+ void handleSingleHighlightGradientUpdate();
+ void handleMultiHighlightGradientUpdate();
+
+signals:
+ void selectedBarChanged(QPointF position);
+ void baseGradientChanged(ColorGradient *gradient);
+ void singleHighlightGradientChanged(ColorGradient *gradient);
+ void multiHighlightGradientChanged(ColorGradient *gradient);
+
+private:
+ ColorGradient *m_baseGradient; // Not owned
+ ColorGradient *m_singleHighlightGradient; // Not owned
+ ColorGradient *m_multiHighlightGradient; // Not owned
+};
+
+class DeclarativeScatter3DSeries : public QScatter3DSeries
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<QObject> seriesChildren READ seriesChildren)
+ Q_PROPERTY(ColorGradient *baseGradient READ baseGradient WRITE setBaseGradient NOTIFY baseGradientChanged)
+ Q_PROPERTY(ColorGradient *singleHighlightGradient READ singleHighlightGradient WRITE setSingleHighlightGradient NOTIFY singleHighlightGradientChanged)
+ Q_PROPERTY(ColorGradient *multiHighlightGradient READ multiHighlightGradient WRITE setMultiHighlightGradient NOTIFY multiHighlightGradientChanged)
+ Q_CLASSINFO("DefaultProperty", "seriesChildren")
+public:
+ DeclarativeScatter3DSeries(QObject *parent = 0);
+ virtual ~DeclarativeScatter3DSeries();
+
+ QQmlListProperty<QObject> seriesChildren();
+ static void appendSeriesChildren(QQmlListProperty<QObject> *list, QObject *element);
+
+ void setBaseGradient(ColorGradient *gradient);
+ ColorGradient *baseGradient() const;
+ void setSingleHighlightGradient(ColorGradient *gradient);
+ ColorGradient *singleHighlightGradient() const;
+ void setMultiHighlightGradient(ColorGradient *gradient);
+ ColorGradient *multiHighlightGradient() const;
+
+public slots:
+ void handleBaseGradientUpdate();
+ void handleSingleHighlightGradientUpdate();
+ void handleMultiHighlightGradientUpdate();
+
+signals:
+ void baseGradientChanged(ColorGradient *gradient);
+ void singleHighlightGradientChanged(ColorGradient *gradient);
+ void multiHighlightGradientChanged(ColorGradient *gradient);
+
+private:
+ ColorGradient *m_baseGradient; // Not owned
+ ColorGradient *m_singleHighlightGradient; // Not owned
+ ColorGradient *m_multiHighlightGradient; // Not owned
+};
+
+class DeclarativeSurface3DSeries : public QSurface3DSeries
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<QObject> seriesChildren READ seriesChildren)
+ Q_PROPERTY(QPointF selectedPoint READ selectedPoint WRITE setSelectedPoint NOTIFY selectedPointChanged)
+ Q_PROPERTY(ColorGradient *baseGradient READ baseGradient WRITE setBaseGradient NOTIFY baseGradientChanged)
+ Q_PROPERTY(ColorGradient *singleHighlightGradient READ singleHighlightGradient WRITE setSingleHighlightGradient NOTIFY singleHighlightGradientChanged)
+ Q_PROPERTY(ColorGradient *multiHighlightGradient READ multiHighlightGradient WRITE setMultiHighlightGradient NOTIFY multiHighlightGradientChanged)
+ Q_CLASSINFO("DefaultProperty", "seriesChildren")
+public:
+ DeclarativeSurface3DSeries(QObject *parent = 0);
+ virtual ~DeclarativeSurface3DSeries();
+
+ void setSelectedPoint(const QPointF &position);
+ QPointF selectedPoint() const;
+ Q_INVOKABLE QPointF invalidSelectionPosition() const;
+
+ QQmlListProperty<QObject> seriesChildren();
+ static void appendSeriesChildren(QQmlListProperty<QObject> *list, QObject *element);
+
+ void setBaseGradient(ColorGradient *gradient);
+ ColorGradient *baseGradient() const;
+ void setSingleHighlightGradient(ColorGradient *gradient);
+ ColorGradient *singleHighlightGradient() const;
+ void setMultiHighlightGradient(ColorGradient *gradient);
+ ColorGradient *multiHighlightGradient() const;
+
+public slots:
+ void handleBaseGradientUpdate();
+ void handleSingleHighlightGradientUpdate();
+ void handleMultiHighlightGradientUpdate();
+
+signals:
+ void selectedPointChanged(QPointF position);
+ void baseGradientChanged(ColorGradient *gradient);
+ void singleHighlightGradientChanged(ColorGradient *gradient);
+ void multiHighlightGradientChanged(ColorGradient *gradient);
+
+private:
+ ColorGradient *m_baseGradient; // Not owned
+ ColorGradient *m_singleHighlightGradient; // Not owned
+ ColorGradient *m_multiHighlightGradient; // Not owned
+};
+
+QT_DATAVISUALIZATION_END_NAMESPACE
+
+#endif
diff --git a/src/datavisualizationqml2/declarativesurface.cpp b/src/datavisualizationqml2/declarativesurface.cpp
index 9ace6c55..3ba5f923 100644
--- a/src/datavisualizationqml2/declarativesurface.cpp
+++ b/src/datavisualizationqml2/declarativesurface.cpp
@@ -17,20 +17,15 @@
****************************************************************************/
#include "declarativesurface_p.h"
-#include "declarativesurfacerenderer_p.h"
#include "q3dvalueaxis.h"
#include "qitemmodelsurfacedataproxy.h"
-#include "theme_p.h"
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
DeclarativeSurface::DeclarativeSurface(QQuickItem *parent)
: AbstractDeclarative(parent),
- m_shared(0),
- m_initialisedSize(0, 0),
- m_gradient(0)
+ m_surfaceController(0)
{
- setFlags(QQuickItem::ItemHasContents);
setAcceptedMouseButtons(Qt::AllButtons);
// TODO: These seem to have no effect; find a way to activate anti-aliasing
@@ -38,151 +33,95 @@ DeclarativeSurface::DeclarativeSurface(QQuickItem *parent)
setSmooth(true);
// Create the shared component on the main GUI thread.
- m_shared = new Surface3DController(boundingRect().toRect());
- setSharedController(m_shared);
+ m_surfaceController = new Surface3DController(boundingRect().toRect());
+ setSharedController(m_surfaceController);
- QObject::connect(m_shared, &Surface3DController::smoothSurfaceEnabledChanged, this,
- &DeclarativeSurface::smoothSurfaceEnabledChanged);
-
- QItemModelSurfaceDataProxy *proxy = new QItemModelSurfaceDataProxy;
- m_shared->setActiveDataProxy(proxy);
+ // TODO: Uncomment when doing QTRD-2669
+// connect(m_surfaceController, &Surface3DController::axisXChanged,
+// this, &DeclarativeBars::axisXChanged);
+// connect(m_surfaceController, &Surface3DController::axisYChanged,
+// this, &DeclarativeBars::axisYChanged);
+// connect(m_surfaceController, &Surface3DController::axisZChanged,
+// this, &DeclarativeBars::axisZChanged);
}
DeclarativeSurface::~DeclarativeSurface()
{
- delete m_shared;
-}
-
-void DeclarativeSurface::handleGradientUpdate()
-{
- if (m_gradient)
- setControllerGradient(*m_gradient);
-}
-
-QSGNode *DeclarativeSurface::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
-{
- // If old node exists and has right size, reuse it.
- if (oldNode && m_initialisedSize == boundingRect().size().toSize()) {
- // Update bounding rectangle (that has same size as before).
- static_cast<DeclarativeSurfaceRenderer *>( oldNode )->setRect(boundingRect());
- return oldNode;
- }
-
- // Create a new render node when size changes or if there is no node yet
- m_initialisedSize = boundingRect().size().toSize();
-
- // Delete old node
- if (oldNode)
- delete oldNode;
-
- // Create a new one and set its bounding rectangle
- DeclarativeSurfaceRenderer *node = new DeclarativeSurfaceRenderer(window(), m_shared);
- node->setRect(boundingRect());
- m_shared->setBoundingRect(boundingRect().toRect());
- return node;
-}
-
-void DeclarativeSurface::setDataProxy(QSurfaceDataProxy *dataProxy)
-{
- m_shared->setActiveDataProxy(dataProxy);
-}
-
-QSurfaceDataProxy *DeclarativeSurface::dataProxy() const
-{
- return static_cast<QSurfaceDataProxy *>(m_shared->activeDataProxy());
+ delete m_surfaceController;
}
Q3DValueAxis *DeclarativeSurface::axisX() const
{
- return static_cast<Q3DValueAxis *>(m_shared->axisX());
+ return static_cast<Q3DValueAxis *>(m_surfaceController->axisX());
}
void DeclarativeSurface::setAxisX(Q3DValueAxis *axis)
{
- m_shared->setAxisX(axis);
+ m_surfaceController->setAxisX(axis);
}
Q3DValueAxis *DeclarativeSurface::axisY() const
{
- return static_cast<Q3DValueAxis *>(m_shared->axisY());
+ return static_cast<Q3DValueAxis *>(m_surfaceController->axisY());
}
void DeclarativeSurface::setAxisY(Q3DValueAxis *axis)
{
- m_shared->setAxisY(axis);
+ m_surfaceController->setAxisY(axis);
}
Q3DValueAxis *DeclarativeSurface::axisZ() const
{
- return static_cast<Q3DValueAxis *>(m_shared->axisZ());
+ return static_cast<Q3DValueAxis *>(m_surfaceController->axisZ());
}
void DeclarativeSurface::setAxisZ(Q3DValueAxis *axis)
{
- m_shared->setAxisZ(axis);
+ m_surfaceController->setAxisZ(axis);
}
-void DeclarativeSurface::setSmoothSurfaceEnabled(bool enabled)
+QQmlListProperty<QSurface3DSeries> DeclarativeSurface::seriesList()
{
- m_shared->setSmoothSurface(enabled);
+ return QQmlListProperty<QSurface3DSeries>(this, this,
+ &DeclarativeSurface::appendSeriesFunc,
+ &DeclarativeSurface::countSeriesFunc,
+ &DeclarativeSurface::atSeriesFunc,
+ &DeclarativeSurface::clearSeriesFunc);
}
-bool DeclarativeSurface::isSmoothSurfaceEnabled() const
+void DeclarativeSurface::appendSeriesFunc(QQmlListProperty<QSurface3DSeries> *list, QSurface3DSeries *series)
{
- return m_shared->smoothSurface();
+ reinterpret_cast<DeclarativeSurface *>(list->data)->addSeries(series);
}
-void DeclarativeSurface::setSurfaceGridEnabled(bool enabled)
+int DeclarativeSurface::countSeriesFunc(QQmlListProperty<QSurface3DSeries> *list)
{
- m_shared->setSurfaceGrid(enabled);
+ return reinterpret_cast<DeclarativeSurface *>(list->data)->m_surfaceController->surfaceSeriesList().size();
}
-bool DeclarativeSurface::isSurfaceGridEnabled() const
+QSurface3DSeries *DeclarativeSurface::atSeriesFunc(QQmlListProperty<QSurface3DSeries> *list, int index)
{
- return m_shared->surfaceGrid();
+ return reinterpret_cast<DeclarativeSurface *>(list->data)->m_surfaceController->surfaceSeriesList().at(index);
}
-void DeclarativeSurface::setGradient(ColorGradient *gradient)
+void DeclarativeSurface::clearSeriesFunc(QQmlListProperty<QSurface3DSeries> *list)
{
- // connect new / disconnect old
- if (gradient != m_gradient) {
- if (m_gradient)
- QObject::disconnect(m_gradient, 0, this, 0);
-
- m_gradient = gradient;
-
- if (m_gradient) {
- QObject::connect(m_gradient, &ColorGradient::updated, this,
- &DeclarativeSurface::handleGradientUpdate);
- }
- }
-
- if (m_gradient)
- setControllerGradient(*m_gradient);
+ DeclarativeSurface *declSurface = reinterpret_cast<DeclarativeSurface *>(list->data);
+ QList<QSurface3DSeries *> realList = declSurface->m_surfaceController->surfaceSeriesList();
+ int count = realList.size();
+ for (int i = 0; i < count; i++)
+ declSurface->removeSeries(realList.at(i));
}
-ColorGradient *DeclarativeSurface::gradient() const
+void DeclarativeSurface::addSeries(QSurface3DSeries *series)
{
-
- return m_gradient;
+ m_surfaceController->addSeries(series);
}
-void DeclarativeSurface::setControllerGradient(const ColorGradient &gradient)
+void DeclarativeSurface::removeSeries(QSurface3DSeries *series)
{
- QLinearGradient newGradient;
- QGradientStops stops;
- QList<ColorGradientStop *> qmlstops = gradient.m_stops;
-
- // Get sorted gradient stops
- for (int i = 0; i < qmlstops.size(); i++) {
- int j = 0;
- while (j < stops.size() && stops.at(j).first < qmlstops[i]->position())
- j++;
- stops.insert(j, QGradientStop(qmlstops.at(i)->position(), qmlstops.at(i)->color()));
- }
-
- newGradient.setStops(stops);
- m_shared->setGradient(newGradient);
+ m_surfaceController->removeSeries(series);
+ series->setParent(this); // Reparent as removing will leave series parentless
}
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualizationqml2/declarativesurface_p.h b/src/datavisualizationqml2/declarativesurface_p.h
index 6e35b3b3..2c9c2803 100644
--- a/src/datavisualizationqml2/declarativesurface_p.h
+++ b/src/datavisualizationqml2/declarativesurface_p.h
@@ -35,7 +35,7 @@
#include "declarativesurface_p.h"
#include "q3dvalueaxis.h"
#include "qsurfacedataproxy.h"
-#include "colorgradient_p.h"
+#include "qsurface3dseries.h"
#include <QAbstractItemModel>
#include <QQuickItem>
@@ -47,21 +47,16 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class DeclarativeSurface : public AbstractDeclarative
{
Q_OBJECT
- Q_PROPERTY(QSurfaceDataProxy *dataProxy READ dataProxy WRITE setDataProxy)
- Q_PROPERTY(Q3DValueAxis *axisX READ axisX WRITE setAxisX)
- Q_PROPERTY(Q3DValueAxis *axisY READ axisY WRITE setAxisY)
- Q_PROPERTY(Q3DValueAxis *axisZ READ axisZ WRITE setAxisZ)
- Q_PROPERTY(bool smoothSurfaceEnabled READ isSmoothSurfaceEnabled WRITE setSmoothSurfaceEnabled NOTIFY smoothSurfaceEnabledChanged)
- Q_PROPERTY(bool surfaceGridEnabled READ isSurfaceGridEnabled WRITE setSurfaceGridEnabled)
- Q_PROPERTY(ColorGradient *gradient READ gradient WRITE setGradient)
+ Q_PROPERTY(Q3DValueAxis *axisX READ axisX WRITE setAxisX NOTIFY axisXChanged)
+ Q_PROPERTY(Q3DValueAxis *axisY READ axisY WRITE setAxisY NOTIFY axisYChanged)
+ Q_PROPERTY(Q3DValueAxis *axisZ READ axisZ WRITE setAxisZ NOTIFY axisZChanged)
+ Q_PROPERTY(QQmlListProperty<QSurface3DSeries> seriesList READ seriesList)
+ Q_CLASSINFO("DefaultProperty", "seriesList")
public:
explicit DeclarativeSurface(QQuickItem *parent = 0);
~DeclarativeSurface();
- QSurfaceDataProxy *dataProxy() const;
- void setDataProxy(QSurfaceDataProxy *dataProxy);
-
Q3DValueAxis *axisX() const;
void setAxisX(Q3DValueAxis *axis);
Q3DValueAxis *axisY() const;
@@ -69,30 +64,21 @@ public:
Q3DValueAxis *axisZ() const;
void setAxisZ(Q3DValueAxis *axis);
- void setSmoothSurfaceEnabled(bool enabled);
- bool isSmoothSurfaceEnabled() const;
-
- void setSurfaceGridEnabled(bool enabled);
- bool isSurfaceGridEnabled() const;
-
- void setGradient(ColorGradient *gradient);
- ColorGradient *gradient() const;
+ QQmlListProperty<QSurface3DSeries> seriesList();
+ static void appendSeriesFunc(QQmlListProperty<QSurface3DSeries> *list, QSurface3DSeries *series);
+ static int countSeriesFunc(QQmlListProperty<QSurface3DSeries> *list);
+ static QSurface3DSeries *atSeriesFunc(QQmlListProperty<QSurface3DSeries> *list, int index);
+ static void clearSeriesFunc(QQmlListProperty<QSurface3DSeries> *list);
+ Q_INVOKABLE void addSeries(QSurface3DSeries *series);
+ Q_INVOKABLE void removeSeries(QSurface3DSeries *series);
signals:
- void smoothSurfaceEnabledChanged(bool enabled);
-
-protected:
- void handleGradientUpdate();
-
- QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *);
+ void axisXChanged(Q3DValueAxis *axis);
+ void axisYChanged(Q3DValueAxis *axis);
+ void axisZChanged(Q3DValueAxis *axis);
private:
- Surface3DController *m_shared;
-
- void setControllerGradient(const ColorGradient &gradient);
-
- QSize m_initialisedSize;
- ColorGradient *m_gradient; // Not owned
+ Surface3DController *m_surfaceController;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualizationqml2/declarativesurfacerenderer.cpp b/src/datavisualizationqml2/declarativesurfacerenderer.cpp
deleted file mode 100644
index 87a290ce..00000000
--- a/src/datavisualizationqml2/declarativesurfacerenderer.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use contact form at http://qt.digia.com
-**
-** This file is part of the QtDataVisualization module.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** contact form at http://qt.digia.com
-**
-****************************************************************************/
-
-#include "declarativesurfacerenderer_p.h"
-
-#include <QtQuick/QQuickWindow>
-#include <QtGui/QOpenGLFramebufferObject>
-
-QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-
-DeclarativeSurfaceRenderer::DeclarativeSurfaceRenderer(QQuickWindow *window,
- Surface3DController *renderer)
- : m_fbo(0),
- m_texture(0),
- m_window(window),
- m_surfaceRenderer(renderer)
-{
- connect(m_window, &QQuickWindow::beforeSynchronizing, this,
- &DeclarativeSurfaceRenderer::synchDataToRenderer, Qt::DirectConnection);
- connect(m_window, &QQuickWindow::beforeRendering, this,
- &DeclarativeSurfaceRenderer::renderFBO, Qt::DirectConnection);
- connect(m_surfaceRenderer, &Abstract3DController::needRender, m_window,
- &QQuickWindow::update);
-}
-
-DeclarativeSurfaceRenderer::~DeclarativeSurfaceRenderer()
-{
- delete m_texture;
- delete m_fbo;
-}
-
-void DeclarativeSurfaceRenderer::synchDataToRenderer()
-{
- m_surfaceRenderer->initializeOpenGL();
- m_surfaceRenderer->synchDataToRenderer();
-}
-
-void DeclarativeSurfaceRenderer::renderFBO()
-{
- QSize size = rect().size().toSize();
-
- // Create FBO
- if (!m_fbo) {
- QOpenGLFramebufferObjectFormat format;
- format.setAttachment(QOpenGLFramebufferObject::Depth);
- m_fbo = new QOpenGLFramebufferObject(size, format);
- m_texture = m_window->createTextureFromId(m_fbo->texture(), size);
-
- setTexture(m_texture);
-
- // Flip texture
- // TODO: Can be gotten rid of once support for texture flipping becomes available (in Qt5.2)
- QSize ts = m_texture->textureSize();
- QRectF sourceRect(0, 0, ts.width(), ts.height());
- float tmp = sourceRect.top();
- sourceRect.setTop(sourceRect.bottom());
- sourceRect.setBottom(tmp);
- QSGGeometry *geometry = this->geometry();
- QSGGeometry::updateTexturedRectGeometry(geometry, rect(),
- m_texture->convertToNormalizedSourceRect(sourceRect));
- markDirty(DirtyMaterial);
- }
-
- // Call the shared rendering function
- m_fbo->bind();
-
- m_surfaceRenderer->render(m_fbo->handle());
-
- m_fbo->release();
-}
-
-QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualizationqml2/declarativesurfacerenderer_p.h b/src/datavisualizationqml2/declarativesurfacerenderer_p.h
deleted file mode 100644
index 09128f59..00000000
--- a/src/datavisualizationqml2/declarativesurfacerenderer_p.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use contact form at http://qt.digia.com
-**
-** This file is part of the QtDataVisualization module.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** contact form at http://qt.digia.com
-**
-****************************************************************************/
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the QtDataVisualization API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-
-#ifndef DECLARATIVESURFACERENDERER_H
-#define DECLARATIVESURFACERENDERER_H
-
-#include "datavisualizationglobal_p.h"
-#include "surface3dcontroller_p.h"
-#include <qsgsimpletexturenode.h>
-
-class QOpenGLFramebufferObject;
-class QSGTexture;
-class QQuickWindow;
-
-QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-
-class DeclarativeSurfaceRenderer : public QObject, public QSGSimpleTextureNode
-{
- Q_OBJECT
-
-public:
- DeclarativeSurfaceRenderer(QQuickWindow *window, Surface3DController *shared);
- ~DeclarativeSurfaceRenderer();
-
-public slots:
- // Used to synch up data model from controller to renderer while main thread is locked
- void synchDataToRenderer();
- // Renders view to FBO before render cycle starts.
- void renderFBO();
-
-private:
- QOpenGLFramebufferObject *m_fbo;
- QSGTexture *m_texture;
- QQuickWindow *m_window;
- Surface3DController *m_surfaceRenderer;
-};
-
-QT_DATAVISUALIZATION_END_NAMESPACE
-
-#endif
diff --git a/src/datavisualizationqml2/declarativetheme.cpp b/src/datavisualizationqml2/declarativetheme.cpp
new file mode 100644
index 00000000..6c804397
--- /dev/null
+++ b/src/datavisualizationqml2/declarativetheme.cpp
@@ -0,0 +1,362 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#include "declarativetheme_p.h"
+
+QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
+DeclarativeTheme3D::DeclarativeTheme3D(QObject *parent)
+ : Q3DTheme(parent),
+ m_colors(QList<DeclarativeColor *>()),
+ m_gradients(QList<ColorGradient *>()),
+ m_singleHLGradient(0),
+ m_multiHLGradient(0),
+ m_dummyGradients(false),
+ m_dummyColors(false)
+{
+}
+
+DeclarativeTheme3D::~DeclarativeTheme3D()
+{
+}
+
+QQmlListProperty<QObject> DeclarativeTheme3D::seriesChildren()
+{
+ return QQmlListProperty<QObject>(this, this, &DeclarativeTheme3D::appendSeriesChildren,
+ 0, 0, 0);
+}
+
+void DeclarativeTheme3D::appendSeriesChildren(QQmlListProperty<QObject> *list, QObject *element)
+{
+ Q_UNUSED(list)
+ Q_UNUSED(element)
+ // Nothing to do, seriesChildren is there only to enable scoping gradient items in Theme3D item.
+}
+
+void DeclarativeTheme3D::handleBaseColorUpdate()
+{
+ int colorCount = m_colors.size();
+ int changed = 0;
+ // Check which one changed
+ DeclarativeColor *color = qobject_cast<DeclarativeColor *>(QObject::sender());
+ for (int i = 0; i < colorCount; i++) {
+ if (color == m_colors.at(i)) {
+ changed = i;
+ break;
+ }
+ }
+ // Update the changed one from the list
+ QList<QColor> list = Q3DTheme::baseColors();
+ list[changed] = m_colors.at(changed)->color();
+ // Set the changed list
+ Q3DTheme::setBaseColors(list);
+}
+
+void DeclarativeTheme3D::handleBaseGradientUpdate()
+{
+ int gradientCount = m_gradients.size();
+ int changed = 0;
+ // Check which one changed
+ ColorGradient *gradient = qobject_cast<ColorGradient *>(QObject::sender());
+ for (int i = 0; i < gradientCount; i++) {
+ if (gradient == m_gradients.at(i)) {
+ changed = i;
+ break;
+ }
+ }
+ // Update the changed one from the list
+ QList<QLinearGradient> list = Q3DTheme::baseGradients();
+ list[changed] = convertGradient(gradient);
+ // Set the changed list
+ Q3DTheme::setBaseGradients(list);
+}
+
+void DeclarativeTheme3D::handleSingleHLGradientUpdate()
+{
+ if (m_singleHLGradient)
+ setThemeGradient(m_singleHLGradient, GradientTypeSingleHL);
+}
+
+void DeclarativeTheme3D::handleMultiHLGradientUpdate()
+{
+ if (m_multiHLGradient)
+ setThemeGradient(m_multiHLGradient, GradientTypeMultiHL);
+}
+
+void DeclarativeTheme3D::setSingleHighlightGradient(ColorGradient *gradient)
+{
+ // connect new / disconnect old
+ if (gradient != m_singleHLGradient) {
+ if (m_singleHLGradient)
+ QObject::disconnect(m_singleHLGradient, 0, this, 0);
+
+ m_singleHLGradient = gradient;
+
+ if (m_singleHLGradient) {
+ QObject::connect(m_singleHLGradient, &ColorGradient::updated, this,
+ &DeclarativeTheme3D::handleSingleHLGradientUpdate);
+ }
+
+ emit singleHighlightGradientChanged(m_singleHLGradient);
+ }
+
+ if (m_singleHLGradient)
+ setThemeGradient(m_singleHLGradient, GradientTypeSingleHL);
+}
+
+ColorGradient *DeclarativeTheme3D::singleHighlightGradient() const
+{
+ return m_singleHLGradient;
+}
+
+void DeclarativeTheme3D::setMultiHighlightGradient(ColorGradient *gradient)
+{
+ // connect new / disconnect old
+ if (gradient != m_multiHLGradient) {
+ if (m_multiHLGradient)
+ QObject::disconnect(m_multiHLGradient, 0, this, 0);
+
+ m_multiHLGradient = gradient;
+
+ if (m_multiHLGradient) {
+ QObject::connect(m_multiHLGradient, &ColorGradient::updated, this,
+ &DeclarativeTheme3D::handleMultiHLGradientUpdate);
+ }
+
+ emit multiHighlightGradientChanged(m_multiHLGradient);
+ }
+
+ if (m_multiHLGradient)
+ setThemeGradient(m_multiHLGradient, GradientTypeMultiHL);
+}
+
+ColorGradient *DeclarativeTheme3D::multiHighlightGradient() const
+{
+ return m_multiHLGradient;
+}
+
+void DeclarativeTheme3D::setThemeGradient(ColorGradient *gradient, GradientType type)
+{
+ QLinearGradient newGradient = convertGradient(gradient);
+
+ switch (type) {
+ case GradientTypeSingleHL:
+ Q3DTheme::setSingleHighlightGradient(newGradient);
+ break;
+ case GradientTypeMultiHL:
+ break;
+ Q3DTheme::setMultiHighlightGradient(newGradient);
+ default:
+ qWarning("Incorrect usage. Type may be GradientTypeSingleHL or GradientTypeMultiHL.");
+ break;
+ }
+}
+
+QLinearGradient DeclarativeTheme3D::convertGradient(ColorGradient *gradient)
+{
+ QLinearGradient newGradient;
+ QGradientStops stops;
+ QList<ColorGradientStop *> qmlstops = gradient->m_stops;
+
+ // Get sorted gradient stops
+ for (int i = 0; i < qmlstops.size(); i++) {
+ int j = 0;
+ while (j < stops.size() && stops.at(j).first < qmlstops[i]->position())
+ j++;
+ stops.insert(j, QGradientStop(qmlstops.at(i)->position(), qmlstops.at(i)->color()));
+ }
+
+ newGradient.setStops(stops);
+
+ return newGradient;
+}
+
+ColorGradient *DeclarativeTheme3D::convertGradient(const QLinearGradient &gradient)
+{
+ ColorGradient *newGradient = new ColorGradient(this);
+ QGradientStops stops = gradient.stops();
+ ColorGradientStop *qmlstop;
+
+ // Convert stops
+ for (int i = 0; i < stops.size(); i++) {
+ qmlstop = new ColorGradientStop(newGradient);
+ qmlstop->setColor(stops.at(i).second);
+ qmlstop->setPosition(stops.at(i).first);
+ newGradient->m_stops.append(qmlstop);
+ }
+
+ return newGradient;
+}
+
+void DeclarativeTheme3D::addColor(DeclarativeColor *color)
+{
+ clearDummyColors();
+ m_colors.append(color);
+ connect(color, &DeclarativeColor::colorChanged,
+ this, &DeclarativeTheme3D::handleBaseColorUpdate);
+ QList<QColor> list = Q3DTheme::baseColors();
+ list.append(color->color());
+ Q3DTheme::setBaseColors(list);
+}
+
+QList<DeclarativeColor *> DeclarativeTheme3D::colorList()
+{
+ if (m_colors.isEmpty()) {
+ // Create dummy ThemeColors from theme's gradients
+ m_dummyColors = true;
+ QList<QColor> list = Q3DTheme::baseColors();
+ foreach (QColor item, list) {
+ DeclarativeColor *color = new DeclarativeColor(this);
+ color->setColor(item);
+ m_colors.append(color);
+ connect(color, &DeclarativeColor::colorChanged,
+ this, &DeclarativeTheme3D::handleBaseColorUpdate);
+ }
+ }
+ return m_colors;
+}
+
+void DeclarativeTheme3D::clearColors()
+{
+ clearDummyColors();
+ foreach (DeclarativeColor *item, m_colors)
+ disconnect(item, 0, this, 0);
+ m_colors.clear();
+ Q3DTheme::setBaseColors(QList<QColor>());
+}
+
+void DeclarativeTheme3D::clearDummyColors()
+{
+ if (m_dummyColors) {
+ foreach (DeclarativeColor *item, m_colors)
+ delete item;
+ m_colors.clear();
+ m_dummyColors = false;
+ }
+}
+
+void DeclarativeTheme3D::addGradient(ColorGradient *gradient)
+{
+ clearDummyGradients();
+ m_gradients.append(gradient);
+ connect(gradient, &ColorGradient::updated,
+ this, &DeclarativeTheme3D::handleBaseGradientUpdate);
+ QList<QLinearGradient> list = Q3DTheme::baseGradients();
+ list.append(convertGradient(gradient));
+ Q3DTheme::setBaseGradients(list);
+}
+
+QList<ColorGradient *> DeclarativeTheme3D::gradientList()
+{
+ if (m_gradients.isEmpty()) {
+ // Create dummy ColorGradients from theme's gradients
+ m_dummyGradients = true;
+ QList<QLinearGradient> list = Q3DTheme::baseGradients();
+ foreach (QLinearGradient item, list) {
+ ColorGradient *gradient = convertGradient(item);
+ m_gradients.append(gradient);
+ connect(gradient, &ColorGradient::updated,
+ this, &DeclarativeTheme3D::handleBaseGradientUpdate);
+ }
+ }
+
+ return m_gradients;
+}
+
+void DeclarativeTheme3D::clearGradients()
+{
+ clearDummyGradients();
+ foreach (ColorGradient *item, m_gradients)
+ disconnect(item, 0, this, 0);
+ m_gradients.clear();
+ Q3DTheme::setBaseGradients(QList<QLinearGradient>());
+}
+
+void DeclarativeTheme3D::clearDummyGradients()
+{
+ if (m_dummyGradients) {
+ foreach (ColorGradient *item, m_gradients)
+ delete item;
+ m_gradients.clear();
+ m_dummyGradients = false;
+ }
+}
+
+QQmlListProperty<DeclarativeColor> DeclarativeTheme3D::baseColors()
+{
+ return QQmlListProperty<DeclarativeColor>(this, this,
+ &DeclarativeTheme3D::appendBaseColorsFunc,
+ &DeclarativeTheme3D::countBaseColorsFunc,
+ &DeclarativeTheme3D::atBaseColorsFunc,
+ &DeclarativeTheme3D::clearBaseColorsFunc);
+}
+
+void DeclarativeTheme3D::appendBaseColorsFunc(QQmlListProperty<DeclarativeColor> *list,
+ DeclarativeColor *color)
+{
+ reinterpret_cast<DeclarativeTheme3D *>(list->data)->addColor(color);
+}
+
+int DeclarativeTheme3D::countBaseColorsFunc(QQmlListProperty<DeclarativeColor> *list)
+{
+ return reinterpret_cast<DeclarativeTheme3D *>(list->data)->colorList().size();
+}
+
+DeclarativeColor *DeclarativeTheme3D::atBaseColorsFunc(QQmlListProperty<DeclarativeColor> *list,
+ int index)
+{
+ return reinterpret_cast<DeclarativeTheme3D *>(list->data)->colorList().at(index);
+}
+
+void DeclarativeTheme3D::clearBaseColorsFunc(QQmlListProperty<DeclarativeColor> *list)
+{
+ reinterpret_cast<DeclarativeTheme3D *>(list->data)->clearColors();
+}
+
+QQmlListProperty<ColorGradient> DeclarativeTheme3D::baseGradients()
+{
+ return QQmlListProperty<ColorGradient>(this, this,
+ &DeclarativeTheme3D::appendBaseGradientsFunc,
+ &DeclarativeTheme3D::countBaseGradientsFunc,
+ &DeclarativeTheme3D::atBaseGradientsFunc,
+ &DeclarativeTheme3D::clearBaseGradientsFunc);
+}
+
+void DeclarativeTheme3D::appendBaseGradientsFunc(QQmlListProperty<ColorGradient> *list,
+ ColorGradient *gradient)
+{
+ reinterpret_cast<DeclarativeTheme3D *>(list->data)->addGradient(gradient);
+}
+
+int DeclarativeTheme3D::countBaseGradientsFunc(QQmlListProperty<ColorGradient> *list)
+{
+ return reinterpret_cast<DeclarativeTheme3D *>(list->data)->gradientList().size();
+}
+
+ColorGradient *DeclarativeTheme3D::atBaseGradientsFunc(QQmlListProperty<ColorGradient> *list,
+ int index)
+{
+ return reinterpret_cast<DeclarativeTheme3D *>(list->data)->gradientList().at(index);
+}
+
+void DeclarativeTheme3D::clearBaseGradientsFunc(QQmlListProperty<ColorGradient> *list)
+{
+ reinterpret_cast<DeclarativeTheme3D *>(list->data)->clearGradients();
+}
+
+QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualizationqml2/declarativetheme_p.h b/src/datavisualizationqml2/declarativetheme_p.h
new file mode 100644
index 00000000..79c1f5c9
--- /dev/null
+++ b/src/datavisualizationqml2/declarativetheme_p.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the QtDataVisualization API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef DECLARATIVETHEME_P_H
+#define DECLARATIVETHEME_P_H
+
+#include "datavisualizationglobal_p.h"
+#include "declarativecolor_p.h"
+#include "colorgradient_p.h"
+#include "q3dtheme.h"
+
+QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
+class DeclarativeTheme3D : public Q3DTheme
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<QObject> seriesChildren READ seriesChildren)
+ Q_PROPERTY(QQmlListProperty<DeclarativeColor> baseColors READ baseColors)
+ Q_PROPERTY(QQmlListProperty<ColorGradient> baseGradients READ baseGradients)
+ Q_PROPERTY(ColorGradient *singleHighlightGradient READ singleHighlightGradient WRITE setSingleHighlightGradient NOTIFY singleHighlightGradientChanged)
+ Q_PROPERTY(ColorGradient *multiHighlightGradient READ multiHighlightGradient WRITE setMultiHighlightGradient NOTIFY multiHighlightGradientChanged)
+ Q_CLASSINFO("DefaultProperty", "seriesChildren")
+
+public:
+ DeclarativeTheme3D(QObject *parent = 0);
+ virtual ~DeclarativeTheme3D();
+
+ QQmlListProperty<QObject> seriesChildren();
+ static void appendSeriesChildren(QQmlListProperty<QObject> *list, QObject *element);
+
+ QQmlListProperty<DeclarativeColor> baseColors();
+ static void appendBaseColorsFunc(QQmlListProperty<DeclarativeColor> *list,
+ DeclarativeColor *color);
+ static int countBaseColorsFunc(QQmlListProperty<DeclarativeColor> *list);
+ static DeclarativeColor *atBaseColorsFunc(QQmlListProperty<DeclarativeColor> *list, int index);
+ static void clearBaseColorsFunc(QQmlListProperty<DeclarativeColor> *list);
+
+ QQmlListProperty<ColorGradient> baseGradients();
+ static void appendBaseGradientsFunc(QQmlListProperty<ColorGradient> *list,
+ ColorGradient *gradient);
+ static int countBaseGradientsFunc(QQmlListProperty<ColorGradient> *list);
+ static ColorGradient *atBaseGradientsFunc(QQmlListProperty<ColorGradient> *list, int index);
+ static void clearBaseGradientsFunc(QQmlListProperty<ColorGradient> *list);
+
+ void setSingleHighlightGradient(ColorGradient *gradient);
+ ColorGradient *singleHighlightGradient() const;
+
+ void setMultiHighlightGradient(ColorGradient *gradient);
+ ColorGradient *multiHighlightGradient() const;
+
+signals:
+ void singleHighlightGradientChanged(ColorGradient *gradient);
+ void multiHighlightGradientChanged(ColorGradient *gradient);
+
+protected:
+ void handleBaseColorUpdate();
+ void handleBaseGradientUpdate();
+ void handleSingleHLGradientUpdate();
+ void handleMultiHLGradientUpdate();
+
+ enum GradientType {
+ GradientTypeBase = 0,
+ GradientTypeSingleHL,
+ GradientTypeMultiHL
+ };
+
+private:
+ void addColor(DeclarativeColor *color);
+ QList<DeclarativeColor *> colorList();
+ void clearColors();
+ void clearDummyColors();
+
+ void addGradient(ColorGradient *gradient);
+ QList<ColorGradient *> gradientList();
+ void clearGradients();
+ void clearDummyGradients();
+
+ void setThemeGradient(ColorGradient *gradient, GradientType type);
+ QLinearGradient convertGradient(ColorGradient *gradient);
+ ColorGradient *convertGradient(const QLinearGradient &gradient);
+
+ QList<DeclarativeColor *> m_colors; // Not owned
+ QList<ColorGradient *> m_gradients; // Not owned
+ ColorGradient *m_singleHLGradient; // Not owned
+ ColorGradient *m_multiHLGradient; // Not owned
+
+ bool m_dummyGradients;
+ bool m_dummyColors;
+};
+
+QT_DATAVISUALIZATION_END_NAMESPACE
+
+#endif
diff --git a/tests/barstest/chart.cpp b/tests/barstest/chart.cpp
index ad27d83c..8bef7479 100644
--- a/tests/barstest/chart.cpp
+++ b/tests/barstest/chart.cpp
@@ -22,27 +22,29 @@
#include <QtDataVisualization/qbardataproxy.h>
#include <QtDataVisualization/q3dscene.h>
#include <QtDataVisualization/q3dcamera.h>
+#include <QtDataVisualization/q3dtheme.h>
#include <QTime>
QT_DATAVISUALIZATION_USE_NAMESPACE
const QString celsiusString = QString(QChar(0xB0)) + "C";
-GraphModifier::GraphModifier(Q3DBars *barchart)
- : m_chart(barchart),
+GraphModifier::GraphModifier(Q3DBars *barchart, QColorDialog *colorDialog)
+ : m_graph(barchart),
+ m_colorDialog(colorDialog),
m_columnCount(21),
m_rowCount(21),
- m_xRotation(0.0),
- m_yRotation(0.0),
+ m_xRotation(0.0f),
+ m_yRotation(0.0f),
m_static(true),
- m_barSpacingX(0.1),
- m_barSpacingZ(0.1),
+ m_barSpacingX(0.1f),
+ m_barSpacingZ(0.1f),
m_fontSize(20),
m_segments(4),
m_subSegments(3),
- m_minval(-20.0), // TODO Barchart Y-axis currently only properly supports zero-centered ranges
- m_maxval(20.0),
- m_selectedBarPos(-1, -1),
+ m_minval(-16.0f),
+ m_maxval(20.0f),
+ m_selectedBar(-1, -1),
m_autoAdjustingAxis(new Q3DValueAxis),
m_fixedRangeAxis(new Q3DValueAxis),
m_temperatureAxis(new Q3DValueAxis),
@@ -50,9 +52,18 @@ GraphModifier::GraphModifier(Q3DBars *barchart)
m_monthAxis(new Q3DCategoryAxis),
m_genericRowAxis(new Q3DCategoryAxis),
m_genericColumnAxis(new Q3DCategoryAxis),
- m_temperatureData(new QBarDataProxy),
- m_genericData(new QBarDataProxy),
- m_currentAxis(m_fixedRangeAxis)
+ m_temperatureData(new QBar3DSeries),
+ m_temperatureData2(new QBar3DSeries),
+ m_genericData(new QBar3DSeries),
+ m_dummyData(new QBar3DSeries),
+ m_dummyData2(new QBar3DSeries),
+ m_dummyData3(new QBar3DSeries),
+ m_dummyData4(new QBar3DSeries),
+ m_dummyData5(new QBar3DSeries),
+ m_currentAxis(m_fixedRangeAxis),
+ m_negativeValuesOn(false),
+ m_useNullInputHandler(false),
+ m_defaultInputHandler(0)
{
// Generate generic labels
QStringList genericColumnLabels;
@@ -97,31 +108,90 @@ GraphModifier::GraphModifier(Q3DBars *barchart)
m_monthAxis->setTitle("Month");
- m_chart->addAxis(m_autoAdjustingAxis);
- m_chart->addAxis(m_fixedRangeAxis);
- m_chart->addAxis(m_temperatureAxis);
- m_chart->addAxis(m_yearAxis);
- m_chart->addAxis(m_monthAxis);
- m_chart->addAxis(m_genericRowAxis);
- m_chart->addAxis(m_genericColumnAxis);
-
- m_chart->setShadowQuality(QDataVis::ShadowQualitySoftMedium);
-
- m_temperatureData->setItemLabelFormat(QStringLiteral("@valueTitle for @colLabel @rowLabel: @valueLabel"));
- m_genericData->setItemLabelFormat(QStringLiteral("@valueTitle for (@rowIdx, @colIdx): @valueLabel"));
- m_genericData->setColumnLabels(genericColumnLabels);
-
- m_chart->addDataProxy(m_temperatureData);
- m_chart->addDataProxy(m_genericData);
-
- m_chart->setFont(QFont("Times Roman", 20));
+ m_graph->addAxis(m_autoAdjustingAxis);
+ m_graph->addAxis(m_fixedRangeAxis);
+ m_graph->addAxis(m_temperatureAxis);
+ m_graph->addAxis(m_yearAxis);
+ m_graph->addAxis(m_monthAxis);
+ m_graph->addAxis(m_genericRowAxis);
+ m_graph->addAxis(m_genericColumnAxis);
+
+ m_graph->setTheme(new Q3DTheme(Q3DTheme::ThemeStoneMoss));
+ m_graph->setShadowQuality(QDataVis::ShadowQualitySoftMedium);
+
+ m_temperatureData->setItemLabelFormat(QStringLiteral("1: @valueTitle for @colLabel @rowLabel: @valueLabel"));
+ m_temperatureData2->setItemLabelFormat(QStringLiteral("2: @valueTitle for @colLabel @rowLabel: @valueLabel"));
+ m_genericData->setItemLabelFormat(QStringLiteral("3: @valueTitle for (@rowIdx, @colIdx): @valueLabel"));
+ m_genericData->dataProxy()->setColumnLabels(genericColumnLabels);
+
+ m_temperatureData->setBaseColor(Qt::red);
+ m_temperatureData->setSingleHighlightColor(Qt::cyan);
+ m_temperatureData->setMultiHighlightColor(Qt::magenta);
+ m_temperatureData2->setBaseColor(Qt::yellow);
+ m_genericData->setBaseColor(Qt::blue);
+
+ QLinearGradient barGradient1(0, 0, 1, 100);
+ barGradient1.setColorAt(1.0, Qt::red);
+ barGradient1.setColorAt(0.75001, Qt::red);
+ barGradient1.setColorAt(0.75, Qt::magenta);
+ barGradient1.setColorAt(0.50001, Qt::magenta);
+ barGradient1.setColorAt(0.50, Qt::blue);
+ barGradient1.setColorAt(0.25001, Qt::blue);
+ barGradient1.setColorAt(0.25, Qt::black);
+ barGradient1.setColorAt(0.0, Qt::black);
+
+ QLinearGradient barGradient2(0, 0, 1, 100);
+ barGradient2.setColorAt(1.0, Qt::red);
+ barGradient2.setColorAt(0.75, Qt::magenta);
+ barGradient2.setColorAt(0.50, Qt::blue);
+ barGradient2.setColorAt(0.25, Qt::black);
+ barGradient2.setColorAt(0.0, Qt::black);
+
+ QLinearGradient singleHighlightGradient(0, 0, 1, 100);
+ singleHighlightGradient.setColorAt(1.0, Qt::white);
+ singleHighlightGradient.setColorAt(0.75, Qt::lightGray);
+ singleHighlightGradient.setColorAt(0.50, Qt::gray);
+ singleHighlightGradient.setColorAt(0.25, Qt::darkGray);
+ singleHighlightGradient.setColorAt(0.0, Qt::black);
+
+ QLinearGradient multiHighlightGradient(0, 0, 1, 100);
+ multiHighlightGradient.setColorAt(1.0, Qt::lightGray);
+ multiHighlightGradient.setColorAt(0.75, Qt::gray);
+ multiHighlightGradient.setColorAt(0.50, Qt::darkGray);
+ multiHighlightGradient.setColorAt(0.25, Qt::black);
+ multiHighlightGradient.setColorAt(0.0, Qt::black);
+
+ m_temperatureData->setBaseGradient(barGradient1);
+ m_temperatureData2->setBaseGradient(barGradient2);
+ m_temperatureData->setSingleHighlightGradient(singleHighlightGradient);
+ m_temperatureData->setMultiHighlightGradient(multiHighlightGradient);
+
+ m_graph->theme()->setFont(QFont("Times Roman", 20));
+
+ // Release and store the default input handler.
+ m_defaultInputHandler = m_graph->activeInputHandler();
+ m_graph->releaseInputHandler(m_defaultInputHandler);
+ m_graph->setActiveInputHandler(m_defaultInputHandler);
+
+ QObject::connect(m_graph, &Q3DBars::shadowQualityChanged, this,
+ &GraphModifier::shadowQualityUpdatedByVisual);
+ QObject::connect(m_temperatureData, &QBar3DSeries::selectedBarChanged, this,
+ &GraphModifier::handleSelectionChange);
+ QObject::connect(m_temperatureData2, &QBar3DSeries::selectedBarChanged, this,
+ &GraphModifier::handleSelectionChange);
+ QObject::connect(m_genericData, &QBar3DSeries::selectedBarChanged, this,
+ &GraphModifier::handleSelectionChange);
+
+ m_graph->addSeries(m_temperatureData);
+ m_graph->addSeries(m_temperatureData2);
resetTemperatureData();
}
GraphModifier::~GraphModifier()
{
- delete m_chart;
+ delete m_graph;
+ delete m_defaultInputHandler;
}
void GraphModifier::start()
@@ -134,25 +204,24 @@ void GraphModifier::restart(bool dynamicData)
m_static = !dynamicData;
if (m_static) {
- m_chart->setActiveDataProxy(m_temperatureData);
+ m_graph->removeSeries(m_genericData);
- m_chart->setTitle(QStringLiteral("Average temperatures in Oulu, Finland (2006-2012)"));
+ m_graph->setTitle(QStringLiteral("Average temperatures in Oulu, Finland (2006-2012)"));
- m_chart->setValueAxis(m_temperatureAxis);
- m_chart->setRowAxis(m_yearAxis);
- m_chart->setColumnAxis(m_monthAxis);
+ m_graph->setValueAxis(m_temperatureAxis);
+ m_graph->setRowAxis(m_yearAxis);
+ m_graph->setColumnAxis(m_monthAxis);
- m_chart->setSelectionMode(QDataVis::SelectionModeItem);
} else {
- m_chart->setActiveDataProxy(m_genericData);
-
- m_chart->setTitle(QStringLiteral("Generic data"));
+ m_graph->addSeries(m_genericData);
- m_chart->setValueAxis(m_currentAxis);
- m_chart->setRowAxis(m_genericRowAxis);
- m_chart->setColumnAxis(m_genericColumnAxis);
+ m_graph->setTitle(QStringLiteral("Generic data"));
- m_chart->setSelectionMode(QDataVis::SelectionModeItem);
+ m_minval = m_fixedRangeAxis->min();
+ m_maxval = m_fixedRangeAxis->max();
+ m_graph->setValueAxis(m_currentAxis);
+ m_graph->setRowAxis(m_genericRowAxis);
+ m_graph->setColumnAxis(m_genericColumnAxis);
}
}
@@ -160,10 +229,10 @@ void GraphModifier::selectBar()
{
QPoint targetBar(5, 5);
QPoint noSelection(-1, -1);
- if (m_selectedBarPos != targetBar)
- m_chart->setSelectedBarPos(targetBar);
+ if (m_selectedBar != targetBar)
+ m_graph->seriesList().at(0)->setSelectedBar(targetBar);
else
- m_chart->setSelectedBarPos(noSelection);
+ m_graph->seriesList().at(0)->setSelectedBar(noSelection);
}
void GraphModifier::swapAxis()
@@ -182,7 +251,7 @@ void GraphModifier::swapAxis()
qDebug() << "default axis";
}
- m_chart->setValueAxis(m_currentAxis);
+ m_graph->setValueAxis(m_currentAxis);
}
void GraphModifier::releaseAxes()
@@ -190,21 +259,37 @@ void GraphModifier::releaseAxes()
// Releases all axes - results in default axes for all dimensions.
// Axes reset when the graph is switched as set*Axis calls are made, which
// implicitly add axes.
- m_chart->releaseAxis(m_autoAdjustingAxis);
- m_chart->releaseAxis(m_fixedRangeAxis);
- m_chart->releaseAxis(m_temperatureAxis);
- m_chart->releaseAxis(m_yearAxis);
- m_chart->releaseAxis(m_monthAxis);
- m_chart->releaseAxis(m_genericRowAxis);
- m_chart->releaseAxis(m_genericColumnAxis);
+ m_graph->releaseAxis(m_autoAdjustingAxis);
+ m_graph->releaseAxis(m_fixedRangeAxis);
+ m_graph->releaseAxis(m_temperatureAxis);
+ m_graph->releaseAxis(m_yearAxis);
+ m_graph->releaseAxis(m_monthAxis);
+ m_graph->releaseAxis(m_genericRowAxis);
+ m_graph->releaseAxis(m_genericColumnAxis);
}
void GraphModifier::releaseProxies()
{
- // Releases all proxies - results in default proxy.
- // Proxies will get readded back when graph is switched as setDataProxy call is made.
- m_chart->releaseDataProxy(m_temperatureData);
- m_chart->releaseDataProxy(m_genericData);
+ // Releases all series/add all series toggle
+ if (m_graph->seriesList().size() > 0) {
+ m_graph->removeSeries(m_temperatureData);
+ m_graph->removeSeries(m_temperatureData2);
+ m_graph->removeSeries(m_genericData);
+ m_graph->removeSeries(m_dummyData);
+ m_graph->removeSeries(m_dummyData2);
+ m_graph->removeSeries(m_dummyData3);
+ m_graph->removeSeries(m_dummyData4);
+ m_graph->removeSeries(m_dummyData5);
+ } else {
+ m_graph->addSeries(m_temperatureData);
+ m_graph->addSeries(m_temperatureData2);
+ m_graph->addSeries(m_genericData);
+ }
+}
+
+void GraphModifier::flipViews()
+{
+ m_graph->scene()->setSecondarySubviewOnTop(!m_graph->scene()->isSecondarySubviewOnTop());
}
void GraphModifier::createMassiveArray()
@@ -233,28 +318,32 @@ void GraphModifier::createMassiveArray()
dataArray->reserve(arrayDimension);
for (int i = 0; i < arrayDimension; i++) {
QBarDataRow *dataRow = new QBarDataRow(arrayDimension);
- for (int j = 0; j < arrayDimension; j++)
- (*dataRow)[j].setValue((qreal(i % 300 + 1) / 300.0) * qreal(rand() % 100));
+ for (int j = 0; j < arrayDimension; j++) {
+ if (!m_negativeValuesOn)
+ (*dataRow)[j].setValue((float(i % 300 + 1) / 300.0) * float(rand() % int(m_maxval)));
+ else
+ (*dataRow)[j].setValue((float(i % 300 + 1) / 300.0) * float(rand() % int(m_maxval))
+ + m_minval);
+ }
dataArray->append(dataRow);
}
- m_chart->activeDataProxy()->resetArray(dataArray, genericRowLabels, genericColumnLabels);
+ m_genericData->dataProxy()->resetArray(dataArray, genericRowLabels, genericColumnLabels);
qDebug() << "Created Massive Array (" << arrayDimension << "), time:" << timer.elapsed();
}
void GraphModifier::resetTemperatureData()
{
-
// Set up data
- static const qreal temp[7][12] = {
- {-6.7, -11.7, -9.7, 3.3, 9.2, 14.0, 16.3, 17.8, 10.2, 2.1, -2.6, -0.3}, // 2006
- {-6.8, -13.3, 0.2, 1.5, 7.9, 13.4, 16.1, 15.5, 8.2, 5.4, -2.6, -0.8}, // 2007
- {-4.2, -4.0, -4.6, 1.9, 7.3, 12.5, 15.0, 12.8, 7.6, 5.1, -0.9, -1.3}, // 2008
- {-7.8, -8.8, -4.2, 0.7, 9.3, 13.2, 15.8, 15.5, 11.2, 0.6, 0.7, -8.4}, // 2009
- {-14.4, -12.1, -7.0, 2.3, 11.0, 12.6, 18.8, 13.8, 9.4, 3.9, -5.6, -13.0}, // 2010
- {-9.0, -15.2, -3.8, 2.6, 8.3, 15.9, 18.6, 14.9, 11.1, 5.3, 1.8, -0.2}, // 2011
- {-8.7, -11.3, -2.3, 0.4, 7.5, 12.2, 16.4, 14.1, 9.2, 3.1, 0.3, -12.1} // 2012
+ static const float temp[7][12] = {
+ {-6.7f, -11.7f, -9.7f, 3.3f, 9.2f, 14.0f, 16.3f, 17.8f, 10.2f, 2.1f, -2.6f, -0.3f}, // 2006
+ {-6.8f, -13.3f, 0.2f, 1.5f, 7.9f, 13.4f, 16.1f, 15.5f, 8.2f, 5.4f, -2.6f, -0.8f}, // 2007
+ {-4.2f, -4.0f, -4.6f, 1.9f, 7.3f, 12.5f, 15.0f, 12.8f, 7.6f, 5.1f, -0.9f, -1.3f}, // 2008
+ {-7.8f, -8.8f, -4.2f, 0.7f, 9.3f, 13.2f, 15.8f, 15.5f, 11.2f, 0.6f, 0.7f, -8.4f}, // 2009
+ {-14.4f, -12.1f, -7.0f, 2.3f, 11.0f, 12.6f, 18.8f, 13.8f, 9.4f, 3.9f, -5.6f, -13.0f}, // 2010
+ {-9.0f, -15.2f, -3.8f, 2.6f, 8.3f, 15.9f, 18.6f, 14.9f, 11.1f, 5.3f, 1.8f, -0.2f}, // 2011
+ {-8.7f, -11.3f, -2.3f, 0.4f, 7.5f, 12.2f, 16.4f, 14.1f, 9.2f, 3.1f, 0.3f, -12.1f} // 2012
};
// Create data rows
@@ -273,9 +362,23 @@ void GraphModifier::resetTemperatureData()
dataSet->append(dataRow);
}
+ QBarDataArray *dataSet2 = new QBarDataArray;
+
+ dataSet2->reserve(m_years.size());
+ for (int year = m_years.size() - 1; year >= 0; year--) {
+ dataRow = new QBarDataRow(m_months.size());
+ // Create data items
+ for (int month = m_months.size() - 1; month >= 0 ; month--) {
+ // Add data to rows
+ (*dataRow)[month].setValue(temp[year][month]);
+ }
+ // Add row to set
+ dataSet2->append(dataRow);
+ }
// Add data to chart (chart assumes ownership)
- m_temperatureData->resetArray(dataSet, m_years, m_months);
+ m_temperatureData->dataProxy()->resetArray(dataSet, m_years, m_months);
+ m_temperatureData2->dataProxy()->resetArray(dataSet2, m_years, m_months);
}
@@ -286,12 +389,17 @@ static int changeCounter = 0;
void GraphModifier::addRow()
{
QBarDataRow *dataRow = new QBarDataRow(m_columnCount);
- for (qreal i = 0; i < m_columnCount; i++)
- (*dataRow)[i].setValue(((i + 1) / (qreal)m_columnCount) * (qreal)(rand() % 100));
+ for (float i = 0; i < m_columnCount; i++) {
+ if (!m_negativeValuesOn)
+ (*dataRow)[i].setValue(((i + 1) / (float)m_columnCount) * (float)(rand() % int(m_maxval)));
+ else
+ (*dataRow)[i].setValue(((i + 1) / (float)m_columnCount) * (float)(rand() % int(m_maxval))
+ - (float)(rand() % int(m_minval)));
+ }
// TODO Needs to be changed to account for data window offset once it is implemented.
QString label = QStringLiteral("Add %1").arg(addCounter++);
- m_chart->activeDataProxy()->addRow(dataRow, label);
+ m_genericData->dataProxy()->addRow(dataRow, label);
}
void GraphModifier::addRows()
@@ -301,25 +409,26 @@ void GraphModifier::addRows()
for (int i = 0; i < m_rowCount; i++) {
QBarDataRow *dataRow = new QBarDataRow(m_columnCount);
for (int j = 0; j < m_columnCount; j++)
- (*dataRow)[j].setValue(qreal(j + i + m_chart->activeDataProxy()->rowCount()));
+ (*dataRow)[j].setValue(float(j + i + m_genericData->dataProxy()->rowCount()) + m_minval);
dataArray.append(dataRow);
labels.append(QStringLiteral("Add %1").arg(addCounter++));
}
// TODO Needs to be changed to account for data window offset once it is implemented.
- m_chart->activeDataProxy()->addRows(dataArray, labels);
+ m_genericData->dataProxy()->addRows(dataArray, labels);
}
void GraphModifier::insertRow()
{
QBarDataRow *dataRow = new QBarDataRow(m_columnCount);
- for (qreal i = 0; i < m_columnCount; i++)
- (*dataRow)[i].setValue(((i + 1) / (qreal)m_columnCount) * (qreal)(rand() % 100));
+ for (float i = 0; i < m_columnCount; i++)
+ (*dataRow)[i].setValue(((i + 1) / (float)m_columnCount) * (float)(rand() % int(m_maxval))
+ + m_minval);
// TODO Needs to be changed to account for data window offset once it is implemented.
- int row = qMax(m_selectedBarPos.x(), 0);
+ int row = qMax(m_selectedBar.x(), 0);
QString label = QStringLiteral("Insert %1").arg(insertCounter++);
- m_chart->activeDataProxy()->insertRow(row, dataRow, label);
+ m_genericData->dataProxy()->insertRow(row, dataRow, label);
}
void GraphModifier::insertRows()
@@ -331,75 +440,75 @@ void GraphModifier::insertRows()
for (int i = 0; i < m_rowCount; i++) {
QBarDataRow *dataRow = new QBarDataRow(m_columnCount);
for (int j = 0; j < m_columnCount; j++)
- (*dataRow)[j].setValue(qreal(j + i + m_chart->activeDataProxy()->rowCount()));
+ (*dataRow)[j].setValue(float(j + i + m_genericData->dataProxy()->rowCount()) + m_minval);
dataArray.append(dataRow);
labels.append(QStringLiteral("Insert %1").arg(insertCounter++));
}
// TODO Needs to be changed to account for data window offset once it is implemented.
- int row = qMax(m_selectedBarPos.x(), 0);
- m_chart->activeDataProxy()->insertRows(row, dataArray, labels);
+ int row = qMax(m_selectedBar.x(), 0);
+ m_genericData->dataProxy()->insertRows(row, dataArray, labels);
qDebug() << "Inserted" << m_rowCount << "rows, time:" << timer.elapsed();
}
void GraphModifier::changeItem()
{
// TODO Needs to be changed to account for data window offset once it is implemented.
- int row = m_selectedBarPos.x();
- int column = m_selectedBarPos.y();
+ int row = m_selectedBar.x();
+ int column = m_selectedBar.y();
if (row >= 0 && column >= 0) {
- QBarDataItem item(qreal(rand() % 100));
- m_chart->activeDataProxy()->setItem(row, column, item);
+ QBarDataItem item(float(rand() % 100));
+ m_genericData->dataProxy()->setItem(row, column, item);
}
}
void GraphModifier::changeRow()
{
// TODO Needs to be changed to account for data window offset once it is implemented.
- int row = m_selectedBarPos.x();
+ int row = m_selectedBar.x();
if (row >= 0) {
- QBarDataRow *newRow = new QBarDataRow(m_chart->activeDataProxy()->rowAt(row)->size());
+ QBarDataRow *newRow = new QBarDataRow(m_genericData->dataProxy()->rowAt(row)->size());
for (int i = 0; i < newRow->size(); i++)
- (*newRow)[i].setValue(qreal(rand() % 100));
+ (*newRow)[i].setValue(float(rand() % int(m_maxval)) + m_minval);
QString label = QStringLiteral("Change %1").arg(changeCounter++);
- m_chart->activeDataProxy()->setRow(row, newRow, label);
+ m_genericData->dataProxy()->setRow(row, newRow, label);
}
}
void GraphModifier::changeRows()
{
// TODO Needs to be changed to account for data window offset once it is implemented.
- int row = m_selectedBarPos.x();
+ int row = m_selectedBar.x();
if (row >= 0) {
int startRow = qMax(row - 2, 0);
QBarDataArray newArray;
QStringList labels;
for (int i = startRow; i <= row; i++ ) {
- QBarDataRow *newRow = new QBarDataRow(m_chart->activeDataProxy()->rowAt(i)->size());
+ QBarDataRow *newRow = new QBarDataRow(m_genericData->dataProxy()->rowAt(i)->size());
for (int j = 0; j < newRow->size(); j++)
- (*newRow)[j].setValue(qreal(rand() % 100));
+ (*newRow)[j].setValue(float(rand() % int(m_maxval)) + m_minval);
newArray.append(newRow);
labels.append(QStringLiteral("Change %1").arg(changeCounter++));
}
- m_chart->activeDataProxy()->setRows(startRow, newArray, labels);
+ m_genericData->dataProxy()->setRows(startRow, newArray, labels);
}
}
void GraphModifier::removeRow()
{
// TODO Needs to be changed to account for data window offset once it is implemented.
- int row = m_selectedBarPos.x();
+ int row = m_selectedBar.x();
if (row >= 0)
- m_chart->activeDataProxy()->removeRows(row, 1);
+ m_genericData->dataProxy()->removeRows(row, 1);
}
void GraphModifier::removeRows()
{
// TODO Needs to be changed to account for data window offset once it is implemented.
- int row = m_selectedBarPos.x();
+ int row = m_selectedBar.x();
if (row >= 0) {
int startRow = qMax(row - 2, 0);
- m_chart->activeDataProxy()->removeRows(startRow, 3);
+ m_genericData->dataProxy()->removeRows(startRow, 3);
}
}
@@ -408,34 +517,44 @@ void GraphModifier::changeStyle()
static int model = 0;
switch (model) {
case 0:
- m_chart->setBarType(QDataVis::MeshStyleCylinders, false);
+ m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshCylinder);
+ m_graph->seriesList().at(0)->setMeshSmooth(false);
break;
case 1:
- m_chart->setBarType(QDataVis::MeshStyleCylinders, true);
+ m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshCylinder);
+ m_graph->seriesList().at(0)->setMeshSmooth(true);
break;
case 2:
- m_chart->setBarType(QDataVis::MeshStyleCones, false);
+ m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshCone);
+ m_graph->seriesList().at(0)->setMeshSmooth(false);
break;
case 3:
- m_chart->setBarType(QDataVis::MeshStyleCones, true);
+ m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshCone);
+ m_graph->seriesList().at(0)->setMeshSmooth(true);
break;
case 4:
- m_chart->setBarType(QDataVis::MeshStyleBars, false);
+ m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshBar);
+ m_graph->seriesList().at(0)->setMeshSmooth(false);
break;
case 5:
- m_chart->setBarType(QDataVis::MeshStyleBars, true);
+ m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshBar);
+ m_graph->seriesList().at(0)->setMeshSmooth(true);
break;
case 6:
- m_chart->setBarType(QDataVis::MeshStylePyramids, false);
+ m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshPyramid);
+ m_graph->seriesList().at(0)->setMeshSmooth(false);
break;
case 7:
- m_chart->setBarType(QDataVis::MeshStylePyramids, true);
+ m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshPyramid);
+ m_graph->seriesList().at(0)->setMeshSmooth(true);
break;
case 8:
- m_chart->setBarType(QDataVis::MeshStyleBevelBars, false);
+ m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshBevelBar);
+ m_graph->seriesList().at(0)->setMeshSmooth(false);
break;
case 9:
- m_chart->setBarType(QDataVis::MeshStyleBevelBars, true);
+ m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshBevelBar);
+ m_graph->seriesList().at(0)->setMeshSmooth(true);
break;
}
model++;
@@ -445,57 +564,82 @@ void GraphModifier::changeStyle()
void GraphModifier::changePresetCamera()
{
- static int preset = QDataVis::CameraPresetFrontLow;
+ static int preset = Q3DCamera::CameraPresetFrontLow;
- m_chart->scene()->activeCamera()->setCameraPreset((QDataVis::CameraPreset)preset);
+ m_graph->scene()->activeCamera()->setCameraPreset((Q3DCamera::CameraPreset)preset);
- if (++preset > QDataVis::CameraPresetDirectlyBelow)
- preset = QDataVis::CameraPresetFrontLow;
+ if (++preset > Q3DCamera::CameraPresetDirectlyBelow)
+ preset = Q3DCamera::CameraPresetFrontLow;
}
void GraphModifier::changeTheme()
{
- static int theme = QDataVis::ThemeQt;
-
- m_chart->setTheme((QDataVis::Theme)theme);
+ static int theme = Q3DTheme::ThemeQt;
+
+ m_graph->setTheme(new Q3DTheme((Q3DTheme::Theme)theme));
+
+ switch (theme) {
+ case Q3DTheme::ThemeQt:
+ qDebug() << __FUNCTION__ << "ThemeQt";
+ break;
+ case Q3DTheme::ThemePrimaryColors:
+ qDebug() << __FUNCTION__ << "ThemePrimaryColors";
+ break;
+ case Q3DTheme::ThemeDigia:
+ qDebug() << __FUNCTION__ << "ThemeDigia";
+ break;
+ case Q3DTheme::ThemeStoneMoss:
+ qDebug() << __FUNCTION__ << "ThemeStoneMoss";
+ break;
+ case Q3DTheme::ThemeArmyBlue:
+ qDebug() << __FUNCTION__ << "ThemeArmyBlue";
+ break;
+ case Q3DTheme::ThemeRetro:
+ qDebug() << __FUNCTION__ << "ThemeRetro";
+ break;
+ case Q3DTheme::ThemeEbony:
+ qDebug() << __FUNCTION__ << "ThemeEbony";
+ break;
+ case Q3DTheme::ThemeIsabelle:
+ qDebug() << __FUNCTION__ << "ThemeIsabelle";
+ break;
+ default:
+ qDebug() << __FUNCTION__ << "Unknown theme";
+ break;
+ }
- if (++theme > QDataVis::ThemeIsabelle)
- theme = QDataVis::ThemeQt;
+ if (++theme > Q3DTheme::ThemeIsabelle)
+ theme = Q3DTheme::ThemeQt;
}
void GraphModifier::changeLabelStyle()
{
- static int style = QDataVis::LabelStyleOpaque;
-
- m_chart->setLabelStyle((QDataVis::LabelStyle)style);
-
- if (++style > QDataVis::LabelStyleTransparent)
- style = QDataVis::LabelStyleOpaque;
+ m_graph->theme()->setLabelBackgroundEnabled(!m_graph->theme()->isLabelBackgroundEnabled());
}
void GraphModifier::changeSelectionMode()
{
- static int selectionMode = m_chart->selectionMode();
+ static int selectionMode = m_graph->selectionMode();
- if (++selectionMode > QDataVis::SelectionModeSliceColumn)
- selectionMode = QDataVis::SelectionModeNone;
+ if (++selectionMode > (QDataVis::SelectionItemAndColumn | QDataVis::SelectionSlice | QDataVis::SelectionMultiSeries))
+ selectionMode = QDataVis::SelectionNone;
- m_chart->setSelectionMode((QDataVis::SelectionMode)selectionMode);
+ m_graph->setSelectionMode((QDataVis::SelectionFlag)selectionMode);
}
void GraphModifier::changeFont(const QFont &font)
{
QFont newFont = font;
newFont.setPointSize(m_fontSize);
- m_chart->setFont(newFont);
+ m_graph->theme()->setFont(newFont);
}
void GraphModifier::changeFontSize(int fontsize)
{
m_fontSize = fontsize;
- QFont font = m_chart->font();
+ QFont font = m_graph->theme()->font();
font.setPointSize(m_fontSize);
- m_chart->setFont(font);
+ m_graph->theme()->setFont(font);
}
void GraphModifier::shadowQualityUpdatedByVisual(QDataVis::ShadowQuality sq)
@@ -507,54 +651,127 @@ void GraphModifier::shadowQualityUpdatedByVisual(QDataVis::ShadowQuality sq)
void GraphModifier::handleSelectionChange(const QPoint &position)
{
- m_selectedBarPos = position;
- qDebug() << "Selected bar position:" << position;
+ m_selectedBar = position;
+ int index = 0;
+ foreach (QBar3DSeries *series, m_graph->seriesList()) {
+ if (series == sender())
+ break;
+ index++;
+ }
+
+ qDebug() << "Selected bar position:" << position << "series:" << index;
}
+void GraphModifier::setUseNullInputHandler(bool useNull)
+{
+ qDebug() << "setUseNullInputHandler" << useNull;
+ if (m_useNullInputHandler == useNull)
+ return;
+
+ m_useNullInputHandler = useNull;
+
+ if (useNull)
+ m_graph->setActiveInputHandler(0);
+ else
+ m_graph->setActiveInputHandler(m_defaultInputHandler);
+}
+
+
void GraphModifier::changeShadowQuality(int quality)
{
QDataVis::ShadowQuality sq = QDataVis::ShadowQuality(quality);
- m_chart->setShadowQuality(sq);
+ m_graph->setShadowQuality(sq);
emit shadowQualityChanged(quality);
}
+void GraphModifier::showFiveSeries()
+{
+ releaseProxies();
+ releaseAxes();
+ m_graph->setSelectionMode(QDataVis::SelectionItemRowAndColumn | QDataVis::SelectionMultiSeries);
+
+ m_dummyData->dataProxy()->resetArray(makeDummyData(), QStringList(), QStringList());
+ m_dummyData2->dataProxy()->resetArray(makeDummyData(), QStringList(), QStringList());
+ m_dummyData3->dataProxy()->resetArray(makeDummyData(), QStringList(), QStringList());
+ m_dummyData4->dataProxy()->resetArray(makeDummyData(), QStringList(), QStringList());
+ m_dummyData5->dataProxy()->resetArray(makeDummyData(), QStringList(), QStringList());
+
+ m_graph->addSeries(m_dummyData);
+ m_graph->addSeries(m_dummyData2);
+ m_graph->addSeries(m_dummyData3);
+ m_graph->addSeries(m_dummyData4);
+
+ // Toggle between four and five series
+ static int count = 0;
+ if (++count % 2)
+ m_graph->addSeries(m_dummyData5);
+}
+
+QBarDataArray *GraphModifier::makeDummyData()
+{
+ // Set up data
+ static const float temp[4][4] = {
+ {10.0f, 5.0f, 10.0f, 5.0f},
+ {5.0f, 10.0f, 5.0f, 10.0f},
+ {10.0f, 5.0f, 10.0f, 5.0f},
+ {5.0f, 10.0f, 5.0f, 10.0f}
+ };
+
+ // Create data rows
+ QBarDataArray *dataSet = new QBarDataArray;
+ QBarDataRow *dataRow;
+
+ dataSet->reserve(4);
+ for (int i = 0; i < 4; i++) {
+ dataRow = new QBarDataRow(4);
+ // Create data items
+ for (int j = 0; j < 4; j++) {
+ // Add data to rows
+ (*dataRow)[j].setValue(temp[i][j]);
+ }
+ // Add row to set
+ dataSet->append(dataRow);
+ }
+ return dataSet;
+}
+
void GraphModifier::setBackgroundEnabled(int enabled)
{
- m_chart->setBackgroundVisible((bool)enabled);
+ m_graph->theme()->setBackgroundEnabled(bool(enabled));
}
void GraphModifier::setGridEnabled(int enabled)
{
- m_chart->setGridVisible((bool)enabled);
+ m_graph->theme()->setGridEnabled(bool(enabled));
}
void GraphModifier::rotateX(int rotation)
{
m_xRotation = rotation;
- m_chart->scene()->activeCamera()->setCameraPosition(m_xRotation, m_yRotation);
+ m_graph->scene()->activeCamera()->setCameraPosition(m_xRotation, m_yRotation);
}
void GraphModifier::rotateY(int rotation)
{
m_yRotation = rotation;
- m_chart->scene()->activeCamera()->setCameraPosition(m_xRotation, m_yRotation);
+ m_graph->scene()->activeCamera()->setCameraPosition(m_xRotation, m_yRotation);
}
void GraphModifier::setSpecsRatio(int barwidth)
{
- m_chart->setBarThickness((qreal)barwidth / 30.0);
+ m_graph->setBarThickness((float)barwidth / 30.0f);
}
void GraphModifier::setSpacingSpecsX(int spacing)
{
- m_barSpacingX = (qreal)spacing / 100.0;
- m_chart->setBarSpacing(QSizeF(m_barSpacingX, m_barSpacingZ));
+ m_barSpacingX = (float)spacing / 100.0f;
+ m_graph->setBarSpacing(QSizeF(m_barSpacingX, m_barSpacingZ));
}
void GraphModifier::setSpacingSpecsZ(int spacing)
{
- m_barSpacingZ = (qreal)spacing / 100.0;
- m_chart->setBarSpacing(QSizeF(m_barSpacingX, m_barSpacingZ));
+ m_barSpacingZ = (float)spacing / 100.0f;
+ m_graph->setBarSpacing(QSizeF(m_barSpacingX, m_barSpacingZ));
}
void GraphModifier::setSampleCountX(int samples)
@@ -578,3 +795,97 @@ void GraphModifier::setMinZ(int min)
{
m_genericColumnAxis->setRange(min, min + m_rowCount - 1);
}
+
+void GraphModifier::setMinY(int min)
+{
+ m_fixedRangeAxis->setMin(min);
+ m_negativeValuesOn = (min < 0) ? true : false;
+ m_minval = min;
+}
+
+void GraphModifier::setMaxY(int max)
+{
+ m_fixedRangeAxis->setMax(max);
+ m_maxval = max;
+}
+
+void GraphModifier::changeColorStyle()
+{
+ int style = m_graph->theme()->colorStyle();
+
+ if (++style > Q3DTheme::ColorStyleRangeGradient)
+ style = Q3DTheme::ColorStyleUniform;
+
+ m_graph->theme()->setColorStyle(Q3DTheme::ColorStyle(style));
+}
+
+void GraphModifier::useOwnTheme()
+{
+ Q3DTheme *theme = new Q3DTheme();
+ theme->setBackgroundEnabled(true);
+ theme->setGridEnabled(true);
+ theme->setAmbientLightStrength(0.3f);
+ theme->setBackgroundColor(QColor(QRgb(0x99ca53)));
+ QList<QColor> colors;
+ colors.append(QColor(QRgb(0x209fdf)));
+ theme->setBaseColors(colors);
+ theme->setColorStyle(Q3DTheme::ColorStyleUniform);
+ theme->setGridLineColor(QColor(QRgb(0x99ca53)));
+ theme->setHighlightLightStrength(7.0f);
+ theme->setLabelBackgroundEnabled(true);
+ theme->setLabelBorderEnabled(true);
+ theme->setLightColor(Qt::white);
+ theme->setLightStrength(6.0f);
+ theme->setMultiHighlightColor(QColor(QRgb(0x6d5fd5)));
+ theme->setSingleHighlightColor(QColor(QRgb(0xf6a625)));
+ theme->setLabelBackgroundColor(QColor(0xf6, 0xa6, 0x25, 0xa0));
+ theme->setLabelTextColor(QColor(QRgb(0x404044)));
+ theme->setWindowColor(QColor(QRgb(0xffffff)));
+
+ m_graph->setTheme(theme);
+
+ m_colorDialog->open();
+}
+
+void GraphModifier::changeBaseColor(const QColor &color)
+{
+ qDebug() << "base color changed to" << color;
+ QList<QColor> colors;
+ colors.append(color);
+ m_graph->theme()->setBaseColors(colors);
+}
+
+void GraphModifier::setGradient()
+{
+ QLinearGradient barGradient(0, 0, 1, 100);
+ barGradient.setColorAt(1.0, Qt::lightGray);
+ barGradient.setColorAt(0.75001, Qt::lightGray);
+ barGradient.setColorAt(0.75, Qt::blue);
+ barGradient.setColorAt(0.50001, Qt::blue);
+ barGradient.setColorAt(0.50, Qt::red);
+ barGradient.setColorAt(0.25001, Qt::red);
+ barGradient.setColorAt(0.25, Qt::yellow);
+ barGradient.setColorAt(0.0, Qt::yellow);
+
+ QLinearGradient singleHighlightGradient(0, 0, 1, 100);
+ singleHighlightGradient.setColorAt(1.0, Qt::white);
+ singleHighlightGradient.setColorAt(0.75, Qt::lightGray);
+ singleHighlightGradient.setColorAt(0.50, Qt::gray);
+ singleHighlightGradient.setColorAt(0.25, Qt::darkGray);
+ singleHighlightGradient.setColorAt(0.0, Qt::black);
+
+ QLinearGradient multiHighlightGradient(0, 0, 1, 100);
+ multiHighlightGradient.setColorAt(1.0, Qt::black);
+ multiHighlightGradient.setColorAt(0.75, Qt::darkBlue);
+ multiHighlightGradient.setColorAt(0.50, Qt::darkRed);
+ multiHighlightGradient.setColorAt(0.25, Qt::darkYellow);
+ multiHighlightGradient.setColorAt(0.0, Qt::darkGray);
+
+ QList<QLinearGradient> barGradients;
+ barGradients.append(barGradient);
+ m_graph->theme()->setBaseGradients(barGradients);
+ m_graph->theme()->setSingleHighlightGradient(singleHighlightGradient);
+ m_graph->theme()->setMultiHighlightGradient(multiHighlightGradient);
+
+ m_graph->theme()->setColorStyle(Q3DTheme::ColorStyleObjectGradient);
+}
diff --git a/tests/barstest/chart.h b/tests/barstest/chart.h
index e4e96ffb..96038b9f 100644
--- a/tests/barstest/chart.h
+++ b/tests/barstest/chart.h
@@ -20,11 +20,13 @@
#define CHARTMODIFIER_H
#include <QtDataVisualization/q3dbars.h>
-
+#include <QtDataVisualization/qabstract3dinputhandler.h>
+#include <QtDataVisualization/qbar3dseries.h>
#include <QFont>
#include <QDebug>
#include <QStringList>
#include <QPointer>
+#include <QColorDialog>
using namespace QtDataVisualization;
@@ -32,7 +34,7 @@ class GraphModifier : public QObject
{
Q_OBJECT
public:
- explicit GraphModifier(Q3DBars *barchart);
+ explicit GraphModifier(Q3DBars *barchart, QColorDialog *colorDialog);
~GraphModifier();
void resetTemperatureData();
@@ -64,6 +66,8 @@ public:
void setSampleCountZ(int samples);
void setMinX(int min);
void setMinZ(int min);
+ void setMinY(int min);
+ void setMaxY(int max);
void start();
void restart(bool dynamicData);
void selectBar();
@@ -71,32 +75,41 @@ public:
void releaseAxes();
void releaseProxies();
void createMassiveArray();
+ void useOwnTheme();
+ void changeBaseColor(const QColor &color);
+ void changeColorStyle();
+ void showFiveSeries();
+ QBarDataArray *makeDummyData();
public slots:
+ void flipViews();
+ void setGradient();
void changeShadowQuality(int quality);
void shadowQualityUpdatedByVisual(QDataVis::ShadowQuality shadowQuality);
void handleSelectionChange(const QPoint &position);
+ void setUseNullInputHandler(bool useNull);
signals:
void shadowQualityChanged(int quality);
private:
- Q3DBars *m_chart;
+ Q3DBars *m_graph;
+ QColorDialog *m_colorDialog;
int m_columnCount;
int m_rowCount;
- qreal m_xRotation;
- qreal m_yRotation;
+ float m_xRotation;
+ float m_yRotation;
bool m_static;
- qreal m_barSpacingX;
- qreal m_barSpacingZ;
+ float m_barSpacingX;
+ float m_barSpacingZ;
int m_fontSize;
int m_segments;
int m_subSegments;
- qreal m_minval;
- qreal m_maxval;
+ float m_minval;
+ float m_maxval;
QStringList m_months;
QStringList m_years;
- QPoint m_selectedBarPos;
+ QPoint m_selectedBar;
Q3DValueAxis *m_autoAdjustingAxis;
Q3DValueAxis *m_fixedRangeAxis;
Q3DValueAxis *m_temperatureAxis;
@@ -104,9 +117,18 @@ private:
Q3DCategoryAxis *m_monthAxis;
Q3DCategoryAxis *m_genericRowAxis;
Q3DCategoryAxis *m_genericColumnAxis;
- QBarDataProxy *m_temperatureData;
- QBarDataProxy *m_genericData;
+ QBar3DSeries *m_temperatureData;
+ QBar3DSeries *m_temperatureData2;
+ QBar3DSeries *m_genericData;
+ QBar3DSeries *m_dummyData;
+ QBar3DSeries *m_dummyData2;
+ QBar3DSeries *m_dummyData3;
+ QBar3DSeries *m_dummyData4;
+ QBar3DSeries *m_dummyData5;
Q3DValueAxis *m_currentAxis;
+ bool m_negativeValuesOn;
+ bool m_useNullInputHandler;
+ QAbstract3DInputHandler *m_defaultInputHandler;
};
#endif
diff --git a/tests/barstest/main.cpp b/tests/barstest/main.cpp
index 7742cb0e..e18aaed1 100644
--- a/tests/barstest/main.cpp
+++ b/tests/barstest/main.cpp
@@ -29,6 +29,9 @@
#include <QLabel>
#include <QScreen>
#include <QFontDatabase>
+#include <QLinearGradient>
+#include <QPainter>
+#include <QColorDialog>
int main(int argc, char **argv)
{
@@ -124,6 +127,38 @@ int main(int argc, char **argv)
releaseProxiesButton->setText(QStringLiteral("Release all proxies"));
releaseProxiesButton->setEnabled(true);
+ QPushButton *flipViewsButton = new QPushButton(widget);
+ flipViewsButton->setText(QStringLiteral("Flip views"));
+ flipViewsButton->setEnabled(true);
+
+ QPushButton *showFiveSeriesButton = new QPushButton(widget);
+ showFiveSeriesButton->setText(QStringLiteral("Try 5 series"));
+ showFiveSeriesButton->setEnabled(true);
+
+ QPushButton *changeColorStyleButton = new QPushButton(widget);
+ changeColorStyleButton->setText(QStringLiteral("Change color style"));
+ changeColorStyleButton->setEnabled(true);
+
+ QPushButton *ownThemeButton = new QPushButton(widget);
+ ownThemeButton->setText(QStringLiteral("Use own theme"));
+ ownThemeButton->setEnabled(true);
+
+ QColorDialog *colorDialog = new QColorDialog(widget);
+
+ QLinearGradient grBtoY(0, 0, 100, 0);
+ grBtoY.setColorAt(1.0, Qt::black);
+ grBtoY.setColorAt(0.67, Qt::blue);
+ grBtoY.setColorAt(0.33, Qt::red);
+ grBtoY.setColorAt(0.0, Qt::yellow);
+ QPixmap pm(100, 24);
+ QPainter pmp(&pm);
+ pmp.setBrush(QBrush(grBtoY));
+ pmp.setPen(Qt::NoPen);
+ pmp.drawRect(0, 0, 100, 24);
+ QPushButton *gradientBtoYPB = new QPushButton(widget);
+ gradientBtoYPB->setIcon(QIcon(pm));
+ gradientBtoYPB->setIconSize(QSize(100, 24));
+
QCheckBox *backgroundCheckBox = new QCheckBox(widget);
backgroundCheckBox->setText(QStringLiteral("Show background"));
backgroundCheckBox->setChecked(true);
@@ -183,17 +218,33 @@ int main(int argc, char **argv)
sampleSliderZ->setEnabled(false);
QSlider *minSliderX = new QSlider(Qt::Horizontal, widget);
- minSliderX->setTickInterval(1);
+ minSliderX->setTickInterval(10);
+ minSliderX->setTickPosition(QSlider::TicksBelow);
minSliderX->setMinimum(0);
minSliderX->setValue(0);
minSliderX->setMaximum(200);
minSliderX->setEnabled(false);
QSlider *minSliderZ = new QSlider(Qt::Horizontal, widget);
- minSliderZ->setTickInterval(1);
+ minSliderZ->setTickInterval(10);
+ minSliderZ->setTickPosition(QSlider::TicksAbove);
minSliderZ->setMinimum(0);
minSliderZ->setValue(0);
minSliderZ->setMaximum(200);
minSliderZ->setEnabled(false);
+ QSlider *minSliderY = new QSlider(Qt::Horizontal, widget);
+ minSliderY->setTickInterval(10);
+ minSliderY->setTickPosition(QSlider::TicksBelow);
+ minSliderY->setMinimum(-100);
+ minSliderY->setValue(0);
+ minSliderY->setMaximum(100);
+ minSliderY->setEnabled(false);
+ QSlider *maxSliderY = new QSlider(Qt::Horizontal, widget);
+ maxSliderY->setTickInterval(10);
+ maxSliderY->setTickPosition(QSlider::TicksAbove);
+ maxSliderY->setMinimum(-50);
+ maxSliderY->setValue(100);
+ maxSliderY->setMaximum(200);
+ maxSliderY->setEnabled(false);
QSlider *fontSizeSlider = new QSlider(Qt::Horizontal, widget);
fontSizeSlider->setTickInterval(1);
@@ -223,6 +274,7 @@ int main(int argc, char **argv)
vLayout->addWidget(removeRowButton, 0, Qt::AlignTop);
vLayout->addWidget(removeRowsButton, 0, Qt::AlignTop);
vLayout->addWidget(massiveArrayButton, 0, Qt::AlignTop);
+ vLayout->addWidget(showFiveSeriesButton, 0, Qt::AlignTop);
vLayout->addWidget(themeButton, 0, Qt::AlignTop);
vLayout->addWidget(labelButton, 0, Qt::AlignTop);
vLayout->addWidget(styleButton, 0, Qt::AlignTop);
@@ -232,6 +284,10 @@ int main(int argc, char **argv)
vLayout->addWidget(swapAxisButton, 0, Qt::AlignTop);
vLayout->addWidget(releaseAxesButton, 0, Qt::AlignTop);
vLayout->addWidget(releaseProxiesButton, 1, Qt::AlignTop);
+ vLayout->addWidget(flipViewsButton, 0, Qt::AlignTop);
+ vLayout->addWidget(changeColorStyleButton, 0, Qt::AlignTop);
+ vLayout->addWidget(ownThemeButton, 0, Qt::AlignTop);
+ vLayout->addWidget(gradientBtoYPB, 1, Qt::AlignTop);
vLayout2->addWidget(staticCheckBox, 0, Qt::AlignTop);
vLayout2->addWidget(rotationCheckBox, 0, Qt::AlignTop);
@@ -248,6 +304,8 @@ int main(int argc, char **argv)
vLayout2->addWidget(new QLabel(QStringLiteral("Adjust data window minimums")), 0, Qt::AlignTop);
vLayout2->addWidget(minSliderX, 0, Qt::AlignTop);
vLayout2->addWidget(minSliderZ, 0, Qt::AlignTop);
+ vLayout2->addWidget(minSliderY, 0, Qt::AlignTop);
+ vLayout2->addWidget(maxSliderY, 0, Qt::AlignTop);
vLayout2->addWidget(backgroundCheckBox, 0, Qt::AlignTop);
vLayout2->addWidget(gridCheckBox, 0, Qt::AlignTop);
vLayout2->addWidget(new QLabel(QStringLiteral("Adjust shadow quality")), 0, Qt::AlignTop);
@@ -260,7 +318,7 @@ int main(int argc, char **argv)
widget->show();
- GraphModifier *modifier = new GraphModifier(widgetchart);
+ GraphModifier *modifier = new GraphModifier(widgetchart, colorDialog);
QObject::connect(rotationSliderX, &QSlider::valueChanged, modifier, &GraphModifier::rotateX);
QObject::connect(rotationSliderY, &QSlider::valueChanged, modifier, &GraphModifier::rotateY);
@@ -280,16 +338,15 @@ int main(int argc, char **argv)
&GraphModifier::setMinX);
QObject::connect(minSliderZ, &QSlider::valueChanged, modifier,
&GraphModifier::setMinZ);
+ QObject::connect(minSliderY, &QSlider::valueChanged, modifier,
+ &GraphModifier::setMinY);
+ QObject::connect(maxSliderY, &QSlider::valueChanged, modifier,
+ &GraphModifier::setMaxY);
QObject::connect(shadowQuality, SIGNAL(currentIndexChanged(int)), modifier,
SLOT(changeShadowQuality(int)));
QObject::connect(modifier, &GraphModifier::shadowQualityChanged, shadowQuality,
&QComboBox::setCurrentIndex);
- QObject::connect(widgetchart, &Q3DBars::shadowQualityChanged, modifier,
- &GraphModifier::shadowQualityUpdatedByVisual);
- QObject::connect(widgetchart, &Q3DBars::selectedBarPosChanged, modifier,
- &GraphModifier::handleSelectionChange);
-
QObject::connect(fontSizeSlider, &QSlider::valueChanged, modifier,
&GraphModifier::changeFontSize);
@@ -309,6 +366,7 @@ int main(int argc, char **argv)
QObject::connect(removeRowButton, &QPushButton::clicked, modifier, &GraphModifier::removeRow);
QObject::connect(removeRowsButton, &QPushButton::clicked, modifier, &GraphModifier::removeRows);
QObject::connect(massiveArrayButton, &QPushButton::clicked, modifier, &GraphModifier::createMassiveArray);
+ QObject::connect(showFiveSeriesButton, &QPushButton::clicked, modifier, &GraphModifier::showFiveSeries);
QObject::connect(selectionButton, &QPushButton::clicked, modifier,
&GraphModifier::changeSelectionMode);
QObject::connect(setSelectedBarButton, &QPushButton::clicked, modifier,
@@ -320,6 +378,17 @@ int main(int argc, char **argv)
QObject::connect(releaseProxiesButton, &QPushButton::clicked, modifier,
&GraphModifier::releaseProxies);
+ QObject::connect(flipViewsButton, &QPushButton::clicked, modifier,
+ &GraphModifier::flipViews);
+ QObject::connect(changeColorStyleButton, &QPushButton::clicked, modifier,
+ &GraphModifier::changeColorStyle);
+ QObject::connect(ownThemeButton, &QPushButton::clicked, modifier,
+ &GraphModifier::useOwnTheme);
+ QObject::connect(colorDialog, &QColorDialog::currentColorChanged, modifier,
+ &GraphModifier::changeBaseColor);
+ QObject::connect(gradientBtoYPB, &QPushButton::clicked, modifier,
+ &GraphModifier::setGradient);
+
QObject::connect(fontList, &QFontComboBox::currentFontChanged, modifier,
&GraphModifier::changeFont);
@@ -328,6 +397,9 @@ int main(int argc, char **argv)
QObject::connect(gridCheckBox, &QCheckBox::stateChanged, modifier,
&GraphModifier::setGridEnabled);
+ QObject::connect(rotationCheckBox, &QCheckBox::stateChanged, modifier,
+ &GraphModifier::setUseNullInputHandler);
+
QObject::connect(rotationCheckBox, &QCheckBox::stateChanged, rotationSliderX,
&QSlider::setEnabled);
QObject::connect(rotationCheckBox, &QCheckBox::stateChanged, rotationSliderX,
@@ -365,6 +437,10 @@ int main(int argc, char **argv)
&QSlider::setEnabled);
QObject::connect(staticCheckBox, &QCheckBox::stateChanged, minSliderZ,
&QSlider::setEnabled);
+ QObject::connect(staticCheckBox, &QCheckBox::stateChanged, minSliderY,
+ &QSlider::setEnabled);
+ QObject::connect(staticCheckBox, &QCheckBox::stateChanged, maxSliderY,
+ &QSlider::setEnabled);
QObject::connect(staticCheckBox, &QCheckBox::stateChanged, swapAxisButton,
&QSlider::setEnabled);
QObject::connect(staticCheckBox, &QCheckBox::stateChanged, modifier, &GraphModifier::restart);
diff --git a/tests/kinectsurface/surfacedata.cpp b/tests/kinectsurface/surfacedata.cpp
index b11be8d5..fe94519a 100644
--- a/tests/kinectsurface/surfacedata.cpp
+++ b/tests/kinectsurface/surfacedata.cpp
@@ -45,21 +45,21 @@ SurfaceData::SurfaceData(Q3DSurface *surface, Q3DScatter *scatter, Q3DBars *bars
gradient.setColorAt(0.33, Qt::blue);
gradient.setColorAt(0.67, Qt::red);
gradient.setColorAt(1.0, Qt::yellow);
- m_surface->setSelectionMode(QDataVis::SelectionModeNone);
+ m_surface->setSelectionMode(QDataVis::SelectionNone);
m_surface->setGridVisible(false);
m_surface->setGradient(gradient);
m_surface->axisY()->setMax(255);
m_surface->setSurfaceGridEnabled(false);
m_surface->setBackgroundVisible(false);
- m_surface->setSmoothSurfaceEnabled(false);
+ m_surface->setFlatShadingEnabled(true);
m_surface->setActiveDataProxy(new QHeightMapSurfaceDataProxy());
m_surface->setCameraPosition(0.0, 90.0, 105);
// Initialize scatter
m_scatter->setTheme(QDataVis::ThemeStoneMoss);
- m_scatter->setSelectionMode(QDataVis::SelectionModeNone);
+ m_scatter->setSelectionMode(QDataVis::SelectionNone);
m_scatter->setGridVisible(false);
- m_scatter->setObjectType(QDataVis::MeshStyleDots, false);
+ m_scatter->setObjectType(QDataVis::MeshDots, false);
m_scatter->setShadowQuality(QDataVis::ShadowQualitySoftLow);
m_scatter->setCameraPosition(0.0, 85.0, 110);
m_scatter->axisY()->setMin(-128);
@@ -71,9 +71,9 @@ SurfaceData::SurfaceData(Q3DSurface *surface, Q3DScatter *scatter, Q3DBars *bars
// Initialize bars
m_bars->setTheme(QDataVis::ThemeQt);
- m_bars->setSelectionMode(QDataVis::SelectionModeNone);
+ m_bars->setSelectionMode(QDataVis::SelectionNone);
m_bars->setGridVisible(false);
- m_bars->setBarType(QDataVis::MeshStyleBars, true);
+ m_bars->setBarType(QDataVis::MeshBars, true);
#if 1
m_bars->setShadowQuality(QDataVis::ShadowQualityLow);
#else
@@ -98,7 +98,7 @@ SurfaceData::~SurfaceData()
delete m_scatter;
delete m_bars;
delete m_surface;
- } else if (m_mode == MeshStyleBars) {
+ } else if (m_mode == MeshBars) {
delete m_scatter;
delete m_surface;
delete m_bars;
@@ -201,7 +201,7 @@ void SurfaceData::setResolution(int selection)
m_scatter->axisZ()->setMax(m_resolution.height() / 2);
m_scatterDataArray = new QScatterDataArray;
m_scatterDataArray->resize(m_resolution.width() * m_resolution.height());
- } else if (m_mode == MeshStyleBars) {
+ } else if (m_mode == MeshBars) {
m_resize = true;
m_resolution /= 4;
m_barDataArray = new QBarDataArray;
diff --git a/tests/kinectsurface/surfacedata.h b/tests/kinectsurface/surfacedata.h
index 0bf753cd..fcae03b4 100644
--- a/tests/kinectsurface/surfacedata.h
+++ b/tests/kinectsurface/surfacedata.h
@@ -55,7 +55,7 @@ public:
enum VisualizationMode {
Surface = 0,
Scatter,
- MeshStyleBars
+ MeshBars
};
public slots:
diff --git a/tests/minimalbars/minimalbars.pro b/tests/minimalbars/minimalbars.pro
new file mode 100644
index 00000000..b948a31f
--- /dev/null
+++ b/tests/minimalbars/minimalbars.pro
@@ -0,0 +1,6 @@
+QT += core gui datavisualization
+
+TARGET = MinimalBars
+TEMPLATE = app
+
+SOURCES += ../../src/datavisualization/doc/snippets/doc_src_q3dbars_construction.cpp
diff --git a/tests/minimalscatter/minimalscatter.pro b/tests/minimalscatter/minimalscatter.pro
new file mode 100644
index 00000000..6fd9913d
--- /dev/null
+++ b/tests/minimalscatter/minimalscatter.pro
@@ -0,0 +1,6 @@
+QT += core gui datavisualization
+
+TARGET = MinimalScatter
+TEMPLATE = app
+
+SOURCES += ../../src/datavisualization/doc/snippets/doc_src_q3dscatter_construction.cpp
diff --git a/tests/minimalsurface/minimalsurface.pro b/tests/minimalsurface/minimalsurface.pro
new file mode 100644
index 00000000..4ff9b485
--- /dev/null
+++ b/tests/minimalsurface/minimalsurface.pro
@@ -0,0 +1,6 @@
+QT += core gui datavisualization
+
+TARGET = minimalSurface
+TEMPLATE = app
+
+SOURCES += ../../src/datavisualization/doc/snippets/doc_src_q3dsurface_construction.cpp
diff --git a/tests/multigraphs/australia.png b/tests/multigraphs/australia.png
new file mode 100644
index 00000000..a839b6b9
--- /dev/null
+++ b/tests/multigraphs/australia.png
Binary files differ
diff --git a/tests/multigraphs/data.cpp b/tests/multigraphs/data.cpp
new file mode 100644
index 00000000..99354caf
--- /dev/null
+++ b/tests/multigraphs/data.cpp
@@ -0,0 +1,330 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#define NOMINMAX
+
+#include "data.h"
+#include <QtDataVisualization/Q3DValueAxis>
+#include <QtDataVisualization/Q3DCamera>
+#include <QtDataVisualization/QBar3DSeries>
+#include <QtDataVisualization/QScatter3DSeries>
+#include <QtDataVisualization/QSurface3DSeries>
+#include <QtDataVisualization/Q3DTheme>
+#include <QScrollBar>
+#include <QSize>
+#include <QImage>
+
+QT_DATAVISUALIZATION_USE_NAMESPACE
+
+Data::Data(Q3DSurface *surface, Q3DScatter *scatter, Q3DBars *bars,
+ QTextEdit *statusArea, QWidget *widget) :
+ m_surface(surface),
+ m_scatter(scatter),
+ m_bars(bars),
+ m_statusArea(statusArea),
+ m_widget(widget),
+ m_resize(true),
+ m_resolution(QSize(300, 300)),
+ m_resolutionLevel(0),
+ m_mode(Surface),
+ m_started(false)
+{
+ // Initialize surface
+ m_surface->setTheme(new Q3DTheme(Q3DTheme::ThemeIsabelle));
+ QLinearGradient gradient;
+ gradient.setColorAt(0.0, Qt::black);
+ gradient.setColorAt(0.33, Qt::blue);
+ gradient.setColorAt(0.67, Qt::red);
+ gradient.setColorAt(1.0, Qt::yellow);
+ m_surface->setSelectionMode(QDataVis::SelectionNone);
+ m_surface->theme()->setGridEnabled(false);
+ m_surface->theme()->setBackgroundEnabled(false);
+ m_surface->scene()->activeCamera()->setCameraPosition(0.0, 90.0, 150);
+ QSurface3DSeries *series1 = new QSurface3DSeries(new QHeightMapSurfaceDataProxy());
+ series1->setFlatShadingEnabled(true);
+ series1->setDrawMode(QSurface3DSeries::DrawSurface);
+ series1->setColorStyle(Q3DTheme::ColorStyleRangeGradient);
+ series1->setBaseGradient(gradient);
+ m_surface->addSeries(series1);
+
+ // Initialize scatter
+ m_scatter->setTheme(new Q3DTheme(Q3DTheme::ThemeStoneMoss));
+ m_scatter->setSelectionMode(QDataVis::SelectionNone);
+ m_scatter->theme()->setGridEnabled(false);
+ m_scatter->setShadowQuality(QDataVis::ShadowQualitySoftLow);
+ m_scatter->scene()->activeCamera()->setCameraPosition(0.0, 85.0, 150);
+ QScatter3DSeries *series2 = new QScatter3DSeries;
+ series2->setMesh(QAbstract3DSeries::MeshPoint);
+ m_scatter->addSeries(series2);
+
+ // Initialize bars
+ m_bars->setTheme(new Q3DTheme(Q3DTheme::ThemeQt));
+ m_bars->setSelectionMode(QDataVis::SelectionItemAndRow | QDataVis::SelectionSlice);
+ m_bars->theme()->setGridEnabled(false);
+ m_bars->setShadowQuality(QDataVis::ShadowQualityLow);
+ m_bars->setBarSpacing(QSizeF(0.0, 0.0));
+ m_bars->scene()->activeCamera()->setCameraPosition(0.0, 75.0, 150);
+ QBar3DSeries *series3 = new QBar3DSeries;
+ series3->setMesh(QAbstract3DSeries::MeshBar);
+ m_bars->addSeries(series3);
+
+ // Hide scroll bar
+ m_statusArea->verticalScrollBar()->setVisible(false);
+}
+
+Data::~Data()
+{ // HACK: The current context needs to be destroyed last
+ // TODO: Fix properly in datavis code somehow
+ if (m_mode == Surface) {
+ delete m_scatter;
+ delete m_bars;
+ delete m_surface;
+ } else if (m_mode == Bars) {
+ delete m_scatter;
+ delete m_surface;
+ delete m_bars;
+ } else {
+ delete m_bars;
+ delete m_surface;
+ delete m_scatter;
+ }
+ delete m_widget;
+ delete m_scatterDataArray; // only portion of this array is set to graph
+}
+
+void Data::updateData()
+{
+ if (!m_started) {
+ m_statusArea->append(QStringLiteral("<i>We are stopped. The changes will take effect once started.</i>"));
+ return;
+ }
+ QImage depthMap = QImage(":/australia.png");
+ if (m_resize) // Resize for better performance
+ depthMap = depthMap.scaled(m_resolution);
+ if (m_mode != Surface)
+ setData(depthMap);
+ else
+ static_cast<QHeightMapSurfaceDataProxy *>(m_surface->seriesList().at(0)->dataProxy())->setHeightMap(
+ depthMap);
+}
+
+void Data::clearData()
+{
+ m_bars->seriesList().at(0)->dataProxy()->resetArray(0);
+ m_scatter->seriesList().at(0)->dataProxy()->resetArray(0);
+ m_surface->seriesList().at(0)->dataProxy()->resetArray(0);
+}
+
+void Data::setResolution(int selection)
+{
+ m_resolutionLevel = selection;
+ switch (selection) {
+ case 0: {
+ m_resize = true;
+ m_resolution = QSize(300, 300);
+ break;
+ }
+ case 1: {
+ m_resize = true;
+ m_resolution = QSize(600, 600);
+ break;
+ }
+ case 2: {
+ m_resize = true;
+ m_resolution = QSize(800, 800);
+ break;
+ }
+ case 3: {
+ m_resize = false;
+ m_resolution = QSize(1020, 1020); // image size
+ break;
+ }
+ };
+ if (m_mode == Scatter) {
+ m_resize = true;
+ m_resolution /= 3;
+ m_scatterDataArray = new QScatterDataArray;
+ m_scatterDataArray->resize(m_resolution.width() * m_resolution.height());
+ } else if (m_mode == Bars) {
+ m_resize = true;
+ m_resolution /= 6;
+ m_barDataArray = new QBarDataArray;
+ m_barDataArray->reserve(m_resolution.height());
+ for (int i = 0; i < m_resolution.height(); i++) {
+ QBarDataRow *newProxyRow = new QBarDataRow(m_resolution.width());
+ m_barDataArray->append(newProxyRow);
+ }
+ }
+
+ m_statusArea->append(QString(QStringLiteral("<b>Resolution:</b> %1 x %2")).arg(
+ m_resolution.width()).arg(m_resolution.height()));
+
+ updateData();
+}
+
+void Data::scrollDown()
+{
+ QScrollBar *scrollbar = m_statusArea->verticalScrollBar();
+ scrollbar->setValue(scrollbar->maximum());
+}
+
+void Data::useGradientOne()
+{
+ m_surface->setTheme(new Q3DTheme(Q3DTheme::ThemeIsabelle));
+ QLinearGradient gradient;
+ gradient.setColorAt(0.0, Qt::black);
+ gradient.setColorAt(0.33, Qt::blue);
+ gradient.setColorAt(0.67, Qt::red);
+ gradient.setColorAt(1.0, Qt::yellow);
+ m_surface->seriesList().at(0)->setBaseGradient(gradient);
+ m_statusArea->append(QStringLiteral("<b>Colors:</b> Thermal image imitation"));
+}
+
+void Data::useGradientTwo()
+{
+ m_surface->setTheme(new Q3DTheme(Q3DTheme::ThemeQt));
+ QLinearGradient gradient;
+ gradient.setColorAt(0.0, Qt::white);
+ gradient.setColorAt(0.8, Qt::red);
+ gradient.setColorAt(1.0, Qt::green);
+ m_surface->seriesList().at(0)->setBaseGradient(gradient);
+ m_statusArea->append(QStringLiteral("<b>Colors:</b> Highlight foreground"));
+}
+
+void Data::setData(const QImage &image)
+{
+ QImage heightImage = image;
+
+ uchar *bits = heightImage.bits();
+
+ int imageHeight = heightImage.height();
+ int imageWidth = heightImage.width();
+ int bitCount = imageWidth * 4 * (imageHeight - 1);
+ int widthBits = imageWidth * 4;
+
+ if (m_mode == Scatter) {
+ QScatterDataItem *ptrToDataArray = &m_scatterDataArray->first();
+
+ int limitsX = imageWidth / 2;
+ int limitsZ = imageHeight / 2;
+ float height = 0;
+ int count = 0;
+
+ for (int i = -limitsZ; i < limitsZ; i++, bitCount -= widthBits) {
+ for (int j = -limitsX; j < limitsX; j++) {
+ height = float(bits[bitCount + ((j + limitsX) * 4)]) - 128.0;
+ if (height > -128) {
+ ptrToDataArray->setPosition(QVector3D(float(j), height, float(i)));
+ ptrToDataArray++;
+ count++;
+ }
+ }
+ }
+
+ QScatterDataArray *dataArray = new QScatterDataArray(m_scatterDataArray->mid(0, count));
+ m_scatter->seriesList().at(0)->dataProxy()->resetArray(dataArray);
+ } else {
+ QBarDataArray *dataArray = m_barDataArray;
+ for (int i = 0; i < imageHeight; i++, bitCount -= widthBits) {
+ QBarDataRow &newRow = *dataArray->at(i);
+ for (int j = 0; j < imageWidth; j++)
+ newRow[j] = float(bits[bitCount + (j * 4)]);
+ }
+
+ m_bars->seriesList().at(0)->dataProxy()->resetArray(dataArray);
+ }
+}
+
+void Data::changeMode(int mode)
+{
+ m_mode = VisualizationMode(mode);
+ switch (m_mode) {
+ case Surface: {
+ m_statusArea->append(QStringLiteral("<b>Visualization Type:</b> Surface"));
+ break;
+ }
+ case Scatter: {
+ m_statusArea->append(QStringLiteral("<b>Visualization Type:</b> Scatter"));
+ break;
+ }
+ default: {
+ m_statusArea->append(QStringLiteral("<b>Visualization Type:</b> Bars"));
+ break;
+ }
+ }
+ // Reset resolution after mode change
+ setResolution(m_resolutionLevel);
+}
+
+void Data::start()
+{
+ m_started = true;
+ updateData();
+ m_statusArea->append(QStringLiteral("<b>Started<\b>"));
+}
+
+void Data::stop()
+{
+ m_started = false;
+ clearData();
+ m_statusArea->append(QStringLiteral("<b>Stopped<\b>"));
+}
+
+ContainerChanger::ContainerChanger(QWidget *surface, QWidget *scatter, QWidget *bars,
+ QWidget *buttonOne, QWidget *buttonTwo)
+ : m_surface(surface),
+ m_scatter(scatter),
+ m_bars(bars),
+ m_button1(buttonOne),
+ m_button2(buttonTwo)
+{
+}
+
+ContainerChanger::~ContainerChanger()
+{
+}
+
+void ContainerChanger::changeContainer(int container)
+{
+ switch (container) {
+ case 0: {
+ m_scatter->setVisible(false);
+ m_bars->setVisible(false);
+ m_surface->setVisible(true);
+ m_button1->setEnabled(true);
+ m_button2->setEnabled(true);
+ break;
+ }
+ case 1: {
+ m_surface->setVisible(false);
+ m_bars->setVisible(false);
+ m_scatter->setVisible(true);
+ m_button1->setEnabled(false);
+ m_button2->setEnabled(false);
+ break;
+ }
+ case 2: {
+ m_surface->setVisible(false);
+ m_scatter->setVisible(false);
+ m_bars->setVisible(true);
+ m_button1->setEnabled(false);
+ m_button2->setEnabled(false);
+ break;
+ }
+ }
+}
diff --git a/tests/multigraphs/data.h b/tests/multigraphs/data.h
new file mode 100644
index 00000000..91e68334
--- /dev/null
+++ b/tests/multigraphs/data.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#ifndef DATA_H
+#define DATA_H
+
+#include <QtDataVisualization/Q3DScatter>
+#include <QtDataVisualization/Q3DBars>
+#include <QtDataVisualization/Q3DSurface>
+#include <QtDataVisualization/QScatterDataProxy>
+#include <QtDataVisualization/QBarDataProxy>
+#include <QtDataVisualization/QHeightMapSurfaceDataProxy>
+#include <QTextEdit>
+
+using namespace QtDataVisualization;
+
+class Data : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit Data(Q3DSurface *surface, Q3DScatter *scatter, Q3DBars *bars,
+ QTextEdit *statusLabel, QWidget *widget);
+ ~Data();
+
+ void start();
+ void stop();
+
+ void updateData();
+ void clearData();
+
+ void scrollDown();
+ void setData(const QImage &image);
+ void useGradientOne();
+ void useGradientTwo();
+
+public:
+ enum VisualizationMode {
+ Surface = 0,
+ Scatter,
+ Bars
+ };
+
+public slots:
+ void setResolution(int selection);
+ void changeMode(int mode);
+
+private:
+ Q3DSurface *m_surface;
+ Q3DScatter *m_scatter;
+ Q3DBars *m_bars;
+ QTextEdit *m_statusArea;
+ QWidget *m_widget;
+ bool m_resize;
+ QSize m_resolution;
+ int m_resolutionLevel;
+ VisualizationMode m_mode;
+ QScatterDataArray *m_scatterDataArray;
+ QBarDataArray *m_barDataArray;
+ bool m_started;
+};
+
+class ContainerChanger : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit ContainerChanger(QWidget *surface, QWidget *scatter, QWidget *bars,
+ QWidget *buttonOne, QWidget *buttonTwo);
+ ~ContainerChanger();
+
+public slots:
+ void changeContainer(int container);
+
+private:
+ QWidget *m_surface;
+ QWidget *m_scatter;
+ QWidget *m_bars;
+ QWidget *m_button1;
+ QWidget *m_button2;
+};
+
+#endif
diff --git a/tests/multigraphs/main.cpp b/tests/multigraphs/main.cpp
new file mode 100644
index 00000000..a959641d
--- /dev/null
+++ b/tests/multigraphs/main.cpp
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#include "data.h"
+
+#include <QApplication>
+#include <QWidget>
+#include <QHBoxLayout>
+#include <QVBoxLayout>
+#include <QPushButton>
+#include <QLabel>
+#include <QComboBox>
+#include <QSlider>
+#include <QTextEdit>
+#include <QScreen>
+#include <QPainter>
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+
+ QWidget *widget = new QWidget();
+ QHBoxLayout *hLayout = new QHBoxLayout(widget);
+ QVBoxLayout *vLayout = new QVBoxLayout();
+
+ Q3DSurface *surface = new Q3DSurface();
+ Q3DScatter *scatter = new Q3DScatter();
+ Q3DBars *bars = new Q3DBars();
+
+ QSize screenSize = surface->screen()->size();
+
+ QWidget *containerSurface = QWidget::createWindowContainer(surface);
+ containerSurface->setMinimumSize(QSize(screenSize.height() / 1.2, screenSize.height() / 1.2));
+ containerSurface->setMaximumSize(screenSize);
+ containerSurface->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ containerSurface->setFocusPolicy(Qt::StrongFocus);
+
+ QWidget *containerScatter = QWidget::createWindowContainer(scatter);
+ containerScatter->setMinimumSize(QSize(screenSize.height() / 1.2, screenSize.height() / 1.2));
+ containerScatter->setMaximumSize(screenSize);
+ containerScatter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ containerScatter->setFocusPolicy(Qt::StrongFocus);
+ containerScatter->setVisible(false);
+
+ QWidget *containerBars = QWidget::createWindowContainer(bars);
+ containerBars->setMinimumSize(QSize(screenSize.height() / 1.2, screenSize.height() / 1.2));
+ containerBars->setMaximumSize(screenSize);
+ containerBars->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ containerBars->setFocusPolicy(Qt::StrongFocus);
+ containerBars->setVisible(false);
+
+ widget->setWindowTitle(QStringLiteral("Test switching graphs on the fly"));
+
+ hLayout->addWidget(containerSurface, 1);
+ hLayout->addWidget(containerScatter, 1);
+ hLayout->addWidget(containerBars, 1);
+ hLayout->addLayout(vLayout);
+
+ QPushButton *startButton = new QPushButton(widget);
+ startButton->setText(QStringLiteral("Start"));
+
+ QPushButton *stopButton = new QPushButton(widget);
+ stopButton->setText(QStringLiteral("Stop"));
+
+ QComboBox *resolutionBox = new QComboBox(widget);
+ resolutionBox->addItem(QStringLiteral("Low"));
+ resolutionBox->addItem(QStringLiteral("Medium"));
+ resolutionBox->addItem(QStringLiteral("High"));
+ resolutionBox->addItem(QStringLiteral("Max")); // Comment this out if demo machine is low-perf
+ resolutionBox->setCurrentIndex(0);
+
+ QComboBox *modeBox = new QComboBox(widget);
+ modeBox->addItem(QStringLiteral("Surface Plot"));
+ modeBox->addItem(QStringLiteral("Scatter Chart"));
+ modeBox->addItem(QStringLiteral("Bar Chart"));
+ modeBox->setCurrentIndex(0);
+
+ QLinearGradient gradientOne(0, 0, 200, 1);
+ gradientOne.setColorAt(0.0, Qt::black);
+ gradientOne.setColorAt(0.33, Qt::blue);
+ gradientOne.setColorAt(0.67, Qt::red);
+ gradientOne.setColorAt(1.0, Qt::yellow);
+
+ QPixmap pm(200, 24);
+ QPainter pmp(&pm);
+ pmp.setBrush(QBrush(gradientOne));
+ pmp.setPen(Qt::NoPen);
+ pmp.drawRect(0, 0, 200, 24);
+
+ QPushButton *gradientOneButton = new QPushButton(widget);
+ gradientOneButton->setIcon(QIcon(pm));
+ gradientOneButton->setIconSize(QSize(200, 24));
+ gradientOneButton->setToolTip(QStringLiteral("Colors: Thermal Imitation"));
+
+ QLinearGradient gradientTwo(0, 0, 200, 1);
+ gradientTwo.setColorAt(0.0, Qt::white);
+ gradientTwo.setColorAt(0.8, Qt::red);
+ gradientTwo.setColorAt(1.0, Qt::green);
+
+ pmp.setBrush(QBrush(gradientTwo));
+ pmp.setPen(Qt::NoPen);
+ pmp.drawRect(0, 0, 200, 24);
+
+ QPushButton *gradientTwoButton = new QPushButton(widget);
+ gradientTwoButton->setIcon(QIcon(pm));
+ gradientTwoButton->setIconSize(QSize(200, 24));
+ gradientTwoButton->setToolTip(QStringLiteral("Colors: Highlight Foreground"));
+
+ QTextEdit *status = new QTextEdit(QStringLiteral("<b>Ready</b><br>"), widget);
+ status->setReadOnly(true);
+
+ vLayout->addWidget(startButton);
+ vLayout->addWidget(stopButton);
+ vLayout->addWidget(new QLabel(QStringLiteral("Change resolution")));
+ vLayout->addWidget(resolutionBox);
+ vLayout->addWidget(new QLabel(QStringLiteral("Change visualization type")));
+ vLayout->addWidget(modeBox);
+ vLayout->addWidget(new QLabel(QStringLiteral("Change color scheme")));
+ vLayout->addWidget(gradientOneButton);
+ vLayout->addWidget(gradientTwoButton);
+ vLayout->addWidget(status, 1, Qt::AlignBottom);
+
+ widget->show();
+
+ Data datagen(surface, scatter, bars, status, widget);
+ ContainerChanger changer(containerSurface, containerScatter, containerBars,
+ gradientOneButton, gradientTwoButton);
+
+ QObject::connect(startButton, &QPushButton::clicked, &datagen, &Data::start);
+ QObject::connect(stopButton, &QPushButton::clicked, &datagen, &Data::stop);
+ QObject::connect(resolutionBox, SIGNAL(activated(int)), &datagen, SLOT(setResolution(int)));
+ QObject::connect(modeBox, SIGNAL(activated(int)), &changer, SLOT(changeContainer(int)));
+ QObject::connect(modeBox, SIGNAL(activated(int)), &datagen, SLOT(changeMode(int)));
+ QObject::connect(status, &QTextEdit::textChanged, &datagen, &Data::scrollDown);
+ QObject::connect(gradientOneButton, &QPushButton::clicked, &datagen,
+ &Data::useGradientOne);
+ QObject::connect(gradientTwoButton, &QPushButton::clicked, &datagen,
+ &Data::useGradientTwo);
+
+ return app.exec();
+}
diff --git a/tests/multigraphs/multigraphs.pro b/tests/multigraphs/multigraphs.pro
new file mode 100644
index 00000000..914a816a
--- /dev/null
+++ b/tests/multigraphs/multigraphs.pro
@@ -0,0 +1,14 @@
+!include( ../tests.pri ) {
+ error( "Couldn't find the tests.pri file!" )
+}
+
+SOURCES += main.cpp \
+ data.cpp
+HEADERS += data.h
+
+QT += widgets
+
+INSTALLS += target
+
+RESOURCES += \
+ multigraphs.qrc
diff --git a/tests/multigraphs/multigraphs.qrc b/tests/multigraphs/multigraphs.qrc
new file mode 100644
index 00000000..bd924255
--- /dev/null
+++ b/tests/multigraphs/multigraphs.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>australia.png</file>
+ </qresource>
+</RCC>
diff --git a/tests/qmlcamera/main.cpp b/tests/qmlcamera/main.cpp
index 90d81eab..f35e9fc8 100644
--- a/tests/qmlcamera/main.cpp
+++ b/tests/qmlcamera/main.cpp
@@ -24,6 +24,17 @@ int main(int argc, char *argv[])
QGuiApplication app(argc, argv);
QtQuick2ApplicationViewer viewer;
+
+#if !defined(QT_OPENGL_ES_2)
+ // Enable antialiasing
+ QSurfaceFormat surfaceFormat;
+ surfaceFormat.setDepthBufferSize(24);
+ surfaceFormat.setSamples(8);
+ surfaceFormat.setRenderableType(QSurfaceFormat::OpenGL);
+ surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
+ viewer.setFormat(surfaceFormat);
+#endif
+
#ifdef Q_OS_ANDROID
viewer.addImportPath(QString::fromLatin1("assets:/qml"));
viewer.engine()->addPluginPath(QString::fromLatin1("%1/../%2").arg(QDir::homePath(),
diff --git a/tests/qmlcamera/qml/qmlcamera/Axes.qml b/tests/qmlcamera/qml/qmlcamera/Axes.qml
index 5da1e680..0506d9ee 100644
--- a/tests/qmlcamera/qml/qmlcamera/Axes.qml
+++ b/tests/qmlcamera/qml/qmlcamera/Axes.qml
@@ -30,7 +30,7 @@ Item {
// Custom labels for columns, since the data contains abbreviated month names.
CategoryAxis3D {
id: columnAxis
- categoryLabels: ["January", "February", "March", "April", "May", "June",
+ labels: ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"]
}
ValueAxis3D {
diff --git a/tests/qmlcamera/qml/qmlcamera/Data.qml b/tests/qmlcamera/qml/qmlcamera/Data.qml
index 8b7057d5..f7b71c7a 100644
--- a/tests/qmlcamera/qml/qmlcamera/Data.qml
+++ b/tests/qmlcamera/qml/qmlcamera/Data.qml
@@ -20,21 +20,22 @@ import QtQuick 2.1
import QtDataVisualization 1.0
Item {
- property alias mapping: valueMapping
property alias model: dataModel
property alias proxy: modelProxy
+ property alias series: barSeries
- BarDataMapping {
- id: valueMapping
+ ItemModelBarDataProxy {
+ id: modelProxy
+ itemModel: dataModel
rowRole: "year"
columnRole: "month"
valueRole: "expenses"
}
- ItemModelBarDataProxy {
- id: modelProxy
- activeMapping: valueMapping
- itemModel: dataModel
+ Bar3DSeries {
+ id: barSeries
+ dataProxy: modelProxy
+ itemLabelFormat: "@valueTitle for @colLabel, @rowLabel: @valueLabel"
}
ListModel {
diff --git a/tests/qmlcamera/qml/qmlcamera/main.qml b/tests/qmlcamera/qml/qmlcamera/main.qml
index e48861a8..c1266b41 100644
--- a/tests/qmlcamera/qml/qmlcamera/main.qml
+++ b/tests/qmlcamera/qml/qmlcamera/main.qml
@@ -46,24 +46,19 @@ Item {
width: dataView.width
height: dataView.height
shadowQuality: Bars3D.ShadowQualityMedium
- selectionMode: Bars3D.SelectionModeItem
- font.pointSize: 35
- theme: Bars3D.ThemeRetro
- labelStyle: Bars3D.LabelStyleFromTheme
- dataProxy: chartData.proxy
+ selectionMode: Bars3D.SelectionItem
+ theme: Theme3D {
+ type: Theme3D.ThemeDigia
+ font.pointSize: 35
+ labelBackgroundEnabled: true
+ }
+ seriesList: [chartData.series]
barThickness: 0.5
barSpacing: Qt.size(0.5, 0.5)
barSpacingRelative: false
columnAxis: chartAxes.column
valueAxis: chartAxes.expenses
- itemLabelFormat: "@valueTitle for @colLabel, @rowLabel: @valueLabel"
-
- onSelectedBarPosChanged: {
- // Set camControlArea current row to selected bar
- var rowRole = chartData.proxy.rowLabels[position.x];
- var colRole = chartData.proxy.columnLabels[position.y];
- }
// Bind UI controls to the camera
scene.activeCamera.wrapXRotation: false
@@ -72,6 +67,30 @@ Item {
scene.activeCamera.zoomLevel: zoomSlider.value
inputHandler: null
}
+
+ MouseArea {
+ id: inputArea
+ anchors.fill: parent
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ property bool selectionOn: false
+
+ onPressed: {
+ if (mouse.button == Qt.LeftButton)
+ selectionOn = true;
+ testChart.scene.selectionQueryPosition = Qt.point(mouse.x, mouse.y);
+ }
+
+ onReleased: {
+ if (mouse.button == Qt.LeftButton)
+ selectionOn = false;
+ }
+
+ onPositionChanged: {
+ if (selectionOn) {
+ testChart.scene.selectionQueryPosition = Qt.point(mouse.x, mouse.y);
+ }
+ }
+ }
}
ControlSurface {
@@ -101,12 +120,12 @@ Item {
width: camControlArea.width
text: "Show Income"
onClicked: {
- if (chartData.mapping.valueRole === "expenses") {
- chartData.mapping.valueRole = "income"
+ if (chartData.proxy.valueRole === "expenses") {
+ chartData.proxy.valueRole = "income"
text = "Show Expenses"
testChart.valueAxis = chartAxes.income
} else {
- chartData.mapping.valueRole = "expenses"
+ chartData.proxy.valueRole = "expenses"
text = "Show Income"
testChart.valueAxis = chartAxes.expenses
}
@@ -119,11 +138,11 @@ Item {
width: camControlArea.width
text: "Hide Shadows"
onClicked: {
- if (testChart.shadowQuality == Bars3D.ShadowQualityNone) {
- testChart.shadowQuality = Bars3D.ShadowQualityMedium;
+ if (testChart.shadowQuality == AbstractGraph3D.ShadowQualityNone) {
+ testChart.shadowQuality = AbstractGraph3D.ShadowQualityMedium;
text = "Hide Shadows"
} else {
- testChart.shadowQuality = Bars3D.ShadowQualityNone;
+ testChart.shadowQuality = AbstractGraph3D.ShadowQualityNone;
text = "Show Shadows"
}
}
@@ -137,13 +156,13 @@ Item {
onClicked: {
if (testChart.rowAxis.max !== 6) {
text = "Show 2010 - 2012"
- chartData.mapping.autoRowCategories = true
+ chartData.proxy.autoRowCategories = true
} else {
text = "Show all years"
// Explicitly defining row categories, since we do not want to show data for
// all years in the model, just for the selected ones.
- chartData.mapping.autoRowCategories = false
- chartData.mapping.rowCategories = ["2010", "2011", "2012"]
+ chartData.proxy.autoRowCategories = false
+ chartData.proxy.rowCategories = ["2010", "2011", "2012"]
}
}
}
diff --git a/tests/qmldynamicdata/main.cpp b/tests/qmldynamicdata/main.cpp
new file mode 100644
index 00000000..aedc026e
--- /dev/null
+++ b/tests/qmldynamicdata/main.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#include <QtGui/QGuiApplication>
+#include "qtquick2applicationviewer.h"
+#ifdef Q_OS_ANDROID
+#include <QDir>
+#include <QQmlEngine>
+#endif
+#include <QDebug>
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ QtQuick2ApplicationViewer viewer;
+
+#if !defined(QT_OPENGL_ES_2)
+ // Enable antialiasing
+ QSurfaceFormat surfaceFormat;
+ surfaceFormat.setDepthBufferSize(24);
+ surfaceFormat.setSamples(8);
+ surfaceFormat.setRenderableType(QSurfaceFormat::OpenGL);
+ surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
+ viewer.setFormat(surfaceFormat);
+#endif
+
+#ifdef Q_OS_ANDROID
+ viewer.addImportPath(QString::fromLatin1("assets:/qml"));
+ viewer.engine()->addPluginPath(QString::fromLatin1("%1/../%2").arg(QDir::homePath(),
+ QString::fromLatin1("lib")));
+#endif
+ viewer.setTitle(QStringLiteral("QML Dynamic Data Test"));
+
+ viewer.setSource(QUrl("qrc:/qml/main.qml"));
+ viewer.setResizeMode(QQuickView::SizeRootObjectToView);
+ viewer.show();
+
+ return app.exec();
+}
diff --git a/tests/qmldynamicdata/qml/qmldynamicdata/main.qml b/tests/qmldynamicdata/qml/qmldynamicdata/main.qml
new file mode 100644
index 00000000..4ed3b8ae
--- /dev/null
+++ b/tests/qmldynamicdata/qml/qmldynamicdata/main.qml
@@ -0,0 +1,222 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import QtDataVisualization 1.0
+import "."
+
+Item {
+ id: mainView
+ width: 1280
+ height: 720
+ visible: true
+
+ ListModel {
+ id: graphModel
+ ListElement{ xPos: 0.0; yPos: 0.0; zPos: 0.0 }
+ ListElement{ xPos: 1.0; yPos: 1.0; zPos: 1.0 }
+ }
+
+ Timer {
+ id: dataTimer
+ interval: 20
+ running: true
+ repeat: true
+ property bool isIncreasing: true
+
+ onTriggered: {
+ if (isIncreasing) {
+ graphModel.append({"xPos": Math.random(), "yPos": Math.random(), "zPos": Math.random()});
+ if (graphModel.count == 500) {
+ scatterGraph.theme.type = Theme3D.ThemeIsabelle;
+ isIncreasing = false;
+ }
+ } else {
+ // TODO: Once QTRD-2645 is fixed, change this to remove from
+ // random index to add coverage.
+ graphModel.remove(2);
+ if (graphModel.count == 2) {
+ scatterGraph.theme.type = Theme3D.ThemeDigia;
+ isIncreasing = true;
+ }
+ }
+ }
+ }
+
+ ThemeColor {
+ id: dynamicColor
+ ColorAnimation on color {
+ from: "red"
+ to: "yellow"
+ duration: 5000
+ loops: Animation.Infinite
+ }
+ }
+
+ Item {
+ id: dataView
+ anchors.bottom: parent.bottom
+ width: parent.width
+ height: parent.height - shadowToggle.height
+
+ Scatter3D {
+ id: scatterGraph
+ width: dataView.width
+ height: dataView.height
+ theme: Theme3D {
+ type: Theme3D.ThemeQt
+ baseColors: [dynamicColor]
+ }
+ shadowQuality: AbstractGraph3D.ShadowQualitySoftMedium
+ scene.activeCamera.yRotation: 30.0
+ inputHandler: null
+
+ Scatter3DSeries {
+ id: scatterSeries
+ itemLabelFormat: "X:@xLabel Y:@yLabel Z:@zLabel"
+ mesh: Abstract3DSeries.MeshCube
+
+ ItemModelScatterDataProxy {
+ itemModel: graphModel
+ xPosRole: "xPos"
+ yPosRole: "yPos"
+ zPosRole: "zPos"
+ }
+ }
+ }
+
+ MouseArea {
+ id: inputArea
+ anchors.fill: parent
+ hoverEnabled: true
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ property int mouseX: -1
+ property int mouseY: -1
+
+ onPositionChanged: {
+ mouseX = mouse.x;
+ mouseY = mouse.y;
+ }
+
+ onWheel: {
+ // Adjust zoom level based on what zoom range we're in.
+ var zoomLevel = scatterGraph.scene.activeCamera.zoomLevel;
+ if (zoomLevel > 100)
+ zoomLevel += wheel.angleDelta.y / 12.0;
+ else if (zoomLevel > 50)
+ zoomLevel += wheel.angleDelta.y / 60.0;
+ else
+ zoomLevel += wheel.angleDelta.y / 120.0;
+ if (zoomLevel > 500)
+ zoomLevel = 500;
+ else if (zoomLevel < 10)
+ zoomLevel = 10;
+
+ scatterGraph.scene.activeCamera.zoomLevel = zoomLevel;
+ }
+ }
+
+ Timer {
+ id: reselectTimer
+ interval: 10
+ running: true
+ repeat: true
+ onTriggered: {
+ scatterGraph.scene.selectionQueryPosition = Qt.point(inputArea.mouseX, inputArea.mouseY);
+ }
+ }
+ }
+
+ NumberAnimation {
+ id: cameraAnimationX
+ loops: Animation.Infinite
+ running: true
+ target: scatterGraph.scene.activeCamera
+ property:"xRotation"
+ from: 0.0
+ to: 360.0
+ duration: 20000
+ }
+
+
+ SequentialAnimation {
+ id: cameraAnimationY
+ loops: Animation.Infinite
+ running: true
+
+ NumberAnimation {
+ target: scatterGraph.scene.activeCamera
+ property:"yRotation"
+ from: 5.0
+ to: 45.0
+ duration: 9000
+ easing.type: Easing.InOutSine
+ }
+
+ NumberAnimation {
+ target: scatterGraph.scene.activeCamera
+ property:"yRotation"
+ from: 45.0
+ to: 5.0
+ duration: 9000
+ easing.type: Easing.InOutSine
+ }
+ }
+
+ NewButton {
+ id: shadowToggle
+ width: parent.width / 3 // We're adding 3 buttons and want to divide them equally
+ text: "Hide Shadows"
+ anchors.left: parent.left
+
+ onClicked: {
+ if (scatterGraph.shadowQuality === AbstractGraph3D.ShadowQualityNone) {
+ scatterGraph.shadowQuality = AbstractGraph3D.ShadowQualitySoftMedium;
+ text = "Hide Shadows";
+ } else {
+ scatterGraph.shadowQuality = AbstractGraph3D.ShadowQualityNone;
+ text = "Show Shadows";
+ }
+ }
+ }
+
+ NewButton {
+ id: cameraToggle
+ width: parent.width / 3
+ text: "Pause Camera"
+ anchors.left: shadowToggle.right
+
+ onClicked: {
+ cameraAnimationX.paused = !cameraAnimationX.paused;
+ cameraAnimationY.paused = cameraAnimationX.paused;
+ if (cameraAnimationX.paused) {
+ text = "Animate Camera";
+ } else {
+ text = "Pause Camera";
+ }
+ }
+ }
+
+ NewButton {
+ id: exitButton
+ width: parent.width / 3
+ text: "Quit"
+ anchors.left: cameraToggle.right
+ onClicked: Qt.quit(0);
+ }
+}
diff --git a/tests/qmldynamicdata/qml/qmldynamicdata/newbutton.qml b/tests/qmldynamicdata/qml/qmldynamicdata/newbutton.qml
new file mode 100644
index 00000000..895db183
--- /dev/null
+++ b/tests/qmldynamicdata/qml/qmldynamicdata/newbutton.qml
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import QtQuick.Controls 1.0
+
+Item {
+ id: newbutton
+
+ property alias text: buttonText.text
+
+ signal clicked
+
+ height: 80
+
+ Button {
+ width: parent.width
+ height: parent.height
+ Text {
+ id: buttonText
+ wrapMode: Text.WordWrap
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ anchors.fill: parent
+ }
+ onClicked: newbutton.clicked()
+ }
+}
diff --git a/tests/qmldynamicdata/qmldynamicdata.pro b/tests/qmldynamicdata/qmldynamicdata.pro
new file mode 100644
index 00000000..da987ff0
--- /dev/null
+++ b/tests/qmldynamicdata/qmldynamicdata.pro
@@ -0,0 +1,26 @@
+!include( ../tests.pri ) {
+ error( "Couldn't find the examples.pri file!" )
+}
+
+QT += widgets
+
+# Add more folders to ship with the application, here
+folder_01.source = qml/qmldynamicdata
+folder_01.target = qml
+DEPLOYMENTFOLDERS = folder_01
+
+# Additional import path used to resolve QML modules in Creator's code model
+QML_IMPORT_PATH =
+
+# The .cpp file which was generated for your project. Feel free to hack it.
+SOURCES += main.cpp
+
+# Please do not modify the following two lines. Required for deployment.
+include(qtquick2applicationviewer/qtquick2applicationviewer.pri)
+qtcAddDeployment()
+
+RESOURCES += \
+ qmldynamicdata.qrc
+
+OTHER_FILES += doc/src/* \
+ doc/images/*
diff --git a/tests/qmldynamicdata/qmldynamicdata.qrc b/tests/qmldynamicdata/qmldynamicdata.qrc
new file mode 100644
index 00000000..3a13d7b4
--- /dev/null
+++ b/tests/qmldynamicdata/qmldynamicdata.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/qml">
+ <file alias="main.qml">qml/qmldynamicdata/main.qml</file>
+ <file alias="NewButton.qml">qml/qmldynamicdata/newbutton.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/qmldynamicdata/qtquick2applicationviewer/qtquick2applicationviewer.cpp b/tests/qmldynamicdata/qtquick2applicationviewer/qtquick2applicationviewer.cpp
new file mode 100644
index 00000000..10709d7a
--- /dev/null
+++ b/tests/qmldynamicdata/qtquick2applicationviewer/qtquick2applicationviewer.cpp
@@ -0,0 +1,81 @@
+// checksum 0x4f6f version 0x90005
+/*
+ This file was generated by the Qt Quick 2 Application wizard of Qt Creator.
+ QtQuick2ApplicationViewer is a convenience class containing mobile device specific
+ code such as screen orientation handling. Also QML paths and debugging are
+ handled here.
+ It is recommended not to modify this file, since newer versions of Qt Creator
+ may offer an updated version of it.
+*/
+
+#include "qtquick2applicationviewer.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDir>
+#include <QtQml/QQmlEngine>
+
+class QtQuick2ApplicationViewerPrivate
+{
+ QString mainQmlFile;
+ friend class QtQuick2ApplicationViewer;
+ static QString adjustPath(const QString &path);
+};
+
+QString QtQuick2ApplicationViewerPrivate::adjustPath(const QString &path)
+{
+#if defined(Q_OS_MAC)
+ if (!QDir::isAbsolutePath(path))
+ return QString::fromLatin1("%1/../Resources/%2")
+ .arg(QCoreApplication::applicationDirPath(), path);
+#elif defined(Q_OS_BLACKBERRY)
+ if (!QDir::isAbsolutePath(path))
+ return QString::fromLatin1("app/native/%1").arg(path);
+#elif !defined(Q_OS_ANDROID)
+ QString pathInInstallDir =
+ QString::fromLatin1("%1/../%2").arg(QCoreApplication::applicationDirPath(), path);
+ if (QFileInfo(pathInInstallDir).exists())
+ return pathInInstallDir;
+ pathInInstallDir =
+ QString::fromLatin1("%1/%2").arg(QCoreApplication::applicationDirPath(), path);
+ if (QFileInfo(pathInInstallDir).exists())
+ return pathInInstallDir;
+#endif
+ return path;
+}
+
+QtQuick2ApplicationViewer::QtQuick2ApplicationViewer(QWindow *parent)
+ : QQuickView(parent)
+ , d(new QtQuick2ApplicationViewerPrivate())
+{
+ connect(engine(), SIGNAL(quit()), SLOT(close()));
+ setResizeMode(QQuickView::SizeRootObjectToView);
+}
+
+QtQuick2ApplicationViewer::~QtQuick2ApplicationViewer()
+{
+ delete d;
+}
+
+void QtQuick2ApplicationViewer::setMainQmlFile(const QString &file)
+{
+ d->mainQmlFile = QtQuick2ApplicationViewerPrivate::adjustPath(file);
+#ifdef Q_OS_ANDROID
+ setSource(QUrl(QLatin1String("assets:/")+d->mainQmlFile));
+#else
+ setSource(QUrl::fromLocalFile(d->mainQmlFile));
+#endif
+}
+
+void QtQuick2ApplicationViewer::addImportPath(const QString &path)
+{
+ engine()->addImportPath(QtQuick2ApplicationViewerPrivate::adjustPath(path));
+}
+
+void QtQuick2ApplicationViewer::showExpanded()
+{
+#if defined(Q_WS_SIMULATOR) || defined(Q_OS_QNX)
+ showFullScreen();
+#else
+ show();
+#endif
+}
diff --git a/tests/qmldynamicdata/qtquick2applicationviewer/qtquick2applicationviewer.h b/tests/qmldynamicdata/qtquick2applicationviewer/qtquick2applicationviewer.h
new file mode 100644
index 00000000..cf66f140
--- /dev/null
+++ b/tests/qmldynamicdata/qtquick2applicationviewer/qtquick2applicationviewer.h
@@ -0,0 +1,33 @@
+// checksum 0xfde6 version 0x90005
+/*
+ This file was generated by the Qt Quick 2 Application wizard of Qt Creator.
+ QtQuick2ApplicationViewer is a convenience class containing mobile device specific
+ code such as screen orientation handling. Also QML paths and debugging are
+ handled here.
+ It is recommended not to modify this file, since newer versions of Qt Creator
+ may offer an updated version of it.
+*/
+
+#ifndef QTQUICK2APPLICATIONVIEWER_H
+#define QTQUICK2APPLICATIONVIEWER_H
+
+#include <QtQuick/QQuickView>
+
+class QtQuick2ApplicationViewer : public QQuickView
+{
+ Q_OBJECT
+
+public:
+ explicit QtQuick2ApplicationViewer(QWindow *parent = 0);
+ virtual ~QtQuick2ApplicationViewer();
+
+ void setMainQmlFile(const QString &file);
+ void addImportPath(const QString &path);
+
+ void showExpanded();
+
+private:
+ class QtQuick2ApplicationViewerPrivate *d;
+};
+
+#endif // QTQUICK2APPLICATIONVIEWER_H
diff --git a/tests/qmldynamicdata/qtquick2applicationviewer/qtquick2applicationviewer.pri b/tests/qmldynamicdata/qtquick2applicationviewer/qtquick2applicationviewer.pri
new file mode 100644
index 00000000..e5f7990f
--- /dev/null
+++ b/tests/qmldynamicdata/qtquick2applicationviewer/qtquick2applicationviewer.pri
@@ -0,0 +1,180 @@
+# checksum 0x7b0d version 0x90005
+# This file was generated by the Qt Quick 2 Application wizard of Qt Creator.
+# The code below adds the QtQuick2ApplicationViewer to the project and handles
+# the activation of QML debugging.
+# It is recommended not to modify this file, since newer versions of Qt Creator
+# may offer an updated version of it.
+
+QT += qml quick
+
+SOURCES += $$PWD/qtquick2applicationviewer.cpp
+HEADERS += $$PWD/qtquick2applicationviewer.h
+INCLUDEPATH += $$PWD
+# This file was generated by an application wizard of Qt Creator.
+# The code below handles deployment to Android and Maemo, aswell as copying
+# of the application data to shadow build directories on desktop.
+# It is recommended not to modify this file, since newer versions of Qt Creator
+# may offer an updated version of it.
+
+defineTest(qtcAddDeployment) {
+for(deploymentfolder, DEPLOYMENTFOLDERS) {
+ item = item$${deploymentfolder}
+ greaterThan(QT_MAJOR_VERSION, 4) {
+ itemsources = $${item}.files
+ } else {
+ itemsources = $${item}.sources
+ }
+ $$itemsources = $$eval($${deploymentfolder}.source)
+ itempath = $${item}.path
+ $$itempath= $$eval($${deploymentfolder}.target)
+ export($$itemsources)
+ export($$itempath)
+ DEPLOYMENT += $$item
+}
+
+MAINPROFILEPWD = $$PWD
+
+android-no-sdk {
+ for(deploymentfolder, DEPLOYMENTFOLDERS) {
+ item = item$${deploymentfolder}
+ itemfiles = $${item}.files
+ $$itemfiles = $$eval($${deploymentfolder}.source)
+ itempath = $${item}.path
+ $$itempath = /data/user/qt/$$eval($${deploymentfolder}.target)
+ export($$itemfiles)
+ export($$itempath)
+ INSTALLS += $$item
+ }
+
+ target.path = /data/user/qt
+
+ export(target.path)
+ INSTALLS += target
+} else:android {
+ for(deploymentfolder, DEPLOYMENTFOLDERS) {
+ item = item$${deploymentfolder}
+ itemfiles = $${item}.files
+ $$itemfiles = $$eval($${deploymentfolder}.source)
+ itempath = $${item}.path
+ $$itempath = /assets/$$eval($${deploymentfolder}.target)
+ export($$itemfiles)
+ export($$itempath)
+ INSTALLS += $$item
+ }
+
+ x86 {
+ target.path = /libs/x86
+ } else: armeabi-v7a {
+ target.path = /libs/armeabi-v7a
+ } else {
+ target.path = /libs/armeabi
+ }
+
+ export(target.path)
+ INSTALLS += target
+} else:win32 {
+ copyCommand =
+ for(deploymentfolder, DEPLOYMENTFOLDERS) {
+ source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source)
+ source = $$replace(source, /, \\)
+ sourcePathSegments = $$split(source, \\)
+ target = $$OUT_PWD/$$eval($${deploymentfolder}.target)/$$last(sourcePathSegments)
+ target = $$replace(target, /, \\)
+ target ~= s,\\\\\\.?\\\\,\\,
+ !isEqual(source,$$target) {
+ !isEmpty(copyCommand):copyCommand += &&
+ isEqual(QMAKE_DIR_SEP, \\) {
+ copyCommand += $(COPY_DIR) \"$$source\" \"$$target\"
+ } else {
+ source = $$replace(source, \\\\, /)
+ target = $$OUT_PWD/$$eval($${deploymentfolder}.target)
+ target = $$replace(target, \\\\, /)
+ copyCommand += test -d \"$$target\" || mkdir -p \"$$target\" && cp -r \"$$source\" \"$$target\"
+ }
+ }
+ }
+ !isEmpty(copyCommand) {
+ copyCommand = @echo Copying application data... && $$copyCommand
+ copydeploymentfolders.commands = $$copyCommand
+ first.depends = $(first) copydeploymentfolders
+ export(first.depends)
+ export(copydeploymentfolders.commands)
+ QMAKE_EXTRA_TARGETS += first copydeploymentfolders
+ }
+} else:unix {
+ maemo5 {
+ desktopfile.files = $${TARGET}.desktop
+ desktopfile.path = /usr/share/applications/hildon
+ icon.files = $${TARGET}64.png
+ icon.path = /usr/share/icons/hicolor/64x64/apps
+ } else:!isEmpty(MEEGO_VERSION_MAJOR) {
+ desktopfile.files = $${TARGET}_harmattan.desktop
+ desktopfile.path = /usr/share/applications
+ icon.files = $${TARGET}80.png
+ icon.path = /usr/share/icons/hicolor/80x80/apps
+ } else { # Assumed to be a Desktop Unix
+ copyCommand =
+ for(deploymentfolder, DEPLOYMENTFOLDERS) {
+ source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source)
+ source = $$replace(source, \\\\, /)
+ macx {
+ target = $$OUT_PWD/$${TARGET}.app/Contents/Resources/$$eval($${deploymentfolder}.target)
+ } else {
+ target = $$OUT_PWD/$$eval($${deploymentfolder}.target)
+ }
+ target = $$replace(target, \\\\, /)
+ sourcePathSegments = $$split(source, /)
+ targetFullPath = $$target/$$last(sourcePathSegments)
+ targetFullPath ~= s,/\\.?/,/,
+ !isEqual(source,$$targetFullPath) {
+ !isEmpty(copyCommand):copyCommand += &&
+ copyCommand += $(MKDIR) \"$$target\"
+ copyCommand += && $(COPY_DIR) \"$$source\" \"$$target\"
+ }
+ }
+ !isEmpty(copyCommand) {
+ copyCommand = @echo Copying application data... && $$copyCommand
+ copydeploymentfolders.commands = $$copyCommand
+ first.depends = $(first) copydeploymentfolders
+ export(first.depends)
+ export(copydeploymentfolders.commands)
+ QMAKE_EXTRA_TARGETS += first copydeploymentfolders
+ }
+ }
+ !isEmpty(target.path) {
+ installPrefix = $${target.path}
+ } else {
+ installPrefix = /opt/$${TARGET}
+ }
+ for(deploymentfolder, DEPLOYMENTFOLDERS) {
+ item = item$${deploymentfolder}
+ itemfiles = $${item}.files
+ $$itemfiles = $$eval($${deploymentfolder}.source)
+ itempath = $${item}.path
+ $$itempath = $${installPrefix}/$$eval($${deploymentfolder}.target)
+ export($$itemfiles)
+ export($$itempath)
+ INSTALLS += $$item
+ }
+
+ !isEmpty(desktopfile.path) {
+ export(icon.files)
+ export(icon.path)
+ export(desktopfile.files)
+ export(desktopfile.path)
+ INSTALLS += icon desktopfile
+ }
+
+ isEmpty(target.path) {
+ target.path = $${installPrefix}/bin
+ export(target.path)
+ }
+ INSTALLS += target
+}
+
+export (ICON)
+export (INSTALLS)
+export (DEPLOYMENT)
+export (LIBS)
+export (QMAKE_EXTRA_TARGETS)
+}
diff --git a/tests/scattertest/main.cpp b/tests/scattertest/main.cpp
index dda4536b..26f30beb 100644
--- a/tests/scattertest/main.cpp
+++ b/tests/scattertest/main.cpp
@@ -30,6 +30,8 @@
#include <QLabel>
#include <QScreen>
#include <QFontDatabase>
+#include <QLinearGradient>
+#include <QPainter>
int main(int argc, char **argv)
{
@@ -68,6 +70,9 @@ int main(int argc, char **argv)
QPushButton *clearButton = new QPushButton(widget);
clearButton->setText(QStringLiteral("Clear chart"));
+ QPushButton *resetButton = new QPushButton(widget);
+ resetButton->setText(QStringLiteral("Reset axes"));
+
QPushButton *addOneButton = new QPushButton(widget);
addOneButton->setText(QStringLiteral("Add item"));
@@ -95,9 +100,29 @@ int main(int argc, char **argv)
QPushButton *setSelectedItemButton = new QPushButton(widget);
setSelectedItemButton->setText(QStringLiteral("Select/deselect item 3"));
+ QPushButton *addSeriesButton = new QPushButton(widget);
+ addSeriesButton->setText(QStringLiteral("Add Series"));
+
+ QPushButton *removeSeriesButton = new QPushButton(widget);
+ removeSeriesButton->setText(QStringLiteral("Remove Series"));
+
QPushButton *startTimerButton = new QPushButton(widget);
startTimerButton->setText(QStringLiteral("Start/stop timer"));
+ QLinearGradient grBtoY(0, 0, 100, 0);
+ grBtoY.setColorAt(1.0, Qt::black);
+ grBtoY.setColorAt(0.67, Qt::blue);
+ grBtoY.setColorAt(0.33, Qt::red);
+ grBtoY.setColorAt(0.0, Qt::yellow);
+ QPixmap pm(100, 24);
+ QPainter pmp(&pm);
+ pmp.setBrush(QBrush(grBtoY));
+ pmp.setPen(Qt::NoPen);
+ pmp.drawRect(0, 0, 100, 24);
+ QPushButton *gradientBtoYPB = new QPushButton(widget);
+ gradientBtoYPB->setIcon(QIcon(pm));
+ gradientBtoYPB->setIconSize(QSize(100, 24));
+
QCheckBox *backgroundCheckBox = new QCheckBox(widget);
backgroundCheckBox->setText(QStringLiteral("Show background"));
backgroundCheckBox->setChecked(true);
@@ -114,7 +139,7 @@ int main(int argc, char **argv)
shadowQuality->addItem(QStringLiteral("Low Soft"));
shadowQuality->addItem(QStringLiteral("Medium Soft"));
shadowQuality->addItem(QStringLiteral("High Soft"));
- shadowQuality->setCurrentIndex(3);
+ shadowQuality->setCurrentIndex(0);
QFontComboBox *fontList = new QFontComboBox(widget);
@@ -124,11 +149,18 @@ int main(int argc, char **argv)
fontSizeSlider->setValue(30);
fontSizeSlider->setMaximum(200);
+ QSlider *pointSizeSlider = new QSlider(Qt::Horizontal, widget);
+ pointSizeSlider->setTickInterval(1);
+ pointSizeSlider->setMinimum(1);
+ pointSizeSlider->setValue(30);
+ pointSizeSlider->setMaximum(100);
+
vLayout->addWidget(themeButton, 0, Qt::AlignTop);
vLayout->addWidget(labelButton, 0, Qt::AlignTop);
vLayout->addWidget(styleButton, 0, Qt::AlignTop);
vLayout->addWidget(cameraButton, 0, Qt::AlignTop);
vLayout->addWidget(clearButton, 0, Qt::AlignTop);
+ vLayout->addWidget(resetButton, 0, Qt::AlignTop);
vLayout->addWidget(addOneButton, 0, Qt::AlignTop);
vLayout->addWidget(addBunchButton, 0, Qt::AlignTop);
vLayout->addWidget(insertOneButton, 0, Qt::AlignTop);
@@ -138,7 +170,10 @@ int main(int argc, char **argv)
vLayout->addWidget(removeOneButton, 0, Qt::AlignTop);
vLayout->addWidget(removeBunchButton, 0, Qt::AlignTop);
vLayout->addWidget(setSelectedItemButton, 0, Qt::AlignTop);
+ vLayout->addWidget(addSeriesButton, 0, Qt::AlignTop);
+ vLayout->addWidget(removeSeriesButton, 0, Qt::AlignTop);
vLayout->addWidget(startTimerButton, 0, Qt::AlignTop);
+ vLayout->addWidget(gradientBtoYPB, 0, Qt::AlignTop);
vLayout->addWidget(backgroundCheckBox);
vLayout->addWidget(gridCheckBox);
vLayout->addWidget(new QLabel(QStringLiteral("Adjust shadow quality")));
@@ -147,6 +182,8 @@ int main(int argc, char **argv)
vLayout->addWidget(fontList);
vLayout->addWidget(new QLabel(QStringLiteral("Adjust font size")));
vLayout->addWidget(fontSizeSlider, 1, Qt::AlignTop);
+ vLayout->addWidget(new QLabel(QStringLiteral("Adjust point size")));
+ vLayout->addWidget(pointSizeSlider, 1, Qt::AlignTop);
widget->show();
@@ -154,6 +191,8 @@ int main(int argc, char **argv)
QObject::connect(fontSizeSlider, &QSlider::valueChanged, modifier,
&ScatterDataModifier::changeFontSize);
+ QObject::connect(pointSizeSlider, &QSlider::valueChanged, modifier,
+ &ScatterDataModifier::changePointSize);
QObject::connect(styleButton, &QPushButton::clicked, modifier,
&ScatterDataModifier::changeStyle);
@@ -161,6 +200,8 @@ int main(int argc, char **argv)
&ScatterDataModifier::changePresetCamera);
QObject::connect(clearButton, &QPushButton::clicked, modifier,
&ScatterDataModifier::clear);
+ QObject::connect(resetButton, &QPushButton::clicked, modifier,
+ &ScatterDataModifier::resetAxes);
QObject::connect(addOneButton, &QPushButton::clicked, modifier,
&ScatterDataModifier::addOne);
QObject::connect(addBunchButton, &QPushButton::clicked, modifier,
@@ -179,8 +220,14 @@ int main(int argc, char **argv)
&ScatterDataModifier::removeBunch);
QObject::connect(setSelectedItemButton, &QPushButton::clicked, modifier,
&ScatterDataModifier::selectItem);
+ QObject::connect(addSeriesButton, &QPushButton::clicked, modifier,
+ &ScatterDataModifier::addSeries);
+ QObject::connect(removeSeriesButton, &QPushButton::clicked, modifier,
+ &ScatterDataModifier::removeSeries);
QObject::connect(startTimerButton, &QPushButton::clicked, modifier,
&ScatterDataModifier::startStopTimer);
+ QObject::connect(gradientBtoYPB, &QPushButton::clicked, modifier,
+ &ScatterDataModifier::setGradient);
QObject::connect(themeButton, &QPushButton::clicked, modifier,
&ScatterDataModifier::changeTheme);
QObject::connect(labelButton, &QPushButton::clicked, modifier,
@@ -190,11 +237,6 @@ int main(int argc, char **argv)
SLOT(changeShadowQuality(int)));
QObject::connect(modifier, &ScatterDataModifier::shadowQualityChanged, shadowQuality,
&QComboBox::setCurrentIndex);
- QObject::connect(chart, &Q3DScatter::shadowQualityChanged, modifier,
- &ScatterDataModifier::shadowQualityUpdatedByVisual);
- QObject::connect(chart, &Q3DScatter::selectedItemIndexChanged, modifier,
- &ScatterDataModifier::handleSelectionChange);
-
QObject::connect(fontList, &QFontComboBox::currentFontChanged, modifier,
&ScatterDataModifier::changeFont);
diff --git a/tests/scattertest/scatterchart.cpp b/tests/scattertest/scatterchart.cpp
index f23ee99d..b1df526a 100644
--- a/tests/scattertest/scatterchart.cpp
+++ b/tests/scattertest/scatterchart.cpp
@@ -18,9 +18,11 @@
#include "scatterchart.h"
#include <QtDataVisualization/qscatterdataproxy.h>
+#include <QtDataVisualization/qscatter3dseries.h>
#include <QtDataVisualization/q3dvalueaxis.h>
#include <QtDataVisualization/q3dscene.h>
#include <QtDataVisualization/q3dcamera.h>
+#include <QtDataVisualization/q3dtheme.h>
#include <qmath.h>
using namespace QtDataVisualization;
@@ -31,24 +33,28 @@ const int numberOfItems = 10000;
ScatterDataModifier::ScatterDataModifier(Q3DScatter *scatter)
: m_chart(scatter),
m_fontSize(30.0f),
- m_selectedItem(-1)
+ m_loopCounter(0),
+ m_selectedItem(-1),
+ m_targetSeries(0)
{
- QFont font = m_chart->font();
+ m_chart->setTheme(new Q3DTheme(Q3DTheme::ThemeStoneMoss));
+ QFont font = m_chart->theme()->font();
font.setPointSize(m_fontSize);
- m_chart->setFont(font);
- m_chart->setObjectType(QDataVis::MeshStyleSpheres, true);
- m_chart->setTheme(QDataVis::ThemeStoneMoss);
- m_chart->setShadowQuality(QDataVis::ShadowQualityHigh);
- m_chart->scene()->activeCamera()->setCameraPreset(QDataVis::CameraPresetFront);
+ m_chart->theme()->setFont(font);
+ m_chart->setShadowQuality(QDataVis::ShadowQualityNone);
+ m_chart->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetFront);
m_chart->setAxisX(new Q3DValueAxis);
m_chart->setAxisY(new Q3DValueAxis);
m_chart->setAxisZ(new Q3DValueAxis);
- QScatterDataProxy *proxy = new QScatterDataProxy;
- proxy->setItemLabelFormat("@xTitle: @xLabel @yTitle: @yLabel @zTitle: @zLabel");
- m_chart->setActiveDataProxy(proxy);
+ createAndAddSeries();
+ createAndAddSeries();
- connect(&m_timer, &QTimer::timeout, this, &ScatterDataModifier::timeout);
+ m_chart->setSelectionMode(QDataVis::SelectionItem);
+
+ QObject::connect(&m_timer, &QTimer::timeout, this, &ScatterDataModifier::timeout);
+ QObject::connect(m_chart, &Q3DScatter::shadowQualityChanged, this,
+ &ScatterDataModifier::shadowQualityUpdatedByVisual);
}
ScatterDataModifier::~ScatterDataModifier()
@@ -67,18 +73,23 @@ void ScatterDataModifier::addData()
m_chart->axisX()->setTitle("X");
m_chart->axisY()->setTitle("Y");
m_chart->axisZ()->setTitle("Z");
- m_chart->axisX()->setRange(-50.0, 50.0);
- m_chart->axisY()->setRange(-1.0, 1.0);
- m_chart->axisZ()->setRange(-50.0, 50.0);
+ m_chart->axisX()->setRange(-50.0f, 50.0f);
+ m_chart->axisY()->setRange(-1.0f, 1.2f);
+ m_chart->axisZ()->setRange(-50.0f, 50.0f);
QScatterDataArray *dataArray = new QScatterDataArray;
dataArray->resize(numberOfItems);
QScatterDataItem *ptrToDataArray = &dataArray->first();
+ QScatterDataArray *dataArray2 = new QScatterDataArray;
+ dataArray2->resize(numberOfItems);
+ QScatterDataItem *ptrToDataArray2 = &dataArray2->first();
#ifdef RANDOM_SCATTER
for (int i = 0; i < numberOfItems; i++) {
ptrToDataArray->setPosition(randVector());
ptrToDataArray++;
+ ptrToDataArray2->setPosition(randVector());
+ ptrToDataArray2++;
}
#else
float limit = qSqrt(numberOfItems) / 2.0f;
@@ -86,78 +97,99 @@ void ScatterDataModifier::addData()
for (float j = -limit; j < limit; j++) {
ptrToDataArray->setPosition(QVector3D(i, qCos(qDegreesToRadians((i * j) / 7.5)), j));
ptrToDataArray++;
+ ptrToDataArray2->setPosition(QVector3D(i, qCos(qDegreesToRadians((i * j) / 7.5)) + 0.2, j));
+ ptrToDataArray2++;
}
}
#endif
- static_cast<QScatterDataProxy *>(m_chart->activeDataProxy())->resetArray(dataArray);
+ m_chart->seriesList().at(0)->dataProxy()->resetArray(dataArray);
+ m_chart->seriesList().at(1)->dataProxy()->resetArray(dataArray2);
}
void ScatterDataModifier::changeStyle()
{
- static int model = 0;
- switch (model) {
- case 0:
- m_chart->setObjectType(QDataVis::MeshStyleDots, false);
- break;
- case 1:
- m_chart->setObjectType(QDataVis::MeshStyleDots, true);
- break;
- case 2:
- m_chart->setObjectType(QDataVis::MeshStyleSpheres, false);
- break;
- case 3:
- m_chart->setObjectType(QDataVis::MeshStyleSpheres, true);
- break;
+ if (!m_targetSeries)
+ createAndAddSeries();
+
+ if (m_targetSeries->isMeshSmooth()) {
+ m_targetSeries->setMeshSmooth(false);
+ switch (m_targetSeries->mesh()) {
+ case QAbstract3DSeries::MeshCube:
+ m_targetSeries->setMesh(QAbstract3DSeries::MeshPyramid);
+ break;
+ case QAbstract3DSeries::MeshPyramid:
+ m_targetSeries->setMesh(QAbstract3DSeries::MeshCone);
+ break;
+ case QAbstract3DSeries::MeshCone:
+ m_targetSeries->setMesh(QAbstract3DSeries::MeshCylinder);
+ break;
+ case QAbstract3DSeries::MeshCylinder:
+ m_targetSeries->setMesh(QAbstract3DSeries::MeshBevelCube);
+ break;
+ case QAbstract3DSeries::MeshBevelCube:
+ m_targetSeries->setMesh(QAbstract3DSeries::MeshSphere);
+ break;
+ case QAbstract3DSeries::MeshSphere:
+ m_targetSeries->setMesh(QAbstract3DSeries::MeshMinimal);
+ break;
+ case QAbstract3DSeries::MeshMinimal:
+ m_targetSeries->setMesh(QAbstract3DSeries::MeshPoint);
+ break;
+ default:
+ m_targetSeries->setMesh(QAbstract3DSeries::MeshCube);
+ break;
+ }
+ } else {
+ m_targetSeries->setMeshSmooth(true);
}
- model++;
- if (model > 3)
- model = 0;
+
+ qDebug() << __FUNCTION__ << m_targetSeries->mesh() << m_targetSeries->isMeshSmooth();
}
void ScatterDataModifier::changePresetCamera()
{
- static int preset = QDataVis::CameraPresetFrontLow;
+ static int preset = Q3DCamera::CameraPresetFrontLow;
- m_chart->scene()->activeCamera()->setCameraPreset((QDataVis::CameraPreset)preset);
+ m_chart->scene()->activeCamera()->setCameraPreset((Q3DCamera::CameraPreset)preset);
- if (++preset > QDataVis::CameraPresetDirectlyAboveCCW45)
- preset = QDataVis::CameraPresetFrontLow;
+ if (++preset > Q3DCamera::CameraPresetDirectlyAboveCCW45)
+ preset = Q3DCamera::CameraPresetFrontLow;
}
void ScatterDataModifier::changeTheme()
{
- static int theme = QDataVis::ThemeQt;
+ static int theme = Q3DTheme::ThemeQt;
- m_chart->setTheme((QDataVis::Theme)theme);
+ m_chart->setTheme(new Q3DTheme(Q3DTheme::Theme(theme)));
- if (++theme > QDataVis::ThemeIsabelle)
- theme = QDataVis::ThemeQt;
+ if (++theme > Q3DTheme::ThemeIsabelle)
+ theme = Q3DTheme::ThemeQt;
}
void ScatterDataModifier::changeLabelStyle()
{
- static int style = QDataVis::LabelStyleOpaque;
-
- m_chart->setLabelStyle((QDataVis::LabelStyle)style);
-
- if (++style > QDataVis::LabelStyleTransparent)
- style = QDataVis::LabelStyleOpaque;
+ m_chart->theme()->setLabelBackgroundEnabled(!m_chart->theme()->isLabelBackgroundEnabled());
}
void ScatterDataModifier::changeFont(const QFont &font)
{
QFont newFont = font;
newFont.setPointSizeF(m_fontSize);
- m_chart->setFont(newFont);
+ m_chart->theme()->setFont(newFont);
}
-void ScatterDataModifier::changeFontSize(int fontsize)
+void ScatterDataModifier::changeFontSize(int fontSize)
{
- m_fontSize = fontsize;
- QFont font = m_chart->font();
+ m_fontSize = fontSize;
+ QFont font = m_chart->theme()->font();
font.setPointSize(m_fontSize);
- m_chart->setFont(font);
+ m_chart->theme()->setFont(font);
+}
+
+void ScatterDataModifier::changePointSize(int pointSize)
+{
+ m_targetSeries->setItemSize(0.01f * float(pointSize));
}
void ScatterDataModifier::shadowQualityUpdatedByVisual(QDataVis::ShadowQuality sq)
@@ -169,80 +201,127 @@ void ScatterDataModifier::shadowQualityUpdatedByVisual(QDataVis::ShadowQuality s
void ScatterDataModifier::clear()
{
- m_chart->activeDataProxy()->resetArray(0);
+ foreach (QScatter3DSeries *series, m_chart->seriesList()) {
+ m_chart->removeSeries(series);
+ delete series;
+ }
+
+ m_targetSeries = 0;
+
qDebug() << m_loopCounter << "Cleared array";
}
+void ScatterDataModifier::resetAxes()
+{
+ m_chart->releaseAxis(m_chart->axisX());
+ m_chart->releaseAxis(m_chart->axisY());
+ m_chart->releaseAxis(m_chart->axisZ());
+
+ m_chart->setAxisX(new Q3DValueAxis);
+ m_chart->setAxisY(new Q3DValueAxis);
+ m_chart->setAxisZ(new Q3DValueAxis);
+ m_chart->axisX()->setSegmentCount(5);
+ m_chart->axisY()->setSegmentCount(5);
+ m_chart->axisZ()->setSegmentCount(5);
+ m_chart->axisX()->setTitle("X");
+ m_chart->axisY()->setTitle("Y");
+ m_chart->axisZ()->setTitle("Z");
+}
+
void ScatterDataModifier::addOne()
{
+ if (!m_targetSeries)
+ createAndAddSeries();
+
QScatterDataItem item(randVector());
- int addIndex = m_chart->activeDataProxy()->addItem(item);
- qDebug() << m_loopCounter << "added one to index:" << addIndex << "array size:" << m_chart->activeDataProxy()->array()->size();
+ int addIndex = m_targetSeries->dataProxy()->addItem(item);
+ qDebug() << m_loopCounter << "added one to index:" << addIndex << "array size:" << m_targetSeries->dataProxy()->array()->size();
}
void ScatterDataModifier::addBunch()
{
+ if (!m_targetSeries)
+ createAndAddSeries();
+
QScatterDataArray items(100);
for (int i = 0; i < items.size(); i++)
items[i].setPosition(randVector());
- int addIndex = m_chart->activeDataProxy()->addItems(items);
- qDebug() << m_loopCounter << "added bunch to index:" << addIndex << "array size:" << m_chart->activeDataProxy()->array()->size();
+ int addIndex = m_targetSeries->dataProxy()->addItems(items);
+ qDebug() << m_loopCounter << "added bunch to index:" << addIndex << "array size:" << m_targetSeries->dataProxy()->array()->size();
}
void ScatterDataModifier::insertOne()
{
+ if (!m_targetSeries)
+ createAndAddSeries();
+
QScatterDataItem item(randVector());
- m_chart->activeDataProxy()->insertItem(0, item);
- qDebug() << m_loopCounter << "Inserted one, array size:" << m_chart->activeDataProxy()->array()->size();
+ m_targetSeries->dataProxy()->insertItem(0, item);
+ qDebug() << m_loopCounter << "Inserted one, array size:" << m_targetSeries->dataProxy()->array()->size();
}
void ScatterDataModifier::insertBunch()
{
+ if (!m_targetSeries)
+ createAndAddSeries();
+
QScatterDataArray items(100);
for (int i = 0; i < items.size(); i++)
items[i].setPosition(randVector());
- m_chart->activeDataProxy()->insertItems(0, items);
- qDebug() << m_loopCounter << "Inserted bunch, array size:" << m_chart->activeDataProxy()->array()->size();
+ m_targetSeries->dataProxy()->insertItems(0, items);
+ qDebug() << m_loopCounter << "Inserted bunch, array size:" << m_targetSeries->dataProxy()->array()->size();
}
void ScatterDataModifier::changeOne()
{
- if (m_selectedItem >= 0 && m_chart->activeDataProxy()->array()->size()) {
+ if (!m_targetSeries)
+ createAndAddSeries();
+
+ if (m_selectedItem >= 0 && m_selectedItem < m_targetSeries->dataProxy()->itemCount()) {
QScatterDataItem item(randVector());
- m_chart->activeDataProxy()->setItem(m_selectedItem, item);
- qDebug() << m_loopCounter << "Changed one, array size:" << m_chart->activeDataProxy()->array()->size();
+ m_targetSeries->dataProxy()->setItem(m_selectedItem, item);
+ qDebug() << m_loopCounter << "Changed one, array size:" << m_targetSeries->dataProxy()->array()->size();
}
}
void ScatterDataModifier::changeBunch()
{
- if (m_chart->activeDataProxy()->array()->size()) {
- int amount = qMin(m_chart->activeDataProxy()->array()->size(), 100);
+ if (!m_targetSeries)
+ createAndAddSeries();
+
+ if (m_targetSeries->dataProxy()->array()->size()) {
+ int amount = qMin(m_targetSeries->dataProxy()->array()->size(), 100);
QScatterDataArray items(amount);
for (int i = 0; i < items.size(); i++)
items[i].setPosition(randVector());
- m_chart->activeDataProxy()->setItems(0, items);
- qDebug() << m_loopCounter << "Changed bunch, array size:" << m_chart->activeDataProxy()->array()->size();
+ m_targetSeries->dataProxy()->setItems(0, items);
+ qDebug() << m_loopCounter << "Changed bunch, array size:" << m_targetSeries->dataProxy()->array()->size();
}
}
void ScatterDataModifier::removeOne()
{
+ if (!m_targetSeries)
+ createAndAddSeries();
+
if (m_selectedItem >= 0) {
- m_chart->activeDataProxy()->removeItems(m_selectedItem, 1);
- qDebug() << m_loopCounter << "Removed one, array size:" << m_chart->activeDataProxy()->array()->size();
+ m_targetSeries->dataProxy()->removeItems(m_selectedItem, 1);
+ qDebug() << m_loopCounter << "Removed one, array size:" << m_targetSeries->dataProxy()->array()->size();
}
}
void ScatterDataModifier::removeBunch()
{
- m_chart->activeDataProxy()->removeItems(0, 100);
- qDebug() << m_loopCounter << "Removed bunch, array size:" << m_chart->activeDataProxy()->array()->size();
+ if (!m_targetSeries)
+ createAndAddSeries();
+
+ m_targetSeries->dataProxy()->removeItems(0, 100);
+ qDebug() << m_loopCounter << "Removed bunch, array size:" << m_targetSeries->dataProxy()->array()->size();
}
void ScatterDataModifier::timeout()
{
- int doWhat = rand() % 8;
+ int doWhat = rand() % 10;
if (!(rand() % 100))
doWhat = -1;
@@ -271,6 +350,15 @@ void ScatterDataModifier::timeout()
case 7:
removeBunch();
break;
+ case 8:
+ addSeries();
+ break;
+ case 9:
+ if (m_chart->seriesList().size())
+ m_targetSeries = m_chart->seriesList().at(rand() % m_chart->seriesList().size());
+ else
+ addSeries();
+ break;
default:
clear();
break;
@@ -292,18 +380,85 @@ void ScatterDataModifier::startStopTimer()
void ScatterDataModifier::selectItem()
{
+ if (!m_targetSeries)
+ createAndAddSeries();
+
int targetItem(3);
int noSelection(-1);
- if (m_selectedItem != targetItem)
- m_chart->setSelectedItemIndex(targetItem);
+ if (m_selectedItem != targetItem || m_targetSeries != m_chart->seriesList().at(0))
+ m_chart->seriesList().at(0)->setSelectedItem(targetItem);
else
- m_chart->setSelectedItemIndex(noSelection);
+ m_chart->seriesList().at(0)->setSelectedItem(noSelection);
}
void ScatterDataModifier::handleSelectionChange(int index)
{
m_selectedItem = index;
- qDebug() << "Selected item index:" << index;
+ m_targetSeries = static_cast<QScatter3DSeries *>(sender());
+ int seriesIndex = 0;
+ foreach (QScatter3DSeries *series, m_chart->seriesList()) {
+ if (series == sender())
+ break;
+ seriesIndex++;
+ }
+
+ qDebug() << "Selected item index:" << index << "series:" << seriesIndex;
+}
+
+void ScatterDataModifier::setGradient()
+{
+ QLinearGradient baseGradient(0, 0, 1, 100);
+ baseGradient.setColorAt(1.0, Qt::lightGray);
+ baseGradient.setColorAt(0.75001, Qt::lightGray);
+ baseGradient.setColorAt(0.75, Qt::blue);
+ baseGradient.setColorAt(0.50001, Qt::blue);
+ baseGradient.setColorAt(0.50, Qt::red);
+ baseGradient.setColorAt(0.25001, Qt::red);
+ baseGradient.setColorAt(0.25, Qt::yellow);
+ baseGradient.setColorAt(0.0, Qt::yellow);
+
+ QLinearGradient singleHighlightGradient(0, 0, 1, 100);
+ singleHighlightGradient.setColorAt(1.0, Qt::lightGray);
+ singleHighlightGradient.setColorAt(0.75, Qt::blue);
+ singleHighlightGradient.setColorAt(0.50, Qt::red);
+ singleHighlightGradient.setColorAt(0.25, Qt::yellow);
+ singleHighlightGradient.setColorAt(0.0, Qt::white);
+
+ m_targetSeries->setBaseColor(Qt::green);
+ m_targetSeries->setSingleHighlightColor(Qt::white);
+
+ m_targetSeries->setBaseGradient(baseGradient);
+ m_targetSeries->setSingleHighlightGradient(singleHighlightGradient);
+
+ Q3DTheme::ColorStyle oldStyle = m_targetSeries->colorStyle();
+ if (oldStyle == Q3DTheme::ColorStyleUniform)
+ m_targetSeries->setColorStyle(Q3DTheme::ColorStyleObjectGradient);
+ else if (oldStyle == Q3DTheme::ColorStyleObjectGradient)
+ m_targetSeries->setColorStyle(Q3DTheme::ColorStyleRangeGradient);
+ if (oldStyle == Q3DTheme::ColorStyleRangeGradient)
+ m_targetSeries->setColorStyle(Q3DTheme::ColorStyleUniform);
+}
+
+void ScatterDataModifier::addSeries()
+{
+ QScatter3DSeries *series = createAndAddSeries();
+
+ QScatter3DSeries *oldTargetSeries = m_targetSeries;
+ m_targetSeries = series; // adding always adds to target series, so fake it for a bit
+ addOne(); // add one random item to start the new series off
+ m_targetSeries = oldTargetSeries;
+}
+
+void ScatterDataModifier::removeSeries()
+{
+ if (m_targetSeries) {
+ m_chart->removeSeries(m_targetSeries);
+ delete m_targetSeries;
+ if (m_chart->seriesList().size())
+ m_targetSeries = m_chart->seriesList().at(0);
+ else
+ m_targetSeries = 0;
+ }
}
void ScatterDataModifier::changeShadowQuality(int quality)
@@ -315,12 +470,12 @@ void ScatterDataModifier::changeShadowQuality(int quality)
void ScatterDataModifier::setBackgroundEnabled(int enabled)
{
- m_chart->setBackgroundVisible((bool)enabled);
+ m_chart->theme()->setBackgroundEnabled((bool)enabled);
}
void ScatterDataModifier::setGridEnabled(int enabled)
{
- m_chart->setGridVisible((bool)enabled);
+ m_chart->theme()->setGridEnabled((bool)enabled);
}
QVector3D ScatterDataModifier::randVector()
@@ -330,3 +485,24 @@ QVector3D ScatterDataModifier::randVector()
(float)(rand() % 100) / 100.0f - (float)(rand() % 100) / 100.0f,
(float)(rand() % 100) / 2.0f - (float)(rand() % 100) / 2.0f);
}
+
+QScatter3DSeries *ScatterDataModifier::createAndAddSeries()
+{
+ static int counter = 0;
+
+ QScatter3DSeries *series = new QScatter3DSeries;
+
+ if (!m_targetSeries)
+ m_targetSeries = series;
+
+ m_chart->addSeries(series);
+ series->setItemLabelFormat(QString("%1: @xLabel - @yLabel - @zLabel").arg(counter++));
+ series->setMesh(QAbstract3DSeries::MeshSphere);
+ series->setMeshSmooth(true);
+ series->setBaseColor(QColor(rand() % 256, rand() % 256, rand() % 256));
+
+ QObject::connect(series, &QScatter3DSeries::selectedItemChanged, this,
+ &ScatterDataModifier::handleSelectionChange);
+
+ return series;
+}
diff --git a/tests/scattertest/scatterchart.h b/tests/scattertest/scatterchart.h
index 7132e7ce..5524929e 100644
--- a/tests/scattertest/scatterchart.h
+++ b/tests/scattertest/scatterchart.h
@@ -20,6 +20,7 @@
#define SCATTERDATAMODIFIER_H
#include <QtDataVisualization/q3dscatter.h>
+#include <QtDataVisualization/qscatter3dseries.h>
#include <QFont>
#include <QDebug>
@@ -40,7 +41,8 @@ public:
void changeTheme();
void changeLabelStyle();
void changeFont(const QFont &font);
- void changeFontSize(int fontsize);
+ void changeFontSize(int fontSize);
+ void changePointSize(int pointSize);
void setBackgroundEnabled(int enabled);
void setGridEnabled(int enabled);
void start();
@@ -49,6 +51,7 @@ public slots:
void changeShadowQuality(int quality);
void shadowQualityUpdatedByVisual(QDataVis::ShadowQuality shadowQuality);
void clear();
+ void resetAxes();
void addOne();
void addBunch();
void insertOne();
@@ -61,17 +64,23 @@ public slots:
void startStopTimer();
void selectItem();
void handleSelectionChange(int index);
+ void setGradient();
+ void addSeries();
+ void removeSeries();
signals:
void shadowQualityChanged(int quality);
private:
QVector3D randVector();
+ QScatter3DSeries *createAndAddSeries();
+
Q3DScatter *m_chart;
int m_fontSize;
QTimer m_timer;
int m_loopCounter;
int m_selectedItem;
+ QScatter3DSeries *m_targetSeries;
};
#endif
diff --git a/tests/spectrum/spectrumapp/main.cpp b/tests/spectrum/spectrumapp/main.cpp
index 3d2e2bf1..311de719 100644
--- a/tests/spectrum/spectrumapp/main.cpp
+++ b/tests/spectrum/spectrumapp/main.cpp
@@ -25,6 +25,8 @@
#include <QtDataVisualization/q3dcategoryaxis.h>
#include <QtDataVisualization/q3dscene.h>
#include <QtDataVisualization/q3dcamera.h>
+#include <QtDataVisualization/qbar3dseries.h>
+#include <QtDataVisualization/q3dtheme.h>
#include <QGuiApplication>
#include <QAudio>
@@ -72,9 +74,9 @@ MainApp::MainApp(Q3DBars *window)
m_chart->rowAxis()->setMax(SpectrumNumBands * 2);
m_chart->columnAxis()->setMax(SpectrumNumBands - 1);
// Disable grid
- m_chart->setGridVisible(false);
+ m_chart->theme()->setGridEnabled(false);
// Disable auto-scaling of height by defining explicit range
- m_chart->valueAxis()->setRange(0.0, 1.0);
+ m_chart->valueAxis()->setRange(0.0f, 1.0f);
// Disable shadows
m_chart->setShadowQuality(QDataVis::ShadowQualityNone);
#if USE_CONES
@@ -83,30 +85,29 @@ MainApp::MainApp(Q3DBars *window)
m_chart->setBarThickness(1.25);
m_chart->setBarSpacing(QSizeF(0.2, -0.75));
// Set bar type, smooth cones
- m_chart->setBarType(QDataVis::MeshStyleCones, true);
+ m_chart->setBarType(QDataVis::MeshCones, true);
// Adjust zoom manually; automatic zoom level calculation does not work well with negative
// spacings (in setBarSpacing)
- m_chart->setCameraPosition(10.0f, 5.0f, 70);
+ m_chart->setCameraPosition(10.0f, 5.0f, 70.0f);
#else
// Set bar specifications; make them twice as wide as they're deep
- m_chart->setBarThickness(2.0);
+ m_chart->setBarThickness(2.0f);
m_chart->setBarSpacing(QSizeF(0.0, 0.0));
// Set bar type, flat bars
- m_chart->setBarType(QDataVis::MeshStyleBars, false);
// Adjust camera position
- m_chart->scene()->activeCamera()->setCameraPosition(10.0f, 7.5f, 75);
+ m_chart->scene()->activeCamera()->setCameraPosition(10.0f, 7.5f, 75.0f);
#endif
- // Set color scheme
- m_chart->setBarColor(QColor(Qt::red), false);
// Disable selection
- m_chart->setSelectionMode(QDataVis::SelectionModeNone);
+ m_chart->setSelectionMode(QDataVis::SelectionNone);
QObject::connect(m_engine, &Engine::changedSpectrum, this, &MainApp::spectrumChanged);
QObject::connect(m_engine, &Engine::stateChanged, this, &MainApp::stateChanged);
m_restartTimer->setSingleShot(true);
QObject::connect(m_restartTimer, &QTimer::timeout, this, &MainApp::restart);
- QBarDataProxy *proxy = new QBarDataProxy;
- m_chart->setActiveDataProxy(proxy);
+ QBar3DSeries *series = new QBar3DSeries();
+ series->setBaseColor(QColor(Qt::red));
+ series->setMesh(QAbstract3DSeries::MeshBar);
+ m_chart->addSeries(series);
}
MainApp::~MainApp()
@@ -140,10 +141,10 @@ void MainApp::spectrumChanged(qint64 position, qint64 length, const FrequencySpe
for ( ; i != end; ++i) {
const FrequencySpectrum::Element e = *i;
if (e.frequency >= m_lowFreq && e.frequency < m_highFreq) {
- (*data)[barIndex(e.frequency)].setValue(qMax(data->at(barIndex(e.frequency)).value(), qreal(e.amplitude)));
+ (*data)[barIndex(e.frequency)].setValue(qMax(data->at(barIndex(e.frequency)).value(), float(e.amplitude)));
}
}
- static_cast<QBarDataProxy *>(m_chart->activeDataProxy())->insertRow(0, data);
+ m_chart->seriesList().at(0)->dataProxy()->insertRow(0, data);
}
void MainApp::stateChanged(QAudio::Mode mode, QAudio::State state)
@@ -197,6 +198,7 @@ int main(int argc, char *argv[])
app.setApplicationName("QtDataVisualization spectrum analyzer");
Q3DBars window;
+ window.setFlags(window.flags() ^ Qt::FramelessWindowHint);
window.resize(1024, 768);
window.show();
diff --git a/tests/spectrum/spectrumapp/spectrumapp.pro b/tests/spectrum/spectrumapp/spectrumapp.pro
index 940cce75..f5b52954 100644
--- a/tests/spectrum/spectrumapp/spectrumapp.pro
+++ b/tests/spectrum/spectrumapp/spectrumapp.pro
@@ -31,6 +31,7 @@ HEADERS += engine.h \
fftreal_dir = ../3rdparty/fftreal
INCLUDEPATH += $${fftreal_dir}
+INCLUDEPATH += ../../../include
RESOURCES = spectrum.qrc
diff --git a/tests/surfacetest/graphmodifier.cpp b/tests/surfacetest/graphmodifier.cpp
index d4e99031..3474b67f 100644
--- a/tests/surfacetest/graphmodifier.cpp
+++ b/tests/surfacetest/graphmodifier.cpp
@@ -19,10 +19,13 @@
#include "graphmodifier.h"
#include <QtDataVisualization/Q3DValueAxis>
#include <QtDataVisualization/QSurfaceDataProxy>
+#include <QtDataVisualization/QSurface3DSeries>
+#include <QtDataVisualization/Q3DTheme>
#include <qmath.h>
#include <QLinearGradient>
#include <QDebug>
+#include <QComboBox>
QT_DATAVISUALIZATION_USE_NAMESPACE
@@ -45,16 +48,23 @@ GraphModifier::GraphModifier(Q3DSurface *graph)
m_rangeZ(16.0),
m_minX(-8.0),
m_minZ(-8.0),
- m_planeArray(0)
+ m_addRowCounter(m_zCount),
+ m_insertTestZPos(0),
+ m_insertTestIndexPos(1),
+ m_planeArray(0),
+ m_theSeries(new QSurface3DSeries),
+ m_drawMode(QSurface3DSeries::DrawSurfaceAndWireframe)
{
m_graph->setAxisX(new Q3DValueAxis);
m_graph->setAxisY(new Q3DValueAxis);
m_graph->setAxisZ(new Q3DValueAxis);
m_graph->axisX()->setRange(m_minX, m_minX + m_rangeX);
m_graph->axisZ()->setRange(m_minZ, m_minZ + m_rangeZ);
+ m_graph->addSeries(m_theSeries);
changeStyle();
connect(&m_timer, &QTimer::timeout, this, &GraphModifier::timeout);
+ connect(m_theSeries, &QSurface3DSeries::selectedPointChanged, this, &GraphModifier::selectedPointChanged);
}
GraphModifier::~GraphModifier()
@@ -65,13 +75,34 @@ GraphModifier::~GraphModifier()
void GraphModifier::toggleSmooth(bool enabled)
{
qDebug() << "GraphModifier::toggleSmooth " << enabled;
- m_graph->setSmoothSurfaceEnabled(enabled);
+ m_theSeries->setFlatShadingEnabled(enabled);
}
void GraphModifier::toggleSurfaceGrid(bool enable)
{
qDebug() << "GraphModifier::toggleSurfaceGrid" << enable;
- m_graph->setSurfaceGridEnabled(enable);
+ if (enable)
+ m_drawMode |= QSurface3DSeries::DrawWireframe;
+ else
+ m_drawMode &= ~QSurface3DSeries::DrawWireframe;
+
+ m_theSeries->setDrawMode(m_drawMode);
+}
+
+void GraphModifier::toggleSurface(bool enable)
+{
+ qDebug() << "GraphModifier::toggleSurface" << enable;
+ if (enable)
+ m_drawMode |= QSurface3DSeries::DrawSurface;
+ else
+ m_drawMode &= ~QSurface3DSeries::DrawSurface;
+
+ m_theSeries->setDrawMode(m_drawMode);
+}
+
+void GraphModifier::toggleSeriesVisible(bool enable)
+{
+ m_theSeries->setVisible(enable);
}
void GraphModifier::toggleSqrtSin(bool enable)
@@ -79,10 +110,10 @@ void GraphModifier::toggleSqrtSin(bool enable)
if (enable) {
qDebug() << "Create Sqrt&Sin surface, (" << m_xCount << ", " << m_zCount << ")";
- float minX = -10.0;
- float maxX = 10.0;
- float minZ = -10.0;
- float maxZ = 10.0;
+ float minX = -10.0f;
+ float maxX = 10.0f;
+ float minZ = -10.0f;
+ float maxZ = 10.0f;
float stepX = (maxX - minX) / float(m_xCount - 1);
float stepZ = (maxZ - minZ) / float(m_zCount - 1);
@@ -90,9 +121,11 @@ void GraphModifier::toggleSqrtSin(bool enable)
dataArray->reserve(m_zCount);
for (float i = 0; i < m_zCount; i++) {
QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount);
+ // Keep values within range bounds, since just adding step can cause minor drift due
+ // to the rounding errors.
+ float z = qMin(maxZ, (i * stepZ + minZ));
for (float j = 0; j < m_xCount; j++) {
- float x = j * stepX + minX;
- float z = i * stepZ + minZ;
+ float x = qMin(maxX, (j * stepX + minX));
float R = qSqrt(x * x + z * z) + 0.01f;
float y = (qSin(R) / R + 0.24f) * 1.61f + 1.0f;
(*newRow)[j].setPosition(QVector3D(x, y, z));
@@ -127,16 +160,17 @@ void GraphModifier::togglePlane(bool enable)
m_graph->axisZ()->setLabelFormat("%.2f");
m_planeArray->reserve(m_zCount);
- float minX = -10.0;
- float maxX = 20.0;
- float minZ = -10.0;
- float maxZ = 10.0;
+ float minX = -10.0f;
+ float maxX = 20.0f;
+ float minZ = -10.0f;
+ float maxZ = 10.0f;
float stepX = (maxX - minX) / float(m_xCount - 1);
float stepZ = (maxZ - minZ) / float(m_zCount - 1);
#ifdef WONKY_PLANE
float halfZ = m_zCount / 2;
float wonkyFactor = 0.01f;
float maxStepX = 0.0f;
+ float add = 0.0f;
for (float i = 0; i < m_zCount; i++) {
QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount);
if (i < halfZ) {
@@ -145,20 +179,32 @@ void GraphModifier::togglePlane(bool enable)
} else {
stepX -= wonkyFactor;
}
+ add = 0.0f;
for (float j = 0; j < m_xCount; j++) {
(*newRow)[j].setPosition(QVector3D(j * stepX + minX, -0.04f,
- i * stepZ + minZ));
+ i * stepZ + minZ + add));
+ add += 0.5f;
}
*m_planeArray << newRow;
}
- resetArrayAndSliders(m_planeArray, minZ, maxZ, minX, m_xCount * maxStepX + minZ);
+ resetArrayAndSliders(m_planeArray, minZ, maxZ + add, minX, m_xCount * maxStepX + minX);
#else
for (float i = 0; i < m_zCount; i++) {
QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount);
- for (float j = 0; j < m_xCount; j++)
- (*newRow)[j].setPosition(QVector3D(j * stepX + minX, -0.04f, i * stepZ + minZ));
+ // Keep values within range bounds, since just adding step can cause minor drift due
+ // to the rounding errors.
+ float zVal;
+ if (i == (m_zCount - 1))
+ zVal = maxZ;
+ else
+ zVal = i * stepZ + minZ;
+
+ float j = 0;
+ for (; j < m_xCount - 1; j++)
+ (*newRow)[j].setPosition(QVector3D(j * stepX + minX, -0.04f, zVal));
+ (*newRow)[j].setPosition(QVector3D(maxX, -0.04f, zVal));
*m_planeArray << newRow;
}
@@ -283,29 +329,47 @@ void GraphModifier::gradientPressed()
gradient.setColorAt(0.33, Qt::blue);
gradient.setColorAt(0.67, Qt::red);
gradient.setColorAt(1.0, Qt::yellow);
- m_graph->setGradient(gradient);
+ m_graph->seriesList().at(0)->setBaseGradient(gradient);
+ m_graph->seriesList().at(0)->setSingleHighlightColor(Qt::red);
+ m_graph->seriesList().at(0)->setColorStyle(Q3DTheme::ColorStyleRangeGradient);
}
void GraphModifier::changeFont(const QFont &font)
{
QFont newFont = font;
newFont.setPointSizeF(m_fontSize);
- m_graph->setFont(newFont);
+ m_graph->theme()->setFont(newFont);
}
void GraphModifier::changeStyle()
{
- static int style = QDataVis::LabelStyleFromTheme;
+ m_graph->theme()->setLabelBackgroundEnabled(!m_graph->theme()->isLabelBackgroundEnabled());
+}
+
+void GraphModifier::selectButtonClicked()
+{
+ QSurfaceDataProxy *proxy = m_theSeries->dataProxy();
+ int row = rand() % proxy->rowCount();
+ int col = rand() % proxy->columnCount();
- m_graph->setLabelStyle((QDataVis::LabelStyle)style);
+ m_theSeries->setSelectedPoint(QPoint(row, col));
+}
- if (++style > QDataVis::LabelStyleTransparent)
- style = QDataVis::LabelStyleOpaque;
+void GraphModifier::selectedPointChanged(const QPoint &point)
+{
+ QString labelText = QStringLiteral("Selected row: %1, column: %2").arg(point.x()).arg(point.y());
+ m_selectionInfoLabel->setText(labelText);
}
void GraphModifier::changeTheme(int theme)
{
- m_graph->setTheme((QDataVis::Theme)theme);
+ m_graph->setTheme(new Q3DTheme(Q3DTheme::Theme(theme)));
+}
+
+
+void GraphModifier::flipViews()
+{
+ m_graph->scene()->setSecondarySubviewOnTop(!m_graph->scene()->isSecondarySubviewOnTop());
}
void GraphModifier::timeout()
@@ -326,17 +390,17 @@ void GraphModifier::timeout()
}
// Reset same array to make it redraw
- m_graph->activeDataProxy()->resetArray(m_planeArray);
+ m_theSeries->dataProxy()->resetArray(m_planeArray);
}
-void GraphModifier::resetArrayAndSliders(QSurfaceDataArray *array, qreal minZ, qreal maxZ, qreal minX, qreal maxX)
+void GraphModifier::resetArrayAndSliders(QSurfaceDataArray *array, float minZ, float maxZ, float minX, float maxX)
{
m_axisMinSliderX->setValue(minX);
m_axisMinSliderZ->setValue(minZ);
m_axisRangeSliderX->setValue(maxX - minX);
m_axisRangeSliderZ->setValue(maxZ - minZ);
- m_graph->activeDataProxy()->resetArray(array);
+ m_theSeries->dataProxy()->resetArray(array);
}
void GraphModifier::changeShadowQuality(int quality)
@@ -347,27 +411,287 @@ void GraphModifier::changeShadowQuality(int quality)
void GraphModifier::changeSelectionMode(int mode)
{
- switch (mode) {
+ QComboBox *comboBox = qobject_cast<QComboBox *>(sender());
+ if (comboBox) {
+ int flags = comboBox->itemData(mode).toInt();
+ m_graph->setSelectionMode(QDataVis::SelectionFlags(flags));
+ }
+}
+
+void GraphModifier::changeRow()
+{
+ if (m_activeSample == GraphModifier::SqrtSin) {
+ qDebug() << "Generating new values to a row at random pos";
+ float minX = -10.0f;
+ float maxX = 10.0f;
+ float minZ = -10.0f;
+ float maxZ = 10.0f;
+ float stepX = (maxX - minX) / float(m_xCount - 1);
+ float stepZ = (maxZ - minZ) / float(m_zCount - 1);
+ float i = float(rand() % m_zCount);
+
+ QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount);
+ float z = qMin(maxZ, (i * stepZ + minZ));
+ for (float j = 0; j < m_xCount; j++) {
+ float x = qMin(maxX, (j * stepX + minX));
+ float R = qSqrt(x * x + z * z) + 0.01f;
+ float y = (qSin(R) / R + 0.24f) * 1.61f + 1.2f;
+ (*newRow)[j].setPosition(QVector3D(x, y, z));
+ }
+
+ m_theSeries->dataProxy()->setRow(int(i), newRow);
+ } else {
+ qDebug() << "Change row function active only for SqrtSin";
+ }
+}
+
+void GraphModifier::changeRows()
+{
+ if (m_activeSample == GraphModifier::SqrtSin) {
+ qDebug() << "Generating new values to 3 rows from random pos";
+
+ float minX = -10.0f;
+ float maxX = 10.0f;
+ float minZ = -10.0f;
+ float maxZ = 10.0f;
+ float stepX = (maxX - minX) / float(m_xCount - 1);
+ float stepZ = (maxZ - minZ) / float(m_zCount - 1);
+ float start = float(rand() % (m_zCount - 3));
+
+ QSurfaceDataArray dataArray;
+
+ for (float i = start; i < (start + 3.0f); i++) {
+ QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount);
+ float z = qMin(maxZ, (i * stepZ + minZ));
+ for (float j = 0; j < m_xCount; j++) {
+ float x = qMin(maxX, (j * stepX + minX));
+ float R = qSqrt(x * x + z * z) + 0.01f;
+ float y = (qSin(R) / R + 0.24f) * 1.61f + 1.2f;
+ (*newRow)[j].setPosition(QVector3D(x, y, z));
+ }
+ dataArray.append(newRow);
+ }
+
+ m_theSeries->dataProxy()->setRows(int(start), dataArray);
+ } else {
+ qDebug() << "Change row function active only for SqrtSin";
+ }
+}
+
+void GraphModifier::changeItem()
+{
+ if (m_activeSample == GraphModifier::SqrtSin) {
+ qDebug() << "Generating new values for an item at random pos";
+ float minX = -10.0f;
+ float maxX = 10.0f;
+ float minZ = -10.0f;
+ float maxZ = 10.0f;
+ float stepX = (maxX - minX) / float(m_xCount - 1);
+ float stepZ = (maxZ - minZ) / float(m_zCount - 1);
+ float i = float(rand() % m_zCount);
+ float j = float(rand() % m_xCount);
+
+ float x = qMin(maxX, (j * stepX + minX));
+ float z = qMin(maxZ, (i * stepZ + minZ));
+ float R = qSqrt(x * x + z * z) + 0.01f;
+ float y = (qSin(R) / R + 0.24f) * 1.61f + 1.2f;
+ QSurfaceDataItem newItem(QVector3D(x, y, z));
+
+ m_theSeries->dataProxy()->setItem(int(i), int(j), newItem);
+ } else {
+ qDebug() << "Change row function active only for SqrtSin";
+ }
+}
+
+void GraphModifier::changeMultipleRows()
+{
+ for (int i = 0; i < 30; i++)
+ changeRow();
+}
+
+void GraphModifier::changeMultipleItem()
+{
+ for (int i = 0; i < 30; i++)
+ changeItem();
+}
+
+void GraphModifier::addRow()
+{
+ if (m_activeSample == GraphModifier::SqrtSin) {
+ qDebug() << "Adding a new row";
+
+ float minX = -10.0f;
+ float maxX = 10.0f;
+ float minZ = -10.0f;
+ float maxZ = 10.0f;
+ float stepX = (maxX - minX) / float(m_xCount - 1);
+ float stepZ = (maxZ - minZ) / float(m_zCount - 1);
+
+ QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount);
+ float z = float(m_addRowCounter) * stepZ + minZ;
+ for (float j = 0; j < m_xCount; j++) {
+ float x = qMin(maxX, (j * stepX + minX));
+ float R = qSqrt(x * x + z * z) + 0.01f;
+ float y = (qSin(R) / R + 0.24f) * 1.61f + 1.0f;
+ (*newRow)[j].setPosition(QVector3D(x, y, z));
+ }
+ m_addRowCounter++;
+
+ m_theSeries->dataProxy()->addRow(newRow);
+ } else {
+ qDebug() << "Change row function active only for SqrtSin";
+ }
+}
+
+void GraphModifier::addRows()
+{
+ if (m_activeSample == GraphModifier::SqrtSin) {
+ qDebug() << "Adding few new row";
+
+ float minX = -10.0f;
+ float maxX = 10.0f;
+ float minZ = -10.0f;
+ float maxZ = 10.0f;
+ float stepX = (maxX - minX) / float(m_xCount - 1);
+ float stepZ = (maxZ - minZ) / float(m_zCount - 1);
+
+ QSurfaceDataArray dataArray;
+
+ for (int i = 0; i < 3; i++) {
+ QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount);
+ float z = m_addRowCounter * stepZ + minZ;
+ for (float j = 0; j < m_xCount; j++) {
+ float x = qMin(maxX, (j * stepX + minX));
+ float R = qSqrt(x * x + z * z) + 0.01f;
+ float y = (qSin(R) / R + 0.24f) * 1.61f + 1.0f;
+ (*newRow)[j].setPosition(QVector3D(x, y, z));
+ }
+ dataArray.append(newRow);
+ m_addRowCounter++;
+ }
+
+ m_theSeries->dataProxy()->addRows(dataArray);
+ } else {
+ qDebug() << "Change row function active only for SqrtSin";
+ }
+}
+
+void GraphModifier::insertRow()
+{
+ if (m_activeSample == GraphModifier::SqrtSin) {
+ qDebug() << "Inserting a row";
+ float minX = -10.0f;
+ float maxX = 10.0f;
+ float minZ = -10.0f;
+ float maxZ = 10.0f;
+ float stepX = (maxX - minX) / float(m_xCount - 1);
+ float stepZ = (maxZ - minZ) / float(m_zCount - 1);
+
+ QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount);
+ float z = qMin(maxZ, (float(m_insertTestZPos) * stepZ + minZ + (stepZ / 2.0f)));
+ for (float j = 0; j < m_xCount; j++) {
+ float x = qMin(maxX, (j * stepX + minX));
+ float R = qSqrt(x * x + z * z) + 0.01f;
+ float y = (qSin(R) / R + 0.24f) * 1.61f + 1.3f;
+ (*newRow)[j].setPosition(QVector3D(x, y, z));
+ }
+ m_insertTestZPos++;
+
+ m_theSeries->dataProxy()->insertRow(m_insertTestIndexPos, newRow);
+ m_insertTestIndexPos += 2;
+ } else {
+ qDebug() << "Change row function active only for SqrtSin";
+ }
+}
+
+void GraphModifier::insertRows()
+{
+ if (m_activeSample == GraphModifier::SqrtSin) {
+ qDebug() << "Inserting 3 rows";
+ float minX = -10.0f;
+ float maxX = 10.0f;
+ float minZ = -10.0f;
+ float maxZ = 10.0f;
+ float stepX = (maxX - minX) / float(m_xCount - 1);
+ float stepZ = (maxZ - minZ) / float(m_zCount - 1);
+
+ QSurfaceDataArray dataArray;
+ for (int i = 0; i < 3; i++) {
+ QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount);
+ float z = qMin(maxZ, (float(m_insertTestZPos) * stepZ + minZ + i * (stepZ / 4.0f)));
+ for (float j = 0; j < m_xCount; j++) {
+ float x = qMin(maxX, (j * stepX + minX));
+ float R = qSqrt(x * x + z * z) + 0.01f;
+ float y = (qSin(R) / R + 0.24f) * 1.61f + 1.3f;
+ (*newRow)[j].setPosition(QVector3D(x, y, z));
+ }
+ dataArray.append(newRow);
+ }
+ m_insertTestZPos++;
+
+ m_theSeries->dataProxy()->insertRows(m_insertTestIndexPos, dataArray);
+ m_insertTestIndexPos += 4;
+ } else {
+ qDebug() << "Change row function active only for SqrtSin";
+ }
+}
+
+void GraphModifier::removeRow()
+{
+ qDebug() << "Remove an arbitrary row";
+ int row = rand() % m_zCount;
+ m_theSeries->dataProxy()->removeRows(row, 1);
+ m_zCount--;
+}
+
+void GraphModifier::changeMesh()
+{
+ static int model = 0;
+ switch (model) {
case 0:
- qDebug() << "QDataVis::SelectionModeNone";
- m_graph->setSelectionMode(QDataVis::SelectionModeNone);
+ m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshCylinder);
+ m_graph->seriesList().at(0)->setMeshSmooth(false);
break;
case 1:
- qDebug() << "QDataVis::SelectionModeItem";
- m_graph->setSelectionMode(QDataVis::SelectionModeItem);
+ m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshCylinder);
+ m_graph->seriesList().at(0)->setMeshSmooth(true);
break;
case 2:
- qDebug() << "QDataVis::SelectionModeSliceRow";
- m_graph->setSelectionMode(QDataVis::SelectionModeSliceRow);
+ m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshCone);
+ m_graph->seriesList().at(0)->setMeshSmooth(false);
break;
case 3:
- qDebug() << "QDataVis::SelectionModeSliceColumn";
- m_graph->setSelectionMode(QDataVis::SelectionModeSliceColumn);
+ m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshCone);
+ m_graph->seriesList().at(0)->setMeshSmooth(true);
break;
- default:
- qDebug() << __FUNCTION__ << " Unsupported selection mode.";
+ case 4:
+ m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshBar);
+ m_graph->seriesList().at(0)->setMeshSmooth(false);
+ break;
+ case 5:
+ m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshBar);
+ m_graph->seriesList().at(0)->setMeshSmooth(true);
+ break;
+ case 6:
+ m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshPyramid);
+ m_graph->seriesList().at(0)->setMeshSmooth(false);
+ break;
+ case 7:
+ m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshPyramid);
+ m_graph->seriesList().at(0)->setMeshSmooth(true);
+ break;
+ case 8:
+ m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshBevelBar);
+ m_graph->seriesList().at(0)->setMeshSmooth(false);
+ break;
+ case 9:
+ m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshBevelBar);
+ m_graph->seriesList().at(0)->setMeshSmooth(true);
break;
}
+ model++;
+ if (model > 9)
+ model = 0;
}
void GraphModifier::updateSamples()
@@ -385,4 +709,3 @@ void GraphModifier::updateSamples()
break;
}
}
-
diff --git a/tests/surfacetest/graphmodifier.h b/tests/surfacetest/graphmodifier.h
index 83b1873b..f0b5cce7 100644
--- a/tests/surfacetest/graphmodifier.h
+++ b/tests/surfacetest/graphmodifier.h
@@ -21,8 +21,10 @@
#include <QtDataVisualization/Q3DSurface>
#include <QtDataVisualization/QSurfaceDataProxy>
+#include <QtDataVisualization/QSurface3DSeries>
#include <QSlider>
#include <QTimer>
+#include <QLabel>
using namespace QtDataVisualization;
@@ -41,6 +43,8 @@ public:
void toggleSmooth(bool enabled);
void toggleSurfaceGrid(bool enable);
+ void toggleSurface(bool enable);
+ void toggleSeriesVisible(bool enable);
void toggleSqrtSin(bool enable);
void togglePlane(bool enable);
void setHeightMapData(bool enable);
@@ -61,16 +65,31 @@ public:
void gradientPressed();
void changeFont(const QFont &font);
void changeStyle();
+ void selectButtonClicked();
+ void setSelectionInfoLabel(QLabel *label) {m_selectionInfoLabel = label; }
+ void selectedPointChanged(const QPoint &point);
+ void changeRow();
+ void changeRows();
+ void changeMesh();
+ void changeItem();
+ void changeMultipleItem();
+ void changeMultipleRows();
+ void addRow();
+ void addRows();
+ void insertRow();
+ void insertRows();
+ void removeRow();
public slots:
void changeShadowQuality(int quality);
void changeTheme(int theme);
+ void flipViews();
void changeSelectionMode(int mode);
void timeout();
private:
- void resetArrayAndSliders(QSurfaceDataArray *array, qreal minZ, qreal maxZ, qreal minX,
- qreal maxX);
+ void resetArrayAndSliders(QSurfaceDataArray *array, float minZ, float maxZ, float minX,
+ float maxX);
Q3DSurface *m_graph;
QSlider *m_gridSliderX;
@@ -84,12 +103,18 @@ private:
int m_zCount;
int m_activeSample;
int m_fontSize;
- qreal m_rangeX;
- qreal m_rangeZ;
- qreal m_minX;
- qreal m_minZ;
+ float m_rangeX;
+ float m_rangeZ;
+ float m_minX;
+ float m_minZ;
+ int m_addRowCounter;
+ int m_insertTestZPos;
+ int m_insertTestIndexPos;
QTimer m_timer;
QSurfaceDataArray *m_planeArray;
+ QLabel *m_selectionInfoLabel;
+ QSurface3DSeries *m_theSeries;
+ QSurface3DSeries::DrawFlags m_drawMode;
};
#endif
diff --git a/tests/surfacetest/main.cpp b/tests/surfacetest/main.cpp
index 19f30e5d..c25c5b89 100644
--- a/tests/surfacetest/main.cpp
+++ b/tests/surfacetest/main.cpp
@@ -17,6 +17,7 @@
****************************************************************************/
#include "graphmodifier.h"
+#include <QtDataVisualization/q3dtheme.h>
#include <QApplication>
#include <QWidget>
@@ -43,13 +44,15 @@ int main(int argc, char *argv[])
QWidget *widget = new QWidget;
QHBoxLayout *hLayout = new QHBoxLayout(widget);
QVBoxLayout *vLayout = new QVBoxLayout();
+ QVBoxLayout *vLayout2 = new QVBoxLayout();
vLayout->setAlignment(Qt::AlignTop);
+ vLayout2->setAlignment(Qt::AlignTop);
Q3DSurface *surfaceGraph = new Q3DSurface();
QSize screenSize = surfaceGraph->screen()->size();
// Set to default, should be same as the initial on themeList
- surfaceGraph->setTheme(QDataVis::Theme(initialTheme));
+ surfaceGraph->setTheme(new Q3DTheme(Q3DTheme::Theme(initialTheme)));
QWidget *container = QWidget::createWindowContainer(surfaceGraph);
container->setMinimumSize(QSize(screenSize.width() / 2, screenSize.height() / 2));
@@ -61,15 +64,24 @@ int main(int argc, char *argv[])
hLayout->addWidget(container, 1);
hLayout->addLayout(vLayout);
+ hLayout->addLayout(vLayout2);
QCheckBox *smoothCB = new QCheckBox(widget);
- smoothCB->setText(QStringLiteral("Smooth "));
- smoothCB->setChecked(surfaceGraph->isSmoothSurfaceEnabled());
+ smoothCB->setText(QStringLiteral("Flat Surface"));
+ smoothCB->setChecked(true);
QCheckBox *surfaceGridCB = new QCheckBox(widget);
surfaceGridCB->setText(QStringLiteral("Surface Grid"));
surfaceGridCB->setChecked(true);
+ QCheckBox *surfaceCB = new QCheckBox(widget);
+ surfaceCB->setText(QStringLiteral("Surface Visible"));
+ surfaceCB->setChecked(true);
+
+ QCheckBox *seriesVisibleCB = new QCheckBox(widget);
+ seriesVisibleCB->setText(QStringLiteral("Series Visible"));
+ seriesVisibleCB->setChecked(true);
+
//QCheckBox *sqrtSinCB = new QCheckBox(widget);
QRadioButton *sqrtSinCB = new QRadioButton(widget);
sqrtSinCB->setText(QStringLiteral("Sqrt & Sin"));
@@ -146,6 +158,9 @@ int main(int argc, char *argv[])
QPushButton *labelButton = new QPushButton(widget);
labelButton->setText(QStringLiteral("Change label style"));
+ QPushButton *meshButton = new QPushButton(widget);
+ meshButton->setText(QStringLiteral("Change pointer mesh"));
+
QComboBox *themeList = new QComboBox(widget);
themeList->addItem(QStringLiteral("Qt"));
themeList->addItem(QStringLiteral("Primary Colors"));
@@ -157,25 +172,86 @@ int main(int argc, char *argv[])
themeList->addItem(QStringLiteral("Isabelle"));
themeList->setCurrentIndex(initialTheme);
-// QComboBox *shadowQuality = new QComboBox(widget);
-// shadowQuality->addItem(QStringLiteral("None"));
-// shadowQuality->addItem(QStringLiteral("Low"));
-// shadowQuality->addItem(QStringLiteral("Medium"));
-// shadowQuality->addItem(QStringLiteral("High"));
-// shadowQuality->addItem(QStringLiteral("Low Soft"));
-// shadowQuality->addItem(QStringLiteral("Medium Soft"));
-// shadowQuality->addItem(QStringLiteral("High Soft"));
-// shadowQuality->setCurrentIndex(3);
+ QComboBox *shadowQuality = new QComboBox(widget);
+ shadowQuality->addItem(QStringLiteral("None"));
+ shadowQuality->addItem(QStringLiteral("Low"));
+ shadowQuality->addItem(QStringLiteral("Medium"));
+ shadowQuality->addItem(QStringLiteral("High"));
+ shadowQuality->addItem(QStringLiteral("Low Soft"));
+ shadowQuality->addItem(QStringLiteral("Medium Soft"));
+ shadowQuality->addItem(QStringLiteral("High Soft"));
+ shadowQuality->setCurrentIndex(3);
+
QComboBox *selectionMode = new QComboBox(widget);
- selectionMode->addItem(QStringLiteral("SelectionModeNone"));
- selectionMode->addItem(QStringLiteral("SelectionModeItem"));
- selectionMode->addItem(QStringLiteral("SelectionModeSliceRow"));
- selectionMode->addItem(QStringLiteral("SelectionModeSliceColumn"));
+ selectionMode->addItem(QStringLiteral("None"),
+ int(QDataVis::SelectionNone));
+ selectionMode->addItem(QStringLiteral("Item"),
+ int(QDataVis::SelectionItem));
+ selectionMode->addItem(QStringLiteral("Row"),
+ int(QDataVis::SelectionRow));
+ selectionMode->addItem(QStringLiteral("Item and Row"),
+ int(QDataVis::SelectionItemAndRow));
+ selectionMode->addItem(QStringLiteral("Column"),
+ int(QDataVis::SelectionColumn));
+ selectionMode->addItem(QStringLiteral("Item and Column"),
+ int(QDataVis::SelectionItemAndColumn));
+ selectionMode->addItem(QStringLiteral("Row and Column"),
+ int(QDataVis::SelectionRowAndColumn));
+ selectionMode->addItem(QStringLiteral("Item, Row and Column"),
+ int(QDataVis::SelectionItemRowAndColumn));
+ selectionMode->addItem(QStringLiteral("Slice into Row"),
+ int(QDataVis::SelectionSlice | QDataVis::SelectionRow));
+ selectionMode->addItem(QStringLiteral("Slice into Row and Item"),
+ int(QDataVis::SelectionSlice | QDataVis::SelectionItemAndRow));
+ selectionMode->addItem(QStringLiteral("Slice into Column"),
+ int(QDataVis::SelectionSlice | QDataVis::SelectionColumn));
+ selectionMode->addItem(QStringLiteral("Slice into Column and Item"),
+ int(QDataVis::SelectionSlice | QDataVis::SelectionItemAndColumn));
selectionMode->setCurrentIndex(1);
+ QPushButton *selectButton = new QPushButton(widget);
+ selectButton->setText(QStringLiteral("Select random point"));
+
+ QPushButton *flipViewsButton = new QPushButton(widget);
+ flipViewsButton->setText(QStringLiteral("Flip Views"));
+
+ QLabel *selectionInfoLabel = new QLabel(widget);
+
+ QPushButton *changeRowButton = new QPushButton(widget);
+ changeRowButton->setText(QStringLiteral("Change a row"));
+
+ QPushButton *changeRowsButton = new QPushButton(widget);
+ changeRowsButton->setText(QStringLiteral("Change 3 rows"));
+
+ QPushButton *changeItemButton = new QPushButton(widget);
+ changeItemButton->setText(QStringLiteral("Change item"));
+
+ QPushButton *changeMultipleItemButton = new QPushButton(widget);
+ changeMultipleItemButton->setText(QStringLiteral("Change many items"));
+
+ QPushButton *changeMultipleRowsButton = new QPushButton(widget);
+ changeMultipleRowsButton->setText(QStringLiteral("Change many rows"));
+
+ QPushButton *addRowButton = new QPushButton(widget);
+ addRowButton->setText(QStringLiteral("Add a row"));
+
+ QPushButton *addRowsButton = new QPushButton(widget);
+ addRowsButton->setText(QStringLiteral("Add 3 rows"));
+
+ QPushButton *insertRowButton = new QPushButton(widget);
+ insertRowButton->setText(QStringLiteral("Insert a row"));
+
+ QPushButton *insertRowsButton = new QPushButton(widget);
+ insertRowsButton->setText(QStringLiteral("Insert 3 rows"));
+
+ QPushButton *removeRowButton = new QPushButton(widget);
+ removeRowButton->setText(QStringLiteral("Remove a row"));
+
// Add controls to the layout
vLayout->addWidget(smoothCB);
vLayout->addWidget(surfaceGridCB);
+ vLayout->addWidget(surfaceCB);
+ vLayout->addWidget(seriesVisibleCB);
vLayout->addWidget(new QLabel(QStringLiteral("Select surface sample")));
vLayout->addWidget(sqrtSinCB);
vLayout->addWidget(planeCB);
@@ -194,12 +270,27 @@ int main(int argc, char *argv[])
vLayout->addWidget(new QLabel(QStringLiteral("Change font")));
vLayout->addWidget(fontList);
vLayout->addWidget(labelButton);
+ vLayout->addWidget(meshButton);
vLayout->addWidget(new QLabel(QStringLiteral("Change theme")));
vLayout->addWidget(themeList);
-// vLayout->addWidget(new QLabel(QStringLiteral("Adjust shadow quality")));
-// vLayout->addWidget(shadowQuality);
+ vLayout->addWidget(new QLabel(QStringLiteral("Adjust shadow quality")));
+ vLayout->addWidget(shadowQuality);
vLayout->addWidget(new QLabel(QStringLiteral("Selection Mode")));
vLayout->addWidget(selectionMode);
+ vLayout->addWidget(selectButton);
+ vLayout->addWidget(selectionInfoLabel);
+ vLayout->addWidget(flipViewsButton);
+
+ vLayout2->addWidget(changeRowButton);
+ vLayout2->addWidget(changeRowsButton);
+ vLayout2->addWidget(changeMultipleRowsButton);
+ vLayout2->addWidget(changeItemButton);
+ vLayout2->addWidget(changeMultipleItemButton);
+ vLayout2->addWidget(addRowButton);
+ vLayout2->addWidget(addRowsButton);
+ vLayout2->addWidget(insertRowButton);
+ vLayout2->addWidget(insertRowsButton);
+ vLayout2->addWidget(removeRowButton);
widget->show();
@@ -210,6 +301,10 @@ int main(int argc, char *argv[])
modifier, &GraphModifier::toggleSmooth);
QObject::connect(surfaceGridCB, &QCheckBox::stateChanged,
modifier, &GraphModifier::toggleSurfaceGrid);
+ QObject::connect(surfaceCB, &QCheckBox::stateChanged,
+ modifier, &GraphModifier::toggleSurface);
+ QObject::connect(seriesVisibleCB, &QCheckBox::stateChanged,
+ modifier, &GraphModifier::toggleSeriesVisible);
QObject::connect(sqrtSinCB, &QRadioButton::toggled,
modifier, &GraphModifier::toggleSqrtSin);
QObject::connect(planeCB, &QCheckBox::toggled,
@@ -236,12 +331,38 @@ int main(int argc, char *argv[])
modifier, &GraphModifier::changeFont);
QObject::connect(labelButton, &QPushButton::clicked,
modifier, &GraphModifier::changeStyle);
+ QObject::connect(meshButton, &QPushButton::clicked,
+ modifier, &GraphModifier::changeMesh);
QObject::connect(themeList, SIGNAL(currentIndexChanged(int)),
modifier, SLOT(changeTheme(int)));
-// QObject::connect(shadowQuality, SIGNAL(currentIndexChanged(int)),
-// modifier, SLOT(changeShadowQuality(int)));
+ QObject::connect(shadowQuality, SIGNAL(currentIndexChanged(int)),
+ modifier, SLOT(changeShadowQuality(int)));
QObject::connect(selectionMode, SIGNAL(currentIndexChanged(int)),
modifier, SLOT(changeSelectionMode(int)));
+ QObject::connect(selectButton, &QPushButton::clicked,
+ modifier, &GraphModifier::selectButtonClicked);
+ QObject::connect(flipViewsButton, &QPushButton::clicked,
+ modifier, &GraphModifier::flipViews);
+ QObject::connect(changeRowButton,&QPushButton::clicked,
+ modifier, &GraphModifier::changeRow);
+ QObject::connect(changeRowsButton,&QPushButton::clicked,
+ modifier, &GraphModifier::changeRows);
+ QObject::connect(changeItemButton,&QPushButton::clicked,
+ modifier, &GraphModifier::changeItem);
+ QObject::connect(changeMultipleItemButton,&QPushButton::clicked,
+ modifier, &GraphModifier::changeMultipleItem);
+ QObject::connect(changeMultipleRowsButton,&QPushButton::clicked,
+ modifier, &GraphModifier::changeMultipleRows);
+ QObject::connect(addRowButton,&QPushButton::clicked,
+ modifier, &GraphModifier::addRow);
+ QObject::connect(addRowsButton,&QPushButton::clicked,
+ modifier, &GraphModifier::addRows);
+ QObject::connect(insertRowButton,&QPushButton::clicked,
+ modifier, &GraphModifier::insertRow);
+ QObject::connect(insertRowsButton,&QPushButton::clicked,
+ modifier, &GraphModifier::insertRows);
+ QObject::connect(removeRowButton,&QPushButton::clicked,
+ modifier, &GraphModifier::removeRow);
modifier->setGridSliderZ(gridSliderZ);
modifier->setGridSliderX(gridSliderX);
@@ -250,7 +371,9 @@ int main(int argc, char *argv[])
modifier->setAxisMinSliderX(axisMinSliderX);
modifier->setAxisMinSliderZ(axisMinSliderZ);
modifier->toggleGridSliderLock(gridSlidersLockCB->checkState());
+ modifier->setSelectionInfoLabel(selectionInfoLabel);
sqrtSinCB->setChecked(true);
+ shadowQuality->setCurrentIndex(3);
return app.exec();
}
diff --git a/tests/tests.pri b/tests/tests.pri
index 04115f06..fd17b360 100644
--- a/tests/tests.pri
+++ b/tests/tests.pri
@@ -11,6 +11,8 @@ win32 {
DESTDIR = $$OUT_PWD
}
+INCLUDEPATH += ../../include
+
LIBS += -L$$OUT_PWD/../../lib
TEMPLATE = app
diff --git a/tests/tests.pro b/tests/tests.pro
index 3fe3edb8..01b0f109 100644
--- a/tests/tests.pro
+++ b/tests/tests.pro
@@ -10,8 +10,16 @@ TEMPLATE = subdirs
SUBDIRS += barstest \
scattertest \
surfacetest \
- qmlcamera
+ qmlcamera \
+ qmldynamicdata \
+ multigraphs
#SUBDIRS += kinectsurface
qtHaveModule(multimedia):!android: SUBDIRS += spectrum
+
+# For testing code snippets of minimal applications
+SUBDIRS += minimalbars \
+ minimalscatter \
+ minimalsurface
+
diff --git a/tools/generate_package_linux.sh b/tools/generate_package_linux.sh
index 97aff841..134a59c3 100755
--- a/tools/generate_package_linux.sh
+++ b/tools/generate_package_linux.sh
@@ -21,11 +21,11 @@ fi
DATAVIS_VERSION=$1
DATAVIS_CURRENT_DIR=$PWD
DATAVIS_BUILD_DIR=$DATAVIS_TEMP_DIR_FULL/tempbuild
-DATAVIS_PACKAGE_UNTAR_NAME=qtdatavisualization_$DATAVIS_VERSION
+DATAVIS_PACKAGE_UNTAR_NAME=qt-data-visualization-enterprise-src-$DATAVIS_VERSION
DATAVIS_PACKAGE_UNTAR_DIR=$DATAVIS_TEMP_DIR_FULL/$DATAVIS_PACKAGE_UNTAR_NAME
DATAVIS_TEMP_TAR=qtdatavisualization_temp_$DATAVIS_VERSION.tar
DATAVIS_TEMP_TAR_FULL=$DATAVIS_TEMP_DIR_FULL/$DATAVIS_TEMP_TAR
-DATAVIS_FINAL_TAR=$DATAVIS_CURRENT_DIR/../qtdatavisualization_$DATAVIS_VERSION.tar
+DATAVIS_FINAL_TAR=$DATAVIS_CURRENT_DIR/../qt-data-visualization-enterprise-src-$DATAVIS_VERSION.tar
echo Exporting $DATAVIS_BRANCH to $DATAVIS_TEMP_TAR_FULL...
rm -r -f $DATAVIS_TEMP_DIR_FULL 2> /dev/null
diff --git a/tools/generate_package_win.cmd b/tools/generate_package_win.cmd
index a1046f6b..f3647c49 100644
--- a/tools/generate_package_win.cmd
+++ b/tools/generate_package_win.cmd
@@ -20,12 +20,13 @@ if "%2"=="" (
)
set DATAVIS_VERSION=%1
+set DATAVIS_PACKAGE_NAME=qt-data-visualization-enterprise-src-%DATAVIS_VERSION%
set DATAVIS_BUILD_DIR=%DATAVIS_TEMP_DIR_FULL%\tempbuild
-set DATAVIS_PACKAGE_UNZIP_DIR=%DATAVIS_TEMP_DIR_FULL%\qtdatavisualization_%DATAVIS_VERSION%
+set DATAVIS_PACKAGE_UNZIP_DIR=%DATAVIS_TEMP_DIR_FULL%\%DATAVIS_PACKAGE_NAME%
set DATAVIS_TEMP_ZIP=qtdatavisualization_temp_%DATAVIS_VERSION%.zip
set DATAVIS_TEMP_ZIP_FULL=%DATAVIS_TEMP_DIR_FULL%\%DATAVIS_TEMP_ZIP%
set DATAVIS_XCOPY_CMD=xcopy /s /i /q
-set DATAVIS_FINAL_ZIP=..\qtdatavisualization_%DATAVIS_VERSION%.zip
+set DATAVIS_FINAL_ZIP=..\%DATAVIS_PACKAGE_NAME%.zip
echo Exporting %DATAVIS_BRANCH% to %DATAVIS_TEMP_ZIP_FULL%...
rmdir /q /s %DATAVIS_TEMP_DIR_FULL% 2> NUL