summaryrefslogtreecommitdiffstats
path: root/src/charts
diff options
context:
space:
mode:
authorTitta Heikkala <titta.heikkala@digia.com>2014-07-01 07:10:00 +0300
committerTitta Heikkala <titta.heikkala@theqtcompany.com>2014-10-14 13:04:52 +0300
commitc544258484ff4fd5d2b88402fbaa5d154b89a3a2 (patch)
tree7659625abb566dec55d3783ed820b928542d9b2b /src/charts
parent76339f714f088645e911cee65bdb66055fe029aa (diff)
Qt Charts project file structure change
Charts repository structure is changed to follow the structure of a Qt Add-On module. The task includes following changes: - All macros and definitions named 'commercial' have been renamed. - Compile errors related to QString and qSort usage have been fixed. - Old demos are moved under examples. The QML examples now support only Qt Quick 2.0, the support for Qt Quick 1 is removed. - The QML examples with multiple views are updated so that they are usable also with touch devices. - Unnecessary version checks are removed from examples. - The build stamp has been removed as it was only meant for Charts development purposes and it's no longer needed. Also development build related debug prints are removed as __DATE__ can't be used for all OS thus it doesn't make much sense. - Documentation structure has been updated based on the new module structure. The raw HTML files have been removed. Demos are combined to examples. - Unnecessary .qdocinc files are no longer needed. The content is moved to the corresponding .cpp files. - The Charts widget designer plugin is updated according to the module change. - The test cases updated according to the project structure change. Tests are added also for version 2.0. - cmake modules generation is not needed with Qt 5.4 and Qt Charts so it's disabled. - The new module name and version are updated to the plugin.qmltypes file. Task-number: QTRD-2844, QTRD-3217, QTRD-3218, QTRD-3277, QTRD-3228, QTRD-2526, QTRD-3233, QTRD-3222 Change-Id: Ib7fb26057cde710ffaf6bc780c8bf52a16f45160 Reviewed-by: Miikka Heikkinen <miikka.heikkinen@theqtcompany.com>
Diffstat (limited to 'src/charts')
-rw-r--r--src/charts/animations/animations.pri26
-rw-r--r--src/charts/animations/axisanimation.cpp135
-rw-r--r--src/charts/animations/axisanimation_p.h62
-rw-r--r--src/charts/animations/baranimation.cpp82
-rw-r--r--src/charts/animations/baranimation_p.h59
-rw-r--r--src/charts/animations/boxplotanimation.cpp97
-rw-r--r--src/charts/animations/boxplotanimation_p.h64
-rw-r--r--src/charts/animations/boxwhiskersanimation.cpp110
-rw-r--r--src/charts/animations/boxwhiskersanimation_p.h69
-rw-r--r--src/charts/animations/chartanimation.cpp46
-rw-r--r--src/charts/animations/chartanimation_p.h57
-rw-r--r--src/charts/animations/pieanimation.cpp110
-rw-r--r--src/charts/animations/pieanimation_p.h62
-rw-r--r--src/charts/animations/piesliceanimation.cpp128
-rw-r--r--src/charts/animations/piesliceanimation_p.h60
-rw-r--r--src/charts/animations/scatteranimation.cpp50
-rw-r--r--src/charts/animations/scatteranimation_p.h50
-rw-r--r--src/charts/animations/splineanimation.cpp210
-rw-r--r--src/charts/animations/splineanimation_p.h62
-rw-r--r--src/charts/animations/xyanimation.cpp155
-rw-r--r--src/charts/animations/xyanimation_p.h67
-rw-r--r--src/charts/areachart/areachart.pri13
-rw-r--r--src/charts/areachart/areachartitem.cpp262
-rw-r--r--src/charts/areachart/areachartitem_p.h123
-rw-r--r--src/charts/areachart/qareaseries.cpp657
-rw-r--r--src/charts/areachart/qareaseries.h106
-rw-r--r--src/charts/areachart/qareaseries_p.h76
-rw-r--r--src/charts/axis/axis.pri108
-rw-r--r--src/charts/axis/barcategoryaxis/chartbarcategoryaxisx.cpp140
-rw-r--r--src/charts/axis/barcategoryaxis/chartbarcategoryaxisx_p.h62
-rw-r--r--src/charts/axis/barcategoryaxis/chartbarcategoryaxisy.cpp142
-rw-r--r--src/charts/axis/barcategoryaxis/chartbarcategoryaxisy_p.h61
-rw-r--r--src/charts/axis/barcategoryaxis/qbarcategoryaxis.cpp620
-rw-r--r--src/charts/axis/barcategoryaxis/qbarcategoryaxis.h81
-rw-r--r--src/charts/axis/barcategoryaxis/qbarcategoryaxis_p.h81
-rw-r--r--src/charts/axis/cartesianchartaxis.cpp198
-rw-r--r--src/charts/axis/cartesianchartaxis_p.h79
-rw-r--r--src/charts/axis/categoryaxis/chartcategoryaxisx.cpp119
-rw-r--r--src/charts/axis/categoryaxis/chartcategoryaxisx_p.h61
-rw-r--r--src/charts/axis/categoryaxis/chartcategoryaxisy.cpp119
-rw-r--r--src/charts/axis/categoryaxis/chartcategoryaxisy_p.h61
-rw-r--r--src/charts/axis/categoryaxis/polarchartcategoryaxisangular.cpp80
-rw-r--r--src/charts/axis/categoryaxis/polarchartcategoryaxisangular_p.h56
-rw-r--r--src/charts/axis/categoryaxis/polarchartcategoryaxisradial.cpp79
-rw-r--r--src/charts/axis/categoryaxis/polarchartcategoryaxisradial_p.h56
-rw-r--r--src/charts/axis/categoryaxis/qcategoryaxis.cpp345
-rw-r--r--src/charts/axis/categoryaxis/qcategoryaxis.h70
-rw-r--r--src/charts/axis/categoryaxis/qcategoryaxis_p.h62
-rw-r--r--src/charts/axis/chartaxiselement.cpp404
-rw-r--r--src/charts/axis/chartaxiselement_p.h155
-rw-r--r--src/charts/axis/datetimeaxis/chartdatetimeaxisx.cpp133
-rw-r--r--src/charts/axis/datetimeaxis/chartdatetimeaxisx_p.h60
-rw-r--r--src/charts/axis/datetimeaxis/chartdatetimeaxisy.cpp134
-rw-r--r--src/charts/axis/datetimeaxis/chartdatetimeaxisy_p.h60
-rw-r--r--src/charts/axis/datetimeaxis/polarchartdatetimeaxisangular.cpp80
-rw-r--r--src/charts/axis/datetimeaxis/polarchartdatetimeaxisangular_p.h56
-rw-r--r--src/charts/axis/datetimeaxis/polarchartdatetimeaxisradial.cpp79
-rw-r--r--src/charts/axis/datetimeaxis/polarchartdatetimeaxisradial_p.h56
-rw-r--r--src/charts/axis/datetimeaxis/qdatetimeaxis.cpp390
-rw-r--r--src/charts/axis/datetimeaxis/qdatetimeaxis.h78
-rw-r--r--src/charts/axis/datetimeaxis/qdatetimeaxis_p.h73
-rw-r--r--src/charts/axis/horizontalaxis.cpp227
-rw-r--r--src/charts/axis/horizontalaxis_p.h50
-rw-r--r--src/charts/axis/linearrowitem_p.h76
-rw-r--r--src/charts/axis/logvalueaxis/chartlogvalueaxisx.cpp139
-rw-r--r--src/charts/axis/logvalueaxis/chartlogvalueaxisx_p.h63
-rw-r--r--src/charts/axis/logvalueaxis/chartlogvalueaxisy.cpp139
-rw-r--r--src/charts/axis/logvalueaxis/chartlogvalueaxisy_p.h63
-rw-r--r--src/charts/axis/logvalueaxis/polarchartlogvalueaxisangular.cpp90
-rw-r--r--src/charts/axis/logvalueaxis/polarchartlogvalueaxisangular_p.h57
-rw-r--r--src/charts/axis/logvalueaxis/polarchartlogvalueaxisradial.cpp95
-rw-r--r--src/charts/axis/logvalueaxis/polarchartlogvalueaxisradial_p.h57
-rw-r--r--src/charts/axis/logvalueaxis/qlogvalueaxis.cpp400
-rw-r--r--src/charts/axis/logvalueaxis/qlogvalueaxis.h77
-rw-r--r--src/charts/axis/logvalueaxis/qlogvalueaxis_p.h69
-rw-r--r--src/charts/axis/polarchartaxis.cpp126
-rw-r--r--src/charts/axis/polarchartaxis_p.h70
-rw-r--r--src/charts/axis/polarchartaxisangular.cpp433
-rw-r--r--src/charts/axis/polarchartaxisangular_p.h63
-rw-r--r--src/charts/axis/polarchartaxisradial.cpp297
-rw-r--r--src/charts/axis/polarchartaxisradial_p.h60
-rw-r--r--src/charts/axis/qabstractaxis.cpp1012
-rw-r--r--src/charts/axis/qabstractaxis.h193
-rw-r--r--src/charts/axis/qabstractaxis_p.h130
-rw-r--r--src/charts/axis/valueaxis/chartvalueaxisx.cpp130
-rw-r--r--src/charts/axis/valueaxis/chartvalueaxisx_p.h60
-rw-r--r--src/charts/axis/valueaxis/chartvalueaxisy.cpp130
-rw-r--r--src/charts/axis/valueaxis/chartvalueaxisy_p.h60
-rw-r--r--src/charts/axis/valueaxis/polarchartvalueaxisangular.cpp80
-rw-r--r--src/charts/axis/valueaxis/polarchartvalueaxisangular_p.h56
-rw-r--r--src/charts/axis/valueaxis/polarchartvalueaxisradial.cpp79
-rw-r--r--src/charts/axis/valueaxis/polarchartvalueaxisradial_p.h56
-rw-r--r--src/charts/axis/valueaxis/qvalueaxis.cpp459
-rw-r--r--src/charts/axis/valueaxis/qvalueaxis.h83
-rw-r--r--src/charts/axis/valueaxis/qvalueaxis_p.h70
-rw-r--r--src/charts/axis/verticalaxis.cpp231
-rw-r--r--src/charts/axis/verticalaxis_p.h50
-rw-r--r--src/charts/barchart/abstractbarchartitem.cpp268
-rw-r--r--src/charts/barchart/abstractbarchartitem_p.h96
-rw-r--r--src/charts/barchart/bar.cpp71
-rw-r--r--src/charts/barchart/bar_p.h66
-rw-r--r--src/charts/barchart/barchart.pri71
-rw-r--r--src/charts/barchart/horizontal/bar/horizontalbarchartitem.cpp94
-rw-r--r--src/charts/barchart/horizontal/bar/horizontalbarchartitem_p.h51
-rw-r--r--src/charts/barchart/horizontal/bar/qhorizontalbarseries.cpp126
-rw-r--r--src/charts/barchart/horizontal/bar/qhorizontalbarseries.h45
-rw-r--r--src/charts/barchart/horizontal/bar/qhorizontalbarseries_p.h50
-rw-r--r--src/charts/barchart/horizontal/percent/horizontalpercentbarchartitem.cpp140
-rw-r--r--src/charts/barchart/horizontal/percent/horizontalpercentbarchartitem_p.h52
-rw-r--r--src/charts/barchart/horizontal/percent/qhorizontalpercentbarseries.cpp125
-rw-r--r--src/charts/barchart/horizontal/percent/qhorizontalpercentbarseries.h45
-rw-r--r--src/charts/barchart/horizontal/percent/qhorizontalpercentbarseries_p.h50
-rw-r--r--src/charts/barchart/horizontal/stacked/horizontalstackedbarchartitem.cpp107
-rw-r--r--src/charts/barchart/horizontal/stacked/horizontalstackedbarchartitem_p.h51
-rw-r--r--src/charts/barchart/horizontal/stacked/qhorizontalstackedbarseries.cpp121
-rw-r--r--src/charts/barchart/horizontal/stacked/qhorizontalstackedbarseries.h45
-rw-r--r--src/charts/barchart/horizontal/stacked/qhorizontalstackedbarseries_p.h50
-rw-r--r--src/charts/barchart/qabstractbarseries.cpp1030
-rw-r--r--src/charts/barchart/qabstractbarseries.h105
-rw-r--r--src/charts/barchart/qabstractbarseries_p.h118
-rw-r--r--src/charts/barchart/qbarmodelmapper.cpp561
-rw-r--r--src/charts/barchart/qbarmodelmapper.h69
-rw-r--r--src/charts/barchart/qbarmodelmapper_p.h96
-rw-r--r--src/charts/barchart/qbarset.cpp676
-rw-r--r--src/charts/barchart/qbarset.h120
-rw-r--r--src/charts/barchart/qbarset_p.h82
-rw-r--r--src/charts/barchart/qhbarmodelmapper.cpp258
-rw-r--r--src/charts/barchart/qhbarmodelmapper.h70
-rw-r--r--src/charts/barchart/qvbarmodelmapper.cpp258
-rw-r--r--src/charts/barchart/qvbarmodelmapper.h70
-rw-r--r--src/charts/barchart/vertical/bar/barchartitem.cpp125
-rw-r--r--src/charts/barchart/vertical/bar/barchartitem_p.h57
-rw-r--r--src/charts/barchart/vertical/bar/qbarseries.cpp125
-rw-r--r--src/charts/barchart/vertical/bar/qbarseries.h45
-rw-r--r--src/charts/barchart/vertical/bar/qbarseries_p.h52
-rw-r--r--src/charts/barchart/vertical/percent/percentbarchartitem.cpp171
-rw-r--r--src/charts/barchart/vertical/percent/percentbarchartitem_p.h59
-rw-r--r--src/charts/barchart/vertical/percent/qpercentbarseries.cpp126
-rw-r--r--src/charts/barchart/vertical/percent/qpercentbarseries.h46
-rw-r--r--src/charts/barchart/vertical/percent/qpercentbarseries_p.h51
-rw-r--r--src/charts/barchart/vertical/stacked/qstackedbarseries.cpp123
-rw-r--r--src/charts/barchart/vertical/stacked/qstackedbarseries.h46
-rw-r--r--src/charts/barchart/vertical/stacked/qstackedbarseries_p.h51
-rw-r--r--src/charts/barchart/vertical/stacked/stackedbarchartitem.cpp137
-rw-r--r--src/charts/barchart/vertical/stacked/stackedbarchartitem_p.h58
-rw-r--r--src/charts/boxplotchart/boxplotchart.pri25
-rw-r--r--src/charts/boxplotchart/boxplotchartitem.cpp215
-rw-r--r--src/charts/boxplotchart/boxplotchartitem_p.h84
-rw-r--r--src/charts/boxplotchart/boxwhiskers.cpp194
-rw-r--r--src/charts/boxplotchart/boxwhiskers_p.h102
-rw-r--r--src/charts/boxplotchart/boxwhiskersdata_p.h80
-rw-r--r--src/charts/boxplotchart/qboxplotmodelmapper.cpp489
-rw-r--r--src/charts/boxplotchart/qboxplotmodelmapper.h69
-rw-r--r--src/charts/boxplotchart/qboxplotmodelmapper_p.h93
-rw-r--r--src/charts/boxplotchart/qboxplotseries.cpp690
-rw-r--r--src/charts/boxplotchart/qboxplotseries.h85
-rw-r--r--src/charts/boxplotchart/qboxplotseries_p.h100
-rw-r--r--src/charts/boxplotchart/qboxset.cpp336
-rw-r--r--src/charts/boxplotchart/qboxset.h94
-rw-r--r--src/charts/boxplotchart/qboxset_p.h84
-rw-r--r--src/charts/boxplotchart/qvboxplotmodelmapper.cpp257
-rw-r--r--src/charts/boxplotchart/qvboxplotmodelmapper.h70
-rw-r--r--src/charts/chartbackground.cpp91
-rw-r--r--src/charts/chartbackground_p.h62
-rw-r--r--src/charts/chartconfig_p.h60
-rw-r--r--src/charts/chartdataset.cpp639
-rw-r--r--src/charts/chartdataset_p.h94
-rw-r--r--src/charts/chartelement.cpp55
-rw-r--r--src/charts/chartelement_p.h65
-rw-r--r--src/charts/charthelpers_p.h55
-rw-r--r--src/charts/chartitem.cpp47
-rw-r--r--src/charts/chartitem_p.h57
-rw-r--r--src/charts/chartpresenter.cpp508
-rw-r--r--src/charts/chartpresenter_p.h192
-rw-r--r--src/charts/charts.pro82
-rw-r--r--src/charts/chartsnamespace.h28
-rw-r--r--src/charts/chartthememanager.cpp249
-rw-r--r--src/charts/chartthememanager_p.h84
-rw-r--r--src/charts/charttitle.cpp91
-rw-r--r--src/charts/charttitle_p.h53
-rw-r--r--src/charts/common.pri15
-rw-r--r--src/charts/doc/images/api_category_axis.pngbin0 -> 6793 bytes
-rw-r--r--src/charts/doc/images/api_datatime_axis.pngbin0 -> 78372 bytes
-rw-r--r--src/charts/doc/images/arrow_down.pngbin0 -> 177 bytes
-rw-r--r--src/charts/doc/images/bg.pngbin0 -> 372 bytes
-rw-r--r--src/charts/doc/images/breadcrumb.pngbin0 -> 134 bytes
-rw-r--r--src/charts/doc/images/bullet_dn.pngbin0 -> 230 bytes
-rw-r--r--src/charts/doc/images/bullet_gt.pngbin0 -> 124 bytes
-rw-r--r--src/charts/doc/images/bullet_sq.pngbin0 -> 74 bytes
-rw-r--r--src/charts/doc/images/bullet_up.pngbin0 -> 210 bytes
-rw-r--r--src/charts/doc/images/digia_logo.pngbin0 -> 690 bytes
-rw-r--r--src/charts/doc/images/examples_areachart.pngbin0 -> 41332 bytes
-rw-r--r--src/charts/doc/images/examples_audio.pngbin0 -> 49452 bytes
-rw-r--r--src/charts/doc/images/examples_barchart.pngbin0 -> 31448 bytes
-rw-r--r--src/charts/doc/images/examples_barmodelmapper.pngbin0 -> 91629 bytes
-rw-r--r--src/charts/doc/images/examples_boxplotchart.pngbin0 -> 69135 bytes
-rw-r--r--src/charts/doc/images/examples_callout.pngbin0 -> 79984 bytes
-rw-r--r--src/charts/doc/images/examples_chartthemes_blue_cerulean.pngbin0 -> 129218 bytes
-rw-r--r--src/charts/doc/images/examples_chartthemes_brown_sand.pngbin0 -> 112797 bytes
-rw-r--r--src/charts/doc/images/examples_chartthemes_light.pngbin0 -> 108482 bytes
-rw-r--r--src/charts/doc/images/examples_customchart.pngbin0 -> 30554 bytes
-rw-r--r--src/charts/doc/images/examples_datetimeaxis.pngbin0 -> 75267 bytes
-rw-r--r--src/charts/doc/images/examples_donutbreakdown.pngbin0 -> 92062 bytes
-rw-r--r--src/charts/doc/images/examples_donutchart.pngbin0 -> 47040 bytes
-rw-r--r--src/charts/doc/images/examples_dynamicspline1.pngbin0 -> 34292 bytes
-rw-r--r--src/charts/doc/images/examples_dynamicspline2.pngbin0 -> 40347 bytes
-rw-r--r--src/charts/doc/images/examples_horizontalbarchart.pngbin0 -> 42261 bytes
-rw-r--r--src/charts/doc/images/examples_horizontalpercentbarchart.pngbin0 -> 39993 bytes
-rw-r--r--src/charts/doc/images/examples_horizontalstackedbarchart.pngbin0 -> 40940 bytes
-rw-r--r--src/charts/doc/images/examples_legend_detach.pngbin0 -> 61273 bytes
-rw-r--r--src/charts/doc/images/examples_legend_detach2.pngbin0 -> 75296 bytes
-rw-r--r--src/charts/doc/images/examples_legendmarkers.pngbin0 -> 65162 bytes
-rw-r--r--src/charts/doc/images/examples_lineandbar.pngbin0 -> 48731 bytes
-rw-r--r--src/charts/doc/images/examples_linechart.pngbin0 -> 41188 bytes
-rw-r--r--src/charts/doc/images/examples_logvalueaxis.pngbin0 -> 43823 bytes
-rw-r--r--src/charts/doc/images/examples_modeldata.pngbin0 -> 122670 bytes
-rw-r--r--src/charts/doc/images/examples_multiaxis.pngbin0 -> 91649 bytes
-rw-r--r--src/charts/doc/images/examples_nesteddonuts.pngbin0 -> 99909 bytes
-rw-r--r--src/charts/doc/images/examples_percentbarchart.pngbin0 -> 41041 bytes
-rw-r--r--src/charts/doc/images/examples_percentbarchart_legend.pngbin0 -> 66859 bytes
-rw-r--r--src/charts/doc/images/examples_piechart.pngbin0 -> 37613 bytes
-rw-r--r--src/charts/doc/images/examples_piechartdrill1.pngbin0 -> 48580 bytes
-rw-r--r--src/charts/doc/images/examples_piechartdrill2.pngbin0 -> 59468 bytes
-rw-r--r--src/charts/doc/images/examples_polarchart.pngbin0 -> 144425 bytes
-rw-r--r--src/charts/doc/images/examples_qmlaxes1.pngbin0 -> 43753 bytes
-rw-r--r--src/charts/doc/images/examples_qmlaxes2.pngbin0 -> 40033 bytes
-rw-r--r--src/charts/doc/images/examples_qmlaxes3.pngbin0 -> 35051 bytes
-rw-r--r--src/charts/doc/images/examples_qmlboxplot.pngbin0 -> 38202 bytes
-rw-r--r--src/charts/doc/images/examples_qmlchart1.pngbin0 -> 41391 bytes
-rw-r--r--src/charts/doc/images/examples_qmlchart10.pngbin0 -> 38626 bytes
-rw-r--r--src/charts/doc/images/examples_qmlchart11.pngbin0 -> 37772 bytes
-rw-r--r--src/charts/doc/images/examples_qmlchart12.pngbin0 -> 74409 bytes
-rw-r--r--src/charts/doc/images/examples_qmlchart2.pngbin0 -> 37390 bytes
-rw-r--r--src/charts/doc/images/examples_qmlchart3.pngbin0 -> 39135 bytes
-rw-r--r--src/charts/doc/images/examples_qmlchart4.pngbin0 -> 51563 bytes
-rw-r--r--src/charts/doc/images/examples_qmlchart5.pngbin0 -> 37997 bytes
-rw-r--r--src/charts/doc/images/examples_qmlchart6.pngbin0 -> 20283 bytes
-rw-r--r--src/charts/doc/images/examples_qmlchart7.pngbin0 -> 37926 bytes
-rw-r--r--src/charts/doc/images/examples_qmlchart8.pngbin0 -> 37293 bytes
-rw-r--r--src/charts/doc/images/examples_qmlchart9.pngbin0 -> 37972 bytes
-rw-r--r--src/charts/doc/images/examples_qmlcustomizations.pngbin0 -> 38735 bytes
-rw-r--r--src/charts/doc/images/examples_qmlcustomlegend1.pngbin0 -> 53458 bytes
-rw-r--r--src/charts/doc/images/examples_qmlcustomlegend2.pngbin0 -> 55307 bytes
-rw-r--r--src/charts/doc/images/examples_qmlcustomlegend3.pngbin0 -> 43897 bytes
-rw-r--r--src/charts/doc/images/examples_qmlcustommodel.pngbin0 -> 49142 bytes
-rw-r--r--src/charts/doc/images/examples_qmlf1legends.pngbin0 -> 48312 bytes
-rw-r--r--src/charts/doc/images/examples_qmloscilloscope.pngbin0 -> 56377 bytes
-rw-r--r--src/charts/doc/images/examples_qmlpiechart.pngbin0 -> 32704 bytes
-rw-r--r--src/charts/doc/images/examples_qmlpolarchart1.pngbin0 -> 95929 bytes
-rw-r--r--src/charts/doc/images/examples_qmlpolarchart2.pngbin0 -> 108429 bytes
-rw-r--r--src/charts/doc/images/examples_qmlpolarchart3.pngbin0 -> 90823 bytes
-rw-r--r--src/charts/doc/images/examples_qmlweather.pngbin0 -> 64793 bytes
-rw-r--r--src/charts/doc/images/examples_scatterchart.pngbin0 -> 30702 bytes
-rw-r--r--src/charts/doc/images/examples_scatterinteractions.pngbin0 -> 41609 bytes
-rw-r--r--src/charts/doc/images/examples_splinechart.pngbin0 -> 41052 bytes
-rw-r--r--src/charts/doc/images/examples_stackedbarchart.pngbin0 -> 40699 bytes
-rw-r--r--src/charts/doc/images/examples_stackedbarchartdrilldown1.pngbin0 -> 39237 bytes
-rw-r--r--src/charts/doc/images/examples_stackedbarchartdrilldown2.pngbin0 -> 37845 bytes
-rw-r--r--src/charts/doc/images/examples_temperaturerecords.pngbin0 -> 38760 bytes
-rw-r--r--src/charts/doc/images/examples_zoomlinechart1.pngbin0 -> 50892 bytes
-rw-r--r--src/charts/doc/images/examples_zoomlinechart2.pngbin0 -> 40448 bytes
-rw-r--r--src/charts/doc/images/horBar.pngbin0 -> 2807 bytes
-rw-r--r--src/charts/doc/images/piechart_customization.pngbin0 -> 132696 bytes
-rw-r--r--src/charts/doc/images/qcharts.pngbin0 -> 5582 bytes
-rw-r--r--src/charts/doc/images/qt-logo.pngbin0 -> 5149 bytes
-rw-r--r--src/charts/doc/qtcharts.qdocconf66
-rw-r--r--src/charts/doc/snippets/doc_src_qmlcharts.cpp21
-rw-r--r--src/charts/doc/snippets/doc_src_qtcharts.cpp35
-rw-r--r--src/charts/doc/snippets/doc_src_qtcharts.pro21
-rw-r--r--src/charts/doc/src/examples-areachart.qdoc30
-rw-r--r--src/charts/doc/src/examples-audio.qdoc8
-rw-r--r--src/charts/doc/src/examples-barchart.qdoc47
-rw-r--r--src/charts/doc/src/examples-barmodelmapper.qdoc58
-rw-r--r--src/charts/doc/src/examples-boxplotchart.qdoc78
-rw-r--r--src/charts/doc/src/examples-callout.qdoc15
-rw-r--r--src/charts/doc/src/examples-chartthemes.qdoc15
-rw-r--r--src/charts/doc/src/examples-customchart.qdoc26
-rw-r--r--src/charts/doc/src/examples-datetimeaxis.qdoc38
-rw-r--r--src/charts/doc/src/examples-donutbreakdown.qdoc45
-rw-r--r--src/charts/doc/src/examples-donutchart.qdoc9
-rw-r--r--src/charts/doc/src/examples-dynamicspline.qdoc10
-rw-r--r--src/charts/doc/src/examples-horizontalbarchart.qdoc50
-rw-r--r--src/charts/doc/src/examples-horizontalpercentbarchart.qdoc56
-rw-r--r--src/charts/doc/src/examples-horizontalstackedbarchart.qdoc53
-rw-r--r--src/charts/doc/src/examples-legend.qdoc40
-rw-r--r--src/charts/doc/src/examples-legendmarkers.qdoc43
-rw-r--r--src/charts/doc/src/examples-lineandbarchart.qdoc48
-rw-r--r--src/charts/doc/src/examples-linechart.qdoc30
-rw-r--r--src/charts/doc/src/examples-logvalueaxis.qdoc30
-rw-r--r--src/charts/doc/src/examples-modeldata.qdoc59
-rw-r--r--src/charts/doc/src/examples-multiaxis.qdoc37
-rw-r--r--src/charts/doc/src/examples-nesteddonuts.qdoc50
-rw-r--r--src/charts/doc/src/examples-percentbarchart.qdoc55
-rw-r--r--src/charts/doc/src/examples-piechart.qdoc9
-rw-r--r--src/charts/doc/src/examples-piechartcustomization.qdoc8
-rw-r--r--src/charts/doc/src/examples-piechartdrilldown.qdoc9
-rw-r--r--src/charts/doc/src/examples-polarchart.qdoc34
-rw-r--r--src/charts/doc/src/examples-qmlaxes.qdoc32
-rw-r--r--src/charts/doc/src/examples-qmlchart.qdoc125
-rw-r--r--src/charts/doc/src/examples-qmlcustomizations.qdoc28
-rw-r--r--src/charts/doc/src/examples-qmlcustomlegend.qdoc43
-rw-r--r--src/charts/doc/src/examples-qmlf1legends.qdoc23
-rw-r--r--src/charts/doc/src/examples-qmloscilloscope.qdoc47
-rw-r--r--src/charts/doc/src/examples-qmlpolarchart.qdoc35
-rw-r--r--src/charts/doc/src/examples-qmlweather.qdoc34
-rw-r--r--src/charts/doc/src/examples-scatterchart.qdoc39
-rw-r--r--src/charts/doc/src/examples-scatterinteractions.qdoc10
-rw-r--r--src/charts/doc/src/examples-splinechart.qdoc34
-rw-r--r--src/charts/doc/src/examples-stackedbarchart.qdoc53
-rw-r--r--src/charts/doc/src/examples-stackedbarchartdrilldown.qdoc50
-rw-r--r--src/charts/doc/src/examples-temperaturerecords.qdoc46
-rw-r--r--src/charts/doc/src/examples-zoomlinechart.qdoc33
-rw-r--r--src/charts/doc/src/index.qdoc61
-rw-r--r--src/charts/doc/src/qtcharts.qdoc200
-rw-r--r--src/charts/doc/style/offline.css722
-rw-r--r--src/charts/domain/abstractdomain.cpp265
-rw-r--r--src/charts/domain/abstractdomain_p.h132
-rw-r--r--src/charts/domain/domain.pri28
-rw-r--r--src/charts/domain/logxlogydomain.cpp278
-rw-r--r--src/charts/domain/logxlogydomain_p.h79
-rw-r--r--src/charts/domain/logxlogypolardomain.cpp273
-rw-r--r--src/charts/domain/logxlogypolardomain_p.h81
-rw-r--r--src/charts/domain/logxydomain.cpp245
-rw-r--r--src/charts/domain/logxydomain_p.h75
-rw-r--r--src/charts/domain/logxypolardomain.cpp242
-rw-r--r--src/charts/domain/logxypolardomain_p.h77
-rw-r--r--src/charts/domain/polardomain.cpp91
-rw-r--r--src/charts/domain/polardomain_p.h62
-rw-r--r--src/charts/domain/xlogydomain.cpp241
-rw-r--r--src/charts/domain/xlogydomain_p.h75
-rw-r--r--src/charts/domain/xlogypolardomain.cpp237
-rw-r--r--src/charts/domain/xlogypolardomain_p.h77
-rw-r--r--src/charts/domain/xydomain.cpp186
-rw-r--r--src/charts/domain/xydomain_p.h64
-rw-r--r--src/charts/domain/xypolardomain.cpp184
-rw-r--r--src/charts/domain/xypolardomain_p.h65
-rw-r--r--src/charts/layout/abstractchartlayout.cpp203
-rw-r--r--src/charts/layout/abstractchartlayout_p.h82
-rw-r--r--src/charts/layout/cartesianchartlayout.cpp246
-rw-r--r--src/charts/layout/cartesianchartlayout_p.h50
-rw-r--r--src/charts/layout/layout.pri12
-rw-r--r--src/charts/layout/polarchartlayout.cpp82
-rw-r--r--src/charts/layout/polarchartlayout_p.h50
-rw-r--r--src/charts/legend/legend.pri36
-rw-r--r--src/charts/legend/legendlayout.cpp506
-rw-r--r--src/charts/legend/legendlayout_p.h84
-rw-r--r--src/charts/legend/legendmarkeritem.cpp192
-rw-r--r--src/charts/legend/legendmarkeritem_p.h101
-rw-r--r--src/charts/legend/legendscroller.cpp74
-rw-r--r--src/charts/legend/legendscroller_p.h57
-rw-r--r--src/charts/legend/qarealegendmarker.cpp126
-rw-r--r--src/charts/legend/qarealegendmarker.h56
-rw-r--r--src/charts/legend/qarealegendmarker_p.h64
-rw-r--r--src/charts/legend/qbarlegendmarker.cpp146
-rw-r--r--src/charts/legend/qbarlegendmarker.h57
-rw-r--r--src/charts/legend/qbarlegendmarker_p.h66
-rw-r--r--src/charts/legend/qboxplotlegendmarker.cpp127
-rw-r--r--src/charts/legend/qboxplotlegendmarker.h55
-rw-r--r--src/charts/legend/qboxplotlegendmarker_p.h64
-rw-r--r--src/charts/legend/qlegend.cpp632
-rw-r--r--src/charts/legend/qlegend.h112
-rw-r--r--src/charts/legend/qlegend_p.h101
-rw-r--r--src/charts/legend/qlegendmarker.cpp294
-rw-r--r--src/charts/legend/qlegendmarker.h105
-rw-r--r--src/charts/legend/qlegendmarker_p.h82
-rw-r--r--src/charts/legend/qpielegendmarker.cpp144
-rw-r--r--src/charts/legend/qpielegendmarker.h57
-rw-r--r--src/charts/legend/qpielegendmarker_p.h68
-rw-r--r--src/charts/legend/qxylegendmarker.cpp138
-rw-r--r--src/charts/legend/qxylegendmarker.h55
-rw-r--r--src/charts/legend/qxylegendmarker_p.h64
-rw-r--r--src/charts/linechart/linechart.pri13
-rw-r--r--src/charts/linechart/linechartitem.cpp405
-rw-r--r--src/charts/linechart/linechartitem_p.h91
-rw-r--r--src/charts/linechart/qlineseries.cpp173
-rw-r--r--src/charts/linechart/qlineseries.h52
-rw-r--r--src/charts/linechart/qlineseries_p.h51
-rw-r--r--src/charts/piechart/piechart.pri26
-rw-r--r--src/charts/piechart/piechartitem.cpp228
-rw-r--r--src/charts/piechart/piechartitem_p.h86
-rw-r--r--src/charts/piechart/pieslicedata_p.h141
-rw-r--r--src/charts/piechart/piesliceitem.cpp319
-rw-r--r--src/charts/piechart/piesliceitem_p.h91
-rw-r--r--src/charts/piechart/qhpiemodelmapper.cpp267
-rw-r--r--src/charts/piechart/qhpiemodelmapper.h70
-rw-r--r--src/charts/piechart/qpiemodelmapper.cpp568
-rw-r--r--src/charts/piechart/qpiemodelmapper.h69
-rw-r--r--src/charts/piechart/qpiemodelmapper_p.h99
-rw-r--r--src/charts/piechart/qpieseries.cpp947
-rw-r--r--src/charts/piechart/qpieseries.h103
-rw-r--r--src/charts/piechart/qpieseries_p.h93
-rw-r--r--src/charts/piechart/qpieslice.cpp794
-rw-r--r--src/charts/piechart/qpieslice.h147
-rw-r--r--src/charts/piechart/qpieslice_p.h80
-rw-r--r--src/charts/piechart/qvpiemodelmapper.cpp270
-rw-r--r--src/charts/piechart/qvpiemodelmapper.h70
-rw-r--r--src/charts/qabstractseries.cpp328
-rw-r--r--src/charts/qabstractseries.h98
-rw-r--r--src/charts/qabstractseries_p.h105
-rw-r--r--src/charts/qchart.cpp872
-rw-r--r--src/charts/qchart.h183
-rw-r--r--src/charts/qchart_p.h70
-rw-r--r--src/charts/qchartglobal.h78
-rw-r--r--src/charts/qchartview.cpp317
-rw-r--r--src/charts/qchartview.h74
-rw-r--r--src/charts/qchartview_p.h65
-rw-r--r--src/charts/qpolarchart.cpp133
-rw-r--r--src/charts/qpolarchart.h60
-rw-r--r--src/charts/scatterchart/qscatterseries.cpp336
-rw-r--r--src/charts/scatterchart/qscatterseries.h75
-rw-r--r--src/charts/scatterchart/qscatterseries_p.h53
-rw-r--r--src/charts/scatterchart/scatter.pri13
-rw-r--r--src/charts/scatterchart/scatterchartitem.cpp237
-rw-r--r--src/charts/scatterchart/scatterchartitem_p.h151
-rw-r--r--src/charts/scroller.cpp216
-rw-r--r--src/charts/scroller_p.h109
-rw-r--r--src/charts/splinechart/qsplineseries.cpp165
-rw-r--r--src/charts/splinechart/qsplineseries.h51
-rw-r--r--src/charts/splinechart/qsplineseries_p.h54
-rw-r--r--src/charts/splinechart/splinechart.pri13
-rw-r--r--src/charts/splinechart/splinechartitem.cpp485
-rw-r--r--src/charts/splinechart/splinechartitem_p.h94
-rw-r--r--src/charts/themes/charttheme_p.h93
-rw-r--r--src/charts/themes/chartthemebluecerulean_p.h70
-rw-r--r--src/charts/themes/chartthemeblueicy_p.h72
-rw-r--r--src/charts/themes/chartthemebluencs_p.h71
-rw-r--r--src/charts/themes/chartthemebrownsand_p.h71
-rw-r--r--src/charts/themes/chartthemedark_p.h71
-rw-r--r--src/charts/themes/chartthemehighcontrast_p.h73
-rw-r--r--src/charts/themes/chartthemelight_p.h73
-rw-r--r--src/charts/themes/chartthemeqt_p.h74
-rw-r--r--src/charts/themes/chartthemesystem_p.h177
-rw-r--r--src/charts/themes/themes.pri14
-rw-r--r--src/charts/xychart/qhxymodelmapper.cpp243
-rw-r--r--src/charts/xychart/qhxymodelmapper.h70
-rw-r--r--src/charts/xychart/qvxymodelmapper.cpp243
-rw-r--r--src/charts/xychart/qvxymodelmapper.h70
-rw-r--r--src/charts/xychart/qxymodelmapper.cpp533
-rw-r--r--src/charts/xychart/qxymodelmapper.h69
-rw-r--r--src/charts/xychart/qxymodelmapper_p.h97
-rw-r--r--src/charts/xychart/qxyseries.cpp801
-rw-r--r--src/charts/xychart/qxyseries.h120
-rw-r--r--src/charts/xychart/qxyseries_p.h79
-rw-r--r--src/charts/xychart/xychart.cpp189
-rw-r--r--src/charts/xychart/xychart.pri20
-rw-r--r--src/charts/xychart/xychart_p.h92
446 files changed, 48435 insertions, 0 deletions
diff --git a/src/charts/animations/animations.pri b/src/charts/animations/animations.pri
new file mode 100644
index 00000000..28b6db1e
--- /dev/null
+++ b/src/charts/animations/animations.pri
@@ -0,0 +1,26 @@
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+
+SOURCES += \
+ $$PWD/axisanimation.cpp \
+ $$PWD/xyanimation.cpp \
+ $$PWD/pieanimation.cpp \
+ $$PWD/piesliceanimation.cpp \
+ $$PWD/splineanimation.cpp \
+ $$PWD/baranimation.cpp \
+ $$PWD/scatteranimation.cpp \
+ $$PWD/boxplotanimation.cpp \
+ $$PWD/boxwhiskersanimation.cpp \
+ $$PWD/chartanimation.cpp
+
+PRIVATE_HEADERS += \
+ $$PWD/axisanimation_p.h \
+ $$PWD/chartanimation_p.h \
+ $$PWD/xyanimation_p.h \
+ $$PWD/pieanimation_p.h \
+ $$PWD/piesliceanimation_p.h \
+ $$PWD/splineanimation_p.h \
+ $$PWD/baranimation_p.h \
+ $$PWD/scatteranimation_p.h \
+ $$PWD/boxplotanimation_p.h \
+ $$PWD/boxwhiskersanimation_p.h
diff --git a/src/charts/animations/axisanimation.cpp b/src/charts/animations/axisanimation.cpp
new file mode 100644
index 00000000..ef346287
--- /dev/null
+++ b/src/charts/animations/axisanimation.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "axisanimation_p.h"
+#include "chartaxiselement_p.h"
+#include "qabstractaxis_p.h"
+
+Q_DECLARE_METATYPE(QVector<qreal>)
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+
+AxisAnimation::AxisAnimation(ChartAxisElement *axis)
+ : ChartAnimation(axis),
+ m_axis(axis),
+ m_type(DefaultAnimation)
+{
+ setDuration(ChartAnimationDuration);
+ setEasingCurve(QEasingCurve::OutQuart);
+}
+
+AxisAnimation::~AxisAnimation()
+{
+}
+
+void AxisAnimation::setAnimationType(Animation type)
+{
+ if (state() != QAbstractAnimation::Stopped)
+ stop();
+ m_type = type;
+}
+
+void AxisAnimation::setAnimationPoint(const QPointF &point)
+{
+ if (state() != QAbstractAnimation::Stopped)
+ stop();
+ m_point = point;
+}
+
+void AxisAnimation::setValues(QVector<qreal> &oldLayout, QVector<qreal> &newLayout)
+{
+ if (state() != QAbstractAnimation::Stopped) stop();
+
+ switch (m_type) {
+ case ZoomOutAnimation: {
+ QRectF rect = m_axis->gridGeometry();
+ oldLayout.resize(newLayout.count());
+
+ for (int i = 0, j = oldLayout.count() - 1; i < (oldLayout.count() + 1) / 2; ++i, --j) {
+ oldLayout[i] = m_axis->axis()->orientation() == Qt::Horizontal ? rect.left() : rect.bottom();
+ oldLayout[j] = m_axis->axis()->orientation() == Qt::Horizontal ? rect.right() : rect.top();
+ }
+ }
+ break;
+ case ZoomInAnimation: {
+ int index = qMin(oldLayout.count() * (m_axis->axis()->orientation() == Qt::Horizontal ? m_point.x() : (1 - m_point.y())), newLayout.count() - (qreal)1.0);
+ oldLayout.resize(newLayout.count());
+
+ for (int i = 0; i < oldLayout.count(); i++)
+ oldLayout[i] = oldLayout[index];
+ }
+ break;
+ case MoveForwardAnimation: {
+ oldLayout.resize(newLayout.count());
+
+ for (int i = 0, j = i + 1; i < oldLayout.count() - 1; ++i, ++j)
+ oldLayout[i] = oldLayout[j];
+ }
+ break;
+ case MoveBackwordAnimation: {
+ oldLayout.resize(newLayout.count());
+
+ for (int i = oldLayout.count() - 1, j = i - 1; i > 0; --i, --j)
+ oldLayout[i] = oldLayout[j];
+ }
+ break;
+ default: {
+ oldLayout.resize(newLayout.count());
+ QRectF rect = m_axis->gridGeometry();
+ for (int i = 0, j = oldLayout.count() - 1; i < oldLayout.count(); ++i, --j)
+ oldLayout[i] = m_axis->axis()->orientation() == Qt::Horizontal ? rect.left() : rect.top();
+ }
+ break;
+ }
+
+ QVariantAnimation::KeyValues value;
+ setKeyValues(value); //workaround for wrong interpolation call
+ setKeyValueAt(0.0, qVariantFromValue(oldLayout));
+ setKeyValueAt(1.0, qVariantFromValue(newLayout));
+}
+
+QVariant AxisAnimation::interpolated(const QVariant &start, const QVariant &end, qreal progress) const
+{
+ QVector<qreal> startVector = qvariant_cast<QVector<qreal> >(start);
+ QVector<qreal> endVecotr = qvariant_cast<QVector<qreal> >(end);
+ QVector<qreal> result;
+
+ Q_ASSERT(startVector.count() == endVecotr.count()) ;
+
+ for (int i = 0; i < startVector.count(); i++) {
+ qreal value = startVector[i] + ((endVecotr[i] - startVector[i]) * progress);
+ result << value;
+ }
+ return qVariantFromValue(result);
+}
+
+
+void AxisAnimation::updateCurrentValue(const QVariant &value)
+{
+ if (state() != QAbstractAnimation::Stopped) { //workaround
+ QVector<qreal> vector = qvariant_cast<QVector<qreal> >(value);
+ m_axis->setLayout(vector);
+ m_axis->updateGeometry();
+ }
+
+}
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/animations/axisanimation_p.h b/src/charts/animations/axisanimation_p.h
new file mode 100644
index 00000000..9e886b2b
--- /dev/null
+++ b/src/charts/animations/axisanimation_p.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 AXISANIMATION_H
+#define AXISANIMATION_H
+
+#include "chartanimation_p.h"
+#include <QPointF>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class ChartAxisElement;
+
+class AxisAnimation: public ChartAnimation
+{
+public:
+ enum Animation { DefaultAnimation, ZoomOutAnimation, ZoomInAnimation, MoveForwardAnimation, MoveBackwordAnimation};
+ AxisAnimation(ChartAxisElement *axis);
+ ~AxisAnimation();
+ void setAnimationType(Animation type);
+ void setAnimationPoint(const QPointF &point);
+ void setValues(QVector<qreal> &oldLayout, QVector<qreal> &newLayout);
+protected:
+ QVariant interpolated(const QVariant &from, const QVariant &to, qreal progress) const;
+ void updateCurrentValue(const QVariant &value);
+private:
+ ChartAxisElement *m_axis;
+ Animation m_type;
+ QPointF m_point;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+
+
+#endif /* AXISANIMATION_H */
diff --git a/src/charts/animations/baranimation.cpp b/src/charts/animations/baranimation.cpp
new file mode 100644
index 00000000..15b69288
--- /dev/null
+++ b/src/charts/animations/baranimation.cpp
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "baranimation_p.h"
+#include "abstractbarchartitem_p.h"
+
+Q_DECLARE_METATYPE(QVector<QRectF>)
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+BarAnimation::BarAnimation(AbstractBarChartItem *item)
+ : ChartAnimation(item),
+ m_item(item)
+{
+ setDuration(ChartAnimationDuration);
+ setEasingCurve(QEasingCurve::OutQuart);
+}
+
+BarAnimation::~BarAnimation()
+{
+}
+
+QVariant BarAnimation::interpolated(const QVariant &from, const QVariant &to, qreal progress) const
+{
+ QVector<QRectF> startVector = qvariant_cast<QVector<QRectF> >(from);
+ QVector<QRectF> endVector = qvariant_cast<QVector<QRectF> >(to);
+ QVector<QRectF> result;
+
+ Q_ASSERT(startVector.count() == endVector.count());
+
+ for (int i = 0; i < startVector.count(); i++) {
+ QRectF start = startVector[i].normalized();
+ QRectF end = endVector[i].normalized();
+ qreal x1 = start.left() + progress * (end.left() - start.left());
+ qreal x2 = start.right() + progress * (end.right() - start.right());
+ qreal y1 = start.top() + progress * (end.top() - start.top());
+ qreal y2 = start.bottom() + progress * (end.bottom() - start.bottom());
+
+ QRectF value(QPointF(x1, y1), QPointF(x2, y2));
+ result << value.normalized();
+ }
+ return qVariantFromValue(result);
+}
+
+void BarAnimation::updateCurrentValue(const QVariant &value)
+{
+ if (state() != QAbstractAnimation::Stopped) { //workaround
+
+ QVector<QRectF> layout = qvariant_cast<QVector<QRectF> >(value);
+ m_item->setLayout(layout);
+ }
+}
+
+void BarAnimation::setup(const QVector<QRectF> &oldLayout, const QVector<QRectF> &newLayout)
+{
+ QVariantAnimation::KeyValues value;
+ setKeyValues(value); //workaround for wrong interpolation call
+ setKeyValueAt(0.0, qVariantFromValue(oldLayout));
+ setKeyValueAt(1.0, qVariantFromValue(newLayout));
+}
+
+#include "moc_baranimation_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
+
diff --git a/src/charts/animations/baranimation_p.h b/src/charts/animations/baranimation_p.h
new file mode 100644
index 00000000..5b49f302
--- /dev/null
+++ b/src/charts/animations/baranimation_p.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 BARANIMATION_P_H
+#define BARANIMATION_P_H
+
+#include "chartanimation_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class AbstractBarChartItem;
+
+class BarAnimation : public ChartAnimation
+{
+ Q_OBJECT
+
+public:
+ BarAnimation(AbstractBarChartItem *item);
+ ~BarAnimation();
+
+public: // from QVariantAnimation
+ virtual QVariant interpolated(const QVariant &from, const QVariant &to, qreal progress) const;
+ virtual void updateCurrentValue(const QVariant &value);
+
+ void setup(const QVector<QRectF> &oldLayout, const QVector<QRectF> &newLayout);
+
+protected:
+ AbstractBarChartItem *m_item;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // BARANIMATION_P_H
diff --git a/src/charts/animations/boxplotanimation.cpp b/src/charts/animations/boxplotanimation.cpp
new file mode 100644
index 00000000..cfd474bb
--- /dev/null
+++ b/src/charts/animations/boxplotanimation.cpp
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "boxplotanimation_p.h"
+#include "boxplotchartitem_p.h"
+#include "boxwhiskersdata_p.h"
+#include "boxwhiskersanimation_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+BoxPlotAnimation::BoxPlotAnimation(BoxPlotChartItem *item)
+ : QObject(item),
+ m_item(item)
+{
+}
+
+BoxPlotAnimation::~BoxPlotAnimation()
+{
+}
+
+void BoxPlotAnimation::addBox(BoxWhiskers *box)
+{
+ BoxWhiskersAnimation *animation = m_animations.value(box);
+ if (!animation) {
+ animation = new BoxWhiskersAnimation(box, this);
+ m_animations.insert(box, animation);
+ BoxWhiskersData start;
+ start.m_lowerExtreme = box->m_data.m_median;
+ start.m_lowerQuartile = box->m_data.m_median;
+ start.m_median = box->m_data.m_median;
+ start.m_upperQuartile = box->m_data.m_median;
+ start.m_upperExtreme = box->m_data.m_median;
+ animation->setup(start, box->m_data);
+ } else {
+ animation->stop();
+ animation->setEndData(box->m_data);
+ }
+}
+
+ChartAnimation *BoxPlotAnimation::boxAnimation(BoxWhiskers *box)
+{
+ BoxWhiskersAnimation *animation = m_animations.value(box);
+ if (animation)
+ animation->m_changeAnimation = false;
+
+ return animation;
+}
+
+ChartAnimation *BoxPlotAnimation::boxChangeAnimation(BoxWhiskers *box)
+{
+ BoxWhiskersAnimation *animation = m_animations.value(box);
+ animation->m_changeAnimation = true;
+ animation->setEndData(box->m_data);
+
+ return animation;
+}
+
+void BoxPlotAnimation::setAnimationStart(BoxWhiskers *box)
+{
+ BoxWhiskersAnimation *animation = m_animations.value(box);
+ animation->setStartData(box->m_data);
+}
+
+void BoxPlotAnimation::stopAll()
+{
+ foreach (BoxWhiskers *box, m_animations.keys()) {
+ BoxWhiskersAnimation *animation = m_animations.value(box);
+ animation->stopAndDestroyLater();
+ m_animations.remove(box);
+ }
+}
+
+void BoxPlotAnimation::removeBoxAnimation(BoxWhiskers *box)
+{
+ m_animations.remove(box);
+}
+
+#include "moc_boxplotanimation_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/animations/boxplotanimation_p.h b/src/charts/animations/boxplotanimation_p.h
new file mode 100644
index 00000000..3eba311b
--- /dev/null
+++ b/src/charts/animations/boxplotanimation_p.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 BOXPLOTANIMATION_P_H
+#define BOXPLOTANIMATION_P_H
+
+#include "chartanimation_p.h"
+#include "boxwhiskers_p.h"
+#include "boxwhiskersdata_p.h"
+#include "boxwhiskersanimation_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class BoxPlotChartItem;
+
+class BoxPlotAnimation : public QObject
+{
+ Q_OBJECT
+public:
+ BoxPlotAnimation(BoxPlotChartItem *item);
+ ~BoxPlotAnimation();
+
+ void addBox(BoxWhiskers *box);
+ ChartAnimation *boxAnimation(BoxWhiskers *box);
+ ChartAnimation *boxChangeAnimation(BoxWhiskers *box);
+
+ void setAnimationStart(BoxWhiskers *box);
+ void stopAll();
+ void removeBoxAnimation(BoxWhiskers *box);
+
+protected:
+ BoxPlotChartItem *m_item;
+ QHash<BoxWhiskers *, BoxWhiskersAnimation *> m_animations;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // BOXPLOTANIMATION_P_H
diff --git a/src/charts/animations/boxwhiskersanimation.cpp b/src/charts/animations/boxwhiskersanimation.cpp
new file mode 100644
index 00000000..6d5404fa
--- /dev/null
+++ b/src/charts/animations/boxwhiskersanimation.cpp
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "boxwhiskersanimation_p.h"
+#include "boxplotanimation_p.h"
+#include "boxplotchartitem_p.h"
+#include "boxwhiskersdata_p.h"
+
+Q_DECLARE_METATYPE(QVector<QRectF>)
+Q_DECLARE_METATYPE(QT_CHARTS_NAMESPACE::BoxWhiskersData)
+Q_DECLARE_METATYPE(qreal)
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+BoxWhiskersAnimation::BoxWhiskersAnimation(BoxWhiskers *box, BoxPlotAnimation *boxPlotAnimation)
+ : ChartAnimation(box),
+ m_box(box),
+ m_boxPlotAnimation(boxPlotAnimation)
+{
+ setDuration(ChartAnimationDuration);
+ setEasingCurve(QEasingCurve::OutQuart);
+}
+
+BoxWhiskersAnimation::~BoxWhiskersAnimation()
+{
+ if (m_boxPlotAnimation)
+ m_boxPlotAnimation->removeBoxAnimation(m_box);
+}
+
+QVariant BoxWhiskersAnimation::interpolated(const QVariant &from, const QVariant &to, qreal progress) const
+{
+ BoxWhiskersData startData = qvariant_cast<BoxWhiskersData>(from);
+ BoxWhiskersData endData = qvariant_cast<BoxWhiskersData>(to);
+ BoxWhiskersData result;
+
+ if (m_changeAnimation) {
+ result.m_lowerExtreme = startData.m_lowerExtreme + progress * (endData.m_lowerExtreme - startData.m_lowerExtreme);
+ result.m_lowerQuartile = startData.m_lowerQuartile + progress * (endData.m_lowerQuartile - startData.m_lowerQuartile);
+ result.m_median = startData.m_median + progress * (endData.m_median - startData.m_median);
+ result.m_upperQuartile = startData.m_upperQuartile + progress * (endData.m_upperQuartile - startData.m_upperQuartile);
+ result.m_upperExtreme = startData.m_upperExtreme + progress * (endData.m_upperExtreme - startData.m_upperExtreme);
+ } else {
+ result.m_lowerExtreme = endData.m_median + progress * (endData.m_lowerExtreme - endData.m_median);
+ result.m_lowerQuartile = endData.m_median + progress * (endData.m_lowerQuartile - endData.m_median);
+ result.m_median = endData.m_median;
+ result.m_upperQuartile = endData.m_median + progress * (endData.m_upperQuartile - endData.m_median);
+ result.m_upperExtreme = endData.m_median + progress * (endData.m_upperExtreme - endData.m_median);
+ }
+ result.m_index = endData.m_index;
+ result.m_boxItems = endData.m_boxItems;
+
+ result.m_maxX = endData.m_maxX;
+ result.m_minX = endData.m_minX;
+ result.m_maxY = endData.m_maxY;
+ result.m_minY = endData.m_minY;
+ result.m_seriesIndex = endData.m_seriesIndex;
+ result.m_seriesCount = endData.m_seriesCount;
+
+ return qVariantFromValue(result);
+}
+
+void BoxWhiskersAnimation::updateCurrentValue(const QVariant &value)
+{
+ BoxWhiskersData data = qvariant_cast<BoxWhiskersData>(value);
+ m_box->setLayout(data);
+}
+
+void BoxWhiskersAnimation::setup(const BoxWhiskersData &startData, const BoxWhiskersData &endData)
+{
+ setKeyValueAt(0.0, qVariantFromValue(startData));
+ setKeyValueAt(1.0, qVariantFromValue(endData));
+}
+
+void BoxWhiskersAnimation::setEndData(const BoxWhiskersData &endData)
+{
+ if (state() != QAbstractAnimation::Stopped)
+ stop();
+
+ setEndValue(qVariantFromValue(endData));
+}
+
+void BoxWhiskersAnimation::setStartData(const BoxWhiskersData &endData)
+{
+ if (state() != QAbstractAnimation::Stopped)
+ stop();
+
+ setStartValue(qVariantFromValue(endData));
+}
+
+#include "moc_boxwhiskersanimation_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
+
diff --git a/src/charts/animations/boxwhiskersanimation_p.h b/src/charts/animations/boxwhiskersanimation_p.h
new file mode 100644
index 00000000..ff56222b
--- /dev/null
+++ b/src/charts/animations/boxwhiskersanimation_p.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 BOXWHISKERSANIMATION_P_H
+#define BOXWHISKERSANIMATION_P_H
+
+#include "chartanimation_p.h"
+#include "boxwhiskers_p.h"
+#include "boxwhiskersdata_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class BoxPlotChartItem;
+class BoxPlotAnimation;
+
+class BoxWhiskersAnimation : public ChartAnimation
+{
+ Q_OBJECT
+
+public:
+ BoxWhiskersAnimation(BoxWhiskers *box, BoxPlotAnimation *boxPlotAnimation);
+ ~BoxWhiskersAnimation();
+
+public: // from QVariantAnimation
+ virtual QVariant interpolated(const QVariant &from, const QVariant &to, qreal progress) const;
+ virtual void updateCurrentValue(const QVariant &value);
+
+ void setup(const BoxWhiskersData &startData, const BoxWhiskersData &endData);
+ void setEndData(const BoxWhiskersData &endData);
+ void setStartData(const BoxWhiskersData &endData);
+
+ void moveMedianLine(bool move);
+
+protected:
+ friend class BoxPlotAnimation;
+ BoxWhiskers *m_box;
+ bool m_changeAnimation;
+ BoxPlotAnimation *m_boxPlotAnimation;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // BOXWHISKERSANIMATION_P_H
diff --git a/src/charts/animations/chartanimation.cpp b/src/charts/animations/chartanimation.cpp
new file mode 100644
index 00000000..0e512932
--- /dev/null
+++ b/src/charts/animations/chartanimation.cpp
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "chartanimation_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+ChartAnimation::ChartAnimation(QObject *parent) :
+ QVariantAnimation(parent),
+ m_destructing(false)
+{
+}
+
+void ChartAnimation::stopAndDestroyLater()
+{
+ m_destructing = true;
+ stop();
+ deleteLater();
+}
+
+void ChartAnimation::startChartAnimation()
+{
+ if (!m_destructing)
+ start();
+}
+
+QT_CHARTS_END_NAMESPACE
+
+
diff --git a/src/charts/animations/chartanimation_p.h b/src/charts/animations/chartanimation_p.h
new file mode 100644
index 00000000..81ec72c4
--- /dev/null
+++ b/src/charts/animations/chartanimation_p.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTANIMATION_H
+#define CHARTANIMATION_H
+
+#include "qchartglobal.h"
+#include <QVariantAnimation>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+const static int ChartAnimationDuration = 1000;
+
+class ChartAnimation: public QVariantAnimation
+{
+ Q_OBJECT
+public:
+ ChartAnimation(QObject *parent = 0);
+
+ void stopAndDestroyLater();
+
+public Q_SLOTS:
+ void startChartAnimation();
+
+protected:
+ bool m_destructing;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif /* CHARTANIMATION_H */
diff --git a/src/charts/animations/pieanimation.cpp b/src/charts/animations/pieanimation.cpp
new file mode 100644
index 00000000..30d6865f
--- /dev/null
+++ b/src/charts/animations/pieanimation.cpp
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "pieanimation_p.h"
+#include "piesliceanimation_p.h"
+#include "piechartitem_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+PieAnimation::PieAnimation(PieChartItem *item)
+ : ChartAnimation(item),
+ m_item(item)
+{
+}
+
+PieAnimation::~PieAnimation()
+{
+}
+
+ChartAnimation *PieAnimation::updateValue(PieSliceItem *sliceItem, const PieSliceData &sliceData)
+{
+ PieSliceAnimation *animation = m_animations.value(sliceItem);
+ if (!animation) {
+ animation = new PieSliceAnimation(sliceItem);
+ m_animations.insert(sliceItem, animation);
+ } else {
+ animation->stop();
+ }
+
+ animation->updateValue(sliceData);
+ animation->setDuration(ChartAnimationDuration);
+ animation->setEasingCurve(QEasingCurve::OutQuart);
+
+ return animation;
+}
+
+ChartAnimation *PieAnimation::addSlice(PieSliceItem *sliceItem, const PieSliceData &sliceData, bool startupAnimation)
+{
+ PieSliceAnimation *animation = new PieSliceAnimation(sliceItem);
+ m_animations.insert(sliceItem, animation);
+
+ PieSliceData startValue = sliceData;
+ startValue.m_radius = 0;
+ if (startupAnimation)
+ startValue.m_startAngle = 0;
+ else
+ startValue.m_startAngle = sliceData.m_startAngle + (sliceData.m_angleSpan / 2);
+ startValue.m_angleSpan = 0;
+
+ if (sliceData.m_holeRadius > 0)
+ startValue.m_radius = sliceData.m_holeRadius;
+
+ animation->setValue(startValue, sliceData);
+ animation->setDuration(ChartAnimationDuration);
+ animation->setEasingCurve(QEasingCurve::OutQuart);
+
+ return animation;
+}
+
+ChartAnimation *PieAnimation::removeSlice(PieSliceItem *sliceItem)
+{
+ PieSliceAnimation *animation = m_animations.value(sliceItem);
+ Q_ASSERT(animation);
+ animation->stop();
+
+ PieSliceData endValue = animation->currentSliceValue();
+ if (endValue.m_holeRadius > 0)
+ endValue.m_radius = endValue.m_holeRadius;
+ else
+ endValue.m_radius = 0;
+ endValue.m_startAngle = endValue.m_startAngle + endValue.m_angleSpan;
+ endValue.m_angleSpan = 0;
+ endValue.m_isLabelVisible = false;
+
+ animation->updateValue(endValue);
+ animation->setDuration(ChartAnimationDuration);
+ animation->setEasingCurve(QEasingCurve::OutQuart);
+
+ // PieSliceItem is the parent of PieSliceAnimation so the animation will be deleted as well..
+ connect(animation, SIGNAL(finished()), sliceItem, SLOT(deleteLater()));
+ m_animations.remove(sliceItem);
+
+ return animation;
+}
+
+void PieAnimation::updateCurrentValue(const QVariant &)
+{
+ // nothing to do...
+}
+
+#include "moc_pieanimation_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/animations/pieanimation_p.h b/src/charts/animations/pieanimation_p.h
new file mode 100644
index 00000000..33599694
--- /dev/null
+++ b/src/charts/animations/pieanimation_p.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 PIEANIMATION_P_H
+#define PIEANIMATION_P_H
+
+#include "chartanimation_p.h"
+#include "piechartitem_p.h"
+#include "piesliceanimation_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class PieChartItem;
+
+class PieAnimation : public ChartAnimation
+{
+ Q_OBJECT
+
+public:
+ PieAnimation(PieChartItem *item);
+ ~PieAnimation();
+ ChartAnimation *updateValue(PieSliceItem *sliceItem, const PieSliceData &newValue);
+ ChartAnimation *addSlice(PieSliceItem *sliceItem, const PieSliceData &endValue, bool startupAnimation);
+ ChartAnimation *removeSlice(PieSliceItem *sliceItem);
+
+public: // from QVariantAnimation
+ void updateCurrentValue(const QVariant &value);
+
+private:
+ PieChartItem *m_item;
+ QHash<PieSliceItem *, PieSliceAnimation *> m_animations;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/animations/piesliceanimation.cpp b/src/charts/animations/piesliceanimation.cpp
new file mode 100644
index 00000000..0a4503c9
--- /dev/null
+++ b/src/charts/animations/piesliceanimation.cpp
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "piesliceanimation_p.h"
+#include "piechartitem_p.h"
+
+Q_DECLARE_METATYPE(QT_CHARTS_NAMESPACE::PieSliceData)
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+qreal linearPos(qreal start, qreal end, qreal pos)
+{
+ return start + ((end - start) * pos);
+}
+
+QPointF linearPos(QPointF start, QPointF end, qreal pos)
+{
+ qreal x = linearPos(start.x(), end.x(), pos);
+ qreal y = linearPos(start.y(), end.y(), pos);
+ return QPointF(x, y);
+}
+
+QPen linearPos(QPen start, QPen end, qreal pos)
+{
+ QColor c;
+ c.setRedF(linearPos(start.color().redF(), end.color().redF(), pos));
+ c.setGreenF(linearPos(start.color().greenF(), end.color().greenF(), pos));
+ c.setBlueF(linearPos(start.color().blueF(), end.color().blueF(), pos));
+ end.setColor(c);
+ return end;
+}
+
+QBrush linearPos(QBrush start, QBrush end, qreal pos)
+{
+ QColor c;
+ c.setRedF(linearPos(start.color().redF(), end.color().redF(), pos));
+ c.setGreenF(linearPos(start.color().greenF(), end.color().greenF(), pos));
+ c.setBlueF(linearPos(start.color().blueF(), end.color().blueF(), pos));
+ end.setColor(c);
+ return end;
+}
+
+PieSliceAnimation::PieSliceAnimation(PieSliceItem *sliceItem)
+ : ChartAnimation(sliceItem),
+ m_sliceItem(sliceItem),
+ m_currentValue(m_sliceItem->m_data)
+{
+
+}
+
+PieSliceAnimation::~PieSliceAnimation()
+{
+}
+
+void PieSliceAnimation::setValue(const PieSliceData &startValue, const PieSliceData &endValue)
+{
+ if (state() != QAbstractAnimation::Stopped)
+ stop();
+
+ m_currentValue = startValue;
+
+ setKeyValueAt(0.0, qVariantFromValue(startValue));
+ setKeyValueAt(1.0, qVariantFromValue(endValue));
+}
+
+void PieSliceAnimation::updateValue(const PieSliceData &endValue)
+{
+ if (state() != QAbstractAnimation::Stopped)
+ stop();
+
+ setKeyValueAt(0.0, qVariantFromValue(m_currentValue));
+ setKeyValueAt(1.0, qVariantFromValue(endValue));
+}
+
+PieSliceData PieSliceAnimation::currentSliceValue()
+{
+ // NOTE:
+ // We must use an internal current value because QVariantAnimation::currentValue() is updated
+ // before the animation is actually started. So if we get 2 updateValue() calls in a row the currentValue()
+ // will have the end value set from the first call and the second call will interpolate that instead of
+ // the original current value as it was before the first call.
+ return m_currentValue;
+}
+
+QVariant PieSliceAnimation::interpolated(const QVariant &start, const QVariant &end, qreal progress) const
+{
+ PieSliceData startValue = qvariant_cast<PieSliceData>(start);
+ PieSliceData endValue = qvariant_cast<PieSliceData>(end);
+
+ PieSliceData result;
+ result = endValue;
+ result.m_center = linearPos(startValue.m_center, endValue.m_center, progress);
+ result.m_radius = linearPos(startValue.m_radius, endValue.m_radius, progress);
+ result.m_startAngle = linearPos(startValue.m_startAngle, endValue.m_startAngle, progress);
+ result.m_angleSpan = linearPos(startValue.m_angleSpan, endValue.m_angleSpan, progress);
+ result.m_slicePen = linearPos(startValue.m_slicePen, endValue.m_slicePen, progress);
+ result.m_sliceBrush = linearPos(startValue.m_sliceBrush, endValue.m_sliceBrush, progress);
+ result.m_holeRadius = linearPos(startValue.m_holeRadius, endValue.m_holeRadius, progress);
+
+ return qVariantFromValue(result);
+}
+
+void PieSliceAnimation::updateCurrentValue(const QVariant &value)
+{
+ if (state() != QAbstractAnimation::Stopped) { //workaround
+ m_currentValue = qvariant_cast<PieSliceData>(value);
+ m_sliceItem->setLayout(m_currentValue);
+ }
+}
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/animations/piesliceanimation_p.h b/src/charts/animations/piesliceanimation_p.h
new file mode 100644
index 00000000..88155054
--- /dev/null
+++ b/src/charts/animations/piesliceanimation_p.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 PIESLICEANIMATION_P_H
+#define PIESLICEANIMATION_P_H
+
+#include "chartanimation_p.h"
+#include "piesliceitem_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class PieChartItem;
+
+class PieSliceAnimation : public ChartAnimation
+{
+public:
+ PieSliceAnimation(PieSliceItem *sliceItem);
+ ~PieSliceAnimation();
+ void setValue(const PieSliceData &startValue, const PieSliceData &endValue);
+ void updateValue(const PieSliceData &endValue);
+ PieSliceData currentSliceValue();
+
+protected:
+ QVariant interpolated(const QVariant &start, const QVariant &end, qreal progress) const;
+ void updateCurrentValue(const QVariant &value);
+
+private:
+ PieSliceItem *m_sliceItem;
+ PieSliceData m_currentValue;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/animations/scatteranimation.cpp b/src/charts/animations/scatteranimation.cpp
new file mode 100644
index 00000000..faf66d11
--- /dev/null
+++ b/src/charts/animations/scatteranimation.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+ **
+ ** $QT_BEGIN_LICENSE$
+ ** 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
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include "scatteranimation_p.h"
+#include "scatterchartitem_p.h"
+#include <QDebug>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+ScatterAnimation::ScatterAnimation(ScatterChartItem *item)
+ : XYAnimation(item)
+{
+}
+
+ScatterAnimation::~ScatterAnimation()
+{
+}
+
+void ScatterAnimation::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
+{
+ XYAnimation::updateState(newState, oldState);
+
+ if (oldState == QAbstractAnimation::Running && newState == QAbstractAnimation::Stopped
+ && animationType() == RemovePointAnimation) {
+ // Removing a point from scatter chart will keep extra marker item after animation stops.
+ // Also, if the removed point was not the last one in series, points after the removed one
+ // will report wrong coordinates when clicked. To fix these issues, update geometry after
+ // point removal animation has finished.
+ chartItem()->updateGeometry();
+ }
+}
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/animations/scatteranimation_p.h b/src/charts/animations/scatteranimation_p.h
new file mode 100644
index 00000000..7a4f8bfb
--- /dev/null
+++ b/src/charts/animations/scatteranimation_p.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 SCATTERANIMATION_P_H
+#define SCATTERANIMATION_P_H
+#include "xyanimation_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class ScatterChartItem;
+
+class ScatterAnimation : public XYAnimation
+{
+public:
+ ScatterAnimation(ScatterChartItem *item);
+ ~ScatterAnimation();
+
+protected:
+ void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState);
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/animations/splineanimation.cpp b/src/charts/animations/splineanimation.cpp
new file mode 100644
index 00000000..4056d825
--- /dev/null
+++ b/src/charts/animations/splineanimation.cpp
@@ -0,0 +1,210 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+ **
+ ** $QT_BEGIN_LICENSE$
+ ** 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
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include "splineanimation_p.h"
+#include "splinechartitem_p.h"
+#include <QDebug>
+
+Q_DECLARE_METATYPE(QVector<QPointF>)
+Q_DECLARE_METATYPE(SplineVector)
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+SplineAnimation::SplineAnimation(SplineChartItem *item)
+ : XYAnimation(item),
+ m_item(item),
+ m_valid(false)
+{
+}
+
+SplineAnimation::~SplineAnimation()
+{
+}
+
+void SplineAnimation::setup(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, QVector<QPointF> &oldControlPoints, QVector<QPointF> &newControlPoints, int index)
+{
+ if (newPoints.count() * 2 - 2 != newControlPoints.count() || newControlPoints.count() < 2) {
+ m_valid = false;
+ m_dirty = false;
+ m_item->setGeometryPoints(newPoints);
+ m_item->setControlGeometryPoints(newControlPoints);
+ m_item->setDirty(false);
+ m_item->updateGeometry();
+ return;
+ }
+
+ m_type = NewAnimation;
+
+ if (state() != QAbstractAnimation::Stopped) {
+ stop();
+ m_dirty = false;
+ }
+
+ if (!m_dirty) {
+ m_dirty = true;
+ m_oldSpline.first = oldPoints;
+ m_oldSpline.second = oldControlPoints;
+ }
+
+ m_newSpline.first = newPoints;
+ m_newSpline.second = newControlPoints;
+
+
+ int x = m_oldSpline.first.count();
+ int y = m_newSpline.first.count();
+
+ if (x - y == 1 && index >= 0 && y > 0) {
+ //remove point
+ if (index > 0) {
+ m_newSpline.first.insert(index, newPoints[index - 1]);
+ m_newSpline.second.insert((index - 1) * 2, newPoints[index - 1]);
+ m_newSpline.second.insert((index - 1) * 2 + 1, newPoints[index - 1]);
+ } else {
+ m_newSpline.first.insert(0, newPoints[index]);
+ m_newSpline.second.insert(0, newPoints[index]);
+ m_newSpline.second.insert(1, newPoints[index]);
+ }
+ m_index = index;
+ m_type = RemovePointAnimation;
+ }
+
+ if (x - y == -1 && index >= 0) {
+ //add point
+ if (index > 0) {
+ m_oldSpline.first.insert(index, newPoints[index - 1]);
+ m_oldSpline.second.insert((index - 1) * 2, newPoints[index - 1]);
+ m_oldSpline.second.insert((index - 1) * 2 + 1, newPoints[index - 1]);
+ } else {
+ m_oldSpline.first.insert(0, newPoints[index]);
+ m_oldSpline.second.insert(0, newPoints[index]);
+ m_oldSpline.second.insert(1, newPoints[index]);
+ }
+ m_index = index;
+ m_type = AddPointAnimation;
+ }
+
+ x = m_oldSpline.first.count();
+ y = m_newSpline.first.count();
+
+ if (x != y) {
+ m_type = NewAnimation;
+ } else if (m_type == NewAnimation) {
+ m_type = ReplacePointAnimation;
+ }
+
+
+ setKeyValueAt(0.0, qVariantFromValue(m_oldSpline));
+ setKeyValueAt(1.0, qVariantFromValue(m_newSpline));
+
+ m_valid = true;
+
+}
+
+QVariant SplineAnimation::interpolated(const QVariant &start, const QVariant &end, qreal progress) const
+{
+
+ SplineVector startPair = qvariant_cast< SplineVector >(start);
+ SplineVector endPair = qvariant_cast< SplineVector >(end);
+ SplineVector result;
+
+ switch (animationType()) {
+ case RemovePointAnimation:
+ case AddPointAnimation:
+ case ReplacePointAnimation: {
+ if (startPair.first.count() != endPair.first.count())
+ break;
+ Q_ASSERT(startPair.first.count() * 2 - 2 == startPair.second.count());
+ Q_ASSERT(endPair.first.count() * 2 - 2 == endPair.second.count());
+ for (int i = 0; i < endPair.first.count(); i++) {
+ qreal x = startPair.first[i].x() + ((endPair.first[i].x() - startPair.first[i].x()) * progress);
+ qreal y = startPair.first[i].y() + ((endPair.first[i].y() - startPair.first[i].y()) * progress);
+ result.first << QPointF(x, y);
+ if (i + 1 >= endPair.first.count())
+ continue;
+ x = startPair.second[i * 2].x() + ((endPair.second[i * 2].x() - startPair.second[i * 2].x()) * progress);
+ y = startPair.second[i * 2].y() + ((endPair.second[i * 2].y() - startPair.second[i * 2].y()) * progress);
+ result.second << QPointF(x, y);
+ x = startPair.second[i * 2 + 1].x() + ((endPair.second[i * 2 + 1].x() - startPair.second[i * 2 + 1].x()) * progress);
+ y = startPair.second[i * 2 + 1].y() + ((endPair.second[i * 2 + 1].y() - startPair.second[i * 2 + 1].y()) * progress);
+ result.second << QPointF(x, y);
+ }
+ }
+ break;
+ case NewAnimation: {
+ Q_ASSERT(endPair.first.count() * 2 - 2 == endPair.second.count());
+ int count = endPair.first.count() * qBound(qreal(0), progress, qreal(1));
+ for (int i = 0; i < count; i++) {
+ result.first << endPair.first[i];
+ if (i + 1 == count)
+ break;
+ result.second << endPair.second[2 * i];
+ result.second << endPair.second[2 * i + 1];
+ }
+ }
+ break;
+ default:
+ qWarning() << "Unknown type of animation";
+ break;
+ }
+
+ return qVariantFromValue(result);
+}
+
+void SplineAnimation::updateCurrentValue(const QVariant &value)
+{
+ if (state() != QAbstractAnimation::Stopped && m_valid) { //workaround
+ QPair<QVector<QPointF >, QVector<QPointF > > pair = qvariant_cast< QPair< QVector<QPointF>, QVector<QPointF> > >(value);
+ m_item->setGeometryPoints(pair.first);
+ m_item->setControlGeometryPoints(pair.second);
+ m_item->updateGeometry();
+ m_item->setDirty(true);
+ m_dirty = false;
+ }
+}
+
+void SplineAnimation::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
+{
+ XYAnimation::updateState(newState, oldState);
+
+ if (oldState == QAbstractAnimation::Running && newState == QAbstractAnimation::Stopped) {
+ if (m_item->isDirty() && m_type == RemovePointAnimation) {
+ if (!m_newSpline.first.isEmpty()) {
+ if (m_index) {
+ m_newSpline.first.remove(m_index);
+ m_newSpline.second.remove((m_index - 1) * 2);
+ m_newSpline.second.remove((m_index - 1) * 2);
+ } else {
+ m_newSpline.first.remove(0);
+ m_newSpline.second.remove(0);
+ m_newSpline.second.remove(0);
+ }
+ }
+ m_item->setGeometryPoints(m_newSpline.first);
+ m_item->setControlGeometryPoints(m_newSpline.second);
+ }
+ }
+
+ if (oldState == QAbstractAnimation::Stopped && newState == QAbstractAnimation::Running) {
+ if (!m_valid)
+ stop();
+ }
+}
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/animations/splineanimation_p.h b/src/charts/animations/splineanimation_p.h
new file mode 100644
index 00000000..ad9120ed
--- /dev/null
+++ b/src/charts/animations/splineanimation_p.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 SPLINEANIMATION_P_H
+#define SPLINEANIMATION_P_H
+#include "xyanimation_p.h"
+#include <QPointF>
+
+typedef QPair<QVector<QPointF >, QVector<QPointF > > SplineVector;
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class SplineChartItem;
+
+class SplineAnimation : public XYAnimation
+{
+public:
+ SplineAnimation(SplineChartItem *item);
+ ~SplineAnimation();
+ void setup(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, QVector<QPointF> &oldContorlPoints, QVector<QPointF> &newControlPoints, int index = -1);
+
+protected:
+ QVariant interpolated(const QVariant &start, const QVariant &end, qreal progress) const;
+ void updateCurrentValue(const QVariant &value);
+ void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState);
+
+private:
+ SplineVector m_oldSpline;
+ SplineVector m_newSpline;
+ SplineChartItem *m_item;
+ bool m_valid;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/animations/xyanimation.cpp b/src/charts/animations/xyanimation.cpp
new file mode 100644
index 00000000..3e395c1a
--- /dev/null
+++ b/src/charts/animations/xyanimation.cpp
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "xyanimation_p.h"
+#include "xychart_p.h"
+#include <QDebug>
+
+Q_DECLARE_METATYPE(QVector<QPointF>)
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+XYAnimation::XYAnimation(XYChart *item)
+ : ChartAnimation(item),
+ m_type(NewAnimation),
+ m_dirty(false),
+ m_index(-1),
+ m_item(item)
+{
+ setDuration(ChartAnimationDuration);
+ setEasingCurve(QEasingCurve::OutQuart);
+}
+
+XYAnimation::~XYAnimation()
+{
+}
+
+void XYAnimation::setup(const QVector<QPointF> &oldPoints, const QVector<QPointF> &newPoints, int index)
+{
+ m_type = NewAnimation;
+
+ if (state() != QAbstractAnimation::Stopped) {
+ stop();
+ m_dirty = false;
+ }
+
+ if (!m_dirty) {
+ m_dirty = true;
+ m_oldPoints = oldPoints;
+ }
+
+ m_newPoints = newPoints;
+
+ int x = m_oldPoints.count();
+ int y = m_newPoints.count();
+ int diff = x - y;
+ int requestedDiff = oldPoints.count() - y;
+
+ // m_oldPoints can be whatever between 0 and actual points count if new animation setup
+ // interrupts a previous animation, so only do remove and add animations if both
+ // stored diff and requested diff indicate add or remove. Also ensure that index is not
+ // invalid.
+ if (diff == 1 && requestedDiff == 1 && index >= 0 && y > 0 && index <= y) {
+ //remove point
+ m_newPoints.insert(index, index > 0 ? newPoints[index - 1] : newPoints[index]);
+ m_index = index;
+ m_type = RemovePointAnimation;
+ }
+
+ if (diff == -1 && requestedDiff == -1 && index >= 0 && index <= x) {
+ //add point
+ m_oldPoints.insert(index, index > 0 ? newPoints[index - 1] : newPoints[index]);
+ m_index = index;
+ m_type = AddPointAnimation;
+ }
+
+ x = m_oldPoints.count();
+ y = m_newPoints.count();
+
+ if (x != y)
+ m_type = NewAnimation;
+ else if (m_type == NewAnimation)
+ m_type = ReplacePointAnimation;
+
+ setKeyValueAt(0.0, qVariantFromValue(m_oldPoints));
+ setKeyValueAt(1.0, qVariantFromValue(m_newPoints));
+}
+
+QVariant XYAnimation::interpolated(const QVariant &start, const QVariant &end, qreal progress) const
+{
+ QVector<QPointF> startVector = qvariant_cast<QVector<QPointF> >(start);
+ QVector<QPointF> endVector = qvariant_cast<QVector<QPointF> >(end);
+ QVector<QPointF> result;
+
+ switch (m_type) {
+
+ case ReplacePointAnimation:
+ case AddPointAnimation:
+ case RemovePointAnimation: {
+ if (startVector.count() != endVector.count())
+ break;
+
+ for (int i = 0; i < startVector.count(); i++) {
+ qreal x = startVector[i].x() + ((endVector[i].x() - startVector[i].x()) * progress);
+ qreal y = startVector[i].y() + ((endVector[i].y() - startVector[i].y()) * progress);
+ result << QPointF(x, y);
+ }
+
+ }
+ break;
+ case NewAnimation: {
+ for (int i = 0; i < endVector.count() * qBound(qreal(0), progress, qreal(1)); i++)
+ result << endVector[i];
+ }
+ break;
+ default:
+ qWarning() << "Unknown type of animation";
+ break;
+ }
+
+ return qVariantFromValue(result);
+}
+
+void XYAnimation::updateCurrentValue(const QVariant &value)
+{
+ if (state() != QAbstractAnimation::Stopped) { //workaround
+
+ QVector<QPointF> vector = qvariant_cast<QVector<QPointF> >(value);
+ m_item->setGeometryPoints(vector);
+ m_item->updateGeometry();
+ m_item->setDirty(true);
+ m_dirty = false;
+
+ }
+}
+
+void XYAnimation::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
+{
+ if (oldState == QAbstractAnimation::Running && newState == QAbstractAnimation::Stopped) {
+ if (m_item->isDirty() && m_type == RemovePointAnimation) {
+ if (!m_newPoints.isEmpty())
+ m_newPoints.remove(m_index);
+ m_item->setGeometryPoints(m_newPoints);
+ }
+ }
+}
+
+#include "moc_chartanimation_p.cpp"
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/animations/xyanimation_p.h b/src/charts/animations/xyanimation_p.h
new file mode 100644
index 00000000..ef54c530
--- /dev/null
+++ b/src/charts/animations/xyanimation_p.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 XYANIMATION_P_H
+#define XYANIMATION_P_H
+
+#include "chartanimation_p.h"
+#include <QPointF>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class XYChart;
+
+class XYAnimation : public ChartAnimation
+{
+protected:
+ enum Animation { AddPointAnimation, RemovePointAnimation, ReplacePointAnimation, NewAnimation };
+public:
+ XYAnimation(XYChart *item);
+ ~XYAnimation();
+ void setup(const QVector<QPointF> &oldPoints, const QVector<QPointF> &newPoints, int index = -1);
+ Animation animationType() const { return m_type; };
+
+protected:
+ QVariant interpolated(const QVariant &start, const QVariant &end, qreal progress) const;
+ void updateCurrentValue(const QVariant &value);
+ void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState);
+ XYChart *chartItem() { return m_item; }
+protected:
+ Animation m_type;
+ bool m_dirty;
+ int m_index;
+private:
+ XYChart *m_item;
+ QVector<QPointF> m_oldPoints;
+ QVector<QPointF> m_newPoints;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/areachart/areachart.pri b/src/charts/areachart/areachart.pri
new file mode 100644
index 00000000..af5fa608
--- /dev/null
+++ b/src/charts/areachart/areachart.pri
@@ -0,0 +1,13 @@
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+
+SOURCES += \
+ $$PWD/areachartitem.cpp \
+ $$PWD/qareaseries.cpp
+
+PRIVATE_HEADERS += \
+ $$PWD/areachartitem_p.h \
+ $$PWD/qareaseries_p.h
+
+PUBLIC_HEADERS += \
+ $$PWD/qareaseries.h \ No newline at end of file
diff --git a/src/charts/areachart/areachartitem.cpp b/src/charts/areachart/areachartitem.cpp
new file mode 100644
index 00000000..cf2d0e8f
--- /dev/null
+++ b/src/charts/areachart/areachartitem.cpp
@@ -0,0 +1,262 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "areachartitem_p.h"
+#include "qareaseries.h"
+#include "qareaseries_p.h"
+#include "qlineseries.h"
+#include "chartpresenter_p.h"
+#include "abstractdomain_p.h"
+#include <QPainter>
+#include <QGraphicsSceneMouseEvent>
+#include <QDebug>
+
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+AreaChartItem::AreaChartItem(QAreaSeries *areaSeries, QGraphicsItem* item)
+ : ChartItem(areaSeries->d_func(),item),
+ m_series(areaSeries),
+ m_upper(0),
+ m_lower(0),
+ m_pointsVisible(false),
+ m_pointLabelsVisible(false),
+ m_pointLabelsFormat(areaSeries->pointLabelsFormat()),
+ m_pointLabelsFont(areaSeries->pointLabelsFont()),
+ m_pointLabelsColor(areaSeries->pointLabelsColor())
+{
+ setAcceptHoverEvents(true);
+ setZValue(ChartPresenter::LineChartZValue);
+ if (m_series->upperSeries())
+ m_upper = new AreaBoundItem(this, m_series->upperSeries());
+ if (m_series->lowerSeries())
+ m_lower = new AreaBoundItem(this, m_series->lowerSeries());
+
+ QObject::connect(m_series->d_func(), SIGNAL(updated()), this, SLOT(handleUpdated()));
+ QObject::connect(m_series, SIGNAL(visibleChanged()), this, SLOT(handleUpdated()));
+ QObject::connect(m_series, SIGNAL(opacityChanged()), this, SLOT(handleUpdated()));
+ QObject::connect(this, SIGNAL(clicked(QPointF)), areaSeries, SIGNAL(clicked(QPointF)));
+ QObject::connect(this, SIGNAL(hovered(QPointF,bool)), areaSeries, SIGNAL(hovered(QPointF,bool)));
+ QObject::connect(areaSeries, SIGNAL(pointLabelsFormatChanged(QString)),
+ this, SLOT(handleUpdated()));
+ QObject::connect(areaSeries, SIGNAL(pointLabelsVisibilityChanged(bool)),
+ this, SLOT(handleUpdated()));
+ QObject::connect(areaSeries, SIGNAL(pointLabelsFontChanged(QFont)),
+ this, SLOT(handleUpdated()));
+ QObject::connect(areaSeries, SIGNAL(pointLabelsColorChanged(QColor)),
+ this, SLOT(handleUpdated()));
+
+ handleUpdated();
+}
+
+AreaChartItem::~AreaChartItem()
+{
+ delete m_upper;
+ delete m_lower;
+}
+
+void AreaChartItem::setPresenter(ChartPresenter *presenter)
+{
+ if (m_upper)
+ m_upper->setPresenter(presenter);
+ if (m_lower) {
+ m_lower->setPresenter(presenter);
+ }
+ ChartItem::setPresenter(presenter);
+}
+
+QRectF AreaChartItem::boundingRect() const
+{
+ return m_rect;
+}
+
+QPainterPath AreaChartItem::shape() const
+{
+ return m_path;
+}
+
+void AreaChartItem::updatePath()
+{
+ QPainterPath path;
+ QRectF rect(QPointF(0,0),domain()->size());
+
+ path = m_upper->path();
+
+ if (m_lower) {
+ // Note: Polarcharts always draw area correctly only when both series have equal width or are
+ // fully displayed. If one series is partally off-chart, the connecting line between
+ // the series does not attach to the end of the partially hidden series but to the point
+ // where it intersects the axis line. The problem is especially noticeable when one of the series
+ // is entirely off-chart, in which case the connecting line connects two ends of the
+ // visible series.
+ // This happens because we get the paths from linechart, which omits off-chart segments.
+ // To properly fix, linechart would need to provide true full path, in right, left, and the rest
+ // portions to enable proper clipping. However, combining those to single visually unified area
+ // would be a nightmare, since they would have to be painted separately.
+ path.connectPath(m_lower->path().toReversed());
+ } else {
+ QPointF first = path.pointAtPercent(0);
+ QPointF last = path.pointAtPercent(1);
+ if (presenter()->chartType() == QChart::ChartTypeCartesian) {
+ path.lineTo(last.x(), rect.bottom());
+ path.lineTo(first.x(), rect.bottom());
+ } else { // polar
+ path.lineTo(rect.center());
+ }
+ }
+ path.closeSubpath();
+
+ // Only zoom in if the bounding rect of the path fits inside int limits. QWidget::update() uses
+ // a region that has to be compatible with QRect.
+ if (path.boundingRect().height() <= INT_MAX
+ && path.boundingRect().width() <= INT_MAX) {
+ prepareGeometryChange();
+ m_path = path;
+ m_rect = path.boundingRect();
+ update();
+ }
+}
+
+void AreaChartItem::handleUpdated()
+{
+ setVisible(m_series->isVisible());
+ m_pointsVisible = m_series->pointsVisible();
+ m_linePen = m_series->pen();
+ m_brush = m_series->brush();
+ m_pointPen = m_series->pen();
+ m_pointPen.setWidthF(2 * m_pointPen.width());
+ setOpacity(m_series->opacity());
+ m_pointLabelsFormat = m_series->pointLabelsFormat();
+ m_pointLabelsVisible = m_series->pointLabelsVisible();
+ m_pointLabelsFont = m_series->pointLabelsFont();
+ m_pointLabelsColor = m_series->pointLabelsColor();
+ update();
+}
+
+void AreaChartItem::handleDomainUpdated()
+{
+ if (m_upper) {
+ AbstractDomain* d = m_upper->domain();
+ d->setSize(domain()->size());
+ d->setRange(domain()->minX(),domain()->maxX(),domain()->minY(),domain()->maxY());
+ m_upper->handleDomainUpdated();
+ }
+
+ if (m_lower) {
+ AbstractDomain* d = m_lower->domain();
+ d->setSize(domain()->size());
+ d->setRange(domain()->minX(),domain()->maxX(),domain()->minY(),domain()->maxY());
+ m_lower->handleDomainUpdated();
+ }
+}
+
+void AreaChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(widget)
+ Q_UNUSED(option)
+ painter->save();
+ painter->setPen(m_linePen);
+ painter->setBrush(m_brush);
+ QRectF clipRect = QRectF(QPointF(0, 0), domain()->size());
+ if (presenter()->chartType() == QChart::ChartTypePolar)
+ painter->setClipRegion(QRegion(clipRect.toRect(), QRegion::Ellipse));
+ else
+ painter->setClipRect(clipRect);
+ painter->drawPath(m_path);
+ if (m_pointsVisible) {
+ painter->setPen(m_pointPen);
+ painter->drawPoints(m_upper->geometryPoints());
+ if (m_lower)
+ painter->drawPoints(m_lower->geometryPoints());
+ }
+
+ // Draw series point label
+ if (m_pointLabelsVisible) {
+ static const QString xPointTag(QLatin1String("@xPoint"));
+ static const QString yPointTag(QLatin1String("@yPoint"));
+ const int labelOffset = 2;
+
+ painter->setFont(m_pointLabelsFont);
+ painter->setPen(QPen(m_pointLabelsColor));
+ QFontMetrics fm(painter->font());
+
+ QString pointLabel = m_pointLabelsFormat;
+
+ if (m_series->upperSeries()) {
+ for (int i(0); i < m_series->upperSeries()->count(); i++) {
+ pointLabel.replace(xPointTag,
+ presenter()->numberToString(m_series->upperSeries()->at(i).x()));
+ pointLabel.replace(yPointTag,
+ presenter()->numberToString(m_series->upperSeries()->at(i).y()));
+
+ // Position text in relation to the point
+ int pointLabelWidth = fm.width(pointLabel);
+ QPointF position(m_upper->geometryPoints().at(i));
+ position.setX(position.x() - pointLabelWidth / 2);
+ position.setY(position.y() - m_series->upperSeries()->pen().width() / 2 - labelOffset);
+
+ painter->drawText(position, pointLabel);
+ }
+ }
+
+ if (m_series->lowerSeries()) {
+ for (int i(0); i < m_series->lowerSeries()->count(); i++) {
+ pointLabel.replace(xPointTag,
+ presenter()->numberToString(m_series->lowerSeries()->at(i).x()));
+ pointLabel.replace(yPointTag,
+ presenter()->numberToString(m_series->lowerSeries()->at(i).y()));
+
+ // Position text in relation to the point
+ int pointLabelWidth = fm.width(pointLabel);
+ QPointF position(m_lower->geometryPoints().at(i));
+ position.setX(position.x() - pointLabelWidth / 2);
+ position.setY(position.y() - m_series->lowerSeries()->pen().width() / 2 - labelOffset);
+
+ painter->drawText(position, pointLabel);
+ }
+ }
+ }
+
+ painter->restore();
+}
+
+void AreaChartItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ emit clicked(m_upper->domain()->calculateDomainPoint(event->pos()));
+ ChartItem::mousePressEvent(event);
+}
+
+void AreaChartItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
+{
+ emit hovered(domain()->calculateDomainPoint(event->pos()), true);
+ event->accept();
+// QGraphicsItem::hoverEnterEvent(event);
+}
+
+void AreaChartItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
+{
+ emit hovered(domain()->calculateDomainPoint(event->pos()), false);
+ event->accept();
+// QGraphicsItem::hoverEnterEvent(event);
+}
+
+#include "moc_areachartitem_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/areachart/areachartitem_p.h b/src/charts/areachart/areachartitem_p.h
new file mode 100644
index 00000000..5f806af6
--- /dev/null
+++ b/src/charts/areachart/areachartitem_p.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 AREACHARTITEM_H
+#define AREACHARTITEM_H
+
+#include "qchartglobal.h"
+#include "linechartitem_p.h"
+#include "qareaseries.h"
+#include <QPen>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class AreaChartItem;
+
+class AreaChartItem : public ChartItem
+{
+ Q_OBJECT
+public:
+ AreaChartItem(QAreaSeries *areaSeries, QGraphicsItem* item = 0);
+ ~AreaChartItem();
+
+ //from QGraphicsItem
+ QRectF boundingRect() const;
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+ QPainterPath shape() const;
+
+ LineChartItem *upperLineItem() const { return m_upper; }
+ LineChartItem *lowerLineItem() const { return m_lower; }
+
+ void updatePath();
+
+ void setPresenter(ChartPresenter *presenter);
+ QAreaSeries *series() const { return m_series; }
+
+protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
+ void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
+
+Q_SIGNALS:
+ void clicked(const QPointF &point);
+ void hovered(const QPointF &point, bool state);
+
+public Q_SLOTS:
+ void handleUpdated();
+ void handleDomainUpdated();
+
+private:
+ QAreaSeries *m_series;
+ LineChartItem *m_upper;
+ LineChartItem *m_lower;
+ QPainterPath m_path;
+ QRectF m_rect;
+ QPen m_linePen;
+ QPen m_pointPen;
+ QBrush m_brush;
+ bool m_pointsVisible;
+
+ bool m_pointLabelsVisible;
+ QString m_pointLabelsFormat;
+ QFont m_pointLabelsFont;
+ QColor m_pointLabelsColor;
+
+};
+
+class AreaBoundItem : public LineChartItem
+{
+public:
+ AreaBoundItem(AreaChartItem *area, QLineSeries *lineSeries,QGraphicsItem* item = 0)
+ : LineChartItem(lineSeries, item), m_item(area)
+ {
+ // We do not actually want to draw anything from LineChartItem.
+ // Drawing is done in AreaChartItem only.
+ setVisible(false);
+ }
+ ~AreaBoundItem() {}
+
+ void updateGeometry()
+ {
+ // Turn off points drawing from component line chart item, as that
+ // messes up the fill for area series.
+ suppressPoints();
+ // Component lineseries are not necessarily themselves on the chart,
+ // so get the chart type for them from area chart.
+ forceChartType(m_item->series()->chart()->chartType());
+ LineChartItem::updateGeometry();
+ m_item->updatePath();
+ }
+
+private:
+ AreaChartItem *m_item;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/areachart/qareaseries.cpp b/src/charts/areachart/qareaseries.cpp
new file mode 100644
index 00000000..e2a2ea2f
--- /dev/null
+++ b/src/charts/areachart/qareaseries.cpp
@@ -0,0 +1,657 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qareaseries.h"
+#include "qareaseries_p.h"
+#include "qlineseries.h"
+#include "areachartitem_p.h"
+#include "abstractdomain_p.h"
+#include "chartdataset_p.h"
+#include "charttheme_p.h"
+#include "qvalueaxis.h"
+#include "qarealegendmarker.h"
+#include "qchart_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QAreaSeries
+ \inmodule Qt Charts
+ \brief The QAreaSeries class is used for making area charts.
+
+ \mainclass
+
+ An area chart is used to show quantitative data. It is based on line chart, in the way that area between axis and the line
+ is emphasized with color. Since the area chart is based on line chart, QAreaSeries constructor needs QLineSeries instance,
+ which defines "upper" boundary of the area. "Lower" boundary is defined by default by axis X. Instead of axis X "lower" boundary can be specified by other line.
+ In that case QAreaSeries should be initiated with two QLineSeries instances. Please note terms "upper" and "lower" boundary can be misleading in cases
+ where "lower" boundary had bigger values than the "upper" one, however the main point that area between these two boundary lines will be filled.
+
+ See the \l {AreaChart Example} {area chart example} to learn how to create a simple area chart.
+ \image examples_areachart.png
+*/
+
+/*!
+ \qmltype AreaSeries
+ \instantiates QAreaSeries
+ \inqmlmodule QtCharts
+
+ \inherits AbstractSeries
+
+ \brief The AreaSeries type is used for making area charts.
+
+ The following QML shows how to create a simple area chart:
+ \snippet qmlchart/qml/qmlchart/View4.qml 1
+ \beginfloatleft
+ \image examples_qmlchart4.png
+ \endfloat
+ \clearfloat
+*/
+
+/*!
+ \property QAreaSeries::upperSeries
+ \brief The upper one of the two line series used to define area series boundaries.
+*/
+/*!
+ \qmlproperty LineSeries AreaSeries::upperSeries
+ The upper one of the two line series used to define area series boundaries.
+*/
+
+/*!
+ \property QAreaSeries::lowerSeries
+ The lower one of the two line series used to define are series boundaries. Note if
+ QAreaSeries was constructed without a\ lowerSeries this is null.
+*/
+/*!
+ \qmlproperty LineSeries AreaSeries::lowerSeries
+ The lower one of the two line series used to define are series boundaries. Note if
+ AreaSeries was constructed without a\ lowerSeries this is null.
+*/
+
+/*!
+ \property QAreaSeries::color
+ Fill (brush) color of the series. This is a convenience property for modifying the color of brush.
+ \sa QAreaSeries::brush()
+*/
+/*!
+ \qmlproperty color AreaSeries::color
+ Fill (brush) color of the series.
+*/
+
+/*!
+ \property QAreaSeries::borderColor
+ Line (pen) color of the series. This is a convenience property for modifying the color of pen.
+ \sa QAreaSeries::pen()
+*/
+/*!
+ \qmlproperty color AreaSeries::borderColor
+ Line (pen) color of the series.
+*/
+
+/*!
+ \qmlproperty real AreaSeries::borderWidth
+ The width of the border line. By default the width is 2.0.
+*/
+
+/*!
+ \fn QPen QAreaSeries::pen() const
+ \brief Returns the pen used to draw line for this series.
+ \sa setPen()
+*/
+
+/*!
+ \fn QPen QAreaSeries::brush() const
+ \brief Returns the brush used to draw line for this series.
+ \sa setBrush()
+*/
+
+/*!
+ \qmlproperty QString AreaSeries::brushFilename
+ The name of the file used as a brush image for the series.
+*/
+
+/*!
+ \fn void QAreaSeries::colorChanged(QColor color)
+ \brief Signal is emitted when the fill (brush) color has changed to \a color.
+*/
+/*!
+ \qmlsignal AreaSeries::onColorChanged(color color)
+ Signal is emitted when the fill (brush) color has changed to \a color.
+*/
+
+/*!
+ \fn void QAreaSeries::borderColorChanged(QColor color)
+ \brief Signal is emitted when the line (pen) color has changed to \a color.
+*/
+/*!
+ \qmlsignal AreaSeries::onBorderColorChanged(color color)
+ Signal is emitted when the line (pen) color has changed to \a color.
+*/
+
+/*!
+ \fn void QAreaSeries::clicked(const QPointF& point)
+ \brief Signal is emitted when user clicks the \a point on area chart.
+*/
+/*!
+ \qmlsignal AreaSeries::onClicked(QPointF point)
+ Signal is emitted when user clicks the \a point on area chart.
+*/
+
+/*!
+ \fn void QAreaSeries::hovered(const QPointF &point, bool state)
+ This signal is emitted when user has hovered over or away from the series. \a point shows the origin (coordinate)
+ of the hover event. \a state is true when user has hovered over the series and false when hover has moved away from
+ the series.
+*/
+/*!
+ \qmlsignal AreaSeries::onHovered(point point, bool state)
+ This signal is emitted when user has hovered over or away from the series. \a point shows the origin (coordinate)
+ of the hover event. \a state is true when user has hovered over the series and false when hover has moved away from
+ the series.
+*/
+
+/*!
+ \fn void QAreaSeries::selected()
+ The signal is emitted if the user selects/deselects the XY series. The logic for maintaining selections should be
+ implemented by the user of QAreaSeries API.
+*/
+/*!
+ \qmlsignal AreaSeries::onSelected()
+ The signal is emitted if the user selects/deselects the XY series. The logic for maintaining selections should be
+ implemented by the user of AreaSeries API.
+*/
+
+/*!
+ \fn void QAreaSeriesPrivate::updated()
+ \brief \internal
+*/
+
+/*!
+ \property QAreaSeries::pointLabelsFormat
+ The \a format used for showing labels with series points.
+
+ QAreaSeries supports the following format tags:
+ \table
+ \row
+ \li @xPoint \li The x value of the data point
+ \row
+ \li @yPoint \li The y value of the data point
+ \endtable
+
+ For example, the following usage of the format tags would produce labels that have the data
+ point (x, y) shown inside brackets separated by a comma:
+ \code
+ series->setPointLabelsFormat("(@xPoint, @yPoint)");
+ \endcode
+
+ By default, the labels format is set to '@xPoint, @yPoint'. The labels are shown on the plot
+ area, labels on the edge of the plot area are cut. If the points are close to each other the
+ labels may overlap.
+
+ \sa QAreaSeries::pointLabelsVisible, QAreaSeries::pointLabelsFont, QAreaSeries::pointLabelsColor
+*/
+/*!
+ \qmlproperty string AreaSeries::pointLabelsFormat
+ The \a format used for showing labels with series points.
+
+ \sa QAreaSeries::pointLabelsFormat, pointLabelsVisible, pointLabelsFont, pointLabelsColor
+*/
+/*!
+ \fn void QAreaSeries::pointLabelsFormatChanged(const QString &format)
+ Signal is emitted when the \a format of data point labels is changed.
+*/
+/*!
+ \qmlsignal AreaSeries::onPointLabelsFormatChanged(string format)
+ Signal is emitted when the \a format of data point labels is changed.
+*/
+
+/*!
+ \property QAreaSeries::pointLabelsVisible
+ Defines the visibility for data point labels. False by default.
+
+ \sa QAreaSeries::pointLabelsFormat
+*/
+/*!
+ \qmlproperty bool AreaSeries::pointLabelsVisible
+ Defines the visibility for data point labels.
+
+ \sa pointLabelsFormat
+*/
+/*!
+ \fn void QAreaSeries::pointLabelsVisibilityChanged(bool visible)
+ The visibility of the data point labels is changed to \a visible.
+*/
+/*!
+ \qmlsignal AreaSeries::onPointLabelsVisibilityChanged(bool visible)
+ The visibility of the data point labels is changed to \a visible.
+*/
+
+/*!
+ \property QAreaSeries::pointLabelsFont
+ Defines the font used for data point labels.
+
+ \sa QAreaSeries::pointLabelsFormat
+*/
+/*!
+ \qmlproperty font AreaSeries::pointLabelsFont
+ Defines the font used for data point labels.
+
+ \sa pointLabelsFormat
+*/
+/*!
+ \fn void QAreaSeries::pointLabelsFontChanged(const QFont &font);
+ The font used for data point labels is changed to \a font.
+*/
+/*!
+ \qmlsignal AreaSeries::onPointLabelsFontChanged(Font font)
+ The font used for data point labels is changed to \a font.
+*/
+
+/*!
+ \property QAreaSeries::pointLabelsColor
+ Defines the color used for data point labels. By default, the color is the color of the brush
+ defined in theme for labels.
+
+ \sa QAreaSeries::pointLabelsFormat
+*/
+/*!
+ \qmlproperty font AreaSeries::pointLabelsColor
+ Defines the color used for data point labels. By default, the color is the color of the brush
+ defined in theme for labels.
+
+ \sa pointLabelsFormat
+*/
+/*!
+ \fn void QAreaSeries::pointLabelsColorChanged(const QColor &color);
+ The color used for data point labels is changed to \a color.
+*/
+/*!
+ \qmlsignal AreaSeries::onPointLabelsColorChanged(Color color)
+ The color used for data point labels is changed to \a color.
+*/
+
+/*!
+ Constructs area series object which is a child of \a upperSeries. Area will be spanned between \a
+ upperSeries line and \a lowerSeries line. If no \a lowerSeries is passed to constructor, area is specified by axis x (y=0) instead.
+ When series object is added to QChartView or QChart instance ownerships is transferred.
+*/
+QAreaSeries::QAreaSeries(QLineSeries *upperSeries, QLineSeries *lowerSeries)
+ : QAbstractSeries(*new QAreaSeriesPrivate(upperSeries, lowerSeries, this), upperSeries)
+{
+}
+
+/*!
+ Constructs area series object without upper or lower series with \a parent object.
+*/
+QAreaSeries::QAreaSeries(QObject *parent)
+ : QAbstractSeries(*new QAreaSeriesPrivate(0, 0, this), parent)
+{
+}
+
+/*!
+ Destroys the object.
+*/
+QAreaSeries::~QAreaSeries()
+{
+ Q_D(QAreaSeries);
+ if (d->m_chart)
+ d->m_chart->removeSeries(this);
+}
+
+/*!
+ Returns QAbstractSeries::SeriesTypeArea.
+*/
+QAbstractSeries::SeriesType QAreaSeries::type() const
+{
+ return QAbstractSeries::SeriesTypeArea;
+}
+
+/*!
+ Sets the \a series that is to be used as the area chart upper series.
+*/
+void QAreaSeries::setUpperSeries(QLineSeries *series)
+{
+ Q_D(QAreaSeries);
+ if (d->m_upperSeries != series)
+ d->m_upperSeries = series;
+}
+
+QLineSeries *QAreaSeries::upperSeries() const
+{
+ Q_D(const QAreaSeries);
+ return d->m_upperSeries;
+}
+
+/*!
+ Sets the \a series that is to be used as the area chart lower series.
+*/
+void QAreaSeries::setLowerSeries(QLineSeries *series)
+{
+ Q_D(QAreaSeries);
+ d->m_lowerSeries = series;
+}
+
+QLineSeries *QAreaSeries::lowerSeries() const
+{
+ Q_D(const QAreaSeries);
+ return d->m_lowerSeries;
+}
+
+/*!
+ Sets \a pen used for drawing area outline.
+*/
+void QAreaSeries::setPen(const QPen &pen)
+{
+ Q_D(QAreaSeries);
+ if (d->m_pen != pen) {
+ d->m_pen = pen;
+ emit d->updated();
+ }
+}
+
+QPen QAreaSeries::pen() const
+{
+ Q_D(const QAreaSeries);
+ if (d->m_pen == QChartPrivate::defaultPen())
+ return QPen();
+ else
+ return d->m_pen;
+}
+
+/*!
+ Sets \a brush used for filling the area.
+*/
+void QAreaSeries::setBrush(const QBrush &brush)
+{
+ Q_D(QAreaSeries);
+ if (d->m_brush != brush) {
+ bool emitColorChanged = brush.color() != d->m_brush.color();
+ d->m_brush = brush;
+ emit d->updated();
+ if (emitColorChanged)
+ emit colorChanged(brush.color());
+ }
+}
+
+QBrush QAreaSeries::brush() const
+{
+ Q_D(const QAreaSeries);
+ if (d->m_brush == QChartPrivate::defaultBrush())
+ return QBrush();
+ else
+ return d->m_brush;
+}
+
+void QAreaSeries::setColor(const QColor &color)
+{
+ QBrush b = brush();
+ if (b == QBrush())
+ b.setStyle(Qt::SolidPattern);
+ b.setColor(color);
+ setBrush(b);
+}
+
+QColor QAreaSeries::color() const
+{
+ return brush().color();
+}
+
+void QAreaSeries::setBorderColor(const QColor &color)
+{
+ QPen p = pen();
+ if (p.color() != color) {
+ p.setColor(color);
+ setPen(p);
+ emit borderColorChanged(color);
+ }
+}
+
+QColor QAreaSeries::borderColor() const
+{
+ return pen().color();
+}
+
+/*!
+ Sets if data points are \a visible and should be drawn on line.
+*/
+void QAreaSeries::setPointsVisible(bool visible)
+{
+ Q_D(QAreaSeries);
+ if (d->m_pointsVisible != visible) {
+ d->m_pointsVisible = visible;
+ emit d->updated();
+ }
+}
+
+/*!
+ Returns if the points are drawn for this series.
+ \sa setPointsVisible()
+*/
+bool QAreaSeries::pointsVisible() const
+{
+ Q_D(const QAreaSeries);
+ return d->m_pointsVisible;
+}
+
+void QAreaSeries::setPointLabelsFormat(const QString &format)
+{
+ Q_D(QAreaSeries);
+ if (d->m_pointLabelsFormat != format) {
+ d->m_pointLabelsFormat = format;
+ emit pointLabelsFormatChanged(format);
+ }
+}
+
+QString QAreaSeries::pointLabelsFormat() const
+{
+ Q_D(const QAreaSeries);
+ return d->m_pointLabelsFormat;
+}
+
+void QAreaSeries::setPointLabelsVisible(bool visible)
+{
+ Q_D(QAreaSeries);
+ if (d->m_pointLabelsVisible != visible) {
+ d->m_pointLabelsVisible = visible;
+ emit pointLabelsVisibilityChanged(visible);
+ }
+}
+
+bool QAreaSeries::pointLabelsVisible() const
+{
+ Q_D(const QAreaSeries);
+ return d->m_pointLabelsVisible;
+}
+
+void QAreaSeries::setPointLabelsFont(const QFont &font)
+{
+ Q_D(QAreaSeries);
+ if (d->m_pointLabelsFont != font) {
+ d->m_pointLabelsFont = font;
+ emit pointLabelsFontChanged(font);
+ }
+}
+
+QFont QAreaSeries::pointLabelsFont() const
+{
+ Q_D(const QAreaSeries);
+ return d->m_pointLabelsFont;
+}
+
+void QAreaSeries::setPointLabelsColor(const QColor &color)
+{
+ Q_D(QAreaSeries);
+ if (d->m_pointLabelsColor != color) {
+ d->m_pointLabelsColor = color;
+ emit pointLabelsColorChanged(color);
+ }
+}
+
+QColor QAreaSeries::pointLabelsColor() const
+{
+ Q_D(const QAreaSeries);
+ if (d->m_pointLabelsColor == QChartPrivate::defaultPen().color())
+ return QPen().color();
+ else
+ return d->m_pointLabelsColor;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QAreaSeriesPrivate::QAreaSeriesPrivate(QLineSeries *upperSeries, QLineSeries *lowerSeries, QAreaSeries *q)
+ : QAbstractSeriesPrivate(q),
+ m_brush(QChartPrivate::defaultBrush()),
+ m_pen(QChartPrivate::defaultPen()),
+ m_upperSeries(upperSeries),
+ m_lowerSeries(lowerSeries),
+ m_pointsVisible(false),
+ m_pointLabelsFormat(QLatin1String("@xPoint, @yPoint")),
+ m_pointLabelsVisible(false),
+ m_pointLabelsFont(QChartPrivate::defaultFont()),
+ m_pointLabelsColor(QChartPrivate::defaultPen().color())
+{
+}
+
+void QAreaSeriesPrivate::initializeDomain()
+{
+ Q_Q(QAreaSeries);
+
+ qreal minX(domain()->minX());
+ qreal minY(domain()->minY());
+ qreal maxX(domain()->maxX());
+ qreal maxY(domain()->maxY());
+
+ QLineSeries *upperSeries = q->upperSeries();
+ QLineSeries *lowerSeries = q->lowerSeries();
+
+ if (upperSeries) {
+ const QList<QPointF>& points = upperSeries->points();
+
+ for (int i = 0; i < points.count(); i++) {
+ qreal x = points[i].x();
+ qreal y = points[i].y();
+ minX = qMin(minX, x);
+ minY = qMin(minY, y);
+ maxX = qMax(maxX, x);
+ maxY = qMax(maxY, y);
+ }
+ }
+ if (lowerSeries) {
+
+ const QList<QPointF>& points = lowerSeries->points();
+
+ for (int i = 0; i < points.count(); i++) {
+ qreal x = points[i].x();
+ qreal y = points[i].y();
+ minX = qMin(minX, x);
+ minY = qMin(minY, y);
+ maxX = qMax(maxX, x);
+ maxY = qMax(maxY, y);
+ }
+ }
+
+ domain()->setRange(minX, maxX, minY, maxY);
+}
+
+void QAreaSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
+{
+ Q_Q(QAreaSeries);
+ AreaChartItem *area = new AreaChartItem(q,parent);
+ m_item.reset(area);
+ QAbstractSeriesPrivate::initializeGraphics(parent);
+}
+void QAreaSeriesPrivate::initializeAnimations(QChart::AnimationOptions options)
+{
+ Q_Q(QAreaSeries);
+ AreaChartItem *area = static_cast<AreaChartItem *>(m_item.data());
+
+ if (q->upperSeries() && area->upperLineItem()->animation())
+ area->upperLineItem()->animation()->stopAndDestroyLater();
+ if (q->lowerSeries() && area->lowerLineItem()->animation())
+ area->lowerLineItem()->animation()->stopAndDestroyLater();
+
+ if (options.testFlag(QChart::SeriesAnimations)) {
+ area->upperLineItem()->setAnimation(new XYAnimation(area->upperLineItem()));
+ if (q->lowerSeries())
+ area->lowerLineItem()->setAnimation(new XYAnimation(area->lowerLineItem()));
+ } else {
+ if (q->upperSeries())
+ area->upperLineItem()->setAnimation(0);
+ if (q->lowerSeries())
+ area->lowerLineItem()->setAnimation(0);
+ }
+ QAbstractSeriesPrivate::initializeAnimations(options);
+}
+
+QList<QLegendMarker*> QAreaSeriesPrivate::createLegendMarkers(QLegend* legend)
+{
+ Q_Q(QAreaSeries);
+ QList<QLegendMarker*> list;
+ return list << new QAreaLegendMarker(q,legend);
+}
+
+
+void QAreaSeriesPrivate::initializeAxes()
+{
+
+}
+
+QAbstractAxis::AxisType QAreaSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
+{
+ Q_UNUSED(orientation);
+ return QAbstractAxis::AxisTypeValue;
+}
+
+QAbstractAxis* QAreaSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const
+{
+ Q_UNUSED(orientation);
+ return new QValueAxis;
+}
+
+void QAreaSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
+{
+ Q_Q(QAreaSeries);
+
+ const QList<QGradient> gradients = theme->seriesGradients();
+ const QList<QColor> colors = theme->seriesColors();
+
+ if (forced || QChartPrivate::defaultPen() == m_pen) {
+ QPen pen;
+ pen.setColor(ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0.0));
+ pen.setWidthF(2);
+ q->setPen(pen);
+ }
+
+ if (forced || QChartPrivate::defaultBrush() == m_brush) {
+ QBrush brush(colors.at(index % colors.size()));
+ q->setBrush(brush);
+ }
+
+ if (forced || QChartPrivate::defaultPen().color() == m_pointLabelsColor) {
+ QColor color = theme->labelBrush().color();
+ q->setPointLabelsColor(color);
+ }
+}
+
+
+#include "moc_qareaseries.cpp"
+#include "moc_qareaseries_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/areachart/qareaseries.h b/src/charts/areachart/qareaseries.h
new file mode 100644
index 00000000..cad15c77
--- /dev/null
+++ b/src/charts/areachart/qareaseries.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QAREASERIES_H
+#define QAREASERIES_H
+
+#include <QtCharts/qchartglobal.h>
+#include <QtCharts/qabstractseries.h>
+#include <QPen>
+#include <QBrush>
+
+QT_CHARTS_BEGIN_NAMESPACE
+class QLineSeries;
+class QAreaSeriesPrivate;
+
+class QT_CHARTS_EXPORT QAreaSeries : public QAbstractSeries
+{
+ Q_OBJECT
+ Q_PROPERTY(QLineSeries *upperSeries READ upperSeries)
+ Q_PROPERTY(QLineSeries *lowerSeries READ lowerSeries)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+ Q_PROPERTY(QColor borderColor READ borderColor WRITE setBorderColor NOTIFY borderColorChanged)
+ Q_PROPERTY(QString pointLabelsFormat READ pointLabelsFormat WRITE setPointLabelsFormat NOTIFY pointLabelsFormatChanged)
+ Q_PROPERTY(bool pointLabelsVisible READ pointLabelsVisible WRITE setPointLabelsVisible NOTIFY pointLabelsVisibilityChanged)
+ Q_PROPERTY(QFont pointLabelsFont READ pointLabelsFont WRITE setPointLabelsFont NOTIFY pointLabelsFontChanged)
+ Q_PROPERTY(QColor pointLabelsColor READ pointLabelsColor WRITE setPointLabelsColor NOTIFY pointLabelsColorChanged)
+
+public:
+ explicit QAreaSeries(QObject *parent = 0);
+ explicit QAreaSeries(QLineSeries *upperSeries, QLineSeries *lowerSeries = 0);
+ ~QAreaSeries();
+
+public:
+ QAbstractSeries::SeriesType type() const;
+
+ void setUpperSeries(QLineSeries *series);
+ QLineSeries *upperSeries() const;
+ void setLowerSeries(QLineSeries *series);
+ QLineSeries *lowerSeries() const;
+
+ void setPen(const QPen &pen);
+ QPen pen() const;
+
+ void setBrush(const QBrush &brush);
+ QBrush brush() const;
+
+ void setColor(const QColor &color);
+ QColor color() const;
+
+ void setBorderColor(const QColor &color);
+ QColor borderColor() const;
+
+ void setPointsVisible(bool visible = true);
+ bool pointsVisible() const;
+
+ void setPointLabelsFormat(const QString &format);
+ QString pointLabelsFormat() const;
+
+ void setPointLabelsVisible(bool visible = true);
+ bool pointLabelsVisible() const;
+
+ void setPointLabelsFont(const QFont &font);
+ QFont pointLabelsFont() const;
+
+ void setPointLabelsColor(const QColor &color);
+ QColor pointLabelsColor() const;
+
+Q_SIGNALS:
+ void clicked(const QPointF &point);
+ void hovered(const QPointF &point, bool state);
+ void selected();
+ void colorChanged(QColor color);
+ void borderColorChanged(QColor color);
+ void pointLabelsFormatChanged(const QString &format);
+ void pointLabelsVisibilityChanged(bool visible);
+ void pointLabelsFontChanged(const QFont &font);
+ void pointLabelsColorChanged(const QColor &color);
+
+private:
+ Q_DECLARE_PRIVATE(QAreaSeries)
+ Q_DISABLE_COPY(QAreaSeries)
+ friend class AreaLegendMarker;
+ friend class AreaChartItem;
+ friend class QAreaLegendMarkerPrivate;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QAREASERIES_H
diff --git a/src/charts/areachart/qareaseries_p.h b/src/charts/areachart/qareaseries_p.h
new file mode 100644
index 00000000..3f6293d3
--- /dev/null
+++ b/src/charts/areachart/qareaseries_p.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QAREASERIES_P_H
+#define QAREASERIES_P_H
+
+#include "qabstractseries_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QAreaSeries;
+
+class QAreaSeriesPrivate: public QAbstractSeriesPrivate
+{
+ Q_OBJECT
+
+public:
+ QAreaSeriesPrivate(QLineSeries *upperSeries, QLineSeries *lowerSeries, QAreaSeries *q);
+
+ void initializeDomain();
+ void initializeAxes();
+ void initializeGraphics(QGraphicsItem* parent);
+ void initializeTheme(int index, ChartTheme* theme, bool forced = false);
+ void initializeAnimations(QChart::AnimationOptions options);
+
+ QList<QLegendMarker *> createLegendMarkers(QLegend *legend);
+
+ QAbstractAxis::AxisType defaultAxisType(Qt::Orientation orientation) const;
+ QAbstractAxis* createDefaultAxis(Qt::Orientation) const;
+
+Q_SIGNALS:
+ void updated();
+
+protected:
+ QBrush m_brush;
+ QPen m_pen;
+ QLineSeries *m_upperSeries;
+ QLineSeries *m_lowerSeries;
+ bool m_pointsVisible;
+ QString m_pointLabelsFormat;
+ bool m_pointLabelsVisible;
+ QFont m_pointLabelsFont;
+ QColor m_pointLabelsColor;
+private:
+ Q_DECLARE_PUBLIC(QAreaSeries);
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/axis/axis.pri b/src/charts/axis/axis.pri
new file mode 100644
index 00000000..6f706aac
--- /dev/null
+++ b/src/charts/axis/axis.pri
@@ -0,0 +1,108 @@
+#Subdirectiores are defined here, because qt creator doesn't handle nested include(foo.pri) chains very well.
+
+INCLUDEPATH += $$PWD \
+ $$PWD/valueaxis \
+ $$PWD/barcategoryaxis \
+ $$PWD/categoryaxis \
+ $$PWD/logvalueaxis
+
+DEPENDPATH += $$PWD \
+ $$PWD/valueaxis \
+ $$PWD/barcategoryaxis \
+ $$PWD/categoryaxis \
+ $$PWD/logvalueaxis
+
+SOURCES += \
+ $$PWD/chartaxiselement.cpp \
+ $$PWD/cartesianchartaxis.cpp \
+ $$PWD/qabstractaxis.cpp \
+ $$PWD/verticalaxis.cpp \
+ $$PWD/horizontalaxis.cpp \
+ $$PWD/valueaxis/chartvalueaxisx.cpp \
+ $$PWD/valueaxis/chartvalueaxisy.cpp \
+ $$PWD/valueaxis/qvalueaxis.cpp \
+ $$PWD/barcategoryaxis/chartbarcategoryaxisx.cpp \
+ $$PWD/barcategoryaxis/chartbarcategoryaxisy.cpp \
+ $$PWD/barcategoryaxis/qbarcategoryaxis.cpp \
+ $$PWD/categoryaxis/chartcategoryaxisx.cpp \
+ $$PWD/categoryaxis/chartcategoryaxisy.cpp \
+ $$PWD/categoryaxis/qcategoryaxis.cpp \
+ $$PWD/logvalueaxis/chartlogvalueaxisx.cpp \
+ $$PWD/logvalueaxis/chartlogvalueaxisy.cpp \
+ $$PWD/logvalueaxis/qlogvalueaxis.cpp
+
+PRIVATE_HEADERS += \
+ $$PWD/chartaxiselement_p.h \
+ $$PWD/cartesianchartaxis_p.h \
+ $$PWD/qabstractaxis_p.h \
+ $$PWD/verticalaxis_p.h \
+ $$PWD/horizontalaxis_p.h \
+ $$PWD/linearrowitem_p.h \
+ $$PWD/valueaxis/chartvalueaxisx_p.h \
+ $$PWD/valueaxis/chartvalueaxisy_p.h \
+ $$PWD/valueaxis/qvalueaxis_p.h \
+ $$PWD/barcategoryaxis/chartbarcategoryaxisx_p.h \
+ $$PWD/barcategoryaxis/chartbarcategoryaxisy_p.h \
+ $$PWD/barcategoryaxis/qbarcategoryaxis_p.h \
+ $$PWD/categoryaxis/chartcategoryaxisx_p.h \
+ $$PWD/categoryaxis/chartcategoryaxisy_p.h \
+ $$PWD/categoryaxis/qcategoryaxis_p.h \
+ $$PWD/logvalueaxis/chartlogvalueaxisx_p.h \
+ $$PWD/logvalueaxis/chartlogvalueaxisy_p.h \
+ $$PWD/logvalueaxis/qlogvalueaxis_p.h
+
+PUBLIC_HEADERS += \
+ $$PWD/qabstractaxis.h \
+ $$PWD/valueaxis/qvalueaxis.h \
+ $$PWD/barcategoryaxis/qbarcategoryaxis.h \
+ $$PWD/categoryaxis/qcategoryaxis.h \
+ $$PWD/logvalueaxis/qlogvalueaxis.h \
+
+# polar
+SOURCES += \
+ $$PWD/polarchartaxis.cpp \
+ $$PWD/polarchartaxisangular.cpp \
+ $$PWD/polarchartaxisradial.cpp \
+ $$PWD/valueaxis/polarchartvalueaxisangular.cpp \
+ $$PWD/valueaxis/polarchartvalueaxisradial.cpp \
+ $$PWD/logvalueaxis/polarchartlogvalueaxisangular.cpp \
+ $$PWD/logvalueaxis/polarchartlogvalueaxisradial.cpp \
+ $$PWD/categoryaxis/polarchartcategoryaxisangular.cpp \
+ $$PWD/categoryaxis/polarchartcategoryaxisradial.cpp
+
+PRIVATE_HEADERS += \
+ $$PWD/polarchartaxis_p.h \
+ $$PWD/polarchartaxisangular_p.h \
+ $$PWD/polarchartaxisradial_p.h \
+ $$PWD/valueaxis/polarchartvalueaxisangular_p.h \
+ $$PWD/valueaxis/polarchartvalueaxisradial_p.h \
+ $$PWD/logvalueaxis/polarchartlogvalueaxisangular_p.h \
+ $$PWD/logvalueaxis/polarchartlogvalueaxisradial_p.h \
+ $$PWD/categoryaxis/polarchartcategoryaxisangular_p.h \
+ $$PWD/categoryaxis/polarchartcategoryaxisradial_p.h
+
+!linux-arm*: {
+INCLUDEPATH += \
+ $$PWD/datetimeaxis
+
+DEPENDPATH += \
+ $$PWD/datetimeaxis
+
+SOURCES += \
+ $$PWD/datetimeaxis/chartdatetimeaxisx.cpp \
+ $$PWD/datetimeaxis/chartdatetimeaxisy.cpp \
+ $$PWD/datetimeaxis/qdatetimeaxis.cpp \
+ $$PWD/datetimeaxis/polarchartdatetimeaxisangular.cpp \
+ $$PWD/datetimeaxis/polarchartdatetimeaxisradial.cpp
+
+PRIVATE_HEADERS += \
+ $$PWD/datetimeaxis/chartdatetimeaxisx_p.h \
+ $$PWD/datetimeaxis/chartdatetimeaxisy_p.h \
+ $$PWD/datetimeaxis/qdatetimeaxis_p.h \
+ $$PWD/datetimeaxis/polarchartdatetimeaxisangular_p.h \
+ $$PWD/datetimeaxis/polarchartdatetimeaxisradial_p.h
+
+PUBLIC_HEADERS += \
+ $$PWD/datetimeaxis/qdatetimeaxis.h
+}
+
diff --git a/src/charts/axis/barcategoryaxis/chartbarcategoryaxisx.cpp b/src/charts/axis/barcategoryaxis/chartbarcategoryaxisx.cpp
new file mode 100644
index 00000000..259cdaa9
--- /dev/null
+++ b/src/charts/axis/barcategoryaxis/chartbarcategoryaxisx.cpp
@@ -0,0 +1,140 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+ **
+ ** $QT_BEGIN_LICENSE$
+ ** 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
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include "chartbarcategoryaxisx_p.h"
+#include "chartpresenter_p.h"
+#include "qbarcategoryaxis_p.h"
+#include "abstractchartlayout_p.h"
+#include <QDebug>
+#include <qmath.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+ChartBarCategoryAxisX::ChartBarCategoryAxisX(QBarCategoryAxis *axis, QGraphicsItem* item)
+ : HorizontalAxis(axis, item, true),
+ m_categoriesAxis(axis)
+{
+ QObject::connect(m_categoriesAxis,SIGNAL(categoriesChanged()),this, SLOT(handleCategoriesChanged()));
+ handleCategoriesChanged();
+}
+
+ChartBarCategoryAxisX::~ChartBarCategoryAxisX()
+{
+}
+
+QVector<qreal> ChartBarCategoryAxisX::calculateLayout() const
+{
+ QVector<qreal> points;
+ const QRectF& gridRect = gridGeometry();
+ qreal range = max() - min();
+ const qreal delta = gridRect.width() / range;
+
+ if (delta < 2)
+ return points;
+
+ qreal adjustedMin = min() + 0.5;
+ qreal offset = (ceil(adjustedMin) - adjustedMin) * delta;
+
+ int count = qFloor(range);
+ if (count < 1)
+ return points;
+
+ points.resize(count + 2);
+
+ for (int i = 0; i < count + 2; ++i)
+ points[i] = offset + (qreal(i) * delta) + gridRect.left();
+
+ return points;
+}
+
+QStringList ChartBarCategoryAxisX::createCategoryLabels(const QVector<qreal>& layout) const
+{
+ QStringList result ;
+ const QRectF &gridRect = gridGeometry();
+ qreal d = (max() - min()) / gridRect.width();
+
+ for (int i = 0; i < layout.count() - 1; ++i) {
+ qreal x = qFloor((((layout[i] + layout[i + 1]) / 2 - gridRect.left()) * d + min() + 0.5));
+ if ((x < m_categoriesAxis->categories().count()) && (x >= 0)) {
+ result << m_categoriesAxis->categories().at(x);
+ } else {
+ // No label for x coordinate
+ result << QString();
+ }
+ }
+ result << QString();
+ return result;
+}
+
+
+void ChartBarCategoryAxisX::updateGeometry()
+{
+ const QVector<qreal>& layout = ChartAxisElement::layout();
+ if (layout.isEmpty())
+ return;
+ setLabels(createCategoryLabels(layout));
+ HorizontalAxis::updateGeometry();
+}
+
+void ChartBarCategoryAxisX::handleCategoriesChanged()
+{
+ QGraphicsLayoutItem::updateGeometry();
+ if(presenter()) presenter()->layout()->invalidate();
+}
+
+QSizeF ChartBarCategoryAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED(constraint)
+
+ QSizeF sh;
+ QSizeF base = HorizontalAxis::sizeHint(which, constraint);
+ QStringList ticksList = m_categoriesAxis->categories();
+
+ qreal width = 0; // Width is irrelevant for X axes with interval labels
+ qreal height = 0;
+
+ switch (which) {
+ case Qt::MinimumSize: {
+ QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(),
+ QStringLiteral("..."),
+ axis()->labelsAngle());
+ height = boundingRect.height() + labelPadding() + base.height() + 1.0;
+ sh = QSizeF(width, height);
+ break;
+ }
+ case Qt::PreferredSize:{
+ qreal labelHeight = 0.0;
+ foreach (const QString& s, ticksList) {
+ QRectF rect = ChartPresenter::textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
+ labelHeight = qMax(rect.height(), labelHeight);
+ }
+ height = labelHeight + labelPadding() + base.height() + 1.0;
+ sh = QSizeF(width, height);
+ break;
+ }
+ default:
+ break;
+ }
+ return sh;
+}
+
+#include "moc_chartbarcategoryaxisx_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/barcategoryaxis/chartbarcategoryaxisx_p.h b/src/charts/axis/barcategoryaxis/chartbarcategoryaxisx_p.h
new file mode 100644
index 00000000..177540e2
--- /dev/null
+++ b/src/charts/axis/barcategoryaxis/chartbarcategoryaxisx_p.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTBARCATEGORYAXISX_H
+#define CHARTBARCATEGORYAXISX_H
+
+#include "horizontalaxis_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class ChartPresenter;
+class QBarCategoryAxis;
+
+class ChartBarCategoryAxisX : public HorizontalAxis
+{
+ Q_OBJECT
+public:
+ ChartBarCategoryAxisX(QBarCategoryAxis *axis, QGraphicsItem* item = 0);
+ ~ChartBarCategoryAxisX();
+
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const;
+protected:
+ QVector<qreal> calculateLayout() const;
+ void updateGeometry();
+private:
+ QStringList createCategoryLabels(const QVector<qreal>& layout) const;
+public Q_SLOTS:
+ void handleCategoriesChanged();
+
+private:
+ QBarCategoryAxis *m_categoriesAxis;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif /* CHARTBARCATEGORYAXISX_H */
diff --git a/src/charts/axis/barcategoryaxis/chartbarcategoryaxisy.cpp b/src/charts/axis/barcategoryaxis/chartbarcategoryaxisy.cpp
new file mode 100644
index 00000000..126c7da3
--- /dev/null
+++ b/src/charts/axis/barcategoryaxis/chartbarcategoryaxisy.cpp
@@ -0,0 +1,142 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+ **
+ ** $QT_BEGIN_LICENSE$
+ ** 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
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include "chartbarcategoryaxisy_p.h"
+#include "chartpresenter_p.h"
+#include "qbarcategoryaxis_p.h"
+#include "abstractchartlayout_p.h"
+#include <qmath.h>
+#include <QDebug>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+ChartBarCategoryAxisY::ChartBarCategoryAxisY(QBarCategoryAxis *axis, QGraphicsItem* item)
+ : VerticalAxis(axis, item, true),
+ m_categoriesAxis(axis)
+{
+ QObject::connect( m_categoriesAxis,SIGNAL(categoriesChanged()),this, SLOT(handleCategoriesChanged()));
+ handleCategoriesChanged();
+}
+
+ChartBarCategoryAxisY::~ChartBarCategoryAxisY()
+{
+}
+
+QVector<qreal> ChartBarCategoryAxisY::calculateLayout() const
+{
+ QVector<qreal> points;
+ const QRectF& gridRect = gridGeometry();
+ qreal range = max() - min();
+ const qreal delta = gridRect.height() / range;
+
+ if (delta < 2)
+ return points;
+
+ qreal adjustedMin = min() + 0.5;
+ qreal offset = (ceil(adjustedMin) - adjustedMin) * delta;
+
+ int count = qFloor(range);
+ if (count < 1)
+ return points;
+
+ points.resize(count + 2);
+
+ for (int i = 0; i < count + 2; ++i)
+ points[i] = gridRect.bottom() - (qreal(i) * delta) - offset;
+
+ return points;
+}
+
+QStringList ChartBarCategoryAxisY::createCategoryLabels(const QVector<qreal>& layout) const
+{
+ QStringList result;
+ const QRectF &gridRect = gridGeometry();
+ qreal d = (max() - min()) / gridRect.height();
+
+ for (int i = 0; i < layout.count() - 1; ++i) {
+ qreal x = qFloor(((gridRect.height() - (layout[i + 1] + layout[i]) / 2 + gridRect.top()) * d + min() + 0.5));
+ if ((x < m_categoriesAxis->categories().count()) && (x >= 0)) {
+ result << m_categoriesAxis->categories().at(x);
+ } else {
+ // No label for x coordinate
+ result << QString();
+ }
+ }
+ result << QString();
+ return result;
+}
+
+void ChartBarCategoryAxisY::updateGeometry()
+{
+ const QVector<qreal>& layout = ChartAxisElement::layout();
+ if (layout.isEmpty())
+ return;
+ setLabels(createCategoryLabels(layout));
+ VerticalAxis::updateGeometry();
+}
+
+void ChartBarCategoryAxisY::handleCategoriesChanged()
+{
+ QGraphicsLayoutItem::updateGeometry();
+ if(presenter()) presenter()->layout()->invalidate();
+}
+
+QSizeF ChartBarCategoryAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED(constraint)
+
+ QSizeF sh;
+ QSizeF base = VerticalAxis::sizeHint(which, constraint);
+ QStringList ticksList = m_categoriesAxis->categories();
+ qreal width = 0;
+ qreal height = 0; // Height is irrelevant for Y axes with interval labels
+
+ switch (which) {
+ case Qt::MinimumSize: {
+ QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(),
+ QStringLiteral("..."),
+ axis()->labelsAngle());
+ width = boundingRect.width() + labelPadding() + base.width() + 1.0;
+ if (base.width() > 0.0)
+ width += labelPadding();
+ sh = QSizeF(width, height);
+ break;
+ }
+ case Qt::PreferredSize:{
+ qreal labelWidth = 0.0;
+ foreach (const QString& s, ticksList) {
+ QRectF rect = ChartPresenter::textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
+ labelWidth = qMax(rect.width(), labelWidth);
+ }
+ width = labelWidth + labelPadding() + base.width() + 1.0;
+ if (base.width() > 0.0)
+ width += labelPadding();
+ sh = QSizeF(width, height);
+ break;
+ }
+ default:
+ break;
+ }
+ return sh;
+}
+
+#include "moc_chartbarcategoryaxisy_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/barcategoryaxis/chartbarcategoryaxisy_p.h b/src/charts/axis/barcategoryaxis/chartbarcategoryaxisy_p.h
new file mode 100644
index 00000000..82f2c505
--- /dev/null
+++ b/src/charts/axis/barcategoryaxis/chartbarcategoryaxisy_p.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTBARCATEGORYAXISY_H
+#define CHARTBARCATEGORYAXISY_H
+
+#include "verticalaxis_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QBarCategoryAxis;
+class ChartPresenter;
+
+class ChartBarCategoryAxisY : public VerticalAxis
+{
+ Q_OBJECT
+public:
+ ChartBarCategoryAxisY(QBarCategoryAxis *axis, QGraphicsItem* item = 0);
+ ~ChartBarCategoryAxisY();
+
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const;
+protected:
+ QVector<qreal> calculateLayout() const;
+ void updateGeometry();
+private:
+ QStringList createCategoryLabels(const QVector<qreal>& layout) const;
+public Q_SLOTS:
+ void handleCategoriesChanged();
+private:
+ QBarCategoryAxis *m_categoriesAxis;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif /* CHARTBARCATEGORYAXISY_H */
diff --git a/src/charts/axis/barcategoryaxis/qbarcategoryaxis.cpp b/src/charts/axis/barcategoryaxis/qbarcategoryaxis.cpp
new file mode 100644
index 00000000..7818d6f6
--- /dev/null
+++ b/src/charts/axis/barcategoryaxis/qbarcategoryaxis.cpp
@@ -0,0 +1,620 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbarcategoryaxis.h"
+#include "qbarcategoryaxis_p.h"
+#include "chartbarcategoryaxisx_p.h"
+#include "chartbarcategoryaxisy_p.h"
+#include "abstractdomain_p.h"
+#include "qchart.h"
+#include <qmath.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+/*!
+ \class QBarCategoryAxis
+ \inmodule Qt Charts
+ \brief The QBarCategoryAxis class is used for manipulating chart's axis.
+ \mainclass
+
+ QBarCategoryAxis can be setup to show axis line with tick marks, grid lines and shades.
+ Categories are drawn between ticks. Note that you can use this also with lineseries too.
+ See the \l {Line and BarChart Example} {Line and BarChart Example} to learn how to do that.
+
+ Example code on how to use QBarCategoryAxis.
+ \code
+ QChartView *chartView = new QChartView;
+ QBarSeries *series = new QBarSeries;
+ // ...
+ chartView->chart()->addSeries(series);
+ chartView->chart()->createDefaultAxes();
+
+ QBarCategoryAxis *axisX = new QBarCategoryAxis;
+ QStringList categories;
+ categories << "Jan" << "Feb" << "Mar" << "Apr" << "May" << "Jun";
+ axisX->append(categories);
+ axisX->setRange("Feb", "May");
+ chartView->chart()->setAxisX(axisX, series);
+ \endcode
+*/
+
+/*!
+ \qmltype BarCategoryAxis
+ \instantiates QBarCategoryAxis
+ \inqmlmodule QtCharts
+
+ \inherits AbstractAxis
+
+ \brief The Axis element is used for manipulating chart's axes.
+
+ Axis can be setup to show axis line with tick marks, grid lines and shades.
+ Categories are drawn between ticks. Note that you can use this also with lineseries too.
+
+ To access BarCategoryAxis you can use ChartView API. For example:
+ \code
+ ChartView {
+ BarCategoryAxis {
+ id: categoryAxis
+ categories: ["Jan", "Feb", "Mar", "Apr", "May", "Jun" ]
+ }
+ // Add a few series...
+ }
+ \endcode
+*/
+
+/*!
+ \property QBarCategoryAxis::categories
+ Defines the categories of axis
+*/
+/*!
+ \qmlproperty QStringList BarCategoryAxis::categories
+ Defines the categories of axis
+*/
+
+/*!
+ \property QBarCategoryAxis::min
+ Defines the minimum value on the axis.
+*/
+/*!
+ \qmlproperty string BarCategoryAxis::min
+ Defines the minimum value on the axis.
+*/
+
+/*!
+ \property QBarCategoryAxis::max
+ Defines the maximum value on the axis.
+*/
+/*!
+ \qmlproperty string BarCategoryAxis::max
+ Defines the maximum value on the axis.
+*/
+
+/*!
+ \property QBarCategoryAxis::count
+ The count of categories.
+*/
+/*!
+ \qmlproperty int BarCategoryAxis::count
+ The count of categories.
+*/
+
+/*!
+ \fn void QBarCategoryAxis::categoriesChanged()
+ Axis emits signal when the categories of the axis have changed.
+*/
+
+/*!
+ \fn void QBarCategoryAxis::minChanged(const QString &min)
+ Axis emits signal when \a min of axis has changed.
+*/
+/*!
+ \qmlsignal BarCategoryAxis::onMinChanged(const QString &min)
+ Axis emits signal when \a min of axis has changed.
+*/
+
+/*!
+ \fn void QBarCategoryAxis::maxChanged(const QString &max)
+ Axis emits signal when \a max of axis has changed.
+*/
+/*!
+ \qmlsignal BarCategoryAxis::onMaxChanged(const QString &max)
+ Axis emits signal when \a max of axis has changed.
+*/
+
+/*!
+ \fn void QBarCategoryAxis::countChanged()
+ Axis emits signal when the count of categories has changed.
+*/
+/*!
+ \qmlsignal BarCategoryAxis::onCountChanged()
+ Axis emits signal when the count of categories has changed.
+*/
+
+/*!
+ \fn void QBarCategoryAxis::rangeChanged(const QString &min, const QString &max)
+ Axis emits signal when \a min or \a max of axis has changed.
+*/
+
+/*!
+ \qmlmethod void BarCategoryAxis::clear()
+ Removes all categories. Sets the maximum and minimum of the axis's range to QString::null.
+*/
+
+/*!
+ Constructs an axis object which is a child of \a parent.
+*/
+QBarCategoryAxis::QBarCategoryAxis(QObject *parent):
+ QAbstractAxis(*new QBarCategoryAxisPrivate(this), parent)
+{
+}
+
+/*!
+ Destroys the object
+*/
+QBarCategoryAxis::~QBarCategoryAxis()
+{
+ Q_D(QBarCategoryAxis);
+ if (d->m_chart)
+ d->m_chart->removeAxis(this);
+}
+
+/*!
+ \internal
+*/
+QBarCategoryAxis::QBarCategoryAxis(QBarCategoryAxisPrivate &d, QObject *parent)
+ : QAbstractAxis(d, parent)
+{
+
+}
+
+/*!
+ Appends \a categories to axis. A maximum of the axis will be changed to last category in \a categories.
+ If there were no categories previously defined, minimum of axis will be also changed to first category in \a categories.
+ A category has to be valid QStrings and can not be duplicated. Duplicated categories will not be appended.
+*/
+void QBarCategoryAxis::append(const QStringList &categories)
+{
+ if (categories.isEmpty())
+ return;
+
+ Q_D(QBarCategoryAxis);
+
+ int count = d->m_categories.count();
+
+ foreach(QString category, categories) {
+ if (!d->m_categories.contains(category) && !category.isNull()) {
+ d->m_categories.append(category);
+ }
+ }
+
+ if (d->m_categories.count() == count)
+ return;
+
+ if (count == 0)
+ setRange(d->m_categories.first(), d->m_categories.last());
+ else
+ setRange(d->m_minCategory, d->m_categories.last());
+
+ emit categoriesChanged();
+ emit countChanged();
+}
+
+/*!
+ Appends \a category to axis. A maximum of the axis will be changed to last \a category.
+ If there were no categories previously defined, minimum of axis will be also changed to \a category.
+ A \a category has to be valid QStrings and can not be duplicated. Duplicated categories will not be appended.
+*/
+void QBarCategoryAxis::append(const QString &category)
+{
+ Q_D(QBarCategoryAxis);
+
+ int count = d->m_categories.count();
+
+ if (!d->m_categories.contains(category) && !category.isNull())
+ d->m_categories.append(category);
+
+ if (d->m_categories.count() == count)
+ return;
+
+ if (count == 0)
+ setRange(d->m_categories.last(), d->m_categories.last());
+ else
+ setRange(d->m_minCategory, d->m_categories.last());
+
+ emit categoriesChanged();
+ emit countChanged();
+}
+
+/*!
+ Removes \a category from axis. Removing category which is currently maximum or minimum
+ will affect the axis range.
+*/
+void QBarCategoryAxis::remove(const QString &category)
+{
+ Q_D(QBarCategoryAxis);
+
+ if (d->m_categories.contains(category)) {
+ d->m_categories.removeAt(d->m_categories.indexOf(category));
+ if (!d->m_categories.isEmpty()) {
+ if (d->m_minCategory == category) {
+ setRange(d->m_categories.first(), d->m_maxCategory);
+ } else if (d->m_maxCategory == category) {
+ setRange(d->m_minCategory, d->m_categories.last());
+ } else {
+ d->updateCategoryDomain();
+ }
+ } else {
+ setRange(QString::null, QString::null);
+ }
+ emit categoriesChanged();
+ emit countChanged();
+ }
+}
+
+/*!
+ Inserts \a category to axis at \a index. A \a category has to be valid QStrings and can not be duplicated.
+ If \a category is prepended or appended to categories, minimum and maximum of axis is updated accordingly.
+*/
+void QBarCategoryAxis::insert(int index, const QString &category)
+{
+ Q_D(QBarCategoryAxis);
+
+ int count = d->m_categories.count();
+
+ if (!d->m_categories.contains(category) && !category.isNull())
+ d->m_categories.insert(index, category);
+
+ if (d->m_categories.count() == count)
+ return;
+
+ if (count == 0) {
+ setRange(d->m_categories.first(), d->m_categories.first());
+ } else if (index == 0) {
+ setRange(d->m_categories.first(), d->m_maxCategory);
+ } else if (index == count) {
+ setRange(d->m_minCategory, d->m_categories.last());
+ } else {
+ d->updateCategoryDomain();
+ }
+
+ emit categoriesChanged();
+ emit countChanged();
+}
+
+/*!
+ Replaces \a oldCategory with \a newCategory. If \a oldCategory does not exist on the axis nothing is done.
+ A \a newCategory has to be valid QStrings and can not be duplicated. In case of replacing minimum or maximum category,
+ minimum and maximum of axis is updated accordingly.
+*/
+void QBarCategoryAxis::replace(const QString &oldCategory, const QString &newCategory)
+{
+ Q_D(QBarCategoryAxis);
+
+ int pos = d->m_categories.indexOf(oldCategory);
+
+ if (pos != -1 && !d->m_categories.contains(newCategory) && !newCategory.isNull()) {
+ d->m_categories.replace(pos, newCategory);
+ if (d->m_minCategory == oldCategory)
+ setRange(newCategory, d->m_maxCategory);
+ else if (d->m_maxCategory == oldCategory)
+ setRange(d->m_minCategory, newCategory);
+
+ emit categoriesChanged();
+ emit countChanged();
+ }
+}
+
+/*!
+ Removes all categories. Sets the maximum and minimum of the axis's range to QString::null.
+ */
+void QBarCategoryAxis::clear()
+{
+ Q_D(QBarCategoryAxis);
+ d->m_categories.clear();
+ setRange(QString::null, QString::null);
+ emit categoriesChanged();
+ emit countChanged();
+}
+
+/*!
+ Set \a categories and discards the old ones, range of axis is adjusted to match first and last category in \a categories.
+ A category has to be valid QStrings and can not be duplicated.
+*/
+void QBarCategoryAxis::setCategories(const QStringList &categories)
+{
+ Q_D(QBarCategoryAxis);
+ d->m_categories.clear();
+ d->m_minCategory = QString::null;
+ d->m_maxCategory = QString::null;
+ d->m_min = 0;
+ d->m_max = 0;
+ d->m_count = 0;
+ append(categories);
+}
+
+/*!
+ Returns categories
+*/
+QStringList QBarCategoryAxis::categories()
+{
+ Q_D(QBarCategoryAxis);
+ return d->m_categories;
+}
+
+/*!
+ Returns number of categories.
+ */
+int QBarCategoryAxis::count() const
+{
+ Q_D(const QBarCategoryAxis);
+ return d->m_categories.count();
+}
+
+/*!
+ Returns category at \a index. Index must be valid.
+*/
+QString QBarCategoryAxis::at(int index) const
+{
+ Q_D(const QBarCategoryAxis);
+ return d->m_categories.at(index);
+}
+
+/*!
+ Sets minimum category to \a min.
+*/
+void QBarCategoryAxis::setMin(const QString &min)
+{
+ Q_D(QBarCategoryAxis);
+ d->setRange(min, d->m_maxCategory);
+}
+
+/*!
+ Returns minimum category.
+*/
+QString QBarCategoryAxis::min() const
+{
+ Q_D(const QBarCategoryAxis);
+ return d->m_minCategory;
+}
+
+/*!
+ Sets maximum category to \a max.
+*/
+void QBarCategoryAxis::setMax(const QString &max)
+{
+ Q_D(QBarCategoryAxis);
+ d->setRange(d->m_minCategory, max);
+}
+
+/*!
+ Returns maximum category
+*/
+QString QBarCategoryAxis::max() const
+{
+ Q_D(const QBarCategoryAxis);
+ return d->m_maxCategory;
+}
+
+/*!
+ Sets range from \a minCategory to \a maxCategory
+*/
+void QBarCategoryAxis::setRange(const QString &minCategory, const QString &maxCategory)
+{
+ Q_D(QBarCategoryAxis);
+ d->setRange(minCategory,maxCategory);
+}
+
+/*!
+ Returns the type of the axis
+*/
+QAbstractAxis::AxisType QBarCategoryAxis::type() const
+{
+ return AxisTypeBarCategory;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QBarCategoryAxisPrivate::QBarCategoryAxisPrivate(QBarCategoryAxis *q)
+ : QAbstractAxisPrivate(q),
+ m_min(0.0),
+ m_max(0.0),
+ m_count(0)
+{
+
+}
+
+QBarCategoryAxisPrivate::~QBarCategoryAxisPrivate()
+{
+
+}
+
+void QBarCategoryAxisPrivate::setMin(const QVariant &min)
+{
+ setRange(min, m_maxCategory);
+}
+
+void QBarCategoryAxisPrivate::setMax(const QVariant &max)
+{
+ setRange(m_minCategory, max);
+}
+
+void QBarCategoryAxisPrivate::setRange(const QVariant &min, const QVariant &max)
+{
+ QString value1 = min.toString();
+ QString value2 = max.toString();
+ setRange(value1, value2);
+}
+
+void QBarCategoryAxisPrivate::setRange(qreal min, qreal max)
+{
+ Q_Q(QBarCategoryAxis);
+
+ bool categoryChanged = false;
+ bool changed = false;
+
+ if (min > max)
+ return;
+
+ if (!qFuzzyIsNull(m_min - min)) {
+ m_min = min;
+ changed = true;
+
+ int imin = m_min + 0.5;
+ if (imin >= 0 && imin < m_categories.count()) {
+ QString minCategory = m_categories.at(imin);
+ if (m_minCategory != minCategory && !minCategory.isEmpty()) {
+ m_minCategory = minCategory;
+ categoryChanged = true;
+ emit q->minChanged(minCategory);
+ }
+ }
+
+ }
+
+ if (!qFuzzyIsNull(m_max - max)) {
+ m_max = max;
+ changed = true;
+
+ int imax = m_max - 0.5;
+ if (imax >= 0 && imax < m_categories.count()) {
+ QString maxCategory = m_categories.at(imax);
+ if (m_maxCategory != maxCategory && !maxCategory.isEmpty()) {
+ m_maxCategory = maxCategory;
+ categoryChanged = true;
+ emit q->maxChanged(maxCategory);
+ }
+ }
+ }
+
+ if (categoryChanged){
+ emit q->rangeChanged(m_minCategory, m_maxCategory);
+ }
+
+ if (changed) {
+ emit rangeChanged(m_min,m_max);
+ }
+}
+
+void QBarCategoryAxisPrivate::setRange(const QString &minCategory, const QString &maxCategory)
+{
+ Q_Q(QBarCategoryAxis);
+ bool changed = false;
+
+ //special case in case or clearing all categories
+ if (minCategory.isNull() && maxCategory.isNull()) {
+ m_minCategory = minCategory;
+ m_maxCategory = maxCategory;
+ m_min = 0;
+ m_max = 0;
+ m_count = 0;
+ emit q->minChanged(minCategory);
+ emit q->maxChanged(maxCategory);
+ emit q->rangeChanged(m_minCategory, m_maxCategory);
+ emit rangeChanged(m_min,m_max);
+ return;
+ }
+
+ if (m_categories.indexOf(maxCategory) < m_categories.indexOf(minCategory))
+ return;
+
+ if (!minCategory.isNull() && (m_minCategory != minCategory || m_minCategory.isNull())
+ && m_categories.contains(minCategory)) {
+ m_minCategory = minCategory;
+ m_min = m_categories.indexOf(m_minCategory) - 0.5;
+ changed = true;
+ emit q->minChanged(minCategory);
+ }
+
+ if (!maxCategory.isNull() && (m_maxCategory != maxCategory || m_maxCategory.isNull())
+ && m_categories.contains(maxCategory)) {
+ m_maxCategory = maxCategory;
+ m_max = m_categories.indexOf(m_maxCategory) + 0.5;
+ changed = true;
+ emit q->maxChanged(maxCategory);
+ }
+
+ if (changed) {
+ m_count = m_max - m_min;
+ emit q->rangeChanged(m_minCategory, m_maxCategory);
+ emit rangeChanged(m_min,m_max);
+ }
+}
+
+void QBarCategoryAxisPrivate::initializeGraphics(QGraphicsItem* parent)
+{
+ Q_Q(QBarCategoryAxis);
+ ChartAxisElement* axis(0);
+ if (orientation() == Qt::Vertical)
+ axis = new ChartBarCategoryAxisY(q,parent);
+ if (orientation() == Qt::Horizontal)
+ axis = new ChartBarCategoryAxisX(q,parent);
+
+ m_item.reset(axis);
+ QAbstractAxisPrivate::initializeGraphics(parent);
+}
+
+void QBarCategoryAxisPrivate::updateCategoryDomain()
+{
+ bool changed = false;
+
+ qreal tmpMin = m_categories.indexOf(m_minCategory) - 0.5;
+ if (!qFuzzyIsNull(m_min - tmpMin)) {
+ m_min = tmpMin;
+ changed = true;
+ }
+ qreal tmpMax = m_categories.indexOf(m_maxCategory) + 0.5;
+ if (!qFuzzyIsNull(m_max - tmpMax)) {
+ m_max = tmpMax;
+ changed = true;
+ }
+ m_count = m_max - m_min;
+
+ if (changed)
+ emit rangeChanged(m_min,m_max);
+}
+
+
+void QBarCategoryAxisPrivate::initializeDomain(AbstractDomain *domain)
+{
+ Q_Q(QBarCategoryAxis);
+ if (m_max == m_min) {
+ int min;
+ int max;
+ if (orientation() == Qt::Vertical) {
+ min = domain->minY() + 0.5;
+ max = domain->maxY() - 0.5;
+ } else {
+ min = domain->minX() + 0.5;
+ max = domain->maxX() - 0.5;
+ }
+
+ if (min > 0 && min < m_categories.count() && max > 0 && max < m_categories.count())
+ q->setRange(m_categories.at(min), m_categories.at(max));
+ } else {
+ if (orientation() == Qt::Vertical)
+ domain->setRangeY(m_min, m_max);
+ else
+ domain->setRangeX(m_min, m_max);
+ }
+}
+
+#include "moc_qbarcategoryaxis.cpp"
+#include "moc_qbarcategoryaxis_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/barcategoryaxis/qbarcategoryaxis.h b/src/charts/axis/barcategoryaxis/qbarcategoryaxis.h
new file mode 100644
index 00000000..55a2430f
--- /dev/null
+++ b/src/charts/axis/barcategoryaxis/qbarcategoryaxis.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBARCATEGORYAXIS_H
+#define QBARCATEGORYAXIS_H
+
+#include <QtCharts/qabstractaxis.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QBarCategoryAxisPrivate;
+
+class QT_CHARTS_EXPORT QBarCategoryAxis : public QAbstractAxis
+{
+ Q_OBJECT
+ Q_PROPERTY(QStringList categories READ categories WRITE setCategories NOTIFY categoriesChanged)
+ Q_PROPERTY(QString min READ min WRITE setMin NOTIFY minChanged)
+ Q_PROPERTY(QString max READ max WRITE setMax NOTIFY maxChanged)
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+
+public:
+ explicit QBarCategoryAxis(QObject *parent = 0);
+ ~QBarCategoryAxis();
+
+protected:
+ QBarCategoryAxis(QBarCategoryAxisPrivate &d, QObject *parent = 0);
+
+public:
+ AxisType type() const;
+ void append(const QStringList &categories);
+ void append(const QString &category);
+ void remove(const QString &category);
+ void insert(int index, const QString &category);
+ void replace(const QString &oldCategory, const QString &newCategory);
+ Q_INVOKABLE void clear();
+ void setCategories(const QStringList &categories);
+ QStringList categories();
+ int count() const;
+ QString at(int index) const;
+
+ //range handling
+ void setMin(const QString &minCategory);
+ QString min() const;
+ void setMax(const QString &maxCategory);
+ QString max() const;
+ void setRange(const QString &minCategory, const QString &maxCategory);
+
+Q_SIGNALS:
+ void categoriesChanged();
+ void minChanged(const QString &min);
+ void maxChanged(const QString &max);
+ void rangeChanged(const QString &min, const QString &max);
+ void countChanged();
+
+private:
+ Q_DECLARE_PRIVATE(QBarCategoryAxis)
+ Q_DISABLE_COPY(QBarCategoryAxis)
+ friend class ChartBarCategoryAxisX;
+ friend class ChartBarCategoryAxisY;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QBARCATEGORYAXIS_H
diff --git a/src/charts/axis/barcategoryaxis/qbarcategoryaxis_p.h b/src/charts/axis/barcategoryaxis/qbarcategoryaxis_p.h
new file mode 100644
index 00000000..8ebc5a4c
--- /dev/null
+++ b/src/charts/axis/barcategoryaxis/qbarcategoryaxis_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QBARCATEGORYAXIS_P_H
+#define QBARCATEGORYAXIS_P_H
+
+#include <qbarcategoryaxis.h>
+#include "qabstractaxis_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class AbstractDomain;
+
+class QBarCategoryAxisPrivate : public QAbstractAxisPrivate
+{
+ Q_OBJECT
+
+public:
+ QBarCategoryAxisPrivate(QBarCategoryAxis *q);
+ ~QBarCategoryAxisPrivate();
+
+public:
+ void initializeGraphics(QGraphicsItem* parent);
+ void initializeDomain(AbstractDomain *domain);
+ void updateCategoryDomain();
+
+ //interface for manipulating range form base class
+ void setRange(const QVariant &min, const QVariant &max);
+ void setMin(const QVariant &min);
+ void setMax(const QVariant &max);
+
+ //interface manipulating range form domain
+ qreal min() { return m_min; }
+ qreal max() { return m_max; }
+ void setRange(qreal min,qreal max);
+
+private:
+ //range handling
+ void setRange(const QString &minCategory, const QString &maxCategory);
+
+private:
+ QStringList m_categories;
+ QString m_minCategory;
+ QString m_maxCategory;
+ qreal m_min;
+ qreal m_max;
+ int m_count;
+
+private:
+ Q_DECLARE_PUBLIC(QBarCategoryAxis);
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QBARCATEGORYAXIS_P_H
diff --git a/src/charts/axis/cartesianchartaxis.cpp b/src/charts/axis/cartesianchartaxis.cpp
new file mode 100644
index 00000000..d067921d
--- /dev/null
+++ b/src/charts/axis/cartesianchartaxis.cpp
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "cartesianchartaxis_p.h"
+#include "qabstractaxis.h"
+#include "qabstractaxis_p.h"
+#include "chartpresenter_p.h"
+#include "abstractchartlayout_p.h"
+#include "abstractdomain_p.h"
+#include "linearrowitem_p.h"
+#include <QValueAxis>
+#include <QLogValueAxis>
+#include <QGraphicsLayout>
+#include <QTextDocument>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+CartesianChartAxis::CartesianChartAxis(QAbstractAxis *axis, QGraphicsItem *item , bool intervalAxis)
+ : ChartAxisElement(axis, item, intervalAxis)
+{
+ Q_ASSERT(item);
+}
+
+
+CartesianChartAxis::~CartesianChartAxis()
+{
+}
+
+void CartesianChartAxis::createItems(int count)
+{
+ if (arrowItems().size() == 0) {
+ QGraphicsLineItem *arrow = new LineArrowItem(this, this);
+ arrow->setPen(axis()->linePen());
+ arrowGroup()->addToGroup(arrow);
+ }
+
+ if (intervalAxis() && gridItems().size() == 0) {
+ for (int i = 0 ; i < 2 ; i ++){
+ QGraphicsLineItem *item = new QGraphicsLineItem(this);
+ item->setPen(axis()->gridLinePen());
+ gridGroup()->addToGroup(item);
+ }
+ }
+
+ QGraphicsTextItem *title = titleItem();
+ title->setFont(axis()->titleFont());
+ title->setDefaultTextColor(axis()->titleBrush().color());
+ title->setHtml(axis()->titleText());
+
+ for (int i = 0; i < count; ++i) {
+ QGraphicsLineItem *arrow = new QGraphicsLineItem(this);
+ QGraphicsLineItem *grid = new QGraphicsLineItem(this);
+ QGraphicsTextItem *label = new QGraphicsTextItem(this);
+ label->document()->setDocumentMargin(ChartPresenter::textMargin());
+ arrow->setPen(axis()->linePen());
+ grid->setPen(axis()->gridLinePen());
+ label->setFont(axis()->labelsFont());
+ label->setDefaultTextColor(axis()->labelsBrush().color());
+ label->setRotation(axis()->labelsAngle());
+ arrowGroup()->addToGroup(arrow);
+ gridGroup()->addToGroup(grid);
+ labelGroup()->addToGroup(label);
+
+ if ((gridItems().size()) % 2 && gridItems().size() > 2) {
+ QGraphicsRectItem* shades = new QGraphicsRectItem(this);
+ shades->setPen(axis()->shadesPen());
+ shades->setBrush(axis()->shadesBrush());
+ shadeGroup()->addToGroup(shades);
+ }
+ }
+
+}
+
+void CartesianChartAxis::deleteItems(int count)
+{
+ QList<QGraphicsItem *> lines = gridItems();
+ QList<QGraphicsItem *> labels = labelItems();
+ QList<QGraphicsItem *> shades = shadeItems();
+ QList<QGraphicsItem *> axis = arrowItems();
+
+ for (int i = 0; i < count; ++i) {
+ if (lines.size() % 2 && lines.size() > 1)
+ delete(shades.takeLast());
+ delete(lines.takeLast());
+ delete(labels.takeLast());
+ delete(axis.takeLast());
+ }
+}
+
+void CartesianChartAxis::updateLayout(QVector<qreal> &layout)
+{
+ int diff = ChartAxisElement::layout().size() - layout.size();
+
+ if (diff > 0)
+ deleteItems(diff);
+ else if (diff < 0)
+ createItems(-diff);
+
+ if (animation()) {
+ switch (presenter()->state()) {
+ case ChartPresenter::ZoomInState:
+ animation()->setAnimationType(AxisAnimation::ZoomInAnimation);
+ animation()->setAnimationPoint(presenter()->statePoint());
+ break;
+ case ChartPresenter::ZoomOutState:
+ animation()->setAnimationType(AxisAnimation::ZoomOutAnimation);
+ animation()->setAnimationPoint(presenter()->statePoint());
+ break;
+ case ChartPresenter::ScrollUpState:
+ case ChartPresenter::ScrollLeftState:
+ animation()->setAnimationType(AxisAnimation::MoveBackwordAnimation);
+ break;
+ case ChartPresenter::ScrollDownState:
+ case ChartPresenter::ScrollRightState:
+ animation()->setAnimationType(AxisAnimation::MoveForwardAnimation);
+ break;
+ case ChartPresenter::ShowState:
+ animation()->setAnimationType(AxisAnimation::DefaultAnimation);
+ break;
+ }
+ animation()->setValues(ChartAxisElement::layout(), layout);
+ presenter()->startAnimation(animation());
+ } else {
+ setLayout(layout);
+ updateGeometry();
+ }
+}
+
+bool CartesianChartAxis::isEmpty()
+{
+ return axisGeometry().isEmpty()
+ || gridGeometry().isEmpty()
+ || qFuzzyCompare(min(), max());
+}
+
+void CartesianChartAxis::setGeometry(const QRectF &axis, const QRectF &grid)
+{
+ m_gridRect = grid;
+ setAxisGeometry(axis);
+
+ if (isEmpty())
+ return;
+
+ QVector<qreal> layout = calculateLayout();
+ updateLayout(layout);
+}
+
+QSizeF CartesianChartAxis::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED(which);
+ Q_UNUSED(constraint);
+ return QSizeF();
+}
+
+void CartesianChartAxis::handleArrowPenChanged(const QPen &pen)
+{
+ foreach (QGraphicsItem *item, arrowItems())
+ static_cast<QGraphicsLineItem *>(item)->setPen(pen);
+}
+
+void CartesianChartAxis::handleGridPenChanged(const QPen &pen)
+{
+ foreach (QGraphicsItem *item, gridItems())
+ static_cast<QGraphicsLineItem *>(item)->setPen(pen);
+}
+
+void CartesianChartAxis::handleShadesBrushChanged(const QBrush &brush)
+{
+ foreach (QGraphicsItem *item, shadeItems())
+ static_cast<QGraphicsRectItem *>(item)->setBrush(brush);
+}
+
+void CartesianChartAxis::handleShadesPenChanged(const QPen &pen)
+{
+ foreach (QGraphicsItem *item, shadeItems())
+ static_cast<QGraphicsRectItem *>(item)->setPen(pen);
+}
+
+#include "moc_cartesianchartaxis_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/cartesianchartaxis_p.h b/src/charts/axis/cartesianchartaxis_p.h
new file mode 100644
index 00000000..c0c2252b
--- /dev/null
+++ b/src/charts/axis/cartesianchartaxis_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CARTESIANCHARTAXIS_H
+#define CARTESIANCHARTAXIS_H
+
+#include "qchartglobal.h"
+#include "chartaxiselement_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QAbstractAxis;
+
+class CartesianChartAxis : public ChartAxisElement
+{
+ Q_OBJECT
+ Q_INTERFACES(QGraphicsLayoutItem)
+public:
+
+ CartesianChartAxis(QAbstractAxis *axis, QGraphicsItem *item = 0, bool intervalAxis = false);
+ ~CartesianChartAxis();
+
+ void setGeometry(const QRectF &axis, const QRectF &grid);
+ QRectF gridGeometry() const { return m_gridRect; }
+ bool isEmpty();
+
+ virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
+
+protected:
+ void setGeometry(const QRectF &size) { Q_UNUSED(size);}
+ virtual void updateGeometry() = 0;
+ void updateLayout(QVector<qreal> &layout);
+
+public Q_SLOTS:
+ virtual void handleArrowPenChanged(const QPen &pen);
+ virtual void handleGridPenChanged(const QPen &pen);
+ virtual void handleShadesBrushChanged(const QBrush &brush);
+ virtual void handleShadesPenChanged(const QPen &pen);
+
+private:
+ void createItems(int count);
+ void deleteItems(int count);
+
+private:
+ QRectF m_gridRect;
+
+ friend class AxisAnimation;
+ friend class LineArrowItem;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif /* CARTESIANCHARTAXIS_H */
diff --git a/src/charts/axis/categoryaxis/chartcategoryaxisx.cpp b/src/charts/axis/categoryaxis/chartcategoryaxisx.cpp
new file mode 100644
index 00000000..2141f353
--- /dev/null
+++ b/src/charts/axis/categoryaxis/chartcategoryaxisx.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "chartcategoryaxisx_p.h"
+#include "qcategoryaxis.h"
+#include "qabstractaxis.h"
+#include "chartpresenter_p.h"
+#include "abstractchartlayout_p.h"
+#include <QGraphicsLayout>
+#include <qmath.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+ChartCategoryAxisX::ChartCategoryAxisX(QCategoryAxis *axis, QGraphicsItem* item)
+ : HorizontalAxis(axis, item, true),
+ m_axis(axis)
+{
+ QObject::connect(axis, SIGNAL(categoriesChanged()), this, SLOT(handleCategoriesChanged()));
+}
+
+ChartCategoryAxisX::~ChartCategoryAxisX()
+{
+}
+
+QVector<qreal> ChartCategoryAxisX::calculateLayout() const
+{
+ int tickCount = m_axis->categoriesLabels().count() + 1;
+ QVector<qreal> points;
+
+ if (tickCount < 2)
+ return points;
+
+ const QRectF &gridRect = gridGeometry();
+ qreal range = max() - min();
+ if (range > 0) {
+ points.resize(tickCount);
+ qreal scale = gridRect.width() / range;
+ for (int i = 0; i < tickCount; ++i) {
+ if (i < tickCount - 1) {
+ qreal x = (m_axis->startValue(m_axis->categoriesLabels().at(i)) - min()) * scale + gridRect.left();
+ points[i] = x;
+ } else {
+ qreal x = (m_axis->endValue(m_axis->categoriesLabels().at(i - 1)) - min()) * scale + gridRect.left();
+ points[i] = x;
+ }
+ }
+ }
+
+ return points;
+}
+
+void ChartCategoryAxisX::updateGeometry()
+{
+ setLabels(m_axis->categoriesLabels() << QString());
+ HorizontalAxis::updateGeometry();
+}
+
+QSizeF ChartCategoryAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED(constraint)
+
+ QSizeF sh;
+ QSizeF base = HorizontalAxis::sizeHint(which, constraint);
+ QStringList ticksList = m_axis->categoriesLabels();
+ qreal width = 0; // Width is irrelevant for X axes with interval labels
+ qreal height = 0;
+
+ switch (which) {
+ case Qt::MinimumSize: {
+ QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(),
+ QStringLiteral("..."),
+ axis()->labelsAngle());
+ height = boundingRect.height() + labelPadding() + base.height() + 1.0;
+ sh = QSizeF(width, height);
+ break;
+ }
+ case Qt::PreferredSize: {
+ qreal labelHeight = 0.0;
+ foreach (const QString& s, ticksList) {
+ QRectF rect = ChartPresenter::textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
+ labelHeight = qMax(rect.height(), labelHeight);
+ }
+ height = labelHeight + labelPadding() + base.height() + 1.0;
+ sh = QSizeF(width, height);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return sh;
+}
+
+void ChartCategoryAxisX::handleCategoriesChanged()
+{
+ QGraphicsLayoutItem::updateGeometry();
+ presenter()->layout()->invalidate();
+}
+
+#include "moc_chartcategoryaxisx_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/categoryaxis/chartcategoryaxisx_p.h b/src/charts/axis/categoryaxis/chartcategoryaxisx_p.h
new file mode 100644
index 00000000..e526b01a
--- /dev/null
+++ b/src/charts/axis/categoryaxis/chartcategoryaxisx_p.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTCATEGORYAXISX_H
+#define CHARTCATEGORYAXISX_H
+
+#include "horizontalaxis_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QCategoryAxis;
+
+class ChartCategoryAxisX : public HorizontalAxis
+{
+ Q_OBJECT
+public:
+ ChartCategoryAxisX(QCategoryAxis *axis, QGraphicsItem* item = 0);
+ ~ChartCategoryAxisX();
+
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const;
+
+public Q_SLOTS:
+ void handleCategoriesChanged();
+
+protected:
+ QVector<qreal> calculateLayout() const;
+ void updateGeometry();
+
+private:
+ QCategoryAxis *m_axis;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif /* CHARTCATEGORYAXISX_H */
diff --git a/src/charts/axis/categoryaxis/chartcategoryaxisy.cpp b/src/charts/axis/categoryaxis/chartcategoryaxisy.cpp
new file mode 100644
index 00000000..7d5ba103
--- /dev/null
+++ b/src/charts/axis/categoryaxis/chartcategoryaxisy.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "chartcategoryaxisy_p.h"
+#include "qcategoryaxis.h"
+#include "qabstractaxis.h"
+#include "chartpresenter_p.h"
+#include "abstractchartlayout_p.h"
+#include <QGraphicsLayout>
+#include <qmath.h>
+#include <QDebug>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+ChartCategoryAxisY::ChartCategoryAxisY(QCategoryAxis *axis, QGraphicsItem* item)
+ : VerticalAxis(axis, item, true),
+ m_axis(axis)
+{
+ QObject::connect(axis, SIGNAL(categoriesChanged()), this, SLOT(handleCategoriesChanged()));
+}
+
+ChartCategoryAxisY::~ChartCategoryAxisY()
+{
+}
+
+QVector<qreal> ChartCategoryAxisY::calculateLayout() const
+{
+ int tickCount = m_axis->categoriesLabels().count() + 1;
+ QVector<qreal> points;
+
+ if (tickCount < 2)
+ return points;
+
+ const QRectF &gridRect = gridGeometry();
+ qreal range = max() - min();
+ if (range > 0) {
+ points.resize(tickCount);
+ qreal scale = gridRect.height() / range;
+ for (int i = 0; i < tickCount; ++i) {
+ if (i < tickCount - 1) {
+ qreal y = -(m_axis->startValue(m_axis->categoriesLabels().at(i)) - min()) * scale + gridRect.bottom();
+ points[i] = y;
+ } else {
+ qreal y = -(m_axis->endValue(m_axis->categoriesLabels().at(i - 1)) - min()) * scale + gridRect.bottom();
+ points[i] = y;
+ }
+ }
+ }
+
+ return points;
+}
+
+void ChartCategoryAxisY::updateGeometry()
+{
+ setLabels(m_axis->categoriesLabels() << QString());
+ VerticalAxis::updateGeometry();
+}
+
+QSizeF ChartCategoryAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED(constraint)
+
+ QSizeF sh;
+ QSizeF base = VerticalAxis::sizeHint(which, constraint);
+ QStringList ticksList = m_axis->categoriesLabels();
+ qreal width = 0;
+ qreal height = 0; // Height is irrelevant for Y axes with interval labels
+
+ switch (which) {
+ case Qt::MinimumSize: {
+ QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(),
+ QStringLiteral("..."),
+ axis()->labelsAngle());
+ width = boundingRect.width() + labelPadding() + base.width() + 1.0;
+ sh = QSizeF(width, height);
+ break;
+ }
+ case Qt::PreferredSize: {
+ qreal labelWidth = 0.0;
+ foreach (const QString& s, ticksList) {
+ QRectF rect = ChartPresenter::textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
+ labelWidth = qMax(rect.width(), labelWidth);
+ }
+ width = labelWidth + labelPadding() + base.width() + 1.0;
+ sh = QSizeF(width, height);
+ break;
+ }
+ default:
+ break;
+ }
+ return sh;
+}
+
+void ChartCategoryAxisY::handleCategoriesChanged()
+{
+ QGraphicsLayoutItem::updateGeometry();
+ presenter()->layout()->invalidate();
+}
+
+#include "moc_chartcategoryaxisy_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/categoryaxis/chartcategoryaxisy_p.h b/src/charts/axis/categoryaxis/chartcategoryaxisy_p.h
new file mode 100644
index 00000000..e416e4c0
--- /dev/null
+++ b/src/charts/axis/categoryaxis/chartcategoryaxisy_p.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTCATEGORYAXISY_H
+#define CHARTCATEGORYAXISY_H
+
+#include "verticalaxis_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QCategoryAxis;
+
+class ChartCategoryAxisY : public VerticalAxis
+{
+ Q_OBJECT
+public:
+ ChartCategoryAxisY(QCategoryAxis *axis, QGraphicsItem* item = 0);
+ ~ChartCategoryAxisY();
+
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const;
+
+public Q_SLOTS:
+ void handleCategoriesChanged();
+
+protected:
+ QVector<qreal> calculateLayout() const;
+ void updateGeometry();
+
+private:
+ QCategoryAxis *m_axis;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif /* CHARTCATEGORYAXISY_H */
diff --git a/src/charts/axis/categoryaxis/polarchartcategoryaxisangular.cpp b/src/charts/axis/categoryaxis/polarchartcategoryaxisangular.cpp
new file mode 100644
index 00000000..8c43dd32
--- /dev/null
+++ b/src/charts/axis/categoryaxis/polarchartcategoryaxisangular.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "polarchartcategoryaxisangular_p.h"
+#include "chartpresenter_p.h"
+#include "abstractchartlayout_p.h"
+#include "qcategoryaxis.h"
+#include <QDebug>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+PolarChartCategoryAxisAngular::PolarChartCategoryAxisAngular(QCategoryAxis *axis, QGraphicsItem *item)
+ : PolarChartAxisAngular(axis, item, true)
+{
+ QObject::connect(axis, SIGNAL(categoriesChanged()), this, SLOT(handleCategoriesChanged()));
+}
+
+PolarChartCategoryAxisAngular::~PolarChartCategoryAxisAngular()
+{
+}
+
+QVector<qreal> PolarChartCategoryAxisAngular::calculateLayout() const
+{
+ QCategoryAxis *catAxis = static_cast<QCategoryAxis *>(axis());
+ int tickCount = catAxis->categoriesLabels().count() + 1;
+ QVector<qreal> points;
+
+ if (tickCount < 2)
+ return points;
+
+ qreal range = max() - min();
+ if (range > 0) {
+ points.resize(tickCount);
+ qreal scale = 360.0 / range;
+ qreal angle;
+ for (int i = 0; i < tickCount; ++i) {
+ if (i < tickCount - 1)
+ angle = (catAxis->startValue(catAxis->categoriesLabels().at(i)) - min()) * scale;
+ else
+ angle = (catAxis->endValue(catAxis->categoriesLabels().at(i - 1)) - min()) * scale;
+ points[i] = angle;
+ }
+ }
+
+ return points;
+}
+
+void PolarChartCategoryAxisAngular::createAxisLabels(const QVector<qreal> &layout)
+{
+ Q_UNUSED(layout);
+ setLabels(static_cast<QCategoryAxis *>(axis())->categoriesLabels() << QString());
+}
+
+void PolarChartCategoryAxisAngular::handleCategoriesChanged()
+{
+ QGraphicsLayoutItem::updateGeometry();
+ presenter()->layout()->invalidate();
+}
+
+
+#include "moc_polarchartcategoryaxisangular_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/categoryaxis/polarchartcategoryaxisangular_p.h b/src/charts/axis/categoryaxis/polarchartcategoryaxisangular_p.h
new file mode 100644
index 00000000..0432fc11
--- /dev/null
+++ b/src/charts/axis/categoryaxis/polarchartcategoryaxisangular_p.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 POLARCHARTCATEGORYAXISANGULAR_P_H
+#define POLARCHARTCATEGORYAXISANGULAR_P_H
+
+#include "polarchartaxisangular_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QCategoryAxis;
+
+class PolarChartCategoryAxisAngular : public PolarChartAxisAngular
+{
+ Q_OBJECT
+
+public:
+ PolarChartCategoryAxisAngular(QCategoryAxis *axis, QGraphicsItem *item);
+ ~PolarChartCategoryAxisAngular();
+
+ virtual QVector<qreal> calculateLayout() const;
+ virtual void createAxisLabels(const QVector<qreal> &layout);
+
+public Q_SLOTS:
+ void handleCategoriesChanged();
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // POLARCHARTCATEGORYAXISANGULAR_P_H
diff --git a/src/charts/axis/categoryaxis/polarchartcategoryaxisradial.cpp b/src/charts/axis/categoryaxis/polarchartcategoryaxisradial.cpp
new file mode 100644
index 00000000..60b77f0c
--- /dev/null
+++ b/src/charts/axis/categoryaxis/polarchartcategoryaxisradial.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "polarchartcategoryaxisradial_p.h"
+#include "chartpresenter_p.h"
+#include "abstractchartlayout_p.h"
+#include "qcategoryaxis.h"
+#include <QDebug>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+PolarChartCategoryAxisRadial::PolarChartCategoryAxisRadial(QCategoryAxis *axis, QGraphicsItem *item)
+ : PolarChartAxisRadial(axis, item, true)
+{
+ QObject::connect(axis, SIGNAL(categoriesChanged()), this, SLOT(handleCategoriesChanged()));
+}
+
+PolarChartCategoryAxisRadial::~PolarChartCategoryAxisRadial()
+{
+}
+
+QVector<qreal> PolarChartCategoryAxisRadial::calculateLayout() const
+{
+ QCategoryAxis *catAxis = static_cast<QCategoryAxis *>(axis());
+ int tickCount = catAxis->categoriesLabels().count() + 1;
+ QVector<qreal> points;
+
+ if (tickCount < 2)
+ return points;
+
+ qreal range = max() - min();
+ if (range > 0) {
+ points.resize(tickCount);
+ qreal scale = (axisGeometry().width() / 2) / range;
+ qreal angle;
+ for (int i = 0; i < tickCount; ++i) {
+ if (i < tickCount - 1)
+ angle = (catAxis->startValue(catAxis->categoriesLabels().at(i)) - min()) * scale;
+ else
+ angle = (catAxis->endValue(catAxis->categoriesLabels().at(i - 1)) - min()) * scale;
+ points[i] = angle;
+ }
+ }
+
+ return points;
+}
+
+void PolarChartCategoryAxisRadial::createAxisLabels(const QVector<qreal> &layout)
+{
+ Q_UNUSED(layout);
+ setLabels(static_cast<QCategoryAxis *>(axis())->categoriesLabels() << QString());
+}
+
+void PolarChartCategoryAxisRadial::handleCategoriesChanged()
+{
+ QGraphicsLayoutItem::updateGeometry();
+ presenter()->layout()->invalidate();
+}
+
+#include "moc_polarchartcategoryaxisradial_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/categoryaxis/polarchartcategoryaxisradial_p.h b/src/charts/axis/categoryaxis/polarchartcategoryaxisradial_p.h
new file mode 100644
index 00000000..3186f5ec
--- /dev/null
+++ b/src/charts/axis/categoryaxis/polarchartcategoryaxisradial_p.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 POLARCHARTCATEGORYAXISRADIAL_P_H
+#define POLARCHARTCATEGORYAXISRADIAL_P_H
+
+#include "polarchartaxisradial_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QCategoryAxis;
+
+class PolarChartCategoryAxisRadial : public PolarChartAxisRadial
+{
+ Q_OBJECT
+
+public:
+ PolarChartCategoryAxisRadial(QCategoryAxis *axis, QGraphicsItem *item);
+ ~PolarChartCategoryAxisRadial();
+
+ virtual QVector<qreal> calculateLayout() const;
+ virtual void createAxisLabels(const QVector<qreal> &layout);
+
+public Q_SLOTS:
+ void handleCategoriesChanged();
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // POLARCHARTCATEGORYAXISRADIAL_P_H
diff --git a/src/charts/axis/categoryaxis/qcategoryaxis.cpp b/src/charts/axis/categoryaxis/qcategoryaxis.cpp
new file mode 100644
index 00000000..d5b3d472
--- /dev/null
+++ b/src/charts/axis/categoryaxis/qcategoryaxis.cpp
@@ -0,0 +1,345 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcategoryaxis.h"
+#include "qcategoryaxis_p.h"
+#include "chartcategoryaxisx_p.h"
+#include "chartcategoryaxisy_p.h"
+#include "polarchartcategoryaxisangular_p.h"
+#include "polarchartcategoryaxisradial_p.h"
+#include "qchart.h"
+#include <qmath.h>
+#include <QDebug>
+
+QT_CHARTS_BEGIN_NAMESPACE
+/*!
+ \class QCategoryAxis
+ \inmodule Qt Charts
+ \brief The QCategoryAxis class allows putting a named ranges on the axis.
+ \mainclass
+
+ This class can be used when the underlying data needs to be given extra meaning.
+ Unlike with the QBarCategoryAxis the QCategoryAxis allows the categories ranges widths to be specified freely.
+
+ Example code on how to use QCategoryAxis:
+ \table
+ \row
+ \li \br
+ \br
+ \code
+ QChartView *chartView = new QChartView;
+ QLineSeries *series = new QLineSeries;
+ // ...
+ chartView->chart()->addSeries(series);
+
+ QCategoryAxis *axisY = new QCategoryAxis;
+ axisY->setMin(0);
+ axisY->setMax(52);
+ axisY->setStartValue(15);
+ axisY->append("First", 20);
+ axisY->append("Second", 37);
+ axisY->append("Third", 52);
+ chartView->chart()->setAxisY(axisY, series);
+ \endcode
+ \li \br
+ \inlineimage api_category_axis.png
+ \endtable
+*/
+/*!
+ \qmltype CategoryAxis
+ \instantiates QCategoryAxis
+ \inqmlmodule QtCharts
+
+ \inherits AbstractAxis
+ \brief CategoryAxis allows putting a named ranges on the axis.
+
+ For example:
+ \table
+ \row
+ \li \br
+ \br
+ \br
+ \snippet qmlaxes/qml/qmlaxes/View3.qml 1
+ \li \inlineimage examples_qmlaxes3.png
+ \endtable
+*/
+
+/*!
+ \property QCategoryAxis::startValue
+ Defines the low end of the first category on the axis.
+*/
+/*!
+ \qmlproperty int CategoryAxis::startValue
+ Defines the low end of the first category on the axis.
+*/
+
+/*!
+ \property QCategoryAxis::count
+ The count of categories.
+*/
+/*!
+ \qmlproperty int CategoryAxis::count
+ The count of categories.
+*/
+
+/*!
+ \property QCategoryAxis::categoriesLabels
+ The category labels as a string list.
+*/
+/*!
+ \qmlproperty StringList CategoryAxis::categoriesLabels
+ The category labels as a list of strings.
+*/
+
+/*!
+ \fn void QCategoryAxis::categoriesChanged()
+ Axis emits signal when the categories of the axis have changed.
+*/
+
+
+/*!
+ Constructs an axis object which is a child of \a parent.
+*/
+QCategoryAxis::QCategoryAxis(QObject *parent):
+ QValueAxis(*new QCategoryAxisPrivate(this), parent)
+{
+}
+
+/*!
+ Destroys the object
+*/
+QCategoryAxis::~QCategoryAxis()
+{
+ Q_D(QCategoryAxis);
+ if (d->m_chart)
+ d->m_chart->removeAxis(this);
+}
+
+/*!
+ \internal
+*/
+QCategoryAxis::QCategoryAxis(QCategoryAxisPrivate &d, QObject *parent): QValueAxis(d, parent)
+{
+
+}
+
+/*!
+ \qmlmethod CategoryAxis::append(string label, real endValue)
+ Appends new category to the axis with an \a label. Category label has to be unique.
+ Parameter \a endValue specifies the high end limit of the category.
+ It has to be greater than the high end limit of the previous category.
+ Otherwise the method returns without adding a new category.
+*/
+/*!
+ Appends new category to the axis with an \a categoryLabel.
+ Category label has to be unique.
+ Parameter \a categoryEndValue specifies the high end limit of the category.
+ It has to be greater than the high end limit of the previous category.
+ Otherwise the method returns without adding a new category.
+*/
+void QCategoryAxis::append(const QString &categoryLabel, qreal categoryEndValue)
+{
+ Q_D(QCategoryAxis);
+
+ if (!d->m_categories.contains(categoryLabel)) {
+ if (d->m_categories.isEmpty()) {
+ Range range(d->m_categoryMinimum, categoryEndValue);
+ d->m_categoriesMap.insert(categoryLabel, range);
+ d->m_categories.append(categoryLabel);
+ emit categoriesChanged();
+ } else if (categoryEndValue > endValue(d->m_categories.last())) {
+ Range previousRange = d->m_categoriesMap.value(d->m_categories.last());
+ d->m_categoriesMap.insert(categoryLabel, Range(previousRange.second, categoryEndValue));
+ d->m_categories.append(categoryLabel);
+ emit categoriesChanged();
+ }
+ }
+}
+
+/*!
+ Sets \a min to be the low end limit of the first category on the axis.
+ If there is already some categories added to the axis then passed value must be lower than the high end value of the already defined first category range.
+ Otherwise nothing is done.
+*/
+void QCategoryAxis::setStartValue(qreal min)
+{
+ Q_D(QCategoryAxis);
+ if (d->m_categories.isEmpty()) {
+ d->m_categoryMinimum = min;
+ emit categoriesChanged();
+ } else {
+ Range range = d->m_categoriesMap.value(d->m_categories.first());
+ if (min < range.second) {
+ d->m_categoriesMap.insert(d->m_categories.first(), Range(min, range.second));
+ emit categoriesChanged();
+ }
+ }
+}
+
+/*!
+ Returns the low end limit of the category specified by an \a categoryLabel
+*/
+qreal QCategoryAxis::startValue(const QString &categoryLabel) const
+{
+ Q_D(const QCategoryAxis);
+ if (categoryLabel.isEmpty())
+ return d->m_categoryMinimum;
+ return d->m_categoriesMap.value(categoryLabel).first;
+}
+
+/*!
+ Returns the high end limit of the interval specified by an \a categoryLabel
+*/
+qreal QCategoryAxis::endValue(const QString &categoryLabel) const
+{
+ Q_D(const QCategoryAxis);
+ return d->m_categoriesMap.value(categoryLabel).second;
+}
+
+/*!
+ \qmlmethod CategoryAxis::remove(string label)
+ Removes a category specified by the \a label from the axis
+*/
+/*!
+ Removes an interval specified by the \a categoryLabel from the axis
+*/
+void QCategoryAxis::remove(const QString &categoryLabel)
+{
+ Q_D(QCategoryAxis);
+ int labelIndex = d->m_categories.indexOf(categoryLabel);
+
+ // check if such label exists
+ if (labelIndex != -1) {
+ d->m_categories.removeAt(labelIndex);
+ d->m_categoriesMap.remove(categoryLabel);
+
+ // the range of the interval that follows (if exists) needs to be updated
+ if (labelIndex < d->m_categories.count()) {
+ QString label = d->m_categories.at(labelIndex);
+ Range range = d->m_categoriesMap.value(label);
+
+ // set the range
+ if (labelIndex == 0) {
+ range.first = d->m_categoryMinimum;
+ d->m_categoriesMap.insert(label, range);
+ } else {
+ range.first = d->m_categoriesMap.value(d->m_categories.at(labelIndex - 1)).second;
+ d->m_categoriesMap.insert(label, range);
+ }
+ }
+ emit categoriesChanged();
+ }
+}
+
+/*!
+ \qmlmethod CategoryAxis::replace(string oldLabel, string newLabel)
+ Replaces \a oldLabel of an existing category with a \a newLabel.
+ If the old label does not exist the method returns without making any changes.
+*/
+/*!
+ Replaces \a oldLabel of an existing category with a \a newLabel
+ If the old label does not exist the method returns without making any changes.
+ */
+void QCategoryAxis::replaceLabel(const QString &oldLabel, const QString &newLabel)
+{
+ Q_D(QCategoryAxis);
+ int labelIndex = d->m_categories.indexOf(oldLabel);
+
+ // check if such label exists
+ if (labelIndex != -1) {
+ d->m_categories.replace(labelIndex, newLabel);
+ Range range = d->m_categoriesMap.value(oldLabel);
+ d->m_categoriesMap.remove(oldLabel);
+ d->m_categoriesMap.insert(newLabel, range);
+ emit categoriesChanged();
+ }
+}
+
+/*!
+ Returns the list of the intervals labels
+ */
+QStringList QCategoryAxis::categoriesLabels()
+{
+ Q_D(QCategoryAxis);
+ return d->m_categories;
+}
+
+/*!
+ Returns number of intervals.
+ */
+int QCategoryAxis::count() const
+{
+ Q_D(const QCategoryAxis);
+ return d->m_categories.count();
+}
+
+/*!
+ Returns the type of the axis
+*/
+QAbstractAxis::AxisType QCategoryAxis::type() const
+{
+ return QAbstractAxis::AxisTypeCategory;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QCategoryAxisPrivate::QCategoryAxisPrivate(QCategoryAxis *q)
+ : QValueAxisPrivate(q),
+ m_categoryMinimum(0)
+{
+
+}
+
+QCategoryAxisPrivate::~QCategoryAxisPrivate()
+{
+
+}
+
+int QCategoryAxisPrivate::ticksCount() const
+{
+ return m_categories.count() + 1;
+}
+
+void QCategoryAxisPrivate::initializeGraphics(QGraphicsItem *parent)
+{
+ Q_Q(QCategoryAxis);
+ ChartAxisElement *axis(0);
+ if (m_chart->chartType() == QChart::ChartTypeCartesian) {
+ if (orientation() == Qt::Vertical)
+ axis = new ChartCategoryAxisY(q,parent);
+ else if (orientation() == Qt::Horizontal)
+ axis = new ChartCategoryAxisX(q,parent);
+ }
+
+ if (m_chart->chartType() == QChart::ChartTypePolar) {
+ if (orientation() == Qt::Vertical)
+ axis = new PolarChartCategoryAxisRadial(q, parent);
+ if (orientation() == Qt::Horizontal)
+ axis = new PolarChartCategoryAxisAngular(q, parent);
+ }
+
+ m_item.reset(axis);
+ QAbstractAxisPrivate::initializeGraphics(parent);
+}
+
+#include "moc_qcategoryaxis.cpp"
+#include "moc_qcategoryaxis_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/categoryaxis/qcategoryaxis.h b/src/charts/axis/categoryaxis/qcategoryaxis.h
new file mode 100644
index 00000000..bd4b3d82
--- /dev/null
+++ b/src/charts/axis/categoryaxis/qcategoryaxis.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCATEGORYAXIS_H
+#define QCATEGORYAXIS_H
+
+#include <QtCharts/qabstractaxis.h>
+#include <QtCharts/qvalueaxis.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QCategoryAxisPrivate;
+
+class QT_CHARTS_EXPORT QCategoryAxis : public QValueAxis
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal startValue READ startValue WRITE setStartValue)
+ Q_PROPERTY(int count READ count)
+ Q_PROPERTY(QStringList categoriesLabels READ categoriesLabels)
+
+public:
+ explicit QCategoryAxis(QObject *parent = 0);
+ ~QCategoryAxis();
+
+protected:
+ QCategoryAxis(QCategoryAxisPrivate &d, QObject *parent = 0);
+
+public:
+ AxisType type() const;
+
+ void append(const QString &label, qreal categoryEndValue);
+ void remove(const QString &label);
+ void replaceLabel(const QString &oldLabel, const QString &newLabel);
+
+ qreal startValue(const QString &categoryLabel = QString()) const;
+ void setStartValue(qreal min);
+
+ qreal endValue(const QString &categoryLabel) const;
+
+ QStringList categoriesLabels();
+ int count() const;
+
+Q_SIGNALS:
+ void categoriesChanged();
+
+private:
+ Q_DECLARE_PRIVATE(QCategoryAxis)
+ Q_DISABLE_COPY(QCategoryAxis)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QCATEGORYAXIS_H
diff --git a/src/charts/axis/categoryaxis/qcategoryaxis_p.h b/src/charts/axis/categoryaxis/qcategoryaxis_p.h
new file mode 100644
index 00000000..bc657521
--- /dev/null
+++ b/src/charts/axis/categoryaxis/qcategoryaxis_p.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QCATEGORYAXIS_P_H
+#define QCATEGORYAXIS_P_H
+
+#include <qcategoryaxis.h>
+#include "qvalueaxis_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+typedef QPair<qreal, qreal> Range;
+
+class QCategoryAxisPrivate : public QValueAxisPrivate
+{
+ Q_OBJECT
+
+public:
+ QCategoryAxisPrivate(QCategoryAxis *q);
+ ~QCategoryAxisPrivate();
+
+ void initializeGraphics(QGraphicsItem* parent);
+ int ticksCount() const;
+
+private:
+ QMap<QString , Range> m_categoriesMap;
+ QStringList m_categories;
+ qreal m_categoryMinimum;
+
+private:
+ Q_DECLARE_PUBLIC(QCategoryAxis)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QCATEGORYAXIS_P_H
diff --git a/src/charts/axis/chartaxiselement.cpp b/src/charts/axis/chartaxiselement.cpp
new file mode 100644
index 00000000..b7a60d27
--- /dev/null
+++ b/src/charts/axis/chartaxiselement.cpp
@@ -0,0 +1,404 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "chartaxiselement_p.h"
+#include "qabstractaxis_p.h"
+#include "chartpresenter_p.h"
+#include "abstractchartlayout_p.h"
+#include <qmath.h>
+#include <QDateTime>
+#include <QTextDocument>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+static const char *labelFormatMatchString = "%[\\-\\+#\\s\\d\\.lhjztL]*([dicuoxfegXFEG])";
+static const char *labelFormatMatchLocalizedString = "^([^%]*)%\\.(\\d+)([defgiEG])(.*)$";
+static QRegExp *labelFormatMatcher = 0;
+static QRegExp *labelFormatMatcherLocalized = 0;
+class StaticLabelFormatMatcherDeleter
+{
+public:
+ StaticLabelFormatMatcherDeleter() {}
+ ~StaticLabelFormatMatcherDeleter() {
+ delete labelFormatMatcher;
+ delete labelFormatMatcherLocalized;
+ }
+};
+static StaticLabelFormatMatcherDeleter staticLabelFormatMatcherDeleter;
+
+ChartAxisElement::ChartAxisElement(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
+ : ChartElement(item),
+ m_axis(axis),
+ m_animation(0),
+ m_grid(new QGraphicsItemGroup(item)),
+ m_arrow(new QGraphicsItemGroup(item)),
+ m_shades(new QGraphicsItemGroup(item)),
+ m_labels(new QGraphicsItemGroup(item)),
+ m_title(new QGraphicsTextItem(item)),
+ m_intervalAxis(intervalAxis)
+
+{
+ //initial initialization
+ m_arrow->setHandlesChildEvents(false);
+ m_arrow->setZValue(ChartPresenter::AxisZValue);
+ m_labels->setZValue(ChartPresenter::AxisZValue);
+ m_shades->setZValue(ChartPresenter::ShadesZValue);
+ m_grid->setZValue(ChartPresenter::GridZValue);
+ m_title->setZValue(ChartPresenter::GridZValue);
+ m_title->document()->setDocumentMargin(ChartPresenter::textMargin());
+ handleVisibleChanged(axis->isVisible());
+ connectSlots();
+
+ setFlag(QGraphicsItem::ItemHasNoContents, true);
+}
+
+ChartAxisElement::~ChartAxisElement()
+{
+}
+
+void ChartAxisElement::connectSlots()
+{
+ QObject::connect(axis(), SIGNAL(visibleChanged(bool)), this, SLOT(handleVisibleChanged(bool)));
+ QObject::connect(axis(), SIGNAL(lineVisibleChanged(bool)), this, SLOT(handleArrowVisibleChanged(bool)));
+ QObject::connect(axis(), SIGNAL(gridVisibleChanged(bool)), this, SLOT(handleGridVisibleChanged(bool)));
+ QObject::connect(axis(), SIGNAL(labelsVisibleChanged(bool)), this, SLOT(handleLabelsVisibleChanged(bool)));
+ QObject::connect(axis(), SIGNAL(shadesVisibleChanged(bool)), this, SLOT(handleShadesVisibleChanged(bool)));
+ QObject::connect(axis(), SIGNAL(labelsAngleChanged(int)), this, SLOT(handleLabelsAngleChanged(int)));
+ QObject::connect(axis(), SIGNAL(linePenChanged(const QPen&)), this, SLOT(handleArrowPenChanged(const QPen&)));
+ QObject::connect(axis(), SIGNAL(labelsPenChanged(const QPen&)), this, SLOT(handleLabelsPenChanged(const QPen&)));
+ QObject::connect(axis(), SIGNAL(labelsBrushChanged(const QBrush&)), this, SLOT(handleLabelsBrushChanged(const QBrush&)));
+ QObject::connect(axis(), SIGNAL(labelsFontChanged(const QFont&)), this, SLOT(handleLabelsFontChanged(const QFont&)));
+ QObject::connect(axis(), SIGNAL(gridLinePenChanged(const QPen&)), this, SLOT(handleGridPenChanged(const QPen&)));
+ QObject::connect(axis(), SIGNAL(shadesPenChanged(const QPen&)), this, SLOT(handleShadesPenChanged(const QPen&)));
+ QObject::connect(axis(), SIGNAL(shadesBrushChanged(const QBrush&)), this, SLOT(handleShadesBrushChanged(const QBrush&)));
+ QObject::connect(axis(), SIGNAL(titleTextChanged(const QString&)), this, SLOT(handleTitleTextChanged(const QString&)));
+ QObject::connect(axis(), SIGNAL(titleFontChanged(const QFont&)), this, SLOT(handleTitleFontChanged(const QFont&)));
+ QObject::connect(axis(), SIGNAL(titlePenChanged(const QPen&)), this, SLOT(handleTitlePenChanged(const QPen&)));
+ QObject::connect(axis(), SIGNAL(titleBrushChanged(const QBrush&)), this, SLOT(handleTitleBrushChanged(const QBrush&)));
+ QObject::connect(axis(), SIGNAL(titleVisibleChanged(bool)), this, SLOT(handleTitleVisibleChanged(bool)));
+ QObject::connect(axis()->d_ptr.data(), SIGNAL(rangeChanged(qreal, qreal)), this, SLOT(handleRangeChanged(qreal, qreal)));
+}
+
+void ChartAxisElement::handleArrowVisibleChanged(bool visible)
+{
+ m_arrow->setVisible(visible);
+}
+
+void ChartAxisElement::handleGridVisibleChanged(bool visible)
+{
+ m_grid->setVisible(visible);
+}
+
+void ChartAxisElement::handleLabelsVisibleChanged(bool visible)
+{
+ QGraphicsLayoutItem::updateGeometry();
+ presenter()->layout()->invalidate();
+ m_labels->setVisible(visible);
+}
+
+void ChartAxisElement::handleShadesVisibleChanged(bool visible)
+{
+ m_shades->setVisible(visible);
+}
+
+void ChartAxisElement::handleTitleVisibleChanged(bool visible)
+{
+ QGraphicsLayoutItem::updateGeometry();
+ presenter()->layout()->invalidate();
+ m_title->setVisible(visible);
+}
+
+void ChartAxisElement::handleLabelsAngleChanged(int angle)
+{
+ foreach (QGraphicsItem *item, m_labels->childItems())
+ item->setRotation(angle);
+
+ QGraphicsLayoutItem::updateGeometry();
+ presenter()->layout()->invalidate();
+}
+
+void ChartAxisElement::handleLabelsPenChanged(const QPen &pen)
+{
+ Q_UNUSED(pen)
+}
+
+void ChartAxisElement::handleLabelsBrushChanged(const QBrush &brush)
+{
+ foreach (QGraphicsItem *item, m_labels->childItems())
+ static_cast<QGraphicsTextItem *>(item)->setDefaultTextColor(brush.color());
+}
+
+void ChartAxisElement::handleLabelsFontChanged(const QFont &font)
+{
+ foreach (QGraphicsItem *item, m_labels->childItems())
+ static_cast<QGraphicsTextItem *>(item)->setFont(font);
+ QGraphicsLayoutItem::updateGeometry();
+ presenter()->layout()->invalidate();
+}
+
+void ChartAxisElement::handleTitleTextChanged(const QString &title)
+{
+ QGraphicsLayoutItem::updateGeometry();
+ presenter()->layout()->invalidate();
+ if (title.isEmpty() || !m_title->isVisible())
+ m_title->setHtml(title);
+}
+
+void ChartAxisElement::handleTitlePenChanged(const QPen &pen)
+{
+ Q_UNUSED(pen)
+}
+
+void ChartAxisElement::handleTitleBrushChanged(const QBrush &brush)
+{
+ m_title->setDefaultTextColor(brush.color());
+}
+
+void ChartAxisElement::handleTitleFontChanged(const QFont &font)
+{
+ if (m_title->font() != font) {
+ m_title->setFont(font);
+ QGraphicsLayoutItem::updateGeometry();
+ presenter()->layout()->invalidate();
+ }
+}
+
+void ChartAxisElement::handleVisibleChanged(bool visible)
+{
+ setVisible(visible);
+ if (!visible) {
+ m_grid->setVisible(visible);
+ m_arrow->setVisible(visible);
+ m_shades->setVisible(visible);
+ m_labels->setVisible(visible);
+ m_title->setVisible(visible);
+ } else {
+ m_grid->setVisible(axis()->isGridLineVisible());
+ m_arrow->setVisible(axis()->isLineVisible());
+ m_shades->setVisible(axis()->shadesVisible());
+ m_labels->setVisible(axis()->labelsVisible());
+ m_title->setVisible(axis()->isTitleVisible());
+ }
+
+ if (presenter()) presenter()->layout()->invalidate();
+}
+
+void ChartAxisElement::handleRangeChanged(qreal min, qreal max)
+{
+ Q_UNUSED(min);
+ Q_UNUSED(max);
+
+ if (!isEmpty()) {
+ QVector<qreal> layout = calculateLayout();
+ updateLayout(layout);
+ QSizeF before = effectiveSizeHint(Qt::PreferredSize);
+ QSizeF after = sizeHint(Qt::PreferredSize);
+
+ if (before != after) {
+ QGraphicsLayoutItem::updateGeometry();
+ // We don't want to call invalidate on layout, since it will change minimum size of
+ // component, which we would like to avoid since it causes nasty flips when scrolling
+ // or zooming, instead recalculate layout and use plotArea for extra space.
+ presenter()->layout()->setGeometry(presenter()->layout()->geometry());
+ }
+ }
+}
+
+bool ChartAxisElement::isEmpty()
+{
+ return axisGeometry().isEmpty()
+ || gridGeometry().isEmpty()
+ || qFuzzyCompare(min(), max());
+}
+
+qreal ChartAxisElement::min() const
+{
+ return m_axis->d_ptr->min();
+}
+
+qreal ChartAxisElement::max() const
+{
+ return m_axis->d_ptr->max();
+}
+
+QString ChartAxisElement::formatLabel(const QString &formatSpec, const QByteArray &array,
+ qreal value, int precision, const QString &preStr,
+ const QString &postStr) const
+{
+ QString retVal;
+ if (!formatSpec.isEmpty()) {
+ if (formatSpec.at(0) == QLatin1Char('d')
+ || formatSpec.at(0) == QLatin1Char('i')
+ || formatSpec.at(0) == QLatin1Char('c')) {
+ if (presenter()->localizeNumbers())
+ retVal = preStr + presenter()->locale().toString(qint64(value)) + postStr;
+ else
+ retVal = QString().sprintf(array, qint64(value));
+ } else if (formatSpec.at(0) == QLatin1Char('u')
+ || formatSpec.at(0) == QLatin1Char('o')
+ || formatSpec.at(0) == QLatin1Char('x')
+ || formatSpec.at(0) == QLatin1Char('X')) {
+ // These formats are not supported by localized numbers
+ retVal = QString().sprintf(array, quint64(value));
+ } else if (formatSpec.at(0) == QLatin1Char('f')
+ || formatSpec.at(0) == QLatin1Char('F')
+ || formatSpec.at(0) == QLatin1Char('e')
+ || formatSpec.at(0) == QLatin1Char('E')
+ || formatSpec.at(0) == QLatin1Char('g')
+ || formatSpec.at(0) == QLatin1Char('G')) {
+ if (presenter()->localizeNumbers()) {
+ retVal = preStr
+ + presenter()->locale().toString(value, formatSpec.at(0).toLatin1(),
+ precision)
+ + postStr;
+ } else {
+ retVal = QString().sprintf(array, value);
+ }
+ }
+ }
+ return retVal;
+}
+
+QStringList ChartAxisElement::createValueLabels(qreal min, qreal max, int ticks,
+ const QString &format) const
+{
+ QStringList labels;
+
+ if (max <= min || ticks < 1)
+ return labels;
+
+ if (format.isNull()) {
+ int n = qMax(int(-qFloor(log10((max - min) / (ticks - 1)))), 0) + 1;
+ for (int i = 0; i < ticks; i++) {
+ qreal value = min + (i * (max - min) / (ticks - 1));
+ labels << presenter()->numberToString(value, 'f', n);
+ }
+ } else {
+ QByteArray array = format.toLatin1();
+ QString formatSpec;
+ QString preStr;
+ QString postStr;
+ int precision = 6; // Six is the default precision in Qt API
+ if (presenter()->localizeNumbers()) {
+ if (!labelFormatMatcherLocalized)
+ labelFormatMatcherLocalized
+ = new QRegExp(QString::fromLatin1(labelFormatMatchLocalizedString));
+ if (labelFormatMatcherLocalized->indexIn(format, 0) != -1) {
+ preStr = labelFormatMatcherLocalized->cap(1);
+ if (!labelFormatMatcherLocalized->cap(2).isEmpty())
+ precision = labelFormatMatcherLocalized->cap(2).toInt();
+ formatSpec = labelFormatMatcherLocalized->cap(3);
+ postStr = labelFormatMatcherLocalized->cap(4);
+ }
+ } else {
+ if (!labelFormatMatcher)
+ labelFormatMatcher = new QRegExp(QString::fromLatin1(labelFormatMatchString));
+ if (labelFormatMatcher->indexIn(format, 0) != -1)
+ formatSpec = labelFormatMatcher->cap(1);
+ }
+ for (int i = 0; i < ticks; i++) {
+ qreal value = min + (i * (max - min) / (ticks - 1));
+ labels << formatLabel(formatSpec, array, value, precision, preStr, postStr);
+ }
+ }
+
+ return labels;
+}
+
+QStringList ChartAxisElement::createLogValueLabels(qreal min, qreal max, qreal base, int ticks,
+ const QString &format) const
+{
+ QStringList labels;
+
+ if (max <= min || ticks < 1)
+ return labels;
+
+ int firstTick;
+ if (base > 1)
+ firstTick = ceil(log10(min) / log10(base));
+ else
+ firstTick = ceil(log10(max) / log10(base));
+
+ if (format.isNull()) {
+ int n = 0;
+ if (ticks > 1)
+ n = qMax(int(-qFloor(log10((max - min) / (ticks - 1)))), 0);
+ n++;
+ for (int i = firstTick; i < ticks + firstTick; i++) {
+ qreal value = qPow(base, i);
+ labels << presenter()->numberToString(value, 'f', n);
+ }
+ } else {
+ QByteArray array = format.toLatin1();
+ QString formatSpec;
+ QString preStr;
+ QString postStr;
+ int precision = 6; // Six is the default precision in Qt API
+ if (presenter()->localizeNumbers()) {
+ if (!labelFormatMatcherLocalized)
+ labelFormatMatcherLocalized =
+ new QRegExp(QString::fromLatin1(labelFormatMatchLocalizedString));
+ if (labelFormatMatcherLocalized->indexIn(format, 0) != -1) {
+ preStr = labelFormatMatcherLocalized->cap(1);
+ if (!labelFormatMatcherLocalized->cap(2).isEmpty())
+ precision = labelFormatMatcherLocalized->cap(2).toInt();
+ formatSpec = labelFormatMatcherLocalized->cap(3);
+ postStr = labelFormatMatcherLocalized->cap(4);
+ }
+ } else {
+ if (!labelFormatMatcher)
+ labelFormatMatcher = new QRegExp(QString::fromLatin1(labelFormatMatchString));
+ if (labelFormatMatcher->indexIn(format, 0) != -1)
+ formatSpec = labelFormatMatcher->cap(1);
+ }
+ for (int i = firstTick; i < ticks + firstTick; i++) {
+ qreal value = qPow(base, i);
+ labels << formatLabel(formatSpec, array, value, precision, preStr, postStr);
+ }
+ }
+
+ return labels;
+}
+
+QStringList ChartAxisElement::createDateTimeLabels(qreal min, qreal max,int ticks,
+ const QString &format) const
+{
+ QStringList labels;
+
+ if (max <= min || ticks < 1)
+ return labels;
+
+ int n = qMax(int(-floor(log10((max - min) / (ticks - 1)))), 0);
+ n++;
+ for (int i = 0; i < ticks; i++) {
+ qreal value = min + (i * (max - min) / (ticks - 1));
+ labels << presenter()->locale().toString(QDateTime::fromMSecsSinceEpoch(value), format);
+ }
+ return labels;
+}
+
+void ChartAxisElement::axisSelected()
+{
+ emit clicked();
+}
+
+#include "moc_chartaxiselement_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/chartaxiselement_p.h b/src/charts/axis/chartaxiselement_p.h
new file mode 100644
index 00000000..1cfac64d
--- /dev/null
+++ b/src/charts/axis/chartaxiselement_p.h
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTAXISELEMENT_H
+#define CHARTAXISELEMENT_H
+
+#include "qchartglobal.h"
+#include "chartelement_p.h"
+#include "axisanimation_p.h"
+#include <QGraphicsItem>
+#include <QGraphicsLayoutItem>
+#include <QFont>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class ChartPresenter;
+class QAbstractAxis;
+
+class ChartAxisElement : public ChartElement, public QGraphicsLayoutItem
+{
+ Q_OBJECT
+
+ using QGraphicsLayoutItem::setGeometry;
+public:
+ ChartAxisElement(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis = false);
+ ~ChartAxisElement();
+
+ virtual QRectF gridGeometry() const = 0;
+ virtual void setGeometry(const QRectF &axis, const QRectF &grid) = 0;
+ virtual bool isEmpty() = 0;
+
+ void setAnimation(AxisAnimation *animation) { m_animation = animation; }
+ AxisAnimation *animation() const { return m_animation; }
+
+ QAbstractAxis *axis() const { return m_axis; }
+ void setLayout(QVector<qreal> &layout) { m_layout = layout; }
+ QVector<qreal> &layout() { return m_layout; } // Modifiable reference
+ inline qreal labelPadding() const { return qreal(4.0); }
+ inline qreal titlePadding() const { return qreal(2.0); }
+ void setLabels(const QStringList &labels) { m_labelsList = labels; }
+ QStringList labels() const { return m_labelsList; }
+
+ qreal min() const;
+ qreal max() const;
+
+ QRectF axisGeometry() const { return m_axisRect; }
+ void setAxisGeometry(const QRectF &axisGeometry) { m_axisRect = axisGeometry; }
+
+ void axisSelected();
+
+ //this flag indicates that axis is used to show intervals it means labels are in between ticks
+ bool intervalAxis() const { return m_intervalAxis; }
+
+ QStringList createValueLabels(qreal max, qreal min, int ticks, const QString &format) const;
+ QStringList createLogValueLabels(qreal min, qreal max, qreal base, int ticks,
+ const QString &format) const;
+ QStringList createDateTimeLabels(qreal max, qreal min, int ticks, const QString &format) const;
+
+ // from QGraphicsLayoutItem
+ QRectF boundingRect() const
+ {
+ return QRectF();
+ }
+
+ // from QGraphicsLayoutItem
+ void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*)
+ {
+ }
+
+protected:
+ virtual QVector<qreal> calculateLayout() const = 0;
+ virtual void updateLayout(QVector<qreal> &layout) = 0;
+
+ QList<QGraphicsItem *> gridItems() { return m_grid->childItems(); }
+ QList<QGraphicsItem *> labelItems() { return m_labels->childItems(); }
+ QList<QGraphicsItem *> shadeItems() { return m_shades->childItems(); }
+ QList<QGraphicsItem *> arrowItems() { return m_arrow->childItems(); }
+ QGraphicsTextItem *titleItem() const { return m_title.data(); }
+ QGraphicsItemGroup *gridGroup() { return m_grid.data(); }
+ QGraphicsItemGroup *labelGroup() { return m_labels.data(); }
+ QGraphicsItemGroup *shadeGroup() { return m_shades.data(); }
+ QGraphicsItemGroup *arrowGroup() { return m_arrow.data(); }
+
+public Q_SLOTS:
+ void handleVisibleChanged(bool visible);
+ void handleArrowVisibleChanged(bool visible);
+ void handleGridVisibleChanged(bool visible);
+ void handleLabelsVisibleChanged(bool visible);
+ void handleShadesVisibleChanged(bool visible);
+ void handleLabelsAngleChanged(int angle);
+ virtual void handleShadesBrushChanged(const QBrush &brush) = 0;
+ virtual void handleShadesPenChanged(const QPen &pen) = 0;
+ virtual void handleArrowPenChanged(const QPen &pen) = 0;
+ virtual void handleGridPenChanged(const QPen &pen) = 0;
+ void handleLabelsPenChanged(const QPen &pen);
+ void handleLabelsBrushChanged(const QBrush &brush);
+ void handleLabelsFontChanged(const QFont &font);
+ void handleTitlePenChanged(const QPen &pen);
+ void handleTitleBrushChanged(const QBrush &brush);
+ void handleTitleFontChanged(const QFont &font);
+ void handleTitleTextChanged(const QString &title);
+ void handleTitleVisibleChanged(bool visible);
+ void handleRangeChanged(qreal min, qreal max);
+
+Q_SIGNALS:
+ void clicked();
+
+private:
+ void connectSlots();
+ QString formatLabel(const QString &formatSpec, const QByteArray &array,
+ qreal value, int precision, const QString &preStr,
+ const QString &postStr) const;
+
+ QAbstractAxis *m_axis;
+ AxisAnimation *m_animation;
+ QVector<qreal> m_layout;
+ QStringList m_labelsList;
+ QRectF m_axisRect;
+ QScopedPointer<QGraphicsItemGroup> m_grid;
+ QScopedPointer<QGraphicsItemGroup> m_arrow;
+ QScopedPointer<QGraphicsItemGroup> m_shades;
+ QScopedPointer<QGraphicsItemGroup> m_labels;
+ QScopedPointer<QGraphicsTextItem> m_title;
+ bool m_intervalAxis;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif /* CHARTAXISELEMENT_H */
diff --git a/src/charts/axis/datetimeaxis/chartdatetimeaxisx.cpp b/src/charts/axis/datetimeaxis/chartdatetimeaxisx.cpp
new file mode 100644
index 00000000..bdd010a0
--- /dev/null
+++ b/src/charts/axis/datetimeaxis/chartdatetimeaxisx.cpp
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "chartdatetimeaxisx_p.h"
+#include "chartpresenter_p.h"
+#include "qdatetimeaxis.h"
+#include "abstractchartlayout_p.h"
+#include <QGraphicsLayout>
+#include <QDateTime>
+#include <qmath.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+ChartDateTimeAxisX::ChartDateTimeAxisX(QDateTimeAxis *axis, QGraphicsItem *item)
+ : HorizontalAxis(axis, item),
+ m_axis(axis)
+{
+ QObject::connect(m_axis, SIGNAL(tickCountChanged(int)), this, SLOT(handleTickCountChanged(int)));
+ QObject::connect(m_axis, SIGNAL(formatChanged(QString)), this, SLOT(handleFormatChanged(QString)));
+}
+
+ChartDateTimeAxisX::~ChartDateTimeAxisX()
+{
+}
+
+QVector<qreal> ChartDateTimeAxisX::calculateLayout() const
+{
+ int tickCount = m_axis->tickCount();
+
+ Q_ASSERT(tickCount >= 2);
+
+ QVector<qreal> points;
+ points.resize(tickCount);
+ const QRectF &gridRect = gridGeometry();
+ const qreal deltaX = gridRect.width() / (qreal(tickCount) - 1.0);
+ for (int i = 0; i < tickCount; ++i)
+ points[i] = qreal(i) * deltaX + gridRect.left();
+ return points;
+}
+
+void ChartDateTimeAxisX::updateGeometry()
+{
+ const QVector<qreal>& layout = ChartAxisElement::layout();
+ if (layout.isEmpty())
+ return;
+ setLabels(createDateTimeLabels(min(), max(), layout.size(), m_axis->format()));
+ HorizontalAxis::updateGeometry();
+}
+
+void ChartDateTimeAxisX::handleTickCountChanged(int tick)
+{
+ Q_UNUSED(tick)
+ QGraphicsLayoutItem::updateGeometry();
+ if (presenter())
+ presenter()->layout()->invalidate();
+}
+
+void ChartDateTimeAxisX::handleFormatChanged(const QString &format)
+{
+ Q_UNUSED(format);
+ QGraphicsLayoutItem::updateGeometry();
+ if (presenter())
+ presenter()->layout()->invalidate();
+}
+
+QSizeF ChartDateTimeAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED(constraint)
+
+ QSizeF sh;
+
+ QSizeF base = HorizontalAxis::sizeHint(which, constraint);
+ QStringList ticksList = createDateTimeLabels(min(), max(), m_axis->tickCount(), m_axis->format());
+ // Width of horizontal axis sizeHint indicates the maximum distance labels can extend past
+ // first and last ticks. Base width is irrelevant.
+ qreal width = 0;
+ qreal height = 0;
+
+ if (ticksList.empty())
+ return sh;
+
+ switch (which) {
+ case Qt::MinimumSize: {
+ QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(),
+ QStringLiteral("..."),
+ axis()->labelsAngle());
+ width = boundingRect.width() / 2.0;
+ height = boundingRect.height() + labelPadding() + base.height() + 1.0;
+ sh = QSizeF(width, height);
+ break;
+ }
+ case Qt::PreferredSize: {
+ qreal labelHeight = 0.0;
+ qreal firstWidth = -1.0;
+ foreach (const QString& s, ticksList) {
+ QRectF rect = ChartPresenter::textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
+ labelHeight = qMax(rect.height(), labelHeight);
+ width = rect.width();
+ if (firstWidth < 0.0)
+ firstWidth = width;
+ }
+ height = labelHeight + labelPadding() + base.height() + 1.0;
+ width = qMax(width, firstWidth) / 2.0;
+ sh = QSizeF(width, height);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return sh;
+}
+
+#include "moc_chartdatetimeaxisx_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/datetimeaxis/chartdatetimeaxisx_p.h b/src/charts/axis/datetimeaxis/chartdatetimeaxisx_p.h
new file mode 100644
index 00000000..3ca2ef45
--- /dev/null
+++ b/src/charts/axis/datetimeaxis/chartdatetimeaxisx_p.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTDATETIMEAXISX_H
+#define CHARTDATETIMEAXISX_H
+
+#include "horizontalaxis_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QDateTimeAxis;
+
+class ChartDateTimeAxisX : public HorizontalAxis
+{
+ Q_OBJECT
+public:
+ ChartDateTimeAxisX(QDateTimeAxis *axis, QGraphicsItem* item = 0);
+ ~ChartDateTimeAxisX();
+
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const;
+protected:
+ QVector<qreal> calculateLayout() const;
+ void updateGeometry();
+private Q_SLOTS:
+ void handleTickCountChanged(int tick);
+ void handleFormatChanged(const QString &format);
+
+private:
+ QDateTimeAxis *m_axis;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif /* CHARTDATETIMEAXISX_H */
diff --git a/src/charts/axis/datetimeaxis/chartdatetimeaxisy.cpp b/src/charts/axis/datetimeaxis/chartdatetimeaxisy.cpp
new file mode 100644
index 00000000..5e67936b
--- /dev/null
+++ b/src/charts/axis/datetimeaxis/chartdatetimeaxisy.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "chartdatetimeaxisy_p.h"
+#include "chartpresenter_p.h"
+#include "qdatetimeaxis.h"
+#include "abstractchartlayout_p.h"
+#include <QGraphicsLayout>
+#include <QDateTime>
+#include <qmath.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+ChartDateTimeAxisY::ChartDateTimeAxisY(QDateTimeAxis *axis, QGraphicsItem *item)
+ : VerticalAxis(axis, item),
+ m_axis(axis)
+{
+ QObject::connect(m_axis, SIGNAL(tickCountChanged(int)), this, SLOT(handleTickCountChanged(int)));
+ QObject::connect(m_axis, SIGNAL(formatChanged(QString)), this, SLOT(handleFormatChanged(QString)));
+}
+
+ChartDateTimeAxisY::~ChartDateTimeAxisY()
+{
+}
+
+QVector<qreal> ChartDateTimeAxisY::calculateLayout() const
+{
+ int tickCount = m_axis->tickCount();
+
+ Q_ASSERT(tickCount >= 2);
+
+ QVector<qreal> points;
+ points.resize(tickCount);
+ const QRectF &gridRect = gridGeometry();
+ const qreal deltaY = gridRect.height() / (qreal(tickCount) - 1.0);
+ for (int i = 0; i < tickCount; ++i)
+ points[i] = qreal(i) * -deltaY + gridRect.bottom();
+
+ return points;
+}
+
+void ChartDateTimeAxisY::updateGeometry()
+{
+ const QVector<qreal> &layout = ChartAxisElement::layout();
+ if (layout.isEmpty())
+ return;
+ setLabels(createDateTimeLabels(min(), max(), layout.size(), m_axis->format()));
+ VerticalAxis::updateGeometry();
+}
+
+void ChartDateTimeAxisY::handleTickCountChanged(int tick)
+{
+ Q_UNUSED(tick)
+ QGraphicsLayoutItem::updateGeometry();
+ if (presenter())
+ presenter()->layout()->invalidate();
+}
+
+void ChartDateTimeAxisY::handleFormatChanged(const QString &format)
+{
+ Q_UNUSED(format);
+ QGraphicsLayoutItem::updateGeometry();
+ if (presenter())
+ presenter()->layout()->invalidate();
+}
+
+QSizeF ChartDateTimeAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED(constraint)
+
+ QSizeF sh;
+
+ QSizeF base = VerticalAxis::sizeHint(which, constraint);
+ QStringList ticksList = createDateTimeLabels(min(), max(), m_axis->tickCount(), m_axis->format());
+ qreal width = 0;
+ // Height of vertical axis sizeHint indicates the maximum distance labels can extend past
+ // first and last ticks. Base height is irrelevant.
+ qreal height = 0;
+
+ if (ticksList.empty())
+ return sh;
+
+ switch (which) {
+ case Qt::MinimumSize: {
+ QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(),
+ QStringLiteral("..."),
+ axis()->labelsAngle());
+ width = boundingRect.width() + labelPadding() + base.width() + 1.0;
+ height = boundingRect.height() / 2.0;
+ sh = QSizeF(width, height);
+ break;
+ }
+ case Qt::PreferredSize: {
+ qreal labelWidth = 0.0;
+ qreal firstHeight = -1.0;
+ foreach (const QString& s, ticksList) {
+ QRectF rect = ChartPresenter::textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
+ labelWidth = qMax(rect.width(), labelWidth);
+ height = rect.height();
+ if (firstHeight < 0.0)
+ firstHeight = height;
+ }
+ width = labelWidth + labelPadding() + base.width() + 2.0; //two pixels of tolerance
+ height = qMax(height, firstHeight) / 2.0;
+ sh = QSizeF(width, height);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return sh;
+}
+
+#include "moc_chartdatetimeaxisy_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/datetimeaxis/chartdatetimeaxisy_p.h b/src/charts/axis/datetimeaxis/chartdatetimeaxisy_p.h
new file mode 100644
index 00000000..0631e157
--- /dev/null
+++ b/src/charts/axis/datetimeaxis/chartdatetimeaxisy_p.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTDATETIMEAXISY_H
+#define CHARTDATETIMEAXISY_H
+
+#include "verticalaxis_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QDateTimeAxis;
+
+class ChartDateTimeAxisY : public VerticalAxis
+{
+ Q_OBJECT
+public:
+ ChartDateTimeAxisY(QDateTimeAxis *axis, QGraphicsItem* item = 0);
+ ~ChartDateTimeAxisY();
+
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const;
+protected:
+ QVector<qreal> calculateLayout() const;
+ void updateGeometry();
+private Q_SLOTS:
+ void handleTickCountChanged(int tick);
+ void handleFormatChanged(const QString &format);
+
+private:
+ QDateTimeAxis *m_axis;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif /* CHARTDATETIMEAXISY_H */
diff --git a/src/charts/axis/datetimeaxis/polarchartdatetimeaxisangular.cpp b/src/charts/axis/datetimeaxis/polarchartdatetimeaxisangular.cpp
new file mode 100644
index 00000000..4ace5de6
--- /dev/null
+++ b/src/charts/axis/datetimeaxis/polarchartdatetimeaxisangular.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "polarchartdatetimeaxisangular_p.h"
+#include "chartpresenter_p.h"
+#include "abstractchartlayout_p.h"
+#include "qdatetimeaxis.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+PolarChartDateTimeAxisAngular::PolarChartDateTimeAxisAngular(QDateTimeAxis *axis, QGraphicsItem *item)
+ : PolarChartAxisAngular(axis, item)
+{
+ QObject::connect(axis, SIGNAL(tickCountChanged(int)), this, SLOT(handleTickCountChanged(int)));
+ QObject::connect(axis, SIGNAL(formatChanged(QString)), this, SLOT(handleFormatChanged(QString)));
+}
+
+PolarChartDateTimeAxisAngular::~PolarChartDateTimeAxisAngular()
+{
+}
+
+QVector<qreal> PolarChartDateTimeAxisAngular::calculateLayout() const
+{
+ int tickCount = static_cast<QDateTimeAxis *>(axis())->tickCount();
+ Q_ASSERT(tickCount >= 2);
+
+ QVector<qreal> points;
+ points.resize(tickCount);
+
+ const qreal d = 360.0 / qreal(tickCount - 1);
+
+ for (int i = 0; i < tickCount; ++i) {
+ qreal angularCoordinate = qreal(i) * d;
+ points[i] = angularCoordinate;
+ }
+
+ return points;
+}
+void PolarChartDateTimeAxisAngular::createAxisLabels(const QVector<qreal> &layout)
+{
+ QStringList labelList = createDateTimeLabels(min(), max(), layout.size(), static_cast<QDateTimeAxis *>(axis())->format());
+ setLabels(labelList);
+}
+
+void PolarChartDateTimeAxisAngular::handleTickCountChanged(int tick)
+{
+ Q_UNUSED(tick);
+ QGraphicsLayoutItem::updateGeometry();
+ if (presenter())
+ presenter()->layout()->invalidate();
+}
+
+void PolarChartDateTimeAxisAngular::handleFormatChanged(const QString &format)
+{
+ Q_UNUSED(format);
+ QGraphicsLayoutItem::updateGeometry();
+ if (presenter())
+ presenter()->layout()->invalidate();
+}
+
+#include "moc_polarchartdatetimeaxisangular_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/datetimeaxis/polarchartdatetimeaxisangular_p.h b/src/charts/axis/datetimeaxis/polarchartdatetimeaxisangular_p.h
new file mode 100644
index 00000000..bbfd8260
--- /dev/null
+++ b/src/charts/axis/datetimeaxis/polarchartdatetimeaxisangular_p.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 POLARCHARTDATETIMEAXISANGULAR_P_H
+#define POLARCHARTDATETIMEAXISANGULAR_P_H
+
+#include "polarchartaxisangular_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QDateTimeAxis;
+
+class PolarChartDateTimeAxisAngular : public PolarChartAxisAngular
+{
+ Q_OBJECT
+public:
+ PolarChartDateTimeAxisAngular(QDateTimeAxis *axis, QGraphicsItem *item);
+ ~PolarChartDateTimeAxisAngular();
+
+ virtual QVector<qreal> calculateLayout() const;
+ virtual void createAxisLabels(const QVector<qreal> &layout);
+
+private Q_SLOTS:
+ void handleTickCountChanged(int tick);
+ void handleFormatChanged(const QString &format);
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // POLARCHARTDATETIMEAXISANGULAR_P_H
diff --git a/src/charts/axis/datetimeaxis/polarchartdatetimeaxisradial.cpp b/src/charts/axis/datetimeaxis/polarchartdatetimeaxisradial.cpp
new file mode 100644
index 00000000..fdcfcc36
--- /dev/null
+++ b/src/charts/axis/datetimeaxis/polarchartdatetimeaxisradial.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "polarchartdatetimeaxisradial_p.h"
+#include "chartpresenter_p.h"
+#include "abstractchartlayout_p.h"
+#include "qdatetimeaxis.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+PolarChartDateTimeAxisRadial::PolarChartDateTimeAxisRadial(QDateTimeAxis *axis, QGraphicsItem *item)
+ : PolarChartAxisRadial(axis, item)
+{
+ QObject::connect(axis, SIGNAL(tickCountChanged(int)), this, SLOT(handleTickCountChanged(int)));
+ QObject::connect(axis, SIGNAL(formatChanged(QString)), this, SLOT(handleFormatChanged(QString)));
+}
+
+PolarChartDateTimeAxisRadial::~PolarChartDateTimeAxisRadial()
+{
+}
+
+QVector<qreal> PolarChartDateTimeAxisRadial::calculateLayout() const
+{
+ int tickCount = static_cast<QDateTimeAxis *>(axis())->tickCount();
+ Q_ASSERT(tickCount >= 2);
+
+ QVector<qreal> points;
+ points.resize(tickCount);
+
+ const qreal d = (axisGeometry().width() / 2) / qreal(tickCount - 1);
+
+ for (int i = 0; i < tickCount; ++i) {
+ qreal radialCoordinate = qreal(i) * d;
+ points[i] = radialCoordinate;
+ }
+
+ return points;
+}
+void PolarChartDateTimeAxisRadial::createAxisLabels(const QVector<qreal> &layout)
+{
+ setLabels(createDateTimeLabels(min(), max(), layout.size(), static_cast<QDateTimeAxis *>(axis())->format()));
+}
+
+void PolarChartDateTimeAxisRadial::handleTickCountChanged(int tick)
+{
+ Q_UNUSED(tick);
+ QGraphicsLayoutItem::updateGeometry();
+ if (presenter())
+ presenter()->layout()->invalidate();
+}
+
+void PolarChartDateTimeAxisRadial::handleFormatChanged(const QString &format)
+{
+ Q_UNUSED(format);
+ QGraphicsLayoutItem::updateGeometry();
+ if (presenter())
+ presenter()->layout()->invalidate();
+}
+
+#include "moc_polarchartdatetimeaxisradial_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/datetimeaxis/polarchartdatetimeaxisradial_p.h b/src/charts/axis/datetimeaxis/polarchartdatetimeaxisradial_p.h
new file mode 100644
index 00000000..207d5a3a
--- /dev/null
+++ b/src/charts/axis/datetimeaxis/polarchartdatetimeaxisradial_p.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 POLARCHARTDATETIMEAXISRADIAL_P_H
+#define POLARCHARTDATETIMEAXISRADIAL_P_H
+
+#include "polarchartaxisradial_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QDateTimeAxis;
+
+class PolarChartDateTimeAxisRadial : public PolarChartAxisRadial
+{
+ Q_OBJECT
+public:
+ PolarChartDateTimeAxisRadial(QDateTimeAxis *axis, QGraphicsItem *item);
+ ~PolarChartDateTimeAxisRadial();
+
+ virtual QVector<qreal> calculateLayout() const;
+ virtual void createAxisLabels(const QVector<qreal> &layout);
+
+private Q_SLOTS:
+ void handleTickCountChanged(int tick);
+ void handleFormatChanged(const QString &format);
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // POLARCHARTDATETIMEAXISRADIAL_P_H
diff --git a/src/charts/axis/datetimeaxis/qdatetimeaxis.cpp b/src/charts/axis/datetimeaxis/qdatetimeaxis.cpp
new file mode 100644
index 00000000..fffd80c2
--- /dev/null
+++ b/src/charts/axis/datetimeaxis/qdatetimeaxis.cpp
@@ -0,0 +1,390 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdatetimeaxis.h"
+#include "qdatetimeaxis_p.h"
+#include "chartdatetimeaxisx_p.h"
+#include "chartdatetimeaxisy_p.h"
+#include "polarchartdatetimeaxisangular_p.h"
+#include "polarchartdatetimeaxisradial_p.h"
+#include "abstractdomain_p.h"
+#include "qchart.h"
+#include <float.h>
+#include <cmath>
+
+QT_CHARTS_BEGIN_NAMESPACE
+/*!
+ \class QDateTimeAxis
+ \inmodule Qt Charts
+ \brief The QDateTimeAxis class is used for manipulating chart's axis.
+ \mainclass
+
+ The labels can be configured by setting an appropriate DateTime format.
+ QDateTimeAxis works correctly with dates from 4714 BCE to 287396 CE.
+ There are also other limitiation related to QDateTime. Please refer to QDateTime documentation.
+ QDateTimeAxis can be setup to show axis line with tick marks, grid lines and shades.
+
+ Note: QDateTimeAxis is disabled on ARM architecture.
+
+ \image api_datatime_axis.png
+
+ QDateTimeAxis can be used with any QXYSeries.
+ To add a data point to the series QDateTime::toMSecsSinceEpoch() is used.
+ \code
+ QLineSeries *series = new QLineSeries;
+
+ QDateTime xValue;
+ xValue.setDate(QDate(2012, 1 , 18));
+ xValue.setTime(QTime(9, 34));
+ qreal yValue = 12;
+ series->append(xValue.toMSecsSinceEpoch(), yValue);
+
+ xValue.setDate(QDate(2013, 5 , 11));
+ xValue.setTime(QTime(11, 14));
+ qreal yValue = 22;
+ series->append(xValue.toMSecsSinceEpoch(), yValue);
+ \endcode
+
+ Adding the series to the chart and setting up the QDateTimeAxis.
+ \code
+ QChartView *chartView = new QChartView;
+ chartView->chart()->addSeries(series);
+
+ // ...
+ QDateTimeAxis *axisX = new QDateTimeAxis;
+ axisX->setFormat("dd-MM-yyyy h:mm");
+ chartView->chart()->setAxisX(axisX, series);
+ \endcode
+*/
+
+/*!
+ \qmltype DateTimeAxis
+ \instantiates QDateTimeAxis
+ \inqmlmodule QtCharts
+
+ \brief The DateTimeAxis element is used for manipulating chart's axes.
+ \inherits AbstractAxis
+
+ The labels can be configured by setting an appropriate DateTime format.
+ Note that any date before 4714 BCE or after about 1.4 million CE may not be accurately stored.
+ DateTimeAxis can be setup to show axis line with tick marks, grid lines and shades.
+*/
+
+/*!
+ \property QDateTimeAxis::min
+ Defines the minimum value on the axis.
+ When setting this property the max is adjusted if necessary, to ensure that the range remains valid.
+*/
+/*!
+ \qmlproperty datetime DateTimeAxis::min
+ Defines the minimum value on the axis.
+ When setting this property the max is adjusted if necessary, to ensure that the range remains valid.
+*/
+
+/*!
+ \property QDateTimeAxis::max
+ Defines the maximum value on the axis.
+ When setting this property the min is adjusted if necessary, to ensure that the range remains valid.
+*/
+/*!
+ \qmlproperty datetime DateTimeAxis::max
+ Defines the maximum value on the axis.
+ When setting this property the min is adjusted if necessary, to ensure that the range remains valid.
+*/
+
+/*!
+ \fn void QDateTimeAxis::minChanged(QDateTime min)
+ Axis emits signal when \a min of axis has changed.
+*/
+/*!
+ \qmlsignal DateTimeAxis::onMinChanged(datetime min)
+ Axis emits signal when \a min of axis has changed.
+*/
+
+/*!
+ \fn void QDateTimeAxis::maxChanged(QDateTime max)
+ Axis emits signal when \a max of axis has changed.
+*/
+/*!
+ \qmlsignal DateTimeAxis::onMaxChanged(datetime max)
+ Axis emits signal when \a max of axis has changed.
+*/
+
+/*!
+ \fn void QDateTimeAxis::rangeChanged(QDateTime min, QDateTime max)
+ Axis emits signal when \a min or \a max of axis has changed.
+*/
+
+/*!
+ \property QDateTimeAxis::tickCount
+ The number of tick marks for the axis.
+*/
+
+/*!
+ \qmlproperty int DateTimeAxis::tickCount
+ The number of tick marks for the axis.
+*/
+
+/*!
+ \property QDateTimeAxis::format
+ The format string that is used when creating label for the axis out of a QDateTime object.
+ Check QDateTime documentation for information on how the string should be defined.
+
+ \sa QChart::locale
+*/
+/*!
+ \qmlproperty string DateTimeAxis::format
+ The format string that is used when creating label for the axis out of a QDateTime object.
+ Check QDateTime documentation for information on how the string should be defined.
+*/
+
+/*!
+ \fn void QDateTimeAxis::tickCountChanged(int tickCount)
+ Axis emits signal when \a tickCount number on axis have changed.
+*/
+/*!
+ \qmlsignal DateTimeAxis::tickCountChanged(int tickCount)
+ Axis emits signal when \a tickCount number on axis have changed.
+*/
+
+/*!
+ \fn void QDateTimeAxis::formatChanged(QString format)
+ Axis emits signal when \a format of the axis has changed.
+*/
+/*!
+ \qmlsignal DateTimeAxis::onFormatChanged(string format)
+ Axis emits signal when \a format of the axis has changed.
+*/
+
+/*!
+ Constructs an axis object which is a child of \a parent.
+*/
+QDateTimeAxis::QDateTimeAxis(QObject *parent) :
+ QAbstractAxis(*new QDateTimeAxisPrivate(this), parent)
+{
+
+}
+
+/*!
+ \internal
+*/
+QDateTimeAxis::QDateTimeAxis(QDateTimeAxisPrivate &d, QObject *parent) : QAbstractAxis(d, parent)
+{
+
+}
+
+/*!
+ Destroys the object.
+*/
+QDateTimeAxis::~QDateTimeAxis()
+{
+ Q_D(QDateTimeAxis);
+ if (d->m_chart)
+ d->m_chart->removeAxis(this);
+}
+
+void QDateTimeAxis::setMin(QDateTime min)
+{
+ Q_D(QDateTimeAxis);
+ if (min.isValid())
+ d->setRange(min.toMSecsSinceEpoch(), qMax(d->m_max, qreal(min.toMSecsSinceEpoch())));
+}
+
+QDateTime QDateTimeAxis::min() const
+{
+ Q_D(const QDateTimeAxis);
+ return QDateTime::fromMSecsSinceEpoch(d->m_min);
+}
+
+void QDateTimeAxis::setMax(QDateTime max)
+{
+ Q_D(QDateTimeAxis);
+ if (max.isValid())
+ d->setRange(qMin(d->m_min, qreal(max.toMSecsSinceEpoch())), max.toMSecsSinceEpoch());
+}
+
+QDateTime QDateTimeAxis::max() const
+{
+ Q_D(const QDateTimeAxis);
+ return QDateTime::fromMSecsSinceEpoch(d->m_max);
+}
+
+/*!
+ Sets range from \a min to \a max on the axis.
+ If min is greater than max then this function returns without making any changes.
+*/
+void QDateTimeAxis::setRange(QDateTime min, QDateTime max)
+{
+ Q_D(QDateTimeAxis);
+ if (!min.isValid() || !max.isValid() || min > max)
+ return;
+
+ d->setRange(min.toMSecsSinceEpoch(),max.toMSecsSinceEpoch());
+}
+
+void QDateTimeAxis::setFormat(QString format)
+{
+ Q_D(QDateTimeAxis);
+ if (d->m_format != format) {
+ d->m_format = format;
+ emit formatChanged(format);
+ }
+}
+
+QString QDateTimeAxis::format() const
+{
+ Q_D(const QDateTimeAxis);
+ return d->m_format;
+}
+
+/*!
+ Sets \a count for ticks on the axis.
+*/
+void QDateTimeAxis::setTickCount(int count)
+{
+ Q_D(QDateTimeAxis);
+ if (d->m_tickCount != count && count >= 2) {
+ d->m_tickCount = count;
+ emit tickCountChanged(count);
+ }
+}
+
+/*!
+ \fn int QDateTimeAxis::tickCount() const
+ Return number of ticks on the axis.
+*/
+int QDateTimeAxis::tickCount() const
+{
+ Q_D(const QDateTimeAxis);
+ return d->m_tickCount;
+}
+
+/*!
+ Returns the type of the axis.
+*/
+QAbstractAxis::AxisType QDateTimeAxis::type() const
+{
+ return AxisTypeDateTime;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QDateTimeAxisPrivate::QDateTimeAxisPrivate(QDateTimeAxis *q)
+ : QAbstractAxisPrivate(q),
+ m_min(0),
+ m_max(0),
+ m_tickCount(5)
+{
+ m_format = QStringLiteral("dd-MM-yyyy\nh:mm");
+}
+
+QDateTimeAxisPrivate::~QDateTimeAxisPrivate()
+{
+
+}
+
+void QDateTimeAxisPrivate::setRange(qreal min,qreal max)
+{
+ Q_Q(QDateTimeAxis);
+
+ bool changed = false;
+
+ if (m_min != min) {
+ m_min = min;
+ changed = true;
+ emit q->minChanged(QDateTime::fromMSecsSinceEpoch(min));
+ }
+
+ if (m_max != max) {
+ m_max = max;
+ changed = true;
+ emit q->maxChanged(QDateTime::fromMSecsSinceEpoch(max));
+ }
+
+ if (changed) {
+ emit q->rangeChanged(QDateTime::fromMSecsSinceEpoch(min), QDateTime::fromMSecsSinceEpoch(max));
+ emit rangeChanged(m_min,m_max);
+ }
+}
+
+
+void QDateTimeAxisPrivate::setMin(const QVariant &min)
+{
+ Q_Q(QDateTimeAxis);
+ if (min.canConvert(QVariant::DateTime))
+ q->setMin(min.toDateTime());
+}
+
+void QDateTimeAxisPrivate::setMax(const QVariant &max)
+{
+
+ Q_Q(QDateTimeAxis);
+ if (max.canConvert(QVariant::DateTime))
+ q->setMax(max.toDateTime());
+}
+
+void QDateTimeAxisPrivate::setRange(const QVariant &min, const QVariant &max)
+{
+ Q_Q(QDateTimeAxis);
+ if (min.canConvert(QVariant::DateTime) && max.canConvert(QVariant::DateTime))
+ q->setRange(min.toDateTime(), max.toDateTime());
+}
+
+void QDateTimeAxisPrivate::initializeGraphics(QGraphicsItem* parent)
+{
+ Q_Q(QDateTimeAxis);
+ ChartAxisElement *axis(0);
+ if (m_chart->chartType() == QChart::ChartTypeCartesian) {
+ if (orientation() == Qt::Vertical)
+ axis = new ChartDateTimeAxisY(q,parent);
+ if (orientation() == Qt::Horizontal)
+ axis = new ChartDateTimeAxisX(q,parent);
+ }
+
+ if (m_chart->chartType() == QChart::ChartTypePolar) {
+ if (orientation() == Qt::Vertical)
+ axis = new PolarChartDateTimeAxisRadial(q, parent);
+ if (orientation() == Qt::Horizontal)
+ axis = new PolarChartDateTimeAxisAngular(q, parent);
+ }
+
+ m_item.reset(axis);
+ QAbstractAxisPrivate::initializeGraphics(parent);
+}
+
+void QDateTimeAxisPrivate::initializeDomain(AbstractDomain *domain)
+{
+ if (m_max == m_min) {
+ if (orientation() == Qt::Vertical)
+ setRange(domain->minY(), domain->maxY());
+ else
+ setRange(domain->minX(), domain->maxX());
+ } else {
+ if (orientation() == Qt::Vertical)
+ domain->setRangeY(m_min, m_max);
+ else
+ domain->setRangeX(m_min, m_max);
+ }
+}
+
+#include "moc_qdatetimeaxis.cpp"
+#include "moc_qdatetimeaxis_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/datetimeaxis/qdatetimeaxis.h b/src/charts/axis/datetimeaxis/qdatetimeaxis.h
new file mode 100644
index 00000000..72d46b5e
--- /dev/null
+++ b/src/charts/axis/datetimeaxis/qdatetimeaxis.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDATETIMEAXIS_H
+#define QDATETIMEAXIS_H
+
+#include <QtCharts/qabstractaxis.h>
+
+class QDateTime;
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QDateTimeAxisPrivate;
+
+class QT_CHARTS_EXPORT QDateTimeAxis : public QAbstractAxis
+{
+ Q_OBJECT
+ Q_PROPERTY(int tickCount READ tickCount WRITE setTickCount NOTIFY tickCountChanged)
+ Q_PROPERTY(QDateTime min READ min WRITE setMin NOTIFY minChanged)
+ Q_PROPERTY(QDateTime max READ max WRITE setMax NOTIFY maxChanged)
+ Q_PROPERTY(QString format READ format WRITE setFormat NOTIFY formatChanged)
+
+public:
+ explicit QDateTimeAxis(QObject *parent = 0);
+ ~QDateTimeAxis();
+
+protected:
+ QDateTimeAxis(QDateTimeAxisPrivate &d, QObject *parent = 0);
+
+public:
+ AxisType type() const;
+
+ //range handling
+ void setMin(QDateTime min);
+ QDateTime min() const;
+ void setMax(QDateTime max);
+ QDateTime max() const;
+ void setRange(QDateTime min, QDateTime max);
+
+ void setFormat(QString format);
+ QString format() const;
+
+ //ticks handling
+ void setTickCount(int count);
+ int tickCount() const;
+
+Q_SIGNALS:
+ void minChanged(QDateTime min);
+ void maxChanged(QDateTime max);
+ void rangeChanged(QDateTime min, QDateTime max);
+ void formatChanged(QString format);
+ void tickCountChanged(int tick);
+
+private:
+ Q_DECLARE_PRIVATE(QDateTimeAxis)
+ Q_DISABLE_COPY(QDateTimeAxis)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QDATETIMEAXIS_H
diff --git a/src/charts/axis/datetimeaxis/qdatetimeaxis_p.h b/src/charts/axis/datetimeaxis/qdatetimeaxis_p.h
new file mode 100644
index 00000000..30551d55
--- /dev/null
+++ b/src/charts/axis/datetimeaxis/qdatetimeaxis_p.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QDATETIMEAXIS_P_H
+#define QDATETIMEAXIS_P_H
+
+#include "qdatetimeaxis.h"
+#include "qabstractaxis_p.h"
+#include <QDateTime>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QDateTimeAxisPrivate : public QAbstractAxisPrivate
+{
+ Q_OBJECT
+public:
+ QDateTimeAxisPrivate(QDateTimeAxis *q);
+ ~QDateTimeAxisPrivate();
+
+public:
+ void initializeGraphics(QGraphicsItem* parent);
+ void initializeDomain(AbstractDomain *domain);
+
+ //interface for manipulating range form base class
+ void setMin(const QVariant &min);
+ void setMax(const QVariant &max);
+ void setRange(const QVariant &min, const QVariant &max);
+
+ //interface manipulating range form domain
+ qreal min() { return m_min; }
+ qreal max() { return m_max; }
+ void setRange(qreal min,qreal max);
+
+protected:
+ int tickCount() const;
+
+protected:
+ qreal m_min;
+ qreal m_max;
+ int m_tickCount;
+ QString m_format;
+ Q_DECLARE_PUBLIC(QDateTimeAxis)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QDATETIMEAXIS_P_H
diff --git a/src/charts/axis/horizontalaxis.cpp b/src/charts/axis/horizontalaxis.cpp
new file mode 100644
index 00000000..941afc05
--- /dev/null
+++ b/src/charts/axis/horizontalaxis.cpp
@@ -0,0 +1,227 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "horizontalaxis_p.h"
+#include "qabstractaxis_p.h"
+#include "chartpresenter_p.h"
+#include <qmath.h>
+#include <QDebug>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+HorizontalAxis::HorizontalAxis(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
+ : CartesianChartAxis(axis, item, intervalAxis)
+{
+}
+
+HorizontalAxis::~HorizontalAxis()
+{
+}
+
+void HorizontalAxis::updateGeometry()
+{
+ const QVector<qreal> &layout = ChartAxisElement::layout();
+
+ if (layout.isEmpty())
+ return;
+
+ QStringList labelList = labels();
+
+ QList<QGraphicsItem *> lines = gridItems();
+ QList<QGraphicsItem *> labels = labelItems();
+ QList<QGraphicsItem *> shades = shadeItems();
+ QList<QGraphicsItem *> arrow = arrowItems();
+ QGraphicsTextItem *title = titleItem();
+
+ Q_ASSERT(labels.size() == labelList.size());
+ Q_ASSERT(layout.size() == labelList.size());
+
+ const QRectF &axisRect = axisGeometry();
+ const QRectF &gridRect = gridGeometry();
+
+ //arrow
+ QGraphicsLineItem *arrowItem = static_cast<QGraphicsLineItem *>(arrow.at(0));
+
+ if (axis()->alignment() == Qt::AlignTop)
+ arrowItem->setLine(gridRect.left(), axisRect.bottom(), gridRect.right(), axisRect.bottom());
+ else if (axis()->alignment() == Qt::AlignBottom)
+ arrowItem->setLine(gridRect.left(), axisRect.top(), gridRect.right(), axisRect.top());
+
+ qreal width = 0;
+ const QLatin1String ellipsis("...");
+
+ //title
+ QRectF titleBoundingRect;
+ QString titleText = axis()->titleText();
+ qreal availableSpace = axisRect.height() - labelPadding();
+ if (!titleText.isEmpty() && titleItem()->isVisible()) {
+ availableSpace -= titlePadding() * 2.0;
+ qreal minimumLabelHeight = ChartPresenter::textBoundingRect(axis()->labelsFont(),
+ QStringLiteral("...")).height();
+ qreal titleSpace = availableSpace - minimumLabelHeight;
+ title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(0.0),
+ gridRect.width(), titleSpace,
+ titleBoundingRect));
+ title->setTextWidth(titleBoundingRect.width());
+
+ titleBoundingRect = title->boundingRect();
+
+ QPointF center = gridRect.center() - titleBoundingRect.center();
+ if (axis()->alignment() == Qt::AlignTop)
+ title->setPos(center.x(), axisRect.top() + titlePadding());
+ else if (axis()->alignment() == Qt::AlignBottom)
+ title->setPos(center.x(), axisRect.bottom() - titleBoundingRect.height() - titlePadding());
+
+ availableSpace -= titleBoundingRect.height();
+ }
+
+ for (int i = 0; i < layout.size(); ++i) {
+ //items
+ QGraphicsLineItem *gridItem = static_cast<QGraphicsLineItem*>(lines.at(i));
+ QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem*>(arrow.at(i + 1));
+ QGraphicsTextItem *labelItem = static_cast<QGraphicsTextItem *>(labels.at(i));
+
+ //grid line
+ gridItem->setLine(layout[i], gridRect.top(), layout[i], gridRect.bottom());
+
+ //label text wrapping
+ QString text = labelList.at(i);
+ QRectF boundingRect;
+ // don't truncate empty labels
+ if (text.isEmpty()) {
+ labelItem->setHtml(text);
+ } else {
+ qreal labelWidth = axisRect.width() / layout.count() - (2 * labelPadding());
+ QString truncatedText = ChartPresenter::truncatedText(axis()->labelsFont(), text,
+ axis()->labelsAngle(),
+ labelWidth,
+ availableSpace, boundingRect);
+ labelItem->setTextWidth(ChartPresenter::textBoundingRect(axis()->labelsFont(),
+ truncatedText).width());
+ labelItem->setHtml(truncatedText);
+ }
+
+ //label transformation origin point
+ const QRectF& rect = labelItem->boundingRect();
+ QPointF center = rect.center();
+ labelItem->setTransformOriginPoint(center.x(), center.y());
+ qreal heightDiff = rect.height() - boundingRect.height();
+ qreal widthDiff = rect.width() - boundingRect.width();
+
+ //ticks and label position
+ if (axis()->alignment() == Qt::AlignTop) {
+ labelItem->setPos(layout[i] - center.x(), axisRect.bottom() - rect.height() + (heightDiff / 2.0) - labelPadding());
+ tickItem->setLine(layout[i], axisRect.bottom(), layout[i], axisRect.bottom() - labelPadding());
+ } else if (axis()->alignment() == Qt::AlignBottom) {
+ labelItem->setPos(layout[i] - center.x(), axisRect.top() - (heightDiff / 2.0) + labelPadding());
+ tickItem->setLine(layout[i], axisRect.top(), layout[i], axisRect.top() + labelPadding());
+ }
+
+ //label in between
+ bool forceHide = false;
+ if (intervalAxis() && (i + 1) != layout.size()) {
+ qreal leftBound = qMax(layout[i], gridRect.left());
+ qreal rightBound = qMin(layout[i + 1], gridRect.right());
+ const qreal delta = rightBound - leftBound;
+ // Hide label in case visible part of the category at the grid edge is too narrow
+ if (delta < boundingRect.width()
+ && (leftBound == gridRect.left() || rightBound == gridRect.right())
+ && !intervalAxis()) {
+ forceHide = true;
+ } else {
+ labelItem->setPos(leftBound + (delta / 2.0) - center.x(), labelItem->pos().y());
+ }
+ }
+
+ //label overlap detection - compensate one pixel for rounding errors
+ if ((labelItem->pos().x() < width && labelItem->toPlainText() == ellipsis) || forceHide ||
+ (labelItem->pos().x() + (widthDiff / 2.0)) < (axisRect.left() - 1.0) ||
+ (labelItem->pos().x() + (widthDiff / 2.0) - 1.0) > axisRect.right()) {
+ labelItem->setVisible(false);
+ } else {
+ labelItem->setVisible(true);
+ width = boundingRect.width() + labelItem->pos().x();
+ }
+
+ //shades
+ if ((i + 1) % 2 && i > 1) {
+ QGraphicsRectItem *rectItem = static_cast<QGraphicsRectItem *>(shades.at(i / 2 - 1));
+ qreal leftBound = qMax(layout[i - 1], gridRect.left());
+ qreal rightBound = qMin(layout[i], gridRect.right());
+ rectItem->setRect(leftBound, gridRect.top(), rightBound - leftBound, gridRect.height());
+ if (rectItem->rect().width() <= 0.0)
+ rectItem->setVisible(false);
+ else
+ rectItem->setVisible(true);
+ }
+
+ // check if the grid line and the axis tick should be shown
+ qreal x = gridItem->line().p1().x();
+ if (x < gridRect.left() || x > gridRect.right()) {
+ gridItem->setVisible(false);
+ tickItem->setVisible(false);
+ } else {
+ gridItem->setVisible(true);
+ tickItem->setVisible(true);
+ }
+
+ }
+
+ //begin/end grid line in case labels between
+ if (intervalAxis()) {
+ QGraphicsLineItem *gridLine;
+ gridLine = static_cast<QGraphicsLineItem *>(lines.at(layout.size()));
+ gridLine->setLine(gridRect.right(), gridRect.top(), gridRect.right(), gridRect.bottom());
+ gridLine->setVisible(true);
+ gridLine = static_cast<QGraphicsLineItem*>(lines.at(layout.size()+1));
+ gridLine->setLine(gridRect.left(), gridRect.top(), gridRect.left(), gridRect.bottom());
+ gridLine->setVisible(true);
+ }
+}
+
+QSizeF HorizontalAxis::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED(constraint);
+ QSizeF sh(0,0);
+
+ if (axis()->titleText().isEmpty() || !titleItem()->isVisible())
+ return sh;
+
+ switch (which) {
+ case Qt::MinimumSize: {
+ QRectF titleRect = ChartPresenter::textBoundingRect(axis()->titleFont(),
+ QStringLiteral("..."));
+ sh = QSizeF(titleRect.width(), titleRect.height() + (titlePadding() * 2.0));
+ break;
+ }
+ case Qt::MaximumSize:
+ case Qt::PreferredSize: {
+ QRectF titleRect = ChartPresenter::textBoundingRect(axis()->titleFont(), axis()->titleText());
+ sh = QSizeF(titleRect.width(), titleRect.height() + (titlePadding() * 2.0));
+ break;
+ }
+ default:
+ break;
+ }
+
+ return sh;
+}
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/horizontalaxis_p.h b/src/charts/axis/horizontalaxis_p.h
new file mode 100644
index 00000000..9f1ad596
--- /dev/null
+++ b/src/charts/axis/horizontalaxis_p.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 HORIZONTALAXIS_P_H_
+#define HORIZONTALAXIS_P_H_
+
+#include "cartesianchartaxis_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class HorizontalAxis : public CartesianChartAxis
+{
+public:
+ HorizontalAxis(QAbstractAxis *axis, QGraphicsItem *item = 0, bool intervalAxis = false);
+ ~HorizontalAxis();
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
+protected:
+ void updateGeometry();
+
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/axis/linearrowitem_p.h b/src/charts/axis/linearrowitem_p.h
new file mode 100644
index 00000000..f1f94acd
--- /dev/null
+++ b/src/charts/axis/linearrowitem_p.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 LINEARROWITEM_P_H
+#define LINEARROWITEM_P_H
+
+#include "chartaxiselement_p.h"
+#include "qabstractaxis_p.h"
+#include <QGraphicsLineItem>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class LineArrowItem: public QGraphicsLineItem
+{
+public:
+ explicit LineArrowItem(ChartAxisElement *axis, QGraphicsItem *parent = 0)
+ : QGraphicsLineItem(parent),
+ m_axis(axis),
+ m_axisOrientation(axis->axis()->orientation())
+ {
+ }
+
+protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent *event)
+ {
+ Q_UNUSED(event)
+ m_axis->axisSelected();
+ }
+
+ QRectF boundingRect() const
+ {
+ return shape().boundingRect();
+ }
+
+ QPainterPath shape() const
+ {
+ QPainterPath path = QGraphicsLineItem::shape();
+ QRectF rect = path.boundingRect();
+ path.addRect(rect.adjusted(0, 0, m_axisOrientation != Qt::Horizontal ? 8 : 0, m_axisOrientation != Qt::Vertical ? 8 : 0));
+ return path;
+ }
+
+private:
+ ChartAxisElement *m_axis;
+ Qt::Orientation m_axisOrientation;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif /* LINEARROWITEM_P_H */
diff --git a/src/charts/axis/logvalueaxis/chartlogvalueaxisx.cpp b/src/charts/axis/logvalueaxis/chartlogvalueaxisx.cpp
new file mode 100644
index 00000000..6057fbb1
--- /dev/null
+++ b/src/charts/axis/logvalueaxis/chartlogvalueaxisx.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "chartlogvalueaxisx_p.h"
+#include "chartpresenter_p.h"
+#include "qlogvalueaxis.h"
+#include "abstractchartlayout_p.h"
+#include <QGraphicsLayout>
+#include <qmath.h>
+#include <QDebug>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+ChartLogValueAxisX::ChartLogValueAxisX(QLogValueAxis *axis, QGraphicsItem *item)
+ : HorizontalAxis(axis, item),
+ m_axis(axis)
+{
+ QObject::connect(m_axis, SIGNAL(baseChanged(qreal)), this, SLOT(handleBaseChanged(qreal)));
+ QObject::connect(m_axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
+}
+
+ChartLogValueAxisX::~ChartLogValueAxisX()
+{
+}
+
+QVector<qreal> ChartLogValueAxisX::calculateLayout() const
+{
+ QVector<qreal> points;
+
+ qreal logMax = log10(m_axis->max()) / log10(m_axis->base());
+ qreal logMin = log10(m_axis->min()) / log10(m_axis->base());
+ qreal leftEdge = logMin < logMax ? logMin : logMax;
+ qreal ceilEdge = ceil(leftEdge);
+ int tickCount = qAbs(ceil(logMax) - ceil(logMin));
+
+ points.resize(tickCount);
+ const QRectF &gridRect = gridGeometry();
+ const qreal deltaX = gridRect.width() / qAbs(logMax - logMin);
+ for (int i = 0; i < tickCount; ++i)
+ points[i] = (ceilEdge + qreal(i)) * deltaX - leftEdge * deltaX + gridRect.left();
+
+ return points;
+}
+
+void ChartLogValueAxisX::updateGeometry()
+{
+ const QVector<qreal>& layout = ChartAxisElement::layout();
+ if (layout.isEmpty())
+ return;
+ setLabels(createLogValueLabels(m_axis->min(), m_axis->max(), m_axis->base(), layout.size(), m_axis->labelFormat()));
+ HorizontalAxis::updateGeometry();
+}
+
+void ChartLogValueAxisX::handleBaseChanged(qreal base)
+{
+ Q_UNUSED(base);
+ QGraphicsLayoutItem::updateGeometry();
+ if(presenter()) presenter()->layout()->invalidate();
+}
+
+void ChartLogValueAxisX::handleLabelFormatChanged(const QString &format)
+{
+ Q_UNUSED(format);
+ QGraphicsLayoutItem::updateGeometry();
+ if(presenter()) presenter()->layout()->invalidate();
+}
+
+QSizeF ChartLogValueAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED(constraint)
+
+ QSizeF sh;
+
+ QSizeF base = HorizontalAxis::sizeHint(which, constraint);
+ QStringList ticksList;
+ qreal logMax = log10(m_axis->max()) / log10(m_axis->base());
+ qreal logMin = log10(m_axis->min()) / log10(m_axis->base());
+ int tickCount = qAbs(ceil(logMax) - ceil(logMin));
+ if (m_axis->max() > m_axis->min() && tickCount > 0)
+ ticksList = createLogValueLabels(m_axis->min(), m_axis->max(), m_axis->base(), tickCount, m_axis->labelFormat());
+ else
+ ticksList.append(QStringLiteral(" "));
+ // Width of horizontal axis sizeHint indicates the maximum distance labels can extend past
+ // first and last ticks. Base width is irrelevant.
+ qreal width = 0;
+ qreal height = 0;
+
+ switch (which) {
+ case Qt::MinimumSize:{
+ QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(),
+ QStringLiteral("..."),
+ axis()->labelsAngle());
+ width = boundingRect.width() / 2.0;
+ height = boundingRect.height() + labelPadding() + base.height() + 1.0;
+ sh = QSizeF(width, height);
+ break;
+ }
+ case Qt::PreferredSize: {
+ qreal labelHeight = 0.0;
+ qreal firstWidth = -1.0;
+ foreach (const QString& s, ticksList) {
+ QRectF rect = ChartPresenter::textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
+ labelHeight = qMax(rect.height(), labelHeight);
+ width = rect.width();
+ if (firstWidth < 0.0)
+ firstWidth = width;
+ }
+ height = labelHeight + labelPadding() + base.height() + 1.0;
+ width = qMax(width, firstWidth) / 2.0;
+ sh = QSizeF(width, height);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return sh;
+}
+
+#include "moc_chartlogvalueaxisx_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/logvalueaxis/chartlogvalueaxisx_p.h b/src/charts/axis/logvalueaxis/chartlogvalueaxisx_p.h
new file mode 100644
index 00000000..490832b5
--- /dev/null
+++ b/src/charts/axis/logvalueaxis/chartlogvalueaxisx_p.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTLOGVALUEAXISX_H
+#define CHARTLOGVALUEAXISX_H
+
+#include "horizontalaxis_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QLogValueAxis;
+
+class ChartLogValueAxisX : public HorizontalAxis
+{
+ Q_OBJECT
+
+public:
+ ChartLogValueAxisX(QLogValueAxis *axis, QGraphicsItem *item);
+ ~ChartLogValueAxisX();
+
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const;
+
+protected:
+ QVector<qreal> calculateLayout() const;
+ void updateGeometry();
+
+private Q_SLOTS:
+ void handleBaseChanged(qreal base);
+ void handleLabelFormatChanged(const QString &format);
+
+private:
+ QLogValueAxis *m_axis;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif /* CHARTLOGVALUEAXISX_H */
diff --git a/src/charts/axis/logvalueaxis/chartlogvalueaxisy.cpp b/src/charts/axis/logvalueaxis/chartlogvalueaxisy.cpp
new file mode 100644
index 00000000..d0492f97
--- /dev/null
+++ b/src/charts/axis/logvalueaxis/chartlogvalueaxisy.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "chartlogvalueaxisy_p.h"
+#include "chartpresenter_p.h"
+#include "qlogvalueaxis.h"
+#include "abstractchartlayout_p.h"
+#include <QGraphicsLayout>
+#include <qmath.h>
+#include <QDebug>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+ChartLogValueAxisY::ChartLogValueAxisY(QLogValueAxis *axis, QGraphicsItem *item)
+ : VerticalAxis(axis, item),
+ m_axis(axis)
+{
+ QObject::connect(m_axis, SIGNAL(baseChanged(qreal)), this, SLOT(handleBaseChanged(qreal)));
+ QObject::connect(m_axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
+}
+
+ChartLogValueAxisY::~ChartLogValueAxisY()
+{
+}
+
+QVector<qreal> ChartLogValueAxisY::calculateLayout() const
+{
+ QVector<qreal> points;
+ qreal logMax = log10(m_axis->max()) / log10(m_axis->base());
+ qreal logMin = log10(m_axis->min()) / log10(m_axis->base());
+ qreal leftEdge = logMin < logMax ? logMin : logMax;
+ qreal ceilEdge = ceil(leftEdge);
+ int tickCount = qAbs(ceil(logMax) - ceil(logMin));
+
+ points.resize(tickCount);
+ const QRectF &gridRect = gridGeometry();
+ const qreal deltaY = gridRect.height() / qAbs(logMax - logMin);
+ for (int i = 0; i < tickCount; ++i)
+ points[i] = (ceilEdge + qreal(i)) * -deltaY - leftEdge * -deltaY + gridRect.bottom();
+
+ return points;
+}
+
+
+void ChartLogValueAxisY::updateGeometry()
+{
+ const QVector<qreal> &layout = ChartAxisElement::layout();
+ if (layout.isEmpty())
+ return;
+ setLabels(createLogValueLabels(m_axis->min(), m_axis->max(), m_axis->base(), layout.size(), m_axis->labelFormat()));
+ VerticalAxis::updateGeometry();
+}
+
+void ChartLogValueAxisY::handleBaseChanged(qreal base)
+{
+ Q_UNUSED(base);
+ QGraphicsLayoutItem::updateGeometry();
+ if(presenter()) presenter()->layout()->invalidate();
+}
+
+void ChartLogValueAxisY::handleLabelFormatChanged(const QString &format)
+{
+ Q_UNUSED(format);
+ QGraphicsLayoutItem::updateGeometry();
+ if(presenter()) presenter()->layout()->invalidate();
+}
+
+QSizeF ChartLogValueAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED(constraint)
+
+ QSizeF sh;
+
+ QSizeF base = VerticalAxis::sizeHint(which, constraint);
+ QStringList ticksList;
+ qreal logMax = log10(m_axis->max()) / log10(m_axis->base());
+ qreal logMin = log10(m_axis->min()) / log10(m_axis->base());
+ int tickCount = qAbs(ceil(logMax) - ceil(logMin));
+ if (m_axis->max() > m_axis->min() && tickCount > 0)
+ ticksList = createLogValueLabels(m_axis->min(), m_axis->max(), m_axis->base(), tickCount, m_axis->labelFormat());
+ else
+ ticksList.append(QStringLiteral(" "));
+ qreal width = 0;
+ // Height of vertical axis sizeHint indicates the maximum distance labels can extend past
+ // first and last ticks. Base height is irrelevant.
+ qreal height = 0;
+
+ switch (which) {
+ case Qt::MinimumSize: {
+ QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(),
+ QStringLiteral("..."),
+ axis()->labelsAngle());
+ width = boundingRect.width() + labelPadding() + base.width() + 1.0;
+ height = boundingRect.height() / 2.0;
+ sh = QSizeF(width, height);
+ break;
+ }
+ case Qt::PreferredSize: {
+ qreal labelWidth = 0.0;
+ qreal firstHeight = -1.0;
+ foreach (const QString& s, ticksList) {
+ QRectF rect = ChartPresenter::textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
+ labelWidth = qMax(rect.width(), labelWidth);
+ height = rect.height();
+ if (firstHeight < 0.0)
+ firstHeight = height;
+ }
+ width = labelWidth + labelPadding() + base.width() + 2.0; //two pixels of tolerance
+ height = qMax(height, firstHeight) / 2.0;
+ sh = QSizeF(width, height);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return sh;
+}
+
+#include "moc_chartlogvalueaxisy_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/logvalueaxis/chartlogvalueaxisy_p.h b/src/charts/axis/logvalueaxis/chartlogvalueaxisy_p.h
new file mode 100644
index 00000000..d65275c3
--- /dev/null
+++ b/src/charts/axis/logvalueaxis/chartlogvalueaxisy_p.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTLOGVALUEAXISY_H
+#define CHARTLOGVALUEAXISY_H
+
+#include "verticalaxis_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QLogValueAxis;
+
+class ChartLogValueAxisY : public VerticalAxis
+{
+ Q_OBJECT
+
+public:
+ ChartLogValueAxisY(QLogValueAxis *axis, QGraphicsItem *item);
+ ~ChartLogValueAxisY();
+
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const;
+
+protected:
+ QVector<qreal> calculateLayout() const;
+ void updateGeometry();
+
+private Q_SLOTS:
+ void handleBaseChanged(qreal base);
+ void handleLabelFormatChanged(const QString &format);
+
+private:
+ QLogValueAxis *m_axis;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif /* CHARTLOGVALUEAXISY_H */
diff --git a/src/charts/axis/logvalueaxis/polarchartlogvalueaxisangular.cpp b/src/charts/axis/logvalueaxis/polarchartlogvalueaxisangular.cpp
new file mode 100644
index 00000000..f9fe664d
--- /dev/null
+++ b/src/charts/axis/logvalueaxis/polarchartlogvalueaxisangular.cpp
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "polarchartlogvalueaxisangular_p.h"
+#include "abstractchartlayout_p.h"
+#include "chartpresenter_p.h"
+#include "qlogvalueaxis.h"
+#include <qmath.h>
+#include <QDebug>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+PolarChartLogValueAxisAngular::PolarChartLogValueAxisAngular(QLogValueAxis *axis, QGraphicsItem *item)
+ : PolarChartAxisAngular(axis, item)
+{
+ QObject::connect(axis, SIGNAL(baseChanged(qreal)), this, SLOT(handleBaseChanged(qreal)));
+ QObject::connect(axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
+}
+
+PolarChartLogValueAxisAngular::~PolarChartLogValueAxisAngular()
+{
+}
+
+QVector<qreal> PolarChartLogValueAxisAngular::calculateLayout() const
+{
+ QLogValueAxis *logValueAxis = static_cast<QLogValueAxis *>(axis());
+ const qreal logMax = log10(logValueAxis->max()) / log10(logValueAxis->base());
+ const qreal logMin = log10(logValueAxis->min()) / log10(logValueAxis->base());
+ const qreal startEdge = logMin < logMax ? logMin : logMax;
+ const qreal delta = 360.0 / qAbs(logMax - logMin);
+ const qreal initialSpan = (ceil(startEdge) - startEdge) * delta;
+ int tickCount = qAbs(ceil(logMax) - ceil(logMin));
+
+ QVector<qreal> points;
+ points.resize(tickCount);
+
+ for (int i = 0; i < tickCount; ++i) {
+ qreal angularCoordinate = initialSpan + (delta * qreal(i));
+ points[i] = angularCoordinate;
+ }
+
+ return points;
+}
+
+void PolarChartLogValueAxisAngular::createAxisLabels(const QVector<qreal> &layout)
+{
+ QLogValueAxis *logValueAxis = static_cast<QLogValueAxis *>(axis());
+ setLabels(createLogValueLabels(logValueAxis->min(),
+ logValueAxis->max(),
+ logValueAxis->base(),
+ layout.size(),
+ logValueAxis->labelFormat()));
+}
+
+void PolarChartLogValueAxisAngular::handleBaseChanged(qreal base)
+{
+ Q_UNUSED(base);
+ QGraphicsLayoutItem::updateGeometry();
+ if (presenter())
+ presenter()->layout()->invalidate();
+}
+
+void PolarChartLogValueAxisAngular::handleLabelFormatChanged(const QString &format)
+{
+ Q_UNUSED(format);
+ QGraphicsLayoutItem::updateGeometry();
+ if (presenter())
+ presenter()->layout()->invalidate();
+}
+
+#include "moc_polarchartlogvalueaxisangular_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/logvalueaxis/polarchartlogvalueaxisangular_p.h b/src/charts/axis/logvalueaxis/polarchartlogvalueaxisangular_p.h
new file mode 100644
index 00000000..d56f7fdc
--- /dev/null
+++ b/src/charts/axis/logvalueaxis/polarchartlogvalueaxisangular_p.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 POLARCHARTLOGVALUEAXISANGULAR_P_H
+#define POLARCHARTLOGVALUEAXISANGULAR_P_H
+
+#include "polarchartaxisangular_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QLogValueAxis;
+
+class PolarChartLogValueAxisAngular : public PolarChartAxisAngular
+{
+ Q_OBJECT
+public:
+ PolarChartLogValueAxisAngular(QLogValueAxis *axis, QGraphicsItem *item);
+ ~PolarChartLogValueAxisAngular();
+
+protected:
+ virtual QVector<qreal> calculateLayout() const;
+ virtual void createAxisLabels(const QVector<qreal> &layout);
+
+private Q_SLOTS:
+ void handleBaseChanged(qreal base);
+ void handleLabelFormatChanged(const QString &format);
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // POLARCHARTLOGVALUEAXISANGULAR_P_H
diff --git a/src/charts/axis/logvalueaxis/polarchartlogvalueaxisradial.cpp b/src/charts/axis/logvalueaxis/polarchartlogvalueaxisradial.cpp
new file mode 100644
index 00000000..3c0d01b3
--- /dev/null
+++ b/src/charts/axis/logvalueaxis/polarchartlogvalueaxisradial.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "polarchartlogvalueaxisradial_p.h"
+#include "abstractchartlayout_p.h"
+#include "chartpresenter_p.h"
+#include "qlogvalueaxis.h"
+#include <qmath.h>
+#include <QDebug>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+PolarChartLogValueAxisRadial::PolarChartLogValueAxisRadial(QLogValueAxis *axis, QGraphicsItem *item)
+ : PolarChartAxisRadial(axis, item)
+{
+ QObject::connect(axis, SIGNAL(baseChanged(qreal)), this, SLOT(handleBaseChanged(qreal)));
+ QObject::connect(axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
+}
+
+PolarChartLogValueAxisRadial::~PolarChartLogValueAxisRadial()
+{
+}
+
+QVector<qreal> PolarChartLogValueAxisRadial::calculateLayout() const
+{
+ QLogValueAxis *logValueAxis = static_cast<QLogValueAxis *>(axis());
+ const qreal logMax = log10(logValueAxis->max()) / log10(logValueAxis->base());
+ const qreal logMin = log10(logValueAxis->min()) / log10(logValueAxis->base());
+ const qreal innerEdge = logMin < logMax ? logMin : logMax;
+ const qreal outerEdge = logMin > logMax ? logMin : logMax;
+ const qreal delta = (axisGeometry().width() / 2.0) / qAbs(logMax - logMin);
+ const qreal initialSpan = (ceil(innerEdge) - innerEdge) * delta;
+ int tickCount = qAbs(ceil(logMax) - ceil(logMin));
+
+ // Extra tick if outer edge is exactly at the tick
+ if (outerEdge == ceil(outerEdge))
+ tickCount++;
+
+ QVector<qreal> points;
+ points.resize(tickCount);
+
+ for (int i = 0; i < tickCount; ++i) {
+ qreal radialCoordinate = initialSpan + (delta * qreal(i));
+ points[i] = radialCoordinate;
+ }
+
+ return points;
+}
+
+void PolarChartLogValueAxisRadial::createAxisLabels(const QVector<qreal> &layout)
+{
+ QLogValueAxis *logValueAxis = static_cast<QLogValueAxis *>(axis());
+ setLabels(createLogValueLabels(logValueAxis->min(),
+ logValueAxis->max(),
+ logValueAxis->base(),
+ layout.size(),
+ logValueAxis->labelFormat()));
+}
+
+void PolarChartLogValueAxisRadial::handleBaseChanged(qreal base)
+{
+ Q_UNUSED(base);
+ QGraphicsLayoutItem::updateGeometry();
+ if (presenter())
+ presenter()->layout()->invalidate();
+}
+
+void PolarChartLogValueAxisRadial::handleLabelFormatChanged(const QString &format)
+{
+ Q_UNUSED(format);
+ QGraphicsLayoutItem::updateGeometry();
+ if (presenter())
+ presenter()->layout()->invalidate();
+}
+
+#include "moc_polarchartlogvalueaxisradial_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/logvalueaxis/polarchartlogvalueaxisradial_p.h b/src/charts/axis/logvalueaxis/polarchartlogvalueaxisradial_p.h
new file mode 100644
index 00000000..4bc59061
--- /dev/null
+++ b/src/charts/axis/logvalueaxis/polarchartlogvalueaxisradial_p.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 POLARCHARTLOGVALUEAXISRADIAL_P_H
+#define POLARCHARTLOGVALUEAXISRADIAL_P_H
+
+#include "polarchartaxisradial_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QLogValueAxis;
+
+class PolarChartLogValueAxisRadial : public PolarChartAxisRadial
+{
+ Q_OBJECT
+public:
+ PolarChartLogValueAxisRadial(QLogValueAxis *axis, QGraphicsItem *item);
+ ~PolarChartLogValueAxisRadial();
+
+protected:
+ virtual QVector<qreal> calculateLayout() const;
+ virtual void createAxisLabels(const QVector<qreal> &layout);
+
+private Q_SLOTS:
+ void handleBaseChanged(qreal base);
+ void handleLabelFormatChanged(const QString &format);
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // POLARCHARTLOGVALUEAXISRADIAL_P_H
diff --git a/src/charts/axis/logvalueaxis/qlogvalueaxis.cpp b/src/charts/axis/logvalueaxis/qlogvalueaxis.cpp
new file mode 100644
index 00000000..ad58905d
--- /dev/null
+++ b/src/charts/axis/logvalueaxis/qlogvalueaxis.cpp
@@ -0,0 +1,400 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlogvalueaxis.h"
+#include "qlogvalueaxis_p.h"
+#include "chartlogvalueaxisx_p.h"
+#include "chartlogvalueaxisy_p.h"
+#include "polarchartlogvalueaxisangular_p.h"
+#include "polarchartlogvalueaxisradial_p.h"
+#include "abstractdomain_p.h"
+#include <float.h>
+#include <cmath>
+
+QT_CHARTS_BEGIN_NAMESPACE
+/*!
+ \class QLogValueAxis
+ \inmodule Qt Charts
+ \brief The QLogValueAxis class is used for manipulating chart's axis.
+ \mainclass
+
+ \note If a QLogValueAxis is attached to a series with one or more points with
+ negative or zero values on the associated dimension, the series will not be
+ plotted at all. This is particularly relevant when XYModelMappers are used,
+ since empty cells in models typically contain zero values.
+*/
+
+/*!
+ \qmltype LogValueAxis
+ \instantiates QLogValueAxis
+ \inqmlmodule QtCharts
+
+ \brief The LogValueAxis element is used for manipulating chart's axes.
+ \inherits AbstractAxis
+
+ \note If a LogValueAxis is attached to a series with one or more points with
+ negative or zero values on the associated dimension, the series will not be
+ plotted at all. This is particularly relevant when XYModelMappers are used,
+ since empty cells in models typically contain zero values.
+*/
+
+/*!
+ \property QLogValueAxis::min
+ Defines the minimum value on the axis.
+ When setting this property the max is adjusted if necessary, to ensure that the range remains valid.
+ Value has to be greater than 0.
+*/
+/*!
+ \qmlproperty real LogValueAxis::min
+ Defines the minimum value on the axis.
+ When setting this property the max is adjusted if necessary, to ensure that the range remains valid.
+ Value has to be greater than 0.
+*/
+
+/*!
+ \property QLogValueAxis::max
+ Defines the maximum value on the axis.
+ When setting this property the min is adjusted if necessary, to ensure that the range remains valid.
+ Value has to be greater than 0.
+*/
+/*!
+ \qmlproperty real LogValueAxis::max
+ Defines the maximum value on the axis.
+ When setting this property the min is adjusted if necessary, to ensure that the range remains valid.
+ Value has to be greater than 0.
+*/
+
+/*!
+ \property QLogValueAxis::base
+ Defines the base of the logarithm.
+ Value has to be greater than 0 and not equal 1
+*/
+/*!
+ \qmlproperty real LogValueAxis::base
+ Defines the maximum value on the axis.
+ Defines the base of the logarithm.
+ Value has to be greater than 0 and not equal 1
+*/
+
+/*!
+ \property QLogValueAxis::labelFormat
+ Defines the label format of the axis.
+ Supported specifiers are: d, i, o, x, X, f, F, e, E, g, G, c
+ See QString::sprintf() for additional details.
+*/
+/*!
+ \qmlproperty real LogValueAxis::labelFormat
+ Defines the label format of the axis.
+ Supported specifiers are: d, i, o, x, X, f, F, e, E, g, G, c
+ See QString::sprintf() for additional details.
+*/
+
+/*!
+ \fn void QLogValueAxis::minChanged(qreal min)
+ Axis emits signal when \a min of axis has changed.
+*/
+/*!
+ \qmlsignal LogValueAxis::onMinChanged(qreal min)
+ Axis emits signal when \a min of axis has changed.
+*/
+
+/*!
+ \fn void QLogValueAxis::maxChanged(qreal max)
+ Axis emits signal when \a max of axis has changed.
+*/
+/*!
+ \qmlsignal LogValueAxis::onMaxChanged(qreal max)
+ Axis emits signal when \a max of axis has changed.
+*/
+
+/*!
+ \fn void QLogValueAxis::rangeChanged(qreal min, qreal max)
+ Axis emits signal when \a min or \a max of axis has changed.
+*/
+
+/*!
+ \fn void QLogValueAxis::labelFormatChanged(const QString &format)
+ Axis emits signal when \a format of axis labels has changed.
+*/
+/*!
+ \qmlsignal LogValueAxis::labelFormatChanged(const QString &format)
+ Axis emits signal when \a format of axis labels has changed.
+*/
+
+/*!
+ \fn void QLogValueAxis::baseChanged(qreal base)
+ Axis emits signal when \a base of logarithm of the axis has changed.
+*/
+/*!
+ \qmlsignal LogValueAxis::baseChanged(qreal base)
+ Axis emits signal when \a base of logarithm of the axis has changed.
+*/
+
+/*!
+ Constructs an axis object which is a child of \a parent.
+*/
+QLogValueAxis::QLogValueAxis(QObject *parent) :
+ QAbstractAxis(*new QLogValueAxisPrivate(this), parent)
+{
+
+}
+
+/*!
+ \internal
+*/
+QLogValueAxis::QLogValueAxis(QLogValueAxisPrivate &d, QObject *parent) : QAbstractAxis(d, parent)
+{
+
+}
+
+/*!
+ Destroys the object
+*/
+QLogValueAxis::~QLogValueAxis()
+{
+ Q_D(QLogValueAxis);
+ if (d->m_chart)
+ d->m_chart->removeAxis(this);
+}
+
+void QLogValueAxis::setMin(qreal min)
+{
+ Q_D(QLogValueAxis);
+ setRange(min, qMax(d->m_max, min));
+}
+
+qreal QLogValueAxis::min() const
+{
+ Q_D(const QLogValueAxis);
+ return d->m_min;
+}
+
+void QLogValueAxis::setMax(qreal max)
+{
+ Q_D(QLogValueAxis);
+ setRange(qMin(d->m_min, max), max);
+}
+
+qreal QLogValueAxis::max() const
+{
+ Q_D(const QLogValueAxis);
+ return d->m_max;
+}
+
+/*!
+ Sets range from \a min to \a max on the axis.
+ If min is greater than max then this function returns without making any changes.
+*/
+void QLogValueAxis::setRange(qreal min, qreal max)
+{
+ Q_D(QLogValueAxis);
+ bool changed = false;
+
+ if (min > max)
+ return;
+
+ if (min > 0) {
+ if (!qFuzzyCompare(d->m_min, min)) {
+ d->m_min = min;
+ changed = true;
+ emit minChanged(min);
+ }
+
+ if (!qFuzzyCompare(d->m_max, max)) {
+ d->m_max = max;
+ changed = true;
+ emit maxChanged(max);
+ }
+
+ if (changed) {
+ emit rangeChanged(min, max);
+ emit d->rangeChanged(min,max);
+ }
+ }
+}
+
+void QLogValueAxis::setLabelFormat(const QString &format)
+{
+ Q_D(QLogValueAxis);
+ d->m_format = format;
+ emit labelFormatChanged(format);
+}
+
+QString QLogValueAxis::labelFormat() const
+{
+ Q_D(const QLogValueAxis);
+ return d->m_format;
+}
+
+void QLogValueAxis::setBase(qreal base)
+{
+ // check if base is correct
+ if (qFuzzyCompare(base, 1))
+ return;
+
+ if (base > 0) {
+ Q_D(QLogValueAxis);
+ d->m_base = base;
+ emit baseChanged(base);
+ }
+}
+
+qreal QLogValueAxis::base() const
+{
+ Q_D(const QLogValueAxis);
+ return d->m_base;
+}
+
+/*!
+ Returns the type of the axis
+*/
+QAbstractAxis::AxisType QLogValueAxis::type() const
+{
+ return AxisTypeLogValue;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QLogValueAxisPrivate::QLogValueAxisPrivate(QLogValueAxis *q)
+ : QAbstractAxisPrivate(q),
+ m_min(1),
+ m_max(1),
+ m_base(10),
+ m_format(QString::null)
+{
+}
+
+QLogValueAxisPrivate::~QLogValueAxisPrivate()
+{
+
+}
+
+void QLogValueAxisPrivate::setMin(const QVariant &min)
+{
+ Q_Q(QLogValueAxis);
+ bool ok;
+ qreal value = min.toReal(&ok);
+ if (ok)
+ q->setMin(value);
+}
+
+void QLogValueAxisPrivate::setMax(const QVariant &max)
+{
+
+ Q_Q(QLogValueAxis);
+ bool ok;
+ qreal value = max.toReal(&ok);
+ if (ok)
+ q->setMax(value);
+}
+
+void QLogValueAxisPrivate::setRange(const QVariant &min, const QVariant &max)
+{
+ Q_Q(QLogValueAxis);
+ bool ok1;
+ bool ok2;
+ qreal value1 = min.toReal(&ok1);
+ qreal value2 = max.toReal(&ok2);
+ if (ok1 && ok2)
+ q->setRange(value1, value2);
+}
+
+void QLogValueAxisPrivate::setRange(qreal min, qreal max)
+{
+ Q_Q(QLogValueAxis);
+ bool changed = false;
+
+ if (min > max)
+ return;
+
+ if (min > 0) {
+ if (!qFuzzyCompare(m_min, min)) {
+ m_min = min;
+ changed = true;
+ emit q->minChanged(min);
+ }
+
+ if (!qFuzzyCompare(m_max, max)) {
+ m_max = max;
+ changed = true;
+ emit q->maxChanged(max);
+ }
+
+ if (changed) {
+ emit rangeChanged(min,max);
+ emit q->rangeChanged(min, max);
+ }
+ }
+}
+
+void QLogValueAxisPrivate::initializeGraphics(QGraphicsItem *parent)
+{
+ Q_Q(QLogValueAxis);
+ ChartAxisElement *axis(0);
+
+ if (m_chart->chartType() == QChart::ChartTypeCartesian) {
+ if (orientation() == Qt::Vertical)
+ axis = new ChartLogValueAxisY(q,parent);
+ if (orientation() == Qt::Horizontal)
+ axis = new ChartLogValueAxisX(q,parent);
+ }
+
+ if (m_chart->chartType() == QChart::ChartTypePolar) {
+ if (orientation() == Qt::Vertical)
+ axis = new PolarChartLogValueAxisRadial(q, parent);
+ if (orientation() == Qt::Horizontal)
+ axis = new PolarChartLogValueAxisAngular(q, parent);
+ }
+
+ m_item.reset(axis);
+ QAbstractAxisPrivate::initializeGraphics(parent);
+}
+
+
+void QLogValueAxisPrivate::initializeDomain(AbstractDomain *domain)
+{
+ if (orientation() == Qt::Vertical) {
+ if (!qFuzzyCompare(m_max, m_min)) {
+ domain->setRangeY(m_min, m_max);
+ } else if ( domain->minY() > 0) {
+ setRange(domain->minY(), domain->maxY());
+ } else if (domain->maxY() > 0) {
+ domain->setRangeY(m_min, domain->maxY());
+ } else {
+ domain->setRangeY(1, 10);
+ }
+ }
+ if (orientation() == Qt::Horizontal) {
+ if (!qFuzzyCompare(m_max, m_min)) {
+ domain->setRangeX(m_min, m_max);
+ } else if (domain->minX() > 0){
+ setRange(domain->minX(), domain->maxX());
+ } else if (domain->maxX() > 0) {
+ domain->setRangeX(m_min, domain->maxX());
+ } else {
+ domain->setRangeX(1, 10);
+ }
+ }
+}
+
+#include "moc_qlogvalueaxis.cpp"
+#include "moc_qlogvalueaxis_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/logvalueaxis/qlogvalueaxis.h b/src/charts/axis/logvalueaxis/qlogvalueaxis.h
new file mode 100644
index 00000000..2ad1f6ab
--- /dev/null
+++ b/src/charts/axis/logvalueaxis/qlogvalueaxis.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLOGVALUEAXIS_H
+#define QLOGVALUEAXIS_H
+
+#include <QtCharts/qabstractaxis.h>
+
+class QDateTime;
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QLogValueAxisPrivate;
+
+class QT_CHARTS_EXPORT QLogValueAxis : public QAbstractAxis
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal min READ min WRITE setMin NOTIFY minChanged)
+ Q_PROPERTY(qreal max READ max WRITE setMax NOTIFY maxChanged)
+ Q_PROPERTY(QString labelFormat READ labelFormat WRITE setLabelFormat NOTIFY labelFormatChanged)
+ Q_PROPERTY(qreal base READ base WRITE setBase NOTIFY baseChanged)
+
+public:
+ explicit QLogValueAxis(QObject *parent = 0);
+ ~QLogValueAxis();
+
+protected:
+ QLogValueAxis(QLogValueAxisPrivate &d, QObject *parent = 0);
+
+public:
+ AxisType type() const;
+
+ //range handling
+ void setMin(qreal min);
+ qreal min() const;
+ void setMax(qreal max);
+ qreal max() const;
+ void setRange(qreal min, qreal max);
+
+ void setLabelFormat(const QString &format);
+ QString labelFormat() const;
+
+ void setBase(qreal base);
+ qreal base() const;
+
+Q_SIGNALS:
+ void minChanged(qreal min);
+ void maxChanged(qreal max);
+ void rangeChanged(qreal min, qreal max);
+ void labelFormatChanged(const QString &format);
+ void baseChanged(qreal base);
+
+private:
+ Q_DECLARE_PRIVATE(QLogValueAxis)
+ Q_DISABLE_COPY(QLogValueAxis)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QLOGVALUEAXIS_H
diff --git a/src/charts/axis/logvalueaxis/qlogvalueaxis_p.h b/src/charts/axis/logvalueaxis/qlogvalueaxis_p.h
new file mode 100644
index 00000000..741626f3
--- /dev/null
+++ b/src/charts/axis/logvalueaxis/qlogvalueaxis_p.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QLOGVALUEAXIS_P_H
+#define QLOGVALUEAXIS_P_H
+
+#include <qlogvalueaxis.h>
+#include "qabstractaxis_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QLogValueAxisPrivate : public QAbstractAxisPrivate
+{
+ Q_OBJECT
+ public:
+ QLogValueAxisPrivate(QLogValueAxis *q);
+ ~QLogValueAxisPrivate();
+
+ public:
+ void initializeGraphics(QGraphicsItem* parent);
+ void initializeDomain(AbstractDomain *domain);
+
+ qreal min() { return m_min; }
+ qreal max() { return m_max; }
+ void setRange(qreal min,qreal max);
+
+ protected:
+ void setMin(const QVariant &min);
+ void setMax(const QVariant &max);
+ void setRange(const QVariant &min, const QVariant &max);
+ int tickCount() const;
+
+ protected:
+ qreal m_min;
+ qreal m_max;
+ qreal m_base;
+ QString m_format;
+ Q_DECLARE_PUBLIC(QLogValueAxis)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QLOGVALUEAXIS_P_H
diff --git a/src/charts/axis/polarchartaxis.cpp b/src/charts/axis/polarchartaxis.cpp
new file mode 100644
index 00000000..bf9caaeb
--- /dev/null
+++ b/src/charts/axis/polarchartaxis.cpp
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "polarchartaxis_p.h"
+#include "qabstractaxis_p.h"
+#include "chartpresenter_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+PolarChartAxis::PolarChartAxis(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
+ : ChartAxisElement(axis, item, intervalAxis)
+{
+}
+
+PolarChartAxis::~PolarChartAxis()
+{
+
+}
+
+void PolarChartAxis::setGeometry(const QRectF &axis, const QRectF &grid)
+{
+ Q_UNUSED(grid);
+ setAxisGeometry(axis);
+
+ if (isEmpty())
+ return;
+
+ QVector<qreal> layout = calculateLayout();
+ updateLayout(layout);
+}
+
+QRectF PolarChartAxis::gridGeometry() const
+{
+ return QRectF();
+}
+
+void PolarChartAxis::updateLayout(QVector<qreal> &layout)
+{
+ int diff = ChartAxisElement::layout().size() - layout.size();
+
+ if (animation()) {
+ switch (presenter()->state()) {
+ case ChartPresenter::ZoomInState:
+ case ChartPresenter::ZoomOutState:
+ case ChartPresenter::ScrollUpState:
+ case ChartPresenter::ScrollLeftState:
+ case ChartPresenter::ScrollDownState:
+ case ChartPresenter::ScrollRightState:
+ case ChartPresenter::ShowState:
+ animation()->setAnimationType(AxisAnimation::DefaultAnimation);
+ break;
+ }
+ // Update to "old" geometry before starting animation to avoid incorrectly sized
+ // axes lingering in wrong position compared to series plot before animation can kick in.
+ // Note that the position mismatch still exists even with this update, but it will be
+ // far less ugly.
+ updateGeometry();
+ }
+
+ if (diff > 0)
+ deleteItems(diff);
+ else if (diff < 0)
+ createItems(-diff);
+
+ if (animation()) {
+ animation()->setValues(ChartAxisElement::layout(), layout);
+ presenter()->startAnimation(animation());
+ } else {
+ setLayout(layout);
+ updateGeometry();
+ }
+}
+
+bool PolarChartAxis::isEmpty()
+{
+ return !axisGeometry().isValid() || qFuzzyIsNull(min() - max());
+}
+
+void PolarChartAxis::deleteItems(int count)
+{
+ QList<QGraphicsItem *> gridLines = gridItems();
+ QList<QGraphicsItem *> labels = labelItems();
+ QList<QGraphicsItem *> shades = shadeItems();
+ QList<QGraphicsItem *> axis = arrowItems();
+
+ for (int i = 0; i < count; ++i) {
+ if (gridItems().size() == 1 || (((gridLines.size() + 1) % 2) && gridLines.size() > 0))
+ delete(shades.takeLast());
+ delete(gridLines.takeLast());
+ delete(labels.takeLast());
+ delete(axis.takeLast());
+ }
+}
+
+void PolarChartAxis::handleShadesBrushChanged(const QBrush &brush)
+{
+ foreach (QGraphicsItem *item, shadeItems())
+ static_cast<QGraphicsPathItem *>(item)->setBrush(brush);
+}
+
+void PolarChartAxis::handleShadesPenChanged(const QPen &pen)
+{
+ foreach (QGraphicsItem *item, shadeItems())
+ static_cast<QGraphicsPathItem *>(item)->setPen(pen);
+}
+
+#include "moc_polarchartaxis_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/polarchartaxis_p.h b/src/charts/axis/polarchartaxis_p.h
new file mode 100644
index 00000000..8924b812
--- /dev/null
+++ b/src/charts/axis/polarchartaxis_p.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 POLARCHARTAXIS_P_H
+#define POLARCHARTAXIS_P_H
+
+#include "chartaxiselement_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class PolarChartAxis : public ChartAxisElement
+{
+ Q_OBJECT
+ Q_INTERFACES(QGraphicsLayoutItem)
+public:
+ PolarChartAxis(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis = false);
+ ~PolarChartAxis();
+
+ void setGeometry(const QRectF &axis, const QRectF &grid);
+ virtual qreal preferredAxisRadius(const QSizeF &maxSize) = 0;
+ int tickWidth() { return 3; }
+
+public: // from ChartAxisElement
+ QRectF gridGeometry() const;
+ bool isEmpty();
+
+protected:
+ void updateLayout(QVector<qreal> &layout);
+
+protected: // virtual functions
+ virtual void createItems(int count) = 0;
+ virtual void createAxisLabels(const QVector<qreal> &layout) = 0;
+
+public Q_SLOTS:
+ virtual void handleShadesBrushChanged(const QBrush &brush);
+ virtual void handleShadesPenChanged(const QPen &pen);
+
+private:
+ void deleteItems(int count);
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // POLARCHARTAXIS_P_H
diff --git a/src/charts/axis/polarchartaxisangular.cpp b/src/charts/axis/polarchartaxisangular.cpp
new file mode 100644
index 00000000..83f1535c
--- /dev/null
+++ b/src/charts/axis/polarchartaxisangular.cpp
@@ -0,0 +1,433 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "polarchartaxisangular_p.h"
+#include "chartpresenter_p.h"
+#include "abstractchartlayout_p.h"
+#include "qabstractaxis.h"
+#include "qabstractaxis_p.h"
+#include <QDebug>
+#include <qmath.h>
+#include <QTextDocument>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+PolarChartAxisAngular::PolarChartAxisAngular(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
+ : PolarChartAxis(axis, item, intervalAxis)
+{
+}
+
+PolarChartAxisAngular::~PolarChartAxisAngular()
+{
+}
+
+void PolarChartAxisAngular::updateGeometry()
+{
+ QGraphicsLayoutItem::updateGeometry();
+
+ const QVector<qreal> &layout = this->layout();
+ if (layout.isEmpty())
+ return;
+
+ createAxisLabels(layout);
+ QStringList labelList = labels();
+ QPointF center = axisGeometry().center();
+ QList<QGraphicsItem *> arrowItemList = arrowItems();
+ QList<QGraphicsItem *> gridItemList = gridItems();
+ QList<QGraphicsItem *> labelItemList = labelItems();
+ QList<QGraphicsItem *> shadeItemList = shadeItems();
+ QGraphicsTextItem *title = titleItem();
+
+ QGraphicsEllipseItem *axisLine = static_cast<QGraphicsEllipseItem *>(arrowItemList.at(0));
+ axisLine->setRect(axisGeometry());
+
+ qreal radius = axisGeometry().height() / 2.0;
+
+ QRectF previousLabelRect;
+ QRectF firstLabelRect;
+
+ qreal labelHeight = 0;
+
+ bool firstShade = true;
+ bool nextTickVisible = false;
+ if (layout.size())
+ nextTickVisible = !(layout.at(0) < 0.0 || layout.at(0) > 360.0);
+
+ for (int i = 0; i < layout.size(); ++i) {
+ qreal angularCoordinate = layout.at(i);
+
+ QGraphicsLineItem *gridLineItem = static_cast<QGraphicsLineItem *>(gridItemList.at(i));
+ QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem *>(arrowItemList.at(i + 1));
+ QGraphicsTextItem *labelItem = static_cast<QGraphicsTextItem *>(labelItemList.at(i));
+ QGraphicsPathItem *shadeItem = 0;
+ if (i == 0)
+ shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0));
+ else if (i % 2)
+ shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at((i / 2) + 1));
+
+ // Ignore ticks outside valid range
+ bool currentTickVisible = nextTickVisible;
+ if ((i == layout.size() - 1)
+ || layout.at(i + 1) < 0.0
+ || layout.at(i + 1) > 360.0) {
+ nextTickVisible = false;
+ } else {
+ nextTickVisible = true;
+ }
+
+ qreal labelCoordinate = angularCoordinate;
+ qreal labelVisible = currentTickVisible;
+ if (intervalAxis()) {
+ qreal farEdge;
+ if (i == (layout.size() - 1))
+ farEdge = 360.0;
+ else
+ farEdge = qMin(qreal(360.0), layout.at(i + 1));
+
+ // Adjust the labelCoordinate to show it if next tick is visible
+ if (nextTickVisible)
+ labelCoordinate = qMax(qreal(0.0), labelCoordinate);
+
+ labelCoordinate = (labelCoordinate + farEdge) / 2.0;
+ // Don't display label once the category gets too small near the axis
+ if (labelCoordinate < 5.0 || labelCoordinate > 355.0)
+ labelVisible = false;
+ else
+ labelVisible = true;
+ }
+
+ // Need this also in label calculations, so determine it first
+ QLineF tickLine(QLineF::fromPolar(radius - tickWidth(), 90.0 - angularCoordinate).p2(),
+ QLineF::fromPolar(radius + tickWidth(), 90.0 - angularCoordinate).p2());
+ tickLine.translate(center);
+
+ // Angular axis label
+ if (axis()->labelsVisible() && labelVisible) {
+ QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(),
+ labelList.at(i),
+ axis()->labelsAngle());
+ labelItem->setTextWidth(boundingRect.width());
+ labelItem->setHtml(labelList.at(i));
+ const QRectF &rect = labelItem->boundingRect();
+ QPointF labelCenter = rect.center();
+ labelItem->setTransformOriginPoint(labelCenter.x(), labelCenter.y());
+ boundingRect.moveCenter(labelCenter);
+ QPointF positionDiff(rect.topLeft() - boundingRect.topLeft());
+
+ QPointF labelPoint;
+ if (intervalAxis()) {
+ QLineF labelLine = QLineF::fromPolar(radius + tickWidth(), 90.0 - labelCoordinate);
+ labelLine.translate(center);
+ labelPoint = labelLine.p2();
+ } else {
+ labelPoint = tickLine.p2();
+ }
+
+ QRectF labelRect = moveLabelToPosition(labelCoordinate, labelPoint, boundingRect);
+ labelItem->setPos(labelRect.topLeft() + positionDiff);
+
+ // Store height for title calculations
+ qreal labelClearance = axisGeometry().top() - labelRect.top();
+ labelHeight = qMax(labelHeight, labelClearance);
+
+ // Label overlap detection
+ if (i && (previousLabelRect.intersects(labelRect) || firstLabelRect.intersects(labelRect))) {
+ labelVisible = false;
+ } else {
+ // Store labelRect for future comparison. Some area is deducted to make things look
+ // little nicer, as usually intersection happens at label corner with angular labels.
+ labelRect.adjust(-2.0, -4.0, -2.0, -4.0);
+ if (firstLabelRect.isEmpty())
+ firstLabelRect = labelRect;
+
+ previousLabelRect = labelRect;
+ labelVisible = true;
+ }
+ }
+
+ labelItem->setVisible(labelVisible);
+ if (!currentTickVisible) {
+ gridLineItem->setVisible(false);
+ tickItem->setVisible(false);
+ if (shadeItem)
+ shadeItem->setVisible(false);
+ continue;
+ }
+
+ // Angular grid line
+ QLineF gridLine = QLineF::fromPolar(radius, 90.0 - angularCoordinate);
+ gridLine.translate(center);
+ gridLineItem->setLine(gridLine);
+ gridLineItem->setVisible(true);
+
+ // Tick
+ tickItem->setLine(tickLine);
+ tickItem->setVisible(true);
+
+ // Shades
+ if (i % 2 || (i == 0 && !nextTickVisible)) {
+ QPainterPath path;
+ path.moveTo(center);
+ if (i == 0) {
+ // If first tick is also the last, we need to custom fill the first partial arc
+ // or it won't get filled.
+ path.arcTo(axisGeometry(), 90.0 - layout.at(0), layout.at(0));
+ path.closeSubpath();
+ } else {
+ qreal nextCoordinate;
+ if (!nextTickVisible) // Last visible tick
+ nextCoordinate = 360.0;
+ else
+ nextCoordinate = layout.at(i + 1);
+ qreal arcSpan = angularCoordinate - nextCoordinate;
+ path.arcTo(axisGeometry(), 90.0 - angularCoordinate, arcSpan);
+ path.closeSubpath();
+
+ // Add additional arc for first shade item if there is a partial arc to be filled
+ if (firstShade) {
+ QGraphicsPathItem *specialShadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0));
+ if (layout.at(i - 1) > 0.0) {
+ QPainterPath specialPath;
+ specialPath.moveTo(center);
+ specialPath.arcTo(axisGeometry(), 90.0 - layout.at(i - 1), layout.at(i - 1));
+ specialPath.closeSubpath();
+ specialShadeItem->setPath(specialPath);
+ specialShadeItem->setVisible(true);
+ } else {
+ specialShadeItem->setVisible(false);
+ }
+ }
+ }
+ shadeItem->setPath(path);
+ shadeItem->setVisible(true);
+ firstShade = false;
+ }
+ }
+
+ // Title, centered above the chart
+ QString titleText = axis()->titleText();
+ if (!titleText.isEmpty() && axis()->isTitleVisible()) {
+ QRectF truncatedRect;
+ qreal availableTitleHeight = axisGeometry().height() - labelPadding() - titlePadding() * 2.0;
+ qreal minimumLabelHeight = ChartPresenter::textBoundingRect(axis()->labelsFont(),
+ QStringLiteral("...")).height();
+ availableTitleHeight -= minimumLabelHeight;
+ title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(0.0),
+ axisGeometry().width(), availableTitleHeight,
+ truncatedRect));
+ title->setTextWidth(truncatedRect.width());
+
+ QRectF titleBoundingRect = title->boundingRect();
+ QPointF titleCenter = center - titleBoundingRect.center();
+ title->setPos(titleCenter.x(), axisGeometry().top() - titlePadding() * 2.0 - titleBoundingRect.height() - labelHeight);
+ }
+}
+
+Qt::Orientation PolarChartAxisAngular::orientation() const
+{
+ return Qt::Horizontal;
+}
+
+void PolarChartAxisAngular::createItems(int count)
+{
+ if (arrowItems().count() == 0) {
+ // angular axis line
+ QGraphicsEllipseItem *arrow = new QGraphicsEllipseItem(presenter()->rootItem());
+ arrow->setPen(axis()->linePen());
+ arrowGroup()->addToGroup(arrow);
+ }
+
+ QGraphicsTextItem *title = titleItem();
+ title->setFont(axis()->titleFont());
+ title->setDefaultTextColor(axis()->titleBrush().color());
+ title->setHtml(axis()->titleText());
+
+ for (int i = 0; i < count; ++i) {
+ QGraphicsLineItem *arrow = new QGraphicsLineItem(presenter()->rootItem());
+ QGraphicsLineItem *grid = new QGraphicsLineItem(presenter()->rootItem());
+ QGraphicsTextItem *label = new QGraphicsTextItem(presenter()->rootItem());
+ label->document()->setDocumentMargin(ChartPresenter::textMargin());
+ arrow->setPen(axis()->linePen());
+ grid->setPen(axis()->gridLinePen());
+ label->setFont(axis()->labelsFont());
+ label->setDefaultTextColor(axis()->labelsBrush().color());
+ label->setRotation(axis()->labelsAngle());
+ arrowGroup()->addToGroup(arrow);
+ gridGroup()->addToGroup(grid);
+ labelGroup()->addToGroup(label);
+ if (gridItems().size() == 1 || (((gridItems().size() + 1) % 2) && gridItems().size() > 0)) {
+ QGraphicsPathItem *shade = new QGraphicsPathItem(presenter()->rootItem());
+ shade->setPen(axis()->shadesPen());
+ shade->setBrush(axis()->shadesBrush());
+ shadeGroup()->addToGroup(shade);
+ }
+ }
+}
+
+void PolarChartAxisAngular::handleArrowPenChanged(const QPen &pen)
+{
+ bool first = true;
+ foreach (QGraphicsItem *item, arrowItems()) {
+ if (first) {
+ first = false;
+ // First arrow item is the outer circle of axis
+ static_cast<QGraphicsEllipseItem *>(item)->setPen(pen);
+ } else {
+ static_cast<QGraphicsLineItem *>(item)->setPen(pen);
+ }
+ }
+}
+
+void PolarChartAxisAngular::handleGridPenChanged(const QPen &pen)
+{
+ foreach (QGraphicsItem *item, gridItems())
+ static_cast<QGraphicsLineItem *>(item)->setPen(pen);
+}
+
+QSizeF PolarChartAxisAngular::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED(which);
+ Q_UNUSED(constraint);
+ return QSizeF(-1, -1);
+}
+
+qreal PolarChartAxisAngular::preferredAxisRadius(const QSizeF &maxSize)
+{
+ qreal radius = maxSize.height() / 2.0;
+ if (maxSize.width() < maxSize.height())
+ radius = maxSize.width() / 2.0;
+
+ if (axis()->labelsVisible()) {
+ QVector<qreal> layout = calculateLayout();
+ if (layout.isEmpty())
+ return radius;
+
+ createAxisLabels(layout);
+ QStringList labelList = labels();
+ QFont font = axis()->labelsFont();
+
+ QRectF maxRect;
+ maxRect.setSize(maxSize);
+ maxRect.moveCenter(QPointF(0.0, 0.0));
+
+ // This is a horrible way to find out the maximum radius for angular axis and its labels.
+ // It just increments the radius down until everyhing fits the constraint size.
+ // Proper way would be to actually calculate it but this seems to work reasonably fast as it is.
+ bool nextTickVisible = false;
+ for (int i = 0; i < layout.size(); ) {
+ if ((i == layout.size() - 1)
+ || layout.at(i + 1) < 0.0
+ || layout.at(i + 1) > 360.0) {
+ nextTickVisible = false;
+ } else {
+ nextTickVisible = true;
+ }
+
+ qreal labelCoordinate = layout.at(i);
+ qreal labelVisible;
+
+ if (intervalAxis()) {
+ qreal farEdge;
+ if (i == (layout.size() - 1))
+ farEdge = 360.0;
+ else
+ farEdge = qMin(qreal(360.0), layout.at(i + 1));
+
+ // Adjust the labelCoordinate to show it if next tick is visible
+ if (nextTickVisible)
+ labelCoordinate = qMax(qreal(0.0), labelCoordinate);
+
+ labelCoordinate = (labelCoordinate + farEdge) / 2.0;
+ }
+
+ if (labelCoordinate < 0.0 || labelCoordinate > 360.0)
+ labelVisible = false;
+ else
+ labelVisible = true;
+
+ if (!labelVisible) {
+ i++;
+ continue;
+ }
+
+ QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(), labelList.at(i), axis()->labelsAngle());
+ QPointF labelPoint = QLineF::fromPolar(radius + tickWidth(), 90.0 - labelCoordinate).p2();
+
+ boundingRect = moveLabelToPosition(labelCoordinate, labelPoint, boundingRect);
+ QRectF intersectRect = maxRect.intersected(boundingRect);
+ if (boundingRect.isEmpty() || intersectRect == boundingRect) {
+ i++;
+ } else {
+ qreal reduction(0.0);
+ // If there is no intersection, reduce by smallest dimension of label rect to be on the safe side
+ if (intersectRect.isEmpty()) {
+ reduction = qMin(boundingRect.height(), boundingRect.width());
+ } else {
+ // Approximate needed radius reduction is the amount label rect exceeds max rect in either dimension.
+ // Could be further optimized by figuring out the proper math how to calculate exact needed reduction.
+ reduction = qMax(boundingRect.height() - intersectRect.height(),
+ boundingRect.width() - intersectRect.width());
+ }
+ // Typically the approximated reduction is little low, so add one
+ radius -= (reduction + 1.0);
+
+ if (radius < 1.0) // safeguard
+ return 1.0;
+ }
+ }
+ }
+
+ if (!axis()->titleText().isEmpty() && axis()->isTitleVisible()) {
+ QRectF titleRect = ChartPresenter::textBoundingRect(axis()->titleFont(), axis()->titleText());
+
+ radius -= titlePadding() + (titleRect.height() / 2.0);
+ if (radius < 1.0) // safeguard
+ return 1.0;
+ }
+
+ return radius;
+}
+
+QRectF PolarChartAxisAngular::moveLabelToPosition(qreal angularCoordinate, QPointF labelPoint, QRectF labelRect) const
+{
+ if (angularCoordinate == 0.0)
+ labelRect.moveCenter(labelPoint + QPointF(0, -labelRect.height() / 2.0));
+ else if (angularCoordinate < 90.0)
+ labelRect.moveBottomLeft(labelPoint);
+ else if (angularCoordinate == 90.0)
+ labelRect.moveCenter(labelPoint + QPointF(labelRect.width() / 2.0 + 2.0, 0)); // +2 so that it does not hit the radial axis
+ else if (angularCoordinate < 180.0)
+ labelRect.moveTopLeft(labelPoint);
+ else if (angularCoordinate == 180.0)
+ labelRect.moveCenter(labelPoint + QPointF(0, labelRect.height() / 2.0));
+ else if (angularCoordinate < 270.0)
+ labelRect.moveTopRight(labelPoint);
+ else if (angularCoordinate == 270.0)
+ labelRect.moveCenter(labelPoint + QPointF(-labelRect.width() / 2.0 - 2.0, 0)); // -2 so that it does not hit the radial axis
+ else if (angularCoordinate < 360.0)
+ labelRect.moveBottomRight(labelPoint);
+ else
+ labelRect.moveCenter(labelPoint + QPointF(0, -labelRect.height() / 2.0));
+ return labelRect;
+}
+
+#include "moc_polarchartaxisangular_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/polarchartaxisangular_p.h b/src/charts/axis/polarchartaxisangular_p.h
new file mode 100644
index 00000000..dd83cba7
--- /dev/null
+++ b/src/charts/axis/polarchartaxisangular_p.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 POLARCHARTAXISANGULAR_P_H
+#define POLARCHARTAXISANGULAR_P_H
+
+#include "polarchartaxis_p.h"
+#include "qvalueaxis.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class PolarChartAxisAngular : public PolarChartAxis
+{
+ Q_OBJECT
+public:
+ PolarChartAxisAngular(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis = false);
+ ~PolarChartAxisAngular();
+
+ Qt::Orientation orientation() const;
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
+
+ virtual void updateGeometry();
+ virtual void createItems(int count);
+
+ qreal preferredAxisRadius(const QSizeF &maxSize);
+
+public Q_SLOTS:
+ virtual void handleArrowPenChanged(const QPen &pen);
+ virtual void handleGridPenChanged(const QPen &pen);
+
+private:
+ QRectF moveLabelToPosition(qreal angularCoordinate, QPointF labelPoint, QRectF labelRect) const;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // POLARCHARTAXISANGULAR_P_H
diff --git a/src/charts/axis/polarchartaxisradial.cpp b/src/charts/axis/polarchartaxisradial.cpp
new file mode 100644
index 00000000..93bf1bd9
--- /dev/null
+++ b/src/charts/axis/polarchartaxisradial.cpp
@@ -0,0 +1,297 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "polarchartaxisradial_p.h"
+#include "chartpresenter_p.h"
+#include "abstractchartlayout_p.h"
+#include "qabstractaxis_p.h"
+#include "linearrowitem_p.h"
+#include <QTextDocument>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+PolarChartAxisRadial::PolarChartAxisRadial(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
+ : PolarChartAxis(axis, item, intervalAxis)
+{
+}
+
+PolarChartAxisRadial::~PolarChartAxisRadial()
+{
+}
+
+void PolarChartAxisRadial::updateGeometry()
+{
+ const QVector<qreal> &layout = this->layout();
+ if (layout.isEmpty())
+ return;
+
+ createAxisLabels(layout);
+ QStringList labelList = labels();
+ QPointF center = axisGeometry().center();
+ QList<QGraphicsItem *> arrowItemList = arrowItems();
+ QList<QGraphicsItem *> gridItemList = gridItems();
+ QList<QGraphicsItem *> labelItemList = labelItems();
+ QList<QGraphicsItem *> shadeItemList = shadeItems();
+ QGraphicsTextItem* title = titleItem();
+ qreal radius = axisGeometry().height() / 2.0;
+
+ QLineF line(center, center + QPointF(0, -radius));
+ QGraphicsLineItem *axisLine = static_cast<QGraphicsLineItem *>(arrowItemList.at(0));
+ axisLine->setLine(line);
+
+ QRectF previousLabelRect;
+ bool firstShade = true;
+ bool nextTickVisible = false;
+ if (layout.size())
+ nextTickVisible = !(layout.at(0) < 0.0 || layout.at(0) > radius);
+
+ for (int i = 0; i < layout.size(); ++i) {
+ qreal radialCoordinate = layout.at(i);
+
+ QGraphicsEllipseItem *gridItem = static_cast<QGraphicsEllipseItem *>(gridItemList.at(i));
+ QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem *>(arrowItemList.at(i + 1));
+ QGraphicsTextItem *labelItem = static_cast<QGraphicsTextItem *>(labelItemList.at(i));
+ QGraphicsPathItem *shadeItem = 0;
+ if (i == 0)
+ shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0));
+ else if (i % 2)
+ shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at((i / 2) + 1));
+
+ // Ignore ticks outside valid range
+ bool currentTickVisible = nextTickVisible;
+ if ((i == layout.size() - 1)
+ || layout.at(i + 1) < 0.0
+ || layout.at(i + 1) > radius) {
+ nextTickVisible = false;
+ } else {
+ nextTickVisible = true;
+ }
+
+ qreal labelCoordinate = radialCoordinate;
+ qreal labelVisible = currentTickVisible;
+ qreal labelPad = labelPadding() / 2.0;
+ if (intervalAxis()) {
+ qreal farEdge;
+ if (i == (layout.size() - 1))
+ farEdge = radius;
+ else
+ farEdge = qMin(radius, layout.at(i + 1));
+
+ // Adjust the labelCoordinate to show it if next tick is visible
+ if (nextTickVisible)
+ labelCoordinate = qMax(qreal(0.0), labelCoordinate);
+
+ labelCoordinate = (labelCoordinate + farEdge) / 2.0;
+ if (labelCoordinate > 0.0 && labelCoordinate < radius)
+ labelVisible = true;
+ else
+ labelVisible = false;
+ }
+
+ // Radial axis label
+ if (axis()->labelsVisible() && labelVisible) {
+ QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(),
+ labelList.at(i),
+ axis()->labelsAngle());
+ labelItem->setTextWidth(boundingRect.width());
+ labelItem->setHtml(labelList.at(i));
+ QRectF labelRect = labelItem->boundingRect();
+ QPointF labelCenter = labelRect.center();
+ labelItem->setTransformOriginPoint(labelCenter.x(), labelCenter.y());
+ boundingRect.moveCenter(labelCenter);
+ QPointF positionDiff(labelRect.topLeft() - boundingRect.topLeft());
+ QPointF labelPoint = center;
+ if (intervalAxis())
+ labelPoint += QPointF(labelPad, -labelCoordinate - (boundingRect.height() / 2.0));
+ else
+ labelPoint += QPointF(labelPad, labelPad - labelCoordinate);
+ labelRect.moveTopLeft(labelPoint);
+ labelItem->setPos(labelRect.topLeft() + positionDiff);
+
+ // Label overlap detection
+ labelRect.setSize(boundingRect.size());
+ if ((i && previousLabelRect.intersects(labelRect))
+ || !axisGeometry().contains(labelRect)) {
+ labelVisible = false;
+ } else {
+ previousLabelRect = labelRect;
+ labelVisible = true;
+ }
+ }
+
+ labelItem->setVisible(labelVisible);
+ if (!currentTickVisible) {
+ gridItem->setVisible(false);
+ tickItem->setVisible(false);
+ if (shadeItem)
+ shadeItem->setVisible(false);
+ continue;
+ }
+
+ // Radial grid line
+ QRectF gridRect;
+ gridRect.setWidth(radialCoordinate * 2.0);
+ gridRect.setHeight(radialCoordinate * 2.0);
+ gridRect.moveCenter(center);
+
+ gridItem->setRect(gridRect);
+ gridItem->setVisible(true);
+
+ // Tick
+ QLineF tickLine(-tickWidth(), 0.0, tickWidth(), 0.0);
+ tickLine.translate(center.rx(), gridRect.top());
+ tickItem->setLine(tickLine);
+ tickItem->setVisible(true);
+
+ // Shades
+ if (i % 2 || (i == 0 && !nextTickVisible)) {
+ QPainterPath path;
+ if (i == 0) {
+ // If first tick is also the last, we need to custom fill the inner circle
+ // or it won't get filled.
+ QRectF innerCircle(0.0, 0.0, layout.at(0) * 2.0, layout.at(0) * 2.0);
+ innerCircle.moveCenter(center);
+ path.addEllipse(innerCircle);
+ } else {
+ QRectF otherGridRect;
+ if (!nextTickVisible) { // Last visible tick
+ otherGridRect = axisGeometry();
+ } else {
+ qreal otherGridRectDimension = layout.at(i + 1) * 2.0;
+ otherGridRect.setWidth(otherGridRectDimension);
+ otherGridRect.setHeight(otherGridRectDimension);
+ otherGridRect.moveCenter(center);
+ }
+ path.addEllipse(gridRect);
+ path.addEllipse(otherGridRect);
+
+ // Add additional shading in first visible shade item if there is a partial tick
+ // to be filled at the center (log & category axes)
+ if (firstShade) {
+ QGraphicsPathItem *specialShadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0));
+ if (layout.at(i - 1) > 0.0) {
+ QRectF innerCircle(0.0, 0.0, layout.at(i - 1) * 2.0, layout.at(i - 1) * 2.0);
+ innerCircle.moveCenter(center);
+ QPainterPath specialPath;
+ specialPath.addEllipse(innerCircle);
+ specialShadeItem->setPath(specialPath);
+ specialShadeItem->setVisible(true);
+ } else {
+ specialShadeItem->setVisible(false);
+ }
+ }
+ }
+ shadeItem->setPath(path);
+ shadeItem->setVisible(true);
+ firstShade = false;
+ }
+ }
+
+ // Title, along the 0 axis
+ QString titleText = axis()->titleText();
+ if (!titleText.isEmpty() && axis()->isTitleVisible()) {
+ QRectF truncatedRect;
+ title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(0.0),
+ radius, radius, truncatedRect));
+ title->setTextWidth(truncatedRect.width());
+
+ QRectF titleBoundingRect = title->boundingRect();
+ QPointF titleCenter = titleBoundingRect.center();
+ QPointF arrowCenter = axisLine->boundingRect().center();
+ QPointF titleCenterDiff = arrowCenter - titleCenter;
+ title->setPos(titleCenterDiff.x() - titlePadding() - (titleBoundingRect.height() / 2.0), titleCenterDiff.y());
+ title->setTransformOriginPoint(titleCenter);
+ title->setRotation(270.0);
+ }
+
+ QGraphicsLayoutItem::updateGeometry();
+}
+
+Qt::Orientation PolarChartAxisRadial::orientation() const
+{
+ return Qt::Vertical;
+}
+
+void PolarChartAxisRadial::createItems(int count)
+{
+ if (arrowItems().count() == 0) {
+ // radial axis center line
+ QGraphicsLineItem *arrow = new LineArrowItem(this, presenter()->rootItem());
+ arrow->setPen(axis()->linePen());
+ arrowGroup()->addToGroup(arrow);
+ }
+
+ QGraphicsTextItem *title = titleItem();
+ title->setFont(axis()->titleFont());
+ title->setDefaultTextColor(axis()->titleBrush().color());
+ title->setHtml(axis()->titleText());
+
+ for (int i = 0; i < count; ++i) {
+ QGraphicsLineItem *arrow = new QGraphicsLineItem(presenter()->rootItem());
+ QGraphicsEllipseItem *grid = new QGraphicsEllipseItem(presenter()->rootItem());
+ QGraphicsTextItem *label = new QGraphicsTextItem(presenter()->rootItem());
+ label->document()->setDocumentMargin(ChartPresenter::textMargin());
+ arrow->setPen(axis()->linePen());
+ grid->setPen(axis()->gridLinePen());
+ label->setFont(axis()->labelsFont());
+ label->setDefaultTextColor(axis()->labelsBrush().color());
+ label->setRotation(axis()->labelsAngle());
+ arrowGroup()->addToGroup(arrow);
+ gridGroup()->addToGroup(grid);
+ labelGroup()->addToGroup(label);
+ if (gridItems().size() == 1 || (((gridItems().size() + 1) % 2) && gridItems().size() > 0)) {
+ QGraphicsPathItem *shade = new QGraphicsPathItem(presenter()->rootItem());
+ shade->setPen(axis()->shadesPen());
+ shade->setBrush(axis()->shadesBrush());
+ shadeGroup()->addToGroup(shade);
+ }
+ }
+}
+
+void PolarChartAxisRadial::handleArrowPenChanged(const QPen &pen)
+{
+ foreach (QGraphicsItem *item, arrowItems())
+ static_cast<QGraphicsLineItem *>(item)->setPen(pen);
+}
+
+void PolarChartAxisRadial::handleGridPenChanged(const QPen &pen)
+{
+ foreach (QGraphicsItem *item, gridItems())
+ static_cast<QGraphicsEllipseItem *>(item)->setPen(pen);
+}
+
+QSizeF PolarChartAxisRadial::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED(which);
+ Q_UNUSED(constraint);
+ return QSizeF(-1.0, -1.0);
+}
+
+qreal PolarChartAxisRadial::preferredAxisRadius(const QSizeF &maxSize)
+{
+ qreal radius = maxSize.height() / 2.0;
+ if (maxSize.width() < maxSize.height())
+ radius = maxSize.width() / 2.0;
+ return radius;
+}
+
+#include "moc_polarchartaxisradial_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/polarchartaxisradial_p.h b/src/charts/axis/polarchartaxisradial_p.h
new file mode 100644
index 00000000..6ce21513
--- /dev/null
+++ b/src/charts/axis/polarchartaxisradial_p.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 POLARCHARTAXISRADIAL_P_H
+#define POLARCHARTAXISRADIAL_P_H
+
+#include "polarchartaxis_p.h"
+#include "qvalueaxis.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class PolarChartAxisRadial : public PolarChartAxis
+{
+ Q_OBJECT
+public:
+ PolarChartAxisRadial(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis = false);
+ ~PolarChartAxisRadial();
+
+ Qt::Orientation orientation() const;
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
+
+ virtual void updateGeometry();
+ virtual void createItems(int count);
+
+ qreal preferredAxisRadius(const QSizeF &maxSize);
+
+public Q_SLOTS:
+ virtual void handleArrowPenChanged(const QPen &pen);
+ virtual void handleGridPenChanged(const QPen &pen);
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // POLARCHARTAXISRADIAL_P_H
diff --git a/src/charts/axis/qabstractaxis.cpp b/src/charts/axis/qabstractaxis.cpp
new file mode 100644
index 00000000..ff7c27b6
--- /dev/null
+++ b/src/charts/axis/qabstractaxis.cpp
@@ -0,0 +1,1012 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qabstractaxis.h"
+#include "qabstractaxis_p.h"
+#include "chartdataset_p.h"
+#include "charttheme_p.h"
+#include "qchart_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QAbstractAxis
+ \inmodule Qt Charts
+ \brief The QAbstractAxis class is used for manipulating chart's axis.
+ \mainclass
+
+ Each series can be bound to one or more horizontal and vertical axes, but mixing axis types
+ that would result in different domains is not supported, such as specifying
+ QValueAxis and QLogValueAxis on the same orientation.
+
+ Properties and visibility of various axis elements such as axis line, title, labels, grid lines,
+ and shades can be individually controlled.
+*/
+/*!
+ \qmltype AbstractAxis
+ \instantiates QAbstractAxis
+ \inqmlmodule QtCharts
+
+ \brief The AbstractAxis is a base element used for specialized axis elements.
+
+ Each series can be bound to only one horizontal and vertical axis.
+
+ Properties and visibility of various axis elements such as axis line, title, labels, grid lines,
+ and shades can be individually controlled.
+*/
+
+/*!
+ \enum QAbstractAxis::AxisType
+
+ The type of the series object.
+
+ \value AxisTypeNoAxis
+ \value AxisTypeValue
+ \value AxisTypeBarCategory
+ \value AxisTypeCategory
+ \value AxisTypeDateTime
+ \value AxisTypeLogValue
+*/
+
+/*!
+ *\fn void QAbstractAxis::type() const
+ Returns the type of the axis
+*/
+
+/*!
+ \property QAbstractAxis::lineVisible
+ The visibility of the axis line
+*/
+/*!
+ \qmlproperty bool AbstractAxis::lineVisible
+ The visibility of the axis line
+*/
+
+/*!
+ \property QAbstractAxis::linePen
+ The pen of the line.
+*/
+
+/*!
+ \property QAbstractAxis::labelsVisible
+ Defines if axis labels are visible.
+*/
+/*!
+ \qmlproperty bool AbstractAxis::labelsVisible
+ Defines if axis labels are visible.
+*/
+
+/*!
+ \property QAbstractAxis::labelsPen
+ \deprecated
+ The pen of the labels.
+*/
+
+/*!
+ \property QAbstractAxis::labelsBrush
+ The brush of the labels. Only the color of the brush is relevant.
+*/
+
+/*!
+ \property QAbstractAxis::visible
+ The visibility of the axis.
+*/
+/*!
+ \qmlproperty bool AbstractAxis::visible
+ The visibility of the axis.
+*/
+
+/*!
+ \property QAbstractAxis::gridVisible
+ The visibility of the grid lines.
+*/
+/*!
+ \qmlproperty bool AbstractAxis::gridVisible
+ The visibility of the grid lines.
+*/
+
+/*!
+ \property QAbstractAxis::color
+ The color of the axis and ticks.
+*/
+/*!
+ \qmlproperty color AbstractAxis::color
+ The color of the axis and ticks.
+*/
+
+/*!
+ \property QAbstractAxis::gridLinePen
+ The pen of the grid line.
+*/
+
+/*!
+ \property QAbstractAxis::labelsFont
+ The font of the axis labels.
+*/
+
+/*!
+ \qmlproperty Font AbstractAxis::labelsFont
+ The font of the axis labels.
+
+ See the Qt documentation for more details of Font.
+*/
+
+/*!
+ \property QAbstractAxis::labelsColor
+ The color of the axis labels.
+*/
+/*!
+ \qmlproperty color AbstractAxis::labelsColor
+ The color of the axis labels.
+*/
+
+/*!
+ \property QAbstractAxis::labelsAngle
+ The angle of the axis labels in degrees.
+*/
+/*!
+ \qmlproperty int AbstractAxis::labelsAngle
+ The angle of the axis labels in degrees.
+*/
+
+/*!
+ \property QAbstractAxis::shadesVisible
+ The visibility of the axis shades.
+*/
+/*!
+ \qmlproperty bool AbstractAxis::shadesVisible
+ The visibility of the axis shades.
+*/
+
+/*!
+ \property QAbstractAxis::shadesColor
+ The fill (brush) color of the axis shades.
+*/
+/*!
+ \qmlproperty color AbstractAxis::shadesColor
+ The fill (brush) color of the axis shades.
+*/
+
+/*!
+ \property QAbstractAxis::shadesBorderColor
+ The border (pen) color of the axis shades.
+*/
+/*!
+ \qmlproperty color AbstractAxis::shadesBorderColor
+ The border (pen) color of the axis shades.
+*/
+
+/*!
+ \property QAbstractAxis::shadesPen
+ The pen of the axis shades (area between grid lines).
+*/
+
+/*!
+ \property QAbstractAxis::shadesBrush
+ The brush of the axis shades (area between grid lines).
+*/
+
+/*!
+ \property QAbstractAxis::titleVisible
+ The visibility of the axis title. By default the value is true.
+*/
+/*!
+ \qmlproperty bool AbstractAxis::titleVisible
+ The visibility of the axis title. By default the value is true.
+*/
+
+/*!
+ \property QAbstractAxis::titleText
+ The title of the axis. Empty by default. Axis titles support html formatting.
+*/
+/*!
+ \qmlproperty String AbstractAxis::titleText
+ The title of the axis. Empty by default. Axis titles support html formatting.
+*/
+
+/*!
+ \property QAbstractAxis::titlePen
+ \deprecated
+ The pen of the title text.
+*/
+
+/*!
+ \property QAbstractAxis::titleBrush
+ The brush of the title text. Only the color of the brush is relevant.
+*/
+
+/*!
+ \property QAbstractAxis::titleFont
+ The font of the title of the axis.
+*/
+/*!
+ \qmlproperty Font AbstractAxis::titleFont
+ The font of the title of the axis.
+*/
+
+/*!
+ \property QAbstractAxis::orientation
+ The orientation of the axis. Fixed to either Qt::Horizontal or Qt::Vertical when you add the axis to a chart.
+*/
+/*!
+ \qmlproperty Qt.Orientation AbstractAxis::orientation
+ The orientation of the axis. Fixed to either Qt.Horizontal or Qt.Vertical when the axis is set to a series.
+*/
+
+/*!
+ \property QAbstractAxis::alignment
+ The alignment of the axis. Can be Qt::AlignLeft, Qt::AlignRight, Qt::AlignBottom, or Qt::AlignTop.
+*/
+/*!
+ \qmlproperty alignment AbstractAxis::alignment
+ The alignment of the axis. Can be Qt.AlignLeft, Qt.AlignRight, Qt.AlignBottom, or Qt.AlignTop.
+*/
+
+/*!
+ \fn void QAbstractAxis::visibleChanged(bool visible)
+ Visibility of the axis has changed to \a visible.
+*/
+/*!
+ \qmlsignal AbstractAxis::onVisibleChanged(bool visible)
+ Visibility of the axis has changed to \a visible.
+*/
+
+/*!
+ \fn void QAbstractAxis::linePenChanged(const QPen& pen)
+ The pen of the line of the axis has changed to \a pen.
+*/
+
+/*!
+ \fn void QAbstractAxis::lineVisibleChanged(bool visible)
+ Visibility of the axis line has changed to \a visible.
+*/
+/*!
+ \qmlsignal AbstractAxis::onLineVisibleChanged(bool visible)
+ Visibility of the axis line has changed to \a visible.
+*/
+
+/*!
+ \fn void QAbstractAxis::labelsVisibleChanged(bool visible)
+ Visibility of the labels of the axis has changed to \a visible.
+*/
+/*!
+ \qmlsignal AbstractAxis::onLabelsVisibleChanged(bool visible)
+ Visibility of the labels of the axis has changed to \a visible.
+*/
+
+/*!
+ \fn void QAbstractAxis::labelsFontChanged(const QFont& font)
+ The font of the axis labels has changed to \a font.
+*/
+/*!
+ \qmlsignal AbstractAxis::onLabelsFontChanged(Font font)
+ The font of the axis labels has changed to \a font.
+*/
+
+/*!
+ \fn void QAbstractAxis::labelsPenChanged(const QPen& pen)
+ \deprecated
+ The pen of the axis labels has changed to \a pen.
+*/
+
+/*!
+ \fn void QAbstractAxis::labelsBrushChanged(const QBrush& brush)
+ The brush of the axis labels has changed to \a brush.
+*/
+
+/*!
+ \fn void QAbstractAxis::labelsAngleChanged(int angle)
+ The angle of the axis labels has changed to \a angle.
+*/
+/*!
+ \qmlsignal AbstractAxis::onLabelsAngleChanged(int angle)
+ The angle of the axis labels has changed to \a angle.
+*/
+
+/*!
+ \fn void QAbstractAxis::gridVisibleChanged(bool visible)
+ Visibility of the grid lines of the axis has changed to \a visible.
+*/
+/*!
+ \qmlsignal AbstractAxis::onGridVisibleChanged(bool visible)
+ Visibility of the grid lines of the axis has changed to \a visible.
+*/
+
+/*!
+ \fn void QAbstractAxis::gridLinePenChanged(const QPen& pen)
+ The pen of the grid line has changed to \a pen.
+*/
+
+/*!
+ \fn void QAbstractAxis::colorChanged(QColor color)
+ Emitted if the \a color of the axis is changed.
+*/
+/*!
+ \qmlsignal AbstractAxis::onColorChanged(QColor color)
+ Emitted if the \a color of the axis is changed.
+*/
+
+/*!
+ \fn void QAbstractAxis::labelsColorChanged(QColor color)
+ Emitted if the \a color of the axis labels is changed.
+*/
+/*!
+ \qmlsignal AbstractAxis::onLabelsColorChanged(QColor color)
+ Emitted if the \a color of the axis labels is changed.
+*/
+
+/*!
+ \fn void QAbstractAxis::titleVisibleChanged(bool visible)
+ Visibility of the title text of the axis has changed to \a visible.
+*/
+/*!
+ \qmlsignal AbstractAxis::onTitleVisibleChanged(bool visible)
+ Visibility of the title text of the axis has changed to \a visible.
+*/
+
+/*!
+ \fn void QAbstractAxis::titleTextChanged(const QString& text)
+ The text of the axis title has changed to \a text.
+*/
+/*!
+ \qmlsignal AbstractAxis::onTitleTextChanged(String text)
+ The text of the axis title has changed to \a text.
+*/
+
+/*!
+ \fn void QAbstractAxis::titlePenChanged(const QPen& pen)
+ \deprecated
+ The pen of the axis shades has changed to \a pen.
+*/
+
+/*!
+ \fn void QAbstractAxis::titleBrushChanged(const QBrush& brush)
+ The brush of the axis title has changed to \a brush.
+*/
+
+/*!
+ \fn void QAbstractAxis::titleFontChanged(const QFont& font)
+ The font of the axis title has changed to \a font.
+*/
+/*!
+ \qmlsignal AbstractAxis::onTitleFontChanged(Font font)
+ The font of the axis title has changed to \a font.
+*/
+
+/*!
+ \fn void QAbstractAxis::shadesVisibleChanged(bool)
+ Emitted if the visibility of the axis shades is changed to \a visible.
+*/
+/*!
+ \qmlsignal AbstractAxis::onShadesVisibleChanged(bool visible)
+ Emitted if the visibility of the axis shades is changed to \a visible.
+*/
+
+/*!
+ \fn void QAbstractAxis::shadesColorChanged(QColor color)
+ Emitted if the \a color of the axis shades is changed.
+*/
+/*!
+ \qmlsignal AbstractAxis::onShadesColorChanged(QColor color)
+ Emitted if the \a color of the axis shades is changed.
+*/
+
+/*!
+ \fn void QAbstractAxis::shadesBorderColorChanged(QColor)
+ Emitted if the border \a color of the axis shades is changed.
+*/
+/*!
+ \qmlsignal AbstractAxis::onBorderColorChanged(QColor color)
+ Emitted if the border \a color of the axis shades is changed.
+*/
+
+/*!
+ \fn void QAbstractAxis::shadesBrushChanged(const QBrush& brush)
+ The brush of the axis shades has changed to \a brush.
+*/
+
+/*!
+ \fn void QAbstractAxis::shadesPenChanged(const QPen& pen)
+ The pen of the axis shades has changed to \a pen.
+*/
+
+/*!
+ \internal
+ Constructs new axis object which is a child of \a parent. Ownership is taken by
+ QChart when axis added.
+*/
+
+QAbstractAxis::QAbstractAxis(QAbstractAxisPrivate &d, QObject *parent)
+ : QObject(parent),
+ d_ptr(&d)
+{
+}
+
+/*!
+ Destructor of the axis object. When axis is added to chart, chart object takes ownership.
+*/
+
+QAbstractAxis::~QAbstractAxis()
+{
+ if (d_ptr->m_chart)
+ qFatal("Still binded axis detected !");
+}
+
+/*!
+ Sets \a pen used to draw axis line and ticks.
+ */
+void QAbstractAxis::setLinePen(const QPen &pen)
+{
+ if (d_ptr->m_axisPen != pen) {
+ d_ptr->m_axisPen = pen;
+ emit linePenChanged(pen);
+ }
+}
+
+/*!
+ Returns pen used to draw axis and ticks.
+*/
+QPen QAbstractAxis::linePen() const
+{
+ if (d_ptr->m_axisPen == QChartPrivate::defaultPen())
+ return QPen();
+ else
+ return d_ptr->m_axisPen;
+}
+
+void QAbstractAxis::setLinePenColor(QColor color)
+{
+ QPen p = d_ptr->m_axisPen;
+ if (p.color() != color) {
+ p.setColor(color);
+ setLinePen(p);
+ emit colorChanged(color);
+ }
+}
+
+QColor QAbstractAxis::linePenColor() const
+{
+ return linePen().color();
+}
+
+/*!
+ Sets if axis and ticks are \a visible.
+ */
+void QAbstractAxis::setLineVisible(bool visible)
+{
+ if (d_ptr->m_arrowVisible != visible) {
+ d_ptr->m_arrowVisible = visible;
+ emit lineVisibleChanged(visible);
+ }
+}
+
+bool QAbstractAxis::isLineVisible() const
+{
+ return d_ptr->m_arrowVisible;
+}
+
+void QAbstractAxis::setGridLineVisible(bool visible)
+{
+ if (d_ptr->m_gridLineVisible != visible) {
+ d_ptr->m_gridLineVisible = visible;
+ emit gridVisibleChanged(visible);
+ }
+}
+
+bool QAbstractAxis::isGridLineVisible() const
+{
+ return d_ptr->m_gridLineVisible;
+}
+
+/*!
+ Sets \a pen used to draw grid line.
+*/
+void QAbstractAxis::setGridLinePen(const QPen &pen)
+{
+ if (d_ptr->m_gridLinePen != pen) {
+ d_ptr->m_gridLinePen = pen;
+ emit gridLinePenChanged(pen);
+ }
+}
+
+/*!
+ Returns pen used to draw grid.
+*/
+QPen QAbstractAxis::gridLinePen() const
+{
+ if (d_ptr->m_gridLinePen == QChartPrivate::defaultPen())
+ return QPen();
+ else
+ return d_ptr->m_gridLinePen;
+}
+
+void QAbstractAxis::setLabelsVisible(bool visible)
+{
+ if (d_ptr->m_labelsVisible != visible) {
+ d_ptr->m_labelsVisible = visible;
+ emit labelsVisibleChanged(visible);
+ }
+}
+
+bool QAbstractAxis::labelsVisible() const
+{
+ return d_ptr->m_labelsVisible;
+}
+
+void QAbstractAxis::setLabelsPen(const QPen &pen)
+{
+ if (d_ptr->m_labelsPen != pen) {
+ d_ptr->m_labelsPen = pen;
+ emit labelsPenChanged(pen);
+ }
+}
+
+QPen QAbstractAxis::labelsPen() const
+{
+ if (d_ptr->m_labelsPen == QChartPrivate::defaultPen())
+ return QPen();
+ else
+ return d_ptr->m_labelsPen;
+}
+
+/*!
+ Sets \a brush used to draw labels.
+ */
+void QAbstractAxis::setLabelsBrush(const QBrush &brush)
+{
+ if (d_ptr->m_labelsBrush != brush) {
+ d_ptr->m_labelsBrush = brush;
+ emit labelsBrushChanged(brush);
+ }
+}
+
+/*!
+ Returns brush used to draw labels.
+*/
+QBrush QAbstractAxis::labelsBrush() const
+{
+ if (d_ptr->m_labelsBrush == QChartPrivate::defaultBrush())
+ return QBrush();
+ else
+ return d_ptr->m_labelsBrush;
+}
+
+/*!
+ Sets \a font used to draw labels.
+*/
+void QAbstractAxis::setLabelsFont(const QFont &font)
+{
+ if (d_ptr->m_labelsFont != font) {
+ d_ptr->m_labelsFont = font;
+ emit labelsFontChanged(font);
+ }
+}
+
+/*!
+ Returns font used to draw labels.
+*/
+QFont QAbstractAxis::labelsFont() const
+{
+ if (d_ptr->m_labelsFont == QChartPrivate::defaultFont())
+ return QFont();
+ else
+ return d_ptr->m_labelsFont;
+}
+
+void QAbstractAxis::setLabelsAngle(int angle)
+{
+ if (d_ptr->m_labelsAngle != angle) {
+ d_ptr->m_labelsAngle = angle;
+ emit labelsAngleChanged(angle);
+ }
+}
+
+int QAbstractAxis::labelsAngle() const
+{
+ return d_ptr->m_labelsAngle;
+}
+void QAbstractAxis::setLabelsColor(QColor color)
+{
+ QBrush b = d_ptr->m_labelsBrush;
+ if (b.color() != color) {
+ b.setColor(color);
+ setLabelsBrush(b);
+ emit labelsColorChanged(color);
+ }
+}
+
+QColor QAbstractAxis::labelsColor() const
+{
+ return labelsBrush().color();
+}
+
+void QAbstractAxis::setTitleVisible(bool visible)
+{
+ if (d_ptr->m_titleVisible != visible) {
+ d_ptr->m_titleVisible = visible;
+ emit titleVisibleChanged(visible);
+ }
+}
+
+bool QAbstractAxis::isTitleVisible() const
+{
+ return d_ptr->m_titleVisible;
+}
+
+void QAbstractAxis::setTitlePen(const QPen &pen)
+{
+ if (d_ptr->m_titlePen != pen) {
+ d_ptr->m_titlePen = pen;
+ emit titlePenChanged(pen);
+ }
+}
+
+QPen QAbstractAxis::titlePen() const
+{
+ if (d_ptr->m_titlePen == QChartPrivate::defaultPen())
+ return QPen();
+ else
+ return d_ptr->m_titlePen;
+}
+
+/*!
+ Sets \a brush used to draw title.
+ */
+void QAbstractAxis::setTitleBrush(const QBrush &brush)
+{
+ if (d_ptr->m_titleBrush != brush) {
+ d_ptr->m_titleBrush = brush;
+ emit titleBrushChanged(brush);
+ }
+}
+
+/*!
+ Returns brush used to draw title.
+*/
+QBrush QAbstractAxis::titleBrush() const
+{
+ if (d_ptr->m_titleBrush == QChartPrivate::defaultBrush())
+ return QBrush();
+ else
+ return d_ptr->m_titleBrush;
+}
+
+/*!
+ Sets \a font used to draw title.
+*/
+void QAbstractAxis::setTitleFont(const QFont &font)
+{
+ if (d_ptr->m_titleFont != font) {
+ d_ptr->m_titleFont = font;
+ emit titleFontChanged(font);
+ }
+}
+
+/*!
+ Returns font used to draw title.
+*/
+QFont QAbstractAxis::titleFont() const
+{
+ if (d_ptr->m_titleFont == QChartPrivate::defaultFont())
+ return QFont();
+ else
+ return d_ptr->m_titleFont;
+}
+
+void QAbstractAxis::setTitleText(const QString &title)
+{
+ if (d_ptr->m_title != title) {
+ d_ptr->m_title = title;
+ emit titleTextChanged(title);
+ }
+}
+
+QString QAbstractAxis::titleText() const
+{
+ return d_ptr->m_title;
+}
+
+
+void QAbstractAxis::setShadesVisible(bool visible)
+{
+ if (d_ptr->m_shadesVisible != visible) {
+ d_ptr->m_shadesVisible = visible;
+ emit shadesVisibleChanged(visible);
+ }
+}
+
+bool QAbstractAxis::shadesVisible() const
+{
+ return d_ptr->m_shadesVisible;
+}
+
+/*!
+ Sets \a pen used to draw shades.
+*/
+void QAbstractAxis::setShadesPen(const QPen &pen)
+{
+ if (d_ptr->m_shadesPen != pen) {
+ d_ptr->m_shadesPen = pen;
+ emit shadesPenChanged(pen);
+ }
+}
+
+/*!
+ Returns pen used to draw shades.
+*/
+QPen QAbstractAxis::shadesPen() const
+{
+ if (d_ptr->m_shadesPen == QChartPrivate::defaultPen())
+ return QPen();
+ else
+ return d_ptr->m_shadesPen;
+}
+
+/*!
+ Sets \a brush used to draw shades.
+*/
+void QAbstractAxis::setShadesBrush(const QBrush &brush)
+{
+ if (d_ptr->m_shadesBrush != brush) {
+ d_ptr->m_shadesBrush = brush;
+ emit shadesBrushChanged(brush);
+ }
+}
+
+/*!
+ Returns brush used to draw shades.
+*/
+QBrush QAbstractAxis::shadesBrush() const
+{
+ if (d_ptr->m_shadesBrush == QChartPrivate::defaultBrush())
+ return QBrush(Qt::SolidPattern);
+ else
+ return d_ptr->m_shadesBrush;
+}
+
+void QAbstractAxis::setShadesColor(QColor color)
+{
+ QBrush b = d_ptr->m_shadesBrush;
+ if (b.color() != color) {
+ b.setColor(color);
+ setShadesBrush(b);
+ emit shadesColorChanged(color);
+ }
+}
+
+QColor QAbstractAxis::shadesColor() const
+{
+ return shadesBrush().color();
+}
+
+void QAbstractAxis::setShadesBorderColor(QColor color)
+{
+ QPen p = d_ptr->m_shadesPen;
+ if (p.color() != color) {
+ p.setColor(color);
+ setShadesPen(p);
+ emit shadesColorChanged(color);
+ }
+}
+
+QColor QAbstractAxis::shadesBorderColor() const
+{
+ return shadesPen().color();
+}
+
+
+bool QAbstractAxis::isVisible() const
+{
+ return d_ptr->m_visible;
+}
+
+/*!
+ Sets axis, shades, labels and grid lines to be visible.
+*/
+void QAbstractAxis::setVisible(bool visible)
+{
+ if (d_ptr->m_visible != visible) {
+ d_ptr->m_visible = visible;
+ emit visibleChanged(visible);
+ }
+}
+
+
+/*!
+ Sets axis, shades, labels and grid lines to be visible.
+*/
+void QAbstractAxis::show()
+{
+ setVisible(true);
+}
+
+/*!
+ Sets axis, shades, labels and grid lines to not be visible.
+*/
+void QAbstractAxis::hide()
+{
+ setVisible(false);
+}
+
+/*!
+ Sets the minimum value shown on the axis.
+ Depending on the actual axis type the \a min parameter is converted to appropriate type.
+ If the conversion is impossible then the function call does nothing
+*/
+void QAbstractAxis::setMin(const QVariant &min)
+{
+ d_ptr->setMin(min);
+}
+
+/*!
+ Sets the maximum value shown on the axis.
+ Depending on the actual axis type the \a max parameter is converted to appropriate type.
+ If the conversion is impossible then the function call does nothing
+*/
+void QAbstractAxis::setMax(const QVariant &max)
+{
+ d_ptr->setMax(max);
+}
+
+/*!
+ Sets the range shown on the axis.
+ Depending on the actual axis type the \a min and \a max parameters are converted to appropriate types.
+ If the conversion is impossible then the function call does nothing.
+*/
+void QAbstractAxis::setRange(const QVariant &min, const QVariant &max)
+{
+ d_ptr->setRange(min, max);
+}
+
+
+/*!
+ Returns the orientation in which the axis is being used (Vertical or Horizontal)
+*/
+Qt::Orientation QAbstractAxis::orientation()
+{
+ return d_ptr->orientation();
+}
+
+Qt::Alignment QAbstractAxis::alignment() const
+{
+ return d_ptr->alignment();
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QAbstractAxisPrivate::QAbstractAxisPrivate(QAbstractAxis *q)
+ : q_ptr(q),
+ m_chart(0),
+ m_alignment(0),
+ m_orientation(Qt::Orientation(0)),
+ m_visible(true),
+ m_arrowVisible(true),
+ m_axisPen(QChartPrivate::defaultPen()),
+ m_axisBrush(QChartPrivate::defaultBrush()),
+ m_gridLineVisible(true),
+ m_gridLinePen(QChartPrivate::defaultPen()),
+ m_labelsVisible(true),
+ m_labelsPen(QChartPrivate::defaultPen()),
+ m_labelsBrush(QChartPrivate::defaultBrush()),
+ m_labelsFont(QChartPrivate::defaultFont()),
+ m_labelsAngle(0),
+ m_titleVisible(true),
+ m_titlePen(QChartPrivate::defaultPen()),
+ m_titleBrush(QChartPrivate::defaultBrush()),
+ m_titleFont(QChartPrivate::defaultFont()),
+ m_shadesVisible(false),
+ m_shadesPen(QChartPrivate::defaultPen()),
+ m_shadesBrush(QChartPrivate::defaultBrush()),
+ m_shadesOpacity(1.0),
+ m_dirty(false)
+{
+}
+
+QAbstractAxisPrivate::~QAbstractAxisPrivate()
+{
+}
+
+void QAbstractAxisPrivate::setAlignment( Qt::Alignment alignment)
+{
+ switch(alignment) {
+ case Qt::AlignTop:
+ case Qt::AlignBottom:
+ m_orientation = Qt::Horizontal;
+ break;
+ case Qt::AlignLeft:
+ case Qt::AlignRight:
+ m_orientation = Qt::Vertical;
+ break;
+ default:
+ qWarning()<<"No alignment specified !";
+ break;
+ };
+ m_alignment=alignment;
+}
+
+void QAbstractAxisPrivate::initializeTheme(ChartTheme* theme, bool forced)
+{
+ if (forced || QChartPrivate::defaultPen() == m_axisPen)
+ q_ptr->setLinePen(theme->axisLinePen());
+
+ if (forced || QChartPrivate::defaultPen() == m_gridLinePen)
+ q_ptr->setGridLinePen(theme->girdLinePen());
+
+ if (forced || QChartPrivate::defaultBrush() == m_labelsBrush)
+ q_ptr->setLabelsBrush(theme->labelBrush());
+ if (forced || QChartPrivate::defaultPen() == m_labelsPen)
+ q_ptr->setLabelsPen(Qt::NoPen); // NoPen for performance reasons
+ if (forced || QChartPrivate::defaultFont() == m_labelsFont)
+ q_ptr->setLabelsFont(theme->labelFont());
+
+ if (forced || QChartPrivate::defaultBrush() == m_titleBrush)
+ q_ptr->setTitleBrush(theme->labelBrush());
+ if (forced || QChartPrivate::defaultPen() == m_titlePen)
+ q_ptr->setTitlePen(Qt::NoPen); // NoPen for performance reasons
+ if (forced || QChartPrivate::defaultFont() == m_titleFont) {
+ QFont font(m_labelsFont);
+ font.setBold(true);
+ q_ptr->setTitleFont(font);
+ }
+
+ if (forced || QChartPrivate::defaultBrush() == m_shadesBrush)
+ q_ptr->setShadesBrush(theme->backgroundShadesBrush());
+ if (forced || QChartPrivate::defaultPen() == m_shadesPen)
+ q_ptr->setShadesPen(theme->backgroundShadesPen());
+
+ bool axisX = m_orientation == Qt::Horizontal;
+ if (forced && (theme->backgroundShades() == ChartTheme::BackgroundShadesBoth
+ || (theme->backgroundShades() == ChartTheme::BackgroundShadesVertical && axisX)
+ || (theme->backgroundShades() == ChartTheme::BackgroundShadesHorizontal && !axisX))) {
+ q_ptr->setShadesVisible(true);
+ } else if (forced) {
+ q_ptr->setShadesVisible(false);
+ }
+}
+
+void QAbstractAxisPrivate::handleRangeChanged(qreal min, qreal max)
+{
+ setRange(min,max);
+}
+
+void QAbstractAxisPrivate::initializeGraphics(QGraphicsItem* parent)
+{
+ Q_UNUSED(parent);
+}
+
+void QAbstractAxisPrivate::initializeAnimations(QChart::AnimationOptions options)
+{
+ ChartAxisElement *axis = m_item.data();
+ Q_ASSERT(axis);
+ if (axis->animation())
+ axis->animation()->stopAndDestroyLater();
+
+ if (options.testFlag(QChart::GridAxisAnimations))
+ axis->setAnimation(new AxisAnimation(axis));
+ else
+ axis->setAnimation(0);
+}
+
+
+
+#include "moc_qabstractaxis.cpp"
+#include "moc_qabstractaxis_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/qabstractaxis.h b/src/charts/axis/qabstractaxis.h
new file mode 100644
index 00000000..cbad09e8
--- /dev/null
+++ b/src/charts/axis/qabstractaxis.h
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTAXIS_H
+#define QABSTRACTAXIS_H
+
+#include <QtCharts/qchartglobal.h>
+#include <QPen>
+#include <QFont>
+#include <QVariant>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QAbstractAxisPrivate;
+
+class QT_CHARTS_EXPORT QAbstractAxis : public QObject
+{
+ Q_OBJECT
+ //visibility
+ Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged)
+ //arrow
+ Q_PROPERTY(bool lineVisible READ isLineVisible WRITE setLineVisible NOTIFY lineVisibleChanged)
+ Q_PROPERTY(QPen linePen READ linePen WRITE setLinePen NOTIFY linePenChanged)
+ Q_PROPERTY(QColor color READ linePenColor WRITE setLinePenColor NOTIFY colorChanged)
+ //labels
+ Q_PROPERTY(bool labelsVisible READ labelsVisible WRITE setLabelsVisible NOTIFY labelsVisibleChanged)
+ Q_PROPERTY(QPen labelsPen READ labelsPen WRITE setLabelsPen NOTIFY labelsPenChanged)
+ Q_PROPERTY(QBrush labelsBrush READ labelsBrush WRITE setLabelsBrush NOTIFY labelsBrushChanged)
+ Q_PROPERTY(int labelsAngle READ labelsAngle WRITE setLabelsAngle NOTIFY labelsAngleChanged)
+ Q_PROPERTY(QFont labelsFont READ labelsFont WRITE setLabelsFont NOTIFY labelsFontChanged)
+ Q_PROPERTY(QColor labelsColor READ labelsColor WRITE setLabelsColor NOTIFY labelsColorChanged)
+ //grid
+ Q_PROPERTY(bool gridVisible READ isGridLineVisible WRITE setGridLineVisible NOTIFY gridVisibleChanged)
+ Q_PROPERTY(QPen gridLinePen READ gridLinePen WRITE setGridLinePen NOTIFY gridLinePenChanged)
+ //shades
+ Q_PROPERTY(bool shadesVisible READ shadesVisible WRITE setShadesVisible NOTIFY shadesVisibleChanged)
+ Q_PROPERTY(QColor shadesColor READ shadesColor WRITE setShadesColor NOTIFY shadesColorChanged)
+ Q_PROPERTY(QColor shadesBorderColor READ shadesBorderColor WRITE setShadesBorderColor NOTIFY shadesBorderColorChanged)
+ Q_PROPERTY(QPen shadesPen READ shadesPen WRITE setShadesPen NOTIFY shadesPenChanged)
+ Q_PROPERTY(QBrush shadesBrush READ shadesBrush WRITE setShadesBrush NOTIFY shadesBrushChanged)
+ //title
+ Q_PROPERTY(QString titleText READ titleText WRITE setTitleText NOTIFY titleTextChanged)
+ Q_PROPERTY(QPen titlePen READ titlePen WRITE setTitlePen NOTIFY titlePenChanged)
+ Q_PROPERTY(QBrush titleBrush READ titleBrush WRITE setTitleBrush NOTIFY titleBrushChanged)
+ Q_PROPERTY(bool titleVisible READ isTitleVisible WRITE setTitleVisible NOTIFY titleVisibleChanged)
+ Q_PROPERTY(QFont titleFont READ titleFont WRITE setTitleFont NOTIFY titleFontChanged)
+ //orientation
+ Q_PROPERTY(Qt::Orientation orientation READ orientation)
+ //aligment
+ Q_PROPERTY(Qt::Alignment alignment READ alignment)
+
+public:
+
+ enum AxisType {
+ AxisTypeNoAxis = 0x0,
+ AxisTypeValue = 0x1,
+ AxisTypeBarCategory = 0x2,
+ AxisTypeCategory = 0x3,
+ AxisTypeDateTime = 0x4,
+ AxisTypeLogValue = 0x5
+ };
+
+ Q_DECLARE_FLAGS(AxisTypes, AxisType)
+
+protected:
+ explicit QAbstractAxis(QAbstractAxisPrivate &d, QObject *parent = 0);
+
+public:
+ ~QAbstractAxis();
+
+ virtual AxisType type() const = 0;
+
+ //visibility handling
+ bool isVisible() const;
+ void setVisible(bool visible = true);
+ void show();
+ void hide();
+
+ //arrow handling
+ bool isLineVisible() const;
+ void setLineVisible(bool visible = true);
+ void setLinePen(const QPen &pen);
+ QPen linePen() const;
+ void setLinePenColor(QColor color);
+ QColor linePenColor() const;
+
+ //grid handling
+ bool isGridLineVisible() const;
+ void setGridLineVisible(bool visible = true);
+ void setGridLinePen(const QPen &pen);
+ QPen gridLinePen() const;
+
+ //labels handling
+ bool labelsVisible() const;
+ void setLabelsVisible(bool visible = true);
+ void setLabelsPen(const QPen &pen);
+ QPen labelsPen() const;
+ void setLabelsBrush(const QBrush &brush);
+ QBrush labelsBrush() const;
+ void setLabelsFont(const QFont &font);
+ QFont labelsFont() const;
+ void setLabelsAngle(int angle);
+ int labelsAngle() const;
+ void setLabelsColor(QColor color);
+ QColor labelsColor() const;
+
+ //title handling
+ bool isTitleVisible() const;
+ void setTitleVisible(bool visible = true);
+ void setTitlePen(const QPen &pen);
+ QPen titlePen() const;
+ void setTitleBrush(const QBrush &brush);
+ QBrush titleBrush() const;
+ void setTitleFont(const QFont &font);
+ QFont titleFont() const;
+ void setTitleText(const QString &title);
+ QString titleText() const;
+
+ //shades handling
+ bool shadesVisible() const;
+ void setShadesVisible(bool visible = true);
+ void setShadesPen(const QPen &pen);
+ QPen shadesPen() const;
+ void setShadesBrush(const QBrush &brush);
+ QBrush shadesBrush() const;
+ void setShadesColor(QColor color);
+ QColor shadesColor() const;
+ void setShadesBorderColor(QColor color);
+ QColor shadesBorderColor() const;
+
+ Qt::Orientation orientation();
+ Qt::Alignment alignment() const;
+
+ //range handling
+ void setMin(const QVariant &min);
+ void setMax(const QVariant &max);
+ void setRange(const QVariant &min, const QVariant &max);
+
+Q_SIGNALS:
+ void visibleChanged(bool visible);
+ void linePenChanged(const QPen &pen);
+ void lineVisibleChanged(bool visible);
+ void labelsVisibleChanged(bool visible);
+ void labelsPenChanged(const QPen &pen);
+ void labelsBrushChanged(const QBrush &brush);
+ void labelsFontChanged(const QFont &pen);
+ void labelsAngleChanged(int angle);
+ void gridLinePenChanged(const QPen &pen);
+ void gridVisibleChanged(bool visible);
+ void colorChanged(QColor color);
+ void labelsColorChanged(QColor color);
+ void titleTextChanged(const QString &title);
+ void titlePenChanged(const QPen &pen);
+ void titleBrushChanged(const QBrush &brush);
+ void titleVisibleChanged(bool visible);
+ void titleFontChanged(const QFont &font);
+ void shadesVisibleChanged(bool visible);
+ void shadesColorChanged(QColor color);
+ void shadesBorderColorChanged(QColor color);
+ void shadesPenChanged(const QPen &pen);
+ void shadesBrushChanged(const QBrush &brush);
+
+protected:
+ QScopedPointer<QAbstractAxisPrivate> d_ptr;
+ Q_DISABLE_COPY(QAbstractAxis)
+ friend class ChartDataSet;
+ friend class ChartPresenter;
+ friend class ChartThemeManager;
+ friend class AbstractDomain;
+ friend class ChartAxisElement;
+ friend class XYChart;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QABSTRACTAXIS_H
diff --git a/src/charts/axis/qabstractaxis_p.h b/src/charts/axis/qabstractaxis_p.h
new file mode 100644
index 00000000..f2f60038
--- /dev/null
+++ b/src/charts/axis/qabstractaxis_p.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QABSTRACTAXIS_P_H
+#define QABSTRACTAXIS_P_H
+
+#include "qabstractaxis.h"
+#include "chartaxiselement_p.h"
+#include "qchart.h"
+#include <QDebug>
+
+class QGraphicsItem;
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class ChartPresenter;
+class AbstractDomain;
+class QChart;
+class QAbstractSeries;
+class ChartTheme;
+class ChartElement;
+
+class QT_CHARTS_AUTOTEST_EXPORT QAbstractAxisPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QAbstractAxisPrivate(QAbstractAxis *q);
+ ~QAbstractAxisPrivate();
+
+public:
+ Qt::Alignment alignment() const { return m_alignment; }
+ Qt::Orientation orientation() const { return m_orientation; }
+ void setAlignment( Qt::Alignment alignment);
+
+ virtual void initializeDomain(AbstractDomain *domain) = 0;
+ virtual void initializeGraphics(QGraphicsItem *parent) = 0;
+ virtual void initializeTheme(ChartTheme* theme, bool forced = false);
+ virtual void initializeAnimations(QChart::AnimationOptions options);
+
+ //interface for manipulating range form base class
+ virtual void setMin(const QVariant &min) = 0;
+ virtual void setMax(const QVariant &max) = 0;
+ virtual void setRange(const QVariant &min, const QVariant &max) = 0;
+
+ //interface manipulating range form domain
+ virtual void setRange(qreal min, qreal max) = 0;
+ virtual qreal min() = 0;
+ virtual qreal max() = 0;
+
+ ChartAxisElement *axisItem() { return m_item.data(); }
+
+public Q_SLOTS:
+ void handleRangeChanged(qreal min, qreal max);
+
+Q_SIGNALS:
+ void rangeChanged(qreal min, qreal max);
+
+protected:
+ QAbstractAxis *q_ptr;
+ QChart *m_chart;
+ QScopedPointer<ChartAxisElement> m_item;
+
+private:
+ QList<QAbstractSeries*> m_series;
+
+ Qt::Alignment m_alignment;
+ Qt::Orientation m_orientation;
+
+ bool m_visible;
+
+ bool m_arrowVisible;
+ QPen m_axisPen;
+ QBrush m_axisBrush;
+
+ bool m_gridLineVisible;
+ QPen m_gridLinePen;
+
+ bool m_labelsVisible;
+ QPen m_labelsPen;
+ QBrush m_labelsBrush;
+ QFont m_labelsFont;
+ int m_labelsAngle;
+
+ bool m_titleVisible;
+ QPen m_titlePen;
+ QBrush m_titleBrush;
+ QFont m_titleFont;
+ QString m_title;
+
+ bool m_shadesVisible;
+ QPen m_shadesPen;
+ QBrush m_shadesBrush;
+ qreal m_shadesOpacity;
+
+ bool m_dirty;
+
+ friend class QAbstractAxis;
+ friend class ChartDataSet;
+ friend class ChartPresenter;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/axis/valueaxis/chartvalueaxisx.cpp b/src/charts/axis/valueaxis/chartvalueaxisx.cpp
new file mode 100644
index 00000000..abf9c434
--- /dev/null
+++ b/src/charts/axis/valueaxis/chartvalueaxisx.cpp
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "chartvalueaxisx_p.h"
+#include "qabstractaxis.h"
+#include "chartpresenter_p.h"
+#include "qvalueaxis.h"
+#include "abstractchartlayout_p.h"
+#include <QGraphicsLayout>
+#include <qmath.h>
+#include <QDebug>
+
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+ChartValueAxisX::ChartValueAxisX(QValueAxis *axis, QGraphicsItem *item )
+ : HorizontalAxis(axis, item),
+ m_axis(axis)
+{
+ QObject::connect(m_axis, SIGNAL(tickCountChanged(int)), this, SLOT(handleTickCountChanged(int)));
+ QObject::connect(m_axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
+}
+
+ChartValueAxisX::~ChartValueAxisX()
+{
+}
+
+QVector<qreal> ChartValueAxisX::calculateLayout() const
+{
+ int tickCount = m_axis->tickCount();
+
+ Q_ASSERT(tickCount >= 2);
+
+ QVector<qreal> points;
+ points.resize(tickCount);
+
+ const QRectF &gridRect = gridGeometry();
+ const qreal deltaX = gridRect.width() / (qreal(tickCount) - 1.0);
+ for (int i = 0; i < tickCount; ++i)
+ points[i] = qreal(i) * deltaX + gridRect.left();
+ return points;
+}
+
+void ChartValueAxisX::updateGeometry()
+{
+ const QVector<qreal>& layout = ChartAxisElement::layout();
+ if (layout.isEmpty())
+ return;
+ setLabels(createValueLabels(min(), max(), layout.size(), m_axis->labelFormat()));
+ HorizontalAxis::updateGeometry();
+}
+
+void ChartValueAxisX::handleTickCountChanged(int tick)
+{
+ Q_UNUSED(tick);
+ QGraphicsLayoutItem::updateGeometry();
+ if(presenter()) presenter()->layout()->invalidate();
+}
+
+void ChartValueAxisX::handleLabelFormatChanged(const QString &format)
+{
+ Q_UNUSED(format);
+ QGraphicsLayoutItem::updateGeometry();
+ if(presenter()) presenter()->layout()->invalidate();
+}
+
+QSizeF ChartValueAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED(constraint)
+
+ QSizeF sh;
+
+ QSizeF base = HorizontalAxis::sizeHint(which, constraint);
+ QStringList ticksList = createValueLabels(min(),max(),m_axis->tickCount(),m_axis->labelFormat());
+ // Width of horizontal axis sizeHint indicates the maximum distance labels can extend past
+ // first and last ticks. Base width is irrelevant.
+ qreal width = 0;
+ qreal height = 0;
+
+ switch (which) {
+ case Qt::MinimumSize: {
+ QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(),
+ QStringLiteral("..."),
+ axis()->labelsAngle());
+ width = boundingRect.width() / 2.0;
+ height = boundingRect.height() + labelPadding() + base.height() + 1.0;
+ sh = QSizeF(width, height);
+ break;
+ }
+ case Qt::PreferredSize: {
+ qreal labelHeight = 0.0;
+ qreal firstWidth = -1.0;
+ foreach (const QString& s, ticksList) {
+ QRectF rect = ChartPresenter::textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
+ labelHeight = qMax(rect.height(), labelHeight);
+ width = rect.width();
+ if (firstWidth < 0.0)
+ firstWidth = width;
+ }
+ height = labelHeight + labelPadding() + base.height() + 1.0;
+ width = qMax(width, firstWidth) / 2.0;
+ sh = QSizeF(width, height);
+ break;
+ }
+ default:
+ break;
+ }
+ return sh;
+}
+
+#include "moc_chartvalueaxisx_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/valueaxis/chartvalueaxisx_p.h b/src/charts/axis/valueaxis/chartvalueaxisx_p.h
new file mode 100644
index 00000000..7f83e5a3
--- /dev/null
+++ b/src/charts/axis/valueaxis/chartvalueaxisx_p.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTVALUEAXISX_H
+#define CHARTVALUEAXISX_H
+
+#include "horizontalaxis_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QValueAxis;
+
+class ChartValueAxisX : public HorizontalAxis
+{
+ Q_OBJECT
+public:
+ ChartValueAxisX(QValueAxis *axis, QGraphicsItem *item = 0);
+ ~ChartValueAxisX();
+
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const;
+protected:
+ QVector<qreal> calculateLayout() const;
+ void updateGeometry();
+private Q_SLOTS:
+ void handleTickCountChanged(int tick);
+ void handleLabelFormatChanged(const QString &format);
+
+private:
+ QValueAxis *m_axis;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif /* CHARTVALUEAXISX_H */
diff --git a/src/charts/axis/valueaxis/chartvalueaxisy.cpp b/src/charts/axis/valueaxis/chartvalueaxisy.cpp
new file mode 100644
index 00000000..d6b7c651
--- /dev/null
+++ b/src/charts/axis/valueaxis/chartvalueaxisy.cpp
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "chartvalueaxisy_p.h"
+#include "qabstractaxis.h"
+#include "chartpresenter_p.h"
+#include "qvalueaxis.h"
+#include "abstractchartlayout_p.h"
+#include <QGraphicsLayout>
+#include <qmath.h>
+#include <QDebug>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+ChartValueAxisY::ChartValueAxisY(QValueAxis *axis, QGraphicsItem *item)
+ : VerticalAxis(axis, item),
+ m_axis(axis)
+{
+ QObject::connect(m_axis, SIGNAL(tickCountChanged(int)), this, SLOT(handleTickCountChanged(int)));
+ QObject::connect(m_axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
+}
+
+ChartValueAxisY::~ChartValueAxisY()
+{
+}
+
+QVector<qreal> ChartValueAxisY::calculateLayout() const
+{
+ int tickCount = m_axis->tickCount();
+
+ Q_ASSERT(tickCount >= 2);
+
+ QVector<qreal> points;
+ points.resize(tickCount);
+
+ const QRectF &gridRect = gridGeometry();
+
+ const qreal deltaY = gridRect.height() / (qreal(tickCount) - 1.0);
+ for (int i = 0; i < tickCount; ++i)
+ points[i] = qreal(i) * -deltaY + gridRect.bottom();
+
+ return points;
+}
+
+void ChartValueAxisY::updateGeometry()
+{
+ const QVector<qreal> &layout = ChartAxisElement::layout();
+ if (layout.isEmpty())
+ return;
+ setLabels(createValueLabels(min(),max(),layout.size(),m_axis->labelFormat()));
+ VerticalAxis::updateGeometry();
+}
+
+void ChartValueAxisY::handleTickCountChanged(int tick)
+{
+ Q_UNUSED(tick);
+ QGraphicsLayoutItem::updateGeometry();
+ if (presenter()) presenter()->layout()->invalidate();
+}
+
+void ChartValueAxisY::handleLabelFormatChanged(const QString &format)
+{
+ Q_UNUSED(format);
+ QGraphicsLayoutItem::updateGeometry();
+ if(presenter()) presenter()->layout()->invalidate();
+}
+
+QSizeF ChartValueAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED(constraint)
+
+ QSizeF sh;
+ QSizeF base = VerticalAxis::sizeHint(which, constraint);
+ QStringList ticksList = createValueLabels(min(),max(),m_axis->tickCount(),m_axis->labelFormat());
+ qreal width = 0;
+ // Height of vertical axis sizeHint indicates the maximum distance labels can extend past
+ // first and last ticks. Base height is irrelevant.
+ qreal height = 0;
+
+ switch (which) {
+ case Qt::MinimumSize: {
+ QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(),
+ QStringLiteral("..."),
+ axis()->labelsAngle());
+ width = boundingRect.width() + labelPadding() + base.width() + 1.0;
+ height = boundingRect.height() / 2.0;
+ sh = QSizeF(width, height);
+ break;
+ }
+ case Qt::PreferredSize: {
+ qreal labelWidth = 0.0;
+ qreal firstHeight = -1.0;
+ foreach (const QString& s, ticksList) {
+ QRectF rect = ChartPresenter::textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
+ labelWidth = qMax(rect.width(), labelWidth);
+ height = rect.height();
+ if (firstHeight < 0.0)
+ firstHeight = height;
+ }
+ width = labelWidth + labelPadding() + base.width() + 2.0; //two pixels of tolerance
+ height = qMax(height, firstHeight) / 2.0;
+ sh = QSizeF(width, height);
+ break;
+ }
+ default:
+ break;
+ }
+ return sh;
+}
+
+#include "moc_chartvalueaxisy_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/valueaxis/chartvalueaxisy_p.h b/src/charts/axis/valueaxis/chartvalueaxisy_p.h
new file mode 100644
index 00000000..3ec30faa
--- /dev/null
+++ b/src/charts/axis/valueaxis/chartvalueaxisy_p.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTVALUEAXISY_H
+#define CHARTVALUEAXISY_H
+
+#include "verticalaxis_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QValueAxis;
+
+class ChartValueAxisY : public VerticalAxis
+{
+ Q_OBJECT
+public:
+ ChartValueAxisY(QValueAxis *axis, QGraphicsItem *item = 0);
+ ~ChartValueAxisY();
+
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const;
+protected:
+ QVector<qreal> calculateLayout() const;
+ void updateGeometry();
+private Q_SLOTS:
+ void handleTickCountChanged(int tick);
+ void handleLabelFormatChanged(const QString &format);
+
+private:
+ QValueAxis *m_axis;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif /* CHARTVALUEAXISY_H */
diff --git a/src/charts/axis/valueaxis/polarchartvalueaxisangular.cpp b/src/charts/axis/valueaxis/polarchartvalueaxisangular.cpp
new file mode 100644
index 00000000..945449a8
--- /dev/null
+++ b/src/charts/axis/valueaxis/polarchartvalueaxisangular.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "polarchartvalueaxisangular_p.h"
+#include "chartpresenter_p.h"
+#include "abstractchartlayout_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+PolarChartValueAxisAngular::PolarChartValueAxisAngular(QValueAxis *axis, QGraphicsItem *item)
+ : PolarChartAxisAngular(axis, item)
+{
+ QObject::connect(axis, SIGNAL(tickCountChanged(int)), this, SLOT(handleTickCountChanged(int)));
+ QObject::connect(axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
+}
+
+PolarChartValueAxisAngular::~PolarChartValueAxisAngular()
+{
+}
+
+QVector<qreal> PolarChartValueAxisAngular::calculateLayout() const
+{
+ int tickCount = static_cast<QValueAxis *>(axis())->tickCount();
+ Q_ASSERT(tickCount >= 2);
+
+ QVector<qreal> points;
+ points.resize(tickCount);
+
+ const qreal d = 360.0 / qreal(tickCount - 1);
+
+ for (int i = 0; i < tickCount; ++i) {
+ qreal angularCoordinate = qreal(i) * d;
+ points[i] = angularCoordinate;
+ }
+
+ return points;
+}
+
+void PolarChartValueAxisAngular::createAxisLabels(const QVector<qreal> &layout)
+{
+ QStringList labelList = createValueLabels(min(), max(), layout.size(), static_cast<QValueAxis *>(axis())->labelFormat());
+ setLabels(labelList);
+}
+
+void PolarChartValueAxisAngular::handleTickCountChanged(int tick)
+{
+ Q_UNUSED(tick);
+ QGraphicsLayoutItem::updateGeometry();
+ if (presenter())
+ presenter()->layout()->invalidate();
+}
+
+void PolarChartValueAxisAngular::handleLabelFormatChanged(const QString &format)
+{
+ Q_UNUSED(format);
+ QGraphicsLayoutItem::updateGeometry();
+ if (presenter())
+ presenter()->layout()->invalidate();
+}
+
+#include "moc_polarchartvalueaxisangular_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/valueaxis/polarchartvalueaxisangular_p.h b/src/charts/axis/valueaxis/polarchartvalueaxisangular_p.h
new file mode 100644
index 00000000..d4a2f653
--- /dev/null
+++ b/src/charts/axis/valueaxis/polarchartvalueaxisangular_p.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 POLARCHARTVALUEAXISANGULAR_P_H
+#define POLARCHARTVALUEAXISANGULAR_P_H
+
+#include "polarchartaxisangular_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QValueAxis;
+
+class PolarChartValueAxisAngular : public PolarChartAxisAngular
+{
+ Q_OBJECT
+public:
+ PolarChartValueAxisAngular(QValueAxis *axis, QGraphicsItem *item);
+ ~PolarChartValueAxisAngular();
+
+ virtual QVector<qreal> calculateLayout() const;
+ virtual void createAxisLabels(const QVector<qreal> &layout);
+
+private Q_SLOTS:
+ void handleTickCountChanged(int tick);
+ void handleLabelFormatChanged(const QString &format);
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // POLARCHARTVALUEAXISANGULAR_P_H
diff --git a/src/charts/axis/valueaxis/polarchartvalueaxisradial.cpp b/src/charts/axis/valueaxis/polarchartvalueaxisradial.cpp
new file mode 100644
index 00000000..006477e8
--- /dev/null
+++ b/src/charts/axis/valueaxis/polarchartvalueaxisradial.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "polarchartvalueaxisradial_p.h"
+#include "chartpresenter_p.h"
+#include "abstractchartlayout_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+PolarChartValueAxisRadial::PolarChartValueAxisRadial(QValueAxis *axis, QGraphicsItem *item)
+ : PolarChartAxisRadial(axis, item)
+{
+ QObject::connect(axis, SIGNAL(tickCountChanged(int)), this, SLOT(handleTickCountChanged(int)));
+ QObject::connect(axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
+}
+
+PolarChartValueAxisRadial::~PolarChartValueAxisRadial()
+{
+}
+
+QVector<qreal> PolarChartValueAxisRadial::calculateLayout() const
+{
+ int tickCount = static_cast<QValueAxis *>(axis())->tickCount();
+ Q_ASSERT(tickCount >= 2);
+
+ QVector<qreal> points;
+ points.resize(tickCount);
+
+ const qreal d = (axisGeometry().width() / 2) / qreal(tickCount - 1);
+
+ for (int i = 0; i < tickCount; ++i) {
+ qreal radialCoordinate = qreal(i) * d;
+ points[i] = radialCoordinate;
+ }
+
+ return points;
+}
+
+void PolarChartValueAxisRadial::createAxisLabels(const QVector<qreal> &layout)
+{
+ setLabels(createValueLabels(min(), max(), layout.size(), static_cast<QValueAxis *>(axis())->labelFormat()));
+}
+
+void PolarChartValueAxisRadial::handleTickCountChanged(int tick)
+{
+ Q_UNUSED(tick);
+ QGraphicsLayoutItem::updateGeometry();
+ if (presenter())
+ presenter()->layout()->invalidate();
+}
+
+void PolarChartValueAxisRadial::handleLabelFormatChanged(const QString &format)
+{
+ Q_UNUSED(format);
+ QGraphicsLayoutItem::updateGeometry();
+ if (presenter())
+ presenter()->layout()->invalidate();
+}
+
+#include "moc_polarchartvalueaxisradial_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/valueaxis/polarchartvalueaxisradial_p.h b/src/charts/axis/valueaxis/polarchartvalueaxisradial_p.h
new file mode 100644
index 00000000..4e13b57a
--- /dev/null
+++ b/src/charts/axis/valueaxis/polarchartvalueaxisradial_p.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 POLARCHARTVALUEAXISRADIAL_P_H
+#define POLARCHARTVALUEAXISRADIAL_P_H
+
+#include "polarchartaxisradial_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QValueAxis;
+
+class PolarChartValueAxisRadial : public PolarChartAxisRadial
+{
+ Q_OBJECT
+public:
+ PolarChartValueAxisRadial(QValueAxis *axis, QGraphicsItem *item);
+ ~PolarChartValueAxisRadial();
+
+ virtual QVector<qreal> calculateLayout() const;
+ virtual void createAxisLabels(const QVector<qreal> &layout);
+
+private Q_SLOTS:
+ void handleTickCountChanged(int tick);
+ void handleLabelFormatChanged(const QString &format);
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // POLARCHARTVALUEAXISRADIAL_P_H
diff --git a/src/charts/axis/valueaxis/qvalueaxis.cpp b/src/charts/axis/valueaxis/qvalueaxis.cpp
new file mode 100644
index 00000000..a055dc22
--- /dev/null
+++ b/src/charts/axis/valueaxis/qvalueaxis.cpp
@@ -0,0 +1,459 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvalueaxis.h"
+#include "qvalueaxis_p.h"
+#include "chartvalueaxisx_p.h"
+#include "chartvalueaxisy_p.h"
+#include "abstractdomain_p.h"
+#include "polarchartvalueaxisangular_p.h"
+#include "polarchartvalueaxisradial_p.h"
+#include "chartdataset_p.h"
+#include "chartpresenter_p.h"
+#include "charttheme_p.h"
+
+
+QT_CHARTS_BEGIN_NAMESPACE
+/*!
+ \class QValueAxis
+ \inmodule Qt Charts
+ \brief The QValueAxis class is used for manipulating chart's axis.
+ \mainclass
+
+ ValueAxis can be setup to show axis line with tick marks, grid lines and shades.
+ Values of axis are drawn to position of ticks.
+
+ Example code on how to use QValueAxis.
+ \code
+ QChartView *chartView = new QChartView;
+ QLineSeries *series = new QLineSeries;
+ // ...
+ chartView->chart()->addSeries(series);
+
+ QValueAxis *axisX = new QValueAxis;
+ axisX->setRange(10, 20.5);
+ axisX->setTickCount(10);
+ axisX->setLabelFormat("%.2f");
+ chartView->chart()->setAxisX(axisX, series);
+ \endcode
+*/
+/*!
+ \qmltype ValueAxis
+ \instantiates QValueAxis
+ \inqmlmodule QtCharts
+
+ \inherits AbstractAxis
+ \brief The ValueAxis element is used for manipulating chart's axes
+
+ ValueAxis can be setup to show axis line with tick marks, grid lines and shades.
+ Values of axis are drawn to position of ticks
+
+ Example about using ValueAxis:
+ \code
+ ChartView {
+ ValueAxis {
+ id: xAxis
+ min: 0
+ max: 10
+ }
+ // Add a few series...
+ }
+ \endcode
+*/
+
+/*!
+ \property QValueAxis::min
+ Defines the minimum value on the axis.
+ When setting this property the max is adjusted if necessary, to ensure that the range remains valid.
+*/
+/*!
+ \qmlproperty real ValueAxis::min
+ Defines the minimum value on the axis.
+ When setting this property the max is adjusted if necessary, to ensure that the range remains valid.
+*/
+
+/*!
+ \property QValueAxis::max
+ Defines the maximum value on the axis.
+ When setting this property the min is adjusted if necessary, to ensure that the range remains valid.
+*/
+/*!
+ \qmlproperty real ValueAxis::max
+ Defines the maximum value on the axis.
+ When setting this property the min is adjusted if necessary, to ensure that the range remains valid.
+*/
+
+/*!
+ \property QValueAxis::tickCount
+ Defines the number of ticks on the axis. This indicates how many grid lines are draw on the chart.
+ The default value is 5, and it can not be below 2.
+*/
+/*!
+ \qmlproperty real ValueAxis::tickCount
+ Defines the number of ticks on the axis. This indicates how many grid lines are draw on the chart.
+ The default value is 5, and it can not be below 2.
+*/
+
+/*!
+ \property QValueAxis::labelFormat
+ Defines the label format of the axis.
+ Supported specifiers are: d, i, o, x, X, f, F, e, E, g, G, and c.
+ See QString::sprintf() for additional details.
+
+ If the QChart::localizeNumbers is \c{true}, the supported specifiers are limited to: d, e, E, f,
+ g, G, and i. Also, only the precision modifier is supported. The rest of the formatting comes from
+ the default QLocale of the application.
+*/
+/*!
+ \qmlproperty real ValueAxis::labelFormat
+ Defines the label format of the axis.
+ Supported specifiers are: d, i, o, x, X, f, F, e, E, g, G, and c.
+ See QString::sprintf() for additional details.
+
+ If the ChartView::localizeNumbers is \c{true}, the supported specifiers are limited to: d, e, E, f,
+ g, G, and i. Also, only the precision modifier is supported. The rest of the formatting comes from
+ the default QLocale of the application.
+*/
+
+/*!
+ \fn void QValueAxis::minChanged(qreal min)
+ Axis emits signal when \a min of axis has changed.
+*/
+/*!
+ \qmlsignal ValueAxis::onMinChanged(real min)
+ Axis emits signal when \a min of axis has changed.
+*/
+
+/*!
+ \fn void QValueAxis::maxChanged(qreal max)
+ Axis emits signal when \a max of axis has changed.
+*/
+/*!
+ \qmlsignal ValueAxis::onMaxChanged(real max)
+ Axis emits signal when \a max of axis has changed.
+*/
+
+/*!
+ \fn void QValueAxis::tickCountChanged(int tickCount)
+ Axis emits signal when \a tickCount of axis has changed.
+*/
+/*!
+ \qmlsignal ValueAxis::tickCountChanged(int tickCount)
+ Axis emits signal when \a tickCount of axis has changed.
+*/
+
+/*!
+ \fn void QValueAxis::rangeChanged(qreal min, qreal max)
+ Axis emits signal when \a min or \a max of axis has changed.
+*/
+
+/*!
+ \fn void QValueAxis::labelFormatChanged(const QString &format)
+ Axis emits signal when \a format of axis labels has changed.
+*/
+/*!
+ \qmlsignal ValueAxis::labelFormatChanged(const QString &format)
+ Axis emits signal when \a format of axis labels has changed.
+*/
+
+/*!
+ \property QValueAxis::niceNumbersEnabled
+ \obsolete
+ Using this function can lead to unexpected behavior. Use applyNiceNumbers() instead.
+*/
+
+/*!
+ \qmlproperty bool ValueAxis::niceNumbersEnabled
+ Deprecated; Using this function can lead to unexpected behavior. Use applyNiceNumbers() instead.
+*/
+
+/*!
+ Constructs an axis object which is a child of \a parent.
+*/
+QValueAxis::QValueAxis(QObject *parent) :
+ QAbstractAxis(*new QValueAxisPrivate(this), parent)
+{
+
+}
+
+/*!
+ \internal
+*/
+QValueAxis::QValueAxis(QValueAxisPrivate &d, QObject *parent)
+ : QAbstractAxis(d, parent)
+{
+
+}
+
+/*!
+ Destroys the object
+*/
+QValueAxis::~QValueAxis()
+{
+ Q_D(QValueAxis);
+ if (d->m_chart)
+ d->m_chart->removeAxis(this);
+}
+
+void QValueAxis::setMin(qreal min)
+{
+ Q_D(QValueAxis);
+ setRange(min, qMax(d->m_max, min));
+}
+
+qreal QValueAxis::min() const
+{
+ Q_D(const QValueAxis);
+ return d->m_min;
+}
+
+void QValueAxis::setMax(qreal max)
+{
+ Q_D(QValueAxis);
+ setRange(qMin(d->m_min, max), max);
+}
+
+qreal QValueAxis::max() const
+{
+ Q_D(const QValueAxis);
+ return d->m_max;
+}
+
+/*!
+ Sets range from \a min to \a max on the axis.
+ If min is greater than max then this function returns without making any changes.
+*/
+void QValueAxis::setRange(qreal min, qreal max)
+{
+ Q_D(QValueAxis);
+ d->setRange(min,max);
+}
+
+void QValueAxis::setTickCount(int count)
+{
+ Q_D(QValueAxis);
+ if (d->m_tickCount != count && count >= 2) {
+ d->m_tickCount = count;
+ emit tickCountChanged(count);
+ }
+}
+
+int QValueAxis::tickCount() const
+{
+ Q_D(const QValueAxis);
+ return d->m_tickCount;
+}
+
+void QValueAxis::setNiceNumbersEnabled(bool enable)
+{
+ Q_D(QValueAxis);
+ qWarning() << "Deprecated; Using this function can lead to unexpected behavior. " \
+ "Use applyNiceNumbers() instead.";
+ if(enable) {
+ QObject::connect(this,SIGNAL(rangeChanged(qreal,qreal)),this,SLOT(applyNiceNumbers()));
+ QObject::connect(this,SIGNAL(tickCountChanged(int)),this,SLOT(applyNiceNumbers()));
+ applyNiceNumbers();
+ }
+ else {
+ QObject::disconnect(this,SIGNAL(rangeChanged(qreal,qreal)),this,SLOT(applyNiceNumbers()));
+ QObject::disconnect(this,SIGNAL(tickCountChanged(int)),this,SLOT(applyNiceNumbers()));
+ }
+ d->m_niceNumbersEnabled=enable;
+}
+
+bool QValueAxis::niceNumbersEnabled() const
+{
+ Q_D(const QValueAxis);
+ qWarning() << "Deprecated; Using this function can lead to unexpected behavior. " \
+ "Use applyNiceNumbers() instead.";
+ return d->m_niceNumbersEnabled;
+}
+
+void QValueAxis::setLabelFormat(const QString &format)
+{
+ Q_D(QValueAxis);
+ d->m_format = format;
+ emit labelFormatChanged(format);
+}
+
+QString QValueAxis::labelFormat() const
+{
+ Q_D(const QValueAxis);
+ return d->m_format;
+}
+
+/*!
+ Returns the type of the axis
+*/
+QAbstractAxis::AxisType QValueAxis::type() const
+{
+ return AxisTypeValue;
+}
+
+/*!
+ This method modifies range and number of ticks on the axis to look "nice". Algorithm considers numbers that
+ can be expressed as form of 1*10^n, 2* 10^n or 5*10^n as a nice numbers. These numbers are used for spacing the ticks.
+ This method will modify the current range and number of ticks.
+ \sa setRange(), setTickCount()
+*/
+void QValueAxis::applyNiceNumbers()
+{
+ Q_D(QValueAxis);
+ if(d->m_applying) return;
+ qreal min = d->m_min;
+ qreal max = d->m_max;
+ int ticks = d->m_tickCount;
+ AbstractDomain::looseNiceNumbers(min,max,ticks);
+ d->m_applying=true;
+ d->setRange(min,max);
+ setTickCount(ticks);
+ d->m_applying=false;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QValueAxisPrivate::QValueAxisPrivate(QValueAxis *q)
+ : QAbstractAxisPrivate(q),
+ m_min(0),
+ m_max(0),
+ m_tickCount(5),
+ m_format(QString::null),
+ m_applying(false),
+ m_niceNumbersEnabled(false)
+{
+
+}
+
+QValueAxisPrivate::~QValueAxisPrivate()
+{
+
+}
+
+void QValueAxisPrivate::setMin(const QVariant &min)
+{
+ Q_Q(QValueAxis);
+ bool ok;
+ qreal value = min.toReal(&ok);
+ if (ok)
+ q->setMin(value);
+}
+
+void QValueAxisPrivate::setMax(const QVariant &max)
+{
+ Q_Q(QValueAxis);
+ bool ok;
+ qreal value = max.toReal(&ok);
+ if (ok)
+ q->setMax(value);
+}
+
+void QValueAxisPrivate::setRange(const QVariant &min, const QVariant &max)
+{
+ Q_Q(QValueAxis);
+ bool ok1;
+ bool ok2;
+ qreal value1 = min.toReal(&ok1);
+ qreal value2 = max.toReal(&ok2);
+ if (ok1 && ok2)
+ q->setRange(value1, value2);
+}
+
+void QValueAxisPrivate::setRange(qreal min, qreal max)
+{
+ Q_Q(QValueAxis);
+ bool changed = false;
+
+ if (min > max)
+ return;
+
+ bool changeMin = false;
+ if (m_min == 0 || min == 0)
+ changeMin = !qFuzzyCompare(1 + m_min, 1 + min);
+ else
+ changeMin = !qFuzzyCompare(m_min, min);
+
+ bool changeMax = false;
+ if (m_max == 0 || max == 0)
+ changeMax = !qFuzzyCompare(1 + m_max, 1 + max);
+ else
+ changeMax = !qFuzzyCompare(m_max, max);
+
+ if (changeMin) {
+ m_min = min;
+ changed = true;
+ emit q->minChanged(min);
+ }
+
+ if (changeMax) {
+ m_max = max;
+ changed = true;
+ emit q->maxChanged(max);
+ }
+
+ if (changed) {
+ emit rangeChanged(min,max);
+ emit q->rangeChanged(min, max);
+ }
+}
+
+void QValueAxisPrivate::initializeGraphics(QGraphicsItem *parent)
+{
+ Q_Q(QValueAxis);
+ ChartAxisElement *axis(0);
+
+ if (m_chart->chartType() == QChart::ChartTypeCartesian) {
+ if (orientation() == Qt::Vertical)
+ axis = new ChartValueAxisY(q,parent);
+ if (orientation() == Qt::Horizontal)
+ axis = new ChartValueAxisX(q,parent);
+ }
+
+ if (m_chart->chartType() == QChart::ChartTypePolar) {
+ if (orientation() == Qt::Vertical)
+ axis = new PolarChartValueAxisRadial(q, parent);
+ if (orientation() == Qt::Horizontal)
+ axis = new PolarChartValueAxisAngular(q, parent);
+ }
+
+ m_item.reset(axis);
+ QAbstractAxisPrivate::initializeGraphics(parent);
+}
+
+
+void QValueAxisPrivate::initializeDomain(AbstractDomain *domain)
+{
+ if (orientation() == Qt::Vertical) {
+ if (!qFuzzyIsNull(m_max - m_min))
+ domain->setRangeY(m_min, m_max);
+ else
+ setRange(domain->minY(), domain->maxY());
+ }
+ if (orientation() == Qt::Horizontal) {
+ if (!qFuzzyIsNull(m_max - m_min))
+ domain->setRangeX(m_min, m_max);
+ else
+ setRange(domain->minX(), domain->maxX());
+ }
+}
+
+#include "moc_qvalueaxis.cpp"
+#include "moc_qvalueaxis_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/valueaxis/qvalueaxis.h b/src/charts/axis/valueaxis/qvalueaxis.h
new file mode 100644
index 00000000..a51203a4
--- /dev/null
+++ b/src/charts/axis/valueaxis/qvalueaxis.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVALUEAXIS_H
+#define QVALUEAXIS_H
+
+#include <QtCharts/qabstractaxis.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QValueAxisPrivate;
+
+class QT_CHARTS_EXPORT QValueAxis : public QAbstractAxis
+{
+ Q_OBJECT
+ Q_PROPERTY(int tickCount READ tickCount WRITE setTickCount NOTIFY tickCountChanged)
+ Q_PROPERTY(bool niceNumbersEnabled READ niceNumbersEnabled WRITE setNiceNumbersEnabled)
+ Q_PROPERTY(qreal min READ min WRITE setMin NOTIFY minChanged)
+ Q_PROPERTY(qreal max READ max WRITE setMax NOTIFY maxChanged)
+ Q_PROPERTY(QString labelFormat READ labelFormat WRITE setLabelFormat NOTIFY labelFormatChanged)
+
+public:
+ explicit QValueAxis(QObject *parent = 0);
+ ~QValueAxis();
+
+protected:
+ QValueAxis(QValueAxisPrivate &d, QObject *parent = 0);
+
+public:
+ AxisType type() const;
+
+ //range handling
+ void setMin(qreal min);
+ qreal min() const;
+ void setMax(qreal max);
+ qreal max() const;
+ void setRange(qreal min, qreal max);
+
+ //ticks handling
+ void setTickCount(int count);
+ int tickCount() const;
+
+ void setLabelFormat(const QString &format);
+ QString labelFormat() const;
+
+ void setNiceNumbersEnabled(bool enable = true);
+ bool niceNumbersEnabled() const;
+
+public Q_SLOTS:
+ void applyNiceNumbers();
+
+Q_SIGNALS:
+ void minChanged(qreal min);
+ void maxChanged(qreal max);
+ void rangeChanged(qreal min, qreal max);
+ void tickCountChanged(int tickCount);
+ void labelFormatChanged(const QString &format);
+
+private:
+ Q_DECLARE_PRIVATE(QValueAxis)
+ Q_DISABLE_COPY(QValueAxis)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QVALUEAXIS_H
diff --git a/src/charts/axis/valueaxis/qvalueaxis_p.h b/src/charts/axis/valueaxis/qvalueaxis_p.h
new file mode 100644
index 00000000..a1d9de5b
--- /dev/null
+++ b/src/charts/axis/valueaxis/qvalueaxis_p.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QVALUEAXIS_P_H
+#define QVALUEAXIS_P_H
+
+#include <qvalueaxis.h>
+#include "qabstractaxis_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QValueAxisPrivate : public QAbstractAxisPrivate
+{
+ Q_OBJECT
+public:
+ QValueAxisPrivate(QValueAxis *q);
+ ~QValueAxisPrivate();
+
+public:
+ void initializeGraphics(QGraphicsItem* parent);
+ void initializeDomain(AbstractDomain *domain);
+
+ qreal min() { return m_min; };
+ qreal max() { return m_max; };
+ void setRange(qreal min,qreal max);
+
+protected:
+ void setMin(const QVariant &min);
+ void setMax(const QVariant &max);
+ void setRange(const QVariant &min, const QVariant &max);
+
+private:
+ qreal m_min;
+ qreal m_max;
+ int m_tickCount;
+ QString m_format;
+ bool m_applying;
+ bool m_niceNumbersEnabled;
+ Q_DECLARE_PUBLIC(QValueAxis)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QVALUEAXIS_P_H
diff --git a/src/charts/axis/verticalaxis.cpp b/src/charts/axis/verticalaxis.cpp
new file mode 100644
index 00000000..64c940f1
--- /dev/null
+++ b/src/charts/axis/verticalaxis.cpp
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "verticalaxis_p.h"
+#include "qabstractaxis.h"
+#include "chartpresenter_p.h"
+#include <QDebug>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+VerticalAxis::VerticalAxis(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
+ : CartesianChartAxis(axis, item, intervalAxis)
+{
+}
+
+VerticalAxis::~VerticalAxis()
+{
+}
+
+void VerticalAxis::updateGeometry()
+{
+ const QVector<qreal> &layout = ChartAxisElement::layout();
+
+ if (layout.isEmpty())
+ return;
+
+ QStringList labelList = labels();
+
+ QList<QGraphicsItem *> lines = gridItems();
+ QList<QGraphicsItem *> labels = labelItems();
+ QList<QGraphicsItem *> shades = shadeItems();
+ QList<QGraphicsItem *> arrow = arrowItems();
+ QGraphicsTextItem *title = titleItem();
+
+ Q_ASSERT(labels.size() == labelList.size());
+ Q_ASSERT(layout.size() == labelList.size());
+
+ const QRectF &axisRect = axisGeometry();
+ const QRectF &gridRect = gridGeometry();
+
+ qreal height = axisRect.bottom();
+
+
+ //arrow
+ QGraphicsLineItem *arrowItem = static_cast<QGraphicsLineItem*>(arrow.at(0));
+
+ //arrow position
+ if (axis()->alignment() == Qt::AlignLeft)
+ arrowItem->setLine(axisRect.right(), gridRect.top(), axisRect.right(), gridRect.bottom());
+ else if (axis()->alignment() == Qt::AlignRight)
+ arrowItem->setLine(axisRect.left(), gridRect.top(), axisRect.left(), gridRect.bottom());
+
+ //title
+ QRectF titleBoundingRect;
+ QString titleText = axis()->titleText();
+ qreal availableSpace = axisRect.width() - labelPadding();
+ if (!titleText.isEmpty() && titleItem()->isVisible()) {
+ availableSpace -= titlePadding() * 2.0;
+ qreal minimumLabelWidth = ChartPresenter::textBoundingRect(axis()->labelsFont(),
+ QStringLiteral("...")).width();
+ qreal titleSpace = availableSpace - minimumLabelWidth;
+ title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(90.0),
+ titleSpace, gridRect.height(),
+ titleBoundingRect));
+ title->setTextWidth(titleBoundingRect.height());
+
+ titleBoundingRect = title->boundingRect();
+
+ QPointF center = gridRect.center() - titleBoundingRect.center();
+ if (axis()->alignment() == Qt::AlignLeft)
+ title->setPos(axisRect.left() - titleBoundingRect.width() / 2.0 + titleBoundingRect.height() / 2.0 + titlePadding(), center.y());
+ else if (axis()->alignment() == Qt::AlignRight)
+ title->setPos(axisRect.right() - titleBoundingRect.width() / 2.0 - titleBoundingRect.height() / 2.0 - titlePadding(), center.y());
+
+ title->setTransformOriginPoint(titleBoundingRect.center());
+ title->setRotation(270);
+
+ availableSpace -= titleBoundingRect.height();
+ }
+
+ for (int i = 0; i < layout.size(); ++i) {
+ //items
+ QGraphicsLineItem *gridItem = static_cast<QGraphicsLineItem *>(lines.at(i));
+ QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem *>(arrow.at(i + 1));
+ QGraphicsTextItem *labelItem = static_cast<QGraphicsTextItem *>(labels.at(i));
+
+ //grid line
+ gridItem->setLine(gridRect.left(), layout[i], gridRect.right(), layout[i]);
+
+ //label text wrapping
+ QString text = labelList.at(i);
+ QRectF boundingRect;
+ // don't truncate empty labels
+ if (text.isEmpty()) {
+ labelItem->setHtml(text);
+ } else {
+ qreal labelHeight = (axisRect.height() / layout.count()) - (2 * labelPadding());
+ QString truncatedText = ChartPresenter::truncatedText(axis()->labelsFont(), text,
+ axis()->labelsAngle(),
+ availableSpace,
+ labelHeight, boundingRect);
+ labelItem->setTextWidth(ChartPresenter::textBoundingRect(axis()->labelsFont(),
+ truncatedText).width());
+ labelItem->setHtml(truncatedText);
+ }
+
+ //label transformation origin point
+ const QRectF &rect = labelItem->boundingRect();
+ QPointF center = rect.center();
+ labelItem->setTransformOriginPoint(center.x(), center.y());
+ qreal widthDiff = rect.width() - boundingRect.width();
+ qreal heightDiff = rect.height() - boundingRect.height();
+
+ //ticks and label position
+ if (axis()->alignment() == Qt::AlignLeft) {
+ labelItem->setPos(axisRect.right() - rect.width() + (widthDiff / 2.0) - labelPadding(), layout[i] - center.y());
+ tickItem->setLine(axisRect.right() - labelPadding(), layout[i], axisRect.right(), layout[i]);
+ } else if (axis()->alignment() == Qt::AlignRight) {
+ labelItem->setPos(axisRect.left() + labelPadding() - (widthDiff / 2.0), layout[i] - center.y());
+ tickItem->setLine(axisRect.left(), layout[i], axisRect.left() + labelPadding(), layout[i]);
+ }
+
+ //label in between
+ bool forceHide = false;
+ if (intervalAxis() && (i + 1) != layout.size()) {
+ qreal lowerBound = qMin(layout[i], gridRect.bottom());
+ qreal upperBound = qMax(layout[i + 1], gridRect.top());
+ const qreal delta = lowerBound - upperBound;
+ // Hide label in case visible part of the category at the grid edge is too narrow
+ if (delta < boundingRect.height()
+ && (lowerBound == gridRect.bottom() || upperBound == gridRect.top())
+ && !intervalAxis()) {
+ forceHide = true;
+ } else {
+ labelItem->setPos(labelItem->pos().x() , lowerBound - (delta / 2.0) - center.y());
+ }
+ }
+
+ //label overlap detection - compensate one pixel for rounding errors
+ if (labelItem->pos().y() + boundingRect.height() > height || forceHide ||
+ (labelItem->pos().y() + (heightDiff / 2.0) - 1.0) > axisRect.bottom() ||
+ labelItem->pos().y() + (heightDiff / 2.0) < (axisRect.top() - 1.0)) {
+ labelItem->setVisible(false);
+ }
+ else {
+ labelItem->setVisible(true);
+ height=labelItem->pos().y();
+ }
+
+ //shades
+ if ((i + 1) % 2 && i > 1) {
+ QGraphicsRectItem *rectItem = static_cast<QGraphicsRectItem *>(shades.at(i / 2 - 1));
+ qreal lowerBound = qMin(layout[i - 1], gridRect.bottom());
+ qreal upperBound = qMax(layout[i], gridRect.top());
+ rectItem->setRect(gridRect.left(), upperBound, gridRect.width(), lowerBound - upperBound);
+ if (rectItem->rect().height() <= 0.0)
+ rectItem->setVisible(false);
+ else
+ rectItem->setVisible(true);
+ }
+
+ // check if the grid line and the axis tick should be shown
+ qreal y = gridItem->line().p1().y();
+ if ((y < gridRect.top() || y > gridRect.bottom()))
+ {
+ gridItem->setVisible(false);
+ tickItem->setVisible(false);
+ }else{
+ gridItem->setVisible(true);
+ tickItem->setVisible(true);
+ }
+
+ }
+ //begin/end grid line in case labels between
+ if (intervalAxis()) {
+ QGraphicsLineItem *gridLine;
+ gridLine = static_cast<QGraphicsLineItem *>(lines.at(layout.size()));
+ gridLine->setLine(gridRect.left(), gridRect.top(), gridRect.right(), gridRect.top());
+ gridLine->setVisible(true);
+ gridLine = static_cast<QGraphicsLineItem*>(lines.at(layout.size() + 1));
+ gridLine->setLine(gridRect.left(), gridRect.bottom(), gridRect.right(), gridRect.bottom());
+ gridLine->setVisible(true);
+ }
+}
+
+QSizeF VerticalAxis::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED(constraint);
+ QSizeF sh(0, 0);
+
+ if (axis()->titleText().isEmpty() || !titleItem()->isVisible())
+ return sh;
+
+ switch (which) {
+ case Qt::MinimumSize: {
+ QRectF titleRect = ChartPresenter::textBoundingRect(axis()->titleFont(),
+ QStringLiteral("..."));
+ sh = QSizeF(titleRect.height() + (titlePadding() * 2.0), titleRect.width());
+ break;
+ }
+ case Qt::MaximumSize:
+ case Qt::PreferredSize: {
+ QRectF titleRect = ChartPresenter::textBoundingRect(axis()->titleFont(), axis()->titleText());
+ sh = QSizeF(titleRect.height() + (titlePadding() * 2.0), titleRect.width());
+ break;
+ }
+ default:
+ break;
+ }
+
+ return sh;
+}
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/axis/verticalaxis_p.h b/src/charts/axis/verticalaxis_p.h
new file mode 100644
index 00000000..8349ff51
--- /dev/null
+++ b/src/charts/axis/verticalaxis_p.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 VERTICALAXIS_P_H_
+#define VERTICALAXIS_P_H_
+
+#include "cartesianchartaxis_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class VerticalAxis : public CartesianChartAxis
+{
+public:
+ VerticalAxis(QAbstractAxis *axis, QGraphicsItem *item = 0, bool intervalAxis = false);
+ ~VerticalAxis();
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
+protected:
+ void updateGeometry();
+
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif /* VERTICALAXIS_P_H_ */
diff --git a/src/charts/barchart/abstractbarchartitem.cpp b/src/charts/barchart/abstractbarchartitem.cpp
new file mode 100644
index 00000000..4cf8b366
--- /dev/null
+++ b/src/charts/barchart/abstractbarchartitem.cpp
@@ -0,0 +1,268 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractbarchartitem_p.h"
+#include "bar_p.h"
+#include "qbarset.h"
+#include "qbarset_p.h"
+#include "qabstractbarseries.h"
+#include "qabstractbarseries_p.h"
+#include "qchart.h"
+#include "chartpresenter_p.h"
+#include "charttheme_p.h"
+#include "baranimation_p.h"
+#include "chartdataset_p.h"
+#include <QPainter>
+#include <QTextDocument>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+AbstractBarChartItem::AbstractBarChartItem(QAbstractBarSeries *series, QGraphicsItem* item) :
+ ChartItem(series->d_func(),item),
+ m_animation(0),
+ m_series(series)
+{
+
+ setFlag(ItemClipsChildrenToShape);
+ connect(series->d_func(), SIGNAL(updatedLayout()), this, SLOT(handleLayoutChanged()));
+ connect(series->d_func(), SIGNAL(updatedBars()), this, SLOT(handleUpdatedBars()));
+ connect(series->d_func(), SIGNAL(labelsVisibleChanged(bool)), this, SLOT(handleLabelsVisibleChanged(bool)));
+ connect(series->d_func(), SIGNAL(restructuredBars()), this, SLOT(handleDataStructureChanged()));
+ connect(series, SIGNAL(visibleChanged()), this, SLOT(handleVisibleChanged()));
+ connect(series, SIGNAL(opacityChanged()), this, SLOT(handleOpacityChanged()));
+ connect(series, SIGNAL(labelsFormatChanged(QString)), this, SLOT(handleUpdatedBars()));
+ connect(series, SIGNAL(labelsFormatChanged(QString)), this, SLOT(positionLabels()));
+ connect(series, SIGNAL(labelsPositionChanged(QAbstractBarSeries::LabelsPosition)),
+ this, SLOT(handleLabelsPositionChanged()));
+ setZValue(ChartPresenter::BarSeriesZValue);
+ handleDataStructureChanged();
+ handleVisibleChanged();
+ handleUpdatedBars();
+}
+
+AbstractBarChartItem::~AbstractBarChartItem()
+{
+}
+
+void AbstractBarChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(painter);
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+}
+
+QRectF AbstractBarChartItem::boundingRect() const
+{
+ return m_rect;
+}
+
+void AbstractBarChartItem::applyLayout(const QVector<QRectF> &layout)
+{
+ QSizeF size = geometry().size();
+ if (geometry().size().isValid()) {
+ if (m_animation) {
+ if (m_layout.count() == 0 || m_oldSize != size) {
+ initializeLayout();
+ m_oldSize = size;
+ }
+ m_animation->setup(m_layout, layout);
+ presenter()->startAnimation(m_animation);
+ } else {
+ setLayout(layout);
+ update();
+ }
+ }
+}
+
+void AbstractBarChartItem::setAnimation(BarAnimation *animation)
+{
+ m_animation = animation;
+}
+
+void AbstractBarChartItem::setLayout(const QVector<QRectF> &layout)
+{
+ if (layout.count() != m_bars.count())
+ return;
+
+ m_layout = layout;
+
+ for (int i = 0; i < m_bars.count(); i++)
+ m_bars.at(i)->setRect(layout.at(i));
+
+ positionLabels();
+}
+//handlers
+
+void AbstractBarChartItem::handleDomainUpdated()
+{
+ m_domainMinX = domain()->minX();
+ m_domainMaxX = domain()->maxX();
+ m_domainMinY = domain()->minY();
+ m_domainMaxY = domain()->maxY();
+
+ QRectF rect(QPointF(0,0),domain()->size());
+
+ if(m_rect != rect){
+ prepareGeometryChange();
+ m_rect = rect;
+ }
+
+ handleLayoutChanged();
+}
+
+void AbstractBarChartItem::handleLayoutChanged()
+{
+ if ((m_rect.width() <= 0) || (m_rect.height() <= 0))
+ return; // rect size zero.
+ QVector<QRectF> layout = calculateLayout();
+ applyLayout(layout);
+ handleUpdatedBars();
+}
+
+void AbstractBarChartItem::handleLabelsVisibleChanged(bool visible)
+{
+ foreach (QGraphicsTextItem *label, m_labels)
+ label->setVisible(visible);
+ update();
+}
+
+void AbstractBarChartItem::handleDataStructureChanged()
+{
+ foreach (QGraphicsItem *item, childItems())
+ delete item;
+
+ m_bars.clear();
+ m_labels.clear();
+ m_layout.clear();
+
+ // Create new graphic items for bars
+ for (int c = 0; c < m_series->d_func()->categoryCount(); c++) {
+ for (int s = 0; s < m_series->count(); s++) {
+ QBarSet *set = m_series->d_func()->barsetAt(s);
+
+ // Bars
+ Bar *bar = new Bar(set, c, this);
+ m_bars.append(bar);
+ connect(bar, SIGNAL(clicked(int,QBarSet*)), m_series, SIGNAL(clicked(int,QBarSet*)));
+ connect(bar, SIGNAL(hovered(bool,QBarSet*)), m_series, SIGNAL(hovered(bool,QBarSet*)));
+ connect(bar, SIGNAL(hovered(bool, int, QBarSet*)), m_series, SIGNAL(hovered(bool, int, QBarSet*)));
+ connect(bar, SIGNAL(clicked(int,QBarSet*)), set, SIGNAL(clicked(int)));
+ connect(bar, SIGNAL(hovered(bool,QBarSet*)), set, SIGNAL(hovered(bool)));
+ connect(bar, SIGNAL(hovered(bool, int, QBarSet*)), set, SIGNAL(hovered(bool, int)));
+ // m_layout.append(QRectF(0, 0, 1, 1));
+
+ // Labels
+ QGraphicsTextItem *newLabel = new QGraphicsTextItem(this);
+ newLabel->document()->setDocumentMargin(ChartPresenter::textMargin());
+ m_labels.append(newLabel);
+ }
+ }
+
+ if(themeManager()) themeManager()->updateSeries(m_series);
+ handleLayoutChanged();
+ handleVisibleChanged();
+}
+
+void AbstractBarChartItem::handleVisibleChanged()
+{
+ bool visible = m_series->isVisible();
+ if (visible)
+ handleLabelsVisibleChanged(m_series->isLabelsVisible());
+ else
+ handleLabelsVisibleChanged(visible);
+
+ foreach (QGraphicsItem *bar, m_bars)
+ bar->setVisible(visible);
+}
+
+void AbstractBarChartItem::handleOpacityChanged()
+{
+ foreach (QGraphicsItem *item, childItems())
+ item->setOpacity(m_series->opacity());
+}
+
+void AbstractBarChartItem::handleUpdatedBars()
+{
+ if (!m_series->d_func()->blockBarUpdate()) {
+ // Handle changes in pen, brush, labels etc.
+ int categoryCount = m_series->d_func()->categoryCount();
+ int setCount = m_series->count();
+ int itemIndex(0);
+ static const QString valueTag(QLatin1String("@value"));
+
+ for (int category = 0; category < categoryCount; category++) {
+ for (int set = 0; set < setCount; set++) {
+ QBarSetPrivate *barSet = m_series->d_func()->barsetAt(set)->d_ptr.data();
+ Bar *bar = m_bars.at(itemIndex);
+ bar->setPen(barSet->m_pen);
+ bar->setBrush(barSet->m_brush);
+ bar->update();
+
+ QGraphicsTextItem *label = m_labels.at(itemIndex);
+ QString valueLabel;
+ if (presenter()) { // At startup presenter is not yet set, yet somehow update comes
+ if (m_series->labelsFormat().isEmpty()) {
+ valueLabel = presenter()->numberToString(barSet->value(category));
+ } else {
+ valueLabel = m_series->labelsFormat();
+ valueLabel.replace(valueTag,
+ presenter()->numberToString(barSet->value(category)));
+ }
+ }
+ label->setHtml(valueLabel);
+ label->setFont(barSet->m_labelFont);
+ label->setDefaultTextColor(barSet->m_labelBrush.color());
+ label->update();
+ itemIndex++;
+ }
+ }
+ }
+}
+
+void AbstractBarChartItem::handleLabelsPositionChanged()
+{
+ positionLabels();
+}
+
+void AbstractBarChartItem::positionLabels()
+{
+ for (int i = 0; i < m_layout.count(); i++) {
+ QGraphicsTextItem *label = m_labels.at(i);
+ qreal xPos = 0;
+ qreal yPos = m_layout.at(i).center().y() - label->boundingRect().center().y();
+
+ int offset = m_bars.at(i)->pen().width() / 2 + 2;
+ if (m_series->labelsPosition() == QAbstractBarSeries::LabelsCenter)
+ xPos = m_layout.at(i).center().x() - label->boundingRect().center().x();
+ else if (m_series->labelsPosition() == QAbstractBarSeries::LabelsInsideEnd)
+ xPos = m_layout.at(i).right() - label->boundingRect().width() - offset;
+ else if (m_series->labelsPosition() == QAbstractBarSeries::LabelsInsideBase)
+ xPos = m_layout.at(i).left() + offset;
+ else if (m_series->labelsPosition() == QAbstractBarSeries::LabelsOutsideEnd)
+ xPos = m_layout.at(i).right() + offset;
+
+ label->setPos(xPos, yPos);
+ label->setZValue(zValue() + 1);
+ }
+}
+
+#include "moc_abstractbarchartitem_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/barchart/abstractbarchartitem_p.h b/src/charts/barchart/abstractbarchartitem_p.h
new file mode 100644
index 00000000..66551a62
--- /dev/null
+++ b/src/charts/barchart/abstractbarchartitem_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 ABSTRACTBARCHARTITEM_H
+#define ABSTRACTBARCHARTITEM_H
+
+#include "chartitem_p.h"
+#include "qabstractbarseries.h"
+#include <QPen>
+#include <QBrush>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class Bar;
+class QAxisCategories;
+class QChart;
+class BarAnimation;
+
+class AbstractBarChartItem : public ChartItem
+{
+ Q_OBJECT
+public:
+ AbstractBarChartItem(QAbstractBarSeries *series, QGraphicsItem* item = 0);
+ virtual ~AbstractBarChartItem();
+
+public:
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+ QRectF boundingRect() const;
+
+ virtual QVector<QRectF> calculateLayout() = 0;
+ virtual void initializeLayout() = 0;
+ virtual void applyLayout(const QVector<QRectF> &layout);
+ virtual void setAnimation(BarAnimation *animation);
+ void setLayout(const QVector<QRectF> &layout);
+ void updateLayout(const QVector<QRectF> &layout);
+ QRectF geometry() const { return m_rect;}
+
+public Q_SLOTS:
+ void handleDomainUpdated();
+ void handleLayoutChanged();
+ void handleLabelsVisibleChanged(bool visible);
+ void handleDataStructureChanged(); // structure of of series has changed, recreate graphic items
+ void handleVisibleChanged();
+ void handleOpacityChanged();
+ virtual void handleUpdatedBars();
+ void handleLabelsPositionChanged();
+ virtual void positionLabels();
+
+protected:
+
+ qreal m_domainMinX;
+ qreal m_domainMaxX;
+ qreal m_domainMinY;
+ qreal m_domainMaxY;
+
+ QRectF m_rect;
+ QVector<QRectF> m_layout;
+
+ BarAnimation *m_animation;
+
+ QAbstractBarSeries *m_series; // Not owned.
+ QList<Bar *> m_bars;
+ QList<QGraphicsTextItem *> m_labels;
+ QSizeF m_oldSize;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // ABSTRACTBARCHARTITEM_H
diff --git a/src/charts/barchart/bar.cpp b/src/charts/barchart/bar.cpp
new file mode 100644
index 00000000..de6c442f
--- /dev/null
+++ b/src/charts/barchart/bar.cpp
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "bar_p.h"
+#include <QPainter>
+#include <QGraphicsSceneEvent>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+Bar::Bar(QBarSet *barset, int index, QGraphicsItem *parent) : QGraphicsRectItem(parent),
+ m_index(index),
+ m_barset(barset),
+ m_hovering(false)
+{
+ setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton);
+ setAcceptHoverEvents(true);
+}
+
+Bar::~Bar()
+{
+ // End hover event, if bar is deleted during it
+ if (m_hovering) {
+ emit hovered(false, m_barset);
+ emit hovered(false, m_index, m_barset);
+ }
+}
+
+void Bar::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_UNUSED(event)
+ emit clicked(m_index, m_barset);
+ QGraphicsItem::mousePressEvent(event);
+}
+
+void Bar::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
+{
+ Q_UNUSED(event)
+ m_hovering = true;
+ emit hovered(true, m_barset);
+ emit hovered(true, m_index, m_barset);
+
+}
+
+void Bar::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
+{
+ Q_UNUSED(event)
+ m_hovering = false;
+ emit hovered(false, m_barset);
+ emit hovered(false, m_index, m_barset);
+}
+
+#include "moc_bar_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/barchart/bar_p.h b/src/charts/barchart/bar_p.h
new file mode 100644
index 00000000..0d46e2b6
--- /dev/null
+++ b/src/charts/barchart/bar_p.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 BAR_H
+#define BAR_H
+
+#include "qchartglobal.h"
+#include <QGraphicsRectItem>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QBarSet;
+
+// Single visual bar item of chart
+class Bar : public QObject, public QGraphicsRectItem
+{
+ Q_OBJECT
+public:
+ Bar(QBarSet *barset, int index, QGraphicsItem *parent = 0);
+ ~Bar();
+
+public:
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
+ void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
+
+Q_SIGNALS:
+ void clicked(int index, QBarSet *barset);
+ void hovered(bool status, QBarSet *barset);
+ void hovered(bool status, int index, QBarSet *barset);
+
+private:
+ int m_index;
+ QBarSet *m_barset;
+ bool m_hovering;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // BAR_H
diff --git a/src/charts/barchart/barchart.pri b/src/charts/barchart/barchart.pri
new file mode 100644
index 00000000..0e78d232
--- /dev/null
+++ b/src/charts/barchart/barchart.pri
@@ -0,0 +1,71 @@
+#Subdirectiores are defined here, because qt creator doesn't handle nested include(foo.pri) chains very well.
+
+INCLUDEPATH += $$PWD \
+ $$PWD/vertical/bar \
+ $$PWD/vertical/stacked \
+ $$PWD/vertical/percent \
+ $$PWD/horizontal/bar \
+ $$PWD/horizontal/stacked \
+ $$PWD/horizontal/percent
+
+DEPENDPATH += $$PWD \
+ $$PWD/vertical/bar \
+ $$PWD/vertical/stacked \
+ $$PWD/vertical/percent \
+ $$PWD/horizontal/bar \
+ $$PWD/horizontal/stacked \
+ $$PWD/horizontal/percent
+
+SOURCES += \
+ $$PWD/bar.cpp \
+ $$PWD/abstractbarchartitem.cpp \
+ $$PWD/qabstractbarseries.cpp \
+ $$PWD/qbarset.cpp \
+ $$PWD/qbarmodelmapper.cpp \
+ $$PWD/qvbarmodelmapper.cpp \
+ $$PWD/qhbarmodelmapper.cpp \
+ $$PWD/vertical/bar/qbarseries.cpp \
+ $$PWD/vertical/bar/barchartitem.cpp \
+ $$PWD/vertical/stacked/qstackedbarseries.cpp \
+ $$PWD/vertical/stacked/stackedbarchartitem.cpp \
+ $$PWD/vertical/percent/qpercentbarseries.cpp \
+ $$PWD/vertical/percent/percentbarchartitem.cpp \
+ $$PWD/horizontal/bar/qhorizontalbarseries.cpp \
+ $$PWD/horizontal/bar/horizontalbarchartitem.cpp \
+ $$PWD/horizontal/stacked/qhorizontalstackedbarseries.cpp \
+ $$PWD/horizontal/stacked/horizontalstackedbarchartitem.cpp \
+ $$PWD/horizontal/percent/qhorizontalpercentbarseries.cpp \
+ $$PWD/horizontal/percent/horizontalpercentbarchartitem.cpp
+
+PRIVATE_HEADERS += \
+ $$PWD/bar_p.h \
+ $$PWD/qbarset_p.h \
+ $$PWD/abstractbarchartitem_p.h \
+ $$PWD/qabstractbarseries_p.h \
+ $$PWD/qbarmodelmapper_p.h \
+ $$PWD/vertical/bar/qbarseries_p.h \
+ $$PWD/vertical/bar/barchartitem_p.h \
+ $$PWD/vertical/stacked/qstackedbarseries_p.h \
+ $$PWD/vertical/stacked/stackedbarchartitem_p.h \
+ $$PWD/vertical/percent/qpercentbarseries_p.h \
+ $$PWD/vertical/percent/percentbarchartitem_p.h \
+ $$PWD/horizontal/bar/qhorizontalbarseries_p.h \
+ $$PWD/horizontal/bar/horizontalbarchartitem_p.h \
+ $$PWD/horizontal/stacked/qhorizontalstackedbarseries_p.h \
+ $$PWD/horizontal/stacked/horizontalstackedbarchartitem_p.h \
+ $$PWD/horizontal/percent/qhorizontalpercentbarseries_p.h \
+ $$PWD/horizontal/percent/horizontalpercentbarchartitem_p.h
+
+PUBLIC_HEADERS += \
+ $$PWD/qabstractbarseries.h \
+ $$PWD/qbarset.h \
+ $$PWD/qbarmodelmapper.h \
+ $$PWD/qvbarmodelmapper.h \
+ $$PWD/qhbarmodelmapper.h \
+ $$PWD/vertical/bar/qbarseries.h \
+ $$PWD/vertical/stacked/qstackedbarseries.h \
+ $$PWD/vertical/percent/qpercentbarseries.h \
+ $$PWD/horizontal/bar/qhorizontalbarseries.h \
+ $$PWD/horizontal/stacked/qhorizontalstackedbarseries.h \
+ $$PWD/horizontal/percent/qhorizontalpercentbarseries.h
+
diff --git a/src/charts/barchart/horizontal/bar/horizontalbarchartitem.cpp b/src/charts/barchart/horizontal/bar/horizontalbarchartitem.cpp
new file mode 100644
index 00000000..d5370a2f
--- /dev/null
+++ b/src/charts/barchart/horizontal/bar/horizontalbarchartitem.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "horizontalbarchartitem_p.h"
+#include "qabstractbarseries_p.h"
+#include "qbarset_p.h"
+#include "bar_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+HorizontalBarChartItem::HorizontalBarChartItem(QAbstractBarSeries *series, QGraphicsItem* item)
+ : AbstractBarChartItem(series, item)
+{
+}
+
+void HorizontalBarChartItem::initializeLayout()
+{
+ qreal categoryCount = m_series->d_func()->categoryCount();
+ qreal setCount = m_series->count();
+ qreal barWidth = m_series->d_func()->barWidth();
+
+ m_layout.clear();
+ for(int category = 0; category < categoryCount; category++) {
+ for (int set = 0; set < setCount; set++) {
+ QRectF rect;
+ QPointF topLeft;
+ QPointF bottomRight;
+ if (domain()->type() == AbstractDomain::LogXYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) {
+ topLeft = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category - barWidth / 2 + set/setCount * barWidth), m_validData);
+ bottomRight = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category - barWidth / 2 + (set + 1)/setCount * barWidth), m_validData);
+ } else {
+ topLeft = domain()->calculateGeometryPoint(QPointF(0, category - barWidth / 2 + set/setCount * barWidth), m_validData);
+ bottomRight = domain()->calculateGeometryPoint(QPointF(0, category - barWidth / 2 + (set + 1)/setCount * barWidth), m_validData);
+ }
+
+ if (!m_validData)
+ return;
+
+ rect.setTopLeft(topLeft);
+ rect.setBottomRight(bottomRight);
+ m_layout.append(rect.normalized());
+ }
+ }
+}
+
+QVector<QRectF> HorizontalBarChartItem::calculateLayout()
+{
+ QVector<QRectF> layout;
+
+ // Use temporary qreals for accuracy
+ qreal categoryCount = m_series->d_func()->categoryCount();
+ qreal setCount = m_series->count();
+ qreal barWidth = m_series->d_func()->barWidth();
+
+ for(int category = 0; category < categoryCount; category++) {
+ for (int set = 0; set < setCount; set++) {
+ qreal value = m_series->barSets().at(set)->at(category);
+ QRectF rect;
+ QPointF topLeft;
+ if (domain()->type() == AbstractDomain::LogXYDomain || domain()->type() == AbstractDomain::LogXLogYDomain)
+ topLeft = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category - barWidth / 2 + set/setCount * barWidth), m_validData);
+ else
+ topLeft = domain()->calculateGeometryPoint(QPointF(0, category - barWidth / 2 + set/setCount * barWidth), m_validData);
+
+ QPointF bottomRight = domain()->calculateGeometryPoint(QPointF(value, category - barWidth / 2 + (set + 1)/setCount * barWidth), m_validData);
+
+ rect.setTopLeft(topLeft);
+ rect.setBottomRight(bottomRight);
+ layout.append(rect.normalized());
+ }
+ }
+ return layout;
+}
+
+#include "moc_horizontalbarchartitem_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/barchart/horizontal/bar/horizontalbarchartitem_p.h b/src/charts/barchart/horizontal/bar/horizontalbarchartitem_p.h
new file mode 100644
index 00000000..df7e793e
--- /dev/null
+++ b/src/charts/barchart/horizontal/bar/horizontalbarchartitem_p.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 HORIZONTALBARCHARTITEM_H
+#define HORIZONTALBARCHARTITEM_H
+
+#include "abstractbarchartitem_p.h"
+#include <QGraphicsItem>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class HorizontalBarChartItem : public AbstractBarChartItem
+{
+ Q_OBJECT
+public:
+ HorizontalBarChartItem(QAbstractBarSeries *series, QGraphicsItem* item = 0);
+
+private:
+ virtual QVector<QRectF> calculateLayout();
+ void initializeLayout();
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // HORIZONTALBARCHARTITEM_H
diff --git a/src/charts/barchart/horizontal/bar/qhorizontalbarseries.cpp b/src/charts/barchart/horizontal/bar/qhorizontalbarseries.cpp
new file mode 100644
index 00000000..d381aadf
--- /dev/null
+++ b/src/charts/barchart/horizontal/bar/qhorizontalbarseries.cpp
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhorizontalbarseries.h"
+#include "qhorizontalbarseries_p.h"
+#include "horizontalbarchartitem_p.h"
+#include "qbarcategoryaxis.h"
+
+#include "chartdataset_p.h"
+#include "charttheme_p.h"
+
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QHorizontalBarSeries
+ \inmodule Qt Charts
+ \brief Series for creating horizontal bar chart.
+ \mainclass
+
+ QHorizontalBarSeries represents a series of data shown as bars. The purpose of this class is to draw bars
+ as groups, where bars in same category are grouped next to each other. QHorizontalBarSeries groups the data
+ from sets to categories, which are defined by a QStringList.
+
+ See the \l {HorizontalBarChart Example} {horizontal bar chart example} to learn how to create a horizontal bar chart.
+ \image examples_horizontalbarchart.png
+
+ \sa QBarSet, QBarSeries, QPercentBarSeries, QAbstractBarSeries, QStackedBarSeries, QHorizontalStackedBarSeries, QHorizontalPercentBarSeries
+*/
+/*!
+ \qmltype HorizontalBarSeries
+ \instantiates QHorizontalBarSeries
+ \inqmlmodule QtCharts
+
+ \inherits AbstractBarSeries
+
+ \brief Series type for creating horizontal bar chart.
+
+ The following QML shows how to create a simple horizontal bar chart:
+ \snippet qmlchart/qml/qmlchart/View9.qml 1
+ \beginfloatleft
+ \image examples_qmlchart9.png
+ \endfloat
+ \clearfloat
+*/
+
+/*!
+ Constructs empty QHorizontalBarSeries.
+ QHorizontalBarSeries is QObject which is a child of a \a parent.
+*/
+QHorizontalBarSeries::QHorizontalBarSeries(QObject *parent)
+ : QAbstractBarSeries(*new QHorizontalBarSeriesPrivate(this), parent)
+{
+}
+
+/*!
+ Destructor.
+ Removes series from chart.
+*/
+QHorizontalBarSeries::~QHorizontalBarSeries()
+{
+ Q_D(QHorizontalBarSeries);
+ if (d->m_chart)
+ d->m_chart->removeSeries(this);
+}
+
+/*!
+ Returns QChartSeries::SeriesTypeHorizontalBar.
+*/
+QAbstractSeries::SeriesType QHorizontalBarSeries::type() const
+{
+ return QAbstractSeries::SeriesTypeHorizontalBar;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QHorizontalBarSeriesPrivate::QHorizontalBarSeriesPrivate(QHorizontalBarSeries *q)
+ : QAbstractBarSeriesPrivate(q)
+{
+
+}
+
+void QHorizontalBarSeriesPrivate::initializeDomain()
+{
+ qreal minX(domain()->minX());
+ qreal minY(domain()->minY());
+ qreal maxX(domain()->maxX());
+ qreal maxY(domain()->maxY());
+
+ qreal y = categoryCount();
+ minX = qMin(minX, min());
+ minY = qMin(minY, - (qreal)0.5);
+ maxX = qMax(maxX, max());
+ maxY = qMax(maxY, y - (qreal)0.5);
+
+ domain()->setRange(minX, maxX, minY, maxY);
+}
+
+void QHorizontalBarSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
+{
+ Q_Q(QHorizontalBarSeries);
+ HorizontalBarChartItem *bar = new HorizontalBarChartItem(q,parent);
+ m_item.reset(bar);
+ QAbstractSeriesPrivate::initializeGraphics(parent);
+}
+
+#include "moc_qhorizontalbarseries.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/barchart/horizontal/bar/qhorizontalbarseries.h b/src/charts/barchart/horizontal/bar/qhorizontalbarseries.h
new file mode 100644
index 00000000..b5cf137b
--- /dev/null
+++ b/src/charts/barchart/horizontal/bar/qhorizontalbarseries.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHORIZONTALBARSERIES_H
+#define QHORIZONTALBARSERIES_H
+
+#include <QtCharts/qabstractbarseries.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QHorizontalBarSeriesPrivate;
+
+class QT_CHARTS_EXPORT QHorizontalBarSeries : public QAbstractBarSeries
+{
+ Q_OBJECT
+public:
+ explicit QHorizontalBarSeries(QObject *parent = 0);
+ ~QHorizontalBarSeries();
+ QAbstractSeries::SeriesType type() const;
+
+private:
+ Q_DECLARE_PRIVATE(QHorizontalBarSeries)
+ Q_DISABLE_COPY(QHorizontalBarSeries)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QHORIZONTALBARSERIES_H
diff --git a/src/charts/barchart/horizontal/bar/qhorizontalbarseries_p.h b/src/charts/barchart/horizontal/bar/qhorizontalbarseries_p.h
new file mode 100644
index 00000000..d32ed320
--- /dev/null
+++ b/src/charts/barchart/horizontal/bar/qhorizontalbarseries_p.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QHORIZONTALBARSERIES_P_H
+#define QHORIZONTALBARSERIES_P_H
+
+#include "qabstractbarseries_p.h"
+#include "abstractdomain_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QHorizontalBarSeriesPrivate: public QAbstractBarSeriesPrivate
+{
+public:
+ QHorizontalBarSeriesPrivate(QHorizontalBarSeries *q);
+ void initializeGraphics(QGraphicsItem* parent);
+ void initializeDomain();
+private:
+ Q_DECLARE_PUBLIC(QHorizontalBarSeries)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QHORIZONTALBARSERIES_P_H
diff --git a/src/charts/barchart/horizontal/percent/horizontalpercentbarchartitem.cpp b/src/charts/barchart/horizontal/percent/horizontalpercentbarchartitem.cpp
new file mode 100644
index 00000000..0bf9afbe
--- /dev/null
+++ b/src/charts/barchart/horizontal/percent/horizontalpercentbarchartitem.cpp
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "horizontalpercentbarchartitem_p.h"
+#include "qabstractbarseries_p.h"
+#include "qbarset_p.h"
+#include "bar_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+HorizontalPercentBarChartItem::HorizontalPercentBarChartItem(QAbstractBarSeries *series, QGraphicsItem* item)
+ : AbstractBarChartItem(series, item)
+{
+}
+
+void HorizontalPercentBarChartItem::initializeLayout()
+{
+ qreal categoryCount = m_series->d_func()->categoryCount();
+ qreal setCount = m_series->count();
+ qreal barWidth = m_series->d_func()->barWidth();
+
+ m_layout.clear();
+ for(int category = 0; category < categoryCount; category++) {
+ for (int set = 0; set < setCount; set++) {
+ QRectF rect;
+ QPointF topLeft;
+ QPointF bottomRight;
+ if (domain()->type() == AbstractDomain::LogXYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) {
+ topLeft = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category - barWidth / 2), m_validData);
+ bottomRight = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category + barWidth / 2), m_validData);
+ } else {
+ topLeft = domain()->calculateGeometryPoint(QPointF(0, category - barWidth / 2), m_validData);
+ bottomRight = domain()->calculateGeometryPoint(QPointF(0, category + barWidth / 2), m_validData);
+ }
+
+ if (!m_validData)
+ return;
+
+ rect.setTopLeft(topLeft);
+ rect.setBottomRight(bottomRight);
+ m_layout.append(rect.normalized());
+ }
+ }
+}
+
+QVector<QRectF> HorizontalPercentBarChartItem::calculateLayout()
+{
+ QVector<QRectF> layout;
+
+ // Use temporary qreals for accuracy
+ qreal categoryCount = m_series->d_func()->categoryCount();
+ qreal setCount = m_series->count();
+ qreal barWidth = m_series->d_func()->barWidth();
+
+ for(int category = 0; category < categoryCount; category++) {
+ qreal sum = 0;
+ qreal categorySum = m_series->d_func()->categorySum(category);
+ for (int set = 0; set < setCount; set++) {
+ qreal value = m_series->barSets().at(set)->at(category);
+ QRectF rect;
+ qreal topX = 0;
+ if (sum > 0)
+ topX = 100 * sum / categorySum;
+ qreal bottomX = 0;
+ qreal newSum = value + sum;
+ if (newSum > 0)
+ bottomX = 100 * newSum / categorySum;
+ QPointF topLeft;
+ if (domain()->type() == AbstractDomain::LogXYDomain || domain()->type() == AbstractDomain::LogXLogYDomain)
+ topLeft = domain()->calculateGeometryPoint(QPointF(set ? topX : domain()->minX(), category - barWidth/2), m_validData);
+ else
+ topLeft = domain()->calculateGeometryPoint(QPointF(set ? topX : 0, category - barWidth/2), m_validData);
+ QPointF bottomRight = domain()->calculateGeometryPoint(QPointF(bottomX, category + barWidth/2), m_validData);
+
+ rect.setTopLeft(topLeft);
+ rect.setBottomRight(bottomRight);
+ layout.append(rect.normalized());
+ sum = newSum;
+ }
+ }
+ return layout;
+}
+
+void HorizontalPercentBarChartItem::handleUpdatedBars()
+{
+ // Handle changes in pen, brush, labels etc.
+ int categoryCount = m_series->d_func()->categoryCount();
+ int setCount = m_series->count();
+ int itemIndex(0);
+ static const QString valueTag(QLatin1String("@value"));
+
+ for (int category = 0; category < categoryCount; category++) {
+ for (int set = 0; set < setCount; set++) {
+ QBarSetPrivate *barSet = m_series->d_func()->barsetAt(set)->d_ptr.data();
+ Bar *bar = m_bars.at(itemIndex);
+ bar->setPen(barSet->m_pen);
+ bar->setBrush(barSet->m_brush);
+ bar->update();
+
+ QGraphicsTextItem *label = m_labels.at(itemIndex);
+ qreal p = m_series->d_func()->percentageAt(set, category) * 100.0;
+ QString vString(presenter()->numberToString(p, 'f', 0));
+ QString valueLabel;
+ if (m_series->labelsFormat().isEmpty()) {
+ vString.append(QStringLiteral("%"));
+ valueLabel = vString;
+ } else {
+ valueLabel = m_series->labelsFormat();
+ valueLabel.replace(valueTag, vString);
+ }
+ label->setHtml(valueLabel);
+ label->setFont(barSet->m_labelFont);
+ label->setDefaultTextColor(barSet->m_labelBrush.color());
+ label->update();
+ itemIndex++;
+ }
+ }
+}
+
+#include "moc_horizontalpercentbarchartitem_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
+
diff --git a/src/charts/barchart/horizontal/percent/horizontalpercentbarchartitem_p.h b/src/charts/barchart/horizontal/percent/horizontalpercentbarchartitem_p.h
new file mode 100644
index 00000000..e24cdcf0
--- /dev/null
+++ b/src/charts/barchart/horizontal/percent/horizontalpercentbarchartitem_p.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 HORIZONTALPERCENTBARCHARTITEM_P_H
+#define HORIZONTALPERCENTBARCHARTITEM_P_H
+
+#include "abstractbarchartitem_p.h"
+#include <QGraphicsItem>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class HorizontalPercentBarChartItem : public AbstractBarChartItem
+{
+ Q_OBJECT
+public:
+ HorizontalPercentBarChartItem(QAbstractBarSeries *series, QGraphicsItem* item = 0);
+ void handleUpdatedBars();
+
+private:
+ virtual QVector<QRectF> calculateLayout();
+ void initializeLayout();
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // HORIZONTALPERCENTBARCHARTITEM_P_H
diff --git a/src/charts/barchart/horizontal/percent/qhorizontalpercentbarseries.cpp b/src/charts/barchart/horizontal/percent/qhorizontalpercentbarseries.cpp
new file mode 100644
index 00000000..bf915c85
--- /dev/null
+++ b/src/charts/barchart/horizontal/percent/qhorizontalpercentbarseries.cpp
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qhorizontalpercentbarseries.h"
+#include "qhorizontalpercentbarseries_p.h"
+#include "horizontalpercentbarchartitem_p.h"
+
+#include "chartdataset_p.h"
+#include "charttheme_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QHorizontalPercentBarSeries
+ \inmodule Qt Charts
+ \brief Series for creating horizontal percent bar chart.
+ \mainclass
+
+ QHorizontalPercentBarSeries represents a series of data shown as bars. The purpose of this
+ class is to draw bars as groups, where bars in same category are grouped next to each other.
+ QHorizontalPercentBarSeries groups the data from sets to categories, which are defined by a
+ QStringList. Bars with zero value are not drawn.
+
+ See the \l {HorizontalPercentBarChart Example} {horizontal percent bar chart example} to learn
+ how to create a horizontal percent bar chart.
+ \image examples_horizontalpercentbarchart.png
+
+ \sa QBarSet, QBarSeries, QPercentBarSeries, QAbstractBarSeries, QStackedBarSeries,
+ QHorizontalStackedBarSeries, QHorizontalBarSeries
+*/
+/*!
+ \qmltype HorizontalPercentBarSeries
+ \instantiates QHorizontalPercentBarSeries
+ \inqmlmodule QtCharts
+
+ \inherits AbstractBarSeries
+
+ \brief Series type for creating horizontal precent bar chart.
+
+ The following QML shows how to create a simple horizontal percent bar chart:
+ \snippet qmlchart/qml/qmlchart/View11.qml 1
+ \beginfloatleft
+ \image examples_qmlchart11.png
+ \endfloat
+ \clearfloat
+*/
+
+/*!
+ Constructs empty QHorizontalPercentBarSeries.
+ QHorizontalPercentBarSeries is QObject which is a child of a \a parent.
+*/
+QHorizontalPercentBarSeries::QHorizontalPercentBarSeries(QObject *parent) :
+ QAbstractBarSeries(*new QHorizontalPercentBarSeriesPrivate(this), parent)
+{
+}
+
+/*!
+ Returns QAbstractSeries::SeriesTypeHorizontalPercentBar.
+*/
+QAbstractSeries::SeriesType QHorizontalPercentBarSeries::type() const
+{
+ return QAbstractSeries::SeriesTypeHorizontalPercentBar;
+}
+
+/*!
+ Destructor.
+ Removes series from chart.
+*/
+QHorizontalPercentBarSeries::~QHorizontalPercentBarSeries()
+{
+ Q_D(QHorizontalPercentBarSeries);
+ if (d->m_chart)
+ d->m_chart->removeSeries(this);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QHorizontalPercentBarSeriesPrivate::QHorizontalPercentBarSeriesPrivate(QHorizontalPercentBarSeries *q) : QAbstractBarSeriesPrivate(q)
+{
+
+}
+
+void QHorizontalPercentBarSeriesPrivate::initializeDomain()
+{
+ qreal minX(domain()->minX());
+ qreal minY(domain()->minY());
+ qreal maxX(domain()->maxX());
+ qreal maxY(domain()->maxY());
+
+ qreal y = categoryCount();
+ minX = 0;
+ maxX = 100;
+ minY = qMin(minY, - (qreal)0.5);
+ maxY = qMax(maxY, y - (qreal)0.5);
+
+ domain()->setRange(minX, maxX, minY, maxY);
+}
+
+void QHorizontalPercentBarSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
+{
+ Q_Q(QHorizontalPercentBarSeries);
+ HorizontalPercentBarChartItem *bar = new HorizontalPercentBarChartItem(q,parent);
+ m_item.reset(bar);
+ QAbstractSeriesPrivate::initializeGraphics(parent);
+}
+
+#include "moc_qhorizontalpercentbarseries.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/barchart/horizontal/percent/qhorizontalpercentbarseries.h b/src/charts/barchart/horizontal/percent/qhorizontalpercentbarseries.h
new file mode 100644
index 00000000..0595532b
--- /dev/null
+++ b/src/charts/barchart/horizontal/percent/qhorizontalpercentbarseries.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHORIZONTALPERCENTBARSERIES_H
+#define QHORIZONTALPERCENTBARSERIES_H
+
+#include <QtCharts/qabstractbarseries.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QHorizontalPercentBarSeriesPrivate;
+
+class QT_CHARTS_EXPORT QHorizontalPercentBarSeries : public QAbstractBarSeries
+{
+ Q_OBJECT
+public:
+ explicit QHorizontalPercentBarSeries(QObject *parent = 0);
+ ~QHorizontalPercentBarSeries();
+ QAbstractSeries::SeriesType type() const;
+
+private:
+ Q_DECLARE_PRIVATE(QHorizontalPercentBarSeries)
+ Q_DISABLE_COPY(QHorizontalPercentBarSeries)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QHORIZONTALPERCENTBARSERIES_H
diff --git a/src/charts/barchart/horizontal/percent/qhorizontalpercentbarseries_p.h b/src/charts/barchart/horizontal/percent/qhorizontalpercentbarseries_p.h
new file mode 100644
index 00000000..079f97bb
--- /dev/null
+++ b/src/charts/barchart/horizontal/percent/qhorizontalpercentbarseries_p.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QHORIZONTALPERCENTBARSERIES_P_H
+#define QHORIZONTALPERCENTBARSERIES_P_H
+
+#include "qabstractbarseries_p.h"
+#include "abstractdomain_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QHorizontalPercentBarSeriesPrivate: public QAbstractBarSeriesPrivate
+{
+public:
+ QHorizontalPercentBarSeriesPrivate(QHorizontalPercentBarSeries *q);
+ void initializeGraphics(QGraphicsItem* parent);
+ void initializeDomain();
+private:
+ Q_DECLARE_PUBLIC(QHorizontalPercentBarSeries)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QHORIZONTALPERCENTBARSERIES_P_H
diff --git a/src/charts/barchart/horizontal/stacked/horizontalstackedbarchartitem.cpp b/src/charts/barchart/horizontal/stacked/horizontalstackedbarchartitem.cpp
new file mode 100644
index 00000000..fe6f162d
--- /dev/null
+++ b/src/charts/barchart/horizontal/stacked/horizontalstackedbarchartitem.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "horizontalstackedbarchartitem_p.h"
+#include "qabstractbarseries_p.h"
+#include "qbarset_p.h"
+#include "bar_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+HorizontalStackedBarChartItem::HorizontalStackedBarChartItem(QAbstractBarSeries *series, QGraphicsItem* item)
+ : AbstractBarChartItem(series, item)
+{
+}
+
+void HorizontalStackedBarChartItem::initializeLayout()
+{
+ qreal categoryCount = m_series->d_func()->categoryCount();
+ qreal setCount = m_series->count();
+ qreal barWidth = m_series->d_func()->barWidth();
+
+ m_layout.clear();
+ for(int category = 0; category < categoryCount; category++) {
+ for (int set = 0; set < setCount; set++) {
+ QRectF rect;
+ QPointF topLeft;
+ QPointF bottomRight;
+ if (domain()->type() == AbstractDomain::LogXYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) {
+ topLeft = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category - barWidth / 2), m_validData);
+ bottomRight = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category + barWidth / 2), m_validData);
+ } else {
+ topLeft = domain()->calculateGeometryPoint(QPointF(0, category - barWidth / 2), m_validData);
+ bottomRight = domain()->calculateGeometryPoint(QPointF(0, category + barWidth / 2), m_validData);
+ }
+
+ if (!m_validData)
+ return;
+
+ rect.setTopLeft(topLeft);
+ rect.setBottomRight(bottomRight);
+ m_layout.append(rect.normalized());
+ }
+ }
+}
+
+QVector<QRectF> HorizontalStackedBarChartItem::calculateLayout()
+{
+ QVector<QRectF> layout;
+
+ // Use temporary qreals for accuracy
+ qreal categoryCount = m_series->d_func()->categoryCount();
+ qreal setCount = m_series->count();
+ qreal barWidth = m_series->d_func()->barWidth();
+
+ for(int category = 0; category < categoryCount; category++) {
+ qreal positiveSum = 0;
+ qreal negativeSum = 0;
+ for (int set = 0; set < setCount; set++) {
+ qreal value = m_series->barSets().at(set)->at(category);
+ QRectF rect;
+ QPointF topLeft;
+ QPointF bottomRight;
+ if (value < 0) {
+ bottomRight = domain()->calculateGeometryPoint(QPointF(value + negativeSum, category - barWidth / 2), m_validData);
+ if (domain()->type() == AbstractDomain::LogXYDomain || domain()->type() == AbstractDomain::LogXLogYDomain)
+ topLeft = domain()->calculateGeometryPoint(QPointF(set ? negativeSum : domain()->minX(), category + barWidth / 2), m_validData);
+ else
+ topLeft = domain()->calculateGeometryPoint(QPointF(set ? negativeSum : 0, category + barWidth / 2), m_validData);
+ negativeSum += value;
+ } else {
+ bottomRight = domain()->calculateGeometryPoint(QPointF(value + positiveSum, category - barWidth / 2), m_validData);
+ if (domain()->type() == AbstractDomain::LogXYDomain || domain()->type() == AbstractDomain::LogXLogYDomain)
+ topLeft = domain()->calculateGeometryPoint(QPointF(set ? positiveSum : domain()->minX(), category + barWidth / 2), m_validData);
+ else
+ topLeft = domain()->calculateGeometryPoint(QPointF(set ? positiveSum : 0, category + barWidth / 2), m_validData);
+ positiveSum += value;
+ }
+
+ rect.setTopLeft(topLeft);
+ rect.setBottomRight(bottomRight);
+ layout.append(rect.normalized());
+ }
+ }
+ return layout;
+}
+
+#include "moc_horizontalstackedbarchartitem_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
+
diff --git a/src/charts/barchart/horizontal/stacked/horizontalstackedbarchartitem_p.h b/src/charts/barchart/horizontal/stacked/horizontalstackedbarchartitem_p.h
new file mode 100644
index 00000000..930a53a5
--- /dev/null
+++ b/src/charts/barchart/horizontal/stacked/horizontalstackedbarchartitem_p.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 HORIZONTALSTACKEDBARCHARTITEM_P_H
+#define HORIZONTALSTACKEDBARCHARTITEM_P_H
+
+#include "abstractbarchartitem_p.h"
+#include <QGraphicsItem>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class HorizontalStackedBarChartItem : public AbstractBarChartItem
+{
+ Q_OBJECT
+public:
+ HorizontalStackedBarChartItem(QAbstractBarSeries *series, QGraphicsItem* item = 0);
+
+private:
+ virtual QVector<QRectF> calculateLayout();
+ void initializeLayout();
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // HORIZONTALSTACKEDBARCHARTITEM_P_H
diff --git a/src/charts/barchart/horizontal/stacked/qhorizontalstackedbarseries.cpp b/src/charts/barchart/horizontal/stacked/qhorizontalstackedbarseries.cpp
new file mode 100644
index 00000000..32c553bf
--- /dev/null
+++ b/src/charts/barchart/horizontal/stacked/qhorizontalstackedbarseries.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qhorizontalstackedbarseries.h"
+#include "qhorizontalstackedbarseries_p.h"
+#include "horizontalstackedbarchartitem_p.h"
+
+#include "chartdataset_p.h"
+#include "charttheme_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+/*!
+ \class QHorizontalStackedBarSeries
+ \inmodule Qt Charts
+ \brief Series for creating horizontal stacked bar chart.
+ \mainclass
+
+ QHorizontalStackedBarSeries represents a series of data shown as bars. The purpose of this class is to draw bars
+ as groups, where bars in same category are grouped next to each other. QHorizontalStackedBarSeries groups the data
+ from sets to categories, which are defined by a QStringList.
+
+ See the \l {HorizontalStackedBarChart Example} {horizontal stacked bar chart example} to learn how to create a horizontal stacked bar chart.
+ \image examples_horizontalstackedbarchart.png
+
+ \sa QBarSet, QBarSeries, QPercentBarSeries, QAbstractBarSeries, QStackedBarSeries, QHorizontalPercentBarSeries, QHorizontalBarSeries
+*/
+/*!
+ \qmltype HorizontalStackedBarSeries
+ \instantiates QHorizontalStackedBarSeries
+ \inqmlmodule QtCharts
+
+ \inherits AbstractBarSeries
+
+ \brief Series type for creating horizontal stacked bar chart.
+
+ The following QML shows how to create a simple horizontal stacked bar chart:
+ \snippet qmlchart/qml/qmlchart/View10.qml 1
+ \beginfloatleft
+ \image examples_qmlchart10.png
+ \endfloat
+ \clearfloat
+*/
+
+/*!
+ Constructs empty QHorizontalStackedBarSeries.
+ QHorizontalStackedBarSeries is QObject which is a child of a \a parent.
+*/
+QHorizontalStackedBarSeries::QHorizontalStackedBarSeries(QObject *parent)
+ : QAbstractBarSeries(*new QHorizontalStackedBarSeriesPrivate(this), parent)
+{
+}
+
+/*!
+ Destructor.
+ Removes series from chart.
+*/
+QHorizontalStackedBarSeries::~QHorizontalStackedBarSeries()
+{
+ Q_D(QHorizontalStackedBarSeries);
+ if (d->m_chart)
+ d->m_chart->removeSeries(this);
+}
+
+/*!
+ Returns QAbstractSeries::SeriesTypeHorizontalStackedBar.
+*/
+QAbstractSeries::SeriesType QHorizontalStackedBarSeries::type() const
+{
+ return QAbstractSeries::SeriesTypeHorizontalStackedBar;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QHorizontalStackedBarSeriesPrivate::QHorizontalStackedBarSeriesPrivate(QHorizontalStackedBarSeries *q) : QAbstractBarSeriesPrivate(q)
+{
+
+}
+
+void QHorizontalStackedBarSeriesPrivate::initializeDomain()
+{
+ qreal minX(domain()->minX());
+ qreal minY(domain()->minY());
+ qreal maxX(domain()->maxX());
+ qreal maxY(domain()->maxY());
+
+ qreal y = categoryCount();
+ minX = qMin(minX, bottom());
+ minY = qMin(minY, - (qreal)0.5);
+ maxX = qMax(maxX, top());
+ maxY = qMax(maxY, y - (qreal)0.5);
+
+ domain()->setRange(minX, maxX, minY, maxY);
+}
+
+void QHorizontalStackedBarSeriesPrivate::initializeGraphics(QGraphicsItem *parent)
+{
+ Q_Q(QHorizontalStackedBarSeries);
+ HorizontalStackedBarChartItem *bar = new HorizontalStackedBarChartItem(q,parent);
+ m_item.reset(bar);
+ QAbstractSeriesPrivate::initializeGraphics(parent);
+}
+
+#include "moc_qhorizontalstackedbarseries.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/barchart/horizontal/stacked/qhorizontalstackedbarseries.h b/src/charts/barchart/horizontal/stacked/qhorizontalstackedbarseries.h
new file mode 100644
index 00000000..fbcf4011
--- /dev/null
+++ b/src/charts/barchart/horizontal/stacked/qhorizontalstackedbarseries.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHORIZONTALSTACKEDBARSERIES_H
+#define QHORIZONTALSTACKEDBARSERIES_H
+
+#include <QtCharts/qabstractbarseries.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QHorizontalStackedBarSeriesPrivate;
+
+class QT_CHARTS_EXPORT QHorizontalStackedBarSeries : public QAbstractBarSeries
+{
+ Q_OBJECT
+public:
+ explicit QHorizontalStackedBarSeries(QObject *parent = 0);
+ ~QHorizontalStackedBarSeries();
+ QAbstractSeries::SeriesType type() const;
+
+private:
+ Q_DECLARE_PRIVATE(QHorizontalStackedBarSeries)
+ Q_DISABLE_COPY(QHorizontalStackedBarSeries)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QHORIZONTALSTACKEDBARSERIES_H
diff --git a/src/charts/barchart/horizontal/stacked/qhorizontalstackedbarseries_p.h b/src/charts/barchart/horizontal/stacked/qhorizontalstackedbarseries_p.h
new file mode 100644
index 00000000..ab643ebd
--- /dev/null
+++ b/src/charts/barchart/horizontal/stacked/qhorizontalstackedbarseries_p.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QHORIZONTALSTACKEDBARSERIES_P_H
+#define QHORIZONTALSTACKEDBARSERIES_P_H
+
+#include "qabstractbarseries_p.h"
+#include "abstractdomain_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QHorizontalStackedBarSeriesPrivate: public QAbstractBarSeriesPrivate
+{
+public:
+ QHorizontalStackedBarSeriesPrivate(QHorizontalStackedBarSeries *q);
+ void initializeGraphics(QGraphicsItem* parent);
+ void initializeDomain();
+private:
+ Q_DECLARE_PUBLIC(QHorizontalStackedBarSeries)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QHORIZONTALSTACKEDBARSERIES_P_H
diff --git a/src/charts/barchart/qabstractbarseries.cpp b/src/charts/barchart/qabstractbarseries.cpp
new file mode 100644
index 00000000..08345112
--- /dev/null
+++ b/src/charts/barchart/qabstractbarseries.cpp
@@ -0,0 +1,1030 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qabstractbarseries.h"
+#include "qabstractbarseries_p.h"
+#include "qbarset.h"
+#include "qbarset_p.h"
+#include "abstractdomain_p.h"
+#include "chartdataset_p.h"
+#include "charttheme_p.h"
+#include "qvalueaxis.h"
+#include "qbarcategoryaxis.h"
+#include "qbarlegendmarker.h"
+#include "baranimation_p.h"
+#include "abstractbarchartitem_p.h"
+#include "qchart_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QAbstractBarSeries
+ \inmodule Qt Charts
+ \brief Series for creating a bar chart.
+ \mainclass
+
+ QAbstractBarSeries represents a series of data shown as bars. The purpose of this class is to draw bars to
+ the position defined by data. Single bar is defined by QPointF, where x value is the x-coordinate of the bar
+ and y-value is the height of the bar. The category names are ignored with this series and x-axis
+ shows the x-values.
+
+ See the \l {BarChart Example} {bar chart example} to learn how to create a simple bar chart.
+ \image examples_barchart.png
+
+ \sa QBarSet, QStackedBarSeries, QPercentBarSeries
+*/
+/*!
+ \qmltype AbstractBarSeries
+ \instantiates QAbstractBarSeries
+ \inqmlmodule QtCharts
+
+ \inherits AbstractSeries
+
+ \brief Series type for creating a bar chart.
+
+ The following QML shows how to create a simple bar chart:
+ \snippet qmlchart/qml/qmlchart/View6.qml 1
+
+ \beginfloatleft
+ \image examples_qmlchart6.png
+ \endfloat
+ \clearfloat
+*/
+
+/*!
+ \qmlproperty AbstractAxis AbstractBarSeries::axisX
+ The x axis used for the series. If you leave both axisX and axisXTop undefined, a BarCategoriesAxis is created for
+ the series.
+ \sa axisXTop
+*/
+
+/*!
+ \qmlproperty AbstractAxis AbstractBarSeries::axisY
+ The y axis used for the series. If you leave both axisY and axisYRight undefined, a ValueAxis is created for
+ the series.
+ \sa axisYRight
+*/
+
+/*!
+ \qmlproperty AbstractAxis AbstractBarSeries::axisXTop
+ The x axis used for the series, drawn on top of the chart view. Note that you can only provide either axisX or
+ axisXTop, but not both.
+ \sa axisX
+*/
+
+/*!
+ \qmlproperty AbstractAxis AbstractBarSeries::axisYRight
+ The y axis used for the series, drawn to the right on the chart view. Note that you can only provide either axisY
+ or axisYRight, but not both.
+ \sa axisY
+*/
+
+/*!
+ \property QAbstractBarSeries::barWidth
+ The width of the bars of the series. The unit of \a width is the unit of x-axis. The minimum width for bars
+ is zero and negative values are treated as zero. Setting the width to zero means that width of the bar on screen
+ is one pixel no matter what the scale of x-axis is. Bars wider than zero are scaled with x-axis.
+ Note that with QBarSeries this value means the width of one group of bars instead of just one bar.
+ \sa QBarSeries
+*/
+/*!
+ \qmlproperty real AbstractBarSeries::barWidth
+ The width of the bars of the series. The unit of width is the unit of x-axis. The minimum width for bars
+ is zero and negative values are treated as zero. Setting the width to zero means that width of the bar on screen
+ is one pixel no matter what the scale of x-axis is. Bars wider than zero are scaled with x-axis.
+ Note that with QBarSeries this value means the width of one group of bars instead of just one bar.
+*/
+
+/*!
+ \property QAbstractBarSeries::count
+ Holds the number of sets in series.
+*/
+/*!
+ \qmlproperty int AbstractBarSeries::count
+ Holds the number of sets in series.
+*/
+
+/*!
+ \property QAbstractBarSeries::labelsVisible
+ Defines the visibility of the labels in series
+*/
+/*!
+ \qmlproperty bool AbstractBarSeries::labelsVisible
+ Defines the visibility of the labels in series
+*/
+
+/*!
+ \property QAbstractBarSeries::labelsFormat
+ The \a format used for showing labels in series.
+
+ QAbstractBarSeries supports the following format tag:
+ \table
+ \row
+ \li @value \li The value of the bar
+ \endtable
+
+ For example, the following usage of the format tags would produce labels that show the value
+ followed by unit ('u'):
+ \code
+ series->setLabelsFormat("@value u");
+ \endcode
+
+ By default, the labels shows the value of the bar. For percent bar series '%' is added after
+ the value. The labels are shown on the plot area, labels on the edge of the plot area are cut.
+ If the bars are close to each other the labels may overlap.
+
+ \sa QAbstractBarSeries::labelsVisible, QAbstractBarSeries::labelsPosition
+*/
+/*!
+ \qmlproperty string AbstractBarSeries::labelsFormat
+ The format used for showing labels in series.
+
+ \sa QAbstractBarSeries::labelsFormat, labelsVisible, labelsPosition
+*/
+/*!
+ \fn void QAbstractBarSeries::labelsFormatChanged(const QString &format)
+ Signal is emitted when the \a format of data value labels is changed.
+*/
+/*!
+ \qmlsignal XYSeries::onLabelsFormatChanged(string format)
+ Signal is emitted when the \a format of data value labels is changed.
+*/
+
+/*!
+ \enum QAbstractBarSeries::LabelsPosition
+
+ This enum describes the position of the data value labels.
+
+ \value LabelsCenter Label is in the center of the bar.
+ \value LabelsInsideEnd Label is inside the bar at the high end of it.
+ \value LabelsInsideBase Label is inside the bar at the low end of it.
+ \value LabelsOutsideEnd Label is outside the bar at the high end of it.
+ */
+
+/*!
+ \property QAbstractBarSeries::labelsPosition
+ Defines the \a position of value labels.
+
+ \sa QAbstractBarSeries::labelsVisible, QAbstractBarSeries::labelsFormat
+*/
+/*!
+ \qmlproperty string AbstractBarSeries::labelsPosition
+ Defines the \a position of value labels.
+
+ \sa labelsVisible, labelsFormat
+*/
+/*!
+ \fn void QAbstractBarSeries::labelsPositionChanged(QAbstractBarSeries::LabelsPosition position)
+ Signal is emitted when the \a position of value labels is changed.
+*/
+/*!
+ \qmlsignal AbstractBarSeries::onLabelsPositionChanged(LabelsPosition position)
+ Signal is emitted when the \a position of value labels is changed.
+*/
+
+/*!
+ \fn void QAbstractBarSeries::clicked(int index, QBarSet *barset)
+ The signal is emitted if the user clicks with a mouse on top of QBarSet \a barset.
+ Clicked bar inside set is indexed by \a index
+*/
+/*!
+ \qmlsignal AbstractBarSeries::onClicked(int index, BarSet barset)
+ The signal is emitted if the user clicks with a mouse on top of BarSet.
+ Clicked bar inside set is indexed by \a index
+*/
+
+/*!
+ \fn void QAbstractBarSeries::hovered(bool status, QBarSet* barset)
+
+ The signal is emitted if mouse is hovered on top of series.
+ Parameter \a barset is the pointer of barset, where hover happened.
+ Parameter \a status is true, if mouse entered on top of series, false if mouse left from top of series.
+*/
+
+/*!
+ \fn void QAbstractBarSeries::hovered(bool status, int index, QBarSet* barset)
+
+ The signal is emitted if mouse is hovered on top of series.
+ Parameter \a barset is the pointer of barset, where hover happened.
+ Parameter \a status is true, if mouse entered on top of series, false if mouse left from top of series.
+ Hovered bar inside the set is indexed by \a index.
+*/
+/*!
+ \qmlsignal AbstractBarSeries::onHovered(bool status, int index, BarSet barset)
+
+ The signal is emitted if mouse is hovered on top of series.
+ Parameter \a barset is the pointer of barset, where hover happened.
+ Parameter \a status is true, if mouse entered on top of series, false if mouse left from top of series.
+ Hovered bar inside the set is indexed by \a index.
+*/
+
+/*!
+ \fn void QAbstractBarSeries::countChanged()
+ This signal is emitted when barset count has been changed, for example by append or remove.
+*/
+/*!
+ \qmlsignal AbstractBarSeries::onCountChanged()
+ This signal is emitted when barset count has been changed, for example by append or remove.
+*/
+
+/*!
+ \fn void QAbstractBarSeries::labelsVisibleChanged()
+ This signal is emitted when labels visibility have changed.
+ \sa isLabelsVisible(), setLabelsVisible()
+*/
+
+/*!
+ \fn void QAbstractBarSeries::barsetsAdded(QList<QBarSet*> sets)
+ This signal is emitted when \a sets have been added to the series.
+ \sa append(), insert()
+*/
+/*!
+ \qmlsignal AbstractBarSeries::onBarsetsAdded(BarSet barset)
+ Emitted when \a barset has been added to the series.
+*/
+
+/*!
+ \fn void QAbstractBarSeries::barsetsRemoved(QList<QBarSet*> sets)
+ This signal is emitted when \a sets have been removed from the series.
+ \sa remove()
+*/
+/*!
+ \qmlsignal AbstractBarSeries::onBarsetsRemoved(BarSet barset)
+ Emitted when \a barset has been removed from the series.
+*/
+
+/*!
+ \qmlmethod BarSet AbstractBarSeries::at(int index)
+ Returns bar set at \a index. Returns null if the index is not valid.
+*/
+
+/*!
+ \qmlmethod BarSet AbstractBarSeries::append(string label, VariantList values)
+ Adds a new bar set with \a label and \a values to \a index. Values is a list of reals.
+ For example:
+ \code
+ myBarSeries.append("set 1", [0, 0.2, 0.2, 0.5, 0.4, 1.5, 0.9]);
+ \endcode
+*/
+
+/*!
+ \qmlmethod BarSet AbstractBarSeries::insert(int index, string label, VariantList values)
+ Inserts a new bar set with \a label and \a values to \a index. Values can be a list of reals or a list of XYPoints.
+ If index is zero or smaller, the new barset is prepended. If the index is count or bigger, the new barset is
+ appended.
+ \sa AbstractBarSeries::append()
+*/
+
+/*!
+ \qmlmethod bool AbstractBarSeries::remove(BarSet barset)
+ Removes the barset from the series. Returns true if successful, false otherwise.
+*/
+
+/*!
+ \qmlmethod AbstractBarSeries::clear()
+ Removes all barsets from the series.
+*/
+
+/*!
+ Destructs abstractbarseries and owned barsets.
+*/
+QAbstractBarSeries::~QAbstractBarSeries()
+{
+
+}
+
+/*!
+ \internal
+*/
+QAbstractBarSeries::QAbstractBarSeries(QAbstractBarSeriesPrivate &o, QObject *parent)
+ : QAbstractSeries(o, parent)
+{
+ Q_D(QAbstractSeries);
+ QObject::connect(this, SIGNAL(countChanged()), d, SIGNAL(countChanged()));
+}
+
+/*!
+ Sets the width of the bars of the series. The unit of \a width is the unit of x-axis. The minimum width for bars
+ is zero and negative values are treated as zero. Setting the width to zero means that width of the bar on screen
+ is one pixel no matter what the scale of x-axis is. Bars wider than zero are scaled with x-axis.
+ Note that with \link QBarSeries \endlink this value means the width of one group of bars instead of just one bar.
+*/
+void QAbstractBarSeries::setBarWidth(qreal width)
+{
+ Q_D(QAbstractBarSeries);
+ d->setBarWidth(width);
+}
+
+/*!
+ Returns the width of the bars of the series.
+ \sa setBarWidth()
+*/
+qreal QAbstractBarSeries::barWidth() const
+{
+ Q_D(const QAbstractBarSeries);
+ return d->barWidth();
+}
+
+/*!
+ Adds a set of bars to series. Takes ownership of \a set. If the set is null or is already in series, it won't be appended.
+ Returns true, if appending succeeded.
+*/
+bool QAbstractBarSeries::append(QBarSet *set)
+{
+ Q_D(QAbstractBarSeries);
+ bool success = d->append(set);
+ if (success) {
+ QList<QBarSet *> sets;
+ sets.append(set);
+ set->setParent(this);
+ emit barsetsAdded(sets);
+ emit countChanged();
+ }
+ return success;
+}
+
+/*!
+ Removes barset from series. Releases ownership of \a set. Deletes the set, if remove
+ was successful.
+ Returns true, if set was removed.
+*/
+bool QAbstractBarSeries::remove(QBarSet *set)
+{
+ Q_D(QAbstractBarSeries);
+ bool success = d->remove(set);
+ if (success) {
+ QList<QBarSet *> sets;
+ sets.append(set);
+ set->setParent(0);
+ emit barsetsRemoved(sets);
+ emit countChanged();
+ delete set;
+ set = 0;
+ }
+ return success;
+}
+
+/*!
+ Takes a single \a set from the series. Does not delete the barset object.
+
+ NOTE: The series remains as the barset's parent object. You must set the
+ parent object to take full ownership.
+
+ Returns true if take was successful.
+*/
+bool QAbstractBarSeries::take(QBarSet *set)
+{
+ Q_D(QAbstractBarSeries);
+ bool success = d->remove(set);
+ if (success) {
+ QList<QBarSet *> sets;
+ sets.append(set);
+ emit barsetsRemoved(sets);
+ emit countChanged();
+ }
+ return success;
+}
+
+/*!
+ Adds a list of barsets to series. Takes ownership of \a sets.
+ Returns true, if all sets were appended successfully. If any of the sets is null or is already appended to series,
+ nothing is appended and function returns false. If any of the sets is in list more than once, nothing is appended
+ and function returns false.
+*/
+bool QAbstractBarSeries::append(QList<QBarSet *> sets)
+{
+ Q_D(QAbstractBarSeries);
+ bool success = d->append(sets);
+ if (success) {
+ emit barsetsAdded(sets);
+ emit countChanged();
+ }
+ return success;
+}
+
+/*!
+ Insert a set of bars to series at \a index postion. Takes ownership of \a set. If the set is null or is already in series, it won't be appended.
+ Returns true, if inserting succeeded.
+
+*/
+bool QAbstractBarSeries::insert(int index, QBarSet *set)
+{
+ Q_D(QAbstractBarSeries);
+ bool success = d->insert(index, set);
+ if (success) {
+ QList<QBarSet *> sets;
+ sets.append(set);
+ emit barsetsAdded(sets);
+ emit countChanged();
+ }
+ return success;
+}
+
+/*!
+ Removes all barsets from the series. Deletes removed sets.
+*/
+void QAbstractBarSeries::clear()
+{
+ Q_D(QAbstractBarSeries);
+ QList<QBarSet *> sets = barSets();
+ bool success = d->remove(sets);
+ if (success) {
+ emit barsetsRemoved(sets);
+ emit countChanged();
+ foreach (QBarSet *set, sets)
+ delete set;
+ }
+}
+
+/*!
+ Returns number of sets in series.
+*/
+int QAbstractBarSeries::count() const
+{
+ Q_D(const QAbstractBarSeries);
+ return d->m_barSets.count();
+}
+
+/*!
+ Returns a list of sets in series. Keeps ownership of sets.
+ */
+QList<QBarSet *> QAbstractBarSeries::barSets() const
+{
+ Q_D(const QAbstractBarSeries);
+ return d->m_barSets;
+}
+
+/*!
+ Sets the visibility of labels in series to \a visible
+*/
+void QAbstractBarSeries::setLabelsVisible(bool visible)
+{
+ Q_D(QAbstractBarSeries);
+ if (d->m_labelsVisible != visible) {
+ d->setLabelsVisible(visible);
+ emit labelsVisibleChanged();
+ }
+}
+
+/*!
+ Returns the visibility of labels
+*/
+bool QAbstractBarSeries::isLabelsVisible() const
+{
+ Q_D(const QAbstractBarSeries);
+ return d->m_labelsVisible;
+}
+
+void QAbstractBarSeries::setLabelsFormat(const QString &format)
+{
+ Q_D(QAbstractBarSeries);
+ if (d->m_labelsFormat != format) {
+ d->m_labelsFormat = format;
+ emit labelsFormatChanged(format);
+ }
+}
+
+QString QAbstractBarSeries::labelsFormat() const
+{
+ Q_D(const QAbstractBarSeries);
+ return d->m_labelsFormat;
+}
+
+void QAbstractBarSeries::setLabelsPosition(QAbstractBarSeries::LabelsPosition position)
+{
+ Q_D(QAbstractBarSeries);
+ if (d->m_labelsPosition != position) {
+ d->m_labelsPosition = position;
+ emit labelsPositionChanged(position);
+ }
+}
+
+QAbstractBarSeries::LabelsPosition QAbstractBarSeries::labelsPosition() const
+{
+ Q_D(const QAbstractBarSeries);
+ return d->m_labelsPosition;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QAbstractBarSeriesPrivate::QAbstractBarSeriesPrivate(QAbstractBarSeries *q) :
+ QAbstractSeriesPrivate(q),
+ m_barWidth(0.5), // Default value is 50% of category width
+ m_labelsVisible(false),
+ m_visible(true),
+ m_blockBarUpdate(false),
+ m_labelsFormat(),
+ m_labelsPosition(QAbstractBarSeries::LabelsCenter)
+{
+}
+
+int QAbstractBarSeriesPrivate::categoryCount() const
+{
+ // No categories defined. return count of longest set.
+ int count = 0;
+ for (int i = 0; i < m_barSets.count(); i++) {
+ if (m_barSets.at(i)->count() > count)
+ count = m_barSets.at(i)->count();
+ }
+
+ return count;
+}
+
+void QAbstractBarSeriesPrivate::setBarWidth(qreal width)
+{
+ if (width < 0.0)
+ width = 0.0;
+ m_barWidth = width;
+ emit updatedLayout();
+}
+
+qreal QAbstractBarSeriesPrivate::barWidth() const
+{
+ return m_barWidth;
+}
+
+QBarSet *QAbstractBarSeriesPrivate::barsetAt(int index)
+{
+ return m_barSets.at(index);
+}
+
+void QAbstractBarSeriesPrivate::setVisible(bool visible)
+{
+ m_visible = visible;
+ emit visibleChanged();
+}
+
+void QAbstractBarSeriesPrivate::setLabelsVisible(bool visible)
+{
+ m_labelsVisible = visible;
+ emit labelsVisibleChanged(visible);
+}
+
+qreal QAbstractBarSeriesPrivate::min()
+{
+ if (m_barSets.count() <= 0)
+ return 0;
+
+ qreal min = INT_MAX;
+
+ for (int i = 0; i < m_barSets.count(); i++) {
+ int categoryCount = m_barSets.at(i)->count();
+ for (int j = 0; j < categoryCount; j++) {
+ qreal temp = m_barSets.at(i)->at(j);
+ if (temp < min)
+ min = temp;
+ }
+ }
+ return min;
+}
+
+qreal QAbstractBarSeriesPrivate::max()
+{
+ if (m_barSets.count() <= 0)
+ return 0;
+
+ qreal max = INT_MIN;
+
+ for (int i = 0; i < m_barSets.count(); i++) {
+ int categoryCount = m_barSets.at(i)->count();
+ for (int j = 0; j < categoryCount; j++) {
+ qreal temp = m_barSets.at(i)->at(j);
+ if (temp > max)
+ max = temp;
+ }
+ }
+
+ return max;
+}
+
+qreal QAbstractBarSeriesPrivate::valueAt(int set, int category)
+{
+ if ((set < 0) || (set >= m_barSets.count()))
+ return 0; // No set, no value.
+ else if ((category < 0) || (category >= m_barSets.at(set)->count()))
+ return 0; // No category, no value.
+
+ return m_barSets.at(set)->at(category);
+}
+
+qreal QAbstractBarSeriesPrivate::percentageAt(int set, int category)
+{
+ if ((set < 0) || (set >= m_barSets.count()))
+ return 0; // No set, no value.
+ else if ((category < 0) || (category >= m_barSets.at(set)->count()))
+ return 0; // No category, no value.
+
+ qreal value = m_barSets.at(set)->at(category);
+ qreal sum = categorySum(category);
+ if (qFuzzyCompare(sum, 0))
+ return 0;
+
+ return value / sum;
+}
+
+qreal QAbstractBarSeriesPrivate::categorySum(int category)
+{
+ qreal sum(0);
+ int count = m_barSets.count(); // Count sets
+ for (int set = 0; set < count; set++) {
+ if (category < m_barSets.at(set)->count())
+ sum += m_barSets.at(set)->at(category);
+ }
+ return sum;
+}
+
+qreal QAbstractBarSeriesPrivate::absoluteCategorySum(int category)
+{
+ qreal sum(0);
+ int count = m_barSets.count(); // Count sets
+ for (int set = 0; set < count; set++) {
+ if (category < m_barSets.at(set)->count())
+ sum += qAbs(m_barSets.at(set)->at(category));
+ }
+ return sum;
+}
+
+qreal QAbstractBarSeriesPrivate::maxCategorySum()
+{
+ qreal max = INT_MIN;
+ int count = categoryCount();
+ for (int i = 0; i < count; i++) {
+ qreal sum = categorySum(i);
+ if (sum > max)
+ max = sum;
+ }
+ return max;
+}
+
+qreal QAbstractBarSeriesPrivate::minX()
+{
+ if (m_barSets.count() <= 0)
+ return 0;
+
+ qreal min = INT_MAX;
+
+ for (int i = 0; i < m_barSets.count(); i++) {
+ int categoryCount = m_barSets.at(i)->count();
+ for (int j = 0; j < categoryCount; j++) {
+ qreal temp = m_barSets.at(i)->d_ptr.data()->m_values.at(j).x();
+ if (temp < min)
+ min = temp;
+ }
+ }
+ return min;
+}
+
+qreal QAbstractBarSeriesPrivate::maxX()
+{
+ if (m_barSets.count() <= 0)
+ return 0;
+
+ qreal max = INT_MIN;
+
+ for (int i = 0; i < m_barSets.count(); i++) {
+ int categoryCount = m_barSets.at(i)->count();
+ for (int j = 0; j < categoryCount; j++) {
+ qreal temp = m_barSets.at(i)->d_ptr.data()->m_values.at(j).x();
+ if (temp > max)
+ max = temp;
+ }
+ }
+
+ return max;
+}
+
+qreal QAbstractBarSeriesPrivate::categoryTop(int category)
+{
+ // Returns top (sum of all positive values) of category.
+ // Returns 0, if all values are negative
+ qreal top(0);
+ int count = m_barSets.count();
+ for (int set = 0; set < count; set++) {
+ if (category < m_barSets.at(set)->count()) {
+ qreal temp = m_barSets.at(set)->at(category);
+ if (temp > 0) {
+ top += temp;
+ }
+ }
+ }
+ return top;
+}
+
+qreal QAbstractBarSeriesPrivate::categoryBottom(int category)
+{
+ // Returns bottom (sum of all negative values) of category
+ // Returns 0, if all values are positive
+ qreal bottom(0);
+ int count = m_barSets.count();
+ for (int set = 0; set < count; set++) {
+ if (category < m_barSets.at(set)->count()) {
+ qreal temp = m_barSets.at(set)->at(category);
+ if (temp < 0) {
+ bottom += temp;
+ }
+ }
+ }
+ return bottom;
+}
+
+qreal QAbstractBarSeriesPrivate::top()
+{
+ // Returns top of all categories
+ qreal top(0);
+ int count = categoryCount();
+ for (int i = 0; i < count; i++) {
+ qreal temp = categoryTop(i);
+ if (temp > top)
+ top = temp;
+ }
+ return top;
+}
+
+qreal QAbstractBarSeriesPrivate::bottom()
+{
+ // Returns bottom of all categories
+ qreal bottom(0);
+ int count = categoryCount();
+ for (int i = 0; i < count; i++) {
+ qreal temp = categoryBottom(i);
+ if (temp < bottom)
+ bottom = temp;
+ }
+ return bottom;
+}
+
+bool QAbstractBarSeriesPrivate::blockBarUpdate()
+{
+ return m_blockBarUpdate;
+}
+
+void QAbstractBarSeriesPrivate::initializeDomain()
+{
+ qreal minX(domain()->minX());
+ qreal minY(domain()->minY());
+ qreal maxX(domain()->maxX());
+ qreal maxY(domain()->maxY());
+
+ qreal seriesMinX = this->minX();
+ qreal seriesMaxX = this->maxX();
+ qreal y = max();
+ minX = qMin(minX, seriesMinX - (qreal)0.5);
+ minY = qMin(minY, y);
+ maxX = qMax(maxX, seriesMaxX + (qreal)0.5);
+ maxY = qMax(maxY, y);
+
+ domain()->setRange(minX, maxX, minY, maxY);
+}
+
+QList<QLegendMarker*> QAbstractBarSeriesPrivate::createLegendMarkers(QLegend* legend)
+{
+ Q_Q(QAbstractBarSeries);
+ QList<QLegendMarker*> markers;
+
+ foreach(QBarSet* set, q->barSets()) {
+ QBarLegendMarker* marker = new QBarLegendMarker(q,set,legend);
+ markers << marker;
+ }
+ return markers;
+}
+
+
+bool QAbstractBarSeriesPrivate::append(QBarSet *set)
+{
+ if ((m_barSets.contains(set)) || (set == 0))
+ return false; // Fail if set is already in list or set is null.
+
+ m_barSets.append(set);
+ QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
+ QObject::connect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars()));
+ QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars()));
+
+ emit restructuredBars(); // this notifies barchartitem
+ return true;
+}
+
+bool QAbstractBarSeriesPrivate::remove(QBarSet *set)
+{
+ if (!m_barSets.contains(set))
+ return false; // Fail if set is not in list
+
+ m_barSets.removeOne(set);
+ QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
+ QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars()));
+ QObject::disconnect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars()));
+
+ emit restructuredBars(); // this notifies barchartitem
+ return true;
+}
+
+bool QAbstractBarSeriesPrivate::append(QList<QBarSet * > sets)
+{
+ foreach (QBarSet *set, sets) {
+ if ((set == 0) || (m_barSets.contains(set)))
+ return false; // Fail if any of the sets is null or is already appended.
+ if (sets.count(set) != 1)
+ return false; // Also fail if same set is more than once in given list.
+ }
+
+ foreach (QBarSet *set, sets) {
+ m_barSets.append(set);
+ QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
+ QObject::connect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars()));
+ QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars()));
+ }
+
+ emit restructuredBars(); // this notifies barchartitem
+ return true;
+}
+
+bool QAbstractBarSeriesPrivate::remove(QList<QBarSet * > sets)
+{
+ if (sets.count() == 0)
+ return false;
+
+ foreach (QBarSet *set, sets) {
+ if ((set == 0) || (!m_barSets.contains(set)))
+ return false; // Fail if any of the sets is null or is not in series
+ if (sets.count(set) != 1)
+ return false; // Also fail if same set is more than once in given list.
+ }
+
+ foreach (QBarSet *set, sets) {
+ m_barSets.removeOne(set);
+ QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
+ QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars()));
+ QObject::disconnect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars()));
+ }
+
+ emit restructuredBars(); // this notifies barchartitem
+
+ return true;
+}
+
+bool QAbstractBarSeriesPrivate::insert(int index, QBarSet *set)
+{
+ if ((m_barSets.contains(set)) || (set == 0))
+ return false; // Fail if set is already in list or set is null.
+
+ m_barSets.insert(index, set);
+ QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
+ QObject::connect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars()));
+ QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars()));
+
+ emit restructuredBars(); // this notifies barchartitem
+ return true;
+}
+
+void QAbstractBarSeriesPrivate::initializeAxes()
+{
+ Q_Q(QAbstractBarSeries);
+
+ foreach(QAbstractAxis* axis, m_axes) {
+
+ if (axis->type() == QAbstractAxis::AxisTypeBarCategory) {
+ switch (q->type()) {
+ case QAbstractSeries::SeriesTypeHorizontalBar:
+ case QAbstractSeries::SeriesTypeHorizontalPercentBar:
+ case QAbstractSeries::SeriesTypeHorizontalStackedBar:
+ if (axis->orientation() == Qt::Vertical)
+ populateCategories(qobject_cast<QBarCategoryAxis *>(axis));
+ break;
+ case QAbstractSeries::SeriesTypeBar:
+ case QAbstractSeries::SeriesTypePercentBar:
+ case QAbstractSeries::SeriesTypeStackedBar:
+ case QAbstractSeries::SeriesTypeBoxPlot:
+ if (axis->orientation() == Qt::Horizontal)
+ populateCategories(qobject_cast<QBarCategoryAxis *>(axis));
+ break;
+ default:
+ qWarning() << "Unexpected series type";
+ break;
+ }
+ }
+ }
+}
+
+QAbstractAxis::AxisType QAbstractBarSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
+{
+ Q_Q(const QAbstractBarSeries);
+
+ switch (q->type()) {
+ case QAbstractSeries::SeriesTypeHorizontalBar:
+ case QAbstractSeries::SeriesTypeHorizontalPercentBar:
+ case QAbstractSeries::SeriesTypeHorizontalStackedBar:
+ if (orientation == Qt::Vertical)
+ return QAbstractAxis::AxisTypeBarCategory;
+ break;
+ case QAbstractSeries::SeriesTypeBar:
+ case QAbstractSeries::SeriesTypePercentBar:
+ case QAbstractSeries::SeriesTypeStackedBar:
+ case QAbstractSeries::SeriesTypeBoxPlot:
+ if (orientation == Qt::Horizontal)
+ return QAbstractAxis::AxisTypeBarCategory;
+ break;
+ default:
+ qWarning() << "Unexpected series type";
+ break;
+ }
+ return QAbstractAxis::AxisTypeValue;
+
+}
+
+void QAbstractBarSeriesPrivate::populateCategories(QBarCategoryAxis *axis)
+{
+ QStringList categories;
+ if (axis->categories().isEmpty()) {
+ for (int i(1); i < categoryCount() + 1; i++)
+ categories << presenter()->numberToString(i);
+ axis->append(categories);
+ }
+}
+
+QAbstractAxis* QAbstractBarSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const
+{
+ if (defaultAxisType(orientation) == QAbstractAxis::AxisTypeBarCategory)
+ return new QBarCategoryAxis;
+ else
+ return new QValueAxis;
+}
+
+void QAbstractBarSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
+{
+ m_blockBarUpdate = true; // Ensures that the bars are not updated before the theme is ready
+
+ const QList<QGradient> gradients = theme->seriesGradients();
+
+ qreal takeAtPos = 0.5;
+ qreal step = 0.2;
+ if (m_barSets.count() > 1) {
+ step = 1.0 / (qreal) m_barSets.count();
+ if (m_barSets.count() % gradients.count())
+ step *= gradients.count();
+ else
+ step *= (gradients.count() - 1);
+ }
+
+ for (int i(0); i < m_barSets.count(); i++) {
+ int colorIndex = (index + i) % gradients.count();
+ if (i > 0 && i %gradients.count() == 0) {
+ // There is no dedicated base color for each sets, generate more colors
+ takeAtPos += step;
+ if (takeAtPos == 1.0)
+ takeAtPos += step;
+ takeAtPos -= (int) takeAtPos;
+ }
+ if (forced || QChartPrivate::defaultBrush() == m_barSets.at(i)->d_ptr->m_brush)
+ m_barSets.at(i)->setBrush(ChartThemeManager::colorAt(gradients.at(colorIndex), takeAtPos));
+
+ // Pick label color from the opposite end of the gradient.
+ // 0.3 as a boundary seems to work well.
+ if (forced || QChartPrivate::defaultBrush() == m_barSets.at(i)->d_ptr->m_labelBrush) {
+ if (takeAtPos < 0.3)
+ m_barSets.at(i)->setLabelBrush(ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 1));
+ else
+ m_barSets.at(i)->setLabelBrush(ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0));
+ }
+ if (forced || QChartPrivate::defaultPen() == m_barSets.at(i)->d_ptr->m_pen) {
+ QColor c = ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0.0);
+ m_barSets.at(i)->setPen(c);
+ }
+ }
+ m_blockBarUpdate = false;
+ emit updatedBars();
+}
+
+void QAbstractBarSeriesPrivate::initializeAnimations(QChart::AnimationOptions options)
+{
+ AbstractBarChartItem *bar = static_cast<AbstractBarChartItem *>(m_item.data());
+ Q_ASSERT(bar);
+ if (bar->animation())
+ bar->animation()->stopAndDestroyLater();
+
+ if (options.testFlag(QChart::SeriesAnimations))
+ bar->setAnimation(new BarAnimation(bar));
+ else
+ bar->setAnimation(0);
+ QAbstractSeriesPrivate::initializeAnimations(options);
+}
+
+#include "moc_qabstractbarseries.cpp"
+#include "moc_qabstractbarseries_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/barchart/qabstractbarseries.h b/src/charts/barchart/qabstractbarseries.h
new file mode 100644
index 00000000..85f32ff7
--- /dev/null
+++ b/src/charts/barchart/qabstractbarseries.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTBARSERIES_H
+#define QABSTRACTBARSERIES_H
+
+#include <QtCharts/qabstractseries.h>
+#include <QStringList>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QBarSet;
+class QAbstractBarSeriesPrivate;
+
+// Container for series
+class QT_CHARTS_EXPORT QAbstractBarSeries : public QAbstractSeries
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal barWidth READ barWidth WRITE setBarWidth)
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+ Q_PROPERTY(bool labelsVisible READ isLabelsVisible WRITE setLabelsVisible NOTIFY labelsVisibleChanged)
+ Q_PROPERTY(QString labelsFormat READ labelsFormat WRITE setLabelsFormat NOTIFY labelsFormatChanged)
+ Q_PROPERTY(LabelsPosition labelsPosition READ labelsPosition WRITE setLabelsPosition NOTIFY labelsPositionChanged)
+ Q_ENUMS(LabelsPosition)
+
+public:
+ enum LabelsPosition {
+ LabelsCenter = 0,
+ LabelsInsideEnd,
+ LabelsInsideBase,
+ LabelsOutsideEnd
+ };
+
+public:
+ virtual ~QAbstractBarSeries();
+
+ void setBarWidth(qreal width);
+ qreal barWidth() const;
+
+ bool append(QBarSet *set);
+ bool remove(QBarSet *set);
+ bool take(QBarSet *set);
+ bool append(QList<QBarSet *> sets);
+ bool insert(int index, QBarSet *set);
+ int count() const;
+ QList<QBarSet *> barSets() const;
+ void clear();
+
+ void setLabelsVisible(bool visible = true);
+ bool isLabelsVisible() const;
+
+ void setLabelsFormat(const QString &format);
+ QString labelsFormat() const;
+
+ void setLabelsPosition(QAbstractBarSeries::LabelsPosition position);
+ QAbstractBarSeries::LabelsPosition labelsPosition() const;
+
+protected:
+ explicit QAbstractBarSeries(QAbstractBarSeriesPrivate &d, QObject *parent = 0);
+
+Q_SIGNALS:
+ void clicked(int index, QBarSet *barset);
+ void hovered(bool status, QBarSet *barset);
+ void hovered(bool status, int index, QBarSet *barset);
+ void countChanged();
+ void labelsVisibleChanged();
+ void labelsFormatChanged(const QString &format);
+ void labelsPositionChanged(QAbstractBarSeries::LabelsPosition position);
+
+ void barsetsAdded(QList<QBarSet *> sets);
+ void barsetsRemoved(QList<QBarSet *> sets);
+
+protected:
+ Q_DECLARE_PRIVATE(QAbstractBarSeries)
+ friend class AbstractBarChartItem;
+ friend class PercentBarChartItem;
+ friend class StackedBarChartItem;
+ friend class BoxPlotChartItem;
+ friend class BarChartItem;
+ friend class HorizontalBarChartItem;
+ friend class HorizontalStackedBarChartItem;
+ friend class HorizontalPercentBarChartItem;
+ friend class BarSet;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QABSTRACTBARSERIES_H
diff --git a/src/charts/barchart/qabstractbarseries_p.h b/src/charts/barchart/qabstractbarseries_p.h
new file mode 100644
index 00000000..c7b0b827
--- /dev/null
+++ b/src/charts/barchart/qabstractbarseries_p.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QABSTRACTBARSERIES_P_H
+#define QABSTRACTBARSERIES_P_H
+
+#include <QtCharts/qabstractbarseries.h>
+#include "qabstractseries_p.h"
+#include <QStringList>
+#include <QAbstractSeries>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QBarModelMapper;
+class QBarCategoryAxis;
+class QLegendMarker;
+
+class QAbstractBarSeriesPrivate : public QAbstractSeriesPrivate
+{
+ Q_OBJECT
+public:
+ QAbstractBarSeriesPrivate(QAbstractBarSeries *parent);
+ int categoryCount() const;
+
+ void setBarWidth(qreal width);
+ qreal barWidth() const;
+
+ void setVisible(bool visible);
+ void setLabelsVisible(bool visible);
+
+ void initializeDomain();
+ void initializeAxes();
+ void initializeAnimations(QChart::AnimationOptions options);
+ void initializeTheme(int index, ChartTheme* theme, bool forced = false);
+
+ QList<QLegendMarker*> createLegendMarkers(QLegend *legend);
+
+ virtual QAbstractAxis::AxisType defaultAxisType(Qt::Orientation orientation) const;
+ QAbstractAxis* createDefaultAxis(Qt::Orientation orientation) const;
+
+ bool append(QBarSet *set);
+ bool remove(QBarSet *set);
+ bool append(QList<QBarSet *> sets);
+ bool remove(QList<QBarSet *> sets);
+ bool insert(int index, QBarSet *set);
+
+ QBarSet *barsetAt(int index);
+ qreal min();
+ qreal max();
+ qreal valueAt(int set, int category);
+ qreal percentageAt(int set, int category);
+ qreal categorySum(int category);
+ qreal absoluteCategorySum(int category);
+ qreal maxCategorySum();
+ qreal minX();
+ qreal maxX();
+ qreal categoryTop(int category);
+ qreal categoryBottom(int category);
+ qreal top();
+ qreal bottom();
+
+ bool blockBarUpdate();
+
+Q_SIGNALS:
+ void clicked(int index, QBarSet *barset);
+ void updatedBars();
+ void updatedLayout();
+ void restructuredBars();
+ void labelsVisibleChanged(bool visible);
+ void visibleChanged();
+
+private:
+ void populateCategories(QBarCategoryAxis *axis);
+
+protected:
+ QList<QBarSet *> m_barSets;
+ qreal m_barWidth;
+ bool m_labelsVisible;
+ bool m_visible;
+ bool m_blockBarUpdate;
+ QString m_labelsFormat;
+ QAbstractBarSeries::LabelsPosition m_labelsPosition;
+
+private:
+ Q_DECLARE_PUBLIC(QAbstractBarSeries)
+ friend class HorizontalBarChartItem;
+ friend class BarChartItem;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QABSTRACTBARSERIES_P_H
diff --git a/src/charts/barchart/qbarmodelmapper.cpp b/src/charts/barchart/qbarmodelmapper.cpp
new file mode 100644
index 00000000..459a72ca
--- /dev/null
+++ b/src/charts/barchart/qbarmodelmapper.cpp
@@ -0,0 +1,561 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbarmodelmapper.h"
+#include "qbarmodelmapper_p.h"
+#include "qabstractbarseries.h"
+#include "qbarset.h"
+#include "qchart.h"
+#include <QAbstractItemModel>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+QBarModelMapper::QBarModelMapper(QObject *parent) :
+ QObject(parent),
+ d_ptr(new QBarModelMapperPrivate(this))
+{
+}
+
+QAbstractItemModel *QBarModelMapper::model() const
+{
+ Q_D(const QBarModelMapper);
+ return d->m_model;
+}
+
+void QBarModelMapper::setModel(QAbstractItemModel *model)
+{
+ if (model == 0)
+ return;
+
+ Q_D(QBarModelMapper);
+ if (d->m_model)
+ disconnect(d->m_model, 0, d, 0);
+
+ d->m_model = model;
+ d->initializeBarFromModel();
+ // connect signals from the model
+ connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
+ connect(d->m_model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), d, SLOT(modelHeaderDataUpdated(Qt::Orientation,int,int)));
+ connect(d->m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelRowsAdded(QModelIndex,int,int)));
+ connect(d->m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelRowsRemoved(QModelIndex,int,int)));
+ connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelColumnsAdded(QModelIndex,int,int)));
+ connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelColumnsRemoved(QModelIndex,int,int)));
+ connect(d->m_model, SIGNAL(destroyed()), d, SLOT(handleModelDestroyed()));
+}
+
+QAbstractBarSeries *QBarModelMapper::series() const
+{
+ Q_D(const QBarModelMapper);
+ return d->m_series;
+}
+
+void QBarModelMapper::setSeries(QAbstractBarSeries *series)
+{
+ Q_D(QBarModelMapper);
+ if (d->m_series)
+ disconnect(d->m_series, 0, d, 0);
+
+ if (series == 0)
+ return;
+
+ d->m_series = series;
+ d->initializeBarFromModel();
+ // connect the signals from the series
+ connect(d->m_series, SIGNAL(barsetsAdded(QList<QBarSet*>)), d, SLOT(barSetsAdded(QList<QBarSet*>)));
+ connect(d->m_series, SIGNAL(barsetsRemoved(QList<QBarSet*>)), d, SLOT(barSetsRemoved(QList<QBarSet*>)));
+ connect(d->m_series, SIGNAL(destroyed()), d, SLOT(handleSeriesDestroyed()));
+}
+
+/*!
+ Returns which row/column of the model contains the first values of the QBarSets in the series.
+ The default value is 0.
+*/
+int QBarModelMapper::first() const
+{
+ Q_D(const QBarModelMapper);
+ return d->m_first;
+}
+
+/*!
+ Sets which row of the model contains the \a first values of the QBarSets in the series.
+ The default value is 0.
+*/
+void QBarModelMapper::setFirst(int first)
+{
+ Q_D(QBarModelMapper);
+ d->m_first = qMax(first, 0);
+ d->initializeBarFromModel();
+}
+
+/*!
+ Returns the number of rows/columns of the model that are mapped as the data for QAbstractBarSeries
+ Minimal and default value is: -1 (count limited by the number of rows/columns in the model)
+*/
+int QBarModelMapper::count() const
+{
+ Q_D(const QBarModelMapper);
+ return d->m_count;
+}
+
+/*!
+ Sets the \a count of rows/columns of the model that are mapped as the data for QAbstractBarSeries
+ Minimal and default value is: -1 (count limited by the number of rows/columns in the model)
+*/
+void QBarModelMapper::setCount(int count)
+{
+ Q_D(QBarModelMapper);
+ d->m_count = qMax(count, -1);
+ d->initializeBarFromModel();
+}
+
+/*!
+ Returns the orientation that is used when QBarModelMapper accesses the model.
+ This mean whether the consecutive values of the bar set are read from row (Qt::Horizontal)
+ or from columns (Qt::Vertical)
+*/
+Qt::Orientation QBarModelMapper::orientation() const
+{
+ Q_D(const QBarModelMapper);
+ return d->m_orientation;
+}
+
+/*!
+ Returns the \a orientation that is used when QBarModelMapper accesses the model.
+ This mean whether the consecutive values of the pie are read from row (Qt::Horizontal)
+ or from columns (Qt::Vertical)
+*/
+void QBarModelMapper::setOrientation(Qt::Orientation orientation)
+{
+ Q_D(QBarModelMapper);
+ d->m_orientation = orientation;
+ d->initializeBarFromModel();
+}
+
+/*!
+ Returns which section of the model is used as the data source for the first bar set
+*/
+int QBarModelMapper::firstBarSetSection() const
+{
+ Q_D(const QBarModelMapper);
+ return d->m_firstBarSetSection;
+}
+
+/*!
+ Sets the model section that is used as the data source for the first bar set
+ Parameter \a firstBarSetSection specifies the section of the model.
+*/
+void QBarModelMapper::setFirstBarSetSection(int firstBarSetSection)
+{
+ Q_D(QBarModelMapper);
+ d->m_firstBarSetSection = qMax(-1, firstBarSetSection);
+ d->initializeBarFromModel();
+}
+
+/*!
+ Returns which section of the model is used as the data source for the last bar set
+*/
+int QBarModelMapper::lastBarSetSection() const
+{
+ Q_D(const QBarModelMapper);
+ return d->m_lastBarSetSection;
+}
+
+/*!
+ Sets the model section that is used as the data source for the last bar set
+ Parameter \a lastBarSetSection specifies the section of the model.
+*/
+void QBarModelMapper::setLastBarSetSection(int lastBarSetSection)
+{
+ Q_D(QBarModelMapper);
+ d->m_lastBarSetSection = qMax(-1, lastBarSetSection);
+ d->initializeBarFromModel();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QBarModelMapperPrivate::QBarModelMapperPrivate(QBarModelMapper *q) :
+ QObject(q),
+ m_series(0),
+ m_model(0),
+ m_first(0),
+ m_count(-1),
+ m_orientation(Qt::Vertical),
+ m_firstBarSetSection(-1),
+ m_lastBarSetSection(-1),
+ m_seriesSignalsBlock(false),
+ m_modelSignalsBlock(false),
+ q_ptr(q)
+{
+}
+
+void QBarModelMapperPrivate::blockModelSignals(bool block)
+{
+ m_modelSignalsBlock = block;
+}
+
+void QBarModelMapperPrivate::blockSeriesSignals(bool block)
+{
+ m_seriesSignalsBlock = block;
+}
+
+QBarSet *QBarModelMapperPrivate::barSet(QModelIndex index)
+{
+ if (!index.isValid())
+ return 0;
+
+ if (m_orientation == Qt::Vertical && index.column() >= m_firstBarSetSection && index.column() <= m_lastBarSetSection) {
+ if (index.row() >= m_first && (m_count == - 1 || index.row() < m_first + m_count)) {
+ return m_series->barSets().at(index.column() - m_firstBarSetSection);
+ }
+ } else if (m_orientation == Qt::Horizontal && index.row() >= m_firstBarSetSection && index.row() <= m_lastBarSetSection) {
+ if (index.column() >= m_first && (m_count == - 1 || index.column() < m_first + m_count))
+ return m_series->barSets().at(index.row() - m_firstBarSetSection);
+ }
+ return 0; // This part of model has not been mapped to any slice
+}
+
+QModelIndex QBarModelMapperPrivate::barModelIndex(int barSection, int posInBar)
+{
+ if (m_count != -1 && posInBar >= m_count)
+ return QModelIndex(); // invalid
+
+ if (barSection < m_firstBarSetSection || barSection > m_lastBarSetSection)
+ return QModelIndex(); // invalid
+
+ if (m_orientation == Qt::Vertical)
+ return m_model->index(posInBar + m_first, barSection);
+ else
+ return m_model->index(barSection, posInBar + m_first);
+}
+
+void QBarModelMapperPrivate::handleSeriesDestroyed()
+{
+ m_series = 0;
+}
+
+void QBarModelMapperPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
+{
+ Q_UNUSED(topLeft)
+ Q_UNUSED(bottomRight)
+
+ if (m_model == 0 || m_series == 0)
+ return;
+
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ QModelIndex index;
+ for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
+ for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
+ index = topLeft.sibling(row, column);
+ QBarSet *bar = barSet(index);
+ if (bar) {
+ if (m_orientation == Qt::Vertical)
+ bar->replace(row - m_first, m_model->data(index).toReal());
+ else
+ bar->replace(column - m_first, m_model->data(index).toReal());
+ }
+ }
+ }
+ blockSeriesSignals(false);
+}
+
+void QBarModelMapperPrivate::modelHeaderDataUpdated(Qt::Orientation orientation, int first, int last)
+{
+ if (m_model == 0 || m_series == 0)
+ return;
+
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ if (orientation != m_orientation) {
+ for (int section = first; section <= last; section++) {
+ if (section >= m_firstBarSetSection && section <= m_lastBarSetSection) {
+ QBarSet *bar = m_series->barSets().at(section - m_firstBarSetSection);
+ if (bar)
+ bar->setLabel(m_model->headerData(section, orientation).toString());
+ }
+ }
+ }
+ blockSeriesSignals(false);
+}
+
+void QBarModelMapperPrivate::modelRowsAdded(QModelIndex parent, int start, int end)
+{
+ Q_UNUSED(parent)
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ if (m_orientation == Qt::Vertical)
+ insertData(start, end);
+ else if (start <= m_firstBarSetSection || start <= m_lastBarSetSection) // if the changes affect the map - reinitialize
+ initializeBarFromModel();
+ blockSeriesSignals(false);
+}
+
+void QBarModelMapperPrivate::modelRowsRemoved(QModelIndex parent, int start, int end)
+{
+ Q_UNUSED(parent)
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ if (m_orientation == Qt::Vertical)
+ removeData(start, end);
+ else if (start <= m_firstBarSetSection || start <= m_lastBarSetSection) // if the changes affect the map - reinitialize
+ initializeBarFromModel();
+ blockSeriesSignals(false);
+}
+
+void QBarModelMapperPrivate::modelColumnsAdded(QModelIndex parent, int start, int end)
+{
+ Q_UNUSED(parent)
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ if (m_orientation == Qt::Horizontal)
+ insertData(start, end);
+ else if (start <= m_firstBarSetSection || start <= m_lastBarSetSection) // if the changes affect the map - reinitialize
+ initializeBarFromModel();
+ blockSeriesSignals(false);
+}
+
+void QBarModelMapperPrivate::modelColumnsRemoved(QModelIndex parent, int start, int end)
+{
+ Q_UNUSED(parent)
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ if (m_orientation == Qt::Horizontal)
+ removeData(start, end);
+ else if (start <= m_firstBarSetSection || start <= m_lastBarSetSection) // if the changes affect the map - reinitialize
+ initializeBarFromModel();
+ blockSeriesSignals(false);
+}
+
+void QBarModelMapperPrivate::handleModelDestroyed()
+{
+ m_model = 0;
+}
+
+void QBarModelMapperPrivate::insertData(int start, int end)
+{
+ Q_UNUSED(end)
+ Q_UNUSED(start)
+ Q_UNUSED(end)
+ // Currently barchart needs to be fully recalculated when change is made.
+ // Re-initialize
+ initializeBarFromModel();
+}
+
+void QBarModelMapperPrivate::removeData(int start, int end)
+{
+ Q_UNUSED(end)
+ Q_UNUSED(start)
+ Q_UNUSED(end)
+ // Currently barchart needs to be fully recalculated when change is made.
+ // Re-initialize
+ initializeBarFromModel();
+}
+
+void QBarModelMapperPrivate::barSetsAdded(QList<QBarSet *> sets)
+{
+ if (m_seriesSignalsBlock)
+ return;
+
+ if (sets.count() == 0)
+ return;
+
+ int firstIndex = m_series->barSets().indexOf(sets.at(0));
+ if (firstIndex == -1)
+ return;
+
+ int maxCount = 0;
+ for (int i = 0; i < sets.count(); i++) {
+ if (sets.at(i)->count() > m_count)
+ maxCount = sets.at(i)->count();
+ }
+
+ if (m_count != -1 && m_count < maxCount)
+ m_count = maxCount;
+
+ m_lastBarSetSection += sets.count();
+
+ blockModelSignals();
+ int modelCapacity = m_orientation == Qt::Vertical ? m_model->rowCount() - m_first : m_model->columnCount() - m_first;
+ if (maxCount > modelCapacity) {
+ if (m_orientation == Qt::Vertical)
+ m_model->insertRows(m_model->rowCount(), maxCount - modelCapacity);
+ else
+ m_model->insertColumns(m_model->columnCount(), maxCount - modelCapacity);
+ }
+
+ if (m_orientation == Qt::Vertical)
+ m_model->insertColumns(firstIndex + m_firstBarSetSection, sets.count());
+ else
+ m_model->insertRows(firstIndex + m_firstBarSetSection, sets.count());
+
+
+ for (int i = firstIndex + m_firstBarSetSection; i < firstIndex + m_firstBarSetSection + sets.count(); i++) {
+ m_model->setHeaderData(i, m_orientation == Qt::Vertical ? Qt::Horizontal : Qt::Vertical, sets.at(i - firstIndex - m_firstBarSetSection)->label());
+ for (int j = 0; j < sets.at(i - firstIndex - m_firstBarSetSection)->count(); j++)
+ m_model->setData(barModelIndex(i, j), sets.at(i - firstIndex - m_firstBarSetSection)->at(j));
+ }
+ blockModelSignals(false);
+ initializeBarFromModel();
+}
+
+void QBarModelMapperPrivate::barSetsRemoved(QList<QBarSet *> sets)
+{
+ if (m_seriesSignalsBlock)
+ return;
+
+ if (sets.count() == 0)
+ return;
+
+ int firstIndex = m_barSets.indexOf(sets.at(0));
+ if (firstIndex == -1)
+ return;
+
+ m_lastBarSetSection -= sets.count();
+
+ for (int i = firstIndex + sets.count() - 1; i >= firstIndex; i--)
+ m_barSets.removeAt(i);
+
+ blockModelSignals();
+ if (m_orientation == Qt::Vertical)
+ m_model->removeColumns(firstIndex + m_firstBarSetSection, sets.count());
+ else
+ m_model->removeRows(firstIndex + m_firstBarSetSection, sets.count());
+ blockModelSignals(false);
+ initializeBarFromModel();
+}
+
+void QBarModelMapperPrivate::valuesAdded(int index, int count)
+{
+ if (m_seriesSignalsBlock)
+ return;
+
+ if (m_count != -1)
+ m_count += count;
+
+ int barSetIndex = m_barSets.indexOf(qobject_cast<QBarSet *>(QObject::sender()));
+
+ blockModelSignals();
+ if (m_orientation == Qt::Vertical)
+ m_model->insertRows(index + m_first, count);
+ else
+ m_model->insertColumns(index + m_first, count);
+
+ for (int j = index; j < index + count; j++)
+ m_model->setData(barModelIndex(barSetIndex + m_firstBarSetSection, j), m_barSets.at(barSetIndex)->at(j));
+
+ blockModelSignals(false);
+ initializeBarFromModel();
+}
+
+void QBarModelMapperPrivate::valuesRemoved(int index, int count)
+{
+ if (m_seriesSignalsBlock)
+ return;
+
+ if (m_count != -1)
+ m_count -= count;
+
+ blockModelSignals();
+ if (m_orientation == Qt::Vertical)
+ m_model->removeRows(index + m_first, count);
+ else
+ m_model->removeColumns(index + m_first, count);
+
+ blockModelSignals(false);
+ initializeBarFromModel();
+}
+
+void QBarModelMapperPrivate::barLabelChanged()
+{
+ if (m_seriesSignalsBlock)
+ return;
+
+ int barSetIndex = m_barSets.indexOf(qobject_cast<QBarSet *>(QObject::sender()));
+
+ blockModelSignals();
+ m_model->setHeaderData(barSetIndex + m_firstBarSetSection, m_orientation == Qt::Vertical ? Qt::Horizontal : Qt::Vertical, m_barSets.at(barSetIndex)->label());
+ blockModelSignals(false);
+ initializeBarFromModel();
+}
+
+void QBarModelMapperPrivate::barValueChanged(int index)
+{
+ if (m_seriesSignalsBlock)
+ return;
+
+ int barSetIndex = m_barSets.indexOf(qobject_cast<QBarSet *>(QObject::sender()));
+
+ blockModelSignals();
+ m_model->setData(barModelIndex(barSetIndex + m_firstBarSetSection, index), m_barSets.at(barSetIndex)->at(index));
+ blockModelSignals(false);
+ initializeBarFromModel();
+}
+
+void QBarModelMapperPrivate::initializeBarFromModel()
+{
+ if (m_model == 0 || m_series == 0)
+ return;
+
+ blockSeriesSignals();
+ // clear current content
+ m_series->clear();
+ m_barSets.clear();
+
+ // create the initial bar sets
+ for (int i = m_firstBarSetSection; i <= m_lastBarSetSection; i++) {
+ int posInBar = 0;
+ QModelIndex barIndex = barModelIndex(i, posInBar);
+ // check if there is such model index
+ if (barIndex.isValid()) {
+ QBarSet *barSet = new QBarSet(m_model->headerData(i, m_orientation == Qt::Vertical ? Qt::Horizontal : Qt::Vertical).toString());
+ while (barIndex.isValid()) {
+ barSet->append(m_model->data(barIndex, Qt::DisplayRole).toDouble());
+ posInBar++;
+ barIndex = barModelIndex(i, posInBar);
+ }
+ connect(barSet, SIGNAL(valuesAdded(int,int)), this, SLOT(valuesAdded(int,int)));
+ connect(barSet, SIGNAL(valuesRemoved(int,int)), this, SLOT(valuesRemoved(int,int)));
+ connect(barSet, SIGNAL(valueChanged(int)), this, SLOT(barValueChanged(int)));
+ connect(barSet, SIGNAL(labelChanged()), this, SLOT(barLabelChanged()));
+ m_series->append(barSet);
+ m_barSets.append(barSet);
+ } else {
+ break;
+ }
+ }
+ blockSeriesSignals(false);
+}
+
+#include "moc_qbarmodelmapper.cpp"
+#include "moc_qbarmodelmapper_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/barchart/qbarmodelmapper.h b/src/charts/barchart/qbarmodelmapper.h
new file mode 100644
index 00000000..a527165a
--- /dev/null
+++ b/src/charts/barchart/qbarmodelmapper.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBARMODELMAPPER_H
+#define QBARMODELMAPPER_H
+
+#include <QtCharts/qchartglobal.h>
+#include <QObject>
+
+class QAbstractItemModel;
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QBarModelMapperPrivate;
+class QAbstractBarSeries;
+
+class QT_CHARTS_EXPORT QBarModelMapper : public QObject
+{
+ Q_OBJECT
+
+protected:
+ explicit QBarModelMapper(QObject *parent = 0);
+
+ QAbstractItemModel *model() const;
+ void setModel(QAbstractItemModel *model);
+
+ QAbstractBarSeries *series() const;
+ void setSeries(QAbstractBarSeries *series);
+
+ int first() const;
+ void setFirst(int first);
+
+ int count() const;
+ void setCount(int count);
+
+ int firstBarSetSection() const;
+ void setFirstBarSetSection(int firstBarSetSection);
+
+ int lastBarSetSection() const;
+ void setLastBarSetSection(int lastBarSetSection);
+
+ Qt::Orientation orientation() const;
+ void setOrientation(Qt::Orientation orientation);
+
+protected:
+ QBarModelMapperPrivate * const d_ptr;
+ Q_DECLARE_PRIVATE(QBarModelMapper)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QBARMODELMAPPER_H
diff --git a/src/charts/barchart/qbarmodelmapper_p.h b/src/charts/barchart/qbarmodelmapper_p.h
new file mode 100644
index 00000000..754ebec1
--- /dev/null
+++ b/src/charts/barchart/qbarmodelmapper_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QBARMODELMAPPER_P_H
+#define QBARMODELMAPPER_P_H
+
+#include <QObject>
+#include "qbarmodelmapper.h"
+
+class QModelIndex;
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QBarSet;
+
+class QBarModelMapperPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QBarModelMapperPrivate(QBarModelMapper *q);
+
+public Q_SLOTS:
+ // for the model
+ void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight);
+ void modelHeaderDataUpdated(Qt::Orientation orientation, int first, int last);
+ void modelRowsAdded(QModelIndex parent, int start, int end);
+ void modelRowsRemoved(QModelIndex parent, int start, int end);
+ void modelColumnsAdded(QModelIndex parent, int start, int end);
+ void modelColumnsRemoved(QModelIndex parent, int start, int end);
+ void handleModelDestroyed();
+
+ // for the series
+ void barSetsAdded(QList<QBarSet *> sets);
+ void barSetsRemoved(QList<QBarSet *> sets);
+ void valuesAdded(int index, int count);
+ void valuesRemoved(int index, int count);
+ void barLabelChanged();
+ void barValueChanged(int index);
+ void handleSeriesDestroyed();
+
+ void initializeBarFromModel();
+
+private:
+ QBarSet *barSet(QModelIndex index);
+ QModelIndex barModelIndex(int barSection, int posInBar);
+ void insertData(int start, int end);
+ void removeData(int start, int end);
+ void blockModelSignals(bool block = true);
+ void blockSeriesSignals(bool block = true);
+
+private:
+ QAbstractBarSeries *m_series;
+ QList<QBarSet *> m_barSets;
+ QAbstractItemModel *m_model;
+ int m_first;
+ int m_count;
+ Qt::Orientation m_orientation;
+ int m_firstBarSetSection;
+ int m_lastBarSetSection;
+ bool m_seriesSignalsBlock;
+ bool m_modelSignalsBlock;
+
+private:
+ QBarModelMapper *q_ptr;
+ Q_DECLARE_PUBLIC(QBarModelMapper)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QBARMODELMAPPER_P_H
diff --git a/src/charts/barchart/qbarset.cpp b/src/charts/barchart/qbarset.cpp
new file mode 100644
index 00000000..e378b327
--- /dev/null
+++ b/src/charts/barchart/qbarset.cpp
@@ -0,0 +1,676 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbarset.h"
+#include "qbarset_p.h"
+#include "charthelpers_p.h"
+#include "qchart_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QBarSet
+ \inmodule Qt Charts
+ \brief Building block for different bar charts.
+
+ QBarSet represents one set of bars. Set of bars contains one data value for each category.
+ First value of set is assumed to belong to first category, second to second category and so on.
+ If set has fewer values than there are categories, then the missing values are assumed to be
+ at the end of set. For missing values in middle of a set, numerical value of zero is used.
+
+ \mainclass
+
+ \sa QAbstractBarSeries, QBarSeries, QStackedBarSeries, QPercentBarSeries
+*/
+/*!
+ \qmltype BarSet
+ \instantiates QBarSet
+ \inqmlmodule QtCharts
+
+ \brief Building block for different bar charts.
+
+ BarSet represents one set of bars. Set of bars contains one data value for each category.
+ First value of set is assumed to belong to first category, second to second category and so on.
+ If set has fewer values than there are categories, then the missing values are assumed to be
+ at the end of set. For missing values in middle of a set, numerical value of zero is used.
+ \sa AbstractBarSeries, BarSeries, StackedBarSeries, PercentBarSeries
+*/
+
+/*!
+ \property QBarSet::label
+ Defines the label of the bar set.
+*/
+/*!
+ \qmlproperty string BarSet::label
+ Defines the label of the bar set.
+*/
+
+/*!
+ \property QBarSet::pen
+ \brief Defines the pen used by the bar set.
+*/
+
+/*!
+ \property QBarSet::brush
+ \brief Defines the brush used by the bar set.
+*/
+
+/*!
+ \qmlproperty QString BarSet::brushFilename
+ The name of the file used as a brush for the set.
+*/
+
+/*!
+ \property QBarSet::labelBrush
+ \brief Defines the brush used by the bar set's label.
+*/
+
+/*!
+ \property QBarSet::labelFont
+ \brief Defines the font used by the bar set's label.
+*/
+
+/*!
+ \qmlproperty Font BarSet::labelFont
+ Defines the font used by the bar set's label.
+
+ See the Qt documentation for more details of Font.
+*/
+
+/*!
+ \property QBarSet::color
+ The fill (brush) color of the bar set.
+*/
+/*!
+ \qmlproperty color BarSet::color
+ The fill (brush) color of the bar set.
+*/
+
+/*!
+ \property QBarSet::borderColor
+ The line (pen) color of the bar set.
+*/
+/*!
+ \qmlproperty color BarSet::borderColor
+ The line (pen) color of the bar set.
+*/
+
+/*!
+ \qmlproperty real BarSet::borderWidth
+ The width of the border line. By default the width is 2.0.
+*/
+
+/*!
+ \property QBarSet::labelColor
+ The text (label) color of the bar set.
+*/
+/*!
+ \qmlproperty color BarSet::labelColor
+ The text (label) color of the bar set.
+*/
+
+/*!
+ \fn void QBarSet::clicked(int index)
+
+ The signal is emitted if the user clicks with a mouse on top of bar set.
+ Clicked bar inside set is indexed by \a index
+*/
+
+/*!
+ \fn void QBarSet::hovered(bool status)
+
+ The signal is emitted if mouse is hovered on top of bar set.
+ Parameter \a status is true, if mouse entered on top of bar set, false if mouse left from top of bar set.
+*/
+
+/*!
+ \fn void QBarSet::hovered(bool status, int index)
+
+ The signal is emitted if mouse is hovered on top of bar set.
+ Parameter \a status is true, if mouse entered on top of bar set, false if mouse left from top of bar set.
+ Hovered bar inside the set is indexed by \a index.
+*/
+
+
+/*!
+ \fn void QBarSet::labelChanged()
+ This signal is emitted when the label of the bar set has changed.
+ \sa label
+*/
+/*!
+ \qmlsignal BarSet::onLabelChanged()
+ This signal is emitted when the label of the bar set has changed.
+*/
+
+/*!
+ \fn void QBarSet::penChanged()
+ This signal is emitted when the pen of the bar set has changed.
+ \sa pen
+*/
+
+/*!
+ \fn void QBarSet::brushChanged()
+ This signal is emitted when the brush of the bar set has changed.
+ \sa brush
+*/
+
+/*!
+ \fn void QBarSet::labelBrushChanged()
+ This signal is emitted when the brush of the bar set's label has changed.
+ \sa labelBrush
+*/
+
+/*!
+ \fn void QBarSet::labelFontChanged()
+ This signal is emitted when the font of the bar set's label has changed.
+ \sa labelBrush
+*/
+
+/*!
+ \fn void QBarSet::colorChanged(QColor)
+ This signal is emitted when the fill (brush) color of the set has changed to \a color.
+*/
+/*!
+ \qmlsignal BarSet::onColorChanged(color color)
+ This signal is emitted when the fill (brush) color of the set has changed to \a color.
+*/
+
+/*!
+ \fn void QBarSet::borderColorChanged(QColor)
+ This signal is emitted when the line (pen) color of the set has changed to \a color.
+*/
+/*!
+ \qmlsignal BarSet::onBorderColorChanged(color color)
+ This signal is emitted when the line (pen) color of the set has changed to \a color.
+*/
+
+/*!
+ \fn void QBarSet::labelColorChanged(QColor)
+ This signal is emitted when the text (label) color of the set has changed to \a color.
+*/
+/*!
+ \qmlsignal BarSet::onLabelColorChanged(color color)
+ This signal is emitted when the text (label) color of the set has changed to \a color.
+*/
+
+/*!
+ \fn void QBarSet::valuesAdded(int index, int count)
+ This signal is emitted when new values have been added to the set.
+ Parameter \a index indicates the position of the first inserted value.
+ Parameter \a count is the number of inserted values.
+ \sa append(), insert()
+*/
+/*!
+ \qmlsignal BarSet::onValuesAdded(int index, int count)
+ This signal is emitted when new values have been added to the set.
+ Parameter \a index indicates the position of the first inserted value.
+ Parameter \a count is the number of inserted values.
+*/
+
+/*!
+ \fn void QBarSet::valuesRemoved(int index, int count)
+ This signal is emitted values have been removed from the set.
+ Parameter \a index indicates the position of the first removed value.
+ Parameter \a count is the number of removed values.
+ \sa remove()
+*/
+/*!
+ \qmlsignal BarSet::onValuesRemoved(int index, int count)
+ This signal is emitted values have been removed from the set.
+ Parameter \a index indicates the position of the first removed value.
+ Parameter \a count is the number of removed values.
+*/
+
+/*!
+ \fn void QBarSet::valueChanged(int index)
+ This signal is emitted values the value in the set has been modified.
+ Parameter \a index indicates the position of the modified value.
+ \sa at()
+*/
+/*!
+ \qmlsignal BarSet::onValueChanged(int index)
+ This signal is emitted values the value in the set has been modified.
+ Parameter \a index indicates the position of the modified value.
+*/
+
+/*!
+ \qmlproperty int BarSet::count
+ The count of values on the bar set
+*/
+
+/*!
+ \qmlproperty QVariantList BarSet::values
+ The values of the bar set. You can set either a list of reals or a list of points as values. If you set a list of
+ reals as values, the values are automatically completed to points by using the index of a value as it's
+ x-coordinate. For example the following sets have equal values:
+ \code
+ myBarSet1.values = [0, 5, 1, 5];
+ myBarSet2.values = [Qt.point(0, 0), Qt.point(1, 5), Qt.point(2, 1), Qt.point(3, 5)];
+ \endcode
+*/
+
+/*!
+ Constructs QBarSet with a label of \a label and with parent of \a parent.
+*/
+QBarSet::QBarSet(const QString label, QObject *parent)
+ : QObject(parent),
+ d_ptr(new QBarSetPrivate(label, this))
+{
+}
+
+/*!
+ Destroys the bar set.
+*/
+QBarSet::~QBarSet()
+{
+ // NOTE: d_ptr destroyed by QObject
+}
+
+/*!
+ Sets new \a label for set.
+*/
+void QBarSet::setLabel(const QString label)
+{
+ d_ptr->m_label = label;
+ emit labelChanged();
+}
+
+/*!
+ Returns label of the set.
+*/
+QString QBarSet::label() const
+{
+ return d_ptr->m_label;
+}
+
+/*!
+ Appends new value \a value to the end of set.
+*/
+void QBarSet::append(const qreal value)
+{
+ // Convert to QPointF
+ int index = d_ptr->m_values.count();
+ d_ptr->append(QPointF(d_ptr->m_values.count(), value));
+ emit valuesAdded(index, 1);
+}
+
+/*!
+ Appends a list of reals to set. Works like append with single real value. The \a values in list
+ are appended to end of bar set.
+ \sa append()
+*/
+void QBarSet::append(const QList<qreal> &values)
+{
+ int index = d_ptr->m_values.count();
+ d_ptr->append(values);
+ emit valuesAdded(index, values.count());
+}
+
+/*!
+ Convenience operator. Same as append, with real \a value.
+ \sa append()
+*/
+QBarSet &QBarSet::operator << (const qreal &value)
+{
+ append(value);
+ return *this;
+}
+
+/*!
+ Inserts new \a value on the \a index position.
+ The value that is currently at this postion is moved to position index + 1
+ \sa remove()
+*/
+void QBarSet::insert(const int index, const qreal value)
+{
+ d_ptr->insert(index, value);
+ emit valuesAdded(index, 1);
+}
+
+/*!
+ Removes \a count number of values from the set starting at \a index.
+ \sa insert()
+*/
+void QBarSet::remove(const int index, const int count)
+{
+ int removedCount = d_ptr->remove(index, count);
+ if (removedCount > 0)
+ emit valuesRemoved(index, removedCount);
+ return;
+}
+
+/*!
+ Sets a new value \a value to set, indexed by \a index.
+*/
+void QBarSet::replace(const int index, const qreal value)
+{
+ if (index >= 0 && index < d_ptr->m_values.count()) {
+ d_ptr->replace(index, value);
+ emit valueChanged(index);
+ }
+}
+
+
+/*!
+ Returns value of set indexed by \a index.
+ If the index is out of bounds 0.0 is returned.
+*/
+qreal QBarSet::at(const int index) const
+{
+ if (index < 0 || index >= d_ptr->m_values.count())
+ return 0;
+ return d_ptr->m_values.at(index).y();
+}
+
+/*!
+ Returns value of set indexed by \a index.
+ If the index is out of bounds 0.0 is returned.
+*/
+qreal QBarSet::operator [](const int index) const
+{
+ return at(index);
+}
+
+/*!
+ Returns count of values in set.
+*/
+int QBarSet::count() const
+{
+ return d_ptr->m_values.count();
+}
+
+/*!
+ Returns sum of all values in the bar set.
+*/
+qreal QBarSet::sum() const
+{
+ qreal total(0);
+ for (int i = 0; i < d_ptr->m_values.count(); i++)
+ total += d_ptr->m_values.at(i).y();
+ return total;
+}
+
+/*!
+ Sets pen for set. Bars of this set are drawn using \a pen
+*/
+void QBarSet::setPen(const QPen &pen)
+{
+ if (d_ptr->m_pen != pen) {
+ d_ptr->m_pen = pen;
+ emit d_ptr->updatedBars();
+ emit penChanged();
+ }
+}
+
+/*!
+ Returns pen of the set.
+*/
+QPen QBarSet::pen() const
+{
+ if (d_ptr->m_pen == QChartPrivate::defaultPen())
+ return QPen();
+ else
+ return d_ptr->m_pen;
+}
+
+/*!
+ Sets brush for the set. Bars of this set are drawn using \a brush.
+*/
+void QBarSet::setBrush(const QBrush &brush)
+{
+ if (d_ptr->m_brush != brush) {
+ d_ptr->m_brush = brush;
+ emit d_ptr->updatedBars();
+ emit brushChanged();
+ }
+}
+
+/*!
+ Returns brush of the set.
+*/
+QBrush QBarSet::brush() const
+{
+ if (d_ptr->m_brush == QChartPrivate::defaultBrush())
+ return QBrush();
+ else
+ return d_ptr->m_brush;
+}
+
+/*!
+ Sets \a brush of the values that are drawn on top of this bar set.
+*/
+void QBarSet::setLabelBrush(const QBrush &brush)
+{
+ if (d_ptr->m_labelBrush != brush) {
+ d_ptr->m_labelBrush = brush;
+ emit d_ptr->updatedBars();
+ emit labelBrushChanged();
+ }
+}
+
+/*!
+ Returns brush of the values that are drawn on top of this bar set.
+*/
+QBrush QBarSet::labelBrush() const
+{
+ if (d_ptr->m_labelBrush == QChartPrivate::defaultBrush())
+ return QBrush();
+ else
+ return d_ptr->m_labelBrush;
+}
+
+/*!
+ Sets the \a font for values that are drawn on top of this bar set.
+*/
+void QBarSet::setLabelFont(const QFont &font)
+{
+ if (d_ptr->m_labelFont != font) {
+ d_ptr->m_labelFont = font;
+ emit d_ptr->updatedBars();
+ emit labelFontChanged();
+ }
+
+}
+
+/*!
+ Returns the pen for values that are drawn on top of this bar set.
+*/
+QFont QBarSet::labelFont() const
+{
+ return d_ptr->m_labelFont;
+}
+
+/*!
+ Returns the color of the brush of bar set.
+*/
+QColor QBarSet::color()
+{
+ return brush().color();
+}
+
+/*!
+ Sets the \a color of brush for this bar set.
+*/
+void QBarSet::setColor(QColor color)
+{
+ QBrush b = brush();
+ if ((b.color() != color) || (b.style() == Qt::NoBrush)) {
+ b.setColor(color);
+ if (b.style() == Qt::NoBrush) {
+ // Set tyle to Qt::SolidPattern. (Default is Qt::NoBrush)
+ // This prevents theme to override color defined in QML side:
+ // BarSet { label: "Bob"; color:"red"; values: [1,2,3] }
+ // The color must be obeyed, since user wanted it.
+ b.setStyle(Qt::SolidPattern);
+ }
+ setBrush(b);
+ emit colorChanged(color);
+ }
+}
+
+/*!
+ Returns the color of pen of this bar set.
+*/
+QColor QBarSet::borderColor()
+{
+ return pen().color();
+}
+
+/*!
+ Sets the color of pen for this bar set.
+*/
+void QBarSet::setBorderColor(QColor color)
+{
+ QPen p = pen();
+ if (p.color() != color) {
+ p.setColor(color);
+ setPen(p);
+ emit borderColorChanged(color);
+ }
+}
+
+/*!
+ Returns the color of labels of this bar set.
+*/
+QColor QBarSet::labelColor()
+{
+ return labelBrush().color();
+}
+
+/*!
+ Sets the color of labels for this bar set.
+*/
+void QBarSet::setLabelColor(QColor color)
+{
+ QBrush b = labelBrush();
+ if (b == QBrush())
+ b.setStyle(Qt::SolidPattern);
+
+ if (b.color() != color) {
+ b.setColor(color);
+ setLabelBrush(b);
+ emit labelColorChanged(color);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QBarSetPrivate::QBarSetPrivate(const QString label, QBarSet *parent) : QObject(parent),
+ q_ptr(parent),
+ m_label(label),
+ m_pen(QChartPrivate::defaultPen()),
+ m_brush(QChartPrivate::defaultBrush()),
+ m_labelBrush(QChartPrivate::defaultBrush())
+{
+}
+
+QBarSetPrivate::~QBarSetPrivate()
+{
+}
+
+void QBarSetPrivate::append(QPointF value)
+{
+ if (isValidValue(value)) {
+ m_values.append(value);
+ emit restructuredBars();
+ }
+}
+
+void QBarSetPrivate::append(QList<QPointF> values)
+{
+ for (int i = 0; i < values.count(); i++) {
+ if (isValidValue(values.at(i)))
+ m_values.append(values.at(i));
+ }
+ emit restructuredBars();
+}
+
+void QBarSetPrivate::append(QList<qreal> values)
+{
+ int index = m_values.count();
+ for (int i = 0; i < values.count(); i++) {
+ if (isValidValue(values.at(i))) {
+ m_values.append(QPointF(index, values.at(i)));
+ index++;
+ }
+ }
+ emit restructuredBars();
+}
+
+void QBarSetPrivate::insert(const int index, const qreal value)
+{
+ m_values.insert(index, QPointF(index, value));
+ emit restructuredBars();
+}
+
+void QBarSetPrivate::insert(const int index, const QPointF value)
+{
+ m_values.insert(index, value);
+ emit restructuredBars();
+}
+
+int QBarSetPrivate::remove(const int index, const int count)
+{
+ int removeCount = count;
+
+ if ((index < 0) || (m_values.count() == 0))
+ return 0; // Invalid index or not values in list, remove nothing.
+ else if ((index + count) > m_values.count())
+ removeCount = m_values.count() - index; // Trying to remove more items than list has. Limit amount to be removed.
+
+ int c = 0;
+ while (c < removeCount) {
+ m_values.removeAt(index);
+ c++;
+ }
+ emit restructuredBars();
+ return removeCount;
+}
+
+void QBarSetPrivate::replace(const int index, const qreal value)
+{
+ m_values.replace(index, QPointF(index, value));
+ emit updatedLayout();
+}
+
+void QBarSetPrivate::replace(const int index, const QPointF value)
+{
+ m_values.replace(index, value);
+ emit updatedLayout();
+}
+
+qreal QBarSetPrivate::pos(const int index)
+{
+ if (index < 0 || index >= m_values.count())
+ return 0;
+ return m_values.at(index).x();
+}
+
+qreal QBarSetPrivate::value(const int index)
+{
+ if (index < 0 || index >= m_values.count())
+ return 0;
+ return m_values.at(index).y();
+}
+
+#include "moc_qbarset.cpp"
+#include "moc_qbarset_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/barchart/qbarset.h b/src/charts/barchart/qbarset.h
new file mode 100644
index 00000000..7d96dec4
--- /dev/null
+++ b/src/charts/barchart/qbarset.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBARSET_H
+#define QBARSET_H
+
+#include <QtCharts/qchartglobal.h>
+#include <QPen>
+#include <QBrush>
+#include <QFont>
+
+QT_CHARTS_BEGIN_NAMESPACE
+class QBarSetPrivate;
+
+class QT_CHARTS_EXPORT QBarSet : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY labelChanged)
+ Q_PROPERTY(QPen pen READ pen WRITE setPen NOTIFY penChanged)
+ Q_PROPERTY(QBrush brush READ brush WRITE setBrush NOTIFY brushChanged)
+ Q_PROPERTY(QBrush labelBrush READ labelBrush WRITE setLabelBrush NOTIFY labelBrushChanged)
+ Q_PROPERTY(QFont labelFont READ labelFont WRITE setLabelFont NOTIFY labelFontChanged)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+ Q_PROPERTY(QColor borderColor READ borderColor WRITE setBorderColor NOTIFY borderColorChanged)
+ Q_PROPERTY(QColor labelColor READ labelColor WRITE setLabelColor NOTIFY labelColorChanged)
+
+public:
+ explicit QBarSet(const QString label, QObject *parent = 0);
+ virtual ~QBarSet();
+
+ void setLabel(const QString label);
+ QString label() const;
+
+ void append(const qreal value);
+ void append(const QList<qreal> &values);
+
+ QBarSet &operator << (const qreal &value);
+
+ void insert(const int index, const qreal value);
+ void remove(const int index, const int count = 1);
+ void replace(const int index, const qreal value);
+ qreal at(const int index) const;
+ qreal operator [](const int index) const;
+ int count() const;
+ qreal sum() const;
+
+ void setPen(const QPen &pen);
+ QPen pen() const;
+
+ void setBrush(const QBrush &brush);
+ QBrush brush() const;
+
+ void setLabelBrush(const QBrush &brush);
+ QBrush labelBrush() const;
+
+ void setLabelFont(const QFont &font);
+ QFont labelFont() const;
+
+ QColor color();
+ void setColor(QColor color);
+
+ QColor borderColor();
+ void setBorderColor(QColor color);
+
+ QColor labelColor();
+ void setLabelColor(QColor color);
+
+Q_SIGNALS:
+ void clicked(int index);
+ void hovered(bool status);
+ void hovered(bool status, int index);
+ void penChanged();
+ void brushChanged();
+ void labelChanged();
+ void labelBrushChanged();
+ void labelFontChanged();
+ void colorChanged(QColor color);
+ void borderColorChanged(QColor color);
+ void labelColorChanged(QColor color);
+
+ void valuesAdded(int index, int count);
+ void valuesRemoved(int index, int count);
+ void valueChanged(int index);
+
+private:
+ QScopedPointer<QBarSetPrivate> d_ptr;
+ Q_DISABLE_COPY(QBarSet)
+ friend class QAbstractBarSeries;
+ friend class BarLegendMarker;
+ friend class AbstractBarChartItem;
+ friend class QAbstractBarSeriesPrivate;
+ friend class StackedBarChartItem;
+ friend class PercentBarChartItem;
+ friend class BarChartItem;
+ friend class HorizontalBarChartItem;
+ friend class HorizontalStackedBarChartItem;
+ friend class HorizontalPercentBarChartItem;
+ friend class BoxPlotChartItem;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QBARSET_H
diff --git a/src/charts/barchart/qbarset_p.h b/src/charts/barchart/qbarset_p.h
new file mode 100644
index 00000000..d0b03efa
--- /dev/null
+++ b/src/charts/barchart/qbarset_p.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QBARSET_P_H
+#define QBARSET_P_H
+
+#include <qbarset.h>
+#include <QMap>
+#include <QPen>
+#include <QBrush>
+#include <QFont>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QBarSetPrivate : public QObject
+{
+ Q_OBJECT
+
+public:
+ QBarSetPrivate(const QString label, QBarSet *parent);
+ ~QBarSetPrivate();
+
+ void append(QPointF value);
+ void append(QList<QPointF> values);
+ void append(QList<qreal> values);
+
+ void insert(const int index, const qreal value);
+ void insert(const int index, const QPointF value);
+ int remove(const int index, const int count);
+
+ void replace(const int index, const qreal value);
+ void replace(const int index, const QPointF value);
+
+ qreal pos(const int index);
+ qreal value(const int index);
+
+Q_SIGNALS:
+ void restructuredBars();
+ void updatedBars();
+ void updatedLayout();
+
+public:
+ QBarSet * const q_ptr;
+ QString m_label;
+ QList<QPointF> m_values;
+ QPen m_pen;
+ QBrush m_brush;
+ QBrush m_labelBrush;
+ QFont m_labelFont;
+
+ friend class QBarSet;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QBARSETPRIVATE_P_H
diff --git a/src/charts/barchart/qhbarmodelmapper.cpp b/src/charts/barchart/qhbarmodelmapper.cpp
new file mode 100644
index 00000000..0312df40
--- /dev/null
+++ b/src/charts/barchart/qhbarmodelmapper.cpp
@@ -0,0 +1,258 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhbarmodelmapper.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QHBarModelMapper
+ \inmodule Qt Charts
+ \brief Horizontal model mapper for bar series.
+ \mainclass
+
+ Model mappers allow you to use QAbstractItemModel derived models as a data source for a chart series.
+ Horizontal model mapper is used to create a connection between QAbstractBarSeries and QAbstractItemModel derived model object.
+ Model mapper maintains equal size of all the BarSets.
+ Adding/removing value from the BarSet causes the the same change in the rest of the BarSets added to the same series.
+ \note Used model has to support adding/removing rows/columns and modifying the data of the cells.
+*/
+/*!
+ \qmltype HBarModelMapper
+ \instantiates QHBarModelMapper
+ \inqmlmodule QtCharts
+
+ \brief Horizontal model mapper for bar series.
+
+ HBarModelMapper allows you to use your own QAbstractItemModel derived model with data in rows as
+ a data source for any bar series. It is possible to use both QAbstractItemModel and bar series
+ data API to manipulate data. HBarModelMapper keeps the series and the model in sync.
+
+ The following QML example would create a bar series with three bar sets (assuming the model has
+ at least four rows). Each bar set would contain data starting from column 1. The name of a set
+ would be defined by the vertical header (of the row).
+ \code
+ BarSeries {
+ HBarModelMapper {
+ model: myCustomModel // QAbstractItemModel derived implementation
+ firstBarSetRow: 1
+ lastBarSetRow: 3
+ firstColumn: 1
+ }
+ }
+ \endcode
+*/
+
+/*!
+ \property QHBarModelMapper::series
+ \brief Defines the QPieSeries object that is used by the mapper.
+
+ All the data in the series is discarded when it is set to the mapper.
+ When new series is specified the old series is disconnected (it preserves its data)
+*/
+/*!
+ \qmlproperty AbstractBarSeries HBarModelMapper::series
+ Defines the AbstractBarSeries based object that is used by the mapper. All the data in the series is discarded when it is
+ set to the mapper. When new series is specified the old series is disconnected (it preserves its data).
+*/
+
+/*!
+ \property QHBarModelMapper::model
+ \brief Defines the model that is used by the mapper.
+*/
+/*!
+ \qmlproperty SomeModel HBarModelMapper::model
+ The QAbstractItemModel based model that is used by the mapper. You need to implement the model
+ and expose it to QML. Note: the model has to support adding/removing rows/columns and modifying
+ the data of the cells.
+*/
+
+/*!
+ \property QHBarModelMapper::firstBarSetRow
+ \brief Defines which column of the model is used as the data source for the first bar set.
+
+ Default value is: -1 (invalid mapping)
+*/
+/*!
+ \qmlproperty int HBarModelMapper::firstBarSetRow
+ Defines which column of the model is used as the data source for the first bar set. The default value is -1
+ (invalid mapping).
+*/
+
+/*!
+ \property QHBarModelMapper::lastBarSetRow
+ \brief Defines which column of the model is used as the data source for the last bar set.
+
+ Default value is: -1 (invalid mapping)
+*/
+/*!
+ \qmlproperty int HBarModelMapper::lastBarSetRow
+ Defines which column of the model is used as the data source for the last bar set. The default value is -1
+ (invalid mapping).
+*/
+
+/*!
+ \property QHBarModelMapper::firstColumn
+ \brief Defines which column of the model contains the first values of the QBarSets in the series.
+
+ Minimal and default value is: 0
+*/
+/*!
+ \qmlproperty int HBarModelMapper::firstColumn
+ Defines which column of the model contains the first values of the QBarSets in the series.
+ The default value is 0.
+*/
+
+/*!
+ \property QHBarModelMapper::columnCount
+ \brief Defines the number of columns of the model that are mapped as the data for QAbstractBarSeries.
+
+ Minimal and default value is: -1 (count limited by the number of columns in the model)
+*/
+/*!
+ \qmlproperty int HBarModelMapper::columnCount
+ Defines the number of columns of the model that are mapped as the data for QAbstractBarSeries. The default value is
+ -1 (count limited by the number of columns in the model)
+*/
+
+/*!
+ \fn void QHBarModelMapper::seriesReplaced()
+
+ Emitted when the series to which mapper is connected to has changed.
+*/
+
+/*!
+ \fn void QHBarModelMapper::modelReplaced()
+
+ Emitted when the model to which mapper is connected to has changed.
+*/
+
+/*!
+ \fn void QHBarModelMapper::firstBarSetRowChanged()
+
+ Emitted when the firstBarSetRow has changed.
+*/
+
+/*!
+ \fn void QHBarModelMapper::lastBarSetRowChanged()
+
+ Emitted when the lastBarSetRow has changed.
+*/
+
+/*!
+ \fn void QHBarModelMapper::firstColumnChanged()
+ Emitted when the firstColumn has changed.
+*/
+
+/*!
+ \fn void QHBarModelMapper::columnCountChanged()
+ Emitted when the columnCount has changed.
+*/
+
+/*!
+ Constructs a mapper object which is a child of \a parent.
+*/
+QHBarModelMapper::QHBarModelMapper(QObject *parent) :
+ QBarModelMapper(parent)
+{
+ QBarModelMapper::setOrientation(Qt::Horizontal);
+}
+
+QAbstractItemModel *QHBarModelMapper::model() const
+{
+ return QBarModelMapper::model();
+}
+
+void QHBarModelMapper::setModel(QAbstractItemModel *model)
+{
+ if (model != QBarModelMapper::model()) {
+ QBarModelMapper::setModel(model);
+ emit modelReplaced();
+ }
+}
+
+QAbstractBarSeries *QHBarModelMapper::series() const
+{
+ return QBarModelMapper::series();
+}
+
+void QHBarModelMapper::setSeries(QAbstractBarSeries *series)
+{
+ if (series != QBarModelMapper::series()) {
+ QBarModelMapper::setSeries(series);
+ emit seriesReplaced();
+ }
+}
+
+int QHBarModelMapper::firstBarSetRow() const
+{
+ return QBarModelMapper::firstBarSetSection();
+}
+
+void QHBarModelMapper::setFirstBarSetRow(int firstBarSetRow)
+{
+ if (firstBarSetRow != firstBarSetSection()) {
+ QBarModelMapper::setFirstBarSetSection(firstBarSetRow);
+ emit firstBarSetRowChanged();
+ }
+}
+
+int QHBarModelMapper::lastBarSetRow() const
+{
+ return QBarModelMapper::lastBarSetSection();
+}
+
+void QHBarModelMapper::setLastBarSetRow(int lastBarSetRow)
+{
+ if (lastBarSetRow != lastBarSetSection()) {
+ QBarModelMapper::setLastBarSetSection(lastBarSetRow);
+ emit lastBarSetRowChanged();
+ }
+}
+
+int QHBarModelMapper::firstColumn() const
+{
+ return QBarModelMapper::first();
+}
+
+void QHBarModelMapper::setFirstColumn(int firstColumn)
+{
+ if (firstColumn != first()) {
+ QBarModelMapper::setFirst(firstColumn);
+ emit firstColumnChanged();
+ }
+}
+
+int QHBarModelMapper::columnCount() const
+{
+ return QBarModelMapper::count();
+}
+
+void QHBarModelMapper::setColumnCount(int columnCount)
+{
+ if (columnCount != count()) {
+ QBarModelMapper::setCount(columnCount);
+ emit columnCountChanged();
+ }
+}
+
+#include "moc_qhbarmodelmapper.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/barchart/qhbarmodelmapper.h b/src/charts/barchart/qhbarmodelmapper.h
new file mode 100644
index 00000000..ee281aef
--- /dev/null
+++ b/src/charts/barchart/qhbarmodelmapper.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHBARMODELMAPPER_H
+#define QHBARMODELMAPPER_H
+
+#include <QtCharts/QBarModelMapper>
+
+QT_CHARTS_BEGIN_NAMESPACE
+/* Comment line for syncqt to generate the fwd-include correctly, due to QTBUG-22432 */
+class QT_CHARTS_EXPORT QHBarModelMapper : public QBarModelMapper
+{
+ Q_OBJECT
+ Q_PROPERTY(QAbstractBarSeries *series READ series WRITE setSeries NOTIFY seriesReplaced)
+ Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelReplaced)
+ Q_PROPERTY(int firstBarSetRow READ firstBarSetRow WRITE setFirstBarSetRow NOTIFY firstBarSetRowChanged)
+ Q_PROPERTY(int lastBarSetRow READ lastBarSetRow WRITE setLastBarSetRow NOTIFY lastBarSetRowChanged)
+ Q_PROPERTY(int firstColumn READ firstColumn WRITE setFirstColumn NOTIFY firstColumnChanged)
+ Q_PROPERTY(int columnCount READ columnCount WRITE setColumnCount NOTIFY columnCountChanged)
+
+public:
+ explicit QHBarModelMapper(QObject *parent = 0);
+
+ QAbstractItemModel *model() const;
+ void setModel(QAbstractItemModel *model);
+
+ QAbstractBarSeries *series() const;
+ void setSeries(QAbstractBarSeries *series);
+
+ int firstBarSetRow() const;
+ void setFirstBarSetRow(int firstBarSetRow);
+
+ int lastBarSetRow() const;
+ void setLastBarSetRow(int lastBarSetRow);
+
+ int firstColumn() const;
+ void setFirstColumn(int firstColumn);
+
+ int columnCount() const;
+ void setColumnCount(int columnCount);
+
+Q_SIGNALS:
+ void seriesReplaced();
+ void modelReplaced();
+ void firstBarSetRowChanged();
+ void lastBarSetRowChanged();
+ void firstColumnChanged();
+ void columnCountChanged();
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QHBARMODELMAPPER_H
diff --git a/src/charts/barchart/qvbarmodelmapper.cpp b/src/charts/barchart/qvbarmodelmapper.cpp
new file mode 100644
index 00000000..a239e696
--- /dev/null
+++ b/src/charts/barchart/qvbarmodelmapper.cpp
@@ -0,0 +1,258 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvbarmodelmapper.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QVBarModelMapper
+ \inmodule Qt Charts
+ \brief Vertical model mapper for bar series.
+ \mainclass
+
+ Model mappers allow you to use QAbstractItemModel derived models as a data source for a chart series.
+ Vertical model mapper is used to create a connection between QAbstractBarSeries and QAbstractItemModel derived model object.
+ Model mapper maintains equal size of all the BarSets.
+ Adding/removing value from the BarSet causes the the same change in the rest of the BarSets added to the same series.
+ \note Used model has to support adding/removing rows/columns and modifying the data of the cells.
+*/
+/*!
+ \qmltype VBarModelMapper
+ \instantiates QVBarModelMapper
+ \inqmlmodule QtCharts
+
+ \inherits BarModelMapper
+
+ \brief Vertical model mapper for bar series.
+
+ VBarModelMapper allows you to use your own QAbstractItemModel derived model with data in columns
+ as a data source for any bar series. It is possible to use both QAbstractItemModel and bar
+ series data API to manipulate data. VBarModelMapper keeps the series and the model in sync.
+
+ The following QML example would create a bar series with three bar sets (assuming the model has
+ at least four columns). Each bar set would contain data starting from row 1. The name of a set
+ would be defined by the horizontal header (of the column).
+ \code
+ BarSeries {
+ VBarModelMapper {
+ model: myCustomModel // QAbstractItemModel derived implementation
+ firstBarSetColumn: 1
+ lastBarSetColumn: 3
+ firstRow: 1
+ }
+ }
+ \endcode
+*/
+
+/*!
+ \property QVBarModelMapper::series
+ \brief Defines the QBarSeries object that is used by the mapper.
+
+ All the data in the series is discarded when it is set to the mapper.
+ When new series is specified the old series is disconnected (it preserves its data)
+*/
+/*!
+ \qmlproperty AbstractBarSeries VBarModelMapper::series
+ Defines the AbstractBarSeries based object that is used by the mapper. All the data in the series is discarded when it is
+ set to the mapper. When new series is specified the old series is disconnected (it preserves its data).
+*/
+
+/*!
+ \property QVBarModelMapper::model
+ \brief Defines the model that is used by the mapper.
+*/
+/*!
+ \qmlproperty SomeModel VBarModelMapper::model
+ The QAbstractItemModel based model that is used by the mapper. You need to implement the model
+ and expose it to QML. Note: the model has to support adding/removing rows/columns and modifying
+ the data of the cells.
+*/
+
+/*!
+ \property QVBarModelMapper::firstBarSetColumn
+ \brief Defines which column of the model is used as the data source for the first bar set.
+
+ Default value is: -1 (invalid mapping)
+*/
+/*!
+ \qmlproperty int VBarModelMapper::firstBarSetColumn
+ Defines which column of the model is used as the data source for the first bar set. Default value
+ is: -1 (invalid mapping).
+*/
+
+/*!
+ \property QVBarModelMapper::lastBarSetColumn
+ \brief Defines which column of the model is used as the data source for the last bar set.
+
+ Default value is: -1 (invalid mapping)
+*/
+/*!
+ \qmlproperty int VBarModelMapper::lastBarSetColumn
+ Defines which column of the model is used as the data source for the last bar set. Default
+ value is: -1 (invalid mapping).
+*/
+
+/*!
+ \property QVBarModelMapper::firstRow
+ \brief Defines which row of the model contains the first values of the QBarSets in the series.
+
+ Minimal and default value is: 0
+*/
+/*!
+ \qmlproperty int VBarModelMapper::firstRow
+ Defines which row of the model contains the first values of the QBarSets in the series.
+ The default value is 0.
+*/
+
+/*!
+ \property QVBarModelMapper::rowCount
+ \brief Defines the number of rows of the model that are mapped as the data for QAbstractBarSeries.
+
+ Minimal and default value is: -1 (count limited by the number of rows in the model)
+*/
+/*!
+ \qmlproperty int VBarModelMapper::rowCount
+ Defines the number of rows of the model that are mapped as the data for QAbstractBarSeries. The default value is
+ -1 (count limited by the number of rows in the model)
+*/
+
+/*!
+ \fn void QVBarModelMapper::seriesReplaced()
+
+ Emitted when the series to which mapper is connected to has changed.
+*/
+
+/*!
+ \fn void QVBarModelMapper::modelReplaced()
+
+ Emitted when the model to which mapper is connected to has changed.
+*/
+
+/*!
+ \fn void QVBarModelMapper::firstBarSetColumnChanged()
+ Emitted when the firstBarSetColumn has changed.
+*/
+
+/*!
+ \fn void QVBarModelMapper::lastBarSetColumnChanged()
+ Emitted when the lastBarSetColumn has changed.
+*/
+
+/*!
+ \fn void QVBarModelMapper::firstRowChanged()
+ Emitted when the firstRow has changed.
+*/
+
+/*!
+ \fn void QVBarModelMapper::rowCountChanged()
+ Emitted when the rowCount has changed.
+*/
+
+/*!
+ Constructs a mapper object which is a child of \a parent.
+*/
+QVBarModelMapper::QVBarModelMapper(QObject *parent) :
+ QBarModelMapper(parent)
+{
+ QBarModelMapper::setOrientation(Qt::Vertical);
+}
+
+QAbstractItemModel *QVBarModelMapper::model() const
+{
+ return QBarModelMapper::model();
+}
+
+void QVBarModelMapper::setModel(QAbstractItemModel *model)
+{
+ if (model != QBarModelMapper::model()) {
+ QBarModelMapper::setModel(model);
+ emit modelReplaced();
+ }
+}
+
+QAbstractBarSeries *QVBarModelMapper::series() const
+{
+ return QBarModelMapper::series();
+}
+
+void QVBarModelMapper::setSeries(QAbstractBarSeries *series)
+{
+ if (series != QBarModelMapper::series()) {
+ QBarModelMapper::setSeries(series);
+ emit seriesReplaced();
+ }
+}
+
+int QVBarModelMapper::firstBarSetColumn() const
+{
+ return QBarModelMapper::firstBarSetSection();
+}
+
+void QVBarModelMapper::setFirstBarSetColumn(int firstBarSetColumn)
+{
+ if (firstBarSetColumn != firstBarSetSection()) {
+ QBarModelMapper::setFirstBarSetSection(firstBarSetColumn);
+ emit firstBarSetColumnChanged();
+ }
+}
+
+int QVBarModelMapper::lastBarSetColumn() const
+{
+ return QBarModelMapper::lastBarSetSection();
+}
+
+void QVBarModelMapper::setLastBarSetColumn(int lastBarSetColumn)
+{
+ if (lastBarSetColumn != lastBarSetSection()) {
+ QBarModelMapper::setLastBarSetSection(lastBarSetColumn);
+ emit lastBarSetColumnChanged();
+ }
+}
+
+int QVBarModelMapper::firstRow() const
+{
+ return QBarModelMapper::first();
+}
+
+void QVBarModelMapper::setFirstRow(int firstRow)
+{
+ if (firstRow != first()) {
+ QBarModelMapper::setFirst(firstRow);
+ emit firstRowChanged();
+ }
+}
+
+int QVBarModelMapper::rowCount() const
+{
+ return QBarModelMapper::count();
+}
+
+void QVBarModelMapper::setRowCount(int rowCount)
+{
+ if (rowCount != count()) {
+ QBarModelMapper::setCount(rowCount);
+ emit rowCountChanged();
+ }
+}
+
+#include "moc_qvbarmodelmapper.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/barchart/qvbarmodelmapper.h b/src/charts/barchart/qvbarmodelmapper.h
new file mode 100644
index 00000000..5f16ac72
--- /dev/null
+++ b/src/charts/barchart/qvbarmodelmapper.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVBARMODELMAPPER_H
+#define QVBARMODELMAPPER_H
+
+#include <QtCharts/QBarModelMapper>
+
+QT_CHARTS_BEGIN_NAMESPACE
+/* Comment line for syncqt to generate the fwd-include correctly, due to QTBUG-22432 */
+class QT_CHARTS_EXPORT QVBarModelMapper : public QBarModelMapper
+{
+ Q_OBJECT
+ Q_PROPERTY(QAbstractBarSeries *series READ series WRITE setSeries NOTIFY seriesReplaced)
+ Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelReplaced)
+ Q_PROPERTY(int firstBarSetColumn READ firstBarSetColumn WRITE setFirstBarSetColumn NOTIFY firstBarSetColumnChanged)
+ Q_PROPERTY(int lastBarSetColumn READ lastBarSetColumn WRITE setLastBarSetColumn NOTIFY lastBarSetColumnChanged)
+ Q_PROPERTY(int firstRow READ firstRow WRITE setFirstRow NOTIFY firstRowChanged)
+ Q_PROPERTY(int rowCount READ rowCount WRITE setRowCount NOTIFY rowCountChanged)
+
+public:
+ explicit QVBarModelMapper(QObject *parent = 0);
+
+ QAbstractItemModel *model() const;
+ void setModel(QAbstractItemModel *model);
+
+ QAbstractBarSeries *series() const;
+ void setSeries(QAbstractBarSeries *series);
+
+ int firstBarSetColumn() const;
+ void setFirstBarSetColumn(int firstBarSetColumn);
+
+ int lastBarSetColumn() const;
+ void setLastBarSetColumn(int lastBarSetColumn);
+
+ int firstRow() const;
+ void setFirstRow(int firstRow);
+
+ int rowCount() const;
+ void setRowCount(int rowCount);
+
+Q_SIGNALS:
+ void seriesReplaced();
+ void modelReplaced();
+ void firstBarSetColumnChanged();
+ void lastBarSetColumnChanged();
+ void firstRowChanged();
+ void rowCountChanged();
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QVBARMODELMAPPER_H
diff --git a/src/charts/barchart/vertical/bar/barchartitem.cpp b/src/charts/barchart/vertical/bar/barchartitem.cpp
new file mode 100644
index 00000000..86b63045
--- /dev/null
+++ b/src/charts/barchart/vertical/bar/barchartitem.cpp
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "barchartitem_p.h"
+#include "bar_p.h"
+#include "qabstractbarseries_p.h"
+#include "qbarset.h"
+#include "qbarset_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+BarChartItem::BarChartItem(QAbstractBarSeries *series, QGraphicsItem* item) :
+ AbstractBarChartItem(series, item)
+{
+ connect(series, SIGNAL(labelsPositionChanged(QAbstractBarSeries::LabelsPosition)),
+ this, SLOT(handleLabelsPositionChanged()));
+ connect(series, SIGNAL(labelsFormatChanged(QString)), this, SLOT(positionLabels()));
+}
+
+void BarChartItem::initializeLayout()
+{
+ qreal categoryCount = m_series->d_func()->categoryCount();
+ qreal setCount = m_series->count();
+ qreal barWidth = m_series->d_func()->barWidth();
+
+ m_layout.clear();
+ for(int category = 0; category < categoryCount; category++) {
+ for (int set = 0; set < setCount; set++) {
+ QRectF rect;
+ QPointF topLeft;
+ QPointF bottomRight;
+
+ if (domain()->type() == AbstractDomain::XLogYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) {
+ topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + set/setCount * barWidth, domain()->minY()), m_validData);
+ bottomRight = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + (set + 1)/setCount * barWidth, domain()->minY()), m_validData);
+ } else {
+ topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + set/setCount * barWidth, 0), m_validData);
+ bottomRight = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + (set + 1)/setCount * barWidth, 0), m_validData);
+ }
+
+ if (!m_validData)
+ return;
+ rect.setTopLeft(topLeft);
+ rect.setBottomRight(bottomRight);
+ m_layout.append(rect.normalized());
+ }
+ }
+}
+
+QVector<QRectF> BarChartItem::calculateLayout()
+{
+ QVector<QRectF> layout;
+
+ // Use temporary qreals for accuracy
+ qreal categoryCount = m_series->d_func()->categoryCount();
+ qreal setCount = m_series->count();
+ qreal barWidth = m_series->d_func()->barWidth();
+
+ for(int category = 0; category < categoryCount; category++) {
+ for (int set = 0; set < setCount; set++) {
+ qreal value = m_series->barSets().at(set)->at(category);
+ QRectF rect;
+ QPointF topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + (set)/(setCount) * barWidth, value), m_validData);
+ QPointF bottomRight;
+ if (domain()->type() == AbstractDomain::XLogYDomain || domain()->type() == AbstractDomain::LogXLogYDomain)
+ bottomRight = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + (set + 1)/(setCount) * barWidth, domain()->minY()), m_validData);
+ else
+ bottomRight = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + (set + 1)/(setCount) * barWidth, 0), m_validData);
+
+ rect.setTopLeft(topLeft);
+ rect.setBottomRight(bottomRight);
+ layout.append(rect.normalized());
+ }
+ }
+
+ return layout;
+}
+
+void BarChartItem::handleLabelsPositionChanged()
+{
+ positionLabels();
+}
+
+void BarChartItem::positionLabels()
+{
+ for (int i = 0; i < m_layout.count(); i++) {
+ QGraphicsTextItem *label = m_labels.at(i);
+ qreal xPos = m_layout.at(i).center().x() - label->boundingRect().center().x();
+ qreal yPos = 0;
+
+ int offset = m_bars.at(i)->pen().width() / 2 + 2;
+ if (m_series->labelsPosition() == QAbstractBarSeries::LabelsCenter)
+ yPos = m_layout.at(i).center().y() - label->boundingRect().center().y();
+ else if (m_series->labelsPosition() == QAbstractBarSeries::LabelsInsideEnd)
+ yPos = m_layout.at(i).top() - offset;
+ else if (m_series->labelsPosition() == QAbstractBarSeries::LabelsInsideBase)
+ yPos = m_layout.at(i).bottom() - label->boundingRect().height() + offset;
+ else if (m_series->labelsPosition() == QAbstractBarSeries::LabelsOutsideEnd)
+ yPos = m_layout.at(i).top() - label->boundingRect().height() + offset;
+
+ label->setPos(xPos, yPos);
+ label->setZValue(zValue() + 1);
+ }
+}
+
+#include "moc_barchartitem_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/barchart/vertical/bar/barchartitem_p.h b/src/charts/barchart/vertical/bar/barchartitem_p.h
new file mode 100644
index 00000000..09df0dbf
--- /dev/null
+++ b/src/charts/barchart/vertical/bar/barchartitem_p.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 BARCHARTITEM_H
+#define BARCHARTITEM_H
+
+#include "abstractbarchartitem_p.h"
+#include <qstackedbarseries.h>
+#include <QGraphicsItem>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class BarChartItem : public AbstractBarChartItem
+{
+ Q_OBJECT
+public:
+ BarChartItem(QAbstractBarSeries *series, QGraphicsItem* item = 0);
+
+private slots:
+ void handleLabelsPositionChanged();
+ void positionLabels();
+
+private:
+ virtual QVector<QRectF> calculateLayout();
+ void initializeLayout();
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // BARCHARTITEM_H
diff --git a/src/charts/barchart/vertical/bar/qbarseries.cpp b/src/charts/barchart/vertical/bar/qbarseries.cpp
new file mode 100644
index 00000000..3ab2a1ee
--- /dev/null
+++ b/src/charts/barchart/vertical/bar/qbarseries.cpp
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbarseries.h"
+#include "qbarseries_p.h"
+#include "barchartitem_p.h"
+#include "chartdataset_p.h"
+#include "charttheme_p.h"
+#include "qvalueaxis.h"
+#include "qbarcategoryaxis.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QBarSeries
+ \inmodule Qt Charts
+ \brief Series for creating bar chart.
+ \mainclass
+
+ QBarSeries represents a series of data shown as bars. The purpose of this class is to draw bars
+ as groups, where bars in same category are grouped next to each other. QBarSeries groups the data
+ from sets to categories, which are defined by a QStringList.
+
+ See the \l {BarChart Example} {bar chart example} to learn how to create a grouped bar chart.
+ \image examples_barchart.png
+
+ \sa QBarSet, QPercentBarSeries, QAbstractBarSeries, QStackedBarSeries
+*/
+/*!
+ \qmltype BarSeries
+ \instantiates QBarSeries
+ \inqmlmodule QtCharts
+
+ \inherits AbstractBarSeries
+
+ \brief Series for creating bar chart.
+
+ The following QML shows how to create a simple grouped bar chart:
+ \snippet qmlchart/qml/qmlchart/View6.qml 1
+ \beginfloatleft
+ \image examples_qmlchart6.png
+ \endfloat
+ \clearfloat
+*/
+
+/*!
+ Constructs empty QBarSeries.
+ QBarSeries is QObject which is a child of a \a parent.
+*/
+QBarSeries::QBarSeries(QObject *parent)
+ : QAbstractBarSeries(*new QBarSeriesPrivate(this), parent)
+{
+
+}
+
+/*!
+ Returns QAbstractSeries::SeriesTypeBar.
+*/
+QAbstractSeries::SeriesType QBarSeries::type() const
+{
+ return QAbstractSeries::SeriesTypeBar;
+}
+
+/*!
+ Destructor. Removes series from chart.
+*/
+QBarSeries::~QBarSeries()
+{
+ Q_D(QBarSeries);
+ if (d->m_chart)
+ d->m_chart->removeSeries(this);
+}
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QBarSeriesPrivate::QBarSeriesPrivate(QBarSeries *q) : QAbstractBarSeriesPrivate(q)
+{
+
+}
+
+void QBarSeriesPrivate::initializeDomain()
+{
+ qreal minX(domain()->minX());
+ qreal minY(domain()->minY());
+ qreal maxX(domain()->maxX());
+ qreal maxY(domain()->maxY());
+
+ qreal x = categoryCount();
+ minX = qMin(minX, - (qreal)0.5);
+ minY = qMin(minY, min());
+ maxX = qMax(maxX, x - (qreal)0.5);
+ maxY = qMax(maxY, max());
+
+ domain()->setRange(minX, maxX, minY, maxY);
+}
+
+
+void QBarSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
+{
+ Q_Q(QBarSeries);
+ BarChartItem *bar = new BarChartItem(q,parent);
+ m_item.reset(bar);
+ QAbstractSeriesPrivate::initializeGraphics(parent);
+}
+
+#include "moc_qbarseries.cpp"
+
+QT_CHARTS_END_NAMESPACE
+
diff --git a/src/charts/barchart/vertical/bar/qbarseries.h b/src/charts/barchart/vertical/bar/qbarseries.h
new file mode 100644
index 00000000..d3fefd8a
--- /dev/null
+++ b/src/charts/barchart/vertical/bar/qbarseries.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBARSERIES_H
+#define QBARSERIES_H
+
+#include <QtCharts/qabstractbarseries.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QBarSeriesPrivate;
+
+class QT_CHARTS_EXPORT QBarSeries : public QAbstractBarSeries
+{
+ Q_OBJECT
+public:
+ explicit QBarSeries(QObject *parent = 0);
+ ~QBarSeries();
+ QAbstractSeries::SeriesType type() const;
+
+private:
+ Q_DECLARE_PRIVATE(QBarSeries)
+ Q_DISABLE_COPY(QBarSeries)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QBARSERIES_H
diff --git a/src/charts/barchart/vertical/bar/qbarseries_p.h b/src/charts/barchart/vertical/bar/qbarseries_p.h
new file mode 100644
index 00000000..c74194d3
--- /dev/null
+++ b/src/charts/barchart/vertical/bar/qbarseries_p.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QBARSERIES_P_H
+#define QBARSERIES_P_H
+
+#include "qabstractbarseries_p.h"
+#include "abstractdomain_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+
+class QBarSeriesPrivate: public QAbstractBarSeriesPrivate
+{
+public:
+ QBarSeriesPrivate(QBarSeries *q);
+ void initializeGraphics(QGraphicsItem* parent);
+ void initializeDomain();
+
+private:
+ Q_DECLARE_PUBLIC(QBarSeries)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QBARSERIES_P_H
diff --git a/src/charts/barchart/vertical/percent/percentbarchartitem.cpp b/src/charts/barchart/vertical/percent/percentbarchartitem.cpp
new file mode 100644
index 00000000..1e0bbbae
--- /dev/null
+++ b/src/charts/barchart/vertical/percent/percentbarchartitem.cpp
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "percentbarchartitem_p.h"
+#include "bar_p.h"
+#include "qabstractbarseries_p.h"
+#include "qbarset.h"
+#include "qbarset_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+PercentBarChartItem::PercentBarChartItem(QAbstractBarSeries *series, QGraphicsItem* item) :
+ AbstractBarChartItem(series, item)
+{
+ connect(series, SIGNAL(labelsPositionChanged(QAbstractBarSeries::LabelsPosition)),
+ this, SLOT(handleLabelsPositionChanged()));
+ connect(series, SIGNAL(labelsFormatChanged(QString)), this, SLOT(positionLabels()));
+}
+
+void PercentBarChartItem::initializeLayout()
+{
+ qreal categoryCount = m_series->d_func()->categoryCount();
+ qreal setCount = m_series->count();
+ qreal barWidth = m_series->d_func()->barWidth();
+
+ m_layout.clear();
+ for(int category = 0; category < categoryCount; category++) {
+ for (int set = 0; set < setCount; set++) {
+ QRectF rect;
+ QPointF topLeft;
+ QPointF bottomRight;
+
+ if (domain()->type() == AbstractDomain::XLogYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) {
+ topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, domain()->minY()), m_validData);
+ bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, domain()->minY()), m_validData);
+ } else {
+ topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, 0), m_validData);
+ bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, 0), m_validData);
+ }
+
+ if (!m_validData)
+ return;
+
+ rect.setTopLeft(topLeft);
+ rect.setBottomRight(bottomRight);
+ m_layout.append(rect.normalized());
+ }
+ }
+}
+
+QVector<QRectF> PercentBarChartItem::calculateLayout()
+{
+ QVector<QRectF> layout;
+
+ // Use temporary qreals for accuracy
+ qreal categoryCount = m_series->d_func()->categoryCount();
+ qreal setCount = m_series->count();
+ qreal barWidth = m_series->d_func()->barWidth();
+
+ for(int category = 0; category < categoryCount; category++) {
+ qreal sum = 0;
+ qreal categorySum = m_series->d_func()->categorySum(category);
+ for (int set = 0; set < setCount; set++) {
+ qreal value = m_series->barSets().at(set)->at(category);
+ QRectF rect;
+ qreal topY = 0;
+ qreal newSum = value + sum;
+ if (newSum > 0)
+ topY = 100 * newSum / categorySum;
+ qreal bottomY = 0;
+ if (sum > 0)
+ bottomY = 100 * sum / categorySum;
+ QPointF topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth/2, topY), m_validData);
+ QPointF bottomRight;
+ if (domain()->type() == AbstractDomain::XLogYDomain || domain()->type() == AbstractDomain::LogXLogYDomain)
+ bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth/2, set ? bottomY : domain()->minY()), m_validData);
+ else
+ bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth/2, set ? bottomY : 0), m_validData);
+
+ rect.setTopLeft(topLeft);
+ rect.setBottomRight(bottomRight);
+ layout.append(rect.normalized());
+ sum = newSum;
+ }
+ }
+ return layout;
+}
+
+void PercentBarChartItem::handleUpdatedBars()
+{
+ // Handle changes in pen, brush, labels etc.
+ int categoryCount = m_series->d_func()->categoryCount();
+ int setCount = m_series->count();
+ int itemIndex(0);
+ static const QString valueTag(QLatin1String("@value"));
+
+ for (int category = 0; category < categoryCount; category++) {
+ for (int set = 0; set < setCount; set++) {
+ QBarSetPrivate *barSet = m_series->d_func()->barsetAt(set)->d_ptr.data();
+ Bar *bar = m_bars.at(itemIndex);
+ bar->setPen(barSet->m_pen);
+ bar->setBrush(barSet->m_brush);
+ bar->update();
+
+ QGraphicsTextItem *label = m_labels.at(itemIndex);
+ qreal p = m_series->d_func()->percentageAt(set, category) * 100.0;
+ QString vString(presenter()->numberToString(p, 'f', 0));
+ QString valueLabel;
+ if (m_series->labelsFormat().isEmpty()) {
+ vString.append(QStringLiteral("%"));
+ valueLabel = vString;
+ } else {
+ valueLabel = m_series->labelsFormat();
+ valueLabel.replace(valueTag, vString);
+ }
+ label->setHtml(valueLabel);
+ label->setFont(barSet->m_labelFont);
+ label->setDefaultTextColor(barSet->m_labelBrush.color());
+ label->update();
+ itemIndex++;
+ }
+ }
+}
+
+void PercentBarChartItem::handleLabelsPositionChanged()
+{
+ positionLabels();
+}
+
+void PercentBarChartItem::positionLabels()
+{
+ for (int i = 0; i < m_layout.count(); i++) {
+ QGraphicsTextItem *label = m_labels.at(i);
+ qreal xPos = m_layout.at(i).center().x() - label->boundingRect().center().x();
+ qreal yPos = 0;
+
+ int offset = m_bars.at(i)->pen().width() / 2 + 2;
+ if (m_series->labelsPosition() == QAbstractBarSeries::LabelsCenter)
+ yPos = m_layout.at(i).center().y() - label->boundingRect().center().y();
+ else if (m_series->labelsPosition() == QAbstractBarSeries::LabelsInsideEnd)
+ yPos = m_layout.at(i).top() - offset;
+ else if (m_series->labelsPosition() == QAbstractBarSeries::LabelsInsideBase)
+ yPos = m_layout.at(i).bottom() - label->boundingRect().height() + offset;
+ else if (m_series->labelsPosition() == QAbstractBarSeries::LabelsOutsideEnd)
+ yPos = m_layout.at(i).top() - label->boundingRect().height() + offset;
+
+ label->setPos(xPos, yPos);
+ label->setZValue(zValue() + 1);
+ }
+}
+
+#include "moc_percentbarchartitem_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/barchart/vertical/percent/percentbarchartitem_p.h b/src/charts/barchart/vertical/percent/percentbarchartitem_p.h
new file mode 100644
index 00000000..4293d875
--- /dev/null
+++ b/src/charts/barchart/vertical/percent/percentbarchartitem_p.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 PERCENTBARCHARTITEM_H
+#define PERCENTBARCHARTITEM_H
+
+#include "abstractbarchartitem_p.h"
+#include <QGraphicsItem>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QAbstractBarSeries;
+
+class PercentBarChartItem : public AbstractBarChartItem
+{
+ Q_OBJECT
+public:
+ PercentBarChartItem(QAbstractBarSeries *series, QGraphicsItem* item = 0);
+ void handleUpdatedBars();
+
+private slots:
+ void handleLabelsPositionChanged();
+ void positionLabels();
+
+private:
+ virtual QVector<QRectF> calculateLayout();
+ void initializeLayout();
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // PERCENTBARCHARTITEM_H
diff --git a/src/charts/barchart/vertical/percent/qpercentbarseries.cpp b/src/charts/barchart/vertical/percent/qpercentbarseries.cpp
new file mode 100644
index 00000000..7899899b
--- /dev/null
+++ b/src/charts/barchart/vertical/percent/qpercentbarseries.cpp
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpercentbarseries.h"
+#include "qpercentbarseries_p.h"
+#include "percentbarchartitem_p.h"
+#include "chartdataset_p.h"
+#include "charttheme_p.h"
+#include "qvalueaxis.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QPercentBarSeries
+ \inmodule Qt Charts
+ \brief Series for creating percent bar chart.
+ \mainclass
+
+ QPercentBarSeries represents a series of data shown as bars. The purpose of this class is to
+ draw bars as stacks, where each bar is shown as percentage of all bars in that category.
+ QPercentBarSeries groups the data from sets to categories, which are defined by a QStringList.
+ Bars with zero value are not drawn.
+
+ See the \l {PercentbarChart Example} {percent bar chart example} to learn how to create a
+ percent bar chart.
+ \image examples_percentbarchart.png
+
+ \sa QBarSet, QStackedBarSeries, QAbstractBarSeries
+*/
+/*!
+ \qmltype PercentBarSeries
+ \instantiates QPercentBarSeries
+ \inqmlmodule QtCharts
+
+ \inherits AbstractBarSeries
+
+ \brief Series for creating persent bar chart.
+
+ The following QML shows how to create a simple percent bar chart:
+ \snippet qmlchart/qml/qmlchart/View8.qml 1
+ \beginfloatleft
+ \image examples_qmlchart8.png
+ \endfloat
+ \clearfloat
+*/
+
+/*!
+ Constructs empty QPercentBarSeries.
+ QPercentBarSeries is QObject which is a child of a \a parent.
+*/
+QPercentBarSeries::QPercentBarSeries(QObject *parent)
+ : QAbstractBarSeries(*new QPercentBarSeriesPrivate(this), parent)
+{
+}
+
+/*!
+ Destructor. Removes series from chart.
+*/
+QPercentBarSeries::~QPercentBarSeries()
+{
+ Q_D(QPercentBarSeries);
+ if (d->m_chart)
+ d->m_chart->removeSeries(this);
+}
+
+/*!
+ Returns QAbstractSeries::SeriesTypePercentBar.
+*/
+QAbstractSeries::SeriesType QPercentBarSeries::type() const
+{
+ return QAbstractSeries::SeriesTypePercentBar;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QPercentBarSeriesPrivate::QPercentBarSeriesPrivate(QPercentBarSeries *q) : QAbstractBarSeriesPrivate(q)
+{
+
+}
+
+void QPercentBarSeriesPrivate::initializeDomain()
+{
+ qreal minX(domain()->minX());
+ qreal minY(domain()->minY());
+ qreal maxX(domain()->maxX());
+ qreal maxY(domain()->maxY());
+
+ qreal x = categoryCount();
+ minX = qMin(minX, - (qreal)0.5);
+ maxX = qMax(maxX, x - (qreal)0.5);
+ minY = 0;
+ maxY = 100;
+
+ domain()->setRange(minX, maxX, minY, maxY);
+}
+
+
+void QPercentBarSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
+{
+ Q_Q(QPercentBarSeries);
+ PercentBarChartItem *bar = new PercentBarChartItem(q,parent);
+ m_item.reset(bar);
+ QAbstractSeriesPrivate::initializeGraphics(parent);
+}
+
+#include "moc_qpercentbarseries.cpp"
+
+QT_CHARTS_END_NAMESPACE
+
diff --git a/src/charts/barchart/vertical/percent/qpercentbarseries.h b/src/charts/barchart/vertical/percent/qpercentbarseries.h
new file mode 100644
index 00000000..5f9ce140
--- /dev/null
+++ b/src/charts/barchart/vertical/percent/qpercentbarseries.h
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPERCENTBARSERIES_H
+#define QPERCENTBARSERIES_H
+
+#include <QStringList>
+#include <QtCharts/qabstractbarseries.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QPercentBarSeriesPrivate;
+
+class QT_CHARTS_EXPORT QPercentBarSeries : public QAbstractBarSeries
+{
+ Q_OBJECT
+public:
+ explicit QPercentBarSeries(QObject *parent = 0);
+ ~QPercentBarSeries();
+ QAbstractSeries::SeriesType type() const;
+
+private:
+ Q_DECLARE_PRIVATE(QPercentBarSeries)
+ Q_DISABLE_COPY(QPercentBarSeries)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QPERCENTBARSERIES_H
diff --git a/src/charts/barchart/vertical/percent/qpercentbarseries_p.h b/src/charts/barchart/vertical/percent/qpercentbarseries_p.h
new file mode 100644
index 00000000..f31c9638
--- /dev/null
+++ b/src/charts/barchart/vertical/percent/qpercentbarseries_p.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QPERCENTBARSERIES_P_H
+#define QPERCENTBARSERIES_P_H
+
+#include "qabstractbarseries_p.h"
+#include "abstractdomain_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+
+class QPercentBarSeriesPrivate: public QAbstractBarSeriesPrivate
+{
+public:
+ QPercentBarSeriesPrivate(QPercentBarSeries *q);
+ void initializeDomain();
+ void initializeGraphics(QGraphicsItem* parent);
+private:
+ Q_DECLARE_PUBLIC(QPercentBarSeries)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/barchart/vertical/stacked/qstackedbarseries.cpp b/src/charts/barchart/vertical/stacked/qstackedbarseries.cpp
new file mode 100644
index 00000000..7a1946f7
--- /dev/null
+++ b/src/charts/barchart/vertical/stacked/qstackedbarseries.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qstackedbarseries.h"
+#include "qstackedbarseries_p.h"
+#include "stackedbarchartitem_p.h"
+#include "chartdataset_p.h"
+#include "charttheme_p.h"
+#include "qvalueaxis.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QStackedBarSeries
+ \inmodule Qt Charts
+ \brief Series for creating stacked bar chart.
+ \mainclass
+
+ QStackedBarSeries represents a series of data shown as bars. The purpose of this class is to draw bars
+ as stacks, where bars in same category are stacked on top of each other.
+ QStackedBarSeries groups the data from sets to categories, which are defined by QStringList.
+
+ See the \l {StackedbarChart Example} {stacked bar chart example} to learn how to create a stacked bar chart.
+ \image examples_stackedbarchart.png
+
+ \sa QBarSet, QPercentBarSeries, QAbstractBarSeries
+*/
+
+/*!
+ \qmltype StackedBarSeries
+ \instantiates QStackedBarSeries
+ \inqmlmodule QtCharts
+
+ \inherits AbstractBarSeries
+
+ \brief Series for creating stacked bar chart.
+
+ The following QML shows how to create a simple stacked bar chart:
+ \snippet qmlchart/qml/qmlchart/View7.qml 1
+ \beginfloatleft
+ \image examples_qmlchart7.png
+ \endfloat
+ \clearfloat
+*/
+
+/*!
+ Constructs empty QStackedBarSeries.
+ QStackedBarSeries is QObject which is a child of a \a parent.
+*/
+QStackedBarSeries::QStackedBarSeries(QObject *parent)
+ : QAbstractBarSeries(*new QStackedBarSeriesPrivate(this), parent)
+{
+}
+
+/*!
+ Destructor. Removes series from chart.
+*/
+QStackedBarSeries::~QStackedBarSeries()
+{
+ Q_D(QStackedBarSeries);
+ if (d->m_chart)
+ d->m_chart->removeSeries(this);
+}
+/*!
+ Returns QAbstractSeries::SeriesTypeStackedBar.
+*/
+QAbstractSeries::SeriesType QStackedBarSeries::type() const
+{
+ return QAbstractSeries::SeriesTypeStackedBar;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QStackedBarSeriesPrivate::QStackedBarSeriesPrivate(QStackedBarSeries *q) : QAbstractBarSeriesPrivate(q)
+{
+
+}
+
+void QStackedBarSeriesPrivate::initializeDomain()
+{
+ qreal minX(domain()->minX());
+ qreal minY(domain()->minY());
+ qreal maxX(domain()->maxX());
+ qreal maxY(domain()->maxY());
+
+ qreal x = categoryCount();
+ minX = qMin(minX, - (qreal)0.5);
+ minY = qMin(minY, bottom());
+ maxX = qMax(maxX, x - (qreal)0.5);
+ maxY = qMax(maxY, top());
+
+ domain()->setRange(minX, maxX, minY, maxY);
+}
+
+void QStackedBarSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
+{
+ Q_Q(QStackedBarSeries);
+ StackedBarChartItem *bar = new StackedBarChartItem(q,parent);
+ m_item.reset(bar);
+ QAbstractSeriesPrivate::initializeGraphics(parent);
+}
+
+#include "moc_qstackedbarseries.cpp"
+
+QT_CHARTS_END_NAMESPACE
+
diff --git a/src/charts/barchart/vertical/stacked/qstackedbarseries.h b/src/charts/barchart/vertical/stacked/qstackedbarseries.h
new file mode 100644
index 00000000..bab6e174
--- /dev/null
+++ b/src/charts/barchart/vertical/stacked/qstackedbarseries.h
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTACKEDBARSERIES_H
+#define QSTACKEDBARSERIES_H
+
+#include <QStringList>
+#include <QtCharts/qabstractbarseries.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QStackedBarSeriesPrivate;
+
+class QT_CHARTS_EXPORT QStackedBarSeries : public QAbstractBarSeries
+{
+ Q_OBJECT
+public:
+ explicit QStackedBarSeries(QObject *parent = 0);
+ ~QStackedBarSeries();
+ QAbstractSeries::SeriesType type() const;
+
+private:
+ Q_DECLARE_PRIVATE(QStackedBarSeries)
+ Q_DISABLE_COPY(QStackedBarSeries)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QSTACKEDBARSERIES_H
diff --git a/src/charts/barchart/vertical/stacked/qstackedbarseries_p.h b/src/charts/barchart/vertical/stacked/qstackedbarseries_p.h
new file mode 100644
index 00000000..d5cf3c2d
--- /dev/null
+++ b/src/charts/barchart/vertical/stacked/qstackedbarseries_p.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QSTACKEDBARSERIES_P_H
+#define QSTACKEDBARSERIES_P_H
+
+#include "qabstractbarseries_p.h"
+#include "abstractdomain_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+
+class QStackedBarSeriesPrivate: public QAbstractBarSeriesPrivate
+{
+public:
+ QStackedBarSeriesPrivate(QStackedBarSeries *q);
+ void initializeGraphics(QGraphicsItem* parent);
+ void initializeDomain();
+private:
+ Q_DECLARE_PUBLIC(QStackedBarSeries)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/barchart/vertical/stacked/stackedbarchartitem.cpp b/src/charts/barchart/vertical/stacked/stackedbarchartitem.cpp
new file mode 100644
index 00000000..953bb455
--- /dev/null
+++ b/src/charts/barchart/vertical/stacked/stackedbarchartitem.cpp
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stackedbarchartitem_p.h"
+#include "bar_p.h"
+#include "qbarset_p.h"
+#include "qabstractbarseries_p.h"
+#include "qbarset.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+StackedBarChartItem::StackedBarChartItem(QAbstractBarSeries *series, QGraphicsItem* item) :
+ AbstractBarChartItem(series, item)
+{
+ connect(series, SIGNAL(labelsPositionChanged(QAbstractBarSeries::LabelsPosition)),
+ this, SLOT(handleLabelsPositionChanged()));
+ connect(series, SIGNAL(labelsFormatChanged(QString)), this, SLOT(positionLabels()));
+}
+
+void StackedBarChartItem::initializeLayout()
+{
+ qreal categoryCount = m_series->d_func()->categoryCount();
+ qreal setCount = m_series->count();
+ qreal barWidth = m_series->d_func()->barWidth();
+
+ m_layout.clear();
+ for(int category = 0; category < categoryCount; category++) {
+ for (int set = 0; set < setCount; set++) {
+ QRectF rect;
+ QPointF topLeft;
+ QPointF bottomRight;
+
+ if (domain()->type() == AbstractDomain::XLogYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) {
+ topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, domain()->minY()), m_validData);
+ bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, domain()->minY()), m_validData);
+ } else {
+ topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, 0), m_validData);
+ bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, 0), m_validData);
+ }
+
+ if (!m_validData)
+ return;
+
+ rect.setTopLeft(topLeft);
+ rect.setBottomRight(bottomRight);
+ m_layout.append(rect.normalized());
+ }
+ }
+}
+
+QVector<QRectF> StackedBarChartItem::calculateLayout()
+{
+ QVector<QRectF> layout;
+ // Use temporary qreals for accuracy
+ qreal categoryCount = m_series->d_func()->categoryCount();
+ qreal setCount = m_series->count();
+ qreal barWidth = m_series->d_func()->barWidth();
+
+ for(int category = 0; category < categoryCount; category++) {
+ qreal positiveSum = 0;
+ qreal negativeSum = 0;
+ for (int set = 0; set < setCount; set++) {
+ qreal value = m_series->barSets().at(set)->at(category);
+ QRectF rect;
+ QPointF topLeft;
+ QPointF bottomRight;
+ if (value < 0) {
+ bottomRight = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, value + negativeSum), m_validData);
+ if (domain()->type() == AbstractDomain::XLogYDomain || domain()->type() == AbstractDomain::LogXLogYDomain)
+ topLeft = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, set ? negativeSum : domain()->minY()), m_validData);
+ else
+ topLeft = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, set ? negativeSum : 0), m_validData);
+ negativeSum += value;
+ } else {
+ topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, value + positiveSum), m_validData);
+ if (domain()->type() == AbstractDomain::XLogYDomain || domain()->type() == AbstractDomain::LogXLogYDomain)
+ bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, set ? positiveSum : domain()->minY()), m_validData);
+ else
+ bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, set ? positiveSum : 0), m_validData);
+ positiveSum += value;
+ }
+
+ rect.setTopLeft(topLeft);
+ rect.setBottomRight(bottomRight);
+ layout.append(rect.normalized());
+ }
+ }
+ return layout;
+}
+
+void StackedBarChartItem::handleLabelsPositionChanged()
+{
+ positionLabels();
+}
+
+void StackedBarChartItem::positionLabels()
+{
+ for (int i = 0; i < m_layout.count(); i++) {
+ QGraphicsTextItem *label = m_labels.at(i);
+ qreal xPos = m_layout.at(i).center().x() - label->boundingRect().center().x();
+ qreal yPos = 0;
+
+ int offset = m_bars.at(i)->pen().width() / 2 + 2;
+ if (m_series->labelsPosition() == QAbstractBarSeries::LabelsCenter)
+ yPos = m_layout.at(i).center().y() - label->boundingRect().center().y();
+ else if (m_series->labelsPosition() == QAbstractBarSeries::LabelsInsideEnd)
+ yPos = m_layout.at(i).top() - offset;
+ else if (m_series->labelsPosition() == QAbstractBarSeries::LabelsInsideBase)
+ yPos = m_layout.at(i).bottom() - label->boundingRect().height() + offset;
+ else if (m_series->labelsPosition() == QAbstractBarSeries::LabelsOutsideEnd)
+ yPos = m_layout.at(i).top() - label->boundingRect().height() + offset;
+
+ label->setPos(xPos, yPos);
+ label->setZValue(zValue() + 1);
+ }
+}
+
+#include "moc_stackedbarchartitem_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/barchart/vertical/stacked/stackedbarchartitem_p.h b/src/charts/barchart/vertical/stacked/stackedbarchartitem_p.h
new file mode 100644
index 00000000..f2fa6b73
--- /dev/null
+++ b/src/charts/barchart/vertical/stacked/stackedbarchartitem_p.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 STACKEDBARCHARTITEM_H
+#define STACKEDBARCHARTITEM_H
+
+#include "abstractbarchartitem_p.h"
+#include <qstackedbarseries.h>
+#include <QGraphicsItem>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class StackedBarChartItem : public AbstractBarChartItem
+{
+ Q_OBJECT
+public:
+ StackedBarChartItem(QAbstractBarSeries *series, QGraphicsItem* item =0);
+
+private slots:
+ void handleLabelsPositionChanged();
+ void positionLabels();
+
+private:
+ virtual QVector<QRectF> calculateLayout();
+ void initializeLayout();
+
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // STACKEDBARCHARTITEM_H
diff --git a/src/charts/boxplotchart/boxplotchart.pri b/src/charts/boxplotchart/boxplotchart.pri
new file mode 100644
index 00000000..db6e034b
--- /dev/null
+++ b/src/charts/boxplotchart/boxplotchart.pri
@@ -0,0 +1,25 @@
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+
+SOURCES += \
+ $$PWD/boxplotchartitem.cpp \
+ $$PWD/qboxplotseries.cpp \
+ $$PWD/boxwhiskers.cpp \
+ $$PWD/qboxset.cpp \
+ $$PWD/qboxplotmodelmapper.cpp \
+ $$PWD/qvboxplotmodelmapper.cpp
+
+PRIVATE_HEADERS += \
+ $$PWD/boxplotchartitem_p.h \
+ $$PWD/qboxplotseries_p.h \
+ $$PWD/boxwhiskers_p.h \
+ $$PWD/boxwhiskersdata_p.h \
+ $$PWD/qboxset_p.h \
+ $$PWD/qboxplotmodelmapper_p.h
+
+PUBLIC_HEADERS += \
+ $$PWD/qboxplotseries.h \
+ $$PWD/qboxset.h \
+ $$PWD/qboxplotmodelmapper.h \
+ $$PWD/qvboxplotmodelmapper.h
+
diff --git a/src/charts/boxplotchart/boxplotchartitem.cpp b/src/charts/boxplotchart/boxplotchartitem.cpp
new file mode 100644
index 00000000..ac1734d5
--- /dev/null
+++ b/src/charts/boxplotchart/boxplotchartitem.cpp
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "boxplotchartitem_p.h"
+#include "qboxplotseries_p.h"
+#include "bar_p.h"
+#include "qboxset_p.h"
+#include "qabstractbarseries_p.h"
+#include "qboxset.h"
+#include "boxwhiskers_p.h"
+#include <QPainter>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+BoxPlotChartItem::BoxPlotChartItem(QBoxPlotSeries *series, QGraphicsItem *item) :
+ ChartItem(series->d_func(), item),
+ m_series(series),
+ m_animation(0)
+{
+ connect(series, SIGNAL(boxsetsRemoved(QList<QBoxSet *>)), this, SLOT(handleBoxsetRemove(QList<QBoxSet *>)));
+ connect(series->d_func(), SIGNAL(restructuredBoxes()), this, SLOT(handleDataStructureChanged()));
+ connect(series->d_func(), SIGNAL(updatedLayout()), this, SLOT(handleLayoutChanged()));
+ connect(series->d_func(), SIGNAL(updatedBoxes()), this, SLOT(handleUpdatedBars()));
+ connect(series->d_func(), SIGNAL(updated()), this, SLOT(handleUpdatedBars()));
+ // QBoxPlotSeriesPrivate calls handleDataStructureChanged(), don't do it here
+ setZValue(ChartPresenter::BoxPlotSeriesZValue);
+}
+
+BoxPlotChartItem::~BoxPlotChartItem()
+{
+}
+
+void BoxPlotChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(painter);
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+}
+
+void BoxPlotChartItem::setAnimation(BoxPlotAnimation *animation)
+{
+ m_animation = animation;
+ if (m_animation) {
+ foreach (BoxWhiskers *item, m_boxTable.values())
+ m_animation->addBox(item);
+ handleDomainUpdated();
+ }
+}
+
+void BoxPlotChartItem::handleDataStructureChanged()
+{
+ int setCount = m_series->count();
+
+ for (int s = 0; s < setCount; s++) {
+ QBoxSet *set = m_series->d_func()->boxSetAt(s);
+
+ BoxWhiskers *box = m_boxTable.value(set);
+ if (!box) {
+ // Item is not yet created, make a box and add it to hash table
+ box = new BoxWhiskers(set, domain(), this);
+ m_boxTable.insert(set, box);
+ connect(box, SIGNAL(clicked(QBoxSet *)), m_series, SIGNAL(clicked(QBoxSet *)));
+ connect(box, SIGNAL(hovered(bool, QBoxSet *)), m_series, SIGNAL(hovered(bool, QBoxSet *)));
+ connect(box, SIGNAL(clicked(QBoxSet *)), set, SIGNAL(clicked()));
+ connect(box, SIGNAL(hovered(bool, QBoxSet *)), set, SIGNAL(hovered(bool)));
+
+ // Set the decorative issues for the newly created box
+ // so that the brush and pen already defined for the set are kept.
+ if (set->brush() == Qt::NoBrush)
+ box->setBrush(m_series->brush());
+ else
+ box->setBrush(set->brush());
+ if (set->pen() == Qt::NoPen)
+ box->setPen(m_series->pen());
+ else
+ box->setPen(set->pen());
+ box->setBoxOutlined(m_series->boxOutlineVisible());
+ box->setBoxWidth(m_series->boxWidth());
+ }
+ updateBoxGeometry(box, s);
+
+ box->updateGeometry(domain());
+
+ if (m_animation)
+ m_animation->addBox(box);
+ }
+
+ handleDomainUpdated();
+}
+
+void BoxPlotChartItem::handleUpdatedBars()
+{
+ foreach (BoxWhiskers *item, m_boxTable.values()) {
+ item->setBrush(m_series->brush());
+ item->setPen(m_series->pen());
+ item->setBoxOutlined(m_series->boxOutlineVisible());
+ item->setBoxWidth(m_series->boxWidth());
+ }
+ // Override with QBoxSet specific settings
+ foreach (QBoxSet *set, m_boxTable.keys()) {
+ if (set->brush().style() != Qt::NoBrush)
+ m_boxTable.value(set)->setBrush(set->brush());
+ if (set->pen().style() != Qt::NoPen)
+ m_boxTable.value(set)->setPen(set->pen());
+ }
+}
+
+void BoxPlotChartItem::handleBoxsetRemove(QList<QBoxSet*> barSets)
+{
+ foreach (QBoxSet *set, barSets) {
+ BoxWhiskers *boxItem = m_boxTable.value(set);
+ m_boxTable.remove(set);
+ delete boxItem;
+ }
+}
+
+void BoxPlotChartItem::handleDomainUpdated()
+{
+ if ((domain()->size().width() <= 0) || (domain()->size().height() <= 0))
+ return;
+
+ // Set my bounding rect to same as domain size. Add one pixel at the top (-1.0) and the bottom as 0.0 would
+ // snip a bit off from the whisker at the grid line
+ m_boundingRect.setRect(0.0, -1.0, domain()->size().width(), domain()->size().height() + 1.0);
+
+ foreach (BoxWhiskers *item, m_boxTable.values()) {
+ item->updateGeometry(domain());
+
+ // If the animation is set, start the animation for each BoxWhisker item
+ if (m_animation)
+ presenter()->startAnimation(m_animation->boxAnimation(item));
+ }
+}
+
+void BoxPlotChartItem::handleLayoutChanged()
+{
+ foreach (BoxWhiskers *item, m_boxTable.values()) {
+ if (m_animation)
+ m_animation->setAnimationStart(item);
+
+ item->setBoxWidth(m_series->boxWidth());
+
+ bool dirty = updateBoxGeometry(item, item->m_data.m_index);
+ if (dirty && m_animation)
+ presenter()->startAnimation(m_animation->boxChangeAnimation(item));
+ else
+ item->updateGeometry(domain());
+ }
+}
+
+QRectF BoxPlotChartItem::boundingRect() const
+{
+ return m_boundingRect;
+}
+
+void BoxPlotChartItem::initializeLayout()
+{
+}
+
+QVector<QRectF> BoxPlotChartItem::calculateLayout()
+{
+ return QVector<QRectF>();
+}
+
+bool BoxPlotChartItem::updateBoxGeometry(BoxWhiskers *box, int index)
+{
+ bool changed = false;
+
+ QBoxSet *set = m_series->d_func()->boxSetAt(index);
+ BoxWhiskersData &data = box->m_data;
+
+ if ((data.m_lowerExtreme != set->at(0)) || (data.m_lowerQuartile != set->at(1)) ||
+ (data.m_median != set->at(2)) || (data.m_upperQuartile != set->at(3)) || (data.m_upperExtreme != set->at(4))) {
+ changed = true;
+ }
+
+ data.m_lowerExtreme = set->at(0);
+ data.m_lowerQuartile = set->at(1);
+ data.m_median = set->at(2);
+ data.m_upperQuartile = set->at(3);
+ data.m_upperExtreme = set->at(4);
+ data.m_index = index;
+ data.m_boxItems = m_series->count();
+
+ data.m_maxX = domain()->maxX();
+ data.m_minX = domain()->minX();
+ data.m_maxY = domain()->maxY();
+ data.m_minY = domain()->minY();
+
+ data.m_seriesIndex = m_seriesIndex;
+ data.m_seriesCount = m_seriesCount;
+
+ return changed;
+}
+
+#include "moc_boxplotchartitem_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/boxplotchart/boxplotchartitem_p.h b/src/charts/boxplotchart/boxplotchartitem_p.h
new file mode 100644
index 00000000..0bba5394
--- /dev/null
+++ b/src/charts/boxplotchart/boxplotchartitem_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 BOXPLOTCHARTITEM_H
+#define BOXPLOTCHARTITEM_H
+
+#include "boxwhiskers_p.h"
+#include "qboxplotseries.h"
+#include "chartitem_p.h"
+#include "boxplotanimation_p.h"
+#include "qboxset.h"
+#include <QGraphicsItem>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class BoxPlotSeriesPrivate;
+
+class BoxPlotChartItem : public ChartItem
+{
+ Q_OBJECT
+public:
+ BoxPlotChartItem(QBoxPlotSeries *series, QGraphicsItem *item = 0);
+ ~BoxPlotChartItem();
+
+ void setAnimation(BoxPlotAnimation *animation);
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+ QRectF boundingRect() const;
+
+public Q_SLOTS:
+ void handleDataStructureChanged();
+ void handleDomainUpdated();
+ void handleLayoutChanged();
+ void handleUpdatedBars();
+ void handleBoxsetRemove(QList<QBoxSet *> barSets);
+
+private:
+ virtual QVector<QRectF> calculateLayout();
+ void initializeLayout();
+ bool updateBoxGeometry(BoxWhiskers *box, int index);
+
+protected:
+ friend class QBoxPlotSeriesPrivate;
+ QBoxPlotSeries *m_series; // Not owned.
+ QList<BoxWhiskers *> m_boxes;
+ QHash<QBoxSet *, BoxWhiskers *> m_boxTable;
+ int m_seriesIndex;
+ int m_seriesCount;
+
+ BoxPlotAnimation *m_animation;
+
+ QRectF m_boundingRect;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // BOXPLOTCHARTITEM_H
diff --git a/src/charts/boxplotchart/boxwhiskers.cpp b/src/charts/boxplotchart/boxwhiskers.cpp
new file mode 100644
index 00000000..1e78d127
--- /dev/null
+++ b/src/charts/boxplotchart/boxwhiskers.cpp
@@ -0,0 +1,194 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+ **
+ ** $QT_BEGIN_LICENSE$
+ ** 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
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include "boxwhiskers_p.h"
+#include <QPainter>
+#include <QWidget>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+BoxWhiskers::BoxWhiskers(QBoxSet *set, AbstractDomain *domain, QGraphicsObject *parent) :
+ QGraphicsObject(parent),
+ m_boxSet(set),
+ m_domain(domain)
+{
+ setAcceptHoverEvents(true);
+ setAcceptedMouseButtons(Qt::MouseButtonMask);
+}
+
+BoxWhiskers::~BoxWhiskers()
+{
+}
+
+void BoxWhiskers::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_UNUSED(event)
+ emit clicked(m_boxSet);
+}
+
+void BoxWhiskers::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
+{
+ Q_UNUSED(event)
+ emit hovered(true, m_boxSet);
+}
+
+void BoxWhiskers::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
+{
+ Q_UNUSED(event)
+ emit hovered(false, m_boxSet);
+}
+
+void BoxWhiskers::setBrush(const QBrush &brush)
+{
+ m_brush = brush;
+ m_outlinePen.setColor(m_brush.color());
+ update();
+}
+
+void BoxWhiskers::setPen(const QPen &pen)
+{
+ qreal widthDiff = pen.widthF() - m_pen.widthF();
+ m_boundingRect.adjust(-widthDiff, -widthDiff, widthDiff, widthDiff);
+
+ m_pen = pen;
+ m_medianPen = pen;
+ m_medianPen.setCapStyle(Qt::FlatCap);
+ m_outlinePen = pen;
+ m_outlinePen.setStyle(Qt::SolidLine);
+ m_outlinePen.setColor(m_brush.color());
+
+ update();
+}
+
+void BoxWhiskers::setBoxWidth(const qreal width)
+{
+ m_boxWidth = width;
+}
+
+void BoxWhiskers::setLayout(const BoxWhiskersData &data)
+{
+ m_data = data;
+
+ updateGeometry(m_domain);
+ update();
+}
+
+QSizeF BoxWhiskers::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED(which)
+ Q_UNUSED(constraint)
+
+ return QSizeF();
+}
+
+void BoxWhiskers::setGeometry(const QRectF &rect)
+{
+ Q_UNUSED(rect)
+}
+
+QRectF BoxWhiskers::boundingRect() const
+{
+ return m_boundingRect;
+}
+
+void BoxWhiskers::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option)
+ Q_UNUSED(widget)
+
+ painter->save();
+ painter->setBrush(m_brush);
+ painter->setClipRect(parentItem()->boundingRect());
+ painter->setPen(m_pen);
+ painter->drawPath(m_boxPath);
+ if (!m_boxOutlined)
+ painter->setPen(m_outlinePen);
+ painter->drawRect(m_middleBox);
+ painter->setPen(m_medianPen);
+ qreal halfLine = m_pen.widthF() / 2.0;
+ painter->drawLine(QLineF(m_geometryLeft - halfLine, m_geometryMedian,
+ m_geometryRight + halfLine, m_geometryMedian));
+ painter->restore();
+}
+
+void BoxWhiskers::updateGeometry(AbstractDomain *domain)
+{
+ m_domain = domain;
+
+ prepareGeometryChange();
+
+ QPainterPath path;
+ m_boxPath = path;
+ m_boundingRect = m_boxPath.boundingRect();
+
+ qreal columnWidth = 1.0 / m_data.m_seriesCount;
+ qreal left = ((1.0 - m_boxWidth) / 2.0) * columnWidth + columnWidth * m_data.m_seriesIndex + m_data.m_index - 0.5;
+ qreal barWidth = m_boxWidth * columnWidth;
+
+ QPointF geometryPoint = m_domain->calculateGeometryPoint(QPointF(left, m_data.m_upperExtreme), m_validData);
+ if (!m_validData)
+ return;
+ m_geometryLeft = geometryPoint.x();
+ qreal geometryUpperExtreme = geometryPoint.y();
+ geometryPoint = m_domain->calculateGeometryPoint(QPointF(left + barWidth, m_data.m_upperQuartile), m_validData);
+ if (!m_validData)
+ return;
+ m_geometryRight = geometryPoint.x();
+ qreal geometryUpperQuartile = geometryPoint.y();
+ geometryPoint = m_domain->calculateGeometryPoint(QPointF(left, m_data.m_lowerQuartile), m_validData);
+ if (!m_validData)
+ return;
+ qreal geometryLowerQuartile = geometryPoint.y();
+ geometryPoint = m_domain->calculateGeometryPoint(QPointF(left, m_data.m_lowerExtreme), m_validData);
+ if (!m_validData)
+ return;
+ qreal geometryLowerExtreme = geometryPoint.y();
+ geometryPoint = m_domain->calculateGeometryPoint(QPointF(left, m_data.m_median), m_validData);
+ if (!m_validData)
+ return;
+ m_geometryMedian = geometryPoint.y();
+
+ // Upper whisker
+ path.moveTo(m_geometryLeft, geometryUpperExtreme);
+ path.lineTo(m_geometryRight, geometryUpperExtreme);
+ path.moveTo((m_geometryLeft + m_geometryRight) / 2.0, geometryUpperExtreme);
+ path.lineTo((m_geometryLeft + m_geometryRight) / 2.0, geometryUpperQuartile);
+
+ // Middle Box
+ m_middleBox.setCoords(m_geometryLeft, geometryUpperQuartile, m_geometryRight, geometryLowerQuartile);
+
+ // Lower whisker
+ path.moveTo(m_geometryLeft, geometryLowerExtreme);
+ path.lineTo(m_geometryRight, geometryLowerExtreme);
+ path.moveTo((m_geometryLeft + m_geometryRight) / 2.0, geometryLowerQuartile);
+ path.lineTo((m_geometryLeft + m_geometryRight) / 2.0, geometryLowerExtreme);
+
+ path.closeSubpath();
+
+ m_boxPath = path;
+ m_boundingRect = m_boxPath.boundingRect();
+
+ qreal extra = m_pen.widthF();
+ m_boundingRect.adjust(-extra, -extra, extra, extra);
+}
+
+#include "moc_boxwhiskers_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/boxplotchart/boxwhiskers_p.h b/src/charts/boxplotchart/boxwhiskers_p.h
new file mode 100644
index 00000000..3dee8335
--- /dev/null
+++ b/src/charts/boxplotchart/boxwhiskers_p.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 BOXWHISKERS_H
+#define BOXWHISKERS_H
+
+#include "boxwhiskersdata_p.h"
+#include "qchartglobal.h"
+#include "abstractdomain_p.h"
+#include <QBoxSet>
+#include <QGraphicsRectItem>
+#include <QGraphicsLineItem>
+#include <QGraphicsLayoutItem>
+#include <QPainterPath>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QBarSet;
+
+class BoxWhiskers : public QGraphicsObject
+{
+ Q_OBJECT
+
+public:
+ BoxWhiskers(QBoxSet *set, AbstractDomain *domain, QGraphicsObject *parent);
+ ~BoxWhiskers();
+
+ void setBrush(const QBrush &brush);
+ void setPen(const QPen &pen);
+ void setLayout(const BoxWhiskersData &data);
+ void setBoxOutlined(const bool outlined) { m_boxOutlined = outlined; }
+ void setBoxWidth(const qreal width);
+
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
+ void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
+
+ QRectF boundingRect() const;
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ void updateGeometry(AbstractDomain *domain);
+protected:
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const;
+ void setGeometry(const QRectF &rect);
+
+Q_SIGNALS:
+ void clicked(QBoxSet *boxset);
+ void hovered(bool status, QBoxSet *boxset);
+
+private:
+ friend class BoxPlotChartItem;
+ friend class BoxPlotAnimation;
+
+ QBoxSet *m_boxSet;
+ AbstractDomain *m_domain;
+ QPainterPath m_boxPath;
+ QRectF m_boundingRect;
+ bool m_hovering;
+ bool m_validData;
+ QBrush m_brush;
+ QPen m_pen;
+ QPen m_medianPen;
+ QPen m_outlinePen;
+ bool m_boxOutlined;
+ qreal m_boxWidth;
+ BoxWhiskersData m_data;
+ QSizeF m_domainSize;
+ QRectF m_middleBox;
+ qreal m_geometryMedian;
+ qreal m_geometryLeft;
+ qreal m_geometryRight;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // BOXWHISKERS_H
diff --git a/src/charts/boxplotchart/boxwhiskersdata_p.h b/src/charts/boxplotchart/boxwhiskersdata_p.h
new file mode 100644
index 00000000..041c9039
--- /dev/null
+++ b/src/charts/boxplotchart/boxwhiskersdata_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 BOXWHISKERSDATA_P_H
+#define BOXWHISKERSDATA_P_H
+
+#include "qchartglobal.h"
+#include <QSizeF>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class BoxWhiskersData
+{
+public:
+ BoxWhiskersData() :
+ m_lowerExtreme(0.0),
+ m_lowerQuartile(0.0),
+ m_median(0.0),
+ m_upperQuartile(0.0),
+ m_upperExtreme(0.0),
+ m_index(0),
+ m_boxItems(0),
+ m_maxX(0.0),
+ m_minX(0.0),
+ m_maxY(0.0),
+ m_minY(0.0),
+ m_seriesIndex(0),
+ m_seriesCount(0)
+ {
+ }
+
+ // Box related statistics
+ qreal m_lowerExtreme;
+ qreal m_lowerQuartile;
+ qreal m_median;
+ qreal m_upperQuartile;
+ qreal m_upperExtreme;
+ int m_index;
+ int m_boxItems;
+
+ // Domain boundaries, axis
+ qreal m_maxX;
+ qreal m_minX;
+ qreal m_maxY;
+ qreal m_minY;
+
+ // Serieses related data
+ int m_seriesIndex;
+ int m_seriesCount;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // BOXWHISKERSDATA_P_H
diff --git a/src/charts/boxplotchart/qboxplotmodelmapper.cpp b/src/charts/boxplotchart/qboxplotmodelmapper.cpp
new file mode 100644
index 00000000..7f1487c8
--- /dev/null
+++ b/src/charts/boxplotchart/qboxplotmodelmapper.cpp
@@ -0,0 +1,489 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qboxplotmodelmapper.h"
+#include "qboxplotmodelmapper_p.h"
+#include "qboxplotseries.h"
+#include "qboxset.h"
+#include "qchart.h"
+#include <QAbstractItemModel>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+QBoxPlotModelMapper::QBoxPlotModelMapper(QObject *parent) :
+ QObject(parent),
+ d_ptr(new QBoxPlotModelMapperPrivate(this))
+{
+}
+
+QAbstractItemModel *QBoxPlotModelMapper::model() const
+{
+ Q_D(const QBoxPlotModelMapper);
+ return d->m_model;
+}
+
+void QBoxPlotModelMapper::setModel(QAbstractItemModel *model)
+{
+ if (model == 0)
+ return;
+
+ Q_D(QBoxPlotModelMapper);
+ if (d->m_model)
+ disconnect(d->m_model, 0, d, 0);
+
+ d->m_model = model;
+ d->initializeBoxFromModel();
+ // connect signals from the model
+ connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
+ connect(d->m_model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), d, SLOT(modelHeaderDataUpdated(Qt::Orientation,int,int)));
+ connect(d->m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelRowsAdded(QModelIndex,int,int)));
+ connect(d->m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelRowsRemoved(QModelIndex,int,int)));
+ connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelColumnsAdded(QModelIndex,int,int)));
+ connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelColumnsRemoved(QModelIndex,int,int)));
+ connect(d->m_model, SIGNAL(destroyed()), d, SLOT(handleModelDestroyed()));
+}
+
+QBoxPlotSeries *QBoxPlotModelMapper::series() const
+{
+ Q_D(const QBoxPlotModelMapper);
+ return d->m_series;
+}
+
+void QBoxPlotModelMapper::setSeries(QBoxPlotSeries *series)
+{
+ Q_D(QBoxPlotModelMapper);
+ if (d->m_series)
+ disconnect(d->m_series, 0, d, 0);
+
+ if (series == 0)
+ return;
+
+ d->m_series = series;
+ d->initializeBoxFromModel();
+ // connect the signals from the series
+ connect(d->m_series, SIGNAL(boxsetsAdded(QList<QBoxSet *>)), d, SLOT(boxSetsAdded(QList<QBoxSet *>)));
+ connect(d->m_series, SIGNAL(boxsetsRemoved(QList<QBoxSet *>)), d, SLOT(boxSetsRemoved(QList<QBoxSet *>)));
+ connect(d->m_series, SIGNAL(destroyed()), d, SLOT(handleSeriesDestroyed()));
+}
+
+/*!
+ Returns which row/column of the model contains the first values of the QBoxSets in the series.
+ The default value is 0.
+*/
+int QBoxPlotModelMapper::first() const
+{
+ Q_D(const QBoxPlotModelMapper);
+ return d->m_first;
+}
+
+/*!
+ Sets which row/column of the model contains the \a first values of the QBoxSets in the series.
+ The default value is 0.
+*/
+void QBoxPlotModelMapper::setFirst(int first)
+{
+ Q_D(QBoxPlotModelMapper);
+ d->m_first = qMax(first, 0);
+ d->initializeBoxFromModel();
+}
+
+/*!
+ Returns the number of rows/columns of the model that are mapped as the data for QBoxPlotSeries
+ Minimal and default value is: -1 (count limited by the number of rows/columns in the model)
+*/
+int QBoxPlotModelMapper::count() const
+{
+ Q_D(const QBoxPlotModelMapper);
+ return d->m_count;
+}
+
+/*!
+ Sets the \a count of rows/columns of the model that are mapped as the data for QBoxPlotSeries
+ Minimal and default value is: -1 (count limited by the number of rows/columns in the model)
+*/
+void QBoxPlotModelMapper::setCount(int count)
+{
+ Q_D(QBoxPlotModelMapper);
+ d->m_count = qMax(count, -1);
+ d->initializeBoxFromModel();
+}
+
+/*!
+ Returns the orientation that is used when QBoxPlotModelMapper accesses the model.
+ This means whether the consecutive values of the box-and-whiskers set are read from row (Qt::Horizontal)
+ or from columns (Qt::Vertical)
+*/
+Qt::Orientation QBoxPlotModelMapper::orientation() const
+{
+ Q_D(const QBoxPlotModelMapper);
+ return d->m_orientation;
+}
+
+/*!
+ Returns the \a orientation that is used when QBoxPlotModelMapper accesses the model.
+ This mean whether the consecutive values of the box-and-whiskers set are read from row (Qt::Horizontal)
+ or from columns (Qt::Vertical)
+*/
+void QBoxPlotModelMapper::setOrientation(Qt::Orientation orientation)
+{
+ Q_D(QBoxPlotModelMapper);
+ d->m_orientation = orientation;
+ d->initializeBoxFromModel();
+}
+
+/*!
+ Returns which section of the model is used as the data source for the first box set
+*/
+int QBoxPlotModelMapper::firstBoxSetSection() const
+{
+ Q_D(const QBoxPlotModelMapper);
+ return d->m_firstBoxSetSection;
+}
+
+/*!
+ Sets the model section that is used as the data source for the first box set
+ Parameter \a firstBoxSetSection specifies the section of the model.
+*/
+void QBoxPlotModelMapper::setFirstBoxSetSection(int firstBoxSetSection)
+{
+ Q_D(QBoxPlotModelMapper);
+ d->m_firstBoxSetSection = qMax(-1, firstBoxSetSection);
+ d->initializeBoxFromModel();
+}
+
+/*!
+ Returns which section of the model is used as the data source for the last box set
+*/
+int QBoxPlotModelMapper::lastBoxSetSection() const
+{
+ Q_D(const QBoxPlotModelMapper);
+ return d->m_lastBoxSetSection;
+}
+
+/*!
+ Sets the model section that is used as the data source for the last box set
+ Parameter \a lastBoxSetSection specifies the section of the model.
+*/
+void QBoxPlotModelMapper::setLastBoxSetSection(int lastBoxSetSection)
+{
+ Q_D(QBoxPlotModelMapper);
+ d->m_lastBoxSetSection = qMax(-1, lastBoxSetSection);
+ d->initializeBoxFromModel();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QBoxPlotModelMapperPrivate::QBoxPlotModelMapperPrivate(QBoxPlotModelMapper *q) :
+ QObject(q),
+ m_series(0),
+ m_model(0),
+ m_first(0),
+ m_count(-1),
+ m_orientation(Qt::Vertical),
+ m_firstBoxSetSection(-1),
+ m_lastBoxSetSection(-1),
+ m_seriesSignalsBlock(false),
+ m_modelSignalsBlock(false),
+ q_ptr(q)
+{
+}
+
+void QBoxPlotModelMapperPrivate::blockModelSignals(bool block)
+{
+ m_modelSignalsBlock = block;
+}
+
+void QBoxPlotModelMapperPrivate::blockSeriesSignals(bool block)
+{
+ m_seriesSignalsBlock = block;
+}
+
+QBoxSet *QBoxPlotModelMapperPrivate::boxSet(QModelIndex index)
+{
+ if (!index.isValid())
+ return 0;
+
+ if (m_orientation == Qt::Vertical && index.column() >= m_firstBoxSetSection && index.column() <= m_lastBoxSetSection) {
+ if (index.row() >= m_first && (m_count == - 1 || index.row() < m_first + m_count))
+ return m_series->boxSets().at(index.column() - m_firstBoxSetSection);
+ } else if (m_orientation == Qt::Horizontal && index.row() >= m_firstBoxSetSection && index.row() <= m_lastBoxSetSection) {
+ if (index.column() >= m_first && (m_count == - 1 || index.column() < m_first + m_count))
+ return m_series->boxSets().at(index.row() - m_firstBoxSetSection);
+ }
+ return 0; // This part of model has not been mapped to any boxset
+}
+
+QModelIndex QBoxPlotModelMapperPrivate::boxModelIndex(int boxSection, int posInBar)
+{
+ if (m_count != -1 && posInBar >= m_count)
+ return QModelIndex(); // invalid
+
+ if (boxSection < m_firstBoxSetSection || boxSection > m_lastBoxSetSection)
+ return QModelIndex(); // invalid
+
+ if (m_orientation == Qt::Vertical)
+ return m_model->index(posInBar + m_first, boxSection);
+ else
+ return m_model->index(boxSection, posInBar + m_first);
+}
+
+void QBoxPlotModelMapperPrivate::handleSeriesDestroyed()
+{
+ m_series = 0;
+}
+
+void QBoxPlotModelMapperPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
+{
+ Q_UNUSED(topLeft)
+ Q_UNUSED(bottomRight)
+
+ if (m_model == 0 || m_series == 0)
+ return;
+
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ QModelIndex index;
+ for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
+ for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
+ index = topLeft.sibling(row, column);
+ QBoxSet *box = boxSet(index);
+ if (box) {
+ if (m_orientation == Qt::Vertical)
+ box->setValue(row - m_first, m_model->data(index).toReal());
+ else
+ box->setValue(column - m_first, m_model->data(index).toReal());
+ }
+ }
+ }
+ blockSeriesSignals(false);
+}
+
+void QBoxPlotModelMapperPrivate::modelHeaderDataUpdated(Qt::Orientation orientation, int first, int last)
+{
+ Q_UNUSED(orientation);
+ Q_UNUSED(first);
+ Q_UNUSED(last);
+}
+
+void QBoxPlotModelMapperPrivate::modelRowsAdded(QModelIndex parent, int start, int end)
+{
+ Q_UNUSED(parent)
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ if (m_orientation == Qt::Vertical)
+ insertData(start, end);
+ else if (start <= m_firstBoxSetSection || start <= m_lastBoxSetSection) // if the changes affect the map - reinitialize
+ initializeBoxFromModel();
+ blockSeriesSignals(false);
+}
+
+void QBoxPlotModelMapperPrivate::modelRowsRemoved(QModelIndex parent, int start, int end)
+{
+ Q_UNUSED(parent)
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ if (m_orientation == Qt::Vertical)
+ removeData(start, end);
+ else if (start <= m_firstBoxSetSection || start <= m_lastBoxSetSection) // if the changes affect the map - reinitialize
+ initializeBoxFromModel();
+ blockSeriesSignals(false);
+}
+
+void QBoxPlotModelMapperPrivate::modelColumnsAdded(QModelIndex parent, int start, int end)
+{
+ Q_UNUSED(parent)
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ if (m_orientation == Qt::Horizontal)
+ insertData(start, end);
+ else if (start <= m_firstBoxSetSection || start <= m_lastBoxSetSection) // if the changes affect the map - reinitialize
+ initializeBoxFromModel();
+ blockSeriesSignals(false);
+}
+
+void QBoxPlotModelMapperPrivate::modelColumnsRemoved(QModelIndex parent, int start, int end)
+{
+ Q_UNUSED(parent)
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ if (m_orientation == Qt::Horizontal)
+ removeData(start, end);
+ else if (start <= m_firstBoxSetSection || start <= m_lastBoxSetSection) // if the changes affect the map - reinitialize
+ initializeBoxFromModel();
+ blockSeriesSignals(false);
+}
+
+void QBoxPlotModelMapperPrivate::handleModelDestroyed()
+{
+ m_model = 0;
+}
+
+void QBoxPlotModelMapperPrivate::insertData(int start, int end)
+{
+ Q_UNUSED(end)
+ Q_UNUSED(start)
+ Q_UNUSED(end)
+ // Currently boxplotchart needs to be fully recalculated when change is made.
+ // Re-initialize
+ initializeBoxFromModel();
+}
+
+void QBoxPlotModelMapperPrivate::removeData(int start, int end)
+{
+ Q_UNUSED(end)
+ Q_UNUSED(start)
+ Q_UNUSED(end)
+ // Currently boxplotchart needs to be fully recalculated when change is made.
+ // Re-initialize
+ initializeBoxFromModel();
+}
+
+void QBoxPlotModelMapperPrivate::boxSetsAdded(QList<QBoxSet *> sets)
+{
+ if (m_seriesSignalsBlock)
+ return;
+
+ if (sets.count() == 0)
+ return;
+
+ int firstIndex = m_series->boxSets().indexOf(sets.at(0));
+ if (firstIndex == -1)
+ return;
+
+ int maxCount = 0;
+ for (int i = 0; i < sets.count(); i++) {
+ if (sets.at(i)->count() > m_count)
+ maxCount = sets.at(i)->count();
+ }
+
+ if (m_count != -1 && m_count < maxCount)
+ m_count = maxCount;
+
+ m_lastBoxSetSection += sets.count();
+
+ blockModelSignals();
+ int modelCapacity = m_orientation == Qt::Vertical ? m_model->rowCount() - m_first : m_model->columnCount() - m_first;
+ if (maxCount > modelCapacity) {
+ if (m_orientation == Qt::Vertical)
+ m_model->insertRows(m_model->rowCount(), maxCount - modelCapacity);
+ else
+ m_model->insertColumns(m_model->columnCount(), maxCount - modelCapacity);
+ }
+
+ if (m_orientation == Qt::Vertical)
+ m_model->insertColumns(firstIndex + m_firstBoxSetSection, sets.count());
+ else
+ m_model->insertRows(firstIndex + m_firstBoxSetSection, sets.count());
+
+
+ for (int i = firstIndex + m_firstBoxSetSection; i < firstIndex + m_firstBoxSetSection + sets.count(); i++) {
+ for (int j = 0; j < sets.at(i - firstIndex - m_firstBoxSetSection)->count(); j++)
+ m_model->setData(boxModelIndex(i, j), sets.at(i - firstIndex - m_firstBoxSetSection)->at(j));
+ }
+ blockModelSignals(false);
+ initializeBoxFromModel();
+}
+
+void QBoxPlotModelMapperPrivate::boxSetsRemoved(QList<QBoxSet *> sets)
+{
+ if (m_seriesSignalsBlock)
+ return;
+
+ if (sets.count() == 0)
+ return;
+
+ int firstIndex = m_boxSets.indexOf(sets.at(0));
+ if (firstIndex == -1)
+ return;
+
+ m_lastBoxSetSection -= sets.count();
+
+ for (int i = firstIndex + sets.count() - 1; i >= firstIndex; i--)
+ m_boxSets.removeAt(i);
+
+ blockModelSignals();
+ if (m_orientation == Qt::Vertical)
+ m_model->removeColumns(firstIndex + m_firstBoxSetSection, sets.count());
+ else
+ m_model->removeRows(firstIndex + m_firstBoxSetSection, sets.count());
+ blockModelSignals(false);
+ initializeBoxFromModel();
+}
+
+void QBoxPlotModelMapperPrivate::boxValueChanged(int index)
+{
+ if (m_seriesSignalsBlock)
+ return;
+
+ int boxSetIndex = m_boxSets.indexOf(qobject_cast<QBoxSet *>(QObject::sender()));
+
+ blockModelSignals();
+ m_model->setData(boxModelIndex(boxSetIndex + m_firstBoxSetSection, index), m_boxSets.at(boxSetIndex)->at(index));
+ blockModelSignals(false);
+ initializeBoxFromModel();
+}
+
+void QBoxPlotModelMapperPrivate::initializeBoxFromModel()
+{
+ if (m_model == 0 || m_series == 0)
+ return;
+
+ blockSeriesSignals();
+ // clear current content
+ m_series->clear();
+ m_boxSets.clear();
+
+ // create the initial box-and-whiskers sets
+ for (int i = m_firstBoxSetSection; i <= m_lastBoxSetSection; i++) {
+ int posInBar = 0;
+ QModelIndex boxIndex = boxModelIndex(i, posInBar);
+ // check if there is such model index
+ if (boxIndex.isValid()) {
+ QBoxSet *boxSet = new QBoxSet();
+ while (boxIndex.isValid()) {
+ boxSet->append(m_model->data(boxIndex, Qt::DisplayRole).toDouble());
+ posInBar++;
+ boxIndex = boxModelIndex(i, posInBar);
+ }
+ connect(boxSet, SIGNAL(valueChanged(int)), this, SLOT(boxValueChanged(int)));
+ m_series->append(boxSet);
+ m_boxSets.append(boxSet);
+ } else {
+ break;
+ }
+ }
+ blockSeriesSignals(false);
+}
+
+#include "moc_qboxplotmodelmapper.cpp"
+#include "moc_qboxplotmodelmapper_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
+
diff --git a/src/charts/boxplotchart/qboxplotmodelmapper.h b/src/charts/boxplotchart/qboxplotmodelmapper.h
new file mode 100644
index 00000000..a114be99
--- /dev/null
+++ b/src/charts/boxplotchart/qboxplotmodelmapper.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBOXPLOTMODELMAPPER_H
+#define QBOXPLOTMODELMAPPER_H
+
+#include <QtCharts/qchartglobal.h>
+#include <QObject>
+
+class QAbstractItemModel;
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QBoxPlotModelMapperPrivate;
+class QBoxPlotSeries;
+
+class QT_CHARTS_EXPORT QBoxPlotModelMapper : public QObject
+{
+ Q_OBJECT
+
+protected:
+ explicit QBoxPlotModelMapper(QObject *parent = 0);
+
+ QAbstractItemModel *model() const;
+ void setModel(QAbstractItemModel *model);
+
+ QBoxPlotSeries *series() const;
+ void setSeries(QBoxPlotSeries *series);
+
+ int first() const;
+ void setFirst(int first);
+
+ int count() const;
+ void setCount(int count);
+
+ int firstBoxSetSection() const;
+ void setFirstBoxSetSection(int firstBoxSetSection);
+
+ int lastBoxSetSection() const;
+ void setLastBoxSetSection(int lastBoxSetSection);
+
+ Qt::Orientation orientation() const;
+ void setOrientation(Qt::Orientation orientation);
+
+protected:
+ QBoxPlotModelMapperPrivate * const d_ptr;
+ Q_DECLARE_PRIVATE(QBoxPlotModelMapper)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QBOXPLOTMODELMAPPER_H
diff --git a/src/charts/boxplotchart/qboxplotmodelmapper_p.h b/src/charts/boxplotchart/qboxplotmodelmapper_p.h
new file mode 100644
index 00000000..9e474d9e
--- /dev/null
+++ b/src/charts/boxplotchart/qboxplotmodelmapper_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QBOXPLOTMODELMAPPER_P_H
+#define QBOXPLOTMODELMAPPER_P_H
+
+#include <QObject>
+#include <qboxplotmodelmapper.h>
+
+class QModelIndex;
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QBoxSet;
+
+class QBoxPlotModelMapperPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QBoxPlotModelMapperPrivate(QBoxPlotModelMapper *q);
+
+public Q_SLOTS:
+ // for the model
+ void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight);
+ void modelHeaderDataUpdated(Qt::Orientation orientation, int first, int last);
+ void modelRowsAdded(QModelIndex parent, int start, int end);
+ void modelRowsRemoved(QModelIndex parent, int start, int end);
+ void modelColumnsAdded(QModelIndex parent, int start, int end);
+ void modelColumnsRemoved(QModelIndex parent, int start, int end);
+ void handleModelDestroyed();
+
+ // for the series
+ void boxSetsAdded(QList<QBoxSet *> sets);
+ void boxSetsRemoved(QList<QBoxSet *> sets);
+ void boxValueChanged(int index);
+ void handleSeriesDestroyed();
+
+ void initializeBoxFromModel();
+
+private:
+ QBoxSet *boxSet(QModelIndex index);
+ QModelIndex boxModelIndex(int boxSection, int posInBox);
+ void insertData(int start, int end);
+ void removeData(int start, int end);
+ void blockModelSignals(bool block = true);
+ void blockSeriesSignals(bool block = true);
+
+private:
+ QBoxPlotSeries *m_series;
+ QList<QBoxSet *> m_boxSets;
+ QAbstractItemModel *m_model;
+ int m_first;
+ int m_count;
+ Qt::Orientation m_orientation;
+ int m_firstBoxSetSection;
+ int m_lastBoxSetSection;
+ bool m_seriesSignalsBlock;
+ bool m_modelSignalsBlock;
+
+private:
+ QBoxPlotModelMapper *q_ptr;
+ Q_DECLARE_PUBLIC(QBoxPlotModelMapper)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QBOXPLOTMODELMAPPER_P_H
diff --git a/src/charts/boxplotchart/qboxplotseries.cpp b/src/charts/boxplotchart/qboxplotseries.cpp
new file mode 100644
index 00000000..2f444b40
--- /dev/null
+++ b/src/charts/boxplotchart/qboxplotseries.cpp
@@ -0,0 +1,690 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qboxplotseries.h"
+#include "qboxplotseries_p.h"
+#include "qboxplotlegendmarker.h"
+#include "qbarcategoryaxis.h"
+#include "boxplotchartitem_p.h"
+#include "chartdataset_p.h"
+#include "charttheme_p.h"
+#include "qvalueaxis.h"
+#include "charttheme_p.h"
+#include "boxplotanimation_p.h"
+#include "qchart_p.h"
+#include "qboxset.h"
+#include "qboxset_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QBoxPlotSeries
+ \inmodule Qt Charts
+ \brief Series for creating box-and-whiskers chart.
+ \mainclass
+
+ QBoxPlotSeries represents a series of data shown as box-and-whisker bars. The purpose of this class is to act as
+ a container for single box-and-whisker items. Each item is drawn to own slot. If chart includes multiple instances of
+ QBoxPlotSeries then box-and-whiskers items with the same index are drawn to same slot.
+
+ See the \l {Box and Whiskers Example} {box-and-whiskers chart example} to learn how to create a box-and-whiskers chart.
+ \image examples_boxplotchart.png
+
+ \sa QBoxSet
+*/
+/*!
+ \fn QBoxPlotSeries::boxsetsAdded(QList<QBoxSet *> sets)
+ \brief Signal is emitted when a new \a sets of box-and-whiskers data is added to the series.
+*/
+/*!
+ \fn QBoxPlotSeries::boxsetsRemoved(QList<QBoxSet *> sets)
+ \brief Signal is emitted when \a sets of box-and-whiskers data is removed from the series.
+*/
+/*!
+ \fn QBoxPlotSeries::clicked(QBoxSet *boxset)
+ \brief Signal is emitted when the user clicks the \a boxset on the chart.
+*/
+/*!
+ \fn QBoxPlotSeries::hovered(bool status, QBoxSet *boxset)
+ \brief Signal is emitted when there is change in hover \a status over \a boxset.
+*/
+/*!
+ \fn QBoxPlotSeries::countChanged()
+ \brief Signal is emitted when there is change in count of box-and-whiskers items in the series.
+*/
+/*!
+ \property QBoxPlotSeries::boxOutlineVisible
+ \brief This property configures the visibility of the middle box outline.
+*/
+/*!
+ \property QBoxPlotSeries::boxWidth
+ \brief This property configures the width of the box-and-whiskers item. The value signifies the relative
+ width of the box-and-whiskers item inside its own slot. The value can between 0.0 and 1.0. Negative values
+ are clamped to 0.0 and values over 1.0 are clamped to 1.0.
+*/
+/*!
+ \property QBoxPlotSeries::pen
+ \brief This property configures the pen of the box-and-whiskers items.
+*/
+/*!
+ \property QBoxPlotSeries::brush
+ \brief This property configures the brush of the box-and-whiskers items.
+*/
+/*!
+ \property QBoxPlotSeries::count
+ \brief The count of sets in series.
+*/
+
+/*!
+ \qmlproperty QString BoxPlotSeries::brushFilename
+ The name of the file used as a brush for the series.
+*/
+
+/*!
+ \fn void QBoxPlotSeries::boxOutlineVisibilityChanged()
+ Signal is emitted when the middle box outline visibility is changed.
+*/
+/*!
+ \fn void QBoxPlotSeries::boxWidthChanged()
+ Signal is emitted when the width of the box-and-whiskers item is changed.
+*/
+/*!
+ \fn void QBoxPlotSeries::penChanged()
+ This signal is emitted when the pen of the box-and-whiskers has changed.
+ \sa brush
+*/
+/*!
+ \fn void QBoxPlotSeries::brushChanged()
+ This signal is emitted when the brush of the box-and-whiskers has changed.
+ \sa brush
+*/
+/*!
+ \fn virtual SeriesType QBoxPlotSeries::type() const
+ \brief Returns type of series.
+ \sa QAbstractSeries, SeriesType
+*/
+
+/*!
+ Constructs empty QBoxPlotSeries.
+ QBoxPlotSeries is QObject which is a child of a \a parent.
+*/
+QBoxPlotSeries::QBoxPlotSeries(QObject *parent)
+ : QAbstractSeries(*new QBoxPlotSeriesPrivate(this), parent)
+{
+}
+
+/*!
+ Destructor. Removes series from chart.
+*/
+QBoxPlotSeries::~QBoxPlotSeries()
+{
+ Q_D(QBoxPlotSeries);
+ if (d->m_chart)
+ d->m_chart->removeSeries(this);
+}
+
+/*!
+ Adds a single box and whiskers set to series. Takes ownership of the \a set. If the set is null or is already in series, it won't be appended.
+ Returns true, if appending succeeded.
+*/
+bool QBoxPlotSeries::append(QBoxSet *set)
+{
+ Q_D(QBoxPlotSeries);
+
+ bool success = d->append(set);
+ if (success) {
+ QList<QBoxSet *> sets;
+ sets.append(set);
+ set->setParent(this);
+ emit boxsetsAdded(sets);
+ emit countChanged();
+ }
+ return success;
+}
+
+/*!
+ Removes boxset from the series. Deletes the \a set and returns true if successful.
+*/
+bool QBoxPlotSeries::remove(QBoxSet *set)
+{
+ Q_D(QBoxPlotSeries);
+ bool success = d->remove(set);
+ if (success) {
+ QList<QBoxSet *> sets;
+ sets.append(set);
+ set->setParent(0);
+ emit boxsetsRemoved(sets);
+ emit countChanged();
+ delete set;
+ set = 0;
+ }
+ return success;
+}
+
+/*!
+ Takes a single \a set from the series. Does not delete the boxset object.
+
+ NOTE: The series remains as the boxset's parent object. You must set the
+ parent object to take full ownership.
+
+ Returns true if take was successful.
+*/
+bool QBoxPlotSeries::take(QBoxSet *set)
+{
+ Q_D(QBoxPlotSeries);
+
+ bool success = d->remove(set);
+ if (success) {
+ QList<QBoxSet *> sets;
+ sets.append(set);
+ emit boxsetsRemoved(sets);
+ emit countChanged();
+ }
+ return success;
+}
+
+/*!
+ Adds a list of boxsets to series. Takes ownership of the \a sets.
+ Returns true, if all sets were appended successfully. If any of the sets is null or is already appended to series,
+ nothing is appended and function returns false. If any of the sets is in list more than once, nothing is appended
+ and function returns false.
+*/
+bool QBoxPlotSeries::append(QList<QBoxSet *> sets)
+{
+ Q_D(QBoxPlotSeries);
+ bool success = d->append(sets);
+ if (success) {
+ emit boxsetsAdded(sets);
+ emit countChanged();
+ }
+ return success;
+}
+
+/*!
+ Insert a box-and-whiskers set to the series at \a index postion. Takes ownership of the \a set. If the set is null or
+ is already in series, it won't be appended. Returns true, if inserting succeeded.
+
+*/
+bool QBoxPlotSeries::insert(int index, QBoxSet *set)
+{
+ Q_D(QBoxPlotSeries);
+ bool success = d->insert(index, set);
+ if (success) {
+ QList<QBoxSet *> sets;
+ sets.append(set);
+ emit boxsetsAdded(sets);
+ emit countChanged();
+ }
+ return success;
+}
+
+/*!
+ Removes all boxsets from the series. Deletes removed sets.
+*/
+void QBoxPlotSeries::clear()
+{
+ Q_D(QBoxPlotSeries);
+ QList<QBoxSet *> sets = boxSets();
+ bool success = d->remove(sets);
+ if (success) {
+ emit boxsetsRemoved(sets);
+ emit countChanged();
+ foreach (QBoxSet *set, sets)
+ delete set;
+ }
+}
+
+/*!
+ Returns number of sets in series.
+*/
+int QBoxPlotSeries::count() const
+{
+ Q_D(const QBoxPlotSeries);
+ return d->m_boxSets.count();
+}
+
+/*!
+ Returns a list of sets in series. Keeps ownership of sets.
+ */
+QList<QBoxSet *> QBoxPlotSeries::boxSets() const
+{
+ Q_D(const QBoxPlotSeries);
+ return d->m_boxSets;
+}
+
+/*
+ Returns QAbstractSeries::SeriesTypeBoxPlot.
+*/
+QAbstractSeries::SeriesType QBoxPlotSeries::type() const
+{
+ return QAbstractSeries::SeriesTypeBoxPlot;
+}
+
+void QBoxPlotSeries::setBoxOutlineVisible(bool visible)
+{
+ Q_D(QBoxPlotSeries);
+
+ if (d->m_boxOutlineVisible != visible) {
+ d->m_boxOutlineVisible = visible;
+ emit d->updated();
+ emit boxOutlineVisibilityChanged();
+ }
+}
+
+bool QBoxPlotSeries::boxOutlineVisible()
+{
+ Q_D(QBoxPlotSeries);
+
+ return d->m_boxOutlineVisible;
+}
+
+void QBoxPlotSeries::setBoxWidth(qreal width)
+{
+ Q_D(QBoxPlotSeries);
+
+ if (width != d->m_boxWidth) {
+ if (width < 0.0)
+ width = 0.0;
+ if (width > 1.0)
+ width = 1.0;
+ d->m_boxWidth = width;
+ emit d->updatedLayout();
+ emit boxWidthChanged();
+ }
+}
+
+qreal QBoxPlotSeries::boxWidth()
+{
+ Q_D(QBoxPlotSeries);
+
+ return d->m_boxWidth;
+}
+
+void QBoxPlotSeries::setBrush(const QBrush &brush)
+{
+ Q_D(QBoxPlotSeries);
+
+ if (d->m_brush != brush) {
+ d->m_brush = brush;
+ emit d->updated();
+ emit brushChanged();
+ }
+}
+
+QBrush QBoxPlotSeries::brush() const
+{
+ Q_D(const QBoxPlotSeries);
+
+ return d->m_brush;
+}
+
+void QBoxPlotSeries::setPen(const QPen &pen)
+{
+ Q_D(QBoxPlotSeries);
+
+ if (d->m_pen != pen) {
+ d->m_pen = pen;
+ emit d->updated();
+ emit penChanged();
+ }
+}
+
+QPen QBoxPlotSeries::pen() const
+{
+ Q_D(const QBoxPlotSeries);
+
+ return d->m_pen;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QBoxPlotSeriesPrivate::QBoxPlotSeriesPrivate(QBoxPlotSeries *q)
+ : QAbstractSeriesPrivate(q),
+ m_pen(QChartPrivate::defaultPen()),
+ m_brush(QChartPrivate::defaultBrush()),
+ m_boxOutlineVisible(true),
+ m_boxWidth(0.5)
+{
+}
+
+QBoxPlotSeriesPrivate::~QBoxPlotSeriesPrivate()
+{
+ disconnect(this, 0, 0, 0);
+}
+
+void QBoxPlotSeriesPrivate::initializeDomain()
+{
+ qreal minX(domain()->minX());
+ qreal minY(domain()->minY());
+ qreal maxX(domain()->maxX());
+ qreal maxY(domain()->maxY());
+
+ qreal x = m_boxSets.count();
+ minX = qMin(minX, qreal(-0.5));
+ minY = qMin(minY, min());
+ maxX = qMax(maxX, x - qreal(0.5));
+ maxY = qMax(maxY, max());
+
+ domain()->setRange(minX, maxX, minY, maxY);
+}
+
+void QBoxPlotSeriesPrivate::initializeAxes()
+{
+ foreach (QAbstractAxis* axis, m_axes) {
+ if (axis->type() == QAbstractAxis::AxisTypeBarCategory) {
+ if (axis->orientation() == Qt::Horizontal)
+ populateCategories(qobject_cast<QBarCategoryAxis *>(axis));
+ }
+ }
+}
+
+QAbstractAxis::AxisType QBoxPlotSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
+{
+ if (orientation == Qt::Horizontal)
+ return QAbstractAxis::AxisTypeBarCategory;
+
+ return QAbstractAxis::AxisTypeValue;
+}
+
+QAbstractAxis* QBoxPlotSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const
+{
+ if (defaultAxisType(orientation) == QAbstractAxis::AxisTypeBarCategory)
+ return new QBarCategoryAxis;
+ else
+ return new QValueAxis;
+}
+
+void QBoxPlotSeriesPrivate::populateCategories(QBarCategoryAxis *axis)
+{
+ QStringList categories;
+ if (axis->categories().isEmpty()) {
+ for (int i(1); i < m_boxSets.count() + 1; i++) {
+ QBoxSet *set = m_boxSets.at(i - 1);
+ if (set->label().isEmpty())
+ categories << presenter()->numberToString(i);
+ else
+ categories << set->label();
+ }
+ axis->append(categories);
+ }
+}
+
+void QBoxPlotSeriesPrivate::initializeGraphics(QGraphicsItem *parent)
+{
+ Q_Q(QBoxPlotSeries);
+
+ BoxPlotChartItem *boxPlot = new BoxPlotChartItem(q, parent);
+ m_item.reset(boxPlot);
+ QAbstractSeriesPrivate::initializeGraphics(parent);
+
+ if (m_chart) {
+ connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), this, SLOT(handleSeriesChange(QAbstractSeries*)) );
+ connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)), this, SLOT(handleSeriesRemove(QAbstractSeries*)) );
+
+ QList<QAbstractSeries *> serieses = m_chart->series();
+
+ // Tries to find this series from the Chart's list of series and deduce the index
+ int index = 0;
+ foreach (QAbstractSeries *s, serieses) {
+ if (s->type() == QAbstractSeries::SeriesTypeBoxPlot) {
+ if (q == static_cast<QBoxPlotSeries *>(s)) {
+ boxPlot->m_seriesIndex = index;
+ m_index = index;
+ }
+ index++;
+ }
+ }
+ boxPlot->m_seriesCount = index;
+ }
+
+ // Make BoxPlotChartItem to instantiate box & whisker items
+ boxPlot->handleDataStructureChanged();
+}
+
+void QBoxPlotSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
+{
+ Q_Q(QBoxPlotSeries);
+
+ const QList<QGradient> gradients = theme->seriesGradients();
+
+ if (forced || QChartPrivate::defaultBrush() == m_brush) {
+ QColor brushColor = ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0.5);
+ q->setBrush(brushColor);
+ }
+
+ if (forced || QChartPrivate::defaultPen() == m_pen) {
+ QPen pen = theme->outlinePen();
+ pen.setCosmetic(true);
+ q->setPen(pen);
+ }
+}
+
+void QBoxPlotSeriesPrivate::initializeAnimations(QChart::AnimationOptions options)
+{
+ BoxPlotChartItem *item = static_cast<BoxPlotChartItem *>(m_item.data());
+ Q_ASSERT(item);
+ if (item->animation())
+ item->animation()->stopAndDestroyLater();
+
+ if (options.testFlag(QChart::SeriesAnimations))
+ m_animation = new BoxPlotAnimation(item);
+ else
+ m_animation = 0;
+ item->setAnimation(m_animation);
+
+ QAbstractSeriesPrivate::initializeAnimations(options);
+}
+
+QList<QLegendMarker*> QBoxPlotSeriesPrivate::createLegendMarkers(QLegend *legend)
+{
+ Q_Q(QBoxPlotSeries);
+ QList<QLegendMarker *> list;
+ return list << new QBoxPlotLegendMarker(q, legend);
+}
+
+void QBoxPlotSeriesPrivate::handleSeriesRemove(QAbstractSeries *series)
+{
+ Q_Q(QBoxPlotSeries);
+
+ QBoxPlotSeries *removedSeries = static_cast<QBoxPlotSeries *>(series);
+
+ if (q == removedSeries && m_animation) {
+ m_animation->stopAll();
+ QObject::disconnect(m_chart->d_ptr->m_dataset, 0, removedSeries->d_func(), 0);
+ }
+
+ // Test if series removed is me, then don't do anything
+ if (q != removedSeries) {
+ BoxPlotChartItem *item = static_cast<BoxPlotChartItem *>(m_item.data());
+ if (item) {
+ item->m_seriesCount = item->m_seriesCount - 1;
+ if (removedSeries->d_func()->m_index < m_index) {
+ m_index--;
+ item->m_seriesIndex = m_index;
+ }
+
+ item->handleDataStructureChanged();
+ }
+ }
+}
+
+void QBoxPlotSeriesPrivate::handleSeriesChange(QAbstractSeries *series)
+{
+ Q_UNUSED(series);
+
+ Q_Q(QBoxPlotSeries);
+
+ BoxPlotChartItem *boxPlot = static_cast<BoxPlotChartItem *>(m_item.data());
+
+ if (m_chart) {
+ QList<QAbstractSeries *> serieses = m_chart->series();
+
+ // Tries to find this series from the Chart's list of series and deduce the index
+ int index = 0;
+ foreach (QAbstractSeries *s, serieses) {
+ if (s->type() == QAbstractSeries::SeriesTypeBoxPlot) {
+ if (q == static_cast<QBoxPlotSeries *>(s)) {
+ boxPlot->m_seriesIndex = index;
+ m_index = index;
+ }
+ index++;
+ }
+ }
+ boxPlot->m_seriesCount = index;
+ }
+
+ boxPlot->handleDataStructureChanged();
+}
+
+bool QBoxPlotSeriesPrivate::append(QBoxSet *set)
+{
+ if (m_boxSets.contains(set) || (set == 0) || set->d_ptr->m_series)
+ return false; // Fail if set is already in list or set is null.
+
+ m_boxSets.append(set);
+ QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
+ QObject::connect(set->d_ptr.data(), SIGNAL(updatedBox()), this, SIGNAL(updatedBoxes()));
+ QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBox()), this, SIGNAL(restructuredBoxes()));
+ set->d_ptr->m_series = this;
+
+ emit restructuredBoxes(); // this notifies boxplotchartitem
+ return true;
+}
+
+bool QBoxPlotSeriesPrivate::remove(QBoxSet *set)
+{
+ if (!m_boxSets.contains(set))
+ return false; // Fail if set is not in list
+
+ set->d_ptr->m_series = 0;
+ m_boxSets.removeOne(set);
+ QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
+ QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedBox()), this, SIGNAL(updatedBoxes()));
+ QObject::disconnect(set->d_ptr.data(), SIGNAL(restructuredBox()), this, SIGNAL(restructuredBoxes()));
+
+ emit restructuredBoxes(); // this notifies boxplotchartitem
+ return true;
+}
+
+bool QBoxPlotSeriesPrivate::append(QList<QBoxSet *> sets)
+{
+ foreach (QBoxSet *set, sets) {
+ if ((set == 0) || m_boxSets.contains(set) || set->d_ptr->m_series)
+ return false; // Fail if any of the sets is null or is already appended.
+ if (sets.count(set) != 1)
+ return false; // Also fail if same set is more than once in given list.
+ }
+
+ foreach (QBoxSet *set, sets) {
+ m_boxSets.append(set);
+ QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
+ QObject::connect(set->d_ptr.data(), SIGNAL(updatedBox()), this, SIGNAL(updatedBoxes()));
+ QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBox()), this, SIGNAL(restructuredBoxes()));
+ set->d_ptr->m_series = this;
+ }
+
+ emit restructuredBoxes(); // this notifies boxplotchartitem
+ return true;
+}
+
+bool QBoxPlotSeriesPrivate::remove(QList<QBoxSet *> sets)
+{
+ if (sets.count() == 0)
+ return false;
+
+ foreach (QBoxSet *set, sets) {
+ if ((set == 0) || (!m_boxSets.contains(set)))
+ return false; // Fail if any of the sets is null or is not in series
+ if (sets.count(set) != 1)
+ return false; // Also fail if same set is more than once in given list.
+ }
+
+ foreach (QBoxSet *set, sets) {
+ set->d_ptr->m_series = 0;
+ m_boxSets.removeOne(set);
+ QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
+ QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedBox()), this, SIGNAL(updatedBoxes()));
+ QObject::disconnect(set->d_ptr.data(), SIGNAL(restructuredBox()), this, SIGNAL(restructuredBoxes()));
+ }
+
+ emit restructuredBoxes(); // this notifies boxplotchartitem
+
+ return true;
+}
+
+bool QBoxPlotSeriesPrivate::insert(int index, QBoxSet *set)
+{
+ if ((m_boxSets.contains(set)) || (set == 0) || set->d_ptr->m_series)
+ return false; // Fail if set is already in list or set is null.
+
+ m_boxSets.insert(index, set);
+ set->d_ptr->m_series = this;
+ QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
+ QObject::connect(set->d_ptr.data(), SIGNAL(updatedBox()), this, SIGNAL(updatedBoxes()));
+ QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBox()), this, SIGNAL(restructuredBoxes()));
+
+ emit restructuredBoxes(); // this notifies boxplotchartitem
+ return true;
+}
+
+QBoxSet *QBoxPlotSeriesPrivate::boxSetAt(int index)
+{
+ return m_boxSets.at(index);
+}
+
+qreal QBoxPlotSeriesPrivate::min()
+{
+ if (m_boxSets.count() <= 0)
+ return 0;
+
+ qreal min = m_boxSets.at(0)->at(0);
+
+ foreach (QBoxSet *set, m_boxSets) {
+ for (int i = 0; i < 5; i++) {
+ if (set->at(i) < min)
+ min = set->at(i);
+ }
+ }
+
+ return min;
+}
+
+qreal QBoxPlotSeriesPrivate::max()
+{
+ if (m_boxSets.count() <= 0)
+ return 0;
+
+ qreal max = m_boxSets.at(0)->at(0);
+
+ foreach (QBoxSet *set, m_boxSets) {
+ for (int i = 0; i < 5; i++) {
+ if (set->at(i) > max)
+ max = set->at(i);
+ }
+ }
+
+ return max;
+}
+
+#include "moc_qboxplotseries.cpp"
+#include "moc_qboxplotseries_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
+
diff --git a/src/charts/boxplotchart/qboxplotseries.h b/src/charts/boxplotchart/qboxplotseries.h
new file mode 100644
index 00000000..f0684cfa
--- /dev/null
+++ b/src/charts/boxplotchart/qboxplotseries.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBOXPLOTSERIES_H
+#define QBOXPLOTSERIES_H
+
+#include <QtCharts/qchartglobal.h>
+#include <QtCharts/qboxset.h>
+#include <QtCharts/qabstractseries.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QBoxPlotSeriesPrivate;
+
+class QT_CHARTS_EXPORT QBoxPlotSeries : public QAbstractSeries
+{
+ Q_OBJECT
+ Q_PROPERTY(bool boxOutlineVisible READ boxOutlineVisible WRITE setBoxOutlineVisible NOTIFY boxOutlineVisibilityChanged)
+ Q_PROPERTY(qreal boxWidth READ boxWidth WRITE setBoxWidth NOTIFY boxWidthChanged)
+ Q_PROPERTY(QPen pen READ pen WRITE setPen NOTIFY penChanged)
+ Q_PROPERTY(QBrush brush READ brush WRITE setBrush NOTIFY brushChanged)
+ Q_PROPERTY(int count READ count NOTIFY countChanged REVISION 1)
+public:
+ explicit QBoxPlotSeries(QObject *parent = 0);
+ ~QBoxPlotSeries();
+
+ bool append(QBoxSet *box);
+ bool remove(QBoxSet *box);
+ bool take(QBoxSet *box);
+ bool append(QList<QBoxSet *> boxes);
+ bool insert(int index, QBoxSet *box);
+ int count() const;
+ QList<QBoxSet *> boxSets() const;
+ void clear();
+
+ QAbstractSeries::SeriesType type() const;
+
+ void setBoxOutlineVisible(bool visible);
+ bool boxOutlineVisible();
+ void setBoxWidth(qreal width);
+ qreal boxWidth();
+ void setBrush(const QBrush &brush);
+ QBrush brush() const;
+ void setPen(const QPen &pen);
+ QPen pen() const;
+
+Q_SIGNALS:
+ void clicked(QBoxSet *boxset);
+ void hovered(bool status, QBoxSet *boxset);
+ void countChanged();
+ void penChanged();
+ void brushChanged();
+ void boxOutlineVisibilityChanged();
+ void boxWidthChanged();
+
+ void boxsetsAdded(QList<QBoxSet *> sets);
+ void boxsetsRemoved(QList<QBoxSet *> sets);
+
+private:
+ Q_DECLARE_PRIVATE(QBoxPlotSeries)
+ Q_DISABLE_COPY(QBoxPlotSeries)
+ friend class BoxPlotChartItem;
+ friend class QBoxPlotLegendMarkerPrivate;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QBOXPLOTSERIES_H
diff --git a/src/charts/boxplotchart/qboxplotseries_p.h b/src/charts/boxplotchart/qboxplotseries_p.h
new file mode 100644
index 00000000..b635064b
--- /dev/null
+++ b/src/charts/boxplotchart/qboxplotseries_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QBOXPLOTSERIES_P_H
+#define QBOXPLOTSERIES_P_H
+
+#include "qboxplotseries.h"
+#include "qabstractbarseries_p.h"
+#include "abstractdomain_p.h"
+#include "qbarset.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class BoxPlotAnimation;
+
+class QBoxPlotSeriesPrivate : public QAbstractSeriesPrivate
+{
+ Q_OBJECT
+
+public:
+ QBoxPlotSeriesPrivate(QBoxPlotSeries *q);
+ ~QBoxPlotSeriesPrivate();
+
+ void initializeGraphics(QGraphicsItem *parent);
+ void initializeDomain();
+ void initializeAxes();
+ void initializeAnimations(QChart::AnimationOptions options);
+ void initializeTheme(int index, ChartTheme *theme, bool forced = false);
+
+ QList<QLegendMarker*> createLegendMarkers(QLegend *legend);
+
+ virtual QAbstractAxis::AxisType defaultAxisType(Qt::Orientation orientation) const;
+ QAbstractAxis *createDefaultAxis(Qt::Orientation orientation) const;
+
+ bool append(QBoxSet *set);
+ bool remove(QBoxSet *set);
+ bool append(QList<QBoxSet *> sets);
+ bool remove(QList<QBoxSet *> sets);
+ bool insert(int index, QBoxSet *set);
+ QBoxSet *boxSetAt(int index);
+
+ qreal max();
+ qreal min();
+
+private:
+ void populateCategories(QBarCategoryAxis *axis);
+
+Q_SIGNALS:
+ void updated();
+ void clicked(int index, QBoxSet *barset);
+ void updatedBoxes();
+ void updatedLayout();
+ void restructuredBoxes();
+
+private slots:
+ void handleSeriesChange(QAbstractSeries *series);
+ void handleSeriesRemove(QAbstractSeries *series);
+
+protected:
+ QList<QBoxSet *> m_boxSets;
+ QPen m_pen;
+ QBrush m_brush;
+ bool m_boxOutlineVisible;
+ int m_index;
+ BoxPlotAnimation *m_animation;
+ qreal m_boxWidth;
+
+private:
+ Q_DECLARE_PUBLIC(QBoxPlotSeries)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/boxplotchart/qboxset.cpp b/src/charts/boxplotchart/qboxset.cpp
new file mode 100644
index 00000000..065746f3
--- /dev/null
+++ b/src/charts/boxplotchart/qboxset.cpp
@@ -0,0 +1,336 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qboxset.h"
+#include "qboxset_p.h"
+#include "charthelpers_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QBoxSet
+ \inmodule Qt Charts
+ \brief Building block for box-and-whiskers chart.
+
+ QBoxSet represents one box-and-whiskers item. It takes five values to create a graphical representation
+ of range and three medians. There are two ways to give the values. The first one is with constructor
+ or stream operator (<<). The values have to be given in the following order: lower extreme,
+ lower quartile, median, upper quartile and upper extreme. The Second method is to create an empty QBoxSet instance and
+ give the values using setValue method.
+
+ \mainclass
+
+ \sa QBoxPlotSeries
+*/
+/*!
+ \enum QBoxSet::ValuePositions
+
+ \value LowerExtreme
+ \value LowerQuartile
+ \value Median
+ \value UpperQuartile
+ \value UpperExtreme
+*/
+/*!
+ \property QBoxSet::pen
+ \brief Defines the pen used by the box-and-whiskers set.
+*/
+/*!
+ \property QBoxSet::brush
+ \brief Defines the brush used by the box-and-whiskers set.
+*/
+
+/*!
+ \qmlproperty QString BoxSet::brushFilename
+ The name of the file used as a brush for the box-and-whiskers set.
+*/
+
+/*!
+ \fn void QBoxSet::clicked()
+ The signal is emitted if the user clicks with a mouse on top of box-and-whisker item.
+*/
+/*!
+ \fn void QBoxSet::hovered(bool status)
+
+ The signal is emitted if mouse is hovered on top of box-and-whisker item.
+ Parameter \a status is true, if mouse entered on top of item, false if mouse left from top of item.
+*/
+/*!
+ \fn void QBoxSet::penChanged()
+ This signal is emitted when the pen of the box-and-whisker item has changed.
+ \sa pen
+*/
+/*!
+ \fn void QBoxSet::brushChanged()
+ This signal is emitted when the brush of the box-and-whisker item has changed.
+ \sa brush
+*/
+/*!
+ \fn void QBoxSet::valuesChanged()
+ This signal is emitted when multiple values have been changed on the box-and-whisker item.
+ \sa append()
+*/
+/*!
+ \fn void QBoxSet::valueChanged(int index)
+ This signal is emitted values the value in the box-and-whisker item has been modified.
+ Parameter \a index indicates the position of the modified value.
+ \sa at()
+*/
+/*!
+ \fn void QBoxSet::cleared()
+ This signal is emitted when all the values on the set are cleared to 0.
+*/
+
+/*!
+ Constructs QBoxSet with optional \a label and parent of \a parent
+*/
+QBoxSet::QBoxSet(const QString label, QObject *parent)
+ : QObject(parent),
+ d_ptr(new QBoxSetPrivate(label, this))
+{
+}
+
+/*!
+ Constructs QBoxSet with given ordered values. \a le for lower extreme, \a lq for lower quartile, \a m for median,
+ \a uq for upper quartile and \a ue for upper quartile. \a label and \a parent are optional.
+ */
+QBoxSet::QBoxSet(const qreal le, const qreal lq, const qreal m, const qreal uq, const qreal ue, const QString label, QObject *parent)
+ : QObject(parent),
+ d_ptr(new QBoxSetPrivate(label, this))
+{
+ d_ptr->append(le);
+ d_ptr->append(lq);
+ d_ptr->append(m);
+ d_ptr->append(uq);
+ d_ptr->append(ue);
+}
+
+/*!
+ Destroys the boxset
+*/
+QBoxSet::~QBoxSet()
+{
+}
+
+/*!
+ Appends new value \a value to the end of set.
+*/
+void QBoxSet::append(const qreal value)
+{
+ if (d_ptr->append(value))
+ emit valueChanged(d_ptr->m_appendCount - 1);
+}
+
+/*!
+ Appends a list of reals to set. Works like append with single real value. The \a values in list
+ are appended to end of boxset.
+ \sa append()
+*/
+void QBoxSet::append(const QList<qreal> &values)
+{
+ if (d_ptr->append(values))
+ emit valuesChanged();
+}
+
+/*!
+ Sets new \a label for set.
+*/
+void QBoxSet::setLabel(const QString label)
+{
+ d_ptr->m_label = label;
+}
+
+/*!
+ Returns label of the set.
+*/
+QString QBoxSet::label() const
+{
+ return d_ptr->m_label;
+}
+
+/*!
+ Convenience operator. Same as append, with real \a value.
+ \sa append()
+*/
+QBoxSet &QBoxSet::operator << (const qreal &value)
+{
+ append(value);
+ return *this;
+}
+
+/*!
+ Sets a new \a value on the \a index position. For \a index ValuePositions can be used.
+*/
+void QBoxSet::setValue(const int index, const qreal value)
+{
+ d_ptr->setValue(index, value);
+ emit valueChanged(index);
+}
+
+/*!
+ Sets all values on the set to 0.
+ */
+void QBoxSet::clear()
+{
+ d_ptr->clear();
+ emit cleared();
+}
+
+/*!
+ Returns value of set indexed by \a index. For \a index ValuePositions can be used.
+ If the index is out of bounds 0.0 is returned.
+*/
+qreal QBoxSet::at(const int index) const
+{
+ if (index < 0 || index >= 5)
+ return 0;
+ return d_ptr->m_values[index];
+}
+
+/*!
+ Returns value of set indexed by \a index. For \a index ValuePositions can be used.
+ If the index is out of bounds 0.0 is returned.
+*/
+qreal QBoxSet::operator [](const int index) const
+{
+ return at(index);
+}
+
+/*!
+ Returns count of values appended to the set.
+*/
+int QBoxSet::count() const
+{
+ return d_ptr->m_appendCount;
+}
+
+/*!
+ Sets pen for set. Boxes of this set are drawn using \a pen
+*/
+void QBoxSet::setPen(const QPen &pen)
+{
+ if (d_ptr->m_pen != pen) {
+ d_ptr->m_pen = pen;
+ emit d_ptr->updatedBox();
+ emit penChanged();
+ }
+}
+
+/*!
+ Returns pen of the set.
+*/
+QPen QBoxSet::pen() const
+{
+ return d_ptr->m_pen;
+}
+
+/*!
+ Sets brush for the set. Boxes of this set are drawn using \a brush
+*/
+void QBoxSet::setBrush(const QBrush &brush)
+{
+ if (d_ptr->m_brush != brush) {
+ d_ptr->m_brush = brush;
+ emit d_ptr->updatedBox();
+ emit brushChanged();
+ }
+}
+
+/*!
+ Returns brush of the set.
+*/
+QBrush QBoxSet::brush() const
+{
+ return d_ptr->m_brush;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QBoxSetPrivate::QBoxSetPrivate(const QString label, QBoxSet *parent) : QObject(parent),
+ q_ptr(parent),
+ m_label(label),
+ m_valuesCount(5),
+ m_appendCount(0),
+ m_pen(QPen(Qt::NoPen)),
+ m_brush(QBrush(Qt::NoBrush)),
+ m_series(0)
+{
+ m_values = new qreal[m_valuesCount];
+}
+
+QBoxSetPrivate::~QBoxSetPrivate()
+{
+}
+
+bool QBoxSetPrivate::append(qreal value)
+{
+ if (isValidValue(value) && m_appendCount < m_valuesCount) {
+ m_values[m_appendCount++] = value;
+ emit restructuredBox();
+
+ return true;
+ }
+ return false;
+}
+
+bool QBoxSetPrivate::append(QList<qreal> values)
+{
+ bool success = false;
+
+ for (int i = 0; i < values.count(); i++) {
+ if (isValidValue(values.at(i)) && m_appendCount < m_valuesCount) {
+ success = true;
+ m_values[m_appendCount++] = values.at(i);
+ }
+ }
+
+ if (success)
+ emit restructuredBox();
+
+ return success;
+}
+
+void QBoxSetPrivate::clear()
+{
+ m_appendCount = 0;
+ for (int i = 0; i < m_valuesCount; i++)
+ m_values[i] = 0.0;
+ emit restructuredBox();
+}
+
+void QBoxSetPrivate::setValue(const int index, const qreal value)
+{
+ if (index < m_valuesCount) {
+ m_values[index] = value;
+ emit updatedLayout();
+ }
+}
+
+qreal QBoxSetPrivate::value(const int index)
+{
+ if (index < 0 || index >= m_valuesCount)
+ return 0;
+ return m_values[index];
+}
+
+#include "moc_qboxset.cpp"
+#include "moc_qboxset_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/boxplotchart/qboxset.h b/src/charts/boxplotchart/qboxset.h
new file mode 100644
index 00000000..498b570d
--- /dev/null
+++ b/src/charts/boxplotchart/qboxset.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBOXSET_H
+#define QBOXSET_H
+
+#include <QtCharts/qchartglobal.h>
+#include <QPen>
+#include <QBrush>
+#include <QFont>
+
+QT_CHARTS_BEGIN_NAMESPACE
+class QBoxSetPrivate;
+
+class QT_CHARTS_EXPORT QBoxSet : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QPen pen READ pen WRITE setPen NOTIFY penChanged)
+ Q_PROPERTY(QBrush brush READ brush WRITE setBrush NOTIFY brushChanged)
+
+public:
+ enum ValuePositions {
+ LowerExtreme,
+ LowerQuartile,
+ Median,
+ UpperQuartile,
+ UpperExtreme
+ };
+
+public:
+ explicit QBoxSet(const QString label = QString(), QObject *parent = 0);
+ explicit QBoxSet(const qreal le, const qreal lq, const qreal m, const qreal uq, const qreal ue, const QString label = QString(), QObject *parent = 0);
+ virtual ~QBoxSet();
+
+ void append(const qreal value);
+ void append(const QList<qreal> &values);
+
+ void clear();
+
+ void setLabel(const QString label);
+ QString label() const;
+
+ QBoxSet &operator << (const qreal &value);
+
+ void setValue(const int index, const qreal value);
+ qreal at(const int index) const;
+ qreal operator [](const int index) const;
+ int count() const;
+
+ void setPen(const QPen &pen);
+ QPen pen() const;
+
+ void setBrush(const QBrush &brush);
+ QBrush brush() const;
+
+Q_SIGNALS:
+ void clicked();
+ void hovered(bool status);
+ void penChanged();
+ void brushChanged();
+
+ void valuesChanged();
+ void valueChanged(int index);
+ void cleared();
+
+private:
+ QScopedPointer<QBoxSetPrivate> d_ptr;
+ Q_DISABLE_COPY(QBoxSet)
+ friend class BarLegendMarker;
+ friend class BarChartItem;
+ friend class BoxPlotChartItem;
+ friend class QBoxPlotSeriesPrivate;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QBOXSET_H
diff --git a/src/charts/boxplotchart/qboxset_p.h b/src/charts/boxplotchart/qboxset_p.h
new file mode 100644
index 00000000..3fd13080
--- /dev/null
+++ b/src/charts/boxplotchart/qboxset_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QBOXSET_P_H
+#define QBOXSET_P_H
+
+#include <qboxset.h>
+#include <QMap>
+#include <QPen>
+#include <QBrush>
+#include <QFont>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QBoxPlotSeriesPrivate;
+
+class QBoxSetPrivate : public QObject
+{
+ Q_OBJECT
+
+public:
+ QBoxSetPrivate(const QString label, QBoxSet *parent);
+ ~QBoxSetPrivate();
+
+ bool append(qreal value);
+ bool append(QList<qreal> values);
+
+ int remove(const int index, const int count);
+ void clear();
+
+ void setValue(const int index, const qreal value);
+
+ qreal value(const int index);
+
+Q_SIGNALS:
+ void restructuredBox();
+ void updatedBox();
+ void updatedLayout();
+
+private:
+ const QBoxSet *q_ptr;
+ QString m_label;
+ const int m_valuesCount;
+ qreal *m_values;
+ int m_appendCount;
+ QPen m_pen;
+ QBrush m_brush;
+ QBrush m_labelBrush;
+ QFont m_labelFont;
+ QBoxPlotSeriesPrivate *m_series;
+
+ friend class QBoxSet;
+ friend class QBoxPlotSeriesPrivate;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QBOXSET_P_H
diff --git a/src/charts/boxplotchart/qvboxplotmodelmapper.cpp b/src/charts/boxplotchart/qvboxplotmodelmapper.cpp
new file mode 100644
index 00000000..fd35e938
--- /dev/null
+++ b/src/charts/boxplotchart/qvboxplotmodelmapper.cpp
@@ -0,0 +1,257 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvboxplotmodelmapper.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QVBoxPlotModelMapper
+ \inmodule Qt Charts
+ \brief Vertical model mapper for box plot series.
+ \mainclass
+
+ Model mappers allow you to use QAbstractItemModel derived models as a data source for a chart series.
+ Vertical model mapper is used to create a connection between QBoxPlotSeries and QAbstractItemModel derived model object.
+ Model mapper maintains equal size of all the QBoxSets.
+ \note used model has to support adding/removing rows/columns and modifying the data of the cells.
+*/
+/*!
+ \qmltype VBoxPlotModelMapper
+ \instantiates QVBoxPlotModelMapper
+ \inqmlmodule QtCharts
+
+ \brief Vertical model mapper for box plot series.
+
+ VBoxPlotModelMapper allows you to use your own QAbstractItemModel derived model with data in
+ columns as a data source for any box-and-whiskers series. It is possible to use both
+ QAbstractItemModel and box-and-whiskers series data API to manipulate data. VBoxPlotModelMapper
+ keeps the series and the model in sync.
+
+ The following QML example would create a box-and-whiskers series with three box sets (assuming
+ the model has at least four columns). Each box set would contain data starting from row 1. The
+ name of a set would be defined by the horizontal header (of the column).
+ \code
+ BoxPlotSeries {
+ VBoxPlotModelMapper {
+ model: myCustomModel // QAbstractItemModel derived implementation
+ firstBoxSetColumn: 1
+ lastBoxSetColumn: 3
+ firstRow: 1
+ }
+ }
+ \endcode
+*/
+
+/*!
+ \property QVBoxPlotModelMapper::series
+ \brief Defines the QBoxPlotSeries object that is used by the mapper.
+
+ All the data in the series is discarded when it is set to the mapper.
+ When new series is specified the old series is disconnected (it preserves its data)
+*/
+/*!
+ \qmlproperty AbstractBarSeries VBoxPlotModelMapper::series
+ Defines the AbstractBarSeries based object that is used by the mapper. All the data in the series is discarded when it is
+ set to the mapper. When new series is specified the old series is disconnected (it preserves its data).
+*/
+
+/*!
+ \property QVBoxPlotModelMapper::model
+ \brief Defines the model that is used by the mapper.
+*/
+/*!
+ \qmlproperty SomeModel VBoxPlotModelMapper::model
+ The QAbstractItemModel based model that is used by the mapper. You need to implement the model
+ and expose it to QML. \note the model has to support adding/removing rows/columns and modifying
+ the data of the cells.
+*/
+
+/*!
+ \property QVBoxPlotModelMapper::firstBoxSetColumn
+ \brief Defines which column of the model is used as the data source for the first box-and-whiskers set.
+
+ Default value is: -1 (invalid mapping)
+*/
+/*!
+ \qmlproperty int VBarModelMapper::firstBoxSetColumn
+ Defines which column of the model is used as the data source for the first box-and-whiskers set. Default value
+ is: -1 (invalid mapping).
+*/
+
+/*!
+ \property QVBoxPlotModelMapper::lastBoxSetColumn
+ \brief Defines which column of the model is used as the data source for the last box-and-whiskers set.
+
+ Default value is: -1 (invalid mapping)
+*/
+/*!
+ \qmlproperty int VBarModelMapper::lastBoxSetColumn
+ Defines which column of the model is used as the data source for the last box-and-whiskers set. Default
+ value is: -1 (invalid mapping).
+*/
+
+/*!
+ \property QVBoxPlotModelMapper::firstRow
+ \brief Defines which row of the model contains the first values of the QBoxSets in the series.
+
+ Minimal and default value is: 0
+*/
+/*!
+ \qmlproperty int VBoxPlotModelMapper::firstRow
+ Defines which row of the model contains the first values of the QBoxSets in the series.
+ The default value is 0.
+*/
+
+/*!
+ \property QVBoxPlotModelMapper::rowCount
+ \brief Defines the number of rows of the model that are mapped as the data for QBoxPlotSeries
+
+ Minimal and default value is: -1 (count limited by the number of rows in the model)
+*/
+/*!
+ \qmlproperty int VBoxModelMapper::rowCount
+ Defines the number of rows of the model that are mapped as the data for QBoxPlotSeries. The default value is
+ -1 (count limited by the number of rows in the model)
+*/
+
+/*!
+ \fn void QVBoxPlotModelMapper::seriesReplaced()
+
+ Emitted when the series to which mapper is connected to has changed.
+*/
+
+/*!
+ \fn void QVBoxPlotModelMapper::modelReplaced()
+
+ Emitted when the model to which mapper is connected to has changed.
+*/
+
+/*!
+ \fn void QVBoxPlotModelMapper::firstBoxSetColumnChanged()
+ Emitted when the firstBoxSetColumn has changed.
+*/
+
+/*!
+ \fn void QVBoxPlotModelMapper::lastBoxSetColumnChanged()
+ Emitted when the lastBoxSetColumn has changed.
+*/
+
+/*!
+ \fn void QVBoxPlotModelMapper::firstRowChanged()
+ Emitted when the firstRow has changed.
+*/
+
+/*!
+ \fn void QVBoxPlotModelMapper::rowCountChanged()
+ Emitted when the rowCount has changed.
+*/
+
+/*!
+ Constructs a mapper object which is a child of \a parent.
+*/
+QVBoxPlotModelMapper::QVBoxPlotModelMapper(QObject *parent) :
+ QBoxPlotModelMapper(parent)
+{
+ QBoxPlotModelMapper::setOrientation(Qt::Vertical);
+}
+
+QAbstractItemModel *QVBoxPlotModelMapper::model() const
+{
+ return QBoxPlotModelMapper::model();
+}
+
+void QVBoxPlotModelMapper::setModel(QAbstractItemModel *model)
+{
+ if (model != QBoxPlotModelMapper::model()) {
+ QBoxPlotModelMapper::setModel(model);
+ emit modelReplaced();
+ }
+}
+
+QBoxPlotSeries *QVBoxPlotModelMapper::series() const
+{
+ return QBoxPlotModelMapper::series();
+}
+
+void QVBoxPlotModelMapper::setSeries(QBoxPlotSeries *series)
+{
+ if (series != QBoxPlotModelMapper::series()) {
+ QBoxPlotModelMapper::setSeries(series);
+ emit seriesReplaced();
+ }
+}
+
+int QVBoxPlotModelMapper::firstBoxSetColumn() const
+{
+ return QBoxPlotModelMapper::firstBoxSetSection();
+}
+
+void QVBoxPlotModelMapper::setFirstBoxSetColumn(int firstBoxSetColumn)
+{
+ if (firstBoxSetColumn != firstBoxSetSection()) {
+ QBoxPlotModelMapper::setFirstBoxSetSection(firstBoxSetColumn);
+ emit firstBoxSetColumnChanged();
+ }
+}
+
+int QVBoxPlotModelMapper::lastBoxSetColumn() const
+{
+ return QBoxPlotModelMapper::lastBoxSetSection();
+}
+
+void QVBoxPlotModelMapper::setLastBoxSetColumn(int lastBoxSetColumn)
+{
+ if (lastBoxSetColumn != lastBoxSetSection()) {
+ QBoxPlotModelMapper::setLastBoxSetSection(lastBoxSetColumn);
+ emit lastBoxSetColumnChanged();
+ }
+}
+
+int QVBoxPlotModelMapper::firstRow() const
+{
+ return QBoxPlotModelMapper::first();
+}
+
+void QVBoxPlotModelMapper::setFirstRow(int firstRow)
+{
+ if (firstRow != first()) {
+ QBoxPlotModelMapper::setFirst(firstRow);
+ emit firstRowChanged();
+ }
+}
+
+int QVBoxPlotModelMapper::rowCount() const
+{
+ return QBoxPlotModelMapper::count();
+}
+
+void QVBoxPlotModelMapper::setRowCount(int rowCount)
+{
+ if (rowCount != count()) {
+ QBoxPlotModelMapper::setCount(rowCount);
+ emit rowCountChanged();
+ }
+}
+
+#include "moc_qvboxplotmodelmapper.cpp"
+
+QT_CHARTS_END_NAMESPACE
+
diff --git a/src/charts/boxplotchart/qvboxplotmodelmapper.h b/src/charts/boxplotchart/qvboxplotmodelmapper.h
new file mode 100644
index 00000000..130e4a89
--- /dev/null
+++ b/src/charts/boxplotchart/qvboxplotmodelmapper.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVBOXPLOTMODELMAPPER_H
+#define QVBOXPLOTMODELMAPPER_H
+
+#include <QtCharts/QBoxPlotModelMapper>
+
+QT_CHARTS_BEGIN_NAMESPACE
+/* Comment line for syncqt to generate the fwd-include correctly, due to QTBUG-22432 */
+class QT_CHARTS_EXPORT QVBoxPlotModelMapper : public QBoxPlotModelMapper
+{
+ Q_OBJECT
+ Q_PROPERTY(QBoxPlotSeries *series READ series WRITE setSeries NOTIFY seriesReplaced)
+ Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelReplaced)
+ Q_PROPERTY(int firstBoxSetColumn READ firstBoxSetColumn WRITE setFirstBoxSetColumn NOTIFY firstBoxSetColumnChanged)
+ Q_PROPERTY(int lastBoxSetColumn READ lastBoxSetColumn WRITE setLastBoxSetColumn NOTIFY lastBoxSetColumnChanged)
+ Q_PROPERTY(int firstRow READ firstRow WRITE setFirstRow NOTIFY firstRowChanged)
+ Q_PROPERTY(int rowCount READ rowCount WRITE setRowCount NOTIFY rowCountChanged)
+
+public:
+ explicit QVBoxPlotModelMapper(QObject *parent = 0);
+
+ QAbstractItemModel *model() const;
+ void setModel(QAbstractItemModel *model);
+
+ QBoxPlotSeries *series() const;
+ void setSeries(QBoxPlotSeries *series);
+
+ int firstBoxSetColumn() const;
+ void setFirstBoxSetColumn(int firstBoxSetColumn);
+
+ int lastBoxSetColumn() const;
+ void setLastBoxSetColumn(int lastBoxSetColumn);
+
+ int firstRow() const;
+ void setFirstRow(int firstRow);
+
+ int rowCount() const;
+ void setRowCount(int rowCount);
+
+Q_SIGNALS:
+ void seriesReplaced();
+ void modelReplaced();
+ void firstBoxSetColumnChanged();
+ void lastBoxSetColumnChanged();
+ void firstRowChanged();
+ void rowCountChanged();
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QVBOXPLOTMODELMAPPER_H
diff --git a/src/charts/chartbackground.cpp b/src/charts/chartbackground.cpp
new file mode 100644
index 00000000..ceec3772
--- /dev/null
+++ b/src/charts/chartbackground.cpp
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "chartbackground_p.h"
+#include "chartconfig_p.h"
+#include <QPen>
+#include <QBrush>
+#include <QPainter>
+#include <QGraphicsDropShadowEffect>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+ChartBackground::ChartBackground(QGraphicsItem *parent)
+ : QGraphicsRectItem(parent),
+ m_diameter(5),
+ m_dropShadow(0)
+{
+}
+
+ChartBackground::~ChartBackground()
+{
+
+}
+
+void ChartBackground::setDropShadowEnabled(bool enabled)
+{
+#ifdef QT_NO_GRAPHICSEFFECT
+ Q_UNUSED(enabled)
+#else
+ if (enabled) {
+ if (!m_dropShadow) {
+ m_dropShadow = new QGraphicsDropShadowEffect();
+#ifdef Q_OS_MAC
+ m_dropShadow->setBlurRadius(15);
+ m_dropShadow->setOffset(0, 0);
+#elif defined(Q_OS_WIN)
+ m_dropShadow->setBlurRadius(10);
+ m_dropShadow->setOffset(0, 0);
+#else
+ m_dropShadow->setBlurRadius(10);
+ m_dropShadow->setOffset(5, 5);
+#endif
+ setGraphicsEffect(m_dropShadow);
+ }
+ } else {
+ delete m_dropShadow;
+ m_dropShadow = 0;
+ }
+#endif
+}
+
+void ChartBackground::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+ painter->save();
+ painter->setPen(pen());
+ painter->setBrush(brush());
+ painter->drawRoundedRect(rect(), m_diameter, m_diameter);
+ painter->restore();
+}
+
+qreal ChartBackground::diameter() const
+{
+ return m_diameter;
+}
+
+void ChartBackground::setDiameter(qreal diameter)
+{
+ m_diameter = diameter;
+ update();
+}
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/chartbackground_p.h b/src/charts/chartbackground_p.h
new file mode 100644
index 00000000..cf27b5bc
--- /dev/null
+++ b/src/charts/chartbackground_p.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTBACKGROUND_H
+#define CHARTBACKGROUND_H
+
+#include "qchartglobal.h"
+#include <QGraphicsRectItem>
+
+class QGraphicsDropShadowEffect;
+QT_CHARTS_BEGIN_NAMESPACE
+
+class ChartBackground: public QGraphicsRectItem
+{
+public:
+ ChartBackground(QGraphicsItem *parent = 0);
+ ~ChartBackground();
+
+ void setDiameter(qreal diameter);
+ qreal diameter() const;
+ void setDropShadowEnabled(bool enabled);
+ bool isDropShadowEnabled() { return m_dropShadow != 0; }
+
+protected:
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+
+private:
+ qreal m_diameter;
+ QGraphicsDropShadowEffect *m_dropShadow;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif /* CHARTBACKGROUND_H */
+
+
diff --git a/src/charts/chartconfig_p.h b/src/charts/chartconfig_p.h
new file mode 100644
index 00000000..e14b1f21
--- /dev/null
+++ b/src/charts/chartconfig_p.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTCONFIG_H
+#define CHARTCONFIG_H
+
+#include "qchartglobal.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class ChartConfig
+{
+private:
+ ChartConfig() {
+ m_instance = this;
+ }
+public:
+ static ChartConfig *instance() {
+ if (!m_instance) {
+ m_instance = new ChartConfig();
+ }
+ return m_instance;
+ }
+
+private:
+ static ChartConfig *m_instance;
+};
+
+
+ChartConfig *ChartConfig::m_instance = 0;
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/chartdataset.cpp b/src/charts/chartdataset.cpp
new file mode 100644
index 00000000..b28e6be0
--- /dev/null
+++ b/src/charts/chartdataset.cpp
@@ -0,0 +1,639 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "chartdataset_p.h"
+#include "chartpresenter_p.h"
+#include "qchart.h"
+#include "qchart_p.h"
+#include "qvalueaxis.h"
+#include "qbarcategoryaxis.h"
+#include "qvalueaxis_p.h"
+#include "qcategoryaxis.h"
+#include "qabstractseries_p.h"
+#include "qabstractbarseries.h"
+#include "qstackedbarseries.h"
+#include "qpercentbarseries.h"
+#include "qpieseries.h"
+#include "chartitem_p.h"
+#include "xydomain_p.h"
+#include "xypolardomain_p.h"
+#include "xlogydomain_p.h"
+#include "logxydomain_p.h"
+#include "logxlogydomain_p.h"
+#include "xlogypolardomain_p.h"
+#include "logxypolardomain_p.h"
+#include "logxlogypolardomain_p.h"
+
+#ifndef QT_ON_ARM
+#include "qdatetimeaxis.h"
+#endif
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+ChartDataSet::ChartDataSet(QChart *chart)
+ : QObject(chart),
+ m_chart(chart)
+{
+
+}
+
+ChartDataSet::~ChartDataSet()
+{
+ deleteAllSeries();
+ deleteAllAxes();
+}
+
+/*
+ * This method adds series to chartdataset, series ownership is taken from caller.
+ */
+void ChartDataSet::addSeries(QAbstractSeries *series)
+{
+ if (m_seriesList.contains(series)) {
+ qWarning() << QObject::tr("Can not add series. Series already on the chart.");
+ return;
+ }
+
+ // Ignore unsupported series added to polar chart
+ if (m_chart && m_chart->chartType() == QChart::ChartTypePolar) {
+ if (!(series->type() == QAbstractSeries::SeriesTypeArea
+ || series->type() == QAbstractSeries::SeriesTypeLine
+ || series->type() == QAbstractSeries::SeriesTypeScatter
+ || series->type() == QAbstractSeries::SeriesTypeSpline)) {
+ qWarning() << QObject::tr("Can not add series. Series type is not supported by a polar chart.");
+ return;
+ }
+ series->d_ptr->setDomain(new XYPolarDomain());
+ } else {
+ series->d_ptr->setDomain(new XYDomain());
+ }
+
+ series->d_ptr->initializeDomain();
+ m_seriesList.append(series);
+
+ series->setParent(this); // take ownership
+ series->d_ptr->m_chart = m_chart;
+
+ emit seriesAdded(series);
+}
+
+/*
+ * This method adds axis to chartdataset, axis ownership is taken from caller.
+ */
+void ChartDataSet::addAxis(QAbstractAxis *axis, Qt::Alignment aligment)
+{
+ if (m_axisList.contains(axis)) {
+ qWarning() << QObject::tr("Can not add axis. Axis already on the chart.");
+ return;
+ }
+
+ axis->d_ptr->setAlignment(aligment);
+
+ if (!axis->alignment()) {
+ qWarning() << QObject::tr("No alignment specified !");
+ return;
+ };
+
+ AbstractDomain *newDomain;
+ if (m_chart && m_chart->chartType() == QChart::ChartTypePolar)
+ newDomain = new XYPolarDomain();
+ else
+ newDomain = new XYDomain();
+
+ QSharedPointer<AbstractDomain> domain(newDomain);
+ axis->d_ptr->initializeDomain(domain.data());
+
+ axis->setParent(this);
+ axis->d_ptr->m_chart = m_chart;
+ m_axisList.append(axis);
+
+ emit axisAdded(axis);
+}
+
+/*
+ * This method removes series form chartdataset, series ownership is passed back to caller.
+ */
+void ChartDataSet::removeSeries(QAbstractSeries *series)
+{
+
+ if (! m_seriesList.contains(series)) {
+ qWarning() << QObject::tr("Can not remove series. Series not found on the chart.");
+ return;
+ }
+
+ QList<QAbstractAxis*> axes = series->d_ptr->m_axes;
+
+ foreach(QAbstractAxis* axis, axes) {
+ detachAxis(series,axis);
+ }
+
+ emit seriesRemoved(series);
+ m_seriesList.removeAll(series);
+
+ // Reset domain to default
+ series->d_ptr->setDomain(new XYDomain());
+ series->setParent(0);
+ series->d_ptr->m_chart = 0;
+}
+
+/*
+ * This method removes axis form chartdataset, series ownership is passed back to caller.
+ */
+void ChartDataSet::removeAxis(QAbstractAxis *axis)
+{
+ if (! m_axisList.contains(axis)) {
+ qWarning() << QObject::tr("Can not remove axis. Axis not found on the chart.");
+ return;
+ }
+
+ QList<QAbstractSeries*> series = axis->d_ptr->m_series;
+
+ foreach(QAbstractSeries* s, series) {
+ detachAxis(s,axis);
+ }
+
+ emit axisRemoved(axis);
+ m_axisList.removeAll(axis);
+
+ axis->setParent(0);
+ axis->d_ptr->m_chart = 0;
+}
+
+/*
+ * This method attaches axis to series, return true if success.
+ */
+bool ChartDataSet::attachAxis(QAbstractSeries *series,QAbstractAxis *axis)
+{
+ Q_ASSERT(axis);
+
+ if (!series)
+ return false;
+
+ QList<QAbstractSeries *> attachedSeriesList = axis->d_ptr->m_series;
+ QList<QAbstractAxis *> attachedAxisList = series->d_ptr->m_axes;
+
+ if (!m_seriesList.contains(series)) {
+ qWarning() << QObject::tr("Can not find series on the chart.");
+ return false;
+ }
+
+ if (axis && !m_axisList.contains(axis)) {
+ qWarning() << QObject::tr("Can not find axis on the chart.");
+ return false;
+ }
+
+ if (attachedAxisList.contains(axis)) {
+ qWarning() << QObject::tr("Axis already attached to series.");
+ return false;
+ }
+
+ if (attachedSeriesList.contains(series)) {
+ qWarning() << QObject::tr("Axis already attached to series.");
+ return false;
+ }
+
+ AbstractDomain *domain = series->d_ptr->domain();
+ AbstractDomain::DomainType type = selectDomain(attachedAxisList<<axis);
+
+ if (type == AbstractDomain::UndefinedDomain) return false;
+
+ if (domain->type() != type) {
+ AbstractDomain *old = domain;
+ domain = createDomain(type);
+ domain->setRange(old->minX(), old->maxX(), old->minY(), old->maxY());
+ // Initialize domain size to old domain size, as it won't get updated
+ // unless geometry changes.
+ domain->setSize(old->size());
+ }
+
+ if (!domain)
+ return false;
+
+ if (!domain->attachAxis(axis))
+ return false;
+
+ QList<AbstractDomain *> blockedDomains;
+ domain->blockRangeSignals(true);
+ blockedDomains << domain;
+
+ if (domain != series->d_ptr->domain()) {
+ foreach (QAbstractAxis *axis, series->d_ptr->m_axes) {
+ series->d_ptr->domain()->detachAxis(axis);
+ domain->attachAxis(axis);
+ foreach (QAbstractSeries *otherSeries, axis->d_ptr->m_series) {
+ if (otherSeries != series && otherSeries->d_ptr->domain()) {
+ if (!otherSeries->d_ptr->domain()->rangeSignalsBlocked()) {
+ otherSeries->d_ptr->domain()->blockRangeSignals(true);
+ blockedDomains << otherSeries->d_ptr->domain();
+ }
+ }
+ }
+ }
+ series->d_ptr->setDomain(domain);
+ series->d_ptr->initializeDomain();
+ }
+
+ series->d_ptr->m_axes<<axis;
+ axis->d_ptr->m_series<<series;
+
+ series->d_ptr->initializeAxes();
+ axis->d_ptr->initializeDomain(domain);
+
+ foreach (AbstractDomain *blockedDomain, blockedDomains)
+ blockedDomain->blockRangeSignals(false);
+
+ return true;
+}
+
+/*
+ * This method detaches axis to series, return true if success.
+ */
+bool ChartDataSet::detachAxis(QAbstractSeries* series,QAbstractAxis *axis)
+{
+ Q_ASSERT(series);
+ Q_ASSERT(axis);
+
+ QList<QAbstractSeries* > attachedSeriesList = axis->d_ptr->m_series;
+ QList<QAbstractAxis* > attachedAxisList = series->d_ptr->m_axes;
+ AbstractDomain* domain = series->d_ptr->domain();
+
+ if (!m_seriesList.contains(series)) {
+ qWarning() << QObject::tr("Can not find series on the chart.");
+ return false;
+ }
+
+ if (axis && !m_axisList.contains(axis)) {
+ qWarning() << QObject::tr("Can not find axis on the chart.");
+ return false;
+ }
+
+ if (!attachedAxisList.contains(axis)) {
+ qWarning() << QObject::tr("Axis not attached to series.");
+ return false;
+ }
+
+ Q_ASSERT(axis->d_ptr->m_series.contains(series));
+
+ domain->detachAxis(axis);
+ series->d_ptr->m_axes.removeAll(axis);
+ axis->d_ptr->m_series.removeAll(series);
+
+ return true;
+}
+
+void ChartDataSet::createDefaultAxes()
+{
+ if (m_seriesList.isEmpty())
+ return;
+
+ QAbstractAxis::AxisTypes typeX(0);
+ QAbstractAxis::AxisTypes typeY(0);
+
+ // Remove possibly existing axes
+ deleteAllAxes();
+
+ Q_ASSERT(m_axisList.isEmpty());
+
+ // Select the required axis x and axis y types based on the types of the current series
+ foreach(QAbstractSeries* s, m_seriesList) {
+ typeX |= s->d_ptr->defaultAxisType(Qt::Horizontal);
+ typeY |= s->d_ptr->defaultAxisType(Qt::Vertical);
+ }
+
+ // Create the axes of the types selected
+ // As long as AxisType enum balues are sequential a check to see if there are series of
+ // different types is needed. In such cases AxisTypeNoAxis is used to create separate axes
+ // for the types.
+ if (typeX != QAbstractAxis::AxisTypeNoAxis) {
+ if (typeX != m_seriesList.first()->d_ptr->defaultAxisType(Qt::Horizontal))
+ typeX = QAbstractAxis::AxisTypeNoAxis;
+ createAxes(typeX, Qt::Horizontal);
+ }
+
+ if (typeY != QAbstractAxis::AxisTypeNoAxis) {
+ if (typeY != m_seriesList.first()->d_ptr->defaultAxisType(Qt::Vertical))
+ typeY = QAbstractAxis::AxisTypeNoAxis;
+ createAxes(typeY, Qt::Vertical);
+ }
+
+}
+
+void ChartDataSet::createAxes(QAbstractAxis::AxisTypes type, Qt::Orientation orientation)
+{
+ QAbstractAxis *axis = 0;
+ //decide what axis should be created
+
+ switch (type) {
+ case QAbstractAxis::AxisTypeValue:
+ axis = new QValueAxis(this);
+ break;
+ case QAbstractAxis::AxisTypeBarCategory:
+ axis = new QBarCategoryAxis(this);
+ break;
+ case QAbstractAxis::AxisTypeCategory:
+ axis = new QCategoryAxis(this);
+ break;
+#ifndef Q_WS_QWS
+ case QAbstractAxis::AxisTypeDateTime:
+ axis = new QDateTimeAxis(this);
+ break;
+#endif
+ default:
+ axis = 0;
+ break;
+ }
+
+ if (axis) {
+ //create one axis for all
+
+ addAxis(axis,orientation==Qt::Horizontal?Qt::AlignBottom:Qt::AlignLeft);
+ qreal min = 0;
+ qreal max = 0;
+ findMinMaxForSeries(m_seriesList,orientation,min,max);
+ foreach(QAbstractSeries *s, m_seriesList) {
+ attachAxis(s,axis);
+ }
+ axis->setRange(min,max);
+ }
+ else if (type.testFlag(QAbstractAxis::AxisTypeNoAxis)) {
+ //create separate axis
+ foreach(QAbstractSeries *s, m_seriesList) {
+ QAbstractAxis *axis = s->d_ptr->createDefaultAxis(orientation);
+ if(axis) {
+ addAxis(axis,orientation==Qt::Horizontal?Qt::AlignBottom:Qt::AlignLeft);
+ attachAxis(s,axis);
+ }
+ }
+ }
+}
+
+void ChartDataSet::findMinMaxForSeries(QList<QAbstractSeries *> series,Qt::Orientations orientation, qreal &min, qreal &max)
+{
+ Q_ASSERT(!series.isEmpty());
+
+ AbstractDomain *domain = series.first()->d_ptr->domain();
+ min = (orientation == Qt::Vertical) ? domain->minY() : domain->minX();
+ max = (orientation == Qt::Vertical) ? domain->maxY() : domain->maxX();
+
+ for (int i = 1; i< series.size(); i++) {
+ AbstractDomain *domain = series[i]->d_ptr->domain();
+ min = qMin((orientation == Qt::Vertical) ? domain->minY() : domain->minX(), min);
+ max = qMax((orientation == Qt::Vertical) ? domain->maxY() : domain->maxX(), max);
+ }
+ if (min == max) {
+ min -= 0.5;
+ max += 0.5;
+ }
+}
+
+void ChartDataSet::deleteAllSeries()
+{
+ foreach (QAbstractSeries *s , m_seriesList){
+ removeSeries(s);
+ s->deleteLater();
+ }
+ Q_ASSERT(m_seriesList.count() == 0);
+}
+
+void ChartDataSet::deleteAllAxes()
+{
+ foreach (QAbstractAxis *a , m_axisList){
+ removeAxis(a);
+ a->deleteLater();
+ }
+ Q_ASSERT(m_axisList.count() == 0);
+}
+
+void ChartDataSet::zoomInDomain(const QRectF &rect)
+{
+ QList<AbstractDomain*> domains;
+ foreach(QAbstractSeries *s, m_seriesList) {
+ AbstractDomain* domain = s->d_ptr->domain();
+ s->d_ptr->m_domain->blockRangeSignals(true);
+ domains<<domain;
+ }
+
+ foreach(AbstractDomain *domain, domains)
+ domain->zoomIn(rect);
+
+ foreach(AbstractDomain *domain, domains)
+ domain->blockRangeSignals(false);
+}
+
+void ChartDataSet::zoomOutDomain(const QRectF &rect)
+{
+ QList<AbstractDomain*> domains;
+ foreach(QAbstractSeries *s, m_seriesList) {
+ AbstractDomain* domain = s->d_ptr->domain();
+ s->d_ptr->m_domain->blockRangeSignals(true);
+ domains<<domain;
+ }
+
+ foreach(AbstractDomain *domain, domains)
+ domain->zoomOut(rect);
+
+ foreach(AbstractDomain *domain, domains)
+ domain->blockRangeSignals(false);
+}
+
+void ChartDataSet::zoomResetDomain()
+{
+ QList<AbstractDomain*> domains;
+ foreach (QAbstractSeries *s, m_seriesList) {
+ AbstractDomain *domain = s->d_ptr->domain();
+ s->d_ptr->m_domain->blockRangeSignals(true);
+ domains << domain;
+ }
+
+ foreach (AbstractDomain *domain, domains)
+ domain->zoomReset();
+
+ foreach (AbstractDomain *domain, domains)
+ domain->blockRangeSignals(false);
+}
+
+bool ChartDataSet::isZoomedDomain()
+{
+ foreach (QAbstractSeries *s, m_seriesList) {
+ if (s->d_ptr->domain()->isZoomed())
+ return true;
+ }
+ return false;
+}
+
+void ChartDataSet::scrollDomain(qreal dx, qreal dy)
+{
+ QList<AbstractDomain*> domains;
+ foreach(QAbstractSeries *s, m_seriesList) {
+ AbstractDomain* domain = s->d_ptr->domain();
+ s->d_ptr->m_domain->blockRangeSignals(true);
+ domains<<domain;
+ }
+
+ foreach(AbstractDomain *domain, domains)
+ domain->move(dx, dy);
+
+ foreach(AbstractDomain *domain, domains)
+ domain->blockRangeSignals(false);
+}
+
+QPointF ChartDataSet::mapToValue(const QPointF &position, QAbstractSeries *series)
+{
+ QPointF point;
+ if (series == 0 && !m_seriesList.isEmpty())
+ series = m_seriesList.first();
+
+ if (series && series->type() == QAbstractSeries::SeriesTypePie)
+ return point;
+
+ if (series && m_seriesList.contains(series))
+ point = series->d_ptr->m_domain->calculateDomainPoint(position - m_chart->plotArea().topLeft());
+ return point;
+}
+
+QPointF ChartDataSet::mapToPosition(const QPointF &value, QAbstractSeries *series)
+{
+ QPointF point = m_chart->plotArea().topLeft();
+ if (series == 0 && !m_seriesList.isEmpty())
+ series = m_seriesList.first();
+
+ if (series && series->type() == QAbstractSeries::SeriesTypePie)
+ return QPoint(0, 0);
+
+ bool ok;
+ if (series && m_seriesList.contains(series))
+ point += series->d_ptr->m_domain->calculateGeometryPoint(value, ok);
+ return point;
+}
+
+QList<QAbstractAxis *> ChartDataSet::axes() const
+{
+ return m_axisList;
+}
+
+QList<QAbstractSeries *> ChartDataSet::series() const
+{
+ return m_seriesList;
+}
+
+AbstractDomain::DomainType ChartDataSet::selectDomain(QList<QAbstractAxis *> axes)
+{
+ enum Type {
+ Undefined = 0,
+ LogType = 0x1,
+ ValueType = 0x2
+ };
+
+ int horizontal(Undefined);
+ int vertical(Undefined);
+
+ // Assume cartesian chart type, unless chart is set
+ QChart::ChartType chartType(QChart::ChartTypeCartesian);
+ if (m_chart)
+ chartType = m_chart->chartType();
+
+ foreach (QAbstractAxis *axis, axes)
+ {
+ switch (axis->type()) {
+ case QAbstractAxis::AxisTypeLogValue:
+ if (axis->orientation() == Qt::Horizontal)
+ horizontal |= LogType;
+ if (axis->orientation() == Qt::Vertical)
+ vertical |= LogType;
+ break;
+ case QAbstractAxis::AxisTypeValue:
+ case QAbstractAxis::AxisTypeBarCategory:
+ case QAbstractAxis::AxisTypeCategory:
+ case QAbstractAxis::AxisTypeDateTime:
+ if (axis->orientation() == Qt::Horizontal)
+ horizontal |= ValueType;
+ if (axis->orientation() == Qt::Vertical)
+ vertical |= ValueType;
+ break;
+ default:
+ qWarning() << "Undefined type";
+ break;
+ }
+ }
+
+ if (vertical == Undefined)
+ vertical = ValueType;
+ if (horizontal == Undefined)
+ horizontal = ValueType;
+
+ if (vertical == ValueType && horizontal == ValueType) {
+ if (chartType == QChart::ChartTypeCartesian)
+ return AbstractDomain::XYDomain;
+ else if (chartType == QChart::ChartTypePolar)
+ return AbstractDomain::XYPolarDomain;
+ }
+
+ if (vertical == LogType && horizontal == ValueType) {
+ if (chartType == QChart::ChartTypeCartesian)
+ return AbstractDomain::XLogYDomain;
+ if (chartType == QChart::ChartTypePolar)
+ return AbstractDomain::XLogYPolarDomain;
+ }
+
+ if (vertical == ValueType && horizontal == LogType) {
+ if (chartType == QChart::ChartTypeCartesian)
+ return AbstractDomain::LogXYDomain;
+ else if (chartType == QChart::ChartTypePolar)
+ return AbstractDomain::LogXYPolarDomain;
+ }
+
+ if (vertical == LogType && horizontal == LogType) {
+ if (chartType == QChart::ChartTypeCartesian)
+ return AbstractDomain::LogXLogYDomain;
+ else if (chartType == QChart::ChartTypePolar)
+ return AbstractDomain::LogXLogYPolarDomain;
+ }
+
+ return AbstractDomain::UndefinedDomain;
+}
+
+//refactor create factory
+AbstractDomain* ChartDataSet::createDomain(AbstractDomain::DomainType type)
+{
+ switch (type)
+ {
+ case AbstractDomain::LogXLogYDomain:
+ return new LogXLogYDomain();
+ case AbstractDomain::XYDomain:
+ return new XYDomain();
+ case AbstractDomain::XLogYDomain:
+ return new XLogYDomain();
+ case AbstractDomain::LogXYDomain:
+ return new LogXYDomain();
+ case AbstractDomain::XYPolarDomain:
+ return new XYPolarDomain();
+ case AbstractDomain::XLogYPolarDomain:
+ return new XLogYPolarDomain();
+ case AbstractDomain::LogXYPolarDomain:
+ return new LogXYPolarDomain();
+ case AbstractDomain::LogXLogYPolarDomain:
+ return new LogXLogYPolarDomain();
+ default:
+ return 0;
+ }
+}
+
+#include "moc_chartdataset_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/chartdataset_p.h b/src/charts/chartdataset_p.h
new file mode 100644
index 00000000..fea47368
--- /dev/null
+++ b/src/charts/chartdataset_p.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTDATASET_P_H
+#define CHARTDATASET_P_H
+
+#include "qabstractseries.h"
+#include "abstractdomain_p.h"
+#include "qabstractaxis_p.h"
+#include <QVector>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QAbstractAxis;
+class ChartPresenter;
+
+class QT_CHARTS_AUTOTEST_EXPORT ChartDataSet : public QObject
+{
+ Q_OBJECT
+public:
+ ChartDataSet(QChart *chart);
+ virtual ~ChartDataSet();
+
+ void addSeries(QAbstractSeries *series);
+ void removeSeries(QAbstractSeries *series);
+ QList<QAbstractSeries *> series() const;
+
+ void addAxis(QAbstractAxis *axis,Qt::Alignment aligment);
+ void removeAxis(QAbstractAxis *axis);
+ QList<QAbstractAxis*> axes() const;
+
+ bool attachAxis(QAbstractSeries* series,QAbstractAxis *axis);
+ bool detachAxis(QAbstractSeries* series,QAbstractAxis *axis);
+
+ void createDefaultAxes();
+
+ void zoomInDomain(const QRectF &rect);
+ void zoomOutDomain(const QRectF &rect);
+ void zoomResetDomain();
+ bool isZoomedDomain();
+ void scrollDomain(qreal dx, qreal dy);
+
+ QPointF mapToValue(const QPointF &position, QAbstractSeries *series = 0);
+ QPointF mapToPosition(const QPointF &value, QAbstractSeries *series = 0);
+
+Q_SIGNALS:
+ void axisAdded(QAbstractAxis* axis);
+ void axisRemoved(QAbstractAxis* axis);
+ void seriesAdded(QAbstractSeries* series);
+ void seriesRemoved(QAbstractSeries* series);
+
+private:
+ void createAxes(QAbstractAxis::AxisTypes type, Qt::Orientation orientation);
+ QAbstractAxis *createAxis(QAbstractAxis::AxisType type, Qt::Orientation orientation);
+ AbstractDomain::DomainType selectDomain(QList<QAbstractAxis* > axes);
+ AbstractDomain* createDomain(AbstractDomain::DomainType type);
+ void deleteAllAxes();
+ void deleteAllSeries();
+ void findMinMaxForSeries(QList<QAbstractSeries *> series,Qt::Orientations orientation, qreal &min, qreal &max);
+private:
+ QList<QAbstractSeries *> m_seriesList;
+ QList<QAbstractAxis *> m_axisList;
+ QChart* m_chart;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif /* CHARTENGINE_P_H */
diff --git a/src/charts/chartelement.cpp b/src/charts/chartelement.cpp
new file mode 100644
index 00000000..6c40c439
--- /dev/null
+++ b/src/charts/chartelement.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "chartelement_p.h"
+#include "chartpresenter_p.h"
+#include "abstractdomain_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+ChartElement::ChartElement(QGraphicsItem* item):
+ QGraphicsObject(item),
+ m_presenter(0),
+ m_themeManager(0)
+{
+
+}
+
+void ChartElement::setPresenter(ChartPresenter *presenter)
+{
+ m_presenter = presenter;
+}
+
+ChartPresenter *ChartElement::presenter() const
+{
+ return m_presenter;
+}
+
+void ChartElement::setThemeManager(ChartThemeManager *manager)
+{
+ m_themeManager = manager;
+}
+
+ChartThemeManager* ChartElement::themeManager() const
+{
+ return m_themeManager;
+}
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/chartelement_p.h b/src/charts/chartelement_p.h
new file mode 100644
index 00000000..26ff5ca7
--- /dev/null
+++ b/src/charts/chartelement_p.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTELEMENT_H
+#define CHARTELEMENT_H
+
+#include "qchartglobal.h"
+#include <QObject>
+#include <QRect>
+#include <QGraphicsObject>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class ChartAnimator;
+class ChartPresenter;
+class ChartAnimation;
+class ChartThemeManager;
+class AbstractDomain;
+
+class ChartElement: public QGraphicsObject
+{
+
+public:
+ explicit ChartElement(QGraphicsItem* item = 0);
+
+ virtual ChartAnimation *animation() const { return 0; }
+ virtual void setPresenter(ChartPresenter *presenter);
+ ChartPresenter *presenter() const;
+ virtual void setThemeManager(ChartThemeManager *manager);
+ ChartThemeManager* themeManager() const;
+
+private:
+ ChartPresenter *m_presenter;
+ ChartThemeManager *m_themeManager;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/charthelpers_p.h b/src/charts/charthelpers_p.h
new file mode 100644
index 00000000..8e96e842
--- /dev/null
+++ b/src/charts/charthelpers_p.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTHELPERS_P_H
+#define CHARTHELPERS_P_H
+
+#include <qnumeric.h>
+#include <QPointF>
+
+static inline bool isValidValue(qreal value)
+{
+ if (qIsNaN(value) || qIsInf(value)) {
+ qWarning("Ignored NaN, Inf, or -Inf value.");
+ return false;
+ }
+ return true;
+}
+
+static inline bool isValidValue(qreal x, qreal y)
+{
+ return (isValidValue(x) && isValidValue(y));
+}
+
+static inline bool isValidValue(const QPointF point)
+{
+ return (isValidValue(point.x()) && isValidValue(point.y()));
+}
+
+#endif // CHARTHELPERS_P_H
diff --git a/src/charts/chartitem.cpp b/src/charts/chartitem.cpp
new file mode 100644
index 00000000..dd8612ab
--- /dev/null
+++ b/src/charts/chartitem.cpp
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "chartitem_p.h"
+#include "qabstractseries_p.h"
+#include "abstractdomain_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+ChartItem::ChartItem(QAbstractSeriesPrivate *series,QGraphicsItem* item):
+ ChartElement(item),
+ m_validData(true),
+ m_series(series)
+{
+
+}
+
+AbstractDomain* ChartItem::domain() const
+{
+ return m_series->domain();
+}
+
+void ChartItem::handleDomainUpdated()
+{
+ qWarning() << __FUNCTION__<< "Slot not implemented";
+}
+
+#include "moc_chartitem_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/chartitem_p.h b/src/charts/chartitem_p.h
new file mode 100644
index 00000000..2e100d67
--- /dev/null
+++ b/src/charts/chartitem_p.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTITEM_H
+#define CHARTITEM_H
+
+#include "chartelement_p.h"
+#include "chartpresenter_p.h"
+#include <QGraphicsItem>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class ChartItem : public ChartElement
+{
+ Q_OBJECT
+ enum ChartItemTypes { AXIS_ITEM = UserType + 1, XYLINE_ITEM };
+public:
+ ChartItem(QAbstractSeriesPrivate *series,QGraphicsItem* item);
+ AbstractDomain* domain() const;
+public Q_SLOTS:
+ virtual void handleDomainUpdated();
+
+protected:
+ bool m_validData;
+private:
+ QAbstractSeriesPrivate* m_series;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif /* CHARTITEM_H */
diff --git a/src/charts/chartpresenter.cpp b/src/charts/chartpresenter.cpp
new file mode 100644
index 00000000..7d3f41a7
--- /dev/null
+++ b/src/charts/chartpresenter.cpp
@@ -0,0 +1,508 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+ **
+ ** $QT_BEGIN_LICENSE$
+ ** 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
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+#include "chartpresenter_p.h"
+#include "qchart.h"
+#include "chartitem_p.h"
+#include "qchart_p.h"
+#include "qabstractaxis.h"
+#include "qabstractaxis_p.h"
+#include "chartdataset_p.h"
+#include "chartanimation_p.h"
+#include "qabstractseries_p.h"
+#include "qareaseries.h"
+#include "chartaxiselement_p.h"
+#include "chartbackground_p.h"
+#include "cartesianchartlayout_p.h"
+#include "polarchartlayout_p.h"
+#include "charttitle_p.h"
+#include <QTimer>
+#include <QTextDocument>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+ChartPresenter::ChartPresenter(QChart *chart, QChart::ChartType type)
+ : QObject(chart),
+ m_chart(chart),
+ m_options(QChart::NoAnimation),
+ m_state(ShowState),
+ m_background(0),
+ m_plotAreaBackground(0),
+ m_title(0),
+ m_localizeNumbers(false)
+{
+ if (type == QChart::ChartTypeCartesian)
+ m_layout = new CartesianChartLayout(this);
+ else if (type == QChart::ChartTypePolar)
+ m_layout = new PolarChartLayout(this);
+ Q_ASSERT(m_layout);
+}
+
+ChartPresenter::~ChartPresenter()
+{
+
+}
+
+void ChartPresenter::setGeometry(const QRectF rect)
+{
+ if (m_rect != rect) {
+ m_rect = rect;
+ foreach (ChartItem *chart, m_chartItems) {
+ chart->domain()->setSize(rect.size());
+ chart->setPos(rect.topLeft());
+ }
+ }
+}
+
+QRectF ChartPresenter::geometry() const
+{
+ return m_rect;
+}
+
+void ChartPresenter::handleAxisAdded(QAbstractAxis *axis)
+{
+ axis->d_ptr->initializeGraphics(rootItem());
+ axis->d_ptr->initializeAnimations(m_options);
+ ChartAxisElement *item = axis->d_ptr->axisItem();
+ item->setPresenter(this);
+ item->setThemeManager(m_chart->d_ptr->m_themeManager);
+ m_axisItems<<item;
+ m_axes<<axis;
+ m_layout->invalidate();
+}
+
+void ChartPresenter::handleAxisRemoved(QAbstractAxis *axis)
+{
+ ChartAxisElement *item = axis->d_ptr->m_item.take();
+ item->hide();
+ item->disconnect();
+ item->deleteLater();
+ m_axisItems.removeAll(item);
+ m_axes.removeAll(axis);
+ m_layout->invalidate();
+}
+
+
+void ChartPresenter::handleSeriesAdded(QAbstractSeries *series)
+{
+ series->d_ptr->initializeGraphics(rootItem());
+ series->d_ptr->initializeAnimations(m_options);
+ series->d_ptr->setPresenter(this);
+ ChartItem *chart = series->d_ptr->chartItem();
+ chart->setPresenter(this);
+ chart->setThemeManager(m_chart->d_ptr->m_themeManager);
+ chart->domain()->setSize(m_rect.size());
+ chart->setPos(m_rect.topLeft());
+ chart->handleDomainUpdated(); //this could be moved to intializeGraphics when animator is refactored
+ m_chartItems<<chart;
+ m_series<<series;
+ m_layout->invalidate();
+}
+
+void ChartPresenter::handleSeriesRemoved(QAbstractSeries *series)
+{
+ ChartItem *chart = series->d_ptr->m_item.take();
+ chart->hide();
+ chart->disconnect();
+ chart->deleteLater();
+ m_chartItems.removeAll(chart);
+ m_series.removeAll(series);
+ m_layout->invalidate();
+}
+
+void ChartPresenter::setAnimationOptions(QChart::AnimationOptions options)
+{
+ if (m_options != options) {
+ QChart::AnimationOptions oldOptions = m_options;
+ m_options = options;
+ if (options.testFlag(QChart::SeriesAnimations) != oldOptions.testFlag(QChart::SeriesAnimations)) {
+ foreach (QAbstractSeries *series, m_series)
+ series->d_ptr->initializeAnimations(m_options);
+ }
+ if (options.testFlag(QChart::GridAxisAnimations) != oldOptions.testFlag(QChart::GridAxisAnimations)) {
+ foreach (QAbstractAxis *axis, m_axes)
+ axis->d_ptr->initializeAnimations(m_options);
+ }
+ m_layout->invalidate(); // So that existing animations don't just stop halfway
+ }
+}
+
+void ChartPresenter::setState(State state,QPointF point)
+{
+ m_state=state;
+ m_statePoint=point;
+}
+
+QChart::AnimationOptions ChartPresenter::animationOptions() const
+{
+ return m_options;
+}
+
+void ChartPresenter::createBackgroundItem()
+{
+ if (!m_background) {
+ m_background = new ChartBackground(rootItem());
+ m_background->setPen(Qt::NoPen); // Theme doesn't touch pen so don't use default
+ m_background->setBrush(QChartPrivate::defaultBrush());
+ m_background->setZValue(ChartPresenter::BackgroundZValue);
+ }
+}
+
+void ChartPresenter::createPlotAreaBackgroundItem()
+{
+ if (!m_plotAreaBackground) {
+ if (m_chart->chartType() == QChart::ChartTypeCartesian)
+ m_plotAreaBackground = new QGraphicsRectItem(rootItem());
+ else
+ m_plotAreaBackground = new QGraphicsEllipseItem(rootItem());
+ // Use transparent pen instead of Qt::NoPen, as Qt::NoPen causes
+ // antialising artifacts with axis lines for some reason.
+ m_plotAreaBackground->setPen(QPen(Qt::transparent));
+ m_plotAreaBackground->setBrush(Qt::NoBrush);
+ m_plotAreaBackground->setZValue(ChartPresenter::PlotAreaZValue);
+ m_plotAreaBackground->setVisible(false);
+ }
+}
+
+void ChartPresenter::createTitleItem()
+{
+ if (!m_title) {
+ m_title = new ChartTitle(rootItem());
+ m_title->setZValue(ChartPresenter::BackgroundZValue);
+ }
+}
+
+void ChartPresenter::startAnimation(ChartAnimation *animation)
+{
+ animation->stop();
+ QTimer::singleShot(0, animation, SLOT(startChartAnimation()));
+}
+
+void ChartPresenter::setBackgroundBrush(const QBrush &brush)
+{
+ createBackgroundItem();
+ m_background->setBrush(brush);
+ m_layout->invalidate();
+}
+
+QBrush ChartPresenter::backgroundBrush() const
+{
+ if (!m_background)
+ return QBrush();
+ return m_background->brush();
+}
+
+void ChartPresenter::setBackgroundPen(const QPen &pen)
+{
+ createBackgroundItem();
+ m_background->setPen(pen);
+ m_layout->invalidate();
+}
+
+QPen ChartPresenter::backgroundPen() const
+{
+ if (!m_background)
+ return QPen();
+ return m_background->pen();
+}
+
+void ChartPresenter::setBackgroundRoundness(qreal diameter)
+{
+ createBackgroundItem();
+ m_background->setDiameter(diameter);
+ m_layout->invalidate();
+}
+
+qreal ChartPresenter::backgroundRoundness() const
+{
+ if (!m_background)
+ return 0;
+ return m_background->diameter();
+}
+
+void ChartPresenter::setPlotAreaBackgroundBrush(const QBrush &brush)
+{
+ createPlotAreaBackgroundItem();
+ m_plotAreaBackground->setBrush(brush);
+ m_layout->invalidate();
+}
+
+QBrush ChartPresenter::plotAreaBackgroundBrush() const
+{
+ if (!m_plotAreaBackground)
+ return QBrush();
+ return m_plotAreaBackground->brush();
+}
+
+void ChartPresenter::setPlotAreaBackgroundPen(const QPen &pen)
+{
+ createPlotAreaBackgroundItem();
+ m_plotAreaBackground->setPen(pen);
+ m_layout->invalidate();
+}
+
+QPen ChartPresenter::plotAreaBackgroundPen() const
+{
+ if (!m_plotAreaBackground)
+ return QPen();
+ return m_plotAreaBackground->pen();
+}
+
+void ChartPresenter::setTitle(const QString &title)
+{
+ createTitleItem();
+ m_title->setText(title);
+ m_layout->invalidate();
+}
+
+QString ChartPresenter::title() const
+{
+ if (!m_title)
+ return QString();
+ return m_title->text();
+}
+
+void ChartPresenter::setTitleFont(const QFont &font)
+{
+ createTitleItem();
+ m_title->setFont(font);
+ m_layout->invalidate();
+}
+
+QFont ChartPresenter::titleFont() const
+{
+ if (!m_title)
+ return QFont();
+ return m_title->font();
+}
+
+void ChartPresenter::setTitleBrush(const QBrush &brush)
+{
+ createTitleItem();
+ m_title->setDefaultTextColor(brush.color());
+ m_layout->invalidate();
+}
+
+QBrush ChartPresenter::titleBrush() const
+{
+ if (!m_title)
+ return QBrush();
+ return QBrush(m_title->defaultTextColor());
+}
+
+void ChartPresenter::setBackgroundVisible(bool visible)
+{
+ createBackgroundItem();
+ m_background->setVisible(visible);
+}
+
+
+bool ChartPresenter::isBackgroundVisible() const
+{
+ if (!m_background)
+ return false;
+ return m_background->isVisible();
+}
+
+void ChartPresenter::setPlotAreaBackgroundVisible(bool visible)
+{
+ createPlotAreaBackgroundItem();
+ m_plotAreaBackground->setVisible(visible);
+}
+
+bool ChartPresenter::isPlotAreaBackgroundVisible() const
+{
+ if (!m_plotAreaBackground)
+ return false;
+ return m_plotAreaBackground->isVisible();
+}
+
+void ChartPresenter::setBackgroundDropShadowEnabled(bool enabled)
+{
+ createBackgroundItem();
+ m_background->setDropShadowEnabled(enabled);
+}
+
+bool ChartPresenter::isBackgroundDropShadowEnabled() const
+{
+ if (!m_background)
+ return false;
+ return m_background->isDropShadowEnabled();
+}
+
+void ChartPresenter::setLocalizeNumbers(bool localize)
+{
+ m_localizeNumbers = localize;
+ m_layout->invalidate();
+}
+
+void ChartPresenter::setLocale(const QLocale &locale)
+{
+ m_locale = locale;
+ m_layout->invalidate();
+}
+
+AbstractChartLayout *ChartPresenter::layout()
+{
+ return m_layout;
+}
+
+QLegend *ChartPresenter::legend()
+{
+ return m_chart->legend();
+}
+
+void ChartPresenter::setVisible(bool visible)
+{
+ m_chart->setVisible(visible);
+}
+
+ChartBackground *ChartPresenter::backgroundElement()
+{
+ return m_background;
+}
+
+QAbstractGraphicsShapeItem *ChartPresenter::plotAreaElement()
+{
+ return m_plotAreaBackground;
+}
+
+QList<ChartAxisElement *> ChartPresenter::axisItems() const
+{
+ return m_axisItems;
+}
+
+QList<ChartItem *> ChartPresenter::chartItems() const
+{
+ return m_chartItems;
+}
+
+ChartTitle *ChartPresenter::titleElement()
+{
+ return m_title;
+}
+
+QRectF ChartPresenter::textBoundingRect(const QFont &font, const QString &text, qreal angle)
+{
+ static QGraphicsTextItem dummyTextItem;
+ static bool initMargin = true;
+ if (initMargin) {
+ dummyTextItem.document()->setDocumentMargin(textMargin());
+ initMargin = false;
+ }
+
+ dummyTextItem.setFont(font);
+ dummyTextItem.setHtml(text);
+ QRectF boundingRect = dummyTextItem.boundingRect();
+
+ // Take rotation into account
+ if (angle) {
+ QTransform transform;
+ transform.rotate(angle);
+ boundingRect = transform.mapRect(boundingRect);
+ }
+
+ return boundingRect;
+}
+
+// boundingRect parameter returns the rotated bounding rect of the text
+QString ChartPresenter::truncatedText(const QFont &font, const QString &text, qreal angle,
+ qreal maxWidth, qreal maxHeight, QRectF &boundingRect)
+{
+ QString truncatedString(text);
+ boundingRect = textBoundingRect(font, truncatedString, angle);
+ if (boundingRect.width() > maxWidth || boundingRect.height() > maxHeight) {
+ // It can be assumed that almost any amount of string manipulation is faster
+ // than calculating one bounding rectangle, so first prepare a list of truncated strings
+ // to try.
+ static QRegExp truncateMatcher(QStringLiteral("&#?[0-9a-zA-Z]*;$"));
+
+ QVector<QString> testStrings(text.length());
+ int count(0);
+ static QLatin1Char closeTag('>');
+ static QLatin1Char openTag('<');
+ static QLatin1Char semiColon(';');
+ static QLatin1String ellipsis("...");
+ while (truncatedString.length() > 1) {
+ int chopIndex(-1);
+ int chopCount(1);
+ QChar lastChar(truncatedString.at(truncatedString.length() - 1));
+
+ if (lastChar == closeTag)
+ chopIndex = truncatedString.lastIndexOf(openTag);
+ else if (lastChar == semiColon)
+ chopIndex = truncateMatcher.indexIn(truncatedString, 0);
+
+ if (chopIndex != -1)
+ chopCount = truncatedString.length() - chopIndex;
+ truncatedString.chop(chopCount);
+ testStrings[count] = truncatedString + ellipsis;
+ count++;
+ }
+
+ // Binary search for best fit
+ int minIndex(0);
+ int maxIndex(count - 1);
+ int bestIndex(count);
+ QRectF checkRect;
+
+ while (maxIndex >= minIndex) {
+ int mid = (maxIndex + minIndex) / 2;
+ checkRect = textBoundingRect(font, testStrings.at(mid), angle);
+ if (checkRect.width() > maxWidth || checkRect.height() > maxHeight) {
+ // Checked index too large, all under this are also too large
+ minIndex = mid + 1;
+ } else {
+ // Checked index fits, all over this also fit
+ maxIndex = mid - 1;
+ bestIndex = mid;
+ boundingRect = checkRect;
+ }
+ }
+ // Default to "..." if nothing fits
+ if (bestIndex == count) {
+ boundingRect = textBoundingRect(font, ellipsis, angle);
+ truncatedString = ellipsis;
+ } else {
+ truncatedString = testStrings.at(bestIndex);
+ }
+ }
+
+ return truncatedString;
+}
+
+QString ChartPresenter::numberToString(double value, char f, int prec)
+{
+ if (m_localizeNumbers)
+ return m_locale.toString(value, f, prec);
+ else
+ return QString::number(value, f, prec);
+}
+
+QString ChartPresenter::numberToString(int value)
+{
+ if (m_localizeNumbers)
+ return m_locale.toString(value);
+ else
+ return QString::number(value);
+}
+
+#include "moc_chartpresenter_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/chartpresenter_p.h b/src/charts/chartpresenter_p.h
new file mode 100644
index 00000000..85f1b1bb
--- /dev/null
+++ b/src/charts/chartpresenter_p.h
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTPRESENTER_H
+#define CHARTPRESENTER_H
+
+#include "qchartglobal.h"
+#include "qchart.h" //because of QChart::ChartThemeId
+#include <QRectF>
+#include <QMargins>
+#include <QLocale>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class ChartItem;
+class AxisItem;
+class QAbstractSeries;
+class ChartDataSet;
+class AbstractDomain;
+class ChartAxisElement;
+class ChartAnimator;
+class ChartBackground;
+class ChartTitle;
+class ChartAnimation;
+class AbstractChartLayout;
+
+class ChartPresenter: public QObject
+{
+ Q_OBJECT
+public:
+ enum ZValues {
+ BackgroundZValue = -1,
+ PlotAreaZValue,
+ ShadesZValue,
+ GridZValue,
+ AxisZValue,
+ SeriesZValue,
+ LineChartZValue = SeriesZValue,
+ SplineChartZValue = SeriesZValue,
+ BarSeriesZValue = SeriesZValue,
+ ScatterSeriesZValue = SeriesZValue,
+ PieSeriesZValue = SeriesZValue,
+ BoxPlotSeriesZValue = SeriesZValue,
+ LegendZValue,
+ TopMostZValue
+ };
+
+ enum State {
+ ShowState,
+ ScrollUpState,
+ ScrollDownState,
+ ScrollLeftState,
+ ScrollRightState,
+ ZoomInState,
+ ZoomOutState
+ };
+
+ ChartPresenter(QChart *chart, QChart::ChartType type);
+ virtual ~ChartPresenter();
+
+
+ void setGeometry(QRectF rect);
+ QRectF geometry() const;
+
+ QGraphicsItem *rootItem(){ return m_chart; }
+ ChartBackground *backgroundElement();
+ QAbstractGraphicsShapeItem *plotAreaElement();
+ ChartTitle *titleElement();
+ QList<ChartAxisElement *> axisItems() const;
+ QList<ChartItem *> chartItems() const;
+
+ QLegend *legend();
+
+ void setBackgroundBrush(const QBrush &brush);
+ QBrush backgroundBrush() const;
+
+ void setBackgroundPen(const QPen &pen);
+ QPen backgroundPen() const;
+
+ void setBackgroundRoundness(qreal diameter);
+ qreal backgroundRoundness() const;
+
+ void setPlotAreaBackgroundBrush(const QBrush &brush);
+ QBrush plotAreaBackgroundBrush() const;
+
+ void setPlotAreaBackgroundPen(const QPen &pen);
+ QPen plotAreaBackgroundPen() const;
+
+ void setTitle(const QString &title);
+ QString title() const;
+
+ void setTitleFont(const QFont &font);
+ QFont titleFont() const;
+
+ void setTitleBrush(const QBrush &brush);
+ QBrush titleBrush() const;
+
+ void setBackgroundVisible(bool visible);
+ bool isBackgroundVisible() const;
+
+ void setPlotAreaBackgroundVisible(bool visible);
+ bool isPlotAreaBackgroundVisible() const;
+
+ void setBackgroundDropShadowEnabled(bool enabled);
+ bool isBackgroundDropShadowEnabled() const;
+
+ void setLocalizeNumbers(bool localize);
+ inline bool localizeNumbers() const { return m_localizeNumbers; }
+ void setLocale(const QLocale &locale);
+ inline const QLocale &locale() const { return m_locale; }
+
+ void setVisible(bool visible);
+
+ void setAnimationOptions(QChart::AnimationOptions options);
+ QChart::AnimationOptions animationOptions() const;
+
+ void startAnimation(ChartAnimation *animation);
+
+ void setState(State state,QPointF point);
+ State state() const { return m_state; }
+ QPointF statePoint() const { return m_statePoint; }
+ AbstractChartLayout *layout();
+
+ QChart::ChartType chartType() const { return m_chart->chartType(); }
+ QChart *chart() { return m_chart; }
+
+ static QRectF textBoundingRect(const QFont &font, const QString &text, qreal angle = 0.0);
+ static QString truncatedText(const QFont &font, const QString &text, qreal angle,
+ qreal maxWidth, qreal maxHeight, QRectF &boundingRect);
+ inline static qreal textMargin() { return qreal(0.5); }
+
+ QString numberToString(double value, char f = 'g', int prec = 6);
+ QString numberToString(int value);
+
+private:
+ void createBackgroundItem();
+ void createPlotAreaBackgroundItem();
+ void createTitleItem();
+
+public Q_SLOTS:
+ void handleSeriesAdded(QAbstractSeries *series);
+ void handleSeriesRemoved(QAbstractSeries *series);
+ void handleAxisAdded(QAbstractAxis *axis);
+ void handleAxisRemoved(QAbstractAxis *axis);
+
+private:
+ QChart *m_chart;
+ QList<ChartItem *> m_chartItems;
+ QList<ChartAxisElement *> m_axisItems;
+ QList<QAbstractSeries *> m_series;
+ QList<QAbstractAxis *> m_axes;
+ QChart::AnimationOptions m_options;
+ State m_state;
+ QPointF m_statePoint;
+ AbstractChartLayout *m_layout;
+ ChartBackground *m_background;
+ QAbstractGraphicsShapeItem *m_plotAreaBackground;
+ ChartTitle *m_title;
+ QRectF m_rect;
+ bool m_localizeNumbers;
+ QLocale m_locale;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif /* CHARTPRESENTER_H */
diff --git a/src/charts/charts.pro b/src/charts/charts.pro
new file mode 100644
index 00000000..8e18fb7c
--- /dev/null
+++ b/src/charts/charts.pro
@@ -0,0 +1,82 @@
+############################# BUILD CONFIG ######################################
+
+TARGET = QtCharts
+
+message($$QT_CONFIG)
+QT = core gui widgets
+DEFINES += QT_CHARTS_LIBRARY
+# Fix exports in static builds for applications linking charts module
+static: MODULE_DEFINES += QT_CHARTS_STATICLIB
+
+MODULE_INCNAME = QtCharts
+
+QMAKE_DOCS = $$PWD/doc/qtcharts.qdocconf
+
+load(qt_module)
+CONFIG -= create_cmake
+
+############################# SOURCES ##########################################
+
+SOURCES += \
+ $$PWD/chartdataset.cpp \
+ $$PWD/chartpresenter.cpp \
+ $$PWD/chartthememanager.cpp \
+ $$PWD/qchart.cpp \
+ $$PWD/qchartview.cpp \
+ $$PWD/qabstractseries.cpp \
+ $$PWD/chartbackground.cpp \
+ $$PWD/chartelement.cpp \
+ $$PWD/chartitem.cpp \
+ $$PWD/scroller.cpp \
+ $$PWD/charttitle.cpp \
+ $$PWD/qpolarchart.cpp
+PRIVATE_HEADERS += \
+ $$PWD/chartdataset_p.h \
+ $$PWD/chartitem_p.h \
+ $$PWD/chartpresenter_p.h \
+ $$PWD/chartthememanager_p.h \
+ $$PWD/chartbackground_p.h \
+ $$PWD/chartelement_p.h \
+ $$PWD/chartconfig_p.h \
+ $$PWD/qchart_p.h \
+ $$PWD/qchartview_p.h \
+ $$PWD/scroller_p.h \
+ $$PWD/qabstractseries_p.h \
+ $$PWD/charttitle_p.h \
+ $$PWD/charthelpers_p.h
+PUBLIC_HEADERS += \
+ $$PWD/qchart.h \
+ $$PWD/qchartglobal.h \
+ $$PWD/qabstractseries.h \
+ $$PWD/qchartview.h \
+ $$PWD/chartsnamespace.h \
+ $$PWD/qpolarchart.h
+
+include($$PWD/common.pri)
+include($$PWD/animations/animations.pri)
+include($$PWD/areachart/areachart.pri)
+include($$PWD/axis/axis.pri)
+include($$PWD/domain/domain.pri)
+include($$PWD/barchart/barchart.pri)
+include($$PWD/legend/legend.pri)
+include($$PWD/linechart/linechart.pri)
+include($$PWD/piechart/piechart.pri)
+include($$PWD/scatterchart/scatter.pri)
+include($$PWD/splinechart/splinechart.pri)
+include($$PWD/themes/themes.pri)
+include($$PWD/xychart/xychart.pri)
+include($$PWD/layout/layout.pri)
+include($$PWD/boxplotchart/boxplotchart.pri)
+
+HEADERS += $$PUBLIC_HEADERS
+HEADERS += $$PRIVATE_HEADERS
+HEADERS += $$THEMES
+
+OTHER_FILES += doc/qtcharts.qdocconf \
+ doc/src/* \
+ doc/images/*
+
+#Define for unit tests
+CONFIG(debug, debug|release) {
+ DEFINES += BUILD_PRIVATE_UNIT_TESTS
+}
diff --git a/src/charts/chartsnamespace.h b/src/charts/chartsnamespace.h
new file mode 100644
index 00000000..f4c76944
--- /dev/null
+++ b/src/charts/chartsnamespace.h
@@ -0,0 +1,28 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CHARTSNAMESPACE_H
+#define CHARTSNAMESPACE_H
+
+// this is needed by the designer plugin.
+
+QT_CHARTS_USE_NAMESPACE
+
+#endif /* CHARTSNAMESPACE_H */
diff --git a/src/charts/chartthememanager.cpp b/src/charts/chartthememanager.cpp
new file mode 100644
index 00000000..211552da
--- /dev/null
+++ b/src/charts/chartthememanager.cpp
@@ -0,0 +1,249 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qabstractseries_p.h"
+#include "qabstractaxis_p.h"
+#include <QTime>
+//themes
+#include "chartthemesystem_p.h"
+#include "chartthemelight_p.h"
+#include "chartthemebluecerulean_p.h"
+#include "chartthemedark_p.h"
+#include "chartthemebrownsand_p.h"
+#include "chartthemebluencs_p.h"
+#include "chartthemehighcontrast_p.h"
+#include "chartthemeblueicy_p.h"
+#include "chartthemeqt_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+ChartThemeManager::ChartThemeManager(QChart* chart) :
+ m_chart(chart)
+{
+ qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
+}
+
+
+void ChartThemeManager::setTheme(QChart::ChartTheme theme)
+{
+ if (m_theme.isNull() || theme != m_theme->id()) {
+ switch (theme) {
+ case QChart::ChartThemeLight:
+ m_theme.reset(new ChartThemeLight());
+ break;
+ case QChart::ChartThemeBlueCerulean:
+ m_theme.reset(new ChartThemeBlueCerulean());
+ break;
+ case QChart::ChartThemeDark:
+ m_theme.reset(new ChartThemeDark());
+ break;
+ case QChart::ChartThemeBrownSand:
+ m_theme.reset(new ChartThemeBrownSand());
+ break;
+ case QChart::ChartThemeBlueNcs:
+ m_theme.reset(new ChartThemeBlueNcs());
+ break;
+ case QChart::ChartThemeHighContrast:
+ m_theme.reset(new ChartThemeHighContrast());
+ break;
+ case QChart::ChartThemeBlueIcy:
+ m_theme.reset(new ChartThemeBlueIcy());
+ break;
+ case QChart::ChartThemeQt:
+ m_theme.reset(new ChartThemeQt());
+ break;
+ default:
+ m_theme.reset(new ChartThemeSystem());
+ break;
+ }
+
+ if (!m_theme.isNull()) {
+ decorateChart(m_chart,m_theme.data());
+ decorateLegend(m_chart->legend(),m_theme.data());
+ foreach (QAbstractAxis* axis, m_axisList)
+ axis->d_ptr->initializeTheme(m_theme.data(), true);
+ foreach (QAbstractSeries* series, m_seriesMap.keys())
+ series->d_ptr->initializeTheme(m_seriesMap[series], m_theme.data(), true);
+ }
+ }
+}
+
+// decorateChart is only called when theme is forcibly initialized
+void ChartThemeManager::decorateChart(QChart *chart, ChartTheme *theme) const
+{
+ chart->setBackgroundBrush(theme->chartBackgroundGradient());
+
+ QPen pen(Qt::transparent);
+ QBrush brush;
+ chart->setPlotAreaBackgroundBrush(brush);
+ chart->setPlotAreaBackgroundPen(pen);
+ chart->setPlotAreaBackgroundVisible(false);
+
+ chart->setTitleFont(theme->masterFont());
+ chart->setTitleBrush(theme->labelBrush());
+ chart->setDropShadowEnabled(theme->isBackgroundDropShadowEnabled());
+}
+
+// decorateLegend is only called when theme is forcibly initialized
+void ChartThemeManager::decorateLegend(QLegend *legend, ChartTheme *theme) const
+{
+ legend->setPen(theme->axisLinePen());
+ legend->setBrush(theme->chartBackgroundGradient());
+ legend->setFont(theme->labelFont());
+ legend->setLabelBrush(theme->labelBrush());
+}
+
+int ChartThemeManager::createIndexKey(QList<int> keys) const
+{
+ std::sort(keys.begin(), keys.end());
+
+ int key = 0;
+ QList<int>::iterator i;
+ i = keys.begin();
+
+ while (i != keys.end()) {
+ if (*i != key)
+ break;
+ key++;
+ i++;
+ }
+
+ return key;
+}
+
+int ChartThemeManager::seriesCount(QAbstractSeries::SeriesType type) const
+{
+ int count = 0;
+ QList<QAbstractSeries *> series = m_seriesMap.keys();
+ foreach(QAbstractSeries *s, series) {
+ if (s->type() == type)
+ count++;
+ }
+ return count;
+}
+
+void ChartThemeManager::handleSeriesAdded(QAbstractSeries *series)
+{
+ int key = createIndexKey(m_seriesMap.values());
+ m_seriesMap.insert(series,key);
+ series->d_ptr->initializeTheme(key,m_theme.data(),false);
+}
+
+void ChartThemeManager::handleSeriesRemoved(QAbstractSeries *series)
+{
+ m_seriesMap.remove(series);
+}
+
+void ChartThemeManager::handleAxisAdded(QAbstractAxis *axis)
+{
+ m_axisList.append(axis);
+ axis->d_ptr->initializeTheme(m_theme.data(),false);
+}
+
+void ChartThemeManager::handleAxisRemoved(QAbstractAxis *axis)
+{
+ m_axisList.removeAll(axis);
+}
+
+void ChartThemeManager::updateSeries(QAbstractSeries *series)
+{
+ if(m_seriesMap.contains(series)){
+ series->d_ptr->initializeTheme(m_seriesMap[series],m_theme.data(),false);
+ }
+}
+QList<QGradient> ChartThemeManager::generateSeriesGradients(const QList<QColor>& colors)
+{
+ QList<QGradient> result;
+ // Generate gradients in HSV color space
+ foreach (const QColor &color, colors) {
+ QLinearGradient g;
+ qreal h = color.hsvHueF();
+ qreal s = color.hsvSaturationF();
+
+ QColor start = color;
+ start.setHsvF(h, 0.0, 1.0);
+ g.setColorAt(0.0, start);
+
+ g.setColorAt(0.5, color);
+
+ QColor end = color;
+ end.setHsvF(h, s, 0.25);
+ g.setColorAt(1.0, end);
+
+ result << g;
+ }
+
+ return result;
+}
+
+
+QColor ChartThemeManager::colorAt(const QColor &start, const QColor &end, qreal pos)
+{
+ Q_ASSERT(pos >= 0.0 && pos <= 1.0);
+ qreal r = start.redF() + ((end.redF() - start.redF()) * pos);
+ qreal g = start.greenF() + ((end.greenF() - start.greenF()) * pos);
+ qreal b = start.blueF() + ((end.blueF() - start.blueF()) * pos);
+ QColor c;
+ c.setRgbF(r, g, b);
+ return c;
+}
+
+QColor ChartThemeManager::colorAt(const QGradient &gradient, qreal pos)
+{
+ Q_ASSERT(pos >= 0 && pos <= 1.0);
+
+ QGradientStops stops = gradient.stops();
+ int count = stops.count();
+
+ // find previous stop relative to position
+ QGradientStop prev = stops.first();
+ for (int i = 0; i < count; i++) {
+ QGradientStop stop = stops.at(i);
+ if (pos > stop.first)
+ prev = stop;
+
+ // given position is actually a stop position?
+ if (pos == stop.first) {
+ //qDebug() << "stop color" << pos;
+ return stop.second;
+ }
+ }
+
+ // find next stop relative to position
+ QGradientStop next = stops.last();
+ for (int i = count - 1; i >= 0; i--) {
+ QGradientStop stop = stops.at(i);
+ if (pos < stop.first)
+ next = stop;
+ }
+
+ //qDebug() << "prev" << prev.first << "pos" << pos << "next" << next.first;
+
+ qreal range = next.first - prev.first;
+ qreal posDelta = pos - prev.first;
+ qreal relativePos = posDelta / range;
+
+ //qDebug() << "range" << range << "posDelta" << posDelta << "relativePos" << relativePos;
+
+ return colorAt(prev.second, next.second, relativePos);
+}
+
+#include "moc_chartthememanager_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/chartthememanager_p.h b/src/charts/chartthememanager_p.h
new file mode 100644
index 00000000..3eabd8e5
--- /dev/null
+++ b/src/charts/chartthememanager_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTTHEMEMANAGER_H
+#define CHARTTHEMEMANAGER_H
+
+#include "qchartglobal.h"
+#include "qchart.h"
+#include <QColor>
+#include <QGradientStops>
+
+QT_CHARTS_BEGIN_NAMESPACE
+class ChartTheme;
+
+class ChartThemeManager: public QObject
+{
+ Q_OBJECT
+public:
+ enum BackgroundShadesMode {
+ BackgroundShadesNone = 0,
+ BackgroundShadesVertical,
+ BackgroundShadesHorizontal,
+ BackgroundShadesBoth
+ };
+
+public:
+ explicit ChartThemeManager(QChart* chart);
+ void setTheme(QChart::ChartTheme theme);
+ ChartTheme* theme() const { return m_theme.data(); }
+ void decorateChart(QChart *chart, ChartTheme* theme) const;
+ void decorateLegend(QLegend *legend, ChartTheme* theme) const;
+ void updateSeries(QAbstractSeries *series);
+
+public:
+ static QList<QGradient> generateSeriesGradients(const QList<QColor>& colors);
+ static QColor colorAt(const QColor &start, const QColor &end, qreal pos);
+ static QColor colorAt(const QGradient &gradient, qreal pos);
+
+private:
+ int createIndexKey(QList<int> keys) const;
+ int seriesCount(QAbstractSeries::SeriesType type) const;
+
+public Q_SLOTS:
+ void handleSeriesAdded(QAbstractSeries *series);
+ void handleSeriesRemoved(QAbstractSeries *series);
+ void handleAxisAdded(QAbstractAxis *axis);
+ void handleAxisRemoved(QAbstractAxis *axis);
+
+protected:
+ QScopedPointer<ChartTheme> m_theme;
+ QMap<QAbstractSeries *,int> m_seriesMap;
+ QList<QAbstractAxis *> m_axisList;
+ QChart* m_chart;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // CHARTTHEME_H
diff --git a/src/charts/charttitle.cpp b/src/charts/charttitle.cpp
new file mode 100644
index 00000000..c7e18b7e
--- /dev/null
+++ b/src/charts/charttitle.cpp
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "charttitle_p.h"
+#include "chartpresenter_p.h"
+#include <QFont>
+#include <QFontMetrics>
+#include <QDebug>
+#include <QTextDocument>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+ChartTitle::ChartTitle(QGraphicsItem *parent)
+ : QGraphicsTextItem(parent)
+{
+ document()->setDocumentMargin(ChartPresenter::textMargin());
+}
+
+ChartTitle::~ChartTitle()
+{
+
+}
+
+void ChartTitle::setText(const QString &text)
+{
+ m_text = text;
+}
+
+QString ChartTitle::text() const
+{
+ return m_text;
+}
+
+void ChartTitle::setGeometry(const QRectF &rect)
+{
+ QRectF truncatedRect;
+ QGraphicsTextItem::setHtml(ChartPresenter::truncatedText(font(), m_text, qreal(0.0),
+ rect.width(), rect.height(),
+ truncatedRect));
+ QGraphicsTextItem::setTextWidth(truncatedRect.width());
+ setPos(rect.topLeft());
+}
+
+
+QSizeF ChartTitle::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED(constraint);
+ QSizeF sh;
+
+ switch (which) {
+ case Qt::MinimumSize: {
+ QRectF titleRect = ChartPresenter::textBoundingRect(font(), QStringLiteral("..."));
+ sh = QSizeF(titleRect.width(), titleRect.height());
+ break;
+ }
+ case Qt::PreferredSize:
+ case Qt::MaximumSize: {
+ QRectF titleRect = ChartPresenter::textBoundingRect(font(), m_text);
+ sh = QSizeF(titleRect.width(), titleRect.height());
+ break;
+ }
+ case Qt::MinimumDescent: {
+ QFontMetrics fn(font());
+ sh = QSizeF(0, fn.descent());
+ break;
+ }
+ default:
+ break;
+ }
+
+ return sh;
+}
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/charttitle_p.h b/src/charts/charttitle_p.h
new file mode 100644
index 00000000..dbdb4fbb
--- /dev/null
+++ b/src/charts/charttitle_p.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTTITLE_P_H_
+#define CHARTTITLE_P_H_
+
+#include "qchartglobal.h"
+#include <QGraphicsTextItem>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class ChartTitle : public QGraphicsTextItem
+{
+public:
+ ChartTitle(QGraphicsItem *parent = 0);
+ ~ChartTitle();
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
+ void setText(const QString &text);
+ QString text() const;
+ void setGeometry(const QRectF &rect);
+private:
+ QString m_text;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif /* CHARTTITLE_P_H_ */
diff --git a/src/charts/common.pri b/src/charts/common.pri
new file mode 100644
index 00000000..1d5b6494
--- /dev/null
+++ b/src/charts/common.pri
@@ -0,0 +1,15 @@
+INCLUDEPATH += $$PWD/ \
+ $$PWD/animations \
+ $$PWD/areachart \
+ $$PWD/axis \
+ $$PWD/barchart \
+ $$PWD/boxplotchart \
+ $$PWD/domain \
+ $$PWD/layout \
+ $$PWD/legend \
+ $$PWD/linechart \
+ $$PWD/piechart \
+ $$PWD/scatterchart \
+ $$PWD/splinechart \
+ $$PWD/themes \
+ $$PWD/xychart
diff --git a/src/charts/doc/images/api_category_axis.png b/src/charts/doc/images/api_category_axis.png
new file mode 100644
index 00000000..97fe6cd3
--- /dev/null
+++ b/src/charts/doc/images/api_category_axis.png
Binary files differ
diff --git a/src/charts/doc/images/api_datatime_axis.png b/src/charts/doc/images/api_datatime_axis.png
new file mode 100644
index 00000000..1c8c8311
--- /dev/null
+++ b/src/charts/doc/images/api_datatime_axis.png
Binary files differ
diff --git a/src/charts/doc/images/arrow_down.png b/src/charts/doc/images/arrow_down.png
new file mode 100644
index 00000000..9d01e97f
--- /dev/null
+++ b/src/charts/doc/images/arrow_down.png
Binary files differ
diff --git a/src/charts/doc/images/bg.png b/src/charts/doc/images/bg.png
new file mode 100644
index 00000000..91c180a2
--- /dev/null
+++ b/src/charts/doc/images/bg.png
Binary files differ
diff --git a/src/charts/doc/images/breadcrumb.png b/src/charts/doc/images/breadcrumb.png
new file mode 100644
index 00000000..0ded5514
--- /dev/null
+++ b/src/charts/doc/images/breadcrumb.png
Binary files differ
diff --git a/src/charts/doc/images/bullet_dn.png b/src/charts/doc/images/bullet_dn.png
new file mode 100644
index 00000000..f7762472
--- /dev/null
+++ b/src/charts/doc/images/bullet_dn.png
Binary files differ
diff --git a/src/charts/doc/images/bullet_gt.png b/src/charts/doc/images/bullet_gt.png
new file mode 100644
index 00000000..7561b4ed
--- /dev/null
+++ b/src/charts/doc/images/bullet_gt.png
Binary files differ
diff --git a/src/charts/doc/images/bullet_sq.png b/src/charts/doc/images/bullet_sq.png
new file mode 100644
index 00000000..a84845e3
--- /dev/null
+++ b/src/charts/doc/images/bullet_sq.png
Binary files differ
diff --git a/src/charts/doc/images/bullet_up.png b/src/charts/doc/images/bullet_up.png
new file mode 100644
index 00000000..7de2f069
--- /dev/null
+++ b/src/charts/doc/images/bullet_up.png
Binary files differ
diff --git a/src/charts/doc/images/digia_logo.png b/src/charts/doc/images/digia_logo.png
new file mode 100644
index 00000000..6ca67c84
--- /dev/null
+++ b/src/charts/doc/images/digia_logo.png
Binary files differ
diff --git a/src/charts/doc/images/examples_areachart.png b/src/charts/doc/images/examples_areachart.png
new file mode 100644
index 00000000..d48f7147
--- /dev/null
+++ b/src/charts/doc/images/examples_areachart.png
Binary files differ
diff --git a/src/charts/doc/images/examples_audio.png b/src/charts/doc/images/examples_audio.png
new file mode 100644
index 00000000..8859ee2e
--- /dev/null
+++ b/src/charts/doc/images/examples_audio.png
Binary files differ
diff --git a/src/charts/doc/images/examples_barchart.png b/src/charts/doc/images/examples_barchart.png
new file mode 100644
index 00000000..bdd51199
--- /dev/null
+++ b/src/charts/doc/images/examples_barchart.png
Binary files differ
diff --git a/src/charts/doc/images/examples_barmodelmapper.png b/src/charts/doc/images/examples_barmodelmapper.png
new file mode 100644
index 00000000..6d41e5f5
--- /dev/null
+++ b/src/charts/doc/images/examples_barmodelmapper.png
Binary files differ
diff --git a/src/charts/doc/images/examples_boxplotchart.png b/src/charts/doc/images/examples_boxplotchart.png
new file mode 100644
index 00000000..6547a34b
--- /dev/null
+++ b/src/charts/doc/images/examples_boxplotchart.png
Binary files differ
diff --git a/src/charts/doc/images/examples_callout.png b/src/charts/doc/images/examples_callout.png
new file mode 100644
index 00000000..cc597110
--- /dev/null
+++ b/src/charts/doc/images/examples_callout.png
Binary files differ
diff --git a/src/charts/doc/images/examples_chartthemes_blue_cerulean.png b/src/charts/doc/images/examples_chartthemes_blue_cerulean.png
new file mode 100644
index 00000000..69ac3793
--- /dev/null
+++ b/src/charts/doc/images/examples_chartthemes_blue_cerulean.png
Binary files differ
diff --git a/src/charts/doc/images/examples_chartthemes_brown_sand.png b/src/charts/doc/images/examples_chartthemes_brown_sand.png
new file mode 100644
index 00000000..ff5157a9
--- /dev/null
+++ b/src/charts/doc/images/examples_chartthemes_brown_sand.png
Binary files differ
diff --git a/src/charts/doc/images/examples_chartthemes_light.png b/src/charts/doc/images/examples_chartthemes_light.png
new file mode 100644
index 00000000..e6a64992
--- /dev/null
+++ b/src/charts/doc/images/examples_chartthemes_light.png
Binary files differ
diff --git a/src/charts/doc/images/examples_customchart.png b/src/charts/doc/images/examples_customchart.png
new file mode 100644
index 00000000..c416ef54
--- /dev/null
+++ b/src/charts/doc/images/examples_customchart.png
Binary files differ
diff --git a/src/charts/doc/images/examples_datetimeaxis.png b/src/charts/doc/images/examples_datetimeaxis.png
new file mode 100644
index 00000000..cedda80a
--- /dev/null
+++ b/src/charts/doc/images/examples_datetimeaxis.png
Binary files differ
diff --git a/src/charts/doc/images/examples_donutbreakdown.png b/src/charts/doc/images/examples_donutbreakdown.png
new file mode 100644
index 00000000..a0569239
--- /dev/null
+++ b/src/charts/doc/images/examples_donutbreakdown.png
Binary files differ
diff --git a/src/charts/doc/images/examples_donutchart.png b/src/charts/doc/images/examples_donutchart.png
new file mode 100644
index 00000000..5eaf3fa3
--- /dev/null
+++ b/src/charts/doc/images/examples_donutchart.png
Binary files differ
diff --git a/src/charts/doc/images/examples_dynamicspline1.png b/src/charts/doc/images/examples_dynamicspline1.png
new file mode 100644
index 00000000..bcee80ed
--- /dev/null
+++ b/src/charts/doc/images/examples_dynamicspline1.png
Binary files differ
diff --git a/src/charts/doc/images/examples_dynamicspline2.png b/src/charts/doc/images/examples_dynamicspline2.png
new file mode 100644
index 00000000..595c38b1
--- /dev/null
+++ b/src/charts/doc/images/examples_dynamicspline2.png
Binary files differ
diff --git a/src/charts/doc/images/examples_horizontalbarchart.png b/src/charts/doc/images/examples_horizontalbarchart.png
new file mode 100644
index 00000000..dfa50d60
--- /dev/null
+++ b/src/charts/doc/images/examples_horizontalbarchart.png
Binary files differ
diff --git a/src/charts/doc/images/examples_horizontalpercentbarchart.png b/src/charts/doc/images/examples_horizontalpercentbarchart.png
new file mode 100644
index 00000000..726a715b
--- /dev/null
+++ b/src/charts/doc/images/examples_horizontalpercentbarchart.png
Binary files differ
diff --git a/src/charts/doc/images/examples_horizontalstackedbarchart.png b/src/charts/doc/images/examples_horizontalstackedbarchart.png
new file mode 100644
index 00000000..32806bb6
--- /dev/null
+++ b/src/charts/doc/images/examples_horizontalstackedbarchart.png
Binary files differ
diff --git a/src/charts/doc/images/examples_legend_detach.png b/src/charts/doc/images/examples_legend_detach.png
new file mode 100644
index 00000000..3376a4a0
--- /dev/null
+++ b/src/charts/doc/images/examples_legend_detach.png
Binary files differ
diff --git a/src/charts/doc/images/examples_legend_detach2.png b/src/charts/doc/images/examples_legend_detach2.png
new file mode 100644
index 00000000..5cc33819
--- /dev/null
+++ b/src/charts/doc/images/examples_legend_detach2.png
Binary files differ
diff --git a/src/charts/doc/images/examples_legendmarkers.png b/src/charts/doc/images/examples_legendmarkers.png
new file mode 100644
index 00000000..ac0ffef1
--- /dev/null
+++ b/src/charts/doc/images/examples_legendmarkers.png
Binary files differ
diff --git a/src/charts/doc/images/examples_lineandbar.png b/src/charts/doc/images/examples_lineandbar.png
new file mode 100644
index 00000000..0d7a66d7
--- /dev/null
+++ b/src/charts/doc/images/examples_lineandbar.png
Binary files differ
diff --git a/src/charts/doc/images/examples_linechart.png b/src/charts/doc/images/examples_linechart.png
new file mode 100644
index 00000000..57177907
--- /dev/null
+++ b/src/charts/doc/images/examples_linechart.png
Binary files differ
diff --git a/src/charts/doc/images/examples_logvalueaxis.png b/src/charts/doc/images/examples_logvalueaxis.png
new file mode 100644
index 00000000..36ae562d
--- /dev/null
+++ b/src/charts/doc/images/examples_logvalueaxis.png
Binary files differ
diff --git a/src/charts/doc/images/examples_modeldata.png b/src/charts/doc/images/examples_modeldata.png
new file mode 100644
index 00000000..aa301fb9
--- /dev/null
+++ b/src/charts/doc/images/examples_modeldata.png
Binary files differ
diff --git a/src/charts/doc/images/examples_multiaxis.png b/src/charts/doc/images/examples_multiaxis.png
new file mode 100644
index 00000000..4e6c23f2
--- /dev/null
+++ b/src/charts/doc/images/examples_multiaxis.png
Binary files differ
diff --git a/src/charts/doc/images/examples_nesteddonuts.png b/src/charts/doc/images/examples_nesteddonuts.png
new file mode 100644
index 00000000..bc8825c8
--- /dev/null
+++ b/src/charts/doc/images/examples_nesteddonuts.png
Binary files differ
diff --git a/src/charts/doc/images/examples_percentbarchart.png b/src/charts/doc/images/examples_percentbarchart.png
new file mode 100644
index 00000000..74d7389b
--- /dev/null
+++ b/src/charts/doc/images/examples_percentbarchart.png
Binary files differ
diff --git a/src/charts/doc/images/examples_percentbarchart_legend.png b/src/charts/doc/images/examples_percentbarchart_legend.png
new file mode 100644
index 00000000..ed1ed4f6
--- /dev/null
+++ b/src/charts/doc/images/examples_percentbarchart_legend.png
Binary files differ
diff --git a/src/charts/doc/images/examples_piechart.png b/src/charts/doc/images/examples_piechart.png
new file mode 100644
index 00000000..4977fa33
--- /dev/null
+++ b/src/charts/doc/images/examples_piechart.png
Binary files differ
diff --git a/src/charts/doc/images/examples_piechartdrill1.png b/src/charts/doc/images/examples_piechartdrill1.png
new file mode 100644
index 00000000..cdc56a9d
--- /dev/null
+++ b/src/charts/doc/images/examples_piechartdrill1.png
Binary files differ
diff --git a/src/charts/doc/images/examples_piechartdrill2.png b/src/charts/doc/images/examples_piechartdrill2.png
new file mode 100644
index 00000000..384acda8
--- /dev/null
+++ b/src/charts/doc/images/examples_piechartdrill2.png
Binary files differ
diff --git a/src/charts/doc/images/examples_polarchart.png b/src/charts/doc/images/examples_polarchart.png
new file mode 100644
index 00000000..55f922c9
--- /dev/null
+++ b/src/charts/doc/images/examples_polarchart.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlaxes1.png b/src/charts/doc/images/examples_qmlaxes1.png
new file mode 100644
index 00000000..3494766a
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlaxes1.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlaxes2.png b/src/charts/doc/images/examples_qmlaxes2.png
new file mode 100644
index 00000000..d6c9164d
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlaxes2.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlaxes3.png b/src/charts/doc/images/examples_qmlaxes3.png
new file mode 100644
index 00000000..eeef7bfa
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlaxes3.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlboxplot.png b/src/charts/doc/images/examples_qmlboxplot.png
new file mode 100644
index 00000000..f9ddc489
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlboxplot.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlchart1.png b/src/charts/doc/images/examples_qmlchart1.png
new file mode 100644
index 00000000..6a3c7812
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlchart1.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlchart10.png b/src/charts/doc/images/examples_qmlchart10.png
new file mode 100644
index 00000000..5fdd744c
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlchart10.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlchart11.png b/src/charts/doc/images/examples_qmlchart11.png
new file mode 100644
index 00000000..663967e7
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlchart11.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlchart12.png b/src/charts/doc/images/examples_qmlchart12.png
new file mode 100644
index 00000000..e00465ad
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlchart12.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlchart2.png b/src/charts/doc/images/examples_qmlchart2.png
new file mode 100644
index 00000000..36a7873b
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlchart2.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlchart3.png b/src/charts/doc/images/examples_qmlchart3.png
new file mode 100644
index 00000000..74e3299c
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlchart3.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlchart4.png b/src/charts/doc/images/examples_qmlchart4.png
new file mode 100644
index 00000000..7b0d96a3
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlchart4.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlchart5.png b/src/charts/doc/images/examples_qmlchart5.png
new file mode 100644
index 00000000..129a4e90
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlchart5.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlchart6.png b/src/charts/doc/images/examples_qmlchart6.png
new file mode 100644
index 00000000..6968ffe3
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlchart6.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlchart7.png b/src/charts/doc/images/examples_qmlchart7.png
new file mode 100644
index 00000000..acf29aed
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlchart7.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlchart8.png b/src/charts/doc/images/examples_qmlchart8.png
new file mode 100644
index 00000000..d1671758
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlchart8.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlchart9.png b/src/charts/doc/images/examples_qmlchart9.png
new file mode 100644
index 00000000..1ebbc7dc
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlchart9.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlcustomizations.png b/src/charts/doc/images/examples_qmlcustomizations.png
new file mode 100644
index 00000000..d28f5c80
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlcustomizations.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlcustomlegend1.png b/src/charts/doc/images/examples_qmlcustomlegend1.png
new file mode 100644
index 00000000..7f235934
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlcustomlegend1.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlcustomlegend2.png b/src/charts/doc/images/examples_qmlcustomlegend2.png
new file mode 100644
index 00000000..184615e9
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlcustomlegend2.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlcustomlegend3.png b/src/charts/doc/images/examples_qmlcustomlegend3.png
new file mode 100644
index 00000000..6f0c81c4
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlcustomlegend3.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlcustommodel.png b/src/charts/doc/images/examples_qmlcustommodel.png
new file mode 100644
index 00000000..1bf610f8
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlcustommodel.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlf1legends.png b/src/charts/doc/images/examples_qmlf1legends.png
new file mode 100644
index 00000000..789d45ab
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlf1legends.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmloscilloscope.png b/src/charts/doc/images/examples_qmloscilloscope.png
new file mode 100644
index 00000000..32e28ffb
--- /dev/null
+++ b/src/charts/doc/images/examples_qmloscilloscope.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlpiechart.png b/src/charts/doc/images/examples_qmlpiechart.png
new file mode 100644
index 00000000..bd347551
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlpiechart.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlpolarchart1.png b/src/charts/doc/images/examples_qmlpolarchart1.png
new file mode 100644
index 00000000..8cb3e8d1
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlpolarchart1.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlpolarchart2.png b/src/charts/doc/images/examples_qmlpolarchart2.png
new file mode 100644
index 00000000..02bcd778
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlpolarchart2.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlpolarchart3.png b/src/charts/doc/images/examples_qmlpolarchart3.png
new file mode 100644
index 00000000..184f5c9e
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlpolarchart3.png
Binary files differ
diff --git a/src/charts/doc/images/examples_qmlweather.png b/src/charts/doc/images/examples_qmlweather.png
new file mode 100644
index 00000000..feab0364
--- /dev/null
+++ b/src/charts/doc/images/examples_qmlweather.png
Binary files differ
diff --git a/src/charts/doc/images/examples_scatterchart.png b/src/charts/doc/images/examples_scatterchart.png
new file mode 100644
index 00000000..41900f66
--- /dev/null
+++ b/src/charts/doc/images/examples_scatterchart.png
Binary files differ
diff --git a/src/charts/doc/images/examples_scatterinteractions.png b/src/charts/doc/images/examples_scatterinteractions.png
new file mode 100644
index 00000000..cd4c78c0
--- /dev/null
+++ b/src/charts/doc/images/examples_scatterinteractions.png
Binary files differ
diff --git a/src/charts/doc/images/examples_splinechart.png b/src/charts/doc/images/examples_splinechart.png
new file mode 100644
index 00000000..733ddb17
--- /dev/null
+++ b/src/charts/doc/images/examples_splinechart.png
Binary files differ
diff --git a/src/charts/doc/images/examples_stackedbarchart.png b/src/charts/doc/images/examples_stackedbarchart.png
new file mode 100644
index 00000000..0c721305
--- /dev/null
+++ b/src/charts/doc/images/examples_stackedbarchart.png
Binary files differ
diff --git a/src/charts/doc/images/examples_stackedbarchartdrilldown1.png b/src/charts/doc/images/examples_stackedbarchartdrilldown1.png
new file mode 100644
index 00000000..9f128b6f
--- /dev/null
+++ b/src/charts/doc/images/examples_stackedbarchartdrilldown1.png
Binary files differ
diff --git a/src/charts/doc/images/examples_stackedbarchartdrilldown2.png b/src/charts/doc/images/examples_stackedbarchartdrilldown2.png
new file mode 100644
index 00000000..67f8afbc
--- /dev/null
+++ b/src/charts/doc/images/examples_stackedbarchartdrilldown2.png
Binary files differ
diff --git a/src/charts/doc/images/examples_temperaturerecords.png b/src/charts/doc/images/examples_temperaturerecords.png
new file mode 100644
index 00000000..ce54eede
--- /dev/null
+++ b/src/charts/doc/images/examples_temperaturerecords.png
Binary files differ
diff --git a/src/charts/doc/images/examples_zoomlinechart1.png b/src/charts/doc/images/examples_zoomlinechart1.png
new file mode 100644
index 00000000..9162035e
--- /dev/null
+++ b/src/charts/doc/images/examples_zoomlinechart1.png
Binary files differ
diff --git a/src/charts/doc/images/examples_zoomlinechart2.png b/src/charts/doc/images/examples_zoomlinechart2.png
new file mode 100644
index 00000000..2a971311
--- /dev/null
+++ b/src/charts/doc/images/examples_zoomlinechart2.png
Binary files differ
diff --git a/src/charts/doc/images/horBar.png b/src/charts/doc/images/horBar.png
new file mode 100644
index 00000000..100fe91c
--- /dev/null
+++ b/src/charts/doc/images/horBar.png
Binary files differ
diff --git a/src/charts/doc/images/piechart_customization.png b/src/charts/doc/images/piechart_customization.png
new file mode 100644
index 00000000..d52ad583
--- /dev/null
+++ b/src/charts/doc/images/piechart_customization.png
Binary files differ
diff --git a/src/charts/doc/images/qcharts.png b/src/charts/doc/images/qcharts.png
new file mode 100644
index 00000000..69098333
--- /dev/null
+++ b/src/charts/doc/images/qcharts.png
Binary files differ
diff --git a/src/charts/doc/images/qt-logo.png b/src/charts/doc/images/qt-logo.png
new file mode 100644
index 00000000..14ddf2a0
--- /dev/null
+++ b/src/charts/doc/images/qt-logo.png
Binary files differ
diff --git a/src/charts/doc/qtcharts.qdocconf b/src/charts/doc/qtcharts.qdocconf
new file mode 100644
index 00000000..5fb7181c
--- /dev/null
+++ b/src/charts/doc/qtcharts.qdocconf
@@ -0,0 +1,66 @@
+include($QT_INSTALL_DOCS/global/macros.qdocconf)
+include($QT_INSTALL_DOCS/global/qt-cpp-defines.qdocconf)
+include($QT_INSTALL_DOCS/global/compat.qdocconf)
+include($QT_INSTALL_DOCS/global/fileextensions.qdocconf)
+include($QT_INSTALL_DOCS/global/qt-html-templates-offline.qdocconf)
+
+project = Qt Charts
+description = Qt Charts Reference Documentation
+version = 2.0.0
+
+sourcedirs += ..
+headerdirs += ..
+exampledirs += ../../../examples/charts \
+ snippets
+imagedirs += images
+examplesinstallpath = charts
+
+indexes += $QT_INSTALL_DOCS/qtcore/qtcore.index \
+ $QT_INSTALL_DOCS/qtgui/qtgui.index \
+ $QT_INSTALL_DOCS/qtqml/qtqml.index \
+ $QT_INSTALL_DOCS/qtquick/qtquick.index \
+ $QT_INSTALL_DOCS/qtmultimedia/qtmultimedia.index
+
+Cpp.ignoretokens = Q_INVOKABLE \
+ QT_CHARTS_EXPORT \
+ QT_CHARTS_END_NAMESPACE \
+ QT_CHARTS_BEGIN_NAMESPACE
+
+qhp.projects = QtCharts
+qhp.QtCharts.file = qtcharts.qhp
+qhp.QtCharts.namespace = com.digia.qtcharts.200
+qhp.QtCharts.virtualFolder = qtcharts
+qhp.QtCharts.indexTitle = Qt Charts Reference
+qhp.QtCharts.indexRoot =
+
+qhp.QtCharts.filterAttributes = qtcharts 2.0.0 qtrefdoc
+qhp.QtCharts.customFilters.Qt.name = QtCharts 2.0.0
+qhp.QtCharts.customFilters.Qt.filterAttributes = qtcharts 2.0.0
+
+qhp.QtCharts.subprojects = gettingstarted classes types examples
+
+qhp.QtCharts.subprojects.gettingstarted.title = Getting Started
+qhp.QtCharts.subprojects.gettingstarted.indexTitle = Qt Charts Getting Started
+qhp.QtCharts.subprojects.gettingstarted.selectors = fake:page
+qhp.QtCharts.subprojects.gettingstarted.sortPages = true
+
+qhp.QtCharts.subprojects.classes.title = C++ Classes
+qhp.QtCharts.subprojects.classes.indexTitle = Qt Charts C++ Classes
+qhp.QtCharts.subprojects.classes.selectors = class
+qhp.QtCharts.subprojects.classes.sortPages = true
+
+qhp.QtCharts.subprojects.types.title = QML Types
+qhp.QtCharts.subprojects.types.indexTitle = Qt Charts QML Types
+qhp.QtCharts.subprojects.types.selectors = fake:qmlclass
+qhp.QtCharts.subprojects.types.sortPages = true
+
+qhp.QtCharts.subprojects.examples.title = Examples
+qhp.QtCharts.subprojects.examples.indexTitle = Qt Charts Examples
+qhp.QtCharts.subprojects.examples.selectors = fake:example
+qhp.QtCharts.subprojects.examples.sortPages = true
+
+navigation.landingpage = Qt Charts
+navigation.cppclassespage = Qt Charts C++ Classes
+navigation.qmltypespage = Qt Charts QML Types
+
+buildversion = Qt Charts $QT_VERSION Reference Documentation
diff --git a/src/charts/doc/snippets/doc_src_qmlcharts.cpp b/src/charts/doc/snippets/doc_src_qmlcharts.cpp
new file mode 100644
index 00000000..3047db7a
--- /dev/null
+++ b/src/charts/doc/snippets/doc_src_qmlcharts.cpp
@@ -0,0 +1,21 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 QtCharts 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
+**
+****************************************************************************/
+
+//! [0]
+import QtCharts 2.0
+//! [0]
diff --git a/src/charts/doc/snippets/doc_src_qtcharts.cpp b/src/charts/doc/snippets/doc_src_qtcharts.cpp
new file mode 100644
index 00000000..d841bb88
--- /dev/null
+++ b/src/charts/doc/snippets/doc_src_qtcharts.cpp
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 QtCharts 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
+**
+****************************************************************************/
+
+//! [0]
+#include <QtCharts>
+
+using namespace QtCharts;
+//! [0]
+
+//! [1]
+qmake CONFIG+=static
+make
+make install
+//! [1]
+
+//! [2]
+qmake
+make
+./qmlpolarchart
+//! [2]
diff --git a/src/charts/doc/snippets/doc_src_qtcharts.pro b/src/charts/doc/snippets/doc_src_qtcharts.pro
new file mode 100644
index 00000000..819b1c9c
--- /dev/null
+++ b/src/charts/doc/snippets/doc_src_qtcharts.pro
@@ -0,0 +1,21 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 QtCharts 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
+**
+****************************************************************************/
+
+#! [0]
+QT += charts
+#! [0]
diff --git a/src/charts/doc/src/examples-areachart.qdoc b/src/charts/doc/src/examples-areachart.qdoc
new file mode 100644
index 00000000..f399adbe
--- /dev/null
+++ b/src/charts/doc/src/examples-areachart.qdoc
@@ -0,0 +1,30 @@
+/*!
+ \example areachart
+ \title AreaChart Example
+ \ingroup qtcharts_examples
+
+ \brief The example shows how to create a simple area chart.
+
+ \image examples_areachart.png
+
+ To create area charts, we need two QLineSeries instances. They are going to define the upper and lower boundary of the area.
+
+ \snippet areachart/main.cpp 1
+
+ We add data to both series and use the stream operator.
+
+ \snippet areachart/main.cpp 2
+
+ Now we create a QAreaSeries instance using two line series objects. We set the custom gradient fill and width of the outline.
+
+ \snippet areachart/main.cpp 3
+
+ Last we create the QChartView instance, set the title, set anti-aliasing, and add the area series. We also create the default axes and specify the ranges on them.
+
+ \snippet areachart/main.cpp 4
+
+ The chart is ready to be shown.
+
+ \snippet areachart/main.cpp 5
+
+*/
diff --git a/src/charts/doc/src/examples-audio.qdoc b/src/charts/doc/src/examples-audio.qdoc
new file mode 100644
index 00000000..2a3a98ec
--- /dev/null
+++ b/src/charts/doc/src/examples-audio.qdoc
@@ -0,0 +1,8 @@
+/*!
+ \example audio
+ \title Audio example
+ \ingroup qtcharts_examples
+
+ \brief This example shows the drawing of dynamic data (microphone input).
+ \image examples_audio.png
+*/
diff --git a/src/charts/doc/src/examples-barchart.qdoc b/src/charts/doc/src/examples-barchart.qdoc
new file mode 100644
index 00000000..d217faac
--- /dev/null
+++ b/src/charts/doc/src/examples-barchart.qdoc
@@ -0,0 +1,47 @@
+/*!
+ \example barchart
+ \title BarChart Example
+ \ingroup qtcharts_examples
+
+ \brief The example shows how to create a bar chart.
+
+ BarChart shows the data in sets as separate bars, which are in categories.
+
+ \image examples_barchart.png
+
+ The barsets are used in the same way in all barcharts.
+ To illustrate the difference between various barcharts, we use the same data in the examples.
+ Data that the barchart visualizes, is defined by the QBarSet instances. Here we create the sets and append data
+ to them. The data is appended here with the << operator. Alternatively, the append method could be used.
+
+ \snippet barchart/main.cpp 1
+
+ We create the series and append the barsets to it. The series takes ownership of the barsets. The series groups the data from sets to categories.
+ First values of each set are grouped together at first category second value to second category and so on.
+
+ \snippet barchart/main.cpp 2
+
+ Here we create the chart object and add the series to it. We set the title for chart with setTitle and then turn on animations of the series by calling
+ setAnimationOptions(QChart::SeriesAnimations)
+
+ \snippet barchart/main.cpp 3
+
+ To have categories displayed on axis, we need to create a QBarCategoryAxis for that. Here we create a category axis with a list of categories and
+ set it to be the x-axis of the chart. The chart takes ownership of axis. For y-axis we use default axis, which is created and scaled to series data
+ by calling createDefaultAxes of the chart. Note that the call for createDefaultAxes must be before we set the category axis. Otherwise the default axis will
+ override the category axis.
+
+ \snippet barchart/main.cpp 4
+
+ We also want to show the legend. To do that, we get the legend pointer from the chart and set it to visible. We also place the legend to the bottom of the chart by setting its alignment to Qt::AlignBottom.
+
+ \snippet barchart/main.cpp 5
+
+ Finally we add the chart onto a view. We also turn on the antialiasing for the chartView.
+
+ \snippet barchart/main.cpp 6
+
+ The chart is ready to be shown. We set the chart to be central widget of the window. We also set the size for the chart window and show it.
+
+ \snippet barchart/main.cpp 7
+*/
diff --git a/src/charts/doc/src/examples-barmodelmapper.qdoc b/src/charts/doc/src/examples-barmodelmapper.qdoc
new file mode 100644
index 00000000..00d23326
--- /dev/null
+++ b/src/charts/doc/src/examples-barmodelmapper.qdoc
@@ -0,0 +1,58 @@
+/*!
+ \example barmodelmapper
+ \title BarModelMapper example
+ \ingroup qtcharts_examples
+
+ \brief This example shows how to use QAbstractItemModel derived model as the data for the bar
+ series.
+
+ \image examples_barmodelmapper.png
+
+ Let's start by creating an instance of CustomTableModel class.
+ The CustomTableModel class is derived from QAbstractTableModel, and it was created for the purpose of this example.
+ The constructor of this class populates the model's internal data store with the data required for our chart example.
+
+ \snippet barmodelmapper/tablewidget.cpp 1
+
+ We now have a model with data that we would like to display both on the chart and in a QTableView.
+ First, we create QTableView and tell it to use the model as a data source. To have the data presented nicely, the minimum width of the table view is set and its headers resize mode changed to stretch.
+
+ \snippet barmodelmapper/tablewidget.cpp 2
+
+ Now we need a QChart instance to display the same data on the chart.
+ We also enable animations. It makes it easier to see how a modification to the model's data affects the chart.
+
+ \snippet barmodelmapper/tablewidget.cpp 3
+
+ The first line of the code below creates new bar series. Variables firstRow and rowCount are used to define a custom model mapping.
+ Custom mapping allows to take only part of the data from the model. In this case data from 5 rows starting with the row with the index 3.
+ The following three lines create an instance of the QVBarModelMapper class and specify that the data for the bar sets should be taken from the model's columns with indexes from 1 to 4 (inclusive).
+ To create a connection between the series and the model we set both of those objects to QVBarModelMapper.
+
+ Finally the series is added to the chart.
+
+ \snippet barmodelmapper/tablewidget.cpp 4
+
+ To show in QTableView which data corresponds with which bar set, this example uses table coloring.
+ When series is added to the chart, it is assigned a color based on the currently selected theme.
+ Code below extracts that color from the series and uses it to create colored QTableView.
+ Coloring of the view is not a part of the QChart functionality.
+
+ \snippet barmodelmapper/tablewidget.cpp 5
+
+ We would like to have categories placed on the chart's axis that describe what the data means.
+ Next snippet shows how to do that.
+
+ \snippet barmodelmapper/tablewidget.cpp 6
+
+ To avoid setting up the QGraphicsScene we use the QChartView class that does it for us. The QChart object pointer is used as a parameter of the QChartView constructor.
+ To make the render look nicer Antialiasing is turned on and the minimum size of the chartView widget is set.
+
+ \snippet barmodelmapper/tablewidget.cpp 7
+
+ Finally, we place both widgets in a layout and use the layout as the application layout.
+
+ \snippet barmodelmapper/tablewidget.cpp 8
+
+ The application is ready. Try modifying the data in the table view and see how it affects the chart.
+*/
diff --git a/src/charts/doc/src/examples-boxplotchart.qdoc b/src/charts/doc/src/examples-boxplotchart.qdoc
new file mode 100644
index 00000000..c4d1eea4
--- /dev/null
+++ b/src/charts/doc/src/examples-boxplotchart.qdoc
@@ -0,0 +1,78 @@
+/*!
+ \example boxplotchart
+ \title Box and Whiskers Example
+ \ingroup qtcharts_examples
+
+ \brief The example shows how to create a box-and-whiskers chart.
+
+ The example also shows how to read the non-continuous data from a file,
+ arrange it and find medians needed for box-and-whiskers plotting.
+
+ \image examples_boxplotchart.png
+
+ To show the share deviation of two companies we start by creating two QBoxPlotSeries to handle monthly data.
+
+ \snippet boxplotchart/main.cpp 1
+
+ QFile class is used to open a text file where the non-continuous data is kept. The BoxDataReader is an auxiliary class for
+ reading the text file and finding the extreme and median values from the data. The BoxDataReader is explained in more detail later.
+ The method readBox reads the values and sets them to the QBoxSet item which the method returns for the caller. The returned QBoxSet
+ item is added to the series.
+
+ \snippet boxplotchart/main.cpp 2
+
+ In this section a second file is opened for reading the data for the second company.
+
+ \snippet boxplotchart/main.cpp 3
+
+ In this code snippet a new QChart instance is created and previously created series are added to it. The title is also defined and
+ animation is set to be SeriesAnimation.
+
+ \snippet boxplotchart/main.cpp 4
+
+ Here we ask the chart to create default axes for our presentation. We also set the range for the vertical axis by querying the pointer
+ for the axis from the chart, and then setting the min and max for that axis.
+
+ \snippet boxplotchart/main.cpp 5
+
+ In this section we set the legends to be visible and place them at the bottom of the chart.
+
+ \snippet boxplotchart/main.cpp 6
+
+ Finally, we add the chart onto a view. We also turn on the antialiasing for the chartView.
+
+ \snippet boxplotchart/main.cpp 7
+
+ The chart is ready to be shown. We set the chart to be the central widget of the window.
+ We also set the size for the chart window and show it.
+
+ \snippet boxplotchart/main.cpp 8
+
+ Here the method readBox is explained in detail. Firstly, a line is read from the file and lines starting with # are rejected
+ since they are considered as comment lines.
+
+ \snippet boxplotchart/boxdatareader.cpp 1
+
+ In this file the data is arranged as number, space, number, or space. On this snippet the line is split into single number strings which
+ are stored on QStringList.
+
+ \snippet boxplotchart/boxdatareader.cpp 2
+
+ The sortedList will hold the numbers in continuous order and in this code segment we show how to do it. First the sortedList is cleared and numbers
+ are read from the strList and stored into sortedList in double format. The qSort method arranges the sortedList into continuous order
+ starting from the smallest.
+
+ \snippet boxplotchart/boxdatareader.cpp 3
+
+ Below you will find a code sample showing how to select extremes and medians from the continuous data. Firstly a new QBoxSet is created.
+ Lower and upper extremes are simple to select; they are just first and last items on the sortedList. For medians we use a helper
+ method findMedian which is explained later. For the median from the upper half we need to adjust the begin number if the
+ amount of the numbers is even or uneven. The end number for lower half comes naturally from int rounding.
+
+ \snippet boxplotchart/boxdatareader.cpp 4
+
+ Below you will find the code sample for the method findMedian. If the amount of numbers is uneven we select the number from
+ the middle. For even amount numbers we take two numbers from the middle and calculate the mean value.
+
+ \snippet boxplotchart/boxdatareader.cpp 5
+*/
diff --git a/src/charts/doc/src/examples-callout.qdoc b/src/charts/doc/src/examples-callout.qdoc
new file mode 100644
index 00000000..1f5f8dcc
--- /dev/null
+++ b/src/charts/doc/src/examples-callout.qdoc
@@ -0,0 +1,15 @@
+/*!
+ \example callout
+ \title Callout example
+ \ingroup qtcharts_examples
+
+ \brief This example shows how to draw an additional element (a callout) on top of the chart.
+ \image examples_callout.png
+
+ QChart class provides two methods that map between the scene coordinates and the series domain
+ (defined by the axes ranges).
+
+ QPointF QChart::mapToPosition(const QPointF &value, QAbstractSeries *series)
+
+ QPointF QChart::mapToValue(const QPointF &position, QAbstractSeries *series)
+*/
diff --git a/src/charts/doc/src/examples-chartthemes.qdoc b/src/charts/doc/src/examples-chartthemes.qdoc
new file mode 100644
index 00000000..d6121435
--- /dev/null
+++ b/src/charts/doc/src/examples-chartthemes.qdoc
@@ -0,0 +1,15 @@
+/*!
+ \example chartthemes
+ \title Chart themes example
+ \ingroup qtcharts_examples
+
+ \brief The example shows the look and feel of the different built-in themes.
+
+ This example shows the look and feel of the different built-in themes for all supported chart
+ types. In order to give the result a more harmonious look, the background palette of the
+ application is customized to the theme selected.
+
+ \image examples_chartthemes_light.png
+ \image examples_chartthemes_brown_sand.png
+ \image examples_chartthemes_blue_cerulean.png
+*/
diff --git a/src/charts/doc/src/examples-customchart.qdoc b/src/charts/doc/src/examples-customchart.qdoc
new file mode 100644
index 00000000..4d1cee42
--- /dev/null
+++ b/src/charts/doc/src/examples-customchart.qdoc
@@ -0,0 +1,26 @@
+/*!
+ \example customchart
+ \title Custom Chart Example
+ \ingroup qtcharts_examples
+
+ \brief This example shows how to customize the appearance of the different elements on a chart.
+ \image examples_customchart.png
+
+ We begin by creating a simple line series and a chart object.
+ \snippet customchart/main.cpp 1
+
+ First we customize the series and the chart's title and background.
+ \snippet customchart/main.cpp 2
+
+ Then we customize the axes.
+ \snippet customchart/main.cpp 3
+
+ Then the axis label values and ranges. Once the axes are ready, we set them to be used by the chart.
+ \snippet customchart/main.cpp 4
+
+ Finally, we create a view containing the chart.
+ \snippet customchart/main.cpp 5
+
+ Now we are ready to show the chart on a main window.
+ \snippet customchart/main.cpp 6
+*/
diff --git a/src/charts/doc/src/examples-datetimeaxis.qdoc b/src/charts/doc/src/examples-datetimeaxis.qdoc
new file mode 100644
index 00000000..b667af4d
--- /dev/null
+++ b/src/charts/doc/src/examples-datetimeaxis.qdoc
@@ -0,0 +1,38 @@
+/*!
+ \example datetimeaxis
+ \title DateTimeAxis Example
+ \ingroup qtcharts_examples
+
+ \brief The example shows how to use QLineChart with QDateTimeAxis.
+
+ \image examples_datetimeaxis.png
+
+ To create line chart, QLineSeries instance is needed. Let's create one.
+
+ \snippet datetimeaxis/main.cpp 1
+
+ On the charts we will present how the number of sun spots changes in time. The data (from the Space Weather Prediction Center) is read from a text file.
+ In the snippet below, notice how the QDateTime::toMSecsSinceEpoch method is used to convert the QDateTime object into a number that can be passed to the QLineSeries append method.
+
+ \snippet datetimeaxis/main.cpp 2
+
+ To present the data on the chart we need the QChart instance. We add the series to it, hide the legend, create the default axes and set the title of the chart.
+
+ \snippet datetimeaxis/main.cpp 3
+
+ Since we use QLineSeries, calling createDefaultAxes will create QValueAxis both as X- and Y-axis. To use QDateTimeAxis we need to set it manually to the chart.
+ First, the instance of QDateTimeAxis is created, then the number of ticks to be shown is set. The number of sun spots is provided as an average for the month.
+ Therefore we don't need the axis labels to contain the information about the time and the day. This is achieved by setting a custom label format.
+ Please refer to the QDateTime::toString() method documentation to learn about the available format options.
+
+ \snippet datetimeaxis/main.cpp 4
+
+ Then we create a QChartView object with QChart as a parameter. This way we don't need to create the QGraphicsView scene ourselves. We also set the Antialiasing on to have the rendered lines look nicer.
+
+ \snippet datetimeaxis/main.cpp 5
+
+ The chart is ready to be shown.
+
+ \snippet datetimeaxis/main.cpp 6
+
+*/
diff --git a/src/charts/doc/src/examples-donutbreakdown.qdoc b/src/charts/doc/src/examples-donutbreakdown.qdoc
new file mode 100644
index 00000000..5586a81c
--- /dev/null
+++ b/src/charts/doc/src/examples-donutbreakdown.qdoc
@@ -0,0 +1,45 @@
+/*!
+ \example donutbreakdown
+ \title Donut chart breakdown example
+ \ingroup qtcharts_examples
+
+ \brief This example shows how to use create a donut breakdown chart using QPieSeries API.
+ \image examples_donutbreakdown.png
+
+ Let's start by defining some data for the chart.
+
+ \snippet donutbreakdown/main.cpp 1
+
+ Then we create a chart where we add the data. Note that this is our own chart derived from QChart.
+
+ \snippet donutbreakdown/main.cpp 2
+
+ Our own chart works in such a way that we create a main series in the constructor we create a main series,
+ which aggregates the data provided by the breakdown series. This is the piechart in the center.
+
+ \snippet donutbreakdown/donutbreakdownchart.cpp 1
+
+ When a breakdown series is added the data is used to create a slice in the main series and the
+ breakdown series itself is used to create a segment of a donut positioned so that it is aligned
+ with the corresponding slice in the main series.
+
+ \snippet donutbreakdown/donutbreakdownchart.cpp 2
+
+ Here's how the start and end angles for the donut segments are calculated.
+
+ \snippet donutbreakdown/donutbreakdownchart.cpp 3
+
+ The legend markers are customized to show the breakdown percentage. The markers for the main level slices are hidden.
+
+ \snippet donutbreakdown/donutbreakdownchart.cpp 4
+
+ Instead the main level slices show the percentage on the label.
+
+ \snippet donutbreakdown/mainslice.cpp 1
+ \snippet donutbreakdown/mainslice.cpp 2
+
+ Now that we have our chart defined, we can finally create a QChartView and show the chart.
+
+ \snippet donutbreakdown/main.cpp 3
+
+*/
diff --git a/src/charts/doc/src/examples-donutchart.qdoc b/src/charts/doc/src/examples-donutchart.qdoc
new file mode 100644
index 00000000..4aa0d8b8
--- /dev/null
+++ b/src/charts/doc/src/examples-donutchart.qdoc
@@ -0,0 +1,9 @@
+/*!
+ \example donutchart
+ \title Donutchart Example
+ \ingroup qtcharts_examples
+
+ \brief This example shows how to create a simple donut chart, and do some customizations to
+ a slice.
+ \image examples_donutchart.png
+*/
diff --git a/src/charts/doc/src/examples-dynamicspline.qdoc b/src/charts/doc/src/examples-dynamicspline.qdoc
new file mode 100644
index 00000000..60814a6f
--- /dev/null
+++ b/src/charts/doc/src/examples-dynamicspline.qdoc
@@ -0,0 +1,10 @@
+/*!
+ \example dynamicspline
+ \title Dynamic spline example
+ \ingroup qtcharts_examples
+
+ \brief This example shows how to draw dynamic data.
+
+ \image examples_dynamicspline1.png
+ \image examples_dynamicspline2.png
+*/
diff --git a/src/charts/doc/src/examples-horizontalbarchart.qdoc b/src/charts/doc/src/examples-horizontalbarchart.qdoc
new file mode 100644
index 00000000..3ec69192
--- /dev/null
+++ b/src/charts/doc/src/examples-horizontalbarchart.qdoc
@@ -0,0 +1,50 @@
+/*!
+ \example horizontalbarchart
+ \title HorizontalBarChart Example
+ \ingroup qtcharts_examples
+
+ \brief The example shows how to create a horizontal bar chart.
+
+ QHorizontalBarChart shows the data in sets as separate bars, which are grouped in categories. QHorizontalBarChart works just like
+ QBarChart, except that the bars are drawn horizontally on the chart.
+
+ \image examples_horizontalbarchart.png
+
+ The bar sets are used in the same way in all bar charts.
+ To illustrate the difference between various bar charts, we use the same data in all examples.
+ Data that bar chart visualizes, is defined by QBarSet instances. Here we create the sets and append data
+ to them. The data is appended here with << operator. Alternatively, the append method could also be used.
+
+ \snippet horizontalbarchart/main.cpp 1
+
+ We create the series and append the bar sets to it. The series takes ownership of the barsets. The series groups the data from sets to categories.
+ The first values of each set are grouped together in the first category; the second values in the second category, and so on.
+
+ \snippet horizontalbarchart/main.cpp 2
+
+ Here we create the chart object and add the series to it. We set the title for chart with setTitle and then turn on animations of the series by calling
+ setAnimationOptions(QChart::SeriesAnimations).
+
+ \snippet horizontalbarchart/main.cpp 3
+
+ To have the categories displayed on axis, we need to create a QBarCategoryAxis. Here we create a category axis with a list of categories and
+ set it to be the y-axis of the chart. The chart takes ownership of axis. For the x-axis we use the default axis, which is created and scaled to series data
+ by calling createDefaultAxes of the chart. Note that the call for createDefaultAxes must be done before we set the category axis. Otherwise the default axis will
+ override the category axis.
+
+ \snippet horizontalbarchart/main.cpp 4
+
+ We also want to show the legend. To do so, we get the legend pointer from chart and set it to visible. We also place the legend to the bottom of the chart by setting its alignment
+ to Qt::AlignBottom.
+
+ \snippet horizontalbarchart/main.cpp 5
+
+ Finally we add the chart onto a view. We also turn on the antialiasing for the chartView.
+
+ \snippet horizontalbarchart/main.cpp 6
+
+ The chart is ready to be shown. We set the chart to be the central widget of the window.
+ We also set the size for the chart window and show it.
+
+ \snippet horizontalbarchart/main.cpp 7
+*/
diff --git a/src/charts/doc/src/examples-horizontalpercentbarchart.qdoc b/src/charts/doc/src/examples-horizontalpercentbarchart.qdoc
new file mode 100644
index 00000000..f3e79353
--- /dev/null
+++ b/src/charts/doc/src/examples-horizontalpercentbarchart.qdoc
@@ -0,0 +1,56 @@
+/*!
+ \example horizontalpercentbarchart
+ \title HorizontalPercentBarChart Example
+ \ingroup qtcharts_examples
+
+ \brief The example shows how to create a simple horizontal percent bar chart.
+
+ The horizontal percent bar chart shows the data in a set as a percentage of
+ all sets per category.
+
+ Creating a horizontal percent bar chart is just like creating a regular \l {BarChart Example} {bar chart}, except that for a
+ horizontal percent bar chart, we use the QHorizontalPercentBarSeries api instead of QBarSeries. Also, in the
+ \l {BarChart Example} {bar chart}, we used a nice numbers algorithm to make the y-axis numbering look better. With
+ the percent bar chart there is no need for that, because the maximum y-axis value is always 100.
+
+ \image examples_horizontalpercentbarchart.png
+
+ The barsets are used in same way in all barcharts.
+ To illustrate the difference between various barcharts, we use same data in examples.
+ The data which the bar chart visualizes is defined by QBarSet instances. Here we create the sets and append data
+ to them. The data is appended here with << operator. Alternatively the append method could be used.
+
+ \snippet horizontalpercentbarchart/main.cpp 1
+
+ We create the series and append the bar sets to it. The series takes ownership of the barsets. The series groups the data from sets to categories.
+ The first values of each set are grouped together in the first category, the second value in the second category etc.
+
+ \snippet horizontalpercentbarchart/main.cpp 2
+
+ Here we create the chart object and add the series to it. We set the title for chart with setTitle and then turn on animations of the series by calling
+ setAnimationOptions(QChart::SeriesAnimations)
+
+ \snippet horizontalpercentbarchart/main.cpp 3
+
+ To have the categories displayed on an axis, we need to create a QBarCategoryAxis first. Here we create a category axis with a list of categories and
+ set it to be the y-axis of the chart. The chart takes ownership of the axis. For the x-axis we use the default axis, which is created and scaled to series data
+ by calling createDefaultAxes of the chart. Note that createDefaultAxes must be called before we set the category axis. Otherwise the default axis will
+ override the category axis.
+
+ \snippet horizontalpercentbarchart/main.cpp 4
+
+ We also want to show the legend. To do that, we get the legend pointer from the chart
+ and set it to visible. We also place the legend to bottom of the chart by setting its
+ alignment to Qt::AlignBottom.
+
+ \snippet horizontalpercentbarchart/main.cpp 5
+
+ Finally, we add the chart onto a view. We also turn on the antialiasing for the chartView.
+
+ \snippet horizontalpercentbarchart/main.cpp 6
+
+ The chart is ready to be shown. We set the chart to be the central widget of the window.
+ We also set the size for the chart window and show it.
+
+ \snippet horizontalpercentbarchart/main.cpp 7
+*/
diff --git a/src/charts/doc/src/examples-horizontalstackedbarchart.qdoc b/src/charts/doc/src/examples-horizontalstackedbarchart.qdoc
new file mode 100644
index 00000000..19e1d1ba
--- /dev/null
+++ b/src/charts/doc/src/examples-horizontalstackedbarchart.qdoc
@@ -0,0 +1,53 @@
+/*!
+ \example horizontalstackedbarchart
+ \title HorizontalStackedBarChart Example
+ \ingroup qtcharts_examples
+
+ \brief The example shows how to create a simple stacked horizontal bar chart.
+
+ The stacked bar chart shows the data in sets as bars that are
+ stacked on top of each other. The stacking is done per category.
+ Creating a stacked horizontal bar chart is just like creating a regular \l {BarChart Example} {bar chart}, except that for a
+ stacked horizontal bar chart, we use the QHorizontalStackedBarSeries api instead of QBarSeries.
+
+ \image examples_horizontalstackedbarchart.png
+
+ The bar sets are used in same way in all bar charts.
+ To illustrate the difference between various barcharts, we use the same data in all examples.
+ The data that barchart visualizes, is defined by the QBarSet instances. Here we create the sets and append data
+ to them. The data is appended here with the << operator. Alternatively, the append method could also be used.
+
+ \snippet horizontalstackedbarchart/main.cpp 1
+
+ We create the series and append the bar sets to it. The series takes ownership of the bar sets. The series groups the data from sets to categories.
+ The first values of each set are grouped together in the first category, the second values in the second category and so on.
+
+ \snippet horizontalstackedbarchart/main.cpp 2
+
+ Here we create the chart object and add the series to it. We set the title for the chart with setTitle, and then turn on the animations of the series by calling
+ setAnimationOptions(QChart::SeriesAnimations).
+
+ \snippet horizontalstackedbarchart/main.cpp 3
+
+ To have categories displayed on an axis, we need to create a QBarCategoryAxis. Here we create a category axis with a list of categories and
+ set it to be the y-axis of the chart. The chart takes ownership of the axis. For the x-axis we use the default axis, which is created and scaled to series data
+ by calling createDefaultAxes of the chart. Note that the call for createDefaultAxes must be before we set the category axis. Otherwise the default axis will
+ override the category axis.
+
+ \snippet horizontalstackedbarchart/main.cpp 4
+
+ We also want to show the legend. To do that, we get the legend pointer from the chart and
+ set it to visible. We also place the legend to the bottom of the chart by setting its alignment
+ to Qt::AlignBottom.
+
+ \snippet horizontalstackedbarchart/main.cpp 5
+
+ Finally we add the chart onto a view. We also turn on the antialiasing for the chartView.
+
+ \snippet horizontalstackedbarchart/main.cpp 6
+
+ The chart is ready to be shown. We set the chart to be the central widget of the window.
+ We also set the size for the chart window and show it.
+
+ \snippet horizontalstackedbarchart/main.cpp 7
+*/
diff --git a/src/charts/doc/src/examples-legend.qdoc b/src/charts/doc/src/examples-legend.qdoc
new file mode 100644
index 00000000..0886058c
--- /dev/null
+++ b/src/charts/doc/src/examples-legend.qdoc
@@ -0,0 +1,40 @@
+/*!
+ \example legend
+ \title Legend Example
+ \ingroup qtcharts_examples
+
+ \brief This example shows how to detach the legend from the chart and how to attach it back.
+
+ By default the chart draws the legend inside the same view with the chart. In some cases the
+ user may want to draw the legend to somewhere else. To make this possible the legend can be
+ detached from the chart. Detaching means that the chart doesn't draw the legend or try to
+ change its layout. Detached legend can then be drawn wherever the user wishes, for example,
+ in a different graphics scene. The behavior of the legend can be inspected by running the
+ legend example.
+ In the example we use the bar series where we add or remove the bar sets. The legend reflects
+ the changes in series. The legend can be detached or attached back to the chart and its
+ alignment can be modified.
+ When the legend is detached, it can be resized and positioned freely.
+
+ \table
+ \row
+ \li \inlineimage examples_legend_detach.png
+ \li \inlineimage examples_legend_detach2.png
+ \endtable
+
+ Here we turn the legend visible and set its alignment to the bottom of the chart.
+
+ \snippet legend/mainwidget.cpp 1
+
+ This snippet shows how to detach the legend from the chart. After detaching, we turn its background to visible and set a different color to it. This makes it easier to see how the items inside the legend are arranged in detached mode.
+
+ \snippet legend/mainwidget.cpp 2
+
+ Here we attach the legend back to the chart. The background is turned invisible.
+
+ \snippet legend/mainwidget.cpp 3
+
+ This shows how we set the detached legend dimensions. After setting the new values, we call update to show changes on screen.
+
+ \snippet legend/mainwidget.cpp 4
+*/
diff --git a/src/charts/doc/src/examples-legendmarkers.qdoc b/src/charts/doc/src/examples-legendmarkers.qdoc
new file mode 100644
index 00000000..35ae5254
--- /dev/null
+++ b/src/charts/doc/src/examples-legendmarkers.qdoc
@@ -0,0 +1,43 @@
+/*!
+ \example legendmarkers
+ \title LegendMarkers Example
+ \ingroup qtcharts_examples
+
+ \brief The example shows how to make use of legend markers.
+
+ In this example we create an application which uses the QLegendMarker clicked signal to show/hide the corresponding series
+ in a chart. The connect marker button connects a clicked signal from all markers in a legend to the handleMarkerClicked slot.
+
+ \image examples_legendmarkers.png
+
+ Our application has buttons for adding or removing a series in a chart and a button to connect or disconnect the legend markers clicked signal to our handler.
+ In the image above we have connected the markers and clicked on one of them.
+
+ \snippet legendmarkers/mainwidget.cpp 1
+
+ Here we connect the markers in the legend to our handler. To avoid connecting the same marker more than once, we first disconnect it.
+
+ \snippet legendmarkers/mainwidget.cpp 2
+
+ Here we disconnect all markers from our handler.
+
+ \snippet legendmarkers/mainwidget.cpp 3
+
+ In our handler we first cast the sender of the event to the QLegendMarker.
+
+ \snippet legendmarkers/mainwidget.cpp 4
+
+ Then we check the type of the marker. This is required if we want to access the detailed methods of the marker and cast it to the correct type.
+ If all we need is the pointer to QAbstractSeries, the casting isn't necessary. In case of a pie or bar series, we may need the pointer to a related QPieSlice or QBarSet.
+
+ \snippet legendmarkers/mainwidget.cpp 5
+
+ We want to toggle the visibility of the series, when the marker is clicked. To do so, we get the pointer to a related series from the marker and toggle its visibility.
+ Since the legend marker follows the visibility of the series by default, we also set the marked back to visible. If we don't do so, the marker will be
+ invisible in the legend and we can't click on it anymore.
+
+ \snippet legendmarkers/mainwidget.cpp 6
+
+ Instead of making the marker invisible when the series is hidden, we dim the color of the marker. Here we do it by modifying the color of the laberBrush.
+
+*/
diff --git a/src/charts/doc/src/examples-lineandbarchart.qdoc b/src/charts/doc/src/examples-lineandbarchart.qdoc
new file mode 100644
index 00000000..d3f69e76
--- /dev/null
+++ b/src/charts/doc/src/examples-lineandbarchart.qdoc
@@ -0,0 +1,48 @@
+/*!
+ \example lineandbar
+ \title Line and BarChart Example
+ \ingroup qtcharts_examples
+
+ \brief The example shows how to combine different charts and set the axes.
+
+ In the example we combine a linechart with
+ a barchart and use the category axis as a common axis for both.
+
+ \image examples_lineandbar.png
+
+ Here we create data for our bar series.
+
+ \snippet lineandbar/main.cpp 1
+
+ We create a bar series and append sets to it.
+ The first values of each set are grouped together in the first category, the second values in the second category and so on.
+
+ \snippet lineandbar/main.cpp 2
+
+ Then we create a line series and add data to it. To make the data match with the barchart, we use the index as an x-value for our line series, so that
+ first point is at (0,value) second at (1,value) and so on.
+
+ \snippet lineandbar/main.cpp 8
+
+ Here we create the chart and add both series to it.
+
+ \snippet lineandbar/main.cpp 3
+
+ To make the chart show the series properly, we have to create custom axes for the series. If we don't create custom axes, then each series will get scaled to
+ use the maximum area of the chart (like in single series case) and the result will be incorrect. With custom axes we set the range of both series to follow the
+ same axis. For the x-axis we use the QBarCategoryAxis and for the y-axis we use QValuesAxis.
+
+ \snippet lineandbar/main.cpp 4
+
+ And we also want to show the legend.
+
+ \snippet lineandbar/main.cpp 5
+
+ Finally we add the chart onto a view.
+
+ \snippet lineandbar/main.cpp 6
+
+ Now it is ready to be shown in a window.
+
+ \snippet lineandbar/main.cpp 7
+*/
diff --git a/src/charts/doc/src/examples-linechart.qdoc b/src/charts/doc/src/examples-linechart.qdoc
new file mode 100644
index 00000000..d425788a
--- /dev/null
+++ b/src/charts/doc/src/examples-linechart.qdoc
@@ -0,0 +1,30 @@
+/*!
+ \example linechart
+ \title LineChart Example
+ \ingroup qtcharts_examples
+
+ \brief The example shows how to create a simple line chart.
+
+ \image examples_linechart.png
+
+ To create a line chart, a QLineSeries instance is needed. Let's create one.
+
+ \snippet linechart/main.cpp 1
+
+ Then we add data to the series. We can use the append() member function or use the stream operator.
+
+ \snippet linechart/main.cpp 2
+
+ To present the data on the chart we need a QChart instance. We add the series to it, create the default axes, and set the title of the chart.
+
+ \snippet linechart/main.cpp 3
+
+ Then we create a QChartView object with QChart as a parameter. This way we don't need to create a QGraphicsView scene ourselves. We also set the Antialiasing on to have the rendered lines look nicer.
+
+ \snippet linechart/main.cpp 4
+
+ The chart is ready to be shown.
+
+ \snippet linechart/main.cpp 5
+
+*/
diff --git a/src/charts/doc/src/examples-logvalueaxis.qdoc b/src/charts/doc/src/examples-logvalueaxis.qdoc
new file mode 100644
index 00000000..f37db92e
--- /dev/null
+++ b/src/charts/doc/src/examples-logvalueaxis.qdoc
@@ -0,0 +1,30 @@
+/*!
+ \example logvalueaxis
+ \title Logarithmic Axis Example
+ \ingroup qtcharts_examples
+
+ \brief The example shows how to use QLogValueAxis.
+
+ \image examples_logvalueaxis.png
+
+ Create a QLineSeries instance and add some data to it.
+
+ \snippet logvalueaxis/main.cpp 1
+
+ To present the data on the chart we need a QChart instance. Add the series to it, hide the legend and set the title of the chart.
+
+ \snippet logvalueaxis/main.cpp 2
+
+ Create the axes. Add them to the chart and attach to the series.
+
+ \snippet logvalueaxis/main.cpp 3
+
+ Then create a QChartView object with QChart as a parameter. Enable antialiasing to have the rendered line look nicer.
+
+ \snippet logvalueaxis/main.cpp 4
+
+ The chart is ready to be shown.
+
+ \snippet logvalueaxis/main.cpp 5
+
+*/
diff --git a/src/charts/doc/src/examples-modeldata.qdoc b/src/charts/doc/src/examples-modeldata.qdoc
new file mode 100644
index 00000000..507aa4cb
--- /dev/null
+++ b/src/charts/doc/src/examples-modeldata.qdoc
@@ -0,0 +1,59 @@
+/*!
+ \example modeldata
+ \title Model Data Example
+ \ingroup qtcharts_examples
+
+ \brief This example shows how to use the QAbstractItemModel derived model as the data for the
+ series.
+
+ \image examples_modeldata.png
+
+ Let's start by creating an instance of the CustomTableModel class.
+ The CustomTableModel class is derived from QAbstractTableModel and it was created for the purpose of this example.
+ The constructor of this class populates the internal data store of the model with the data that is suitable for our chart example.
+
+ \snippet modeldata/tablewidget.cpp 1
+
+ We now have a model with data that we would like to display both on the chart and in a QTableView.
+ First, we create QTableView and tell it to use the model as a data source. To make the data cells fill the table view we also change headers resize mode.
+
+ \snippet modeldata/tablewidget.cpp 2
+
+ Now we need the QChart instance to display the same data on the chart.
+ We also enable animations. It makes it easier to see how modifying the model's data affect the chart.
+
+ \snippet modeldata/tablewidget.cpp 3
+
+ The code below creates new line series and gives it a name. The following line creates an instance of QVXYModelMapper class.
+ The next two lines specify that X-coordinates are taken from the model's column(Qt::Vertical) with index 0. The Y-coordinates are taken from the model's column with index 1.
+ To create a connection between the series and the model we set both of those objects to QVXYModelMapper.
+
+ Finally, the series is added to the chart.
+
+ \snippet modeldata/tablewidget.cpp 4
+
+ To show in QTableView which data corresponds with which series this example uses table coloring.
+ When a series is added to the chart it is assigned a color based on the currently selected theme.
+ The code below extracts that color from the series and uses it to create a colored QTableView.
+ The coloring of the view is not a part of the QChart functionality.
+
+ \snippet modeldata/tablewidget.cpp 5
+
+ The same operations are done with a second series. Notice that for this series different columns of the same model are mapped.
+
+ \snippet modeldata/tablewidget.cpp 6
+
+ \snippet modeldata/tablewidget.cpp 7
+
+ To avoid setting up the QGraphicsScene we use the QChartView class that does it for us.
+ QChart object pointer is used as a parameter of the QChartView constructor.
+ To make the chart look nicer, Antialiasing is turned on and the minimum size of the chartView widget is set.
+
+ \snippet modeldata/tablewidget.cpp 8
+
+ Finally we place both widgets in a layout and use the layout as the application layout.
+
+ \snippet modeldata/tablewidget.cpp 9
+
+ The application is ready. Try modifying the data in the table view and see how it affects the chart.
+*/
diff --git a/src/charts/doc/src/examples-multiaxis.qdoc b/src/charts/doc/src/examples-multiaxis.qdoc
new file mode 100644
index 00000000..4d82e2f5
--- /dev/null
+++ b/src/charts/doc/src/examples-multiaxis.qdoc
@@ -0,0 +1,37 @@
+/*!
+ \example multiaxis
+ \title Multiple Axes Example
+ \ingroup qtcharts_examples
+
+ \brief The example shows how to create a simple chart with two vertical axes. One for each
+ series.
+
+ \image examples_multiaxis.png
+
+ Create the QChart instance, hide the legend of the chart, and set its title.
+
+ \snippet multiaxis/main.cpp 1
+
+ Create a QValueAxis instance that will be used as a horizontal axis by both series and add it the bottom of the chart.
+ The axis can be shared between many series, but each series can have only one vertical and horizontal axis.
+
+ \snippet multiaxis/main.cpp 2
+
+ Create the first series, and add the data to it. Finally, add the series to the chart. Instantiate its own Y-axis, add it to the chart. Then attach both the common X-axis and the series specific Y-axis.
+ In this example the color of the axis line is set to be the same as the color of the series to make it possible to distinguish which axis is attached to which series.
+
+ \snippet multiaxis/main.cpp 3
+
+ Similarly prepare another series. This time a different axis type is used. Additionally grid lines color is also set to be the same as the color of the series.
+
+ \snippet multiaxis/main.cpp 4
+
+ Create a QChartView object with QChart as a parameter. Enable Antialiasing to have the rendered splines look nicer.
+
+ \snippet multiaxis/main.cpp 5
+
+ The chart is ready to be shown.
+
+ \snippet multiaxis/main.cpp 6
+
+*/
diff --git a/src/charts/doc/src/examples-nesteddonuts.qdoc b/src/charts/doc/src/examples-nesteddonuts.qdoc
new file mode 100644
index 00000000..697a59b4
--- /dev/null
+++ b/src/charts/doc/src/examples-nesteddonuts.qdoc
@@ -0,0 +1,50 @@
+/*!
+ \example nesteddonuts
+ \title Nested donuts example
+ \ingroup qtcharts_examples
+
+ \brief This example shows how to create a nested donuts chart using the QPieSeries API.
+ \image examples_nesteddonuts.png
+
+ Let's start by creating a QChartView instance and enabling the Antialiasing on it. A QChart object is then obtained from the QChartView instance.
+ The legend is disabled and the title of the chart is set. Last line enables the animations of the chart.
+
+ \snippet nesteddonuts/widget.cpp 1
+
+ Three variables are defined that will be used to define the donut chart. Min and max size define the relative size of the whole donut.
+ minSize is the relative inner size of the smallest donut. maxSize is the relative outer size of the biggest donut.
+
+ \snippet nesteddonuts/widget.cpp 2
+
+ The following block of code defines the individual donuts and their slices. First a new QPieSeries object is created.
+ The number of slices in each donut is randomized.
+ The internal for loop creates the slices with a random value and label same as the value.
+ Next the label of the slice is set to be visible and its color is set to white.
+ To make the example more interesting the hovered signal of the slice is connected to widget's slot, of which the inner workings are explained later.
+ Finally the slice is added to the donut. The donut's size is adjusted to achieve the nesting of the donuts.
+ Then the donut is added to the widget's list of donuts and to the chart.
+
+ \snippet nesteddonuts/widget.cpp 3
+
+ Finally the widget is placed in a layout used by the application.
+
+ \snippet nesteddonuts/widget.cpp 4
+
+ To make the example more interesting the donuts are rotated randomly every 1.25 sec.
+
+ \snippet nesteddonuts/widget.cpp 5
+
+ The widget's updatedRotation slot is defined below.
+ It goes through all of the donuts and modifies their current rotation by a random value.
+
+ \snippet nesteddonuts/widget.cpp 6
+
+ The earlier mentioned explodeSlice slot code is provided below.
+ If the slice is set to exploded, then stop the timer that controls the donuts rotation.
+ Then the slice's start and end angles are obtained from the slice.
+ To highlight the selected slice all the other donuts that lie outward from the one that contains the selected slice
+ have their start and end angles modified so that they wouldn't "block" the way for the hightlighted slice.
+ If the slice is no longer selected return to the original state.
+
+ \snippet nesteddonuts/widget.cpp 7
+*/
diff --git a/src/charts/doc/src/examples-percentbarchart.qdoc b/src/charts/doc/src/examples-percentbarchart.qdoc
new file mode 100644
index 00000000..d1316e80
--- /dev/null
+++ b/src/charts/doc/src/examples-percentbarchart.qdoc
@@ -0,0 +1,55 @@
+/*!
+ \example percentbarchart
+ \title PercentBarChart Example
+ \ingroup qtcharts_examples
+
+ \brief The example shows how to create a simple percent bar chart.
+
+ A percent bar chart shows the data in sets as a percentage of
+ all sets per category.
+
+ Creating percent bar charts is just like creating a regular \l {BarChart Example} {bar chart}, except that for a
+ percent bar charts, we use the QPercentBarSeries api instead of QBarSeries. Also, in the
+ \l {BarChart Example} {bar chart} we used the nice numbers algorithm to make the y-axis numbering look better. With
+ the percent bar chart there is no need for that, because the maximum y-axis value is always 100.
+
+ \image examples_percentbarchart.png
+
+ The barsets are used in same way in all barcharts.
+ To illustrate the difference between various barcharts, we use the same data in all examples.
+ The data visualized by the bar chart is defined by QBarSet instances. Here we create the sets and append data
+ to them. The data is appended here with the << operator. Alternatively the append method could be used.
+
+ \snippet percentbarchart/main.cpp 1
+
+ We create the series and append the barsets to it. The series takes ownership of the barsets. The series groups the data from sets to categories.
+ The first values of each set are grouped together in the first category, the second values in the second category etc.
+
+ \snippet percentbarchart/main.cpp 2
+
+ Here we create the chart object and add the series to it. We set the title of the chart with setTitle, and then turn on animations of the series by calling
+ setAnimationOptions(QChart::SeriesAnimations)
+
+ \snippet percentbarchart/main.cpp 3
+
+ To have categories displayed on axis, we need to create a QBarCategoryAxis for that. Here we create a category axis with a list of categories and
+ set it to be the x-axis of the chart. The chart takes ownership of the axis. For the y-axis we use the default axis, which is created and scaled
+ to series data by calling createDefaultAxes of the chart. Note that createDefaultAxes must be called before we set the category axis.
+ Otherwise the default axis will override the category axis.
+
+ \snippet percentbarchart/main.cpp 4
+
+ We also want to show the legend. To do so, we get the legend pointer from the chart and set it to visible. We also place the legend to bottom of
+ the chart by setting its alignment to Qt::AlignBottom.
+
+ \snippet percentbarchart/main.cpp 5
+
+ Finally we add the chart onto a view. We also turn on the antialiasing for the chartView.
+
+ \snippet percentbarchart/main.cpp 6
+
+ The chart is ready to be shown. We set the chart to be central widget of the window.
+ We also set the size for the chart window and show it.
+
+ \snippet percentbarchart/main.cpp 7
+*/
diff --git a/src/charts/doc/src/examples-piechart.qdoc b/src/charts/doc/src/examples-piechart.qdoc
new file mode 100644
index 00000000..1ae2b3ea
--- /dev/null
+++ b/src/charts/doc/src/examples-piechart.qdoc
@@ -0,0 +1,9 @@
+/*!
+ \example piechart
+ \title Piechart Example
+ \ingroup qtcharts_examples
+
+ \brief The example shows how to create a simple pie chart and do some customizations to
+ a pie slice.
+ \image examples_piechart.png
+*/
diff --git a/src/charts/doc/src/examples-piechartcustomization.qdoc b/src/charts/doc/src/examples-piechartcustomization.qdoc
new file mode 100644
index 00000000..8a6915c3
--- /dev/null
+++ b/src/charts/doc/src/examples-piechartcustomization.qdoc
@@ -0,0 +1,8 @@
+/*!
+ \example piechartcustomization
+ \title Pie chart customization example
+ \ingroup qtcharts_examples
+
+ \brief This example shows how the look and feel of a pie chart can be customized.
+ \image piechart_customization.png
+*/
diff --git a/src/charts/doc/src/examples-piechartdrilldown.qdoc b/src/charts/doc/src/examples-piechartdrilldown.qdoc
new file mode 100644
index 00000000..f53d9745
--- /dev/null
+++ b/src/charts/doc/src/examples-piechartdrilldown.qdoc
@@ -0,0 +1,9 @@
+/*!
+ \example piechartdrilldown
+ \title Piechart Drilldown Example
+ \ingroup qtcharts_examples
+
+ \brief The example shows how to implement a piechart with drilldown effect.
+ \image examples_piechartdrill1.png
+ \image examples_piechartdrill2.png
+*/
diff --git a/src/charts/doc/src/examples-polarchart.qdoc b/src/charts/doc/src/examples-polarchart.qdoc
new file mode 100644
index 00000000..9d27aafa
--- /dev/null
+++ b/src/charts/doc/src/examples-polarchart.qdoc
@@ -0,0 +1,34 @@
+/*!
+ \example polarchart
+ \title Polar Chart Example
+ \ingroup qtcharts_examples
+
+ \brief The example shows how to create a simple polar chart with multiple different series.
+
+ It also shows how to implement scrolling and zooming of the polar chart as well as
+ visually demonstrate how polar charts and cartesian charts relate to each other.
+
+ \image examples_polarchart.png
+
+ Creating a polar chart is done with a QPolarChart instance instead of a QChart instance.
+
+ \snippet polarchart/main.cpp 1
+
+ Axes are created similarly to cartesian charts, but when axes are added to the chart,
+ you can use polar orientations instead of alignments.
+
+ \snippet polarchart/main.cpp 2
+
+ Zooming and scrolling of a polar chart is logically nearly identical to zooming and scrolling of a cartesian chart.
+ The main difference is that when scrolling along the X-axis (angular axis), the angle is used instead of the number of pixels.
+ Another difference is that zooming to a rectangle cannot be done.
+
+ \snippet polarchart/chartview.cpp 1
+
+ The same axes and series can be used in both cartesian and polar charts, though not simultaneously.
+ To switch between chart types, you first need to remove the series and axes from the old chart, and then add
+ them to the new chart. If you want to preserve the axis ranges, those need to be copied, too.
+
+ \snippet polarchart/chartview.cpp 2
+
+*/
diff --git a/src/charts/doc/src/examples-qmlaxes.qdoc b/src/charts/doc/src/examples-qmlaxes.qdoc
new file mode 100644
index 00000000..88ab61fc
--- /dev/null
+++ b/src/charts/doc/src/examples-qmlaxes.qdoc
@@ -0,0 +1,32 @@
+/*!
+ \example qmlaxes
+ \title Qml Axes
+ \ingroup qtcharts_examples
+
+ \brief This is a demonstration of how to use axes in your QML application.
+
+ \table
+ \row
+ \li \br
+ We begin with a chart that has a line series and a scatter series with random
+ data. Both series use the same axes.
+ \br
+ \br
+ \snippet qmlaxes/qml/qmlaxes/View1.qml 1
+ \li \inlineimage examples_qmlaxes1.png
+ \row
+ \li \br
+ The next example shows a chart with some accurate historical data that makes us to use a DateTimeAxis.
+ \br
+ \br
+ \snippet qmlaxes/qml/qmlaxes/View2.qml 1
+ \li \inlineimage examples_qmlaxes2.png
+ \row
+ \li \br
+ And the final example with a chart that uses a CategoryAxis to make the data easier to understand.
+ \br
+ \br
+ \snippet qmlaxes/qml/qmlaxes/View3.qml 1
+ \li \inlineimage examples_qmlaxes3.png
+ \endtable
+*/
diff --git a/src/charts/doc/src/examples-qmlchart.qdoc b/src/charts/doc/src/examples-qmlchart.qdoc
new file mode 100644
index 00000000..8696461c
--- /dev/null
+++ b/src/charts/doc/src/examples-qmlchart.qdoc
@@ -0,0 +1,125 @@
+/*!
+ \example qmlchart
+ \title Qml charts example
+ \ingroup qtcharts_examples
+
+ \brief This basic demonstration shows how to use the different chart types by using qml.
+
+ Creating each chart type begins with the creation of a ChartView.
+
+ \table
+ \row
+ \li \br
+ To create a pie, we use the PieSeries API together with a few PieSlices:
+ \br
+ \br
+ \snippet qmlchart/qml/qmlchart/View1.qml 1
+ \li \inlineimage examples_qmlchart1.png
+ \endtable
+
+ \table
+ \row
+ \li \br
+ To create a chart with a line series:
+ \br
+ \br
+ \snippet qmlchart/qml/qmlchart/View2.qml 1
+ \li \inlineimage examples_qmlchart2.png
+ \endtable
+
+ \table
+ \row
+ \li \br
+ And spline series:
+ \br
+ \br
+ \snippet qmlchart/qml/qmlchart/View3.qml 1
+ \li \inlineimage examples_qmlchart3.png
+ \endtable
+
+ \table
+ \row
+ \li \br
+ Then we create a chart that illustrates the NHL All-Star player selections by using
+ three area series:
+ \br
+ \br
+ \snippet qmlchart/qml/qmlchart/View4.qml 1
+ \dots
+ \li \inlineimage examples_qmlchart4.png
+ \endtable
+
+ \table
+ \row
+ \li \br
+ Then a couple of scatter series:
+ \br
+ \br
+ \snippet qmlchart/qml/qmlchart/View5.qml 1
+ \dots
+ \li \inlineimage examples_qmlchart5.png
+ \endtable
+
+ And a few different bar series:
+ \table
+ \row
+ \li \br
+ \br
+ \br
+ \snippet qmlchart/qml/qmlchart/View6.qml 1
+ \li \inlineimage examples_qmlchart6.png
+ \endtable
+ \table
+ \row
+ \li \br
+ \br
+ \br
+ \snippet qmlchart/qml/qmlchart/View7.qml 1
+ \li \inlineimage examples_qmlchart7.png
+ \endtable
+ \table
+ \row
+ \li \br
+ \br
+ \br
+ \snippet qmlchart/qml/qmlchart/View8.qml 1
+ \li \inlineimage examples_qmlchart8.png
+ \endtable
+ \table
+ \row
+ \li \br
+ \br
+ \br
+ \snippet qmlchart/qml/qmlchart/View9.qml 1
+ \li \inlineimage examples_qmlchart9.png
+ \endtable
+ \table
+ \row
+ \li \br
+ \br
+ \br
+ \snippet qmlchart/qml/qmlchart/View10.qml 1
+ \li \inlineimage examples_qmlchart10.png
+ \endtable
+ \table
+ \row
+ \li \br
+ \br
+ \br
+ \snippet qmlchart/qml/qmlchart/View11.qml 1
+ \li \inlineimage examples_qmlchart11.png
+ \endtable
+
+ \table
+ \row
+ \li \br
+ And finally an example demonstrating how to create a donut chart with two pie
+ series:
+ \br
+ \br
+ \snippet qmlchart/qml/qmlchart/View12.qml 1
+ \li \inlineimage examples_qmlchart12.png
+ \endtable
+
+ Additionally, antialiasing is set with the qml property in Qt Quick 2.
+*/
diff --git a/src/charts/doc/src/examples-qmlcustomizations.qdoc b/src/charts/doc/src/examples-qmlcustomizations.qdoc
new file mode 100644
index 00000000..3d09009d
--- /dev/null
+++ b/src/charts/doc/src/examples-qmlcustomizations.qdoc
@@ -0,0 +1,28 @@
+/*!
+ \example qmlcustomizations
+ \title Qml Customizations
+ \ingroup qtcharts_examples
+
+ \image examples_qmlcustomizations.png
+
+ \brief This application shows you how to customize different visual properties of a ChartView
+ and series.
+
+ This example shows a wheel of fortune by customizing a pie series.
+
+ First we create the ChartView and a couple of series.
+ \snippet qmlcustomizations/qml/qmlcustomizations/main.qml 1
+
+ The application data is generated in Component.onCompleted of the main rectangle:
+ \snippet qmlcustomizations/qml/qmlcustomizations/main.qml 2
+
+ The following customizations are done repeatedly with a timer. To highlight one of the pie
+ slices at time we modify its exploded property:
+ \snippet qmlcustomizations/qml/qmlcustomizations/main.qml 3
+
+ Then an animation using a scatter series with one data point:
+ \snippet qmlcustomizations/qml/qmlcustomizations/main.qml 4
+
+ When the wheel of fortune has stopped, we make the active slice blink by modifying its colors.
+ \snippet qmlcustomizations/qml/qmlcustomizations/main.qml 5
+*/
diff --git a/src/charts/doc/src/examples-qmlcustomlegend.qdoc b/src/charts/doc/src/examples-qmlcustomlegend.qdoc
new file mode 100644
index 00000000..b8f307ef
--- /dev/null
+++ b/src/charts/doc/src/examples-qmlcustomlegend.qdoc
@@ -0,0 +1,43 @@
+/*!
+ \example qmlcustomlegend
+ \title Qml Custom Legend
+ \ingroup qtcharts_examples
+
+ \brief This example shows you how to create your own custom legend.
+
+ This application shows you how to create your own custom legend instead of using the
+ built-in legend of ChartView API.
+
+ \table
+ \row
+ \li \br
+ The main view of the application shows a stacked area chart. This is how one of
+ \br
+ the stacked areas is created. See ChartViewStacked.qml and AnimatedAreaSeries.qml.
+ \br
+ \br
+ \snippet qmlcustomlegend/qml/qmlcustomlegend/ChartViewStacked.qml 1
+ \li \inlineimage examples_qmlcustomlegend1.png
+ \row
+ \li \br
+ Hovering with mouse on top of the legend will highlight the hovered series.
+ \br
+ (see CustomLegend.qml).
+ \br
+ \br
+ \snippet qmlcustomlegend/qml/qmlcustomlegend/CustomLegend.qml 1
+ \snippet qmlcustomlegend/qml/qmlcustomlegend/CustomLegend.qml 2
+ \dots
+ \snippet qmlcustomlegend/qml/qmlcustomlegend/CustomLegend.qml 3
+ \li \inlineimage examples_qmlcustomlegend2.png
+ \row
+ \li \br
+ You can also select one of the stacked areas for a closer look as a line series by
+ \br
+ a mouse click (see ChartViewHighlighted.qml).
+ \br
+ \br
+ \snippet qmlcustomlegend/qml/qmlcustomlegend/ChartViewHighlighted.qml 1
+ \li \inlineimage examples_qmlcustomlegend3.png
+ \endtable
+*/
diff --git a/src/charts/doc/src/examples-qmlf1legends.qdoc b/src/charts/doc/src/examples-qmlf1legends.qdoc
new file mode 100644
index 00000000..da7a73b2
--- /dev/null
+++ b/src/charts/doc/src/examples-qmlf1legends.qdoc
@@ -0,0 +1,23 @@
+/*!
+ \example qmlf1legends
+ \title Qml F1 Legends
+ \ingroup qtcharts_examples
+
+ \image examples_qmlf1legends.png
+
+ \brief This application demonstrates how to use XmlListModel as a datasource for a Chart.
+
+ Let's define an empty ChartView first:
+ \snippet qmlf1legends/qml/qmlf1legends/main.qml 1
+
+ Our XmlListModel uses hard-coded test data. In a real application the data source would be a
+ timing system.
+ \snippet qmlf1legends/qml/qmlf1legends/SpeedsXml.qml 1
+ \dots
+ \snippet qmlf1legends/qml/qmlf1legends/SpeedsXml.qml 2
+ \snippet qmlf1legends/qml/qmlf1legends/main.qml 2
+
+ The data is parsed with a timer. The line series representing each driver are created on the
+ fly.
+ \snippet qmlf1legends/qml/qmlf1legends/main.qml 3
+*/
diff --git a/src/charts/doc/src/examples-qmloscilloscope.qdoc b/src/charts/doc/src/examples-qmloscilloscope.qdoc
new file mode 100644
index 00000000..eb6c5f43
--- /dev/null
+++ b/src/charts/doc/src/examples-qmloscilloscope.qdoc
@@ -0,0 +1,47 @@
+/*!
+ \example qmloscilloscope
+ \title QML Oscilloscope
+ \ingroup qtcharts_examples
+
+ \image examples_qmloscilloscope.png
+
+ \brief The example shows how to implement application with strict performance requirements
+ using the Qt Charts QML API.
+
+ The oscilloscope application demonstrates how to use the Qt Charts QML API to implement an
+ application with strict performance requirements. The application uses generated data with
+ configurable characteristics to mimic a simple oscilloscope user interface. To find out the
+ actual screen refresh performance of the application, you can set QML_SHOW_FRAMERATE = 1 to
+ your run environment settings to get the framerate shown in the application output console.
+ To do so go to Projects - Run - Run environment in Qt Creator and select Add. Then you can
+ experiment with the different configurable options of the example application to find the
+ configuration that gives you the best performance in your environment.
+
+ Note: You can try if enabling OpenGL improves the performance with the following startup
+ parameter:
+ \code
+ -graphicssystem opengl
+ \endcode
+
+ The application window is shared by control and scope views:
+ \snippet qmloscilloscope/qml/qmloscilloscope/main.qml 1
+ \dots
+ \snippet qmloscilloscope/qml/qmloscilloscope/main.qml 2
+
+ ControlView implements the buttons used for configuring. ScopeView uses a ChartView to show
+ a chart with two line series:
+ \snippet qmloscilloscope/qml/qmloscilloscope/ScopeView.qml 1
+ \dots
+
+ The data of the line series is updated with a QML timer. In a real life application the
+ updating could be triggered with a signal from Qt C++ code.
+ \snippet qmloscilloscope/qml/qmloscilloscope/ScopeView.qml 2
+
+ The oscilloscope also allows you to switch the type of the series used for visualizing the
+ signal sources. This is implemented by dynamically destroying and creating series:
+ \snippet qmloscilloscope/qml/qmloscilloscope/ScopeView.qml 3
+
+ \note QML_SHOW_FRAMERATE environment variable doesn't work with Qt Quick 2.
+ From Qt 5.1.0 on, the QSG_RENDER_TIMING environment variable can be used
+ similarly to display rendering time.
+*/
diff --git a/src/charts/doc/src/examples-qmlpolarchart.qdoc b/src/charts/doc/src/examples-qmlpolarchart.qdoc
new file mode 100644
index 00000000..59115cd1
--- /dev/null
+++ b/src/charts/doc/src/examples-qmlpolarchart.qdoc
@@ -0,0 +1,35 @@
+/*!
+ \example qmlpolarchart
+ \title Qml Polar Chart
+ \ingroup qtcharts_examples
+
+ \brief This is a demonstration on how to use a polar chart in your QML application.
+
+ \table
+ \row
+ \li \br
+ We begin with a chart that has a spline series and a scatter series with random
+ data. Both series use the same axes.
+ \br
+ \br
+ \snippet qmlpolarchart/qml/qmlpolarchart/View1.qml 1
+ \li \inlineimage examples_qmlpolarchart1.png
+ \row
+ \li \br
+ The next example shows a chart with some accurate historical data for which we need
+ to use a DateTimeAxis
+ and a AreaSeries.
+ \br
+ \br
+ \snippet qmlpolarchart/qml/qmlpolarchart/View2.qml 1
+ \li \inlineimage examples_qmlpolarchart2.png
+ \row
+ \li \br
+ And the final example with a chart that uses a CategoryAxis to make the data easier
+ to understand.
+ \br
+ \br
+ \snippet qmlpolarchart/qml/qmlpolarchart/View3.qml 1
+ \li \inlineimage examples_qmlpolarchart3.png
+ \endtable
+*/
diff --git a/src/charts/doc/src/examples-qmlweather.qdoc b/src/charts/doc/src/examples-qmlweather.qdoc
new file mode 100644
index 00000000..87e9010b
--- /dev/null
+++ b/src/charts/doc/src/examples-qmlweather.qdoc
@@ -0,0 +1,34 @@
+/*!
+ \example qmlweather
+ \title Qml Weather
+ \ingroup qtcharts_examples
+
+ \image examples_qmlweather.png
+
+ \brief This is a basic demonstration showing how to use the different chart types by using qml.
+
+ By default the application uses static test data to mimic a weather forecast. You can also
+ obtain an application id from http://www.worldweatheronline.com/ to get access to weather API
+ provided by World Weather Online. You can then give your application id as a parameter to the
+ Qml Weather executable to make it use live data.
+
+ For example:
+ \code
+ bin\qmlweather.exe 1234567890abcdef123456
+ \endcode
+
+ The example application uses a ChartView and a some series to visualize weather data:
+ \snippet qmlweather/qml/qmlweather/main.qml 1
+ \snippet qmlweather/qml/qmlweather/main.qml 2
+
+ To get data with weather forecast data, we make an HTTP GET request to World Weather Online. We
+ request the response in JSON data format.
+ \snippet qmlweather/qml/qmlweather/main.qml 3
+
+ The JSON response contains an array of forecast data:
+ \snippet qmlweather/qml/qmlweather/main.qml 4
+
+ That is then used as input data for our series and a ListModel we use as a container for weather
+ icon URLs:
+ \snippet qmlweather/qml/qmlweather/main.qml 5
+*/
diff --git a/src/charts/doc/src/examples-scatterchart.qdoc b/src/charts/doc/src/examples-scatterchart.qdoc
new file mode 100644
index 00000000..66ef518c
--- /dev/null
+++ b/src/charts/doc/src/examples-scatterchart.qdoc
@@ -0,0 +1,39 @@
+/*!
+ \example scatterchart
+ \title ScatterChart Example
+ \ingroup qtcharts_examples
+
+ \brief The example shows how to create a simple scatter chart.
+
+ \image examples_scatterchart.png
+
+ To create scatter charts, a QScatterSeries instance is needed. Here we create a scatter series
+ instance, and set the type and width of outline for the scatter points.
+
+ \snippet scatterchart/chartview.cpp 1
+
+ We add the data to be shown. We can use the append() member function or use the stream operator.
+
+ \snippet scatterchart/chartview.cpp 2
+
+ We can define the brush of the scatter series to be an image. Here the image is a star created
+ using QPainterPath.
+
+ \snippet scatterchart/chartview.cpp 3
+
+ In the end we enable anti-aliasing, set the chart title, and add the scatter series onto the
+ chart. We also disable drop shadow, because it would not look good on an application with only
+ chart view shown.
+
+ \snippet scatterchart/chartview.cpp 4
+
+ The image used as a brush for the scatter series may contain several colors. Therefore we need
+ to set the desired color explicitly by setting the brush for the legend marker items.
+
+ \snippet scatterchart/chartview.cpp 5
+
+ The chart is ready to be shown.
+
+ \snippet scatterchart/main.cpp 4
+
+*/
diff --git a/src/charts/doc/src/examples-scatterinteractions.qdoc b/src/charts/doc/src/examples-scatterinteractions.qdoc
new file mode 100644
index 00000000..e616e086
--- /dev/null
+++ b/src/charts/doc/src/examples-scatterinteractions.qdoc
@@ -0,0 +1,10 @@
+/*!
+ \example scatterinteractions
+ \title ScatterInteractions Example
+ \ingroup qtcharts_examples
+
+ \brief This example shows how to create a simple scatter chart and how to interact with the
+ chart.
+
+ \image examples_scatterinteractions.png
+*/
diff --git a/src/charts/doc/src/examples-splinechart.qdoc b/src/charts/doc/src/examples-splinechart.qdoc
new file mode 100644
index 00000000..50c634fc
--- /dev/null
+++ b/src/charts/doc/src/examples-splinechart.qdoc
@@ -0,0 +1,34 @@
+/*!
+ \example splinechart
+ \title SplineChart Example
+ \ingroup qtcharts_examples
+
+ \brief The example shows how to create a simple spline chart.
+
+ \image examples_splinechart.png
+
+ To create spline charts we need to put our data into QSplineSeries. QSplineSeries automatically
+ calculates spline segment control points that are needed to properly draw the spline.
+
+ \snippet splinechart/main.cpp 1
+
+ Now let's add some data points to the series.
+
+ \snippet splinechart/main.cpp 2
+
+ The data series has been populated. To display it on a chart we create a QChart object and add
+ the data series to it. We also set the title and the values range on the y-axis, so that our
+ chart's visibility is better.
+
+ \snippet splinechart/main.cpp 3
+
+ Then we create a QChartView object with QChart as a parameter. This way we don't need to create
+ a QGraphicsView scene ourselves. We also set the Antialiasing on to have the rendered lines
+ look nicer.
+
+ \snippet splinechart/main.cpp 4
+
+ Finally, we set the QChartView as the windows's central widget.
+
+ \snippet splinechart/main.cpp 5
+*/
diff --git a/src/charts/doc/src/examples-stackedbarchart.qdoc b/src/charts/doc/src/examples-stackedbarchart.qdoc
new file mode 100644
index 00000000..1e9d8928
--- /dev/null
+++ b/src/charts/doc/src/examples-stackedbarchart.qdoc
@@ -0,0 +1,53 @@
+/*!
+ \example stackedbarchart
+ \title StackedBarChart Example
+ \ingroup qtcharts_examples
+
+ \brief The example shows how to create a simple stacked bar chart.
+
+ The stacked bar chart shows the data in sets as bars stacked on top of each other. The stacking
+ is done per category. The example shows how to create a simple stacked bar chart. Stacked bar
+ chart shows the data in sets as bars that are stacked on top of each other. The stacking is done
+ per category. Creating a stacked bar chart is just like creating a regular \l {BarChart Example}
+ {bar chart}, except that for a stacked bar chart, we use the QStackedBarSeries API instead of
+ QBarSeries.
+
+ \image examples_stackedbarchart.png
+
+ The barsets are used in same way in all barcharts.
+ To illustrate the difference between various barcharts, we use same data in all examples.
+ Data, which the barchart visualizes, is defined by the QBarSet instances. Here we create the sets and append data
+ to them. The data is appended here with << operator. Alternatively the append method could be used.
+
+ \snippet stackedbarchart/main.cpp 1
+
+ We create the series and append the barsets to it. The series takes ownership of the barsets. The series groups the data from sets to categories.
+ The first values of each set are grouped together in the first category, the second values in the second category etc.
+
+ \snippet stackedbarchart/main.cpp 2
+
+ Here we create the chart object and add the series to it. We set the title for the chart with setTitle, and then turn on animations of the series by calling
+ setAnimationOptions(QChart::SeriesAnimations).
+
+ \snippet stackedbarchart/main.cpp 3
+
+ To have categories displayed on the axis, we need to create a QBarCategoryAxis. Here we create a category axis with list of categories and
+ set it to be the x-axis of the chart. The chart takes ownership of the axis. For the y-axis we use default axis, which is created and scaled to series data
+ by calling createDefaultAxes of the chart. Note that the call for createDefaultAxes must be before we set the category axis. Otherwise the default axis will
+ override the category axis.
+
+ \snippet stackedbarchart/main.cpp 4
+
+ We also want to show the legend. To do so, we get the legend pointer from the chart and set it to visible. We also place the legend to the bottom of the chart by setting its alignment to Qt::AlignBottom.
+
+ \snippet stackedbarchart/main.cpp 5
+
+ Finally, we add the chart onto a view. We also turn on the antialiasing for the chartView.
+
+ \snippet stackedbarchart/main.cpp 6
+
+ The chart is ready to be shown. We set the chart to be the central widget of the window.
+ We also set the size for the chart window and show it.
+
+ \snippet stackedbarchart/main.cpp 7
+*/
diff --git a/src/charts/doc/src/examples-stackedbarchartdrilldown.qdoc b/src/charts/doc/src/examples-stackedbarchartdrilldown.qdoc
new file mode 100644
index 00000000..0bfe5fd2
--- /dev/null
+++ b/src/charts/doc/src/examples-stackedbarchartdrilldown.qdoc
@@ -0,0 +1,50 @@
+/*!
+ \example stackedbarchartdrilldown
+ \title StackedBarChart Drilldown Example
+ \ingroup qtcharts_examples
+
+ \brief The example shows how to implement drilldown using a stacked barchart.
+
+ In the drilldown example we create a stacked bar chart, which shows the harvest of various chili
+ peppers during season. In season view the harvest is grouped by month. To drill down to weekly
+ view, right-click the selected month. On weekly view, the harvest of the month clicked is shown
+ by week.
+
+ The season view looks like this:
+ \image examples_stackedbarchartdrilldown1.png
+
+ Clicking on a month shows that month's harvest:
+ \image examples_stackedbarchartdrilldown2.png
+
+ First we define a drilldown series class, which adds categories to the stacked bar series and mapping for categories to other drilldown series.
+ The purpose of the drilldown series is to contain knowledge of the drilldown structure. The mapDrilldownSeries function maps the category to a given series. We can request the mapping for a category with the drilldownSeries(int category) function.
+
+ \snippet stackedbarchartdrilldown/drilldownseries.h 1
+
+ Next we define our own drilldown chart, which implements the handler for the mouse click. All QBarSeries derived classes send out the clicked(QBarSet*, int) signal when a series is clicked with the mouse. The parameter QBarSet contains the pointer to the clicked bar set and parameter int contains the index of the clicked category.
+
+ \snippet stackedbarchartdrilldown/drilldownchart.h 1
+
+ Now we have our drilldown classes and we can start using them.
+ First create the chart.
+
+ \snippet stackedbarchartdrilldown/main.cpp 1
+
+ We define the categories from which the drilldown series will be constructed.
+
+ \snippet stackedbarchartdrilldown/main.cpp 2
+
+ To create the drilldown structure, we first create our top level series, which we call seasonSeries. For each month in seasonSeries we create a drilldown series called weeklySeries which contains more detailed data for that month.
+ In weeklySeries, we use the drilldown handler to bring us back to seasonSeries. To do so we add mapping to the series. The seasonSeries is mapped to weeklySeries for each month. Every weeklySeries is mapped back to the seasonSeries.
+ To make mapping work, we connect the clicked signals from our series to the drilldownChart.
+
+ \snippet stackedbarchartdrilldown/main.cpp 3
+
+ When we have our drilldown structure ready, we can add the data to it. Here we generate a random crop for each plant in each week. The monthly crop is calculated from weekly crops and is set as value to the monthly series.
+
+ \snippet stackedbarchartdrilldown/main.cpp 4
+
+ Here we set the chart to show the top level series initially.
+
+ \snippet stackedbarchartdrilldown/main.cpp 5
+*/
diff --git a/src/charts/doc/src/examples-temperaturerecords.qdoc b/src/charts/doc/src/examples-temperaturerecords.qdoc
new file mode 100644
index 00000000..ce1c5998
--- /dev/null
+++ b/src/charts/doc/src/examples-temperaturerecords.qdoc
@@ -0,0 +1,46 @@
+/*!
+ \example temperaturerecords
+ \title Temperature records example
+ \ingroup qtcharts_examples
+
+ \brief The example shows how to create a bar chart with negative bars.
+
+ For our example we use temperature data.
+
+ \image examples_temperaturerecords.png
+
+ First we create two barsets and append the data to them. One set represents the minimum temperatures and another the maximum temperatures.
+
+ \snippet temperaturerecords/main.cpp 1
+
+ We create the series and append the barsets to it. The series takes ownership of the barsets.
+
+ \snippet temperaturerecords/main.cpp 2
+
+ Here we create the chart object and add the series to it. We set the title for the chart with setTitle, and then turn on animations of the series by calling
+ setAnimationOptions(QChart::SeriesAnimations)
+
+ \snippet temperaturerecords/main.cpp 3
+
+ To have categories displayed on an axis, we need to create a QBarCategoryAxis. Here we create a category axis with a list of categories and
+ set it to be the x-axis of the chart. The chart takes ownership of the axis. For y-axis we use the default axis, which is created and scaled to the series data
+ by calling createDefaultAxes of the chart. We change the range for the y-axis, since this gives nicer result than with autoscaling.
+
+ Note that the call for createDefaultAxes must be before we set the category axis. Otherwise the default axis will override the category axis.
+
+ \snippet temperaturerecords/main.cpp 4
+
+ We also want to show the legend. To do so, we get the legend pointer from the chart and set it to visible. We also place the legend to the bottom
+ of the chart by setting its alignment to Qt::AlignBottom.
+
+ \snippet temperaturerecords/main.cpp 5
+
+ Finally we add the chart onto a view. We also turn on the antialiasing for the chartView.
+
+ \snippet temperaturerecords/main.cpp 6
+
+ Chart is ready to be shown. We set the chart to be the central widget of the window.
+ We also set the size for the chart window and show it.
+
+ \snippet temperaturerecords/main.cpp 7
+*/
diff --git a/src/charts/doc/src/examples-zoomlinechart.qdoc b/src/charts/doc/src/examples-zoomlinechart.qdoc
new file mode 100644
index 00000000..f0ec866a
--- /dev/null
+++ b/src/charts/doc/src/examples-zoomlinechart.qdoc
@@ -0,0 +1,33 @@
+/*!
+ \example zoomlinechart
+ \title Zoom Line Example
+ \ingroup qtcharts_examples
+
+ \brief The example shows how to create your own custom zooming effect
+
+ The example shows how to create your own custom zooming effect with QRubberBand by using a mouse
+ and how to use touch gestures for paning and zooming.
+ \image examples_zoomlinechart1.png
+ \image examples_zoomlinechart2.png
+
+ Let's first create a line series with some example data.
+ \snippet zoomlinechart/main.cpp 1
+
+ Then we create a custom chart view by deriving from QChartView:
+ \snippet zoomlinechart/chartview.h 1
+
+ We override mouse and key event handling
+ \snippet zoomlinechart/chartview.h 2
+
+ Then we implement a custom logic for mouse and key events. For example pressing the '+' key will zoom in and pressing
+ the '-' key will zoom out.
+ \snippet zoomlinechart/chartview.cpp 1
+
+ We also create our own QChart:
+ \snippet zoomlinechart/chart.h 1
+
+ Where we can handle the gestures:
+ \snippet zoomlinechart/chart.cpp 1
+
+ Note that you will need to call grabGesture() to both QMainWindow and QChart.
+*/
diff --git a/src/charts/doc/src/index.qdoc b/src/charts/doc/src/index.qdoc
new file mode 100644
index 00000000..15408f24
--- /dev/null
+++ b/src/charts/doc/src/index.qdoc
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 QtCharts 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
+**
+****************************************************************************/
+
+/*!
+ \title Qt Charts
+ \page index.html
+ \keyword About
+
+ Qt Charts is a part of the Qt Enterprise addons package. It provides a set of easy to use chart
+ components which are available for Qt customers. It uses the Qt Graphics View
+ Framework, therefore charts can be easily integrated to modern user interfaces. Qt Charts can
+ be used as QWidgets, QGraphicsWidget, or QML types. Users can easily create impressive
+ graphs by selecting one of the charts themes.
+
+ \section1 Getting Started
+
+ To import Qt Charts QML types, add the following import statement to your \c .qml file:
+
+ \snippet doc_src_qmlcharts.cpp 0
+
+ If you intend to use Qt Charts C++ classes in your application, use the
+ following include and using directives:
+
+ \snippet doc_src_qtcharts.cpp 0
+
+ \note If you are only using a few classes from this module, we recommend including only those
+ specific classes instead of the whole module.
+
+ To link against the Qt Charts module, add this line to your \c qmake project file:
+
+ \snippet doc_src_qtcharts.pro 0
+
+ See the \l{Qt Charts Getting Started}{Getting started} page for further information on
+ how to use Qt Charts in your application.
+
+ \section1 References
+ \list
+ \li \l{Qt Charts C++ Classes}
+ \li \l{Qt Charts QML Types}
+ \endlist
+
+ Qt Charts comes with the following examples:
+
+ \annotatedlist qtcharts_examples
+
+*/
diff --git a/src/charts/doc/src/qtcharts.qdoc b/src/charts/doc/src/qtcharts.qdoc
new file mode 100644
index 00000000..16194833
--- /dev/null
+++ b/src/charts/doc/src/qtcharts.qdoc
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 QtCharts 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
+**
+****************************************************************************/
+
+/*!
+ \module Qt Charts
+ \title Qt Charts C++ Classes
+ \ingroup modules
+
+ \brief C++ classes for the Qt Charts API.
+
+ Charts API is built on top of Qt Graphics View Framework. Charts can be displayed as QGraphicsWidget using the QChart class. However
+ there is also the convenience class QChartView, which is QWidget based. These enable us to quickly use Qt Charts as a normal Qt widget.
+
+ Each chart type is represented by the QAbstractSeries derived class. To create charts, the users have to use an instance of the related
+ series class and add it to a QChart instance.
+ \code
+ QLineSeries* series = new QLineSeries();
+ series->add(0, 6);
+ series->add(2, 4);
+ ...
+ chartView->chart()->addSeries(series);
+ chartView->chart()->createDefaultAxes();
+ \endcode
+*/
+
+/*!
+ \qmlmodule QtCharts 2.0
+ \title Qt Charts QML Types
+ \ingroup qmlmodules
+
+ \brief QML types for the Qt Charts API.
+
+ The Qt Charts QML API is an intuitive and simple way to show charts in your QML
+ applications.
+
+ \table
+ \row
+ \li \br
+ Use the following QML to create a simple pie chart:
+ \br
+ \br
+ \snippet qmlpiechart/qml/qmlpiechart/main.qml 1
+ \snippet qmlpiechart/qml/qmlpiechart/main.qml 2
+ \snippet qmlpiechart/qml/qmlpiechart/main.qml 3
+ \li \inlineimage examples_qmlpiechart.png
+ \endtable
+
+ \note Since Qt Creator 3.0 the project created with Qt Quick Application wizard based on
+ Qt Quick 2 template uses QGuiApplication by default. As Qt Charts utilizes Qt Graphics View
+ Framework for drawing, QApplication must be used. The project created with the wizard is
+ usable with Qt Charts after the QGuiApplication is replaced with QApplication.
+
+ \section1 QML Types
+*/
+
+/*!
+ \group charts_examples
+ \ingroup all-examples
+ \title Qt Charts Examples
+
+ \brief Examples for the Qt Charts.
+
+ For some code examples, see one of the Qt Charts examples:
+
+ \section1 Examples
+
+ \annotatedlist qtcharts_examples
+*/
+
+/*!
+ \group qtcharts_getting_started
+ \title Qt Charts Getting Started
+
+ \section1 Installing the Qt Charts module
+
+ Use the \c {Package Manager} in \c {Maintenance Tool} or the \c {Online installer} to install
+ the Qt Charts module. The module can be found under \c {Qt Enterprise Add-Ons} in the
+ package manager.
+
+ After installation Qt Charts documentation and examples are available in Qt Creator.
+ Examples can be found on the examples page of Qt Creator by selecting the Qt Charts
+ component from the drop-down menu.
+
+ The source code is installed into the QtCharts folder under EnterpriseAddOns.
+
+ \section1 Building Qt Charts
+
+ To build the Qt Charts module from source code yourself, set up a command prompt with
+ an environment for building Qt applications, navigate to the directory containing
+ \c {qtcharts.pro}, and configure the project with qmake:
+ \code
+ qmake
+ \endcode
+
+ After running qmake, build the project with make:
+ \table
+ \header
+ \li OS \li Make command
+ \row
+ \li Linux \li make
+ \row
+ \li Windows (MinGw) \li mingw32-make
+ \row
+ \li Windows (MSVC) \li nmake
+ \row
+ \li OSX \li make
+ \endtable
+
+ The above generates the default makefiles for your configuration, which is typically
+ the release build if you are using precompiled binary Qt distribution. To build both debug
+ and release, or one specifically, use one of the following qmake lines instead.
+
+ For debug builds:
+ \code
+ qmake CONFIG+=debug
+ make
+ \endcode
+ or
+ \code
+ qmake CONFIG+=debug_and_release
+ make debug
+ \endcode
+
+ For release builds:
+ \code
+ qmake CONFIG+=release
+ make
+ \endcode
+ or
+ \code
+ qmake CONFIG+=debug_and_release
+ make release
+ \endcode
+
+ For both builds (Windows/OS X only):
+ \code
+ qmake CONFIG+="debug_and_release build_all"
+ make
+ \endcode
+
+ After building, install the module to your Qt directory:
+ \code
+ make install
+ \endcode
+
+ If you want to uninstall the module:
+ \code
+ make uninstall
+ \endcode
+
+ To build a statically linked version of the Qt Charts module, give the following commands:
+
+ \snippet doc_src_qtcharts.cpp 1
+
+ \section1 Running examples
+
+ Qt Charts examples are found under the \c examples subdirectory. To build and run a single
+ example, in this case qmlpolarchart, navigate to the example directory and enter the following
+ commands:
+
+ \snippet doc_src_qtcharts.cpp 2
+
+ \note On some platforms, such as Windows, the executable can be generated under debug or
+ release folders, depending on your build.
+
+ \section1 Creating a simple application
+
+ To create a simple application, start by creating a new Qt Gui Application project in Qt
+ Creator and add this line to the \c .pro file of the project:
+
+ \snippet doc_src_qtcharts.pro 0
+
+ In the \c main.cpp file, include the module headers and declare namespace usage:
+
+ \snippet doc_src_qtcharts.cpp 0
+
+ \note Since Qt Creator 3.0 the project created with Qt Quick Application wizard based on
+ Qt Quick 2 template uses QGuiApplication by default. As Qt Charts utilizes Qt Graphics View
+ Framework for drawing, QApplication must be used. The project created with the wizard is
+ usable with Qt Charts after the QGuiApplication is replaced with QApplication.
+
+ For further code examples, see one of the Qt Charts examples:
+
+ \annotatedlist qtcharts_examples
+*/
diff --git a/src/charts/doc/style/offline.css b/src/charts/doc/style/offline.css
new file mode 100644
index 00000000..7a728b49
--- /dev/null
+++ b/src/charts/doc/style/offline.css
@@ -0,0 +1,722 @@
+@media screen
+{
+
+ .qchart
+ {
+ width:1000px;
+ margin-left: auto;
+ margin-right: auto;
+ margin-top: 50px;
+ max-width:100%;
+ overflow-x: auto;
+ }
+
+ .qchart img
+ {
+ float:left;
+ }
+
+ .qchart table
+ {
+ width:1000px;
+ margin-top: 50px;
+ max-width:100%;
+ }
+
+/* basic elements */
+ html
+ {
+ color: #000000;
+ min-width: 1000px;
+ background: #FFFFFF;
+ }
+ table
+ {
+ border-collapse: collapse;
+ border-spacing: 0;
+ }
+ fieldset, img
+ {
+ border: 0;
+ max-width:100%;
+ }
+ address, caption, cite, code, dfn, em, strong, th, var, optgroup
+ {
+ font-style: inherit;
+ font-weight: inherit;
+ }
+ del, ins
+ {
+ text-decoration: none;
+ }
+ li
+ {
+ list-style: none;
+ }
+ ol li
+ {
+ list-style: decimal;
+ }
+ caption, th
+ {
+ text-align: left;
+ }
+ h1, h2, h3, h4, h5, h6
+ {
+ font-size: 100%;
+ }
+ q:before, q:after
+ {
+ content: '';
+ }
+ abbr, acronym
+ {
+ border: 0;
+ font-variant: normal;
+ }
+ sup, sub
+ {
+ vertical-align: baseline;
+ }
+ tt, .qmlreadonly span, .qmldefault span
+ {
+ word-spacing:0.5em;
+ }
+ legend
+ {
+ color: #000000;
+ }
+ strong
+ {
+ font-weight: bold;
+ }
+ em
+ {
+ font-style: italic;
+ }
+
+ body
+ {
+ margin-left: 0.5em;
+ margin-right: 0.5em;
+ }
+ a
+ {
+ color: #00732F;
+ text-decoration: none;
+ }
+ hr
+ {
+ background-color: #E6E6E6;
+ border: 1px solid #E6E6E6;
+ height: 1px;
+ width: 100%;
+ text-align: left;
+ margin: 1.5em 0 1.5em 0;
+ }
+
+ pre
+ {
+ border: 1px solid #DDDDDD;
+ -moz-border-radius: 0.7em 0.7em 0.7em 0.7em;
+ -webkit-border-radius: 0.7em 0.7em 0.7em 0.7em;
+ border-radius: 0.7em 0.7em 0.7em 0.7em;
+ margin: 0 1.5em 1em 1em;
+ padding: 1em 1em 1em 1em;
+ overflow-x: auto;
+ }
+ table, pre
+ {
+ -moz-border-radius: 0.7em 0.7em 0.7em 0.7em;
+ -webkit-border-radius: 0.7em 0.7em 0.7em 0.7em;
+ border-radius: 0.7em 0.7em 0.7em 0.7em;
+ background-color: #F6F6F6;
+ border: 1px solid #E6E6E6;
+ border-collapse: separate;
+ margin-bottom: 2.5em;
+ }
+ pre {
+ font-size: 90%;
+ display: block;
+ overflow:hidden;
+ }
+ thead
+ {
+ margin-top: 0.5em;
+ font-weight: bold
+ }
+ th
+ {
+ padding: 0.5em 1.5em 0.5em 1.5em;
+ background-color: #E1E1E1;
+ border-left: 1px solid #E6E6E6;
+ }
+ td
+ {
+ padding: 0.25em 1.5em 0.25em 2em;
+ }
+
+ td.rightAlign
+ {
+ padding: 0.25em 0.5em 0.25em 1em;
+ }
+ table tr.odd
+ {
+ border-left: 1px solid #E6E6E6;
+ background-color: #F6F6F6;
+ color: #66666E;
+ }
+ table tr.even
+ {
+ border-left: 1px solid #E6E6E6;
+ background-color: #ffffff;
+ color: #66666E;
+ }
+
+ div.float-left
+ {
+ float: left; margin-right: 2em
+ }
+ div.float-right
+ {
+ float: right; margin-left: 2em
+ }
+
+ span.comment
+ {
+ color: #008B00;
+ font-style: italic
+ }
+ span.string, span.char
+ {
+ color: #000084;
+ }
+ span.number
+ {
+ color: #a46200;
+ }
+ span.operator
+ {
+ color: #202020;
+ }
+ span.keyword
+ {
+ color: #840000;
+ }
+ span.name
+ {
+ color: black
+ }
+ span.type
+ {
+ font-weight: bold
+ }
+ span.type a:visited
+ {
+ color: #0F5300;
+ }
+ span.preprocessor
+ {
+ color: #404040
+ }
+/* end basic elements */
+
+/* font style elements */
+ .heading
+ {
+ font-weight: bold;
+ font-size: 125%;
+ }
+ .subtitle
+ {
+ font-size: 110%
+ }
+ .small-subtitle
+ {
+ font-size: 100%
+ }
+ .red
+ {
+ color:red;
+ }
+/* end font style elements */
+
+/* global settings*/
+ .header, .footer
+ {
+ display: block;
+ clear: both;
+ overflow: hidden;
+ }
+/* end global settings*/
+
+/* header elements */
+ .header .qtcharts
+ {
+ color: #00732F;
+ font-weight: bold;
+ font-size: 200%;
+ text-align: center;
+ margin: 10px 0px
+ }
+
+ .header .qtref
+ {
+ color: #00732F;
+ font-weight: bold;
+ font-size: 100%;
+ text-align: center;
+ }
+
+ .header .content
+ {
+ /* margin-bottom: 0.5em*/
+ }
+
+ .header .content img
+ {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+ width: 100px;
+ }
+
+ .naviNextPrevious
+ {
+ display: none
+ }
+ .header .breadcrumb
+ {
+ font-size: 100%;
+ padding: 0.5em 0 0.5em 1em;
+ margin: 0;
+ /*background-color: #393735;*/
+ font-weight: bold;
+ background: #7FBA2E url(../images/bg.png) repeat-x;
+ height: 20px;
+ border-bottom: 1px solid #d1d1d1;
+ }
+
+ .header .breadcrumb ul
+ {
+ margin: 0;
+ padding: 0;
+ }
+
+ .header .content
+ {
+ word-wrap: break-word;
+ }
+
+ .header .breadcrumb ul li
+ {
+ float: left;
+ /*background: url(../images/breadcrumb.png) no-repeat 0 3px;*/
+ padding-left: 1.5em;
+ margin-left: 1.5em;
+ }
+
+ .header .breadcrumb ul li.last
+ {
+ font-weight: normal;
+ }
+
+ .header .breadcrumb ul li a
+ {
+ color: #ffffff;
+ }
+
+ .header .breadcrumb ul li a:hover
+ {
+ color: #00732F;
+ text-decoration: none;
+ }
+
+ .header .breadcrumb ul li.first
+ {
+ background-image: none;
+ padding-left: 0;
+ margin-left: 0;
+ }
+
+ .header .content ol li {
+ background: none;
+ margin-bottom: 1.0em;
+ margin-left: 1.2em;
+ padding-left: 0
+ }
+
+ .header .content li
+ {
+ background: url(../images/bullet_sq.png) no-repeat 0 5px;
+ margin-bottom: 1em;
+ padding-left: 1.2em;
+ }
+
+/* end header elements */
+
+/* content elements */
+ .content h1
+ {
+ font-weight: bold;
+ font-size: 150%
+ }
+
+ .content h2
+ {
+ font-weight: bold;
+ font-size: 135%;
+ width: 100%;
+ }
+ .content h3
+ {
+ font-weight: bold;
+ font-size: 120%;
+ width: 100%;
+ }
+ .content table p
+ {
+ margin: 0
+ }
+ .content ul
+ {
+ padding-left: 2.5em;
+ }
+ .content li
+ {
+ padding-top: 0.25em;
+ padding-bottom: 0.25em;
+ }
+ .content ul img {
+ vertical-align: middle;
+ }
+
+ .content a:visited
+ {
+ color: #4c0033;
+ text-decoration: none;
+ }
+
+ .content a:visited:hover
+ {
+ color: #4c0033;
+ text-decoration: underline;
+ }
+
+ a:hover
+ {
+ color: #4c0033;
+ text-decoration: underline;
+ }
+ descr p a
+ {
+ text-decoration: underline;
+ }
+
+ .descr p a:visited
+ {
+ text-decoration: underline;
+ }
+
+ .alphaChar{
+ width:95%;
+ background-color:#F6F6F6;
+ border:1px solid #E6E6E6;
+ -moz-border-radius: 7px 7px 7px 7px;
+ border-radius: 7px 7px 7px 7px;
+ -webkit-border-radius: 7px 7px 7px 7px;
+ font-size:12pt;
+ padding-left:10px;
+ margin-top:10px;
+ margin-bottom:10px;
+ }
+ .flowList{
+ /*vertical-align:top;*/
+ /*margin:20px auto;*/
+
+ column-count:3;
+ -webkit-column-count:3;
+ -moz-column-count:3;
+/*
+ column-width:100%;
+ -webkit-column-width:200px;
+ -col-column-width:200px;
+*/
+ column-gap:41px;
+ -webkit-column-gap:41px;
+ -moz-column-gap:41px;
+
+ column-rule: 1px dashed #ccc;
+ -webkit-column-rule: 1px dashed #ccc;
+ -moz-column-rule: 1px dashed #ccc;
+ }
+
+ .flowList dl{
+ }
+ .flowList dd{
+ /*display:inline-block;*/
+ margin-left:10px;
+ min-width:250px;
+ line-height: 1.5;
+ min-width:100%;
+ min-height:15px;
+ }
+
+ .flowList dd a{
+ }
+
+ .content .flowList p{
+ padding:0px;
+ }
+
+ .content .alignedsummary
+ {
+ margin: 15px;
+ }
+
+
+ .qmltype
+ {
+ text-align: center;
+ font-size: 120%;
+ }
+ .qmlreadonly
+ {
+ padding-left: 5px;
+ float: right;
+ color: #254117;
+ }
+
+ .qmldefault
+ {
+ padding-left: 5px;
+ float: right;
+ color: red;
+ }
+
+ .qmldoc
+ {
+ }
+
+ .generic .alphaChar{
+ margin-top:5px;
+ }
+
+ .generic .odd .alphaChar{
+ background-color: #F6F6F6;
+ }
+
+ .generic .even .alphaChar{
+ background-color: #FFFFFF;
+ }
+
+ .memItemRight{
+ padding: 0.25em 1.5em 0.25em 0;
+ }
+ .highlightedCode
+ {
+ margin: 1.0em;
+ }
+ .annotated td {
+ padding: 0.25em 0.5em 0.25em 0.5em;
+ }
+
+ .header .content .toc ul
+ {
+ padding-left: 0px;
+ }
+
+ .content .toc h3 {
+ border-bottom: 0px;
+ margin-top: 10px;
+ }
+
+ .content .toc h3 a:hover {
+ color: #00732F;
+ text-decoration: none;
+ }
+
+ .content .toc .level2
+ {
+ margin-left: 1.5em;
+ }
+
+ .content .toc .level3
+ {
+ margin-left: 3.0em;
+ }
+
+ .content ul li
+ {
+ background: url(../images/bullet_sq.png) no-repeat 0 0.7em;
+ padding-left: 1em
+ }
+
+ .content .toc li
+ {
+ background: url(../images/bullet_dn.png) no-repeat 0 5px;
+ padding-left: 1em
+ }
+
+ .relpage
+ {
+ -moz-border-radius: 7px 7px 7px 7px;
+ -webkit-border-radius: 7px 7px 7px 7px;
+ border-radius: 7px 7px 7px 7px;
+ border: 1px solid #DDDDDD;
+ padding: 25px 25px;
+ clear: both;
+ }
+ .relpage ul
+ {
+ float: none;
+ padding: 1.5em;
+ }
+
+ h3.fn, span.fn
+ {
+ -moz-border-radius:7px 7px 7px 7px;
+ -webkit-border-radius:7px 7px 7px 7px;
+ border-radius:7px 7px 7px 7px;
+ background-color: #F6F6F6;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #E6E6E6;
+ font-weight: bold;
+ word-spacing:3px;
+ padding:3px 5px;
+ }
+
+ .functionIndex {
+ font-size:12pt;
+ word-spacing:10px;
+ margin-bottom:10px;
+ background-color: #F6F6F6;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #E6E6E6;
+ -moz-border-radius: 7px 7px 7px 7px;
+ -webkit-border-radius: 7px 7px 7px 7px;
+ border-radius: 7px 7px 7px 7px;
+ width:100%;
+ }
+
+ .centerAlign
+ {
+ text-align:center;
+ }
+
+ .rightAlign
+ {
+ text-align:right;
+ }
+
+ .leftAlign
+ {
+ text-align:left;
+ }
+
+ .topAlign{
+ vertical-align:top
+ }
+
+ .functionIndex a{
+ display:inline-block;
+ }
+
+/* end content elements */
+/* footer elements */
+
+ .footer
+ {
+ color: #393735;
+ font-size: 0.75em;
+ text-align: center;
+ padding-top: 1.5em;
+ padding-bottom: 1em;
+ background-color: #E6E7E8;
+ margin: 0;
+ }
+ .footer p
+ {
+ margin: 0.25em
+ }
+ .small
+ {
+ font-size: 0.5em;
+ }
+/* end footer elements */
+
+ .item {
+ float: left;
+ position: relative;
+ width: 100%;
+ overflow: hidden;
+ }
+
+
+ .item .primary {
+ margin-right: 220px;
+ position: relative;
+ }
+
+ .item hr {
+ margin-left: -220px;
+ }
+
+ .item .secondary {
+ float: right;
+ width: 200px;
+ position: relative;
+ }
+
+ .item .cols {
+ clear: both;
+ display: block;
+ }
+
+ .item .cols .col {
+ float: left;
+ margin-left: 1.5%;
+ }
+
+ .item .cols .col.first {
+ margin-left: 0;
+ }
+
+ .item .cols.two .col {
+ width: 45%;
+ }
+
+ .item .box {
+ margin: 0 0 10px 0;
+ }
+
+ .item .box h3 {
+ margin: 0 0 10px 0;
+ }
+
+ .cols.unclear {
+ clear:none;
+ }
+}
+
+/* end of screen media */
+
+/* start of print media */
+
+@media print
+{
+ input, textarea, .header, .footer, .toolbar, .feedback, .wrapper .hd, .wrapper .bd .sidebar, .wrapper .ft, #feedbackBox, #blurpage, .toc, .breadcrumb, .toolbar, .floatingResult
+ {
+ display: none;
+ background: none;
+ }
+ .content
+ {
+ background: none;
+ display: block;
+ width: 100%; margin: 0; float: none;
+ }
+}
+/* end of print media */
diff --git a/src/charts/domain/abstractdomain.cpp b/src/charts/domain/abstractdomain.cpp
new file mode 100644
index 00000000..c16e46d5
--- /dev/null
+++ b/src/charts/domain/abstractdomain.cpp
@@ -0,0 +1,265 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractdomain_p.h"
+#include "qabstractaxis_p.h"
+#include <qmath.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+AbstractDomain::AbstractDomain(QObject *parent)
+ : QObject(parent),
+ m_minX(0),
+ m_maxX(0),
+ m_minY(0),
+ m_maxY(0),
+ m_signalsBlocked(false),
+ m_zoomed(false),
+ m_zoomResetMinX(0),
+ m_zoomResetMaxX(0),
+ m_zoomResetMinY(0),
+ m_zoomResetMaxY(0)
+
+{
+}
+
+AbstractDomain::~AbstractDomain()
+{
+}
+
+void AbstractDomain::setSize(const QSizeF &size)
+{
+ if (m_size != size) {
+ m_size=size;
+ emit updated();
+ }
+}
+
+QSizeF AbstractDomain::size() const
+{
+ return m_size;
+}
+
+void AbstractDomain::setRangeX(qreal min, qreal max)
+{
+ setRange(min, max, m_minY, m_maxY);
+}
+
+void AbstractDomain::setRangeY(qreal min, qreal max)
+{
+ setRange(m_minX, m_maxX, min, max);
+}
+
+void AbstractDomain::setMinX(qreal min)
+{
+ setRange(min, m_maxX, m_minY, m_maxY);
+}
+
+void AbstractDomain::setMaxX(qreal max)
+{
+ setRange(m_minX, max, m_minY, m_maxY);
+}
+
+void AbstractDomain::setMinY(qreal min)
+{
+ setRange(m_minX, m_maxX, min, m_maxY);
+}
+
+void AbstractDomain::setMaxY(qreal max)
+{
+ setRange(m_minX, m_maxX, m_minY, max);
+}
+
+qreal AbstractDomain::spanX() const
+{
+ Q_ASSERT(m_maxX >= m_minX);
+ return m_maxX - m_minX;
+}
+
+qreal AbstractDomain::spanY() const
+{
+ Q_ASSERT(m_maxY >= m_minY);
+ return m_maxY - m_minY;
+}
+
+bool AbstractDomain::isEmpty() const
+{
+ return qFuzzyCompare(spanX(), 0) || qFuzzyCompare(spanY(), 0) || m_size.isEmpty();
+}
+
+QPointF AbstractDomain::calculateDomainPoint(const QPointF &point) const
+{
+ const qreal deltaX = m_size.width() / (m_maxX - m_minX);
+ const qreal deltaY = m_size.height() / (m_maxY - m_minY);
+ qreal x = point.x() / deltaX + m_minX;
+ qreal y = (point.y() - m_size.height()) / (-deltaY) + m_minY;
+ return QPointF(x, y);
+}
+
+// handlers
+
+void AbstractDomain::handleVerticalAxisRangeChanged(qreal min, qreal max)
+{
+ setRangeY(min, max);
+}
+
+void AbstractDomain::handleHorizontalAxisRangeChanged(qreal min, qreal max)
+{
+ setRangeX(min, max);
+}
+
+void AbstractDomain::blockRangeSignals(bool block)
+{
+ if (m_signalsBlocked!=block) {
+ m_signalsBlocked=block;
+ if (!block) {
+ emit rangeHorizontalChanged(m_minX,m_maxX);
+ emit rangeVerticalChanged(m_minY,m_maxY);
+ }
+ }
+}
+
+void AbstractDomain::zoomReset()
+{
+ if (m_zoomed) {
+ setRange(m_zoomResetMinX,
+ m_zoomResetMaxX,
+ m_zoomResetMinY,
+ m_zoomResetMaxY);
+ m_zoomed = false;
+ }
+}
+
+void AbstractDomain::storeZoomReset()
+{
+ if (!m_zoomed) {
+ m_zoomed = true;
+ m_zoomResetMinX = m_minX;
+ m_zoomResetMaxX = m_maxX;
+ m_zoomResetMinY = m_minY;
+ m_zoomResetMaxY = m_maxY;
+ }
+}
+
+//algorithm defined by Paul S.Heckbert GraphicalGems I
+
+void AbstractDomain::looseNiceNumbers(qreal &min, qreal &max, int &ticksCount)
+{
+ qreal range = niceNumber(max - min, true); //range with ceiling
+ qreal step = niceNumber(range / (ticksCount - 1), false);
+ min = qFloor(min / step);
+ max = qCeil(max / step);
+ ticksCount = int(max - min) + 1;
+ min *= step;
+ max *= step;
+}
+
+//nice numbers can be expressed as form of 1*10^n, 2* 10^n or 5*10^n
+
+qreal AbstractDomain::niceNumber(qreal x, bool ceiling)
+{
+ qreal z = qPow(10, qFloor(log10(x))); //find corresponding number of the form of 10^n than is smaller than x
+ qreal q = x / z; //q<10 && q>=1;
+
+ if (ceiling) {
+ if (q <= 1.0) q = 1;
+ else if (q <= 2.0) q = 2;
+ else if (q <= 5.0) q = 5;
+ else q = 10;
+ } else {
+ if (q < 1.5) q = 1;
+ else if (q < 3.0) q = 2;
+ else if (q < 7.0) q = 5;
+ else q = 10;
+ }
+ return q * z;
+}
+
+bool AbstractDomain::attachAxis(QAbstractAxis *axis)
+{
+ if (axis->orientation() == Qt::Vertical) {
+ QObject::connect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleVerticalAxisRangeChanged(qreal,qreal)));
+ QObject::connect(this, SIGNAL(rangeVerticalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
+ }
+
+ if (axis->orientation() == Qt::Horizontal) {
+ QObject::connect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleHorizontalAxisRangeChanged(qreal,qreal)));
+ QObject::connect(this, SIGNAL(rangeHorizontalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
+ }
+
+ return true;
+}
+
+bool AbstractDomain::detachAxis(QAbstractAxis *axis)
+{
+ if (axis->orientation() == Qt::Vertical) {
+ QObject::disconnect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleVerticalAxisRangeChanged(qreal,qreal)));
+ QObject::disconnect(this, SIGNAL(rangeVerticalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
+ }
+
+ if (axis->orientation() == Qt::Horizontal) {
+ QObject::disconnect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleHorizontalAxisRangeChanged(qreal,qreal)));
+ QObject::disconnect(this, SIGNAL(rangeHorizontalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
+ }
+
+ return true;
+}
+
+// operators
+
+bool QT_CHARTS_AUTOTEST_EXPORT operator== (const AbstractDomain &domain1, const AbstractDomain &domain2)
+{
+ return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
+ && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
+ && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
+ && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
+}
+
+
+bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const AbstractDomain &domain1, const AbstractDomain &domain2)
+{
+ return !(domain1 == domain2);
+}
+
+
+QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const AbstractDomain &domain)
+{
+#ifdef QT_NO_TEXTSTREAM
+ Q_UNUSED(domain)
+#else
+ dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
+#endif
+ return dbg.maybeSpace();
+}
+
+// This function adjusts min/max ranges to failsafe values if negative/zero values are attempted.
+void AbstractDomain::adjustLogDomainRanges(qreal &min, qreal &max)
+{
+ if (min <= 0) {
+ min = 1.0;
+ if (max <= min)
+ max = min + 1.0;
+ }
+}
+
+
+#include "moc_abstractdomain_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/domain/abstractdomain_p.h b/src/charts/domain/abstractdomain_p.h
new file mode 100644
index 00000000..dfd4025f
--- /dev/null
+++ b/src/charts/domain/abstractdomain_p.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 ABSTRACTDOMAIN_H
+#define ABSTRACTDOMAIN_H
+#include "qchartglobal.h"
+#include <QRectF>
+#include <QSizeF>
+#include <QDebug>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QAbstractAxis;
+
+class QT_CHARTS_AUTOTEST_EXPORT AbstractDomain: public QObject
+{
+ Q_OBJECT
+public:
+ enum DomainType { UndefinedDomain,
+ XYDomain,
+ XLogYDomain,
+ LogXYDomain,
+ LogXLogYDomain,
+ XYPolarDomain,
+ XLogYPolarDomain,
+ LogXYPolarDomain,
+ LogXLogYPolarDomain };
+public:
+ explicit AbstractDomain(QObject *object = 0);
+ virtual ~AbstractDomain();
+
+ virtual void setSize(const QSizeF &size);
+ QSizeF size() const;
+
+ virtual DomainType type() = 0;
+
+ virtual void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY) = 0;
+ void setRangeX(qreal min, qreal max);
+ void setRangeY(qreal min, qreal max);
+ void setMinX(qreal min);
+ void setMaxX(qreal max);
+ void setMinY(qreal min);
+ void setMaxY(qreal max);
+
+ qreal minX() const { return m_minX; }
+ qreal maxX() const { return m_maxX; }
+ qreal minY() const { return m_minY; }
+ qreal maxY() const { return m_maxY; }
+
+ qreal spanX() const;
+ qreal spanY() const;
+ bool isEmpty() const;
+
+ void blockRangeSignals(bool block);
+ bool rangeSignalsBlocked() const { return m_signalsBlocked; }
+
+ void zoomReset();
+ void storeZoomReset();
+ bool isZoomed() { return m_zoomed; }
+
+ friend bool QT_CHARTS_AUTOTEST_EXPORT operator== (const AbstractDomain &domain1, const AbstractDomain &domain2);
+ friend bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const AbstractDomain &domain1, const AbstractDomain &domain2);
+ friend QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const AbstractDomain &domain);
+
+ virtual void zoomIn(const QRectF &rect) = 0;
+ virtual void zoomOut(const QRectF &rect) = 0;
+ virtual void move(qreal dx, qreal dy) = 0;
+
+ virtual QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const = 0;
+ virtual QPointF calculateDomainPoint(const QPointF &point) const = 0;
+ virtual QVector<QPointF> calculateGeometryPoints(const QList<QPointF> &vector) const = 0;
+
+ virtual bool attachAxis(QAbstractAxis *axis);
+ virtual bool detachAxis(QAbstractAxis *axis);
+
+ static void looseNiceNumbers(qreal &min, qreal &max, int &ticksCount);
+ static qreal niceNumber(qreal x, bool ceiling);
+
+Q_SIGNALS:
+ void updated();
+ void rangeHorizontalChanged(qreal min, qreal max);
+ void rangeVerticalChanged(qreal min, qreal max);
+
+public Q_SLOTS:
+ void handleVerticalAxisRangeChanged(qreal min,qreal max);
+ void handleHorizontalAxisRangeChanged(qreal min,qreal max);
+
+protected:
+ void adjustLogDomainRanges(qreal &min, qreal &max);
+
+ qreal m_minX;
+ qreal m_maxX;
+ qreal m_minY;
+ qreal m_maxY;
+ QSizeF m_size;
+ bool m_signalsBlocked;
+ bool m_zoomed;
+ qreal m_zoomResetMinX;
+ qreal m_zoomResetMaxX;
+ qreal m_zoomResetMinY;
+ qreal m_zoomResetMaxY;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // ABSTRACTDOMAIN_H
diff --git a/src/charts/domain/domain.pri b/src/charts/domain/domain.pri
new file mode 100644
index 00000000..ab4fcfce
--- /dev/null
+++ b/src/charts/domain/domain.pri
@@ -0,0 +1,28 @@
+#Subdirectiores are defined here, because qt creator doesn't handle nested include(foo.pri) chains very well.
+
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+
+SOURCES += \
+ $$PWD/abstractdomain.cpp \
+ $$PWD/polardomain.cpp \
+ $$PWD/xydomain.cpp \
+ $$PWD/xypolardomain.cpp \
+ $$PWD/xlogydomain.cpp \
+ $$PWD/xlogypolardomain.cpp \
+ $$PWD/logxydomain.cpp \
+ $$PWD/logxypolardomain.cpp \
+ $$PWD/logxlogydomain.cpp \
+ $$PWD/logxlogypolardomain.cpp
+
+PRIVATE_HEADERS += \
+ $$PWD/abstractdomain_p.h \
+ $$PWD/polardomain_p.h \
+ $$PWD/xydomain_p.h \
+ $$PWD/xypolardomain_p.h \
+ $$PWD/xlogydomain_p.h \
+ $$PWD/xlogypolardomain_p.h \
+ $$PWD/logxydomain_p.h \
+ $$PWD/logxypolardomain_p.h \
+ $$PWD/logxlogydomain_p.h \
+ $$PWD/logxlogypolardomain_p.h
diff --git a/src/charts/domain/logxlogydomain.cpp b/src/charts/domain/logxlogydomain.cpp
new file mode 100644
index 00000000..a2e781e3
--- /dev/null
+++ b/src/charts/domain/logxlogydomain.cpp
@@ -0,0 +1,278 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "logxlogydomain_p.h"
+#include "qabstractaxis_p.h"
+#include "qlogvalueaxis.h"
+#include <qmath.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+LogXLogYDomain::LogXLogYDomain(QObject *parent)
+ : AbstractDomain(parent),
+ m_logLeftX(0),
+ m_logRightX(1),
+ m_logBaseX(10),
+ m_logLeftY(0),
+ m_logRightY(1),
+ m_logBaseY(10)
+{
+}
+
+LogXLogYDomain::~LogXLogYDomain()
+{
+}
+
+void LogXLogYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
+{
+ bool axisXChanged = false;
+ bool axisYChanged = false;
+
+ adjustLogDomainRanges(minX, maxX);
+ adjustLogDomainRanges(minY, maxY);
+
+ if (!qFuzzyIsNull(m_minX - minX) || !qFuzzyIsNull(m_maxX - maxX)) {
+ m_minX = minX;
+ m_maxX = maxX;
+ axisXChanged = true;
+ qreal logMinX = log10(m_minX) / log10(m_logBaseX);
+ qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
+ m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
+ m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
+ if(!m_signalsBlocked)
+ emit rangeHorizontalChanged(m_minX, m_maxX);
+ }
+
+ if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
+ m_minY = minY;
+ m_maxY = maxY;
+ axisYChanged = true;
+ qreal logMinY = log10(m_minY) / log10(m_logBaseY);
+ qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
+ m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
+ m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
+ if (!m_signalsBlocked)
+ emit rangeVerticalChanged(m_minY, m_maxY);
+ }
+
+ if (axisXChanged || axisYChanged)
+ emit updated();
+}
+
+void LogXLogYDomain::zoomIn(const QRectF &rect)
+{
+ storeZoomReset();
+ qreal logLeftX = rect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
+ qreal logRightX = rect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
+ qreal leftX = qPow(m_logBaseX, logLeftX);
+ qreal rightX = qPow(m_logBaseX, logRightX);
+ qreal minX = leftX < rightX ? leftX : rightX;
+ qreal maxX = leftX > rightX ? leftX : rightX;
+
+ qreal logLeftY = m_logRightY - rect.bottom() * (m_logRightY - m_logLeftY) / m_size.height();
+ qreal logRightY = m_logRightY - rect.top() * (m_logRightY - m_logLeftY) / m_size.height();
+ qreal leftY = qPow(m_logBaseY, logLeftY);
+ qreal rightY = qPow(m_logBaseY, logRightY);
+ qreal minY = leftY < rightY ? leftY : rightY;
+ qreal maxY = leftY > rightY ? leftY : rightY;
+
+ setRange(minX, maxX, minY, maxY);
+}
+
+void LogXLogYDomain::zoomOut(const QRectF &rect)
+{
+ storeZoomReset();
+ const qreal factorX = m_size.width() / rect.width();
+ const qreal factorY = m_size.height() / rect.height();
+
+ qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 - factorX);
+ qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 + factorX);
+ qreal leftX = qPow(m_logBaseX, logLeftX);
+ qreal rightX = qPow(m_logBaseX, logRIghtX);
+ qreal minX = leftX < rightX ? leftX : rightX;
+ qreal maxX = leftX > rightX ? leftX : rightX;
+
+ qreal newLogMinY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 - factorY);
+ qreal newLogMaxY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 + factorY);
+ qreal leftY = qPow(m_logBaseY, newLogMinY);
+ qreal rightY = qPow(m_logBaseY, newLogMaxY);
+ qreal minY = leftY < rightY ? leftY : rightY;
+ qreal maxY = leftY > rightY ? leftY : rightY;
+
+ setRange(minX, maxX, minY, maxY);
+}
+
+void LogXLogYDomain::move(qreal dx, qreal dy)
+{
+ qreal stepX = dx * qAbs(m_logRightX - m_logLeftX) / m_size.width();
+ qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX);
+ qreal rightX = qPow(m_logBaseX, m_logRightX + stepX);
+ qreal minX = leftX < rightX ? leftX : rightX;
+ qreal maxX = leftX > rightX ? leftX : rightX;
+
+ qreal stepY = dy * (m_logRightY - m_logLeftY) / m_size.height();
+ qreal leftY = qPow(m_logBaseY, m_logLeftY + stepY);
+ qreal rightY = qPow(m_logBaseY, m_logRightY + stepY);
+ qreal minY = leftY < rightY ? leftY : rightY;
+ qreal maxY = leftY > rightY ? leftY : rightY;
+
+ setRange(minX, maxX, minY, maxY);
+}
+
+QPointF LogXLogYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
+{
+ const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX);
+ const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
+ qreal x(0);
+ qreal y(0);
+ if (point.x() > 0 && point.y() > 0) {
+ x = (log10(point.x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
+ y = (log10(point.y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
+ ok = true;
+ } else {
+ qWarning() << "Logarithms of zero and negative values are undefined.";
+ ok = false;
+ if (point.x() > 0)
+ x = (log10(point.x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
+ else
+ x = 0;
+ if (point.y() > 0) {
+ y = (log10(point.y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY
+ + m_size.height();
+ } else {
+ y = m_size.height();
+ }
+ }
+ return QPointF(x, y);
+}
+
+QVector<QPointF> LogXLogYDomain::calculateGeometryPoints(const QList<QPointF> &vector) const
+{
+ const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX);
+ const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
+
+ QVector<QPointF> result;
+ result.resize(vector.count());
+
+ for (int i = 0; i < vector.count(); ++i) {
+ if (vector[i].x() > 0 && vector[i].y() > 0) {
+ qreal x = (log10(vector[i].x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
+ qreal y = (log10(vector[i].y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
+ result[i].setX(x);
+ result[i].setY(y);
+ } else {
+ qWarning() << "Logarithms of zero and negative values are undefined.";
+ return QVector<QPointF>();
+ }
+ }
+ return result;
+}
+
+QPointF LogXLogYDomain::calculateDomainPoint(const QPointF &point) const
+{
+ const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX);
+ const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
+ qreal x = qPow(m_logBaseX, m_logLeftX + point.x() / deltaX);
+ qreal y = qPow(m_logBaseY, m_logLeftY + (m_size.height() - point.y()) / deltaY);
+ return QPointF(x, y);
+}
+
+bool LogXLogYDomain::attachAxis(QAbstractAxis *axis)
+{
+ AbstractDomain::attachAxis(axis);
+ QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
+
+ if (logAxis && logAxis->orientation() == Qt::Vertical) {
+ QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
+ handleVerticalAxisBaseChanged(logAxis->base());
+ }
+
+ if (logAxis && logAxis->orientation() == Qt::Horizontal) {
+ QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
+ handleHorizontalAxisBaseChanged(logAxis->base());
+ }
+
+ return true;
+}
+
+bool LogXLogYDomain::detachAxis(QAbstractAxis *axis)
+{
+ AbstractDomain::detachAxis(axis);
+ QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
+
+ if (logAxis && logAxis->orientation() == Qt::Vertical)
+ QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
+
+ if (logAxis && logAxis->orientation() == Qt::Horizontal)
+ QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
+
+ return true;
+}
+
+void LogXLogYDomain::handleVerticalAxisBaseChanged(qreal baseY)
+{
+ m_logBaseY = baseY;
+ qreal logMinY = log10(m_minY) / log10(m_logBaseY);
+ qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
+ m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
+ m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
+ emit updated();
+}
+
+void LogXLogYDomain::handleHorizontalAxisBaseChanged(qreal baseX)
+{
+ m_logBaseX = baseX;
+ qreal logMinX = log10(m_minX) / log10(m_logBaseX);
+ qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
+ m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
+ m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
+ emit updated();
+}
+
+// operators
+
+bool QT_CHARTS_AUTOTEST_EXPORT operator== (const LogXLogYDomain &domain1, const LogXLogYDomain &domain2)
+{
+ return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
+ && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
+ && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
+ && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
+}
+
+
+bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const LogXLogYDomain &domain1, const LogXLogYDomain &domain2)
+{
+ return !(domain1 == domain2);
+}
+
+
+QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXLogYDomain &domain)
+{
+#ifdef QT_NO_TEXTSTREAM
+ Q_UNUSED(domain)
+#else
+ dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
+#endif
+ return dbg.maybeSpace();
+}
+
+#include "moc_logxlogydomain_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/domain/logxlogydomain_p.h b/src/charts/domain/logxlogydomain_p.h
new file mode 100644
index 00000000..eeb7d7f2
--- /dev/null
+++ b/src/charts/domain/logxlogydomain_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 LOGXLOGYDOMAIN_H
+#define LOGXLOGYDOMAIN_H
+#include "abstractdomain_p.h"
+#include <QRectF>
+#include <QSizeF>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QT_CHARTS_AUTOTEST_EXPORT LogXLogYDomain: public AbstractDomain
+{
+ Q_OBJECT
+public:
+ explicit LogXLogYDomain(QObject *object = 0);
+ virtual ~LogXLogYDomain();
+
+ DomainType type(){ return AbstractDomain::LogXLogYDomain;}
+
+ void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY);
+
+ friend bool QT_CHARTS_AUTOTEST_EXPORT operator== (const LogXLogYDomain &domain1, const LogXLogYDomain &domain2);
+ friend bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const LogXLogYDomain &domain1, const LogXLogYDomain &domain2);
+ friend QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXLogYDomain &domain);
+
+ void zoomIn(const QRectF &rect);
+ void zoomOut(const QRectF &rect);
+ void move(qreal dx, qreal dy);
+
+ QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const;
+ QPointF calculateDomainPoint(const QPointF &point) const;
+ QVector<QPointF> calculateGeometryPoints(const QList<QPointF> &vector) const;
+
+ bool attachAxis(QAbstractAxis *axis);
+ bool detachAxis(QAbstractAxis *axis);
+
+public Q_SLOTS:
+ void handleVerticalAxisBaseChanged(qreal baseY);
+ void handleHorizontalAxisBaseChanged(qreal baseX);
+
+private:
+ qreal m_logLeftX;
+ qreal m_logRightX;
+ qreal m_logBaseX;
+ qreal m_logLeftY;
+ qreal m_logRightY;
+ qreal m_logBaseY;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // LOGXLOGYDOMAIN_H
diff --git a/src/charts/domain/logxlogypolardomain.cpp b/src/charts/domain/logxlogypolardomain.cpp
new file mode 100644
index 00000000..33d8eff9
--- /dev/null
+++ b/src/charts/domain/logxlogypolardomain.cpp
@@ -0,0 +1,273 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "logxlogypolardomain_p.h"
+#include "qabstractaxis_p.h"
+#include "qlogvalueaxis.h"
+#include <qmath.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+LogXLogYPolarDomain::LogXLogYPolarDomain(QObject *parent)
+ : PolarDomain(parent),
+ m_logLeftX(0),
+ m_logRightX(1),
+ m_logBaseX(10),
+ m_logInnerY(0),
+ m_logOuterY(1),
+ m_logBaseY(10)
+{
+}
+
+LogXLogYPolarDomain::~LogXLogYPolarDomain()
+{
+}
+
+void LogXLogYPolarDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
+{
+ bool axisXChanged = false;
+ bool axisYChanged = false;
+
+ adjustLogDomainRanges(minX, maxX);
+ adjustLogDomainRanges(minY, maxY);
+
+ if (!qFuzzyCompare(m_minX, minX) || !qFuzzyCompare(m_maxX, maxX)) {
+ m_minX = minX;
+ m_maxX = maxX;
+ axisXChanged = true;
+ qreal logMinX = log10(m_minX) / log10(m_logBaseX);
+ qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
+ m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
+ m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
+ if (!m_signalsBlocked)
+ emit rangeHorizontalChanged(m_minX, m_maxX);
+ }
+
+ if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
+ m_minY = minY;
+ m_maxY = maxY;
+ axisYChanged = true;
+ qreal logMinY = log10(m_minY) / log10(m_logBaseY);
+ qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
+ m_logInnerY = logMinY < logMaxY ? logMinY : logMaxY;
+ m_logOuterY = logMinY > logMaxY ? logMinY : logMaxY;
+ if (!m_signalsBlocked)
+ emit rangeVerticalChanged(m_minY, m_maxY);
+ }
+
+ if (axisXChanged || axisYChanged)
+ emit updated();
+}
+
+void LogXLogYPolarDomain::zoomIn(const QRectF &rect)
+{
+ storeZoomReset();
+ qreal logLeftX = rect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
+ qreal logRightX = rect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
+ qreal leftX = qPow(m_logBaseX, logLeftX);
+ qreal rightX = qPow(m_logBaseX, logRightX);
+ qreal minX = leftX < rightX ? leftX : rightX;
+ qreal maxX = leftX > rightX ? leftX : rightX;
+
+ qreal logLeftY = m_logOuterY - rect.bottom() * (m_logOuterY - m_logInnerY) / m_size.height();
+ qreal logRightY = m_logOuterY - rect.top() * (m_logOuterY - m_logInnerY) / m_size.height();
+ qreal leftY = qPow(m_logBaseY, logLeftY);
+ qreal rightY = qPow(m_logBaseY, logRightY);
+ qreal minY = leftY < rightY ? leftY : rightY;
+ qreal maxY = leftY > rightY ? leftY : rightY;
+
+ setRange(minX, maxX, minY, maxY);
+}
+
+void LogXLogYPolarDomain::zoomOut(const QRectF &rect)
+{
+ storeZoomReset();
+ const qreal factorX = m_size.width() / rect.width();
+
+ qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2.0 * (1.0 - factorX);
+ qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2.0 * (1.0 + factorX);
+ qreal leftX = qPow(m_logBaseX, logLeftX);
+ qreal rightX = qPow(m_logBaseX, logRIghtX);
+ qreal minX = leftX < rightX ? leftX : rightX;
+ qreal maxX = leftX > rightX ? leftX : rightX;
+
+ const qreal factorY = m_size.height() / rect.height();
+ qreal newLogMinY = m_logInnerY + (m_logOuterY - m_logInnerY) / 2.0 * (1.0 - factorY);
+ qreal newLogMaxY = m_logInnerY + (m_logOuterY - m_logInnerY) / 2.0 * (1.0 + factorY);
+ qreal leftY = qPow(m_logBaseY, newLogMinY);
+ qreal rightY = qPow(m_logBaseY, newLogMaxY);
+ qreal minY = leftY < rightY ? leftY : rightY;
+ qreal maxY = leftY > rightY ? leftY : rightY;
+
+ setRange(minX, maxX, minY, maxY);
+}
+
+void LogXLogYPolarDomain::move(qreal dx, qreal dy)
+{
+ qreal stepX = dx * (m_logRightX - m_logLeftX) / m_size.width();
+ qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX);
+ qreal rightX = qPow(m_logBaseX, m_logRightX + stepX);
+ qreal minX = leftX < rightX ? leftX : rightX;
+ qreal maxX = leftX > rightX ? leftX : rightX;
+
+ qreal stepY = dy * (m_logOuterY - m_logInnerY) / m_radius;
+ qreal leftY = qPow(m_logBaseY, m_logInnerY + stepY);
+ qreal rightY = qPow(m_logBaseY, m_logOuterY + stepY);
+ qreal minY = leftY < rightY ? leftY : rightY;
+ qreal maxY = leftY > rightY ? leftY : rightY;
+
+ setRange(minX, maxX, minY, maxY);
+}
+
+qreal LogXLogYPolarDomain::toAngularCoordinate(qreal value, bool &ok) const
+{
+ qreal retVal;
+ if (value <= 0) {
+ ok = false;
+ retVal = 0.0;
+ } else {
+ ok = true;
+ const qreal tickSpan = 360.0 / qAbs(m_logRightX - m_logLeftX);
+ const qreal logValue = log10(value) / log10(m_logBaseX);
+ const qreal valueDelta = logValue - m_logLeftX;
+
+ retVal = valueDelta * tickSpan;
+ }
+ return retVal;
+}
+
+qreal LogXLogYPolarDomain::toRadialCoordinate(qreal value, bool &ok) const
+{
+ qreal retVal;
+ if (value <= 0) {
+ ok = false;
+ retVal = 0.0;
+ } else {
+ ok = true;
+ const qreal tickSpan = m_radius / qAbs(m_logOuterY - m_logInnerY);
+ const qreal logValue = log10(value) / log10(m_logBaseY);
+ const qreal valueDelta = logValue - m_logInnerY;
+
+ retVal = valueDelta * tickSpan;
+
+ if (retVal < 0.0)
+ retVal = 0.0;
+ }
+ return retVal;
+}
+
+QPointF LogXLogYPolarDomain::calculateDomainPoint(const QPointF &point) const
+{
+ if (point == m_center)
+ return QPointF(0.0, m_minY);
+
+ QLineF line(m_center, point);
+ qreal a = 90.0 - line.angle();
+ if (a < 0.0)
+ a += 360.0;
+
+ const qreal deltaX = 360.0 / qAbs(m_logRightX - m_logLeftX);
+ a = qPow(m_logBaseX, m_logLeftX + (a / deltaX));
+
+ const qreal deltaY = m_radius / qAbs(m_logOuterY - m_logInnerY);
+ qreal r = qPow(m_logBaseY, m_logInnerY + (line.length() / deltaY));
+
+ return QPointF(a, r);
+}
+
+bool LogXLogYPolarDomain::attachAxis(QAbstractAxis *axis)
+{
+ AbstractDomain::attachAxis(axis);
+ QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
+
+ if (logAxis && logAxis->orientation() == Qt::Horizontal) {
+ QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
+ handleHorizontalAxisBaseChanged(logAxis->base());
+ } else if (logAxis && logAxis->orientation() == Qt::Vertical){
+ QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
+ handleVerticalAxisBaseChanged(logAxis->base());
+ }
+
+ return true;
+}
+
+bool LogXLogYPolarDomain::detachAxis(QAbstractAxis *axis)
+{
+ AbstractDomain::detachAxis(axis);
+ QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
+
+ if (logAxis && logAxis->orientation() == Qt::Horizontal)
+ QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
+ else if (logAxis && logAxis->orientation() == Qt::Vertical)
+ QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
+
+ return true;
+}
+
+void LogXLogYPolarDomain::handleHorizontalAxisBaseChanged(qreal baseX)
+{
+ m_logBaseX = baseX;
+ qreal logMinX = log10(m_minX) / log10(m_logBaseX);
+ qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
+ m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
+ m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
+ emit updated();
+}
+
+void LogXLogYPolarDomain::handleVerticalAxisBaseChanged(qreal baseY)
+{
+ m_logBaseY = baseY;
+ qreal logMinY = log10(m_minY) / log10(m_logBaseY);
+ qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
+ m_logInnerY = logMinY < logMaxY ? logMinY : logMaxY;
+ m_logOuterY = logMinY > logMaxY ? logMinY : logMaxY;
+ emit updated();
+}
+
+// operators
+
+bool QT_CHARTS_AUTOTEST_EXPORT operator== (const LogXLogYPolarDomain &domain1, const LogXLogYPolarDomain &domain2)
+{
+ return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
+ && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
+ && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
+ && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
+}
+
+
+bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const LogXLogYPolarDomain &domain1, const LogXLogYPolarDomain &domain2)
+{
+ return !(domain1 == domain2);
+}
+
+
+QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXLogYPolarDomain &domain)
+{
+#ifdef QT_NO_TEXTSTREAM
+ Q_UNUSED(domain)
+#else
+ dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
+#endif
+ return dbg.maybeSpace();
+}
+
+#include "moc_logxlogypolardomain_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/domain/logxlogypolardomain_p.h b/src/charts/domain/logxlogypolardomain_p.h
new file mode 100644
index 00000000..853e5d3c
--- /dev/null
+++ b/src/charts/domain/logxlogypolardomain_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 LOGXLOGYPOLARDOMAIN_H
+#define LOGXLOGYPOLARDOMAIN_H
+#include "polardomain_p.h"
+#include <QRectF>
+#include <QSizeF>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QT_CHARTS_AUTOTEST_EXPORT LogXLogYPolarDomain: public PolarDomain
+{
+ Q_OBJECT
+public:
+ explicit LogXLogYPolarDomain(QObject *object = 0);
+ virtual ~LogXLogYPolarDomain();
+
+ DomainType type() { return AbstractDomain::LogXLogYPolarDomain; }
+
+ void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY);
+
+ friend bool QT_CHARTS_AUTOTEST_EXPORT operator== (const LogXLogYPolarDomain &domain1, const LogXLogYPolarDomain &domain2);
+ friend bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const LogXLogYPolarDomain &domain1, const LogXLogYPolarDomain &domain2);
+ friend QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXLogYPolarDomain &domain);
+
+ void zoomIn(const QRectF &rect);
+ void zoomOut(const QRectF &rect);
+ void move(qreal dx, qreal dy);
+
+ QPointF calculateDomainPoint(const QPointF &point) const;
+
+ bool attachAxis(QAbstractAxis *axis);
+ bool detachAxis(QAbstractAxis *axis);
+
+public Q_SLOTS:
+ void handleVerticalAxisBaseChanged(qreal baseY);
+ void handleHorizontalAxisBaseChanged(qreal baseX);
+
+protected:
+ qreal toAngularCoordinate(qreal value, bool &ok) const;
+ qreal toRadialCoordinate(qreal value, bool &ok) const;
+
+private:
+ qreal m_logLeftX;
+ qreal m_logRightX;
+ qreal m_logBaseX;
+ qreal m_logInnerY;
+ qreal m_logOuterY;
+ qreal m_logBaseY;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // LOGXLOGYPOLARDOMAIN_H
diff --git a/src/charts/domain/logxydomain.cpp b/src/charts/domain/logxydomain.cpp
new file mode 100644
index 00000000..2901bd26
--- /dev/null
+++ b/src/charts/domain/logxydomain.cpp
@@ -0,0 +1,245 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "logxydomain_p.h"
+#include "qabstractaxis_p.h"
+#include "qlogvalueaxis.h"
+#include <qmath.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+LogXYDomain::LogXYDomain(QObject *parent)
+ : AbstractDomain(parent),
+ m_logLeftX(0),
+ m_logRightX(1),
+ m_logBaseX(10)
+{
+}
+
+LogXYDomain::~LogXYDomain()
+{
+}
+
+void LogXYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
+{
+ bool axisXChanged = false;
+ bool axisYChanged = false;
+
+ adjustLogDomainRanges(minX, maxX);
+
+ if (!qFuzzyCompare(m_minX, minX) || !qFuzzyCompare(m_maxX, maxX)) {
+ m_minX = minX;
+ m_maxX = maxX;
+ axisXChanged = true;
+ qreal logMinX = log10(m_minX) / log10(m_logBaseX);
+ qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
+ m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
+ m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
+ if(!m_signalsBlocked)
+ emit rangeHorizontalChanged(m_minX, m_maxX);
+ }
+
+ if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
+ m_minY = minY;
+ m_maxY = maxY;
+ axisYChanged = true;
+ if (!m_signalsBlocked)
+ emit rangeVerticalChanged(m_minY, m_maxY);
+ }
+
+ if (axisXChanged || axisYChanged)
+ emit updated();
+}
+
+void LogXYDomain::zoomIn(const QRectF &rect)
+{
+ storeZoomReset();
+ qreal logLeftX = rect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
+ qreal logRightX = rect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
+ qreal leftX = qPow(m_logBaseX, logLeftX);
+ qreal rightX = qPow(m_logBaseX, logRightX);
+ qreal minX = leftX < rightX ? leftX : rightX;
+ qreal maxX = leftX > rightX ? leftX : rightX;
+
+ qreal dy = spanY() / m_size.height();
+ qreal minY = m_minY;
+ qreal maxY = m_maxY;
+
+ minY = maxY - dy * rect.bottom();
+ maxY = maxY - dy * rect.top();
+
+ setRange(minX, maxX, minY, maxY);
+}
+
+void LogXYDomain::zoomOut(const QRectF &rect)
+{
+ storeZoomReset();
+ const qreal factorX = m_size.width() / rect.width();
+
+ qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 - factorX);
+ qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 + factorX);
+ qreal leftX = qPow(m_logBaseX, logLeftX);
+ qreal rightX = qPow(m_logBaseX, logRIghtX);
+ qreal minX = leftX < rightX ? leftX : rightX;
+ qreal maxX = leftX > rightX ? leftX : rightX;
+
+ qreal dy = spanY() / rect.height();
+ qreal minY = m_minY;
+ qreal maxY = m_maxY;
+
+ maxY = minY + dy * rect.bottom();
+ minY = maxY - dy * m_size.height();
+
+ setRange(minX, maxX, minY, maxY);
+}
+
+void LogXYDomain::move(qreal dx, qreal dy)
+{
+ qreal stepX = dx * (m_logRightX - m_logLeftX) / m_size.width();
+ qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX);
+ qreal rightX = qPow(m_logBaseX, m_logRightX + stepX);
+ qreal minX = leftX < rightX ? leftX : rightX;
+ qreal maxX = leftX > rightX ? leftX : rightX;
+
+ qreal y = spanY() / m_size.height();
+ qreal minY = m_minY;
+ qreal maxY = m_maxY;
+
+ if (dy != 0) {
+ minY = minY + y * dy;
+ maxY = maxY + y * dy;
+ }
+ setRange(minX, maxX, minY, maxY);
+}
+
+QPointF LogXYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
+{
+ const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX);
+ const qreal deltaY = m_size.height() / (m_maxY - m_minY);
+
+ qreal x(0);
+ qreal y = (point.y() - m_minY) * -deltaY + m_size.height();
+ if (point.x() > 0) {
+ x = (log10(point.x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
+ ok = true;
+ } else {
+ x = 0;
+ qWarning() << "Logarithms of zero and negative values are undefined.";
+ ok = false;
+ }
+ return QPointF(x, y);
+}
+
+QVector<QPointF> LogXYDomain::calculateGeometryPoints(const QList<QPointF> &vector) const
+{
+ const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX);
+ const qreal deltaY = m_size.height() / (m_maxY - m_minY);
+
+ QVector<QPointF> result;
+ result.resize(vector.count());
+
+ for (int i = 0; i < vector.count(); ++i) {
+ if (vector[i].x() > 0) {
+ qreal x = (log10(vector[i].x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
+ qreal y = (vector[i].y() - m_minY) * -deltaY + m_size.height();
+ result[i].setX(x);
+ result[i].setY(y);
+ } else {
+ qWarning() << "Logarithms of zero and negative values are undefined.";
+ return QVector<QPointF>();
+ }
+
+ }
+ return result;
+}
+
+QPointF LogXYDomain::calculateDomainPoint(const QPointF &point) const
+{
+ const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX);
+ const qreal deltaY = m_size.height() / (m_maxY - m_minY);
+ qreal x = qPow(m_logBaseX, m_logLeftX + point.x() / deltaX);
+ qreal y = (point.y() - m_size.height()) / (-deltaY) + m_minY;
+ return QPointF(x, y);
+}
+
+bool LogXYDomain::attachAxis(QAbstractAxis *axis)
+{
+ AbstractDomain::attachAxis(axis);
+ QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
+
+ if (logAxis && logAxis->orientation() == Qt::Horizontal) {
+ QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
+ handleHorizontalAxisBaseChanged(logAxis->base());
+ }
+
+ return true;
+}
+
+bool LogXYDomain::detachAxis(QAbstractAxis *axis)
+{
+ AbstractDomain::detachAxis(axis);
+ QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
+
+ if (logAxis && logAxis->orientation() == Qt::Horizontal)
+ QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
+
+ return true;
+}
+
+void LogXYDomain::handleHorizontalAxisBaseChanged(qreal baseX)
+{
+ m_logBaseX = baseX;
+ qreal logMinX = log10(m_minX) / log10(m_logBaseX);
+ qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
+ m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
+ m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
+ emit updated();
+}
+
+// operators
+
+bool QT_CHARTS_AUTOTEST_EXPORT operator== (const LogXYDomain &domain1, const LogXYDomain &domain2)
+{
+ return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
+ && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
+ && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
+ && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
+}
+
+
+bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const LogXYDomain &domain1, const LogXYDomain &domain2)
+{
+ return !(domain1 == domain2);
+}
+
+
+QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXYDomain &domain)
+{
+#ifdef QT_NO_TEXTSTREAM
+ Q_UNUSED(domain)
+#else
+ dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
+#endif
+ return dbg.maybeSpace();
+}
+
+#include "moc_logxydomain_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/domain/logxydomain_p.h b/src/charts/domain/logxydomain_p.h
new file mode 100644
index 00000000..a9b507c4
--- /dev/null
+++ b/src/charts/domain/logxydomain_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 LOGXYDOMAIN_H
+#define LOGXYDOMAIN_H
+#include "abstractdomain_p.h"
+#include <QRectF>
+#include <QSizeF>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QT_CHARTS_AUTOTEST_EXPORT LogXYDomain: public AbstractDomain
+{
+ Q_OBJECT
+public:
+ explicit LogXYDomain(QObject *object = 0);
+ virtual ~LogXYDomain();
+
+ DomainType type(){ return AbstractDomain::LogXYDomain;}
+
+ void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY);
+
+ friend bool QT_CHARTS_AUTOTEST_EXPORT operator== (const LogXYDomain &domain1, const LogXYDomain &domain2);
+ friend bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const LogXYDomain &domain1, const LogXYDomain &domain2);
+ friend QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXYDomain &domain);
+
+ void zoomIn(const QRectF &rect);
+ void zoomOut(const QRectF &rect);
+ void move(qreal dx, qreal dy);
+
+ QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const;
+ QPointF calculateDomainPoint(const QPointF &point) const;
+ QVector<QPointF> calculateGeometryPoints(const QList<QPointF> &vector) const;
+
+ bool attachAxis(QAbstractAxis *axis);
+ bool detachAxis(QAbstractAxis *axis);
+
+public Q_SLOTS:
+ void handleHorizontalAxisBaseChanged(qreal baseX);
+
+private:
+ qreal m_logLeftX;
+ qreal m_logRightX;
+ qreal m_logBaseX;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // LOGXYDOMAIN_H
diff --git a/src/charts/domain/logxypolardomain.cpp b/src/charts/domain/logxypolardomain.cpp
new file mode 100644
index 00000000..bcbac505
--- /dev/null
+++ b/src/charts/domain/logxypolardomain.cpp
@@ -0,0 +1,242 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "logxypolardomain_p.h"
+#include "qabstractaxis_p.h"
+#include "qlogvalueaxis.h"
+#include <qmath.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+LogXYPolarDomain::LogXYPolarDomain(QObject *parent)
+ : PolarDomain(parent),
+ m_logLeftX(0),
+ m_logRightX(1),
+ m_logBaseX(10)
+{
+}
+
+LogXYPolarDomain::~LogXYPolarDomain()
+{
+}
+
+void LogXYPolarDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
+{
+ bool axisXChanged = false;
+ bool axisYChanged = false;
+
+ adjustLogDomainRanges(minX, maxX);
+
+ if (!qFuzzyCompare(m_minX, minX) || !qFuzzyCompare(m_maxX, maxX)) {
+ m_minX = minX;
+ m_maxX = maxX;
+ axisXChanged = true;
+ qreal logMinX = log10(m_minX) / log10(m_logBaseX);
+ qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
+ m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
+ m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
+ if (!m_signalsBlocked)
+ emit rangeHorizontalChanged(m_minX, m_maxX);
+ }
+
+ if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
+ m_minY = minY;
+ m_maxY = maxY;
+ axisYChanged = true;
+ if (!m_signalsBlocked)
+ emit rangeVerticalChanged(m_minY, m_maxY);
+ }
+
+ if (axisXChanged || axisYChanged)
+ emit updated();
+}
+
+void LogXYPolarDomain::zoomIn(const QRectF &rect)
+{
+ storeZoomReset();
+ qreal logLeftX = rect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
+ qreal logRightX = rect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
+ qreal leftX = qPow(m_logBaseX, logLeftX);
+ qreal rightX = qPow(m_logBaseX, logRightX);
+ qreal minX = leftX < rightX ? leftX : rightX;
+ qreal maxX = leftX > rightX ? leftX : rightX;
+
+ qreal dy = spanY() / m_size.height();
+ qreal minY = m_minY;
+ qreal maxY = m_maxY;
+
+ minY = maxY - dy * rect.bottom();
+ maxY = maxY - dy * rect.top();
+
+ setRange(minX, maxX, minY, maxY);
+}
+
+void LogXYPolarDomain::zoomOut(const QRectF &rect)
+{
+ storeZoomReset();
+ const qreal factorX = m_size.width() / rect.width();
+
+ qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2.0 * (1.0 - factorX);
+ qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2.0 * (1.0 + factorX);
+ qreal leftX = qPow(m_logBaseX, logLeftX);
+ qreal rightX = qPow(m_logBaseX, logRIghtX);
+ qreal minX = leftX < rightX ? leftX : rightX;
+ qreal maxX = leftX > rightX ? leftX : rightX;
+
+ qreal dy = spanY() / rect.height();
+ qreal minY = m_minY;
+ qreal maxY = m_maxY;
+
+ maxY = minY + dy * rect.bottom();
+ minY = maxY - dy * m_size.height();
+
+ setRange(minX, maxX, minY, maxY);
+}
+
+void LogXYPolarDomain::move(qreal dx, qreal dy)
+{
+ qreal stepX = dx * (m_logRightX - m_logLeftX) / m_size.width();
+ qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX);
+ qreal rightX = qPow(m_logBaseX, m_logRightX + stepX);
+ qreal minX = leftX < rightX ? leftX : rightX;
+ qreal maxX = leftX > rightX ? leftX : rightX;
+
+ qreal y = spanY() / m_radius;
+ qreal minY = m_minY;
+ qreal maxY = m_maxY;
+
+ if (dy != 0) {
+ minY = minY + y * dy;
+ maxY = maxY + y * dy;
+ }
+ setRange(minX, maxX, minY, maxY);
+}
+
+qreal LogXYPolarDomain::toAngularCoordinate(qreal value, bool &ok) const
+{
+ qreal retVal;
+ if (value <= 0) {
+ ok = false;
+ retVal = 0.0;
+ } else {
+ ok = true;
+ const qreal tickSpan = 360.0 / qAbs(m_logRightX - m_logLeftX);
+ const qreal logValue = log10(value) / log10(m_logBaseX);
+ const qreal valueDelta = logValue - m_logLeftX;
+
+ retVal = valueDelta * tickSpan;
+ }
+ return retVal;
+}
+
+qreal LogXYPolarDomain::toRadialCoordinate(qreal value, bool &ok) const
+{
+ ok = true;
+ if (value < m_minY)
+ value = m_minY;
+
+ // Dont limit the max. The drawing should clip the stuff that goes out of the grid
+ qreal f = (value - m_minY) / (m_maxY - m_minY);
+
+ return f * m_radius;
+}
+
+QPointF LogXYPolarDomain::calculateDomainPoint(const QPointF &point) const
+{
+ if (point == m_center)
+ return QPointF(0.0, m_minY);
+
+ QLineF line(m_center, point);
+ qreal a = 90.0 - line.angle();
+ if (a < 0.0)
+ a += 360.0;
+
+ const qreal deltaX = 360.0 / qAbs(m_logRightX - m_logLeftX);
+ a = qPow(m_logBaseX, m_logLeftX + (a / deltaX));
+
+ qreal r = m_minY + ((m_maxY - m_minY) * (line.length() / m_radius));
+
+ return QPointF(a, r);
+}
+
+bool LogXYPolarDomain::attachAxis(QAbstractAxis *axis)
+{
+ AbstractDomain::attachAxis(axis);
+ QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
+
+ if (logAxis && logAxis->orientation() == Qt::Horizontal) {
+ QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
+ handleHorizontalAxisBaseChanged(logAxis->base());
+ }
+
+ return true;
+}
+
+bool LogXYPolarDomain::detachAxis(QAbstractAxis *axis)
+{
+ AbstractDomain::detachAxis(axis);
+ QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
+
+ if (logAxis && logAxis->orientation() == Qt::Horizontal)
+ QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
+
+ return true;
+}
+
+void LogXYPolarDomain::handleHorizontalAxisBaseChanged(qreal baseX)
+{
+ m_logBaseX = baseX;
+ qreal logMinX = log10(m_minX) / log10(m_logBaseX);
+ qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
+ m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
+ m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
+ emit updated();
+}
+
+// operators
+
+bool QT_CHARTS_AUTOTEST_EXPORT operator== (const LogXYPolarDomain &domain1, const LogXYPolarDomain &domain2)
+{
+ return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
+ && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
+ && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
+ && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
+}
+
+
+bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const LogXYPolarDomain &domain1, const LogXYPolarDomain &domain2)
+{
+ return !(domain1 == domain2);
+}
+
+
+QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXYPolarDomain &domain)
+{
+#ifdef QT_NO_TEXTSTREAM
+ Q_UNUSED(domain)
+#else
+ dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
+#endif
+ return dbg.maybeSpace();
+}
+
+#include "moc_logxypolardomain_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/domain/logxypolardomain_p.h b/src/charts/domain/logxypolardomain_p.h
new file mode 100644
index 00000000..6234b593
--- /dev/null
+++ b/src/charts/domain/logxypolardomain_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 LOGXYPOLARDOMAIN_H
+#define LOGXYPOLARDOMAIN_H
+#include "polardomain_p.h"
+#include <QRectF>
+#include <QSizeF>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QT_CHARTS_AUTOTEST_EXPORT LogXYPolarDomain: public PolarDomain
+{
+ Q_OBJECT
+public:
+ explicit LogXYPolarDomain(QObject *object = 0);
+ virtual ~LogXYPolarDomain();
+
+ DomainType type() { return AbstractDomain::LogXYPolarDomain; }
+
+ void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY);
+
+ friend bool QT_CHARTS_AUTOTEST_EXPORT operator== (const LogXYPolarDomain &domain1, const LogXYPolarDomain &domain2);
+ friend bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const LogXYPolarDomain &domain1, const LogXYPolarDomain &domain2);
+ friend QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXYPolarDomain &domain);
+
+ void zoomIn(const QRectF &rect);
+ void zoomOut(const QRectF &rect);
+ void move(qreal dx, qreal dy);
+
+ QPointF calculateDomainPoint(const QPointF &point) const;
+
+ bool attachAxis(QAbstractAxis *axis);
+ bool detachAxis(QAbstractAxis *axis);
+
+public Q_SLOTS:
+ void handleHorizontalAxisBaseChanged(qreal baseX);
+
+protected:
+ qreal toAngularCoordinate(qreal value, bool &ok) const;
+ qreal toRadialCoordinate(qreal value, bool &ok) const;
+
+private:
+ qreal m_logLeftX;
+ qreal m_logRightX;
+ qreal m_logBaseX;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // LOGXYPOLARDOMAIN_H
diff --git a/src/charts/domain/polardomain.cpp b/src/charts/domain/polardomain.cpp
new file mode 100644
index 00000000..1c01071e
--- /dev/null
+++ b/src/charts/domain/polardomain.cpp
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "polardomain_p.h"
+#include "qabstractaxis_p.h"
+#include <qmath.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+PolarDomain::PolarDomain(QObject *parent)
+ : AbstractDomain(parent)
+{
+}
+
+PolarDomain::~PolarDomain()
+{
+}
+
+void PolarDomain::setSize(const QSizeF &size)
+{
+ Q_ASSERT(size.width() == size.height());
+ m_radius = size.height() / 2.0;
+ m_center = QPointF(m_radius, m_radius);
+ AbstractDomain::setSize(size);
+}
+
+QPointF PolarDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
+{
+ qreal r = 0.0;
+ qreal a = toAngularCoordinate(point.x(), ok);
+ if (ok)
+ r = toRadialCoordinate(point.y(), ok);
+ if (ok) {
+ return m_center + polarCoordinateToPoint(a, r);
+ } else {
+ qWarning() << "Logarithm of negative value is undefined. Empty layout returned.";
+ return QPointF();
+ }
+}
+
+QVector<QPointF> PolarDomain::calculateGeometryPoints(const QList<QPointF> &vector) const
+{
+ QVector<QPointF> result;
+ result.resize(vector.count());
+ bool ok;
+ qreal r = 0.0;
+ qreal a = 0.0;
+
+ for (int i = 0; i < vector.count(); ++i) {
+ a = toAngularCoordinate(vector[i].x(), ok);
+ if (ok)
+ r = toRadialCoordinate(vector[i].y(), ok);
+ if (ok) {
+ result[i] = m_center + polarCoordinateToPoint(a, r);
+ } else {
+ qWarning() << "Logarithm of negative value is undefined. Empty layout returned.";
+ return QVector<QPointF>();
+ }
+ }
+
+ return result;
+}
+
+QPointF PolarDomain::polarCoordinateToPoint(qreal angularCoordinate, qreal radialCoordinate) const
+{
+ qreal dx = qSin(angularCoordinate * (M_PI / 180)) * radialCoordinate;
+ qreal dy = qCos(angularCoordinate * (M_PI / 180)) * radialCoordinate;
+
+ return QPointF(dx, -dy);
+}
+
+#include "moc_polardomain_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/domain/polardomain_p.h b/src/charts/domain/polardomain_p.h
new file mode 100644
index 00000000..06c2993c
--- /dev/null
+++ b/src/charts/domain/polardomain_p.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 POLARDOMAIN_H
+#define POLARDOMAIN_H
+#include "abstractdomain_p.h"
+#include <QRectF>
+#include <QSizeF>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QT_CHARTS_AUTOTEST_EXPORT PolarDomain: public AbstractDomain
+{
+ Q_OBJECT
+public:
+ explicit PolarDomain(QObject *object = 0);
+ virtual ~PolarDomain();
+
+ void setSize(const QSizeF &size);
+
+ QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const;
+ QVector<QPointF> calculateGeometryPoints(const QList<QPointF> &vector) const;
+
+ virtual qreal toAngularCoordinate(qreal value, bool &ok) const = 0;
+ virtual qreal toRadialCoordinate(qreal value, bool &ok) const = 0;
+
+protected:
+ QPointF polarCoordinateToPoint(qreal angularCoordinate, qreal radialCoordinate) const;
+
+ QPointF m_center;
+ qreal m_radius;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // POLARDOMAIN_H
diff --git a/src/charts/domain/xlogydomain.cpp b/src/charts/domain/xlogydomain.cpp
new file mode 100644
index 00000000..d13bbb67
--- /dev/null
+++ b/src/charts/domain/xlogydomain.cpp
@@ -0,0 +1,241 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "xlogydomain_p.h"
+#include "qabstractaxis_p.h"
+#include "qlogvalueaxis.h"
+#include <qmath.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+XLogYDomain::XLogYDomain(QObject *parent)
+ : AbstractDomain(parent),
+ m_logLeftY(0),
+ m_logRightY(1),
+ m_logBaseY(10)
+{
+}
+
+XLogYDomain::~XLogYDomain()
+{
+}
+
+void XLogYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
+{
+ bool axisXChanged = false;
+ bool axisYChanged = false;
+
+ adjustLogDomainRanges(minY, maxY);
+
+ if (!qFuzzyIsNull(m_minX - minX) || !qFuzzyIsNull(m_maxX - maxX)) {
+ m_minX = minX;
+ m_maxX = maxX;
+ axisXChanged = true;
+ if(!m_signalsBlocked)
+ emit rangeHorizontalChanged(m_minX, m_maxX);
+ }
+
+ if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
+ m_minY = minY;
+ m_maxY = maxY;
+ axisYChanged = true;
+ qreal logMinY = log10(m_minY) / log10(m_logBaseY);
+ qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
+ m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
+ m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
+ if (!m_signalsBlocked)
+ emit rangeVerticalChanged(m_minY, m_maxY);
+ }
+
+ if (axisXChanged || axisYChanged)
+ emit updated();
+}
+
+void XLogYDomain::zoomIn(const QRectF &rect)
+{
+ storeZoomReset();
+ qreal dx = spanX() / m_size.width();
+ qreal maxX = m_maxX;
+ qreal minX = m_minX;
+
+ maxX = minX + dx * rect.right();
+ minX = minX + dx * rect.left();
+
+ qreal logLeftY = m_logRightY - rect.bottom() * (m_logRightY - m_logLeftY) / m_size.height();
+ qreal logRightY = m_logRightY - rect.top() * (m_logRightY - m_logLeftY) / m_size.height();
+ qreal leftY = qPow(m_logBaseY, logLeftY);
+ qreal rightY = qPow(m_logBaseY, logRightY);
+ qreal minY = leftY < rightY ? leftY : rightY;
+ qreal maxY = leftY > rightY ? leftY : rightY;
+
+ setRange(minX, maxX, minY, maxY);
+}
+
+void XLogYDomain::zoomOut(const QRectF &rect)
+{
+ storeZoomReset();
+ qreal dx = spanX() / rect.width();
+ qreal maxX = m_maxX;
+ qreal minX = m_minX;
+
+ minX = maxX - dx * rect.right();
+ maxX = minX + dx * m_size.width();
+
+ const qreal factorY = m_size.height() / rect.height();
+ qreal newLogMinY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 - factorY);
+ qreal newLogMaxY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 + factorY);
+ qreal leftY = qPow(m_logBaseY, newLogMinY);
+ qreal rightY = qPow(m_logBaseY, newLogMaxY);
+ qreal minY = leftY < rightY ? leftY : rightY;
+ qreal maxY = leftY > rightY ? leftY : rightY;
+
+ setRange(minX, maxX, minY, maxY);
+}
+
+void XLogYDomain::move(qreal dx, qreal dy)
+{
+ qreal x = spanX() / m_size.width();
+ qreal maxX = m_maxX;
+ qreal minX = m_minX;
+
+ if (dx != 0) {
+ minX = minX + x * dx;
+ maxX = maxX + x * dx;
+ }
+
+ qreal stepY = dy * (m_logRightY - m_logLeftY) / m_size.height();
+ qreal leftY = qPow(m_logBaseY, m_logLeftY + stepY);
+ qreal rightY = qPow(m_logBaseY, m_logRightY + stepY);
+ qreal minY = leftY < rightY ? leftY : rightY;
+ qreal maxY = leftY > rightY ? leftY : rightY;
+
+ setRange(minX, maxX, minY, maxY);
+}
+
+QPointF XLogYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
+{
+ const qreal deltaX = m_size.width() / (m_maxX - m_minX);
+ const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
+
+ qreal x = (point.x() - m_minX) * deltaX;
+ qreal y(0);
+ if (point.y() > 0) {
+ y = (log10(point.y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
+ ok = true;
+ } else {
+ y = m_size.height();
+ qWarning() << "Logarithms of zero and negative values are undefined.";
+ ok = false;
+ }
+ return QPointF(x, y);
+}
+
+QVector<QPointF> XLogYDomain::calculateGeometryPoints(const QList<QPointF> &vector) const
+{
+ const qreal deltaX = m_size.width() / (m_maxX - m_minX);
+ const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
+
+ QVector<QPointF> result;
+ result.resize(vector.count());
+
+ for (int i = 0; i < vector.count(); ++i) {
+ if (vector[i].y() > 0) {
+ qreal x = (vector[i].x() - m_minX) * deltaX;
+ qreal y = (log10(vector[i].y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
+ result[i].setX(x);
+ result[i].setY(y);
+ } else {
+ qWarning() << "Logarithms of zero and negative values are undefined.";
+ return QVector<QPointF>();
+ }
+ }
+ return result;
+}
+
+QPointF XLogYDomain::calculateDomainPoint(const QPointF &point) const
+{
+ const qreal deltaX = m_size.width() / (m_maxX - m_minX);
+ const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
+ qreal x = point.x() / deltaX + m_minX;
+ qreal y = qPow(m_logBaseY, m_logLeftY + (m_size.height() - point.y()) / deltaY);
+ return QPointF(x, y);
+}
+
+bool XLogYDomain::attachAxis(QAbstractAxis *axis)
+{
+ QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
+
+ if (logAxis && logAxis->orientation() == Qt::Vertical) {
+ QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
+ handleVerticalAxisBaseChanged(logAxis->base());
+ }
+ return AbstractDomain::attachAxis(axis);
+}
+
+bool XLogYDomain::detachAxis(QAbstractAxis *axis)
+{
+ QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
+
+ if (logAxis && logAxis->orientation() == Qt::Vertical)
+ QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
+
+ return AbstractDomain::detachAxis(axis);
+}
+
+void XLogYDomain::handleVerticalAxisBaseChanged(qreal baseY)
+{
+ m_logBaseY = baseY;
+ qreal logMinY = log10(m_minY) / log10(m_logBaseY);
+ qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
+ m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
+ m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
+ emit updated();
+}
+
+// operators
+
+bool QT_CHARTS_AUTOTEST_EXPORT operator== (const XLogYDomain &domain1, const XLogYDomain &domain2)
+{
+ return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
+ && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
+ && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
+ && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
+}
+
+
+bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const XLogYDomain &domain1, const XLogYDomain &domain2)
+{
+ return !(domain1 == domain2);
+}
+
+
+QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const XLogYDomain &domain)
+{
+#ifdef QT_NO_TEXTSTREAM
+ Q_UNUSED(domain)
+#else
+ dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
+#endif
+ return dbg.maybeSpace();
+}
+
+#include "moc_xlogydomain_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/domain/xlogydomain_p.h b/src/charts/domain/xlogydomain_p.h
new file mode 100644
index 00000000..8d14d4a7
--- /dev/null
+++ b/src/charts/domain/xlogydomain_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 XLOGYDOMAIN_H
+#define XLOGYDOMAIN_H
+#include "abstractdomain_p.h"
+#include <QRectF>
+#include <QSizeF>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QT_CHARTS_AUTOTEST_EXPORT XLogYDomain: public AbstractDomain
+{
+ Q_OBJECT
+public:
+ explicit XLogYDomain(QObject *object = 0);
+ virtual ~XLogYDomain();
+
+ DomainType type(){ return AbstractDomain::XLogYDomain;};
+
+ void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY);
+
+ friend bool QT_CHARTS_AUTOTEST_EXPORT operator== (const XLogYDomain &domain1, const XLogYDomain &domain2);
+ friend bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const XLogYDomain &domain1, const XLogYDomain &domain2);
+ friend QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const XLogYDomain &domain);
+
+ void zoomIn(const QRectF &rect);
+ void zoomOut(const QRectF &rect);
+ void move(qreal dx, qreal dy);
+
+ QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const;
+ QPointF calculateDomainPoint(const QPointF &point) const;
+ QVector<QPointF> calculateGeometryPoints(const QList<QPointF> &vector) const;
+
+ bool attachAxis(QAbstractAxis *axis);
+ bool detachAxis(QAbstractAxis *axis);
+
+public Q_SLOTS:
+ void handleVerticalAxisBaseChanged(qreal baseY);
+
+private:
+ qreal m_logLeftY;
+ qreal m_logRightY;
+ qreal m_logBaseY;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // XLOGYDOMAIN_H
diff --git a/src/charts/domain/xlogypolardomain.cpp b/src/charts/domain/xlogypolardomain.cpp
new file mode 100644
index 00000000..76c92c51
--- /dev/null
+++ b/src/charts/domain/xlogypolardomain.cpp
@@ -0,0 +1,237 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "xlogypolardomain_p.h"
+#include "qabstractaxis_p.h"
+#include "qlogvalueaxis.h"
+#include <qmath.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+XLogYPolarDomain::XLogYPolarDomain(QObject *parent)
+ : PolarDomain(parent),
+ m_logInnerY(0),
+ m_logOuterY(1),
+ m_logBaseY(10)
+{
+}
+
+XLogYPolarDomain::~XLogYPolarDomain()
+{
+}
+
+void XLogYPolarDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
+{
+ bool axisXChanged = false;
+ bool axisYChanged = false;
+
+ adjustLogDomainRanges(minY, maxY);
+
+ if (!qFuzzyIsNull(m_minX - minX) || !qFuzzyIsNull(m_maxX - maxX)) {
+ m_minX = minX;
+ m_maxX = maxX;
+ axisXChanged = true;
+ if (!m_signalsBlocked)
+ emit rangeHorizontalChanged(m_minX, m_maxX);
+ }
+
+ if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
+ m_minY = minY;
+ m_maxY = maxY;
+ axisYChanged = true;
+ qreal logMinY = log10(m_minY) / log10(m_logBaseY);
+ qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
+ m_logInnerY = logMinY < logMaxY ? logMinY : logMaxY;
+ m_logOuterY = logMinY > logMaxY ? logMinY : logMaxY;
+ if (!m_signalsBlocked)
+ emit rangeVerticalChanged(m_minY, m_maxY);
+ }
+
+ if (axisXChanged || axisYChanged)
+ emit updated();
+}
+
+void XLogYPolarDomain::zoomIn(const QRectF &rect)
+{
+ storeZoomReset();
+ qreal dx = spanX() / m_size.width();
+ qreal maxX = m_maxX;
+ qreal minX = m_minX;
+
+ maxX = minX + dx * rect.right();
+ minX = minX + dx * rect.left();
+
+ qreal logLeftY = m_logOuterY - rect.bottom() * (m_logOuterY - m_logInnerY) / m_size.height();
+ qreal logRightY = m_logOuterY - rect.top() * (m_logOuterY - m_logInnerY) / m_size.height();
+ qreal leftY = qPow(m_logBaseY, logLeftY);
+ qreal rightY = qPow(m_logBaseY, logRightY);
+ qreal minY = leftY < rightY ? leftY : rightY;
+ qreal maxY = leftY > rightY ? leftY : rightY;
+
+ setRange(minX, maxX, minY, maxY);
+}
+
+void XLogYPolarDomain::zoomOut(const QRectF &rect)
+{
+ storeZoomReset();
+ qreal dx = spanX() / rect.width();
+ qreal maxX = m_maxX;
+ qreal minX = m_minX;
+
+ minX = maxX - dx * rect.right();
+ maxX = minX + dx * m_size.width();
+
+ const qreal factorY = m_size.height() / rect.height();
+ qreal newLogMinY = m_logInnerY + (m_logOuterY - m_logInnerY) / 2.0 * (1.0 - factorY);
+ qreal newLogMaxY = m_logInnerY + (m_logOuterY - m_logInnerY) / 2.0 * (1.0 + factorY);
+ qreal leftY = qPow(m_logBaseY, newLogMinY);
+ qreal rightY = qPow(m_logBaseY, newLogMaxY);
+ qreal minY = leftY < rightY ? leftY : rightY;
+ qreal maxY = leftY > rightY ? leftY : rightY;
+
+ setRange(minX, maxX, minY, maxY);
+}
+
+void XLogYPolarDomain::move(qreal dx, qreal dy)
+{
+ qreal x = spanX() / 360.0;
+
+ qreal maxX = m_maxX;
+ qreal minX = m_minX;
+
+ if (dx != 0) {
+ minX = minX + x * dx;
+ maxX = maxX + x * dx;
+ }
+
+ qreal stepY = dy * (m_logOuterY - m_logInnerY) / m_radius;
+ qreal leftY = qPow(m_logBaseY, m_logInnerY + stepY);
+ qreal rightY = qPow(m_logBaseY, m_logOuterY + stepY);
+ qreal minY = leftY < rightY ? leftY : rightY;
+ qreal maxY = leftY > rightY ? leftY : rightY;
+
+ setRange(minX, maxX, minY, maxY);
+}
+
+qreal XLogYPolarDomain::toAngularCoordinate(qreal value, bool &ok) const
+{
+ ok = true;
+ qreal f = (value - m_minX) / (m_maxX - m_minX);
+ return f * 360.0;
+}
+
+qreal XLogYPolarDomain::toRadialCoordinate(qreal value, bool &ok) const
+{
+ qreal retVal;
+ if (value <= 0) {
+ ok = false;
+ retVal = 0.0;
+ } else {
+ ok = true;
+ const qreal tickSpan = m_radius / qAbs(m_logOuterY - m_logInnerY);
+ const qreal logValue = log10(value) / log10(m_logBaseY);
+ const qreal valueDelta = logValue - m_logInnerY;
+
+ retVal = valueDelta * tickSpan;
+
+ if (retVal < 0.0)
+ retVal = 0.0;
+ }
+ return retVal;
+}
+
+QPointF XLogYPolarDomain::calculateDomainPoint(const QPointF &point) const
+{
+ if (point == m_center)
+ return QPointF(0.0, m_minY);
+
+ QLineF line(m_center, point);
+ qreal a = 90.0 - line.angle();
+ if (a < 0.0)
+ a += 360.0;
+ a = ((a / 360.0) * (m_maxX - m_minX)) + m_minX;
+
+ const qreal deltaY = m_radius / qAbs(m_logOuterY - m_logInnerY);
+ qreal r = qPow(m_logBaseY, m_logInnerY + (line.length() / deltaY));
+
+ return QPointF(a, r);
+}
+
+bool XLogYPolarDomain::attachAxis(QAbstractAxis *axis)
+{
+ QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
+
+ if (logAxis && logAxis->orientation() == Qt::Vertical) {
+ QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
+ handleVerticalAxisBaseChanged(logAxis->base());
+ }
+ return AbstractDomain::attachAxis(axis);
+}
+
+bool XLogYPolarDomain::detachAxis(QAbstractAxis *axis)
+{
+ QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
+
+ if (logAxis && logAxis->orientation() == Qt::Vertical)
+ QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
+
+ return AbstractDomain::detachAxis(axis);
+}
+
+void XLogYPolarDomain::handleVerticalAxisBaseChanged(qreal baseY)
+{
+ m_logBaseY = baseY;
+ qreal logMinY = log10(m_minY) / log10(m_logBaseY);
+ qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
+ m_logInnerY = logMinY < logMaxY ? logMinY : logMaxY;
+ m_logOuterY = logMinY > logMaxY ? logMinY : logMaxY;
+ emit updated();
+}
+
+// operators
+
+bool QT_CHARTS_AUTOTEST_EXPORT operator== (const XLogYPolarDomain &domain1, const XLogYPolarDomain &domain2)
+{
+ return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
+ && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
+ && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
+ && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
+}
+
+
+bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const XLogYPolarDomain &domain1, const XLogYPolarDomain &domain2)
+{
+ return !(domain1 == domain2);
+}
+
+
+QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const XLogYPolarDomain &domain)
+{
+#ifdef QT_NO_TEXTSTREAM
+ Q_UNUSED(domain)
+#else
+ dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
+#endif
+ return dbg.maybeSpace();
+}
+
+#include "moc_xlogypolardomain_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/domain/xlogypolardomain_p.h b/src/charts/domain/xlogypolardomain_p.h
new file mode 100644
index 00000000..5beace20
--- /dev/null
+++ b/src/charts/domain/xlogypolardomain_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 XLOGYPOLARDOMAIN_H
+#define XLOGYPOLARDOMAIN_H
+#include "polardomain_p.h"
+#include <QRectF>
+#include <QSizeF>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QT_CHARTS_AUTOTEST_EXPORT XLogYPolarDomain: public PolarDomain
+{
+ Q_OBJECT
+public:
+ explicit XLogYPolarDomain(QObject *object = 0);
+ virtual ~XLogYPolarDomain();
+
+ DomainType type() { return AbstractDomain::XLogYPolarDomain; }
+
+ void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY);
+
+ friend bool QT_CHARTS_AUTOTEST_EXPORT operator== (const XLogYPolarDomain &domain1, const XLogYPolarDomain &domain2);
+ friend bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const XLogYPolarDomain &domain1, const XLogYPolarDomain &domain2);
+ friend QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const XLogYPolarDomain &domain);
+
+ void zoomIn(const QRectF &rect);
+ void zoomOut(const QRectF &rect);
+ void move(qreal dx, qreal dy);
+
+ QPointF calculateDomainPoint(const QPointF &point) const;
+
+ bool attachAxis(QAbstractAxis *axis);
+ bool detachAxis(QAbstractAxis *axis);
+
+public Q_SLOTS:
+ void handleVerticalAxisBaseChanged(qreal baseY);
+
+protected:
+ qreal toAngularCoordinate(qreal value, bool &ok) const;
+ qreal toRadialCoordinate(qreal value, bool &ok) const;
+
+private:
+ qreal m_logInnerY;
+ qreal m_logOuterY;
+ qreal m_logBaseY;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // XLOGYPOLARDOMAIN_H
diff --git a/src/charts/domain/xydomain.cpp b/src/charts/domain/xydomain.cpp
new file mode 100644
index 00000000..9916b7ca
--- /dev/null
+++ b/src/charts/domain/xydomain.cpp
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "xydomain_p.h"
+#include "qabstractaxis_p.h"
+#include <qmath.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+XYDomain::XYDomain(QObject *parent)
+ : AbstractDomain(parent)
+{
+}
+
+XYDomain::~XYDomain()
+{
+}
+
+void XYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
+{
+ bool axisXChanged = false;
+ bool axisYChanged = false;
+
+ if (!qFuzzyCompare(m_minX, minX) || !qFuzzyCompare(m_maxX, maxX)) {
+ m_minX = minX;
+ m_maxX = maxX;
+ axisXChanged = true;
+ if(!m_signalsBlocked)
+ emit rangeHorizontalChanged(m_minX, m_maxX);
+ }
+
+ if (!qFuzzyCompare(m_minY, minY) || !qFuzzyCompare(m_maxY, maxY)) {
+ m_minY = minY;
+ m_maxY = maxY;
+ axisYChanged = true;
+ if(!m_signalsBlocked)
+ emit rangeVerticalChanged(m_minY, m_maxY);
+ }
+
+ if (axisXChanged || axisYChanged)
+ emit updated();
+}
+
+
+void XYDomain::zoomIn(const QRectF &rect)
+{
+ storeZoomReset();
+ qreal dx = spanX() / m_size.width();
+ qreal dy = spanY() / m_size.height();
+
+ qreal maxX = m_maxX;
+ qreal minX = m_minX;
+ qreal minY = m_minY;
+ qreal maxY = m_maxY;
+
+ maxX = minX + dx * rect.right();
+ minX = minX + dx * rect.left();
+ minY = maxY - dy * rect.bottom();
+ maxY = maxY - dy * rect.top();
+
+ setRange(minX, maxX, minY, maxY);
+}
+
+void XYDomain::zoomOut(const QRectF &rect)
+{
+ storeZoomReset();
+ qreal dx = spanX() / rect.width();
+ qreal dy = spanY() / rect.height();
+
+ qreal maxX = m_maxX;
+ qreal minX = m_minX;
+ qreal minY = m_minY;
+ qreal maxY = m_maxY;
+
+ minX = maxX - dx * rect.right();
+ maxX = minX + dx * m_size.width();
+ maxY = minY + dy * rect.bottom();
+ minY = maxY - dy * m_size.height();
+
+ setRange(minX, maxX, minY, maxY);
+}
+
+void XYDomain::move(qreal dx, qreal dy)
+{
+ qreal x = spanX() / m_size.width();
+ qreal y = spanY() / m_size.height();
+
+ qreal maxX = m_maxX;
+ qreal minX = m_minX;
+ qreal minY = m_minY;
+ qreal maxY = m_maxY;
+
+ if (dx != 0) {
+ minX = minX + x * dx;
+ maxX = maxX + x * dx;
+ }
+ if (dy != 0) {
+ minY = minY + y * dy;
+ maxY = maxY + y * dy;
+ }
+ setRange(minX, maxX, minY, maxY);
+}
+
+QPointF XYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
+{
+ const qreal deltaX = m_size.width() / (m_maxX - m_minX);
+ const qreal deltaY = m_size.height() / (m_maxY - m_minY);
+ qreal x = (point.x() - m_minX) * deltaX;
+ qreal y = (point.y() - m_minY) * -deltaY + m_size.height();
+ ok = true;
+ return QPointF(x, y);
+}
+
+QVector<QPointF> XYDomain::calculateGeometryPoints(const QList<QPointF> &vector) const
+{
+ const qreal deltaX = m_size.width() / (m_maxX - m_minX);
+ const qreal deltaY = m_size.height() / (m_maxY - m_minY);
+
+ QVector<QPointF> result;
+ result.resize(vector.count());
+
+ for (int i = 0; i < vector.count(); ++i) {
+ qreal x = (vector[i].x() - m_minX) * deltaX;
+ qreal y = (vector[i].y() - m_minY) * -deltaY + m_size.height();
+ result[i].setX(x);
+ result[i].setY(y);
+ }
+ return result;
+}
+
+QPointF XYDomain::calculateDomainPoint(const QPointF &point) const
+{
+ const qreal deltaX = m_size.width() / (m_maxX - m_minX);
+ const qreal deltaY = m_size.height() / (m_maxY - m_minY);
+ qreal x = point.x() / deltaX + m_minX;
+ qreal y = (point.y() - m_size.height()) / (-deltaY) + m_minY;
+ return QPointF(x, y);
+}
+
+// operators
+
+bool QT_CHARTS_AUTOTEST_EXPORT operator== (const XYDomain &domain1, const XYDomain &domain2)
+{
+ return (qFuzzyCompare(domain1.m_maxX, domain2.m_maxX)
+ && qFuzzyCompare(domain1.m_maxY, domain2.m_maxY)
+ && qFuzzyCompare(domain1.m_minX, domain2.m_minX)
+ && qFuzzyCompare(domain1.m_minY, domain2.m_minY));
+}
+
+
+bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const XYDomain &domain1, const XYDomain &domain2)
+{
+ return !(domain1 == domain2);
+}
+
+
+QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const XYDomain &domain)
+{
+#ifdef QT_NO_TEXTSTREAM
+ Q_UNUSED(domain)
+#else
+ dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
+#endif
+ return dbg.maybeSpace();
+}
+
+#include "moc_xydomain_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/domain/xydomain_p.h b/src/charts/domain/xydomain_p.h
new file mode 100644
index 00000000..a82596ba
--- /dev/null
+++ b/src/charts/domain/xydomain_p.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 XYDOMAIN_H
+#define XYDOMAIN_H
+#include "abstractdomain_p.h"
+#include <QRectF>
+#include <QSizeF>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QT_CHARTS_AUTOTEST_EXPORT XYDomain: public AbstractDomain
+{
+ Q_OBJECT
+public:
+ explicit XYDomain(QObject *object = 0);
+ virtual ~XYDomain();
+
+ DomainType type(){ return AbstractDomain::XYDomain;}
+
+ void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY);
+
+ friend bool QT_CHARTS_AUTOTEST_EXPORT operator== (const XYDomain &Domain1, const XYDomain &Domain2);
+ friend bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const XYDomain &Domain1, const XYDomain &Domain2);
+ friend QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const XYDomain &AbstractDomain);
+
+ void zoomIn(const QRectF &rect);
+ void zoomOut(const QRectF &rect);
+ void move(qreal dx, qreal dy);
+
+ QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const;
+ QPointF calculateDomainPoint(const QPointF &point) const;
+ QVector<QPointF> calculateGeometryPoints(const QList<QPointF> &vector) const;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // XYDOMAIN_H
diff --git a/src/charts/domain/xypolardomain.cpp b/src/charts/domain/xypolardomain.cpp
new file mode 100644
index 00000000..30fdacd3
--- /dev/null
+++ b/src/charts/domain/xypolardomain.cpp
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "xypolardomain_p.h"
+#include "qabstractaxis_p.h"
+#include <qmath.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+XYPolarDomain::XYPolarDomain(QObject *parent)
+ : PolarDomain(parent)
+{
+}
+
+XYPolarDomain::~XYPolarDomain()
+{
+}
+
+void XYPolarDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
+{
+ bool axisXChanged = false;
+ bool axisYChanged = false;
+
+ if (!qFuzzyCompare(m_minX, minX) || !qFuzzyCompare(m_maxX, maxX)) {
+ m_minX = minX;
+ m_maxX = maxX;
+ axisXChanged = true;
+ if (!m_signalsBlocked)
+ emit rangeHorizontalChanged(m_minX, m_maxX);
+ }
+
+ if (!qFuzzyCompare(m_minY, minY) || !qFuzzyCompare(m_maxY, maxY)) {
+ m_minY = minY;
+ m_maxY = maxY;
+ axisYChanged = true;
+ if (!m_signalsBlocked)
+ emit rangeVerticalChanged(m_minY, m_maxY);
+ }
+
+ if (axisXChanged || axisYChanged)
+ emit updated();
+}
+
+
+void XYPolarDomain::zoomIn(const QRectF &rect)
+{
+ storeZoomReset();
+ qreal dx = spanX() / m_size.width();
+ qreal dy = spanY() / m_size.height();
+
+ qreal maxX = m_maxX;
+ qreal minX = m_minX;
+ qreal minY = m_minY;
+ qreal maxY = m_maxY;
+
+ maxX = minX + dx * rect.right();
+ minX = minX + dx * rect.left();
+ minY = maxY - dy * rect.bottom();
+ maxY = maxY - dy * rect.top();
+
+ setRange(minX, maxX, minY, maxY);
+}
+
+void XYPolarDomain::zoomOut(const QRectF &rect)
+{
+ storeZoomReset();
+ qreal dx = spanX() / rect.width();
+ qreal dy = spanY() / rect.height();
+
+ qreal maxX = m_maxX;
+ qreal minX = m_minX;
+ qreal minY = m_minY;
+ qreal maxY = m_maxY;
+
+ minX = maxX - dx * rect.right();
+ maxX = minX + dx * m_size.width();
+ maxY = minY + dy * rect.bottom();
+ minY = maxY - dy * m_size.height();
+
+ setRange(minX, maxX, minY, maxY);
+}
+
+void XYPolarDomain::move(qreal dx, qreal dy)
+{
+ // One unit scrolls one degree angular and one pixel radial
+ qreal x = spanX() / 360.0;
+ qreal y = spanY() / m_radius;
+
+ qreal maxX = m_maxX;
+ qreal minX = m_minX;
+ qreal minY = m_minY;
+ qreal maxY = m_maxY;
+
+ if (dx != 0) {
+ minX = minX + x * dx;
+ maxX = maxX + x * dx;
+ }
+ if (dy != 0) {
+ minY = minY + y * dy;
+ maxY = maxY + y * dy;
+ }
+ setRange(minX, maxX, minY, maxY);
+}
+
+QPointF XYPolarDomain::calculateDomainPoint(const QPointF &point) const
+{
+ if (point == m_center)
+ return QPointF(0.0, m_minX);
+
+ QLineF line(m_center, point);
+ qreal a = 90.0 - line.angle();
+ if (a < 0.0)
+ a += 360.0;
+ a = ((a / 360.0) * (m_maxX - m_minX)) + m_minX;
+ qreal r = m_minY + ((m_maxY - m_minY) * (line.length() / m_radius));
+ return QPointF(a, r);
+}
+
+qreal XYPolarDomain::toAngularCoordinate(qreal value, bool &ok) const
+{
+ ok = true;
+ qreal f = (value - m_minX) / (m_maxX - m_minX);
+ return f * 360.0;
+}
+
+qreal XYPolarDomain::toRadialCoordinate(qreal value, bool &ok) const
+{
+ ok = true;
+ if (value < m_minY)
+ value = m_minY;
+
+ // Dont limit the max. The drawing should clip the stuff that goes out of the grid
+ qreal f = (value - m_minY) / (m_maxY - m_minY);
+
+ return f * m_radius;
+}
+
+// operators
+
+bool QT_CHARTS_AUTOTEST_EXPORT operator== (const XYPolarDomain &domain1, const XYPolarDomain &domain2)
+{
+ return (qFuzzyCompare(domain1.m_maxX, domain2.m_maxX)
+ && qFuzzyCompare(domain1.m_maxY, domain2.m_maxY)
+ && qFuzzyCompare(domain1.m_minX, domain2.m_minX)
+ && qFuzzyCompare(domain1.m_minY, domain2.m_minY));
+}
+
+
+bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const XYPolarDomain &domain1, const XYPolarDomain &domain2)
+{
+ return !(domain1 == domain2);
+}
+
+
+QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const XYPolarDomain &domain)
+{
+#ifdef QT_NO_TEXTSTREAM
+ Q_UNUSED(domain)
+#else
+ dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
+#endif
+ return dbg.maybeSpace();
+}
+
+#include "moc_xypolardomain_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/domain/xypolardomain_p.h b/src/charts/domain/xypolardomain_p.h
new file mode 100644
index 00000000..0d5abbab
--- /dev/null
+++ b/src/charts/domain/xypolardomain_p.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 XYPOLARDOMAIN_H
+#define XYPOLARDOMAIN_H
+#include "polardomain_p.h"
+#include <QRectF>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QT_CHARTS_AUTOTEST_EXPORT XYPolarDomain: public PolarDomain
+{
+ Q_OBJECT
+public:
+ explicit XYPolarDomain(QObject *object = 0);
+ virtual ~XYPolarDomain();
+
+ DomainType type(){ return AbstractDomain::XYPolarDomain;}
+
+ void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY);
+
+ friend bool QT_CHARTS_AUTOTEST_EXPORT operator== (const XYPolarDomain &Domain1, const XYPolarDomain &Domain2);
+ friend bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const XYPolarDomain &Domain1, const XYPolarDomain &Domain2);
+ friend QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const XYPolarDomain &AbstractDomain);
+
+ void zoomIn(const QRectF &rect);
+ void zoomOut(const QRectF &rect);
+ void move(qreal dx, qreal dy);
+
+ QPointF calculateDomainPoint(const QPointF &point) const;
+
+protected:
+ qreal toAngularCoordinate(qreal value, bool &ok) const;
+ qreal toRadialCoordinate(qreal value, bool &ok) const;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // XYPOLARDOMAIN_H
diff --git a/src/charts/layout/abstractchartlayout.cpp b/src/charts/layout/abstractchartlayout.cpp
new file mode 100644
index 00000000..b0d3d067
--- /dev/null
+++ b/src/charts/layout/abstractchartlayout.cpp
@@ -0,0 +1,203 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractchartlayout_p.h"
+#include "chartpresenter_p.h"
+#include "qlegend_p.h"
+#include "chartaxiselement_p.h"
+#include "charttitle_p.h"
+#include "chartbackground_p.h"
+#include <QDebug>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+static const qreal golden_ratio = 0.4;
+
+AbstractChartLayout::AbstractChartLayout(ChartPresenter *presenter)
+ : m_presenter(presenter),
+ m_margins(20, 20, 20, 20),
+ m_minChartRect(0, 0, 200, 200)
+{
+}
+
+AbstractChartLayout::~AbstractChartLayout()
+{
+}
+
+void AbstractChartLayout::setGeometry(const QRectF &rect)
+{
+ if (!rect.isValid())
+ return;
+
+ if (m_presenter->chart()->isVisible()) {
+ QList<ChartAxisElement *> axes = m_presenter->axisItems();
+ ChartTitle *title = m_presenter->titleElement();
+ QLegend *legend = m_presenter->legend();
+ ChartBackground *background = m_presenter->backgroundElement();
+
+ QRectF contentGeometry = calculateBackgroundGeometry(rect, background);
+
+ contentGeometry = calculateContentGeometry(contentGeometry);
+
+ if (title && title->isVisible())
+ contentGeometry = calculateTitleGeometry(contentGeometry, title);
+
+ if (legend->isAttachedToChart() && legend->isVisible())
+ contentGeometry = calculateLegendGeometry(contentGeometry, legend);
+
+ contentGeometry = calculateAxisGeometry(contentGeometry, axes);
+
+ m_presenter->setGeometry(contentGeometry);
+ if (m_presenter->chart()->chartType() == QChart::ChartTypeCartesian)
+ static_cast<QGraphicsRectItem *>(m_presenter->plotAreaElement())->setRect(contentGeometry);
+ else
+ static_cast<QGraphicsEllipseItem *>(m_presenter->plotAreaElement())->setRect(contentGeometry);
+ }
+
+ QGraphicsLayout::setGeometry(rect);
+}
+
+QRectF AbstractChartLayout::calculateContentGeometry(const QRectF &geometry) const
+{
+ return geometry.adjusted(m_margins.left(), m_margins.top(), -m_margins.right(), -m_margins.bottom());
+}
+
+QRectF AbstractChartLayout::calculateContentMinimum(const QRectF &minimum) const
+{
+ return minimum.adjusted(0, 0, m_margins.left() + m_margins.right(), m_margins.top() + m_margins.bottom());
+}
+
+
+QRectF AbstractChartLayout::calculateBackgroundGeometry(const QRectF &geometry, ChartBackground *background) const
+{
+ qreal left;
+ qreal top;
+ qreal right;
+ qreal bottom;
+ getContentsMargins(&left, &top, &right, &bottom);
+ QRectF backgroundGeometry = geometry.adjusted(left, top, -right, -bottom);
+ if (background)
+ background->setRect(backgroundGeometry);
+ return backgroundGeometry;
+}
+
+QRectF AbstractChartLayout::calculateBackgroundMinimum(const QRectF &minimum) const
+{
+ qreal left;
+ qreal top;
+ qreal right;
+ qreal bottom;
+ getContentsMargins(&left, &top, &right, &bottom);
+ return minimum.adjusted(0, 0, left + right, top + bottom);
+}
+
+QRectF AbstractChartLayout::calculateLegendGeometry(const QRectF &geometry, QLegend *legend) const
+{
+ QSizeF size = legend->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, -1));
+ QRectF legendRect;
+ QRectF result;
+
+ switch (legend->alignment()) {
+ case Qt::AlignTop: {
+ legendRect = QRectF(geometry.topLeft(), QSizeF(geometry.width(), size.height()));
+ result = geometry.adjusted(0, legendRect.height(), 0, 0);
+ break;
+ }
+ case Qt::AlignBottom: {
+ legendRect = QRectF(QPointF(geometry.left(), geometry.bottom() - size.height()), QSizeF(geometry.width(), size.height()));
+ result = geometry.adjusted(0, 0, 0, -legendRect.height());
+ break;
+ }
+ case Qt::AlignLeft: {
+ qreal width = qMin(size.width(), geometry.width() * golden_ratio);
+ legendRect = QRectF(geometry.topLeft(), QSizeF(width, geometry.height()));
+ result = geometry.adjusted(width, 0, 0, 0);
+ break;
+ }
+ case Qt::AlignRight: {
+ qreal width = qMin(size.width(), geometry.width() * golden_ratio);
+ legendRect = QRectF(QPointF(geometry.right() - width, geometry.top()), QSizeF(width, geometry.height()));
+ result = geometry.adjusted(0, 0, -width, 0);
+ break;
+ }
+ default: {
+ legendRect = QRectF(0, 0, 0, 0);
+ result = geometry;
+ break;
+ }
+ }
+
+ legend->setGeometry(legendRect);
+
+ return result;
+}
+
+QRectF AbstractChartLayout::calculateLegendMinimum(const QRectF &geometry, QLegend *legend) const
+{
+ QSizeF minSize = legend->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, -1));
+ return geometry.adjusted(0, 0, minSize.width(), minSize.height());
+}
+
+QRectF AbstractChartLayout::calculateTitleGeometry(const QRectF &geometry, ChartTitle *title) const
+{
+ title->setGeometry(geometry);
+ QPointF center = geometry.center() - title->boundingRect().center();
+ title->setPos(center.x(), title->pos().y());
+ return geometry.adjusted(0, title->boundingRect().height()+1, 0, 0);
+}
+
+QRectF AbstractChartLayout::calculateTitleMinimum(const QRectF &minimum, ChartTitle *title) const
+{
+ QSizeF min = title->sizeHint(Qt::MinimumSize);
+ return minimum.adjusted(0, 0, min.width(), min.height());
+}
+
+QSizeF AbstractChartLayout::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED(constraint);
+ if (which == Qt::MinimumSize) {
+ QList<ChartAxisElement *> axes = m_presenter->axisItems();
+ ChartTitle *title = m_presenter->titleElement();
+ QLegend *legend = m_presenter->legend();
+ QRectF minimumRect(0, 0, 0, 0);
+ minimumRect = calculateBackgroundMinimum(minimumRect);
+ minimumRect = calculateContentMinimum(minimumRect);
+ minimumRect = calculateTitleMinimum(minimumRect, title);
+ minimumRect = calculateLegendMinimum(minimumRect, legend);
+ minimumRect = calculateAxisMinimum(minimumRect, axes);
+ return minimumRect.united(m_minChartRect).size().toSize();
+ }
+ return QSize(-1, -1);
+}
+
+void AbstractChartLayout::setMargins(const QMargins &margins)
+{
+ if (m_margins != margins) {
+ m_margins = margins;
+ updateGeometry();
+ }
+}
+
+QMargins AbstractChartLayout::margins() const
+{
+ return m_margins;
+}
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/layout/abstractchartlayout_p.h b/src/charts/layout/abstractchartlayout_p.h
new file mode 100644
index 00000000..a0bf6f25
--- /dev/null
+++ b/src/charts/layout/abstractchartlayout_p.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 ABSTRACTCHARTLAYOUT_H
+#define ABSTRACTCHARTLAYOUT_H
+
+#include <QGraphicsLayout>
+#include <QMargins>
+#include "qchartglobal.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class ChartTitle;
+class ChartAxisElement;
+class ChartPresenter;
+class QLegend;
+class ChartBackground;
+
+class AbstractChartLayout : public QGraphicsLayout
+{
+public:
+ AbstractChartLayout(ChartPresenter *presenter);
+ virtual ~AbstractChartLayout();
+
+ virtual void setMargins(const QMargins &margins);
+ virtual QMargins margins() const;
+ virtual void setGeometry(const QRectF &rect);
+
+protected:
+ virtual QRectF calculateBackgroundGeometry(const QRectF &geometry, ChartBackground *background) const;
+ virtual QRectF calculateBackgroundMinimum(const QRectF &minimum) const;
+ virtual QRectF calculateContentGeometry(const QRectF &geometry) const;
+ virtual QRectF calculateContentMinimum(const QRectF &minimum) const;
+ virtual QRectF calculateTitleGeometry(const QRectF &geometry, ChartTitle *title) const;
+ virtual QRectF calculateTitleMinimum(const QRectF &minimum, ChartTitle *title) const;
+ virtual QRectF calculateLegendGeometry(const QRectF &geometry, QLegend *legend) const;
+ virtual QRectF calculateLegendMinimum(const QRectF &minimum, QLegend *legend) const;
+
+ virtual QRectF calculateAxisGeometry(const QRectF &geometry, const QList<ChartAxisElement *>& axes) const = 0;
+ virtual QRectF calculateAxisMinimum(const QRectF &minimum, const QList<ChartAxisElement *>& axes) const = 0;
+
+ // from QGraphicsLayout
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
+ int count() const { return 0; }
+ QGraphicsLayoutItem *itemAt(int) const { return 0; };
+ void removeAt(int) {};
+
+ ChartPresenter *m_presenter;
+ QMargins m_margins;
+ QRectF m_minChartRect;
+ QRectF m_minAxisRect;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // ABSTRACTCHARTLAYOUT_H
diff --git a/src/charts/layout/cartesianchartlayout.cpp b/src/charts/layout/cartesianchartlayout.cpp
new file mode 100644
index 00000000..7018a638
--- /dev/null
+++ b/src/charts/layout/cartesianchartlayout.cpp
@@ -0,0 +1,246 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "cartesianchartlayout_p.h"
+#include "chartpresenter_p.h"
+#include "chartaxiselement_p.h"
+#include <QDebug>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+static const qreal maxAxisPortion = 0.4;
+
+CartesianChartLayout::CartesianChartLayout(ChartPresenter *presenter)
+ : AbstractChartLayout(presenter)
+{
+}
+
+CartesianChartLayout::~CartesianChartLayout()
+{
+}
+
+QRectF CartesianChartLayout::calculateAxisGeometry(const QRectF &geometry, const QList<ChartAxisElement *> &axes) const
+{
+ QSizeF left(0,0);
+ QSizeF minLeft(0,0);
+ QSizeF right(0,0);
+ QSizeF minRight(0,0);
+ QSizeF bottom(0,0);
+ QSizeF minBottom(0,0);
+ QSizeF top(0,0);
+ QSizeF minTop(0,0);
+ QSizeF labelExtents(0,0);
+ int leftCount = 0;
+ int rightCount = 0;
+ int topCount = 0;
+ int bottomCount = 0;
+
+ foreach (ChartAxisElement *axis , axes) {
+
+ if (!axis->isVisible())
+ continue;
+
+
+ QSizeF size = axis->effectiveSizeHint(Qt::PreferredSize);
+ //this is used to get single thick font size
+ QSizeF minSize = axis->effectiveSizeHint(Qt::MinimumSize);
+
+ switch (axis->axis()->alignment()) {
+ case Qt::AlignLeft:
+ left.setWidth(left.width()+size.width());
+ left.setHeight(qMax(left.height(),size.height()));
+ minLeft.setWidth(minLeft.width()+minSize.width());
+ minLeft.setHeight(qMax(minLeft.height(),minSize.height()));
+ labelExtents.setHeight(qMax(size.height(), labelExtents.height()));
+ leftCount++;
+ break;
+ case Qt::AlignRight:
+ right.setWidth(right.width()+size.width());
+ right.setHeight(qMax(right.height(),size.height()));
+ minRight.setWidth(minRight.width()+minSize.width());
+ minRight.setHeight(qMax(minRight.height(),minSize.height()));
+ labelExtents.setHeight(qMax(size.height(), labelExtents.height()));
+ rightCount++;
+ break;
+ case Qt::AlignTop:
+ top.setWidth(qMax(top.width(),size.width()));
+ top.setHeight(top.height()+size.height());
+ minTop.setWidth(qMax(minTop.width(),minSize.width()));
+ minTop.setHeight(minTop.height()+minSize.height());
+ labelExtents.setWidth(qMax(size.width(), labelExtents.width()));
+ topCount++;
+ break;
+ case Qt::AlignBottom:
+ bottom.setWidth(qMax(bottom.width(), size.width()));
+ bottom.setHeight(bottom.height() + size.height());
+ minBottom.setWidth(qMax(minBottom.width(),minSize.width()));
+ minBottom.setHeight(minBottom.height() + minSize.height());
+ labelExtents.setWidth(qMax(size.width(), labelExtents.width()));
+ bottomCount++;
+ break;
+ default:
+ qWarning()<<"Axis is without alignment !";
+ break;
+ }
+ }
+
+ qreal totalVerticalAxes = leftCount + rightCount;
+ qreal leftSqueezeRatio = 1.0;
+ qreal rightSqueezeRatio = 1.0;
+ qreal vratio = 0;
+
+ if (totalVerticalAxes > 0)
+ vratio = (maxAxisPortion * geometry.width()) / totalVerticalAxes;
+
+ if (leftCount > 0) {
+ int maxWidth = vratio * leftCount;
+ if (left.width() > maxWidth) {
+ leftSqueezeRatio = maxWidth / left.width();
+ left.setWidth(maxWidth);
+ }
+ }
+ if (rightCount > 0) {
+ int maxWidth = vratio * rightCount;
+ if (right.width() > maxWidth) {
+ rightSqueezeRatio = maxWidth / right.width();
+ right.setWidth(maxWidth);
+ }
+ }
+
+ qreal totalHorizontalAxes = topCount + bottomCount;
+ qreal topSqueezeRatio = 1.0;
+ qreal bottomSqueezeRatio = 1.0;
+ qreal hratio = 0;
+
+ if (totalHorizontalAxes > 0)
+ hratio = (maxAxisPortion * geometry.height()) / totalHorizontalAxes;
+
+ if (topCount > 0) {
+ int maxHeight = hratio * topCount;
+ if (top.height() > maxHeight) {
+ topSqueezeRatio = maxHeight / top.height();
+ top.setHeight(maxHeight);
+ }
+ }
+ if (bottomCount > 0) {
+ int maxHeight = hratio * bottomCount;
+ if (bottom.height() > maxHeight) {
+ bottomSqueezeRatio = maxHeight / bottom.height();
+ bottom.setHeight(maxHeight);
+ }
+ }
+
+ qreal minHeight = qMax(minLeft.height(),minRight.height()) + 1;
+ qreal minWidth = qMax(minTop.width(),minBottom.width()) + 1;
+
+ // Ensure that there is enough space for first and last tick labels.
+ left.setWidth(qMax(labelExtents.width(), left.width()));
+ right.setWidth(qMax(labelExtents.width(), right.width()));
+ top.setHeight(qMax(labelExtents.height(), top.height()));
+ bottom.setHeight(qMax(labelExtents.height(), bottom.height()));
+
+ QRectF chartRect = geometry.adjusted(qMax(left.width(),minWidth/2), qMax(top.height(), minHeight/2),-qMax(right.width(),minWidth/2),-qMax(bottom.height(),minHeight/2));
+
+ qreal leftOffset = 0;
+ qreal rightOffset = 0;
+ qreal topOffset = 0;
+ qreal bottomOffset = 0;
+
+ foreach (ChartAxisElement *axis , axes) {
+
+ if (!axis->isVisible())
+ continue;
+
+ QSizeF size = axis->effectiveSizeHint(Qt::PreferredSize);
+
+ switch (axis->axis()->alignment()){
+ case Qt::AlignLeft:{
+ qreal width = size.width();
+ if (leftSqueezeRatio < 1.0)
+ width *= leftSqueezeRatio;
+ leftOffset+=width;
+ axis->setGeometry(QRect(chartRect.left()-leftOffset, geometry.top(),width, geometry.bottom()),chartRect);
+ break;
+ }
+ case Qt::AlignRight:{
+ qreal width = size.width();
+ if (rightSqueezeRatio < 1.0)
+ width *= rightSqueezeRatio;
+ axis->setGeometry(QRect(chartRect.right()+rightOffset,geometry.top(),width,geometry.bottom()),chartRect);
+ rightOffset+=width;
+ break;
+ }
+ case Qt::AlignTop: {
+ qreal height = size.height();
+ if (topSqueezeRatio < 1.0)
+ height *= topSqueezeRatio;
+ axis->setGeometry(QRect(geometry.left(), chartRect.top() - topOffset - height, geometry.width(), height), chartRect);
+ topOffset += height;
+ break;
+ }
+ case Qt::AlignBottom:
+ qreal height = size.height();
+ if (bottomSqueezeRatio < 1.0)
+ height *= bottomSqueezeRatio;
+ axis->setGeometry(QRect(geometry.left(), chartRect.bottom() + bottomOffset, geometry.width(), height), chartRect);
+ bottomOffset += height;
+ break;
+ }
+ }
+
+ return chartRect;
+}
+
+QRectF CartesianChartLayout::calculateAxisMinimum(const QRectF &minimum, const QList<ChartAxisElement *> &axes) const
+{
+ QSizeF left;
+ QSizeF right;
+ QSizeF bottom;
+ QSizeF top;
+
+ foreach (ChartAxisElement *axis, axes) {
+ QSizeF size = axis->effectiveSizeHint(Qt::MinimumSize);
+
+ if (!axis->isVisible())
+ continue;
+
+ switch (axis->axis()->alignment()) {
+ case Qt::AlignLeft:
+ left.setWidth(left.width() + size.width());
+ left.setHeight(qMax(left.height() * 2, size.height()));
+ break;
+ case Qt::AlignRight:
+ right.setWidth(right.width() + size.width());
+ right.setHeight(qMax(right.height() * 2, size.height()));
+ break;
+ case Qt::AlignTop:
+ top.setWidth(qMax(top.width(), size.width()));
+ top.setHeight(top.height() + size.height());
+ break;
+ case Qt::AlignBottom:
+ bottom.setWidth(qMax(bottom.width(), size.width()));
+ bottom.setHeight(bottom.height() + size.height());
+ break;
+ }
+ }
+ return minimum.adjusted(0, 0, left.width() + right.width() + qMax(top.width(), bottom.width()), top.height() + bottom.height() + qMax(left.height(), right.height()));
+}
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/layout/cartesianchartlayout_p.h b/src/charts/layout/cartesianchartlayout_p.h
new file mode 100644
index 00000000..2adcc233
--- /dev/null
+++ b/src/charts/layout/cartesianchartlayout_p.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CARTESIANCHARTLAYOUT_H
+#define CARTESIANCHARTLAYOUT_H
+
+#include "abstractchartlayout_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class CartesianChartLayout : public AbstractChartLayout
+{
+public:
+ CartesianChartLayout(ChartPresenter *presenter);
+ virtual ~CartesianChartLayout();
+
+ // from AbstractChartLayout
+ QRectF calculateAxisMinimum(const QRectF &minimum, const QList<ChartAxisElement *> &axes) const;
+ QRectF calculateAxisGeometry(const QRectF &geometry, const QList<ChartAxisElement *> &axes) const;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // CARTESIANCHARTLAYOUT_H
diff --git a/src/charts/layout/layout.pri b/src/charts/layout/layout.pri
new file mode 100644
index 00000000..159eab13
--- /dev/null
+++ b/src/charts/layout/layout.pri
@@ -0,0 +1,12 @@
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+
+SOURCES += \
+ $$PWD/abstractchartlayout.cpp \
+ $$PWD/cartesianchartlayout.cpp \
+ $$PWD/polarchartlayout.cpp
+
+PRIVATE_HEADERS += \
+ $$PWD/abstractchartlayout_p.h \
+ $$PWD/cartesianchartlayout_p.h \
+ $$PWD/polarchartlayout_p.h
diff --git a/src/charts/layout/polarchartlayout.cpp b/src/charts/layout/polarchartlayout.cpp
new file mode 100644
index 00000000..1f4bda39
--- /dev/null
+++ b/src/charts/layout/polarchartlayout.cpp
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "polarchartlayout_p.h"
+#include "chartpresenter_p.h"
+#include "polarchartaxis_p.h"
+#include <QDebug>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+static const qreal golden_ratio = 0.4;
+
+PolarChartLayout::PolarChartLayout(ChartPresenter *presenter)
+ : AbstractChartLayout(presenter)
+{
+}
+
+PolarChartLayout::~PolarChartLayout()
+{
+}
+
+QRectF PolarChartLayout::calculateAxisGeometry(const QRectF &geometry, const QList<ChartAxisElement *> &axes) const
+{
+ // How to handle multiple angular/radial axes?
+ qreal axisRadius = geometry.height() / 2.0;
+ if (geometry.width() < geometry.height())
+ axisRadius = geometry.width() / 2.0;
+
+ int titleHeight = 0;
+ foreach (ChartAxisElement *chartAxis, axes) {
+ if (!chartAxis->isVisible())
+ continue;
+
+ PolarChartAxis *polarChartAxis = static_cast<PolarChartAxis *>(chartAxis);
+ qreal radius = polarChartAxis->preferredAxisRadius(geometry.size());
+ if (radius < axisRadius)
+ axisRadius = radius;
+
+ if (chartAxis->axis()->orientation() == Qt::Horizontal
+ && chartAxis->axis()->isTitleVisible()
+ && !chartAxis->axis()->titleText().isEmpty()) {
+ // If axis has angular title, adjust geometry down by the space title takes
+ QRectF dummyRect = ChartPresenter::textBoundingRect(chartAxis->axis()->titleFont(), chartAxis->axis()->titleText());
+ titleHeight = (dummyRect.height() / 2.0) + chartAxis->titlePadding();
+ }
+ }
+
+ QRectF axisRect;
+ axisRect.setSize(QSizeF(axisRadius * 2.0, axisRadius * 2.0));
+ axisRect.moveCenter(geometry.center());
+ axisRect.adjust(0, titleHeight, 0, titleHeight);
+
+ foreach (ChartAxisElement *chartAxis, axes)
+ chartAxis->setGeometry(axisRect, QRectF());
+
+ return axisRect;
+}
+
+QRectF PolarChartLayout::calculateAxisMinimum(const QRectF &minimum, const QList<ChartAxisElement *> &axes) const
+{
+ Q_UNUSED(axes);
+ return minimum;
+}
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/layout/polarchartlayout_p.h b/src/charts/layout/polarchartlayout_p.h
new file mode 100644
index 00000000..38cd8612
--- /dev/null
+++ b/src/charts/layout/polarchartlayout_p.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 POLARCHARTLAYOUT_H
+#define POLARCHARTLAYOUT_H
+
+#include "abstractchartlayout_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class PolarChartLayout : public AbstractChartLayout
+{
+public:
+ PolarChartLayout(ChartPresenter *presenter);
+ virtual ~PolarChartLayout();
+
+ // from AbstractChartLayout
+ QRectF calculateAxisMinimum(const QRectF &minimum, const QList<ChartAxisElement *> &axes) const;
+ QRectF calculateAxisGeometry(const QRectF &geometry, const QList<ChartAxisElement *> &axes) const;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // POLARCHARTLAYOUT_H
diff --git a/src/charts/legend/legend.pri b/src/charts/legend/legend.pri
new file mode 100644
index 00000000..c14cf6b0
--- /dev/null
+++ b/src/charts/legend/legend.pri
@@ -0,0 +1,36 @@
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+
+SOURCES += \
+ $$PWD/qlegend.cpp \
+ $$PWD/legendlayout.cpp \
+ $$PWD/qlegendmarker.cpp \
+ $$PWD/qpielegendmarker.cpp \
+ $$PWD/legendmarkeritem.cpp \
+ $$PWD/qbarlegendmarker.cpp \
+ $$PWD/qxylegendmarker.cpp \
+ $$PWD/qarealegendmarker.cpp \
+ $$PWD/legendscroller.cpp \
+ $$PWD/qboxplotlegendmarker.cpp
+
+PRIVATE_HEADERS += \
+ $$PWD/legendscroller_p.h \
+ $$PWD/qlegend_p.h \
+ $$PWD/legendlayout_p.h \
+ $$PWD/qlegendmarker_p.h \
+ $$PWD/legendmarkeritem_p.h \
+ $$PWD/qpielegendmarker_p.h \
+ $$PWD/qbarlegendmarker_p.h \
+ $$PWD/qxylegendmarker_p.h \
+ $$PWD/qarealegendmarker_p.h \
+ $$PWD/qboxplotlegendmarker_p.h
+
+
+PUBLIC_HEADERS += \
+ $$PWD/qlegend.h \
+ $$PWD/qlegendmarker.h \
+ $$PWD/qpielegendmarker.h \
+ $$PWD/qbarlegendmarker.h \
+ $$PWD/qxylegendmarker.h \
+ $$PWD/qarealegendmarker.h \
+ $$PWD/qboxplotlegendmarker.h
diff --git a/src/charts/legend/legendlayout.cpp b/src/charts/legend/legendlayout.cpp
new file mode 100644
index 00000000..b4e443c0
--- /dev/null
+++ b/src/charts/legend/legendlayout.cpp
@@ -0,0 +1,506 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "legendlayout_p.h"
+#include "chartpresenter_p.h"
+#include "qlegend_p.h"
+#include "abstractchartlayout_p.h"
+
+#include "qlegendmarker_p.h"
+#include "legendmarkeritem_p.h"
+#include "qlegendmarker.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+LegendLayout::LegendLayout(QLegend *legend)
+ : m_legend(legend),
+ m_offsetX(0),
+ m_offsetY(0)
+{
+
+}
+
+LegendLayout::~LegendLayout()
+{
+
+}
+
+void LegendLayout::setOffset(qreal x, qreal y)
+{
+ bool scrollHorizontal = true;
+ switch (m_legend->alignment()) {
+ case Qt::AlignTop:
+ case Qt::AlignBottom:
+ scrollHorizontal = true;
+ break;
+ case Qt::AlignLeft:
+ case Qt::AlignRight:
+ scrollHorizontal = false;
+ break;
+ }
+
+ // If detached, the scrolling direction is vertical instead of horizontal and vice versa.
+ if (!m_legend->isAttachedToChart())
+ scrollHorizontal = !scrollHorizontal;
+
+ QRectF boundingRect = geometry();
+ qreal left, top, right, bottom;
+ getContentsMargins(&left, &top, &right, &bottom);
+ boundingRect.adjust(left, top, -right, -bottom);
+
+ // Limit offset between m_minOffset and m_maxOffset
+ if (scrollHorizontal) {
+ if (m_width <= boundingRect.width())
+ return;
+
+ if (x != m_offsetX) {
+ m_offsetX = qBound(m_minOffsetX, x, m_maxOffsetX);
+ m_legend->d_ptr->items()->setPos(-m_offsetX, boundingRect.top());
+ }
+ } else {
+ if (m_height <= boundingRect.height())
+ return;
+
+ if (y != m_offsetY) {
+ m_offsetY = qBound(m_minOffsetY, y, m_maxOffsetY);
+ m_legend->d_ptr->items()->setPos(boundingRect.left(), -m_offsetY);
+ }
+ }
+}
+
+QPointF LegendLayout::offset() const
+{
+ return QPointF(m_offsetX, m_offsetY);
+}
+
+void LegendLayout::invalidate()
+{
+ QGraphicsLayout::invalidate();
+ if (m_legend->isAttachedToChart())
+ m_legend->d_ptr->m_presenter->layout()->invalidate();
+}
+
+void LegendLayout::setGeometry(const QRectF &rect)
+{
+ m_legend->d_ptr->items()->setVisible(m_legend->isVisible());
+
+ QGraphicsLayout::setGeometry(rect);
+
+ if (m_legend->isAttachedToChart())
+ setAttachedGeometry(rect);
+ else
+ setDettachedGeometry(rect);
+}
+
+void LegendLayout::setAttachedGeometry(const QRectF &rect)
+{
+ if (!rect.isValid())
+ return;
+
+ qreal oldOffsetX = m_offsetX;
+ qreal oldOffsetY = m_offsetY;
+ m_offsetX = 0;
+ m_offsetY = 0;
+
+ QSizeF size(0, 0);
+
+ if (m_legend->d_ptr->markers().isEmpty()) {
+ return;
+ }
+
+ m_width = 0;
+ m_height = 0;
+
+ qreal left, top, right, bottom;
+ getContentsMargins(&left, &top, &right, &bottom);
+
+ QRectF geometry = rect.adjusted(left, top, -right, -bottom);
+
+ switch(m_legend->alignment()) {
+ case Qt::AlignTop:
+ case Qt::AlignBottom: {
+ // Calculate the space required for items and add them to a sorted list.
+ qreal markerItemsWidth = 0;
+ qreal itemMargins = 0;
+ QList<LegendWidthStruct *> legendWidthList;
+ foreach (QLegendMarker *marker, m_legend->d_ptr->markers()) {
+ LegendMarkerItem *item = marker->d_ptr->item();
+ if (item->isVisible()) {
+ QSizeF dummySize;
+ qreal itemWidth = item->sizeHint(Qt::PreferredSize, dummySize).width();
+ LegendWidthStruct *structItem = new LegendWidthStruct;
+ structItem->item = item;
+ structItem->width = itemWidth;
+ legendWidthList.append(structItem);
+ markerItemsWidth += itemWidth;
+ itemMargins += marker->d_ptr->item()->m_margin;
+ }
+ }
+ std::sort(legendWidthList.begin(), legendWidthList.end(), widthLongerThan);
+
+ // If the items would occupy more space than is available, start truncating them
+ // from the longest one.
+ qreal availableGeometry = geometry.width() - right - left * 2 - itemMargins;
+ if (markerItemsWidth >= availableGeometry && legendWidthList.count() > 0) {
+ bool truncated(false);
+ int count = legendWidthList.count();
+ for (int i = 1; i < count; i++) {
+ int truncateIndex = i - 1;
+
+ while (legendWidthList.at(truncateIndex)->width >= legendWidthList.at(i)->width
+ && !truncated) {
+ legendWidthList.at(truncateIndex)->width--;
+ markerItemsWidth--;
+ if (i > 1) {
+ // Truncate the items that are before the truncated one in the list.
+ for (int j = truncateIndex - 1; j >= 0; j--) {
+ if (legendWidthList.at(truncateIndex)->width
+ < legendWidthList.at(j)->width) {
+ legendWidthList.at(j)->width--;
+ markerItemsWidth--;
+ }
+ }
+ }
+ if (markerItemsWidth < availableGeometry)
+ truncated = true;
+ }
+ // Truncate the last item if needed.
+ if (i == count - 1) {
+ if (legendWidthList.at(count - 1)->width
+ > legendWidthList.at(truncateIndex)->width) {
+ legendWidthList.at(count - 1)->width--;
+ markerItemsWidth--;
+ }
+ }
+
+ if (truncated)
+ break;
+ }
+ // Items are of same width and all of them need to be truncated
+ // or there is just one item that is truncated.
+ while (markerItemsWidth >= availableGeometry) {
+ for (int i = 0; i < count; i++) {
+ legendWidthList.at(i)->width--;
+ markerItemsWidth--;
+ }
+ }
+ }
+
+ QPointF point(0,0);
+
+ int markerCount = m_legend->d_ptr->markers().count();
+ for (int i = 0; i < markerCount; i++) {
+ QLegendMarker *marker;
+ if (m_legend->d_ptr->m_reverseMarkers)
+ marker = m_legend->d_ptr->markers().at(markerCount - 1 - i);
+ else
+ marker = m_legend->d_ptr->markers().at(i);
+ LegendMarkerItem *item = marker->d_ptr->item();
+ if (item->isVisible()) {
+ QRectF itemRect = geometry;
+ qreal availableWidth = 0;
+ for (int i = 0; i < legendWidthList.size(); ++i) {
+ if (legendWidthList.at(i)->item == item) {
+ availableWidth = legendWidthList.at(i)->width;
+ break;
+ }
+ }
+ itemRect.setWidth(availableWidth);
+ item->setGeometry(itemRect);
+ item->setPos(point.x(),geometry.height()/2 - item->boundingRect().height()/2);
+ const QRectF &rect = item->boundingRect();
+ size = size.expandedTo(rect.size());
+ qreal w = rect.width();
+ m_width = m_width + w - item->m_margin;
+ point.setX(point.x() + w);
+ }
+ }
+ // Delete structs from the container
+ qDeleteAll(legendWidthList);
+
+ if (m_width < geometry.width())
+ m_legend->d_ptr->items()->setPos(geometry.width() / 2 - m_width / 2, geometry.top());
+ else
+ m_legend->d_ptr->items()->setPos(geometry.topLeft());
+ m_height = size.height();
+ }
+ break;
+ case Qt::AlignLeft:
+ case Qt::AlignRight: {
+ QPointF point(0,0);
+ int markerCount = m_legend->d_ptr->markers().count();
+ for (int i = 0; i < markerCount; i++) {
+ QLegendMarker *marker;
+ if (m_legend->d_ptr->m_reverseMarkers)
+ marker = m_legend->d_ptr->markers().at(markerCount - 1 - i);
+ else
+ marker = m_legend->d_ptr->markers().at(i);
+ LegendMarkerItem *item = marker->d_ptr->item();
+ if (item->isVisible()) {
+ item->setGeometry(geometry);
+ item->setPos(point);
+ const QRectF &rect = item->boundingRect();
+ qreal h = rect.height();
+ size = size.expandedTo(rect.size());
+ m_height+=h;
+ point.setY(point.y() + h);
+ }
+ }
+
+ if (m_height < geometry.height())
+ m_legend->d_ptr->items()->setPos(geometry.left(), geometry.height() / 2 - m_height / 2);
+ else
+ m_legend->d_ptr->items()->setPos(geometry.topLeft());
+ m_width = size.width();
+ break;
+ }
+ }
+
+ m_minOffsetX = -left;
+ m_minOffsetY = - top;
+ m_maxOffsetX = m_width - geometry.width() - right;
+ m_maxOffsetY = m_height - geometry.height() - bottom;
+
+ setOffset(oldOffsetX, oldOffsetY);
+}
+
+void LegendLayout::setDettachedGeometry(const QRectF &rect)
+{
+ if (!rect.isValid())
+ return;
+
+ // Detached layout is different.
+ // In detached mode legend may have multiple rows and columns, so layout calculations
+ // differ a log from attached mode.
+ // Also the scrolling logic is bit different.
+
+ qreal oldOffsetX = m_offsetX;
+ qreal oldOffsetY = m_offsetY;
+ m_offsetX = 0;
+ m_offsetY = 0;
+
+ qreal left, top, right, bottom;
+ getContentsMargins(&left, &top, &right, &bottom);
+ QRectF geometry = rect.adjusted(left, top, -right, -bottom);
+
+ QSizeF size(0, 0);
+
+ QList<QLegendMarker *> markers = m_legend->d_ptr->markers();
+
+ if (markers.isEmpty())
+ return;
+
+ switch (m_legend->alignment()) {
+ case Qt::AlignTop: {
+ QPointF point(0, 0);
+ m_width = 0;
+ m_height = 0;
+ for (int i = 0; i < markers.count(); i++) {
+ LegendMarkerItem *item = markers.at(i)->d_ptr->item();
+ if (item->isVisible()) {
+ item->setGeometry(geometry);
+ item->setPos(point.x(),point.y());
+ const QRectF &boundingRect = item->boundingRect();
+ qreal w = boundingRect.width();
+ qreal h = boundingRect.height();
+ m_width = qMax(m_width,w);
+ m_height = qMax(m_height,h);
+ point.setX(point.x() + w);
+ if (point.x() + w > geometry.left() + geometry.width() - right) {
+ // Next item would go off rect.
+ point.setX(0);
+ point.setY(point.y() + h);
+ if (i+1 < markers.count()) {
+ m_height += h;
+ }
+ }
+ }
+ }
+ m_legend->d_ptr->items()->setPos(geometry.topLeft());
+
+ m_minOffsetX = -left;
+ m_minOffsetY = -top;
+ m_maxOffsetX = m_width - geometry.width() - right;
+ m_maxOffsetY = m_height - geometry.height() - bottom;
+ }
+ break;
+ case Qt::AlignBottom: {
+ QPointF point(0, geometry.height());
+ m_width = 0;
+ m_height = 0;
+ for (int i = 0; i < markers.count(); i++) {
+ LegendMarkerItem *item = markers.at(i)->d_ptr->item();
+ if (item->isVisible()) {
+ item->setGeometry(geometry);
+ const QRectF &boundingRect = item->boundingRect();
+ qreal w = boundingRect.width();
+ qreal h = boundingRect.height();
+ m_width = qMax(m_width,w);
+ m_height = qMax(m_height,h);
+ item->setPos(point.x(),point.y() - h);
+ point.setX(point.x() + w);
+ if (point.x() + w > geometry.left() + geometry.width() - right) {
+ // Next item would go off rect.
+ point.setX(0);
+ point.setY(point.y() - h);
+ if (i+1 < markers.count()) {
+ m_height += h;
+ }
+ }
+ }
+ }
+ m_legend->d_ptr->items()->setPos(geometry.topLeft());
+
+ m_minOffsetX = -left;
+ m_minOffsetY = -m_height + geometry.height() - top;
+ m_maxOffsetX = m_width - geometry.width() - right;
+ m_maxOffsetY = -bottom;
+ }
+ break;
+ case Qt::AlignLeft: {
+ QPointF point(0, 0);
+ m_width = 0;
+ m_height = 0;
+ qreal maxWidth = 0;
+ for (int i = 0; i < markers.count(); i++) {
+ LegendMarkerItem *item = markers.at(i)->d_ptr->item();
+ if (item->isVisible()) {
+ item->setGeometry(geometry);
+ const QRectF &boundingRect = item->boundingRect();
+ qreal w = boundingRect.width();
+ qreal h = boundingRect.height();
+ m_height = qMax(m_height,h);
+ maxWidth = qMax(maxWidth,w);
+ item->setPos(point.x(),point.y());
+ point.setY(point.y() + h);
+ if (point.y() + h > geometry.bottom() - bottom) {
+ // Next item would go off rect.
+ point.setX(point.x() + maxWidth);
+ point.setY(0);
+ if (i+1 < markers.count()) {
+ m_width += maxWidth;
+ maxWidth = 0;
+ }
+ }
+ }
+ }
+ m_width += maxWidth;
+ m_legend->d_ptr->items()->setPos(geometry.topLeft());
+
+ m_minOffsetX = -left;
+ m_minOffsetY = -top;
+ m_maxOffsetX = m_width - geometry.width() - right;
+ m_maxOffsetY = m_height - geometry.height() - bottom;
+ }
+ break;
+ case Qt::AlignRight: {
+ QPointF point(geometry.width(), 0);
+ m_width = 0;
+ m_height = 0;
+ qreal maxWidth = 0;
+ for (int i = 0; i < markers.count(); i++) {
+ LegendMarkerItem *item = markers.at(i)->d_ptr->item();
+ if (item->isVisible()) {
+ item->setGeometry(geometry);
+ const QRectF &boundingRect = item->boundingRect();
+ qreal w = boundingRect.width();
+ qreal h = boundingRect.height();
+ m_height = qMax(m_height,h);
+ maxWidth = qMax(maxWidth,w);
+ item->setPos(point.x() - w,point.y());
+ point.setY(point.y() + h);
+ if (point.y() + h > geometry.bottom()-bottom) {
+ // Next item would go off rect.
+ point.setX(point.x() - maxWidth);
+ point.setY(0);
+ if (i+1 < markers.count()) {
+ m_width += maxWidth;
+ maxWidth = 0;
+ }
+ }
+ }
+ }
+ m_width += maxWidth;
+ m_legend->d_ptr->items()->setPos(geometry.topLeft());
+
+ m_minOffsetX = - m_width + geometry.width() - left;
+ m_minOffsetY = -top;
+ m_maxOffsetX = - right;
+ m_maxOffsetY = m_height - geometry.height() - bottom;
+ }
+ break;
+ default:
+ break;
+ }
+
+ setOffset(oldOffsetX, oldOffsetY);
+}
+
+QSizeF LegendLayout::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ QSizeF size(0, 0);
+ qreal left, top, right, bottom;
+ getContentsMargins(&left, &top, &right, &bottom);
+
+ if(constraint.isValid()) {
+ foreach(QLegendMarker *marker, m_legend->d_ptr->markers()) {
+ LegendMarkerItem *item = marker->d_ptr->item();
+ size = size.expandedTo(item->effectiveSizeHint(which));
+ }
+ size = size.boundedTo(constraint);
+ }
+ else if (constraint.width() >= 0) {
+ qreal width = 0;
+ qreal height = 0;
+ foreach(QLegendMarker *marker, m_legend->d_ptr->markers()) {
+ LegendMarkerItem *item = marker->d_ptr->item();
+ width+=item->effectiveSizeHint(which).width();
+ height=qMax(height,item->effectiveSizeHint(which).height());
+ }
+
+ size = QSizeF(qMin(constraint.width(),width), height);
+ }
+ else if (constraint.height() >= 0) {
+ qreal width = 0;
+ qreal height = 0;
+ foreach(QLegendMarker *marker, m_legend->d_ptr->markers()) {
+ LegendMarkerItem *item = marker->d_ptr->item();
+ width=qMax(width,item->effectiveSizeHint(which).width());
+ height+=height,item->effectiveSizeHint(which).height();
+ }
+ size = QSizeF(width,qMin(constraint.height(),height));
+ }
+ else {
+ foreach(QLegendMarker *marker, m_legend->d_ptr->markers()) {
+ LegendMarkerItem *item = marker->d_ptr->item();
+ size = size.expandedTo(item->effectiveSizeHint(which));
+ }
+ }
+ size += QSize(left + right, top + bottom);
+ return size;
+}
+
+bool LegendLayout::widthLongerThan(const LegendWidthStruct *item1,
+ const LegendWidthStruct *item2)
+{
+ return item1->width > item2->width;
+}
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/legend/legendlayout_p.h b/src/charts/legend/legendlayout_p.h
new file mode 100644
index 00000000..ec96aa31
--- /dev/null
+++ b/src/charts/legend/legendlayout_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 LEGENDLAYOUT_H
+#define LEGENDLAYOUT_H
+#include <QGraphicsLayout>
+#include "qchartglobal.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QLegend;
+class LegendMarkerItem;
+
+class LegendLayout : public QGraphicsLayout
+{
+public:
+
+ LegendLayout(QLegend *legend);
+ virtual ~LegendLayout();
+
+ void setGeometry(const QRectF &rect);
+
+ void setOffset(qreal x, qreal y);
+ QPointF offset() const;
+
+ void invalidate();
+protected:
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
+ int count() const { return 0; }
+ QGraphicsLayoutItem *itemAt(int) const { return 0; };
+ void removeAt(int) {};
+
+private:
+ void setAttachedGeometry(const QRectF &rect);
+ void setDettachedGeometry(const QRectF &rect);
+
+ struct LegendWidthStruct {
+ LegendMarkerItem *item;
+ qreal width;
+ };
+ static bool widthLongerThan(const LegendWidthStruct *item1,
+ const LegendWidthStruct *item2);
+
+private:
+ QLegend *m_legend;
+ qreal m_offsetX;
+ qreal m_offsetY;
+ qreal m_minOffsetX;
+ qreal m_minOffsetY;
+ qreal m_maxOffsetX;
+ qreal m_maxOffsetY;
+ qreal m_width;
+ qreal m_height;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/legend/legendmarkeritem.cpp b/src/charts/legend/legendmarkeritem.cpp
new file mode 100644
index 00000000..f40e4dd0
--- /dev/null
+++ b/src/charts/legend/legendmarkeritem.cpp
@@ -0,0 +1,192 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+ **
+ ** $QT_BEGIN_LICENSE$
+ ** 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
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include <QPainter>
+#include <QGraphicsSceneEvent>
+#include <QGraphicsTextItem>
+#include <QTextDocument>
+
+#include "qlegend.h"
+#include "qlegend_p.h"
+#include "qlegendmarker.h"
+#include "qlegendmarker_p.h"
+#include "legendmarkeritem_p.h"
+#include "chartpresenter_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+LegendMarkerItem::LegendMarkerItem(QLegendMarkerPrivate *marker, QGraphicsObject *parent) :
+ QGraphicsObject(parent),
+ m_marker(marker),
+ m_markerRect(0,0,10.0,10.0),
+ m_boundingRect(0,0,0,0),
+ m_textItem(new QGraphicsTextItem(this)),
+ m_rectItem(new QGraphicsRectItem(this)),
+ m_margin(3),
+ m_space(4),
+ m_hovering(false),
+ m_pressPos(0, 0)
+{
+ m_rectItem->setRect(m_markerRect);
+ m_textItem->document()->setDocumentMargin(ChartPresenter::textMargin());
+ setAcceptHoverEvents(true);
+}
+
+LegendMarkerItem::~LegendMarkerItem()
+{
+ if (m_hovering) {
+ emit m_marker->q_ptr->hovered(false);
+ }
+}
+
+void LegendMarkerItem::setPen(const QPen &pen)
+{
+ m_rectItem->setPen(pen);
+}
+
+QPen LegendMarkerItem::pen() const
+{
+ return m_rectItem->pen();
+}
+
+void LegendMarkerItem::setBrush(const QBrush &brush)
+{
+ m_rectItem->setBrush(brush);
+}
+
+QBrush LegendMarkerItem::brush() const
+{
+ return m_rectItem->brush();
+}
+
+void LegendMarkerItem::setFont(const QFont &font)
+{
+ m_textItem->setFont(font);
+ QFontMetrics fn(font);
+ m_markerRect = QRectF(0,0,fn.height()/2,fn.height()/2);
+ updateGeometry();
+}
+
+QFont LegendMarkerItem::font() const
+{
+ return m_textItem->font();
+}
+
+void LegendMarkerItem::setLabel(const QString label)
+{
+ m_label = label;
+ updateGeometry();
+}
+
+QString LegendMarkerItem::label() const
+{
+ return m_label;
+}
+
+void LegendMarkerItem::setLabelBrush(const QBrush &brush)
+{
+ m_textItem->setDefaultTextColor(brush.color());
+}
+
+QBrush LegendMarkerItem::labelBrush() const
+{
+ return QBrush(m_textItem->defaultTextColor());
+}
+
+void LegendMarkerItem::setGeometry(const QRectF &rect)
+{
+ qreal width = rect.width();
+ qreal x = m_margin + m_markerRect.width() + m_space + m_margin;
+ QRectF truncatedRect;
+
+ m_textItem->setHtml(ChartPresenter::truncatedText(m_textItem->font(), m_label, qreal(0.0),
+ width - x, rect.height(), truncatedRect));
+ m_textItem->setTextWidth(truncatedRect.width());
+
+ qreal y = qMax(m_markerRect.height() + 2 * m_margin, truncatedRect.height() + 2 * m_margin);
+
+ const QRectF &textRect = m_textItem->boundingRect();
+
+ m_textItem->setPos(x - m_margin, y / 2 - textRect.height() / 2);
+ m_rectItem->setRect(m_markerRect);
+ // The textMargin adjustments to position are done to make default case rects less blurry with anti-aliasing
+ m_rectItem->setPos(m_margin - ChartPresenter::textMargin(), y / 2.0 - m_markerRect.height() / 2.0 + ChartPresenter::textMargin());
+
+ prepareGeometryChange();
+ m_boundingRect = QRectF(0, 0, x + textRect.width() + m_margin, y);
+}
+
+QRectF LegendMarkerItem::boundingRect() const
+{
+ return m_boundingRect;
+}
+
+void LegendMarkerItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option)
+ Q_UNUSED(widget)
+ Q_UNUSED(painter)
+}
+
+QSizeF LegendMarkerItem::sizeHint(Qt::SizeHint which, const QSizeF& constraint) const
+{
+ Q_UNUSED(constraint)
+
+ QSizeF sh;
+
+ switch (which) {
+ case Qt::MinimumSize: {
+ QRectF labelRect = ChartPresenter::textBoundingRect(m_textItem->font(),
+ QStringLiteral("..."));
+ sh = QSizeF(labelRect.width() + (2.0 * m_margin) + m_space + m_markerRect.width(),
+ qMax(m_markerRect.height(), labelRect.height()) + (2.0 * m_margin));
+ break;
+ }
+ case Qt::PreferredSize: {
+ QRectF labelRect = ChartPresenter::textBoundingRect(m_textItem->font(), m_label);
+ sh = QSizeF(labelRect.width() + (2.0 * m_margin) + m_space + m_markerRect.width(),
+ qMax(m_markerRect.height(), labelRect.height()) + (2.0 * m_margin));
+ break;
+ }
+ default:
+ break;
+ }
+
+ return sh;
+}
+
+void LegendMarkerItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
+{
+ Q_UNUSED(event)
+ m_hovering = true;
+ emit m_marker->q_ptr->hovered(true);
+}
+
+void LegendMarkerItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
+{
+ Q_UNUSED(event)
+ m_hovering = false;
+ emit m_marker->q_ptr->hovered(false);
+}
+
+
+#include "moc_legendmarkeritem_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/legend/legendmarkeritem_p.h b/src/charts/legend/legendmarkeritem_p.h
new file mode 100644
index 00000000..8c49b9d0
--- /dev/null
+++ b/src/charts/legend/legendmarkeritem_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 LEGENDMARKERITEM_P_H
+#define LEGENDMARKERITEM_P_H
+
+#include <qchartglobal.h>
+#include <QGraphicsObject>
+#include <QFont>
+#include <QBrush>
+#include <QPen>
+#include <QGraphicsTextItem>
+#include <QGraphicsLayoutItem>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QLegendMarkerPrivate;
+
+class LegendMarkerItem : public QGraphicsObject, public QGraphicsLayoutItem
+{
+ Q_OBJECT
+ Q_INTERFACES(QGraphicsLayoutItem)
+public:
+ explicit LegendMarkerItem(QLegendMarkerPrivate *marker, QGraphicsObject *parent = 0);
+ ~LegendMarkerItem();
+
+ void setPen(const QPen &pen);
+ QPen pen() const;
+
+ void setBrush(const QBrush &brush);
+ QBrush brush() const;
+
+ void setFont(const QFont &font);
+ QFont font() const;
+
+ void setLabel(const QString label);
+ QString label() const;
+
+ void setLabelBrush(const QBrush &brush);
+ QBrush labelBrush() const;
+
+ void setGeometry(const QRectF &rect);
+ QRectF boundingRect() const;
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+ QSizeF sizeHint (Qt::SizeHint which, const QSizeF &constraint) const;
+
+ void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
+ void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
+
+protected:
+ QLegendMarkerPrivate *m_marker; // Knows
+ QRectF m_markerRect;
+ QRectF m_boundingRect;
+ QGraphicsTextItem *m_textItem;
+ QGraphicsRectItem *m_rectItem;
+ qreal m_margin;
+ qreal m_space;
+ QString m_label;
+
+ QBrush m_labelBrush;
+ QPen m_pen;
+ QBrush m_brush;
+ bool m_hovering;
+
+ QPointF m_pressPos;
+
+ friend class QLegendMarker;
+ friend class QLegendMarkerPrivate;
+ friend class LegendLayout;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // LEGENDMARKERITEM_P_H
diff --git a/src/charts/legend/legendscroller.cpp b/src/charts/legend/legendscroller.cpp
new file mode 100644
index 00000000..ac1784b3
--- /dev/null
+++ b/src/charts/legend/legendscroller.cpp
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QDebug>
+#include <QGraphicsSceneMouseEvent>
+#include <QGraphicsScene>
+#include <QLegendMarker>
+#include "qlegendmarker_p.h"
+#include "legendmarkeritem_p.h"
+#include "legendscroller_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+LegendScroller::LegendScroller(QChart *chart) : QLegend(chart)
+{
+}
+
+void LegendScroller::setOffset(const QPointF &point)
+{
+ d_ptr->setOffset(point);
+}
+
+QPointF LegendScroller::offset() const
+{
+ return d_ptr->offset();
+}
+
+void LegendScroller::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Scroller::handleMousePressEvent(event);
+}
+
+void LegendScroller::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Scroller::handleMouseMoveEvent(event);
+}
+
+void LegendScroller::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Scroller::handleMouseReleaseEvent(event);
+
+ if (!event->isAccepted()) {
+ QList<QGraphicsItem *> items = scene()->items(event->scenePos());
+
+ foreach (QGraphicsItem *i, items) {
+ if (d_ptr->m_markerHash.contains(i)) {
+ QLegendMarker *marker = d_ptr->m_markerHash.value(i);
+ emit marker->clicked();
+ }
+ }
+ event->accept();
+ }
+}
+
+
+#include "moc_legendscroller_p.cpp"
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/legend/legendscroller_p.h b/src/charts/legend/legendscroller_p.h
new file mode 100644
index 00000000..8ea63d78
--- /dev/null
+++ b/src/charts/legend/legendscroller_p.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 LEGENDSCROLLER_P_H
+#define LEGENDSCROLLER_P_H
+
+#include <QtCharts/qlegend.h>
+#include "qlegend_p.h"
+#include "scroller_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class LegendScroller: public QLegend, public Scroller
+{
+ Q_OBJECT
+
+public:
+ LegendScroller(QChart *chart);
+
+ void setOffset(const QPointF &point);
+ QPointF offset() const;
+
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/legend/qarealegendmarker.cpp b/src/charts/legend/qarealegendmarker.cpp
new file mode 100644
index 00000000..6e8a1d53
--- /dev/null
+++ b/src/charts/legend/qarealegendmarker.cpp
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qarealegendmarker.h"
+#include "qarealegendmarker_p.h"
+#include "qareaseries_p.h"
+#include <QAreaSeries>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QAreaLegendMarker
+ \inmodule Qt Charts
+ \brief QLegendMarker subclass for area series.
+ \mainclass
+
+ QAreaLegendMarker is related to QAreaSeries. One QAreaSeries results in one marker.
+
+ \sa QLegend, QAreaSeries
+*/
+
+/*!
+ \fn virtual LegendMarkerType QAreaLegendMarker::type()
+ Returns QLegendMarker::LegendMarkerTypeArea
+*/
+
+/*!
+ \internal
+*/
+QAreaLegendMarker::QAreaLegendMarker(QAreaSeries *series, QLegend *legend, QObject *parent) :
+ QLegendMarker(*new QAreaLegendMarkerPrivate(this,series,legend), parent)
+{
+ d_ptr->updated();
+}
+
+/*!
+ Destructor
+*/
+QAreaLegendMarker::~QAreaLegendMarker()
+{
+}
+
+/*!
+ \internal
+*/
+QAreaLegendMarker::QAreaLegendMarker(QAreaLegendMarkerPrivate &d, QObject *parent) :
+ QLegendMarker(d, parent)
+{
+}
+
+/*!
+ Returns related series of marker
+*/
+QAreaSeries* QAreaLegendMarker::series()
+{
+ Q_D(QAreaLegendMarker);
+ return d->m_series;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QAreaLegendMarkerPrivate::QAreaLegendMarkerPrivate(QAreaLegendMarker *q, QAreaSeries *series, QLegend *legend) :
+ QLegendMarkerPrivate(q,legend),
+ q_ptr(q),
+ m_series(series)
+{
+ QObject::connect(m_series->d_func(),SIGNAL(updated()), this, SLOT(updated()));
+ QObject::connect(m_series, SIGNAL(nameChanged()), this, SLOT(updated()));
+}
+
+QAreaLegendMarkerPrivate::~QAreaLegendMarkerPrivate()
+{
+}
+
+QAreaSeries* QAreaLegendMarkerPrivate::series()
+{
+ return m_series;
+}
+
+QObject* QAreaLegendMarkerPrivate::relatedObject()
+{
+ return m_series;
+}
+
+void QAreaLegendMarkerPrivate::updated()
+{
+ bool labelChanged = false;
+ bool brushChanged = false;
+
+ if (!m_customBrush && (m_item->brush() != m_series->brush())) {
+ m_item->setBrush(m_series->brush());
+ brushChanged = true;
+ }
+ if (!m_customLabel && (m_item->label() != m_series->name())) {
+ m_item->setLabel(m_series->name());
+ labelChanged = true;
+ }
+ invalidateLegend();
+
+ if (labelChanged)
+ emit q_ptr->labelChanged();
+ if (brushChanged)
+ emit q_ptr->brushChanged();
+}
+
+#include "moc_qarealegendmarker.cpp"
+#include "moc_qarealegendmarker_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/legend/qarealegendmarker.h b/src/charts/legend/qarealegendmarker.h
new file mode 100644
index 00000000..687b4431
--- /dev/null
+++ b/src/charts/legend/qarealegendmarker.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QAREALEGENDMARKER_H
+#define QAREALEGENDMARKER_H
+
+#include <QtCharts/qchartglobal.h>
+#include <QtCharts/QLegendMarker>
+#include <QtCharts/QAreaSeries>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QAreaLegendMarkerPrivate;
+
+class QT_CHARTS_EXPORT QAreaLegendMarker : public QLegendMarker
+{
+ Q_OBJECT
+
+public:
+ explicit QAreaLegendMarker(QAreaSeries *series, QLegend *legend, QObject *parent = 0);
+ virtual ~QAreaLegendMarker();
+
+ virtual LegendMarkerType type() { return LegendMarkerTypeArea; }
+
+ // Related series
+ virtual QAreaSeries* series();
+
+protected:
+ QAreaLegendMarker(QAreaLegendMarkerPrivate &d, QObject *parent = 0);
+
+private:
+ Q_DECLARE_PRIVATE(QAreaLegendMarker)
+ Q_DISABLE_COPY(QAreaLegendMarker)
+
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QAREALEGENDMARKER_H
diff --git a/src/charts/legend/qarealegendmarker_p.h b/src/charts/legend/qarealegendmarker_p.h
new file mode 100644
index 00000000..54d4e657
--- /dev/null
+++ b/src/charts/legend/qarealegendmarker_p.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QAREALEGENDMARKER_P_H
+#define QAREALEGENDMARKER_P_H
+
+#include "qchartglobal.h"
+#include "qlegendmarker_p.h"
+#include "legendmarkeritem_p.h"
+#include <QAreaSeries>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QAreaLegendMarker;
+
+class QAreaLegendMarkerPrivate : public QLegendMarkerPrivate
+{
+ Q_OBJECT
+public:
+ explicit QAreaLegendMarkerPrivate(QAreaLegendMarker *q, QAreaSeries *series, QLegend *legend);
+ virtual ~QAreaLegendMarkerPrivate();
+
+ virtual QAreaSeries* series();
+ virtual QObject* relatedObject();
+
+public Q_SLOTS:
+ virtual void updated();
+
+private:
+ QAreaLegendMarker *q_ptr;
+ QAreaSeries *m_series;
+
+ Q_DECLARE_PUBLIC(QAreaLegendMarker)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QAREALEGENDMARKER_P_H
diff --git a/src/charts/legend/qbarlegendmarker.cpp b/src/charts/legend/qbarlegendmarker.cpp
new file mode 100644
index 00000000..710c4129
--- /dev/null
+++ b/src/charts/legend/qbarlegendmarker.cpp
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbarlegendmarker.h"
+#include "qbarlegendmarker_p.h"
+#include <QAbstractBarSeries>
+#include <QBarSet>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QBarLegendMarker
+ \inmodule Qt Charts
+ \brief QLegendMarker subclass for bar series.
+ \mainclass
+
+ QBarLegendMarker is related to QAbstractBarSeries derived classes. With bar series, each marker is related to one QBarSet.
+
+ \sa QLegend, QAbstractBarSeries, QBarSet
+*/
+
+/*!
+ \fn virtual LegendMarkerType QBarLegendMarker::type()
+ Returns QLegendMarker::LegendMarkerTypeBar
+*/
+
+/*!
+ \internal
+ Constructor
+*/
+QBarLegendMarker::QBarLegendMarker(QAbstractBarSeries *series, QBarSet *barset, QLegend *legend, QObject *parent) :
+ QLegendMarker(*new QBarLegendMarkerPrivate(this,series,barset,legend), parent)
+{
+ d_ptr->updated();
+}
+
+/*!
+ Desturctor
+*/
+QBarLegendMarker::~QBarLegendMarker()
+{
+}
+
+/*!
+ \internal
+*/
+QBarLegendMarker::QBarLegendMarker(QBarLegendMarkerPrivate &d, QObject *parent) :
+ QLegendMarker(d, parent)
+{
+}
+
+/*!
+ Returns the related series of marker
+*/
+QAbstractBarSeries *QBarLegendMarker::series()
+{
+ Q_D(QBarLegendMarker);
+ return d->m_series;
+}
+
+/*!
+ Returns the related barset of marker
+*/
+QBarSet* QBarLegendMarker::barset()
+{
+ Q_D(QBarLegendMarker);
+ return d->m_barset;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QBarLegendMarkerPrivate::QBarLegendMarkerPrivate(QBarLegendMarker *q, QAbstractBarSeries *series, QBarSet *barset, QLegend *legend) :
+ QLegendMarkerPrivate(q,legend),
+ q_ptr(q),
+ m_series(series),
+ m_barset(barset)
+{
+ QObject::connect(m_barset, SIGNAL(penChanged()), this, SLOT(updated()));
+ QObject::connect(m_barset, SIGNAL(labelChanged()), this, SLOT(updated()));
+ QObject::connect(m_barset, SIGNAL(brushChanged()), this, SLOT(updated()));
+}
+
+QBarLegendMarkerPrivate::~QBarLegendMarkerPrivate()
+{
+}
+
+QAbstractBarSeries* QBarLegendMarkerPrivate::series()
+{
+ return m_series;
+}
+
+QObject* QBarLegendMarkerPrivate::relatedObject()
+{
+ return m_barset;
+}
+
+void QBarLegendMarkerPrivate::updated()
+{
+ bool labelChanged = false;
+ bool brushChanged = false;
+ bool penChanged = false;
+
+ if (!m_customPen && (m_item->pen() != m_barset->pen())) {
+ m_item->setPen(m_barset->pen());
+ penChanged = true;
+ }
+ if (!m_customBrush && (m_item->brush() != m_barset->brush())) {
+ m_item->setBrush(m_barset->brush());
+ brushChanged = true;
+ }
+ if (!m_customLabel && (m_item->label() != m_barset->label())) {
+ m_item->setLabel(m_barset->label());
+ labelChanged = true;
+ }
+ invalidateLegend();
+
+ if (labelChanged)
+ emit q_ptr->labelChanged();
+ if (brushChanged)
+ emit q_ptr->brushChanged();
+ if (penChanged)
+ emit q_ptr->penChanged();
+}
+
+#include "moc_qbarlegendmarker.cpp"
+#include "moc_qbarlegendmarker_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
+
diff --git a/src/charts/legend/qbarlegendmarker.h b/src/charts/legend/qbarlegendmarker.h
new file mode 100644
index 00000000..4af967f7
--- /dev/null
+++ b/src/charts/legend/qbarlegendmarker.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QBARLEGENDMARKER_H
+#define QBARLEGENDMARKER_H
+
+#include <QtCharts/qchartglobal.h>
+#include <QtCharts/QLegendMarker>
+#include <QtCharts/QAbstractBarSeries>
+#include <QtCharts/QBarSet>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QLegend;
+class QBarLegendMarkerPrivate;
+
+class QT_CHARTS_EXPORT QBarLegendMarker : public QLegendMarker
+{
+ Q_OBJECT
+public:
+ explicit QBarLegendMarker(QAbstractBarSeries *series, QBarSet *barset, QLegend *legend, QObject *parent = 0);
+ virtual ~QBarLegendMarker();
+
+ virtual LegendMarkerType type() { return LegendMarkerTypeBar; }
+
+ // Related series and barset
+ virtual QAbstractBarSeries* series();
+ QBarSet* barset();
+
+protected:
+ QBarLegendMarker(QBarLegendMarkerPrivate &d, QObject *parent = 0);
+
+private:
+ Q_DECLARE_PRIVATE(QBarLegendMarker)
+ Q_DISABLE_COPY(QBarLegendMarker)
+
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QBARLEGENDMARKER_H
diff --git a/src/charts/legend/qbarlegendmarker_p.h b/src/charts/legend/qbarlegendmarker_p.h
new file mode 100644
index 00000000..a42fd0fa
--- /dev/null
+++ b/src/charts/legend/qbarlegendmarker_p.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QBARLEGENDMARKER_P_H
+#define QBARLEGENDMARKER_P_H
+
+#include "qchartglobal.h"
+#include "qlegendmarker_p.h"
+#include "legendmarkeritem_p.h"
+#include <QAbstractBarSeries>
+#include <QBarSet>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QBarLegendMarker;
+
+class QBarLegendMarkerPrivate : public QLegendMarkerPrivate
+{
+ Q_OBJECT
+public:
+ explicit QBarLegendMarkerPrivate(QBarLegendMarker *q, QAbstractBarSeries *series, QBarSet *barset, QLegend *legend);
+ virtual ~QBarLegendMarkerPrivate();
+
+ virtual QAbstractBarSeries* series();
+ virtual QObject* relatedObject();
+
+public Q_SLOTS:
+ virtual void updated();
+
+private:
+ QBarLegendMarker *q_ptr;
+ QAbstractBarSeries *m_series;
+ QBarSet *m_barset;
+
+ Q_DECLARE_PUBLIC(QBarLegendMarker)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QBARLEGENDMARKER_P_H
diff --git a/src/charts/legend/qboxplotlegendmarker.cpp b/src/charts/legend/qboxplotlegendmarker.cpp
new file mode 100644
index 00000000..53594737
--- /dev/null
+++ b/src/charts/legend/qboxplotlegendmarker.cpp
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qboxplotlegendmarker.h"
+#include "qboxplotlegendmarker_p.h"
+#include "qboxplotseries.h"
+#include "qboxplotseries_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QBoxPlotLegendMarker
+ \inmodule Qt Charts
+ \brief QLegendMarker subclass for box plot series.
+ \mainclass
+
+ QBoxPlotLegendMarker is related to QBoxPlotSeries classes.
+
+ \sa QLegend, QBoxPlotSeries
+*/
+
+/*!
+ \fn virtual LegendMarkerType QBoxPlotLegendMarker::type()
+ Returns QLegendMarker::LegendMarkerTypeBoxPlot
+*/
+
+/*!
+ \internal
+*/
+QBoxPlotLegendMarker::QBoxPlotLegendMarker(QBoxPlotSeries *series, QLegend *legend, QObject *parent) :
+ QLegendMarker(*new QBoxPlotLegendMarkerPrivate(this,series,legend), parent)
+{
+ d_ptr->updated();
+}
+
+/*!
+ Destructor
+*/
+QBoxPlotLegendMarker::~QBoxPlotLegendMarker()
+{
+}
+
+/*!
+ \internal
+*/
+QBoxPlotLegendMarker::QBoxPlotLegendMarker(QBoxPlotLegendMarkerPrivate &d, QObject *parent) :
+ QLegendMarker(d, parent)
+{
+}
+
+/*!
+ Returns the related series
+*/
+QBoxPlotSeries* QBoxPlotLegendMarker::series()
+{
+ Q_D(QBoxPlotLegendMarker);
+ return d->m_series;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QBoxPlotLegendMarkerPrivate::QBoxPlotLegendMarkerPrivate(QBoxPlotLegendMarker *q, QBoxPlotSeries *series, QLegend *legend) :
+ QLegendMarkerPrivate(q,legend),
+ q_ptr(q),
+ m_series(series)
+{
+ QObject::connect(m_series, SIGNAL(nameChanged()), this, SLOT(updated()));
+ QObject::connect(m_series->d_func(), SIGNAL(updated()), this, SLOT(updated()));
+}
+
+QBoxPlotLegendMarkerPrivate::~QBoxPlotLegendMarkerPrivate()
+{
+}
+
+QAbstractSeries* QBoxPlotLegendMarkerPrivate::series()
+{
+ return m_series;
+}
+
+QObject* QBoxPlotLegendMarkerPrivate::relatedObject()
+{
+ return m_series;
+}
+
+void QBoxPlotLegendMarkerPrivate::updated()
+{
+ bool labelChanged = false;
+ bool brushChanged = false;
+
+ if (!m_customLabel && (m_item->label() != m_series->name())) {
+ m_item->setLabel(m_series->name());
+ labelChanged = true;
+ }
+ if (!m_customBrush && (m_item->brush() != m_series->brush())) {
+ m_item->setBrush(m_series->brush());
+ brushChanged = true;
+ }
+ invalidateLegend();
+
+ if (labelChanged)
+ emit q_ptr->labelChanged();
+ if (brushChanged)
+ emit q_ptr->brushChanged();
+}
+
+#include "moc_qboxplotlegendmarker.cpp"
+#include "moc_qboxplotlegendmarker_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
+
diff --git a/src/charts/legend/qboxplotlegendmarker.h b/src/charts/legend/qboxplotlegendmarker.h
new file mode 100644
index 00000000..49a5859a
--- /dev/null
+++ b/src/charts/legend/qboxplotlegendmarker.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBOXPLOTLEGENDMARKER_H
+#define QBOXPLOTLEGENDMARKER_H
+
+#include <QtCharts/qchartglobal.h>
+#include <QtCharts/QLegendMarker>
+#include <QtCharts/QBoxPlotSeries>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QBoxPlotLegendMarkerPrivate;
+
+class QT_CHARTS_EXPORT QBoxPlotLegendMarker : public QLegendMarker
+{
+ Q_OBJECT
+
+public:
+ explicit QBoxPlotLegendMarker(QBoxPlotSeries *series, QLegend *legend, QObject *parent = 0);
+ virtual ~QBoxPlotLegendMarker();
+
+ virtual LegendMarkerType type() { return LegendMarkerTypeBoxPlot; }
+
+ // Related series
+ virtual QBoxPlotSeries* series();
+
+protected:
+ QBoxPlotLegendMarker(QBoxPlotLegendMarkerPrivate &d, QObject *parent = 0);
+
+private:
+ Q_DECLARE_PRIVATE(QBoxPlotLegendMarker)
+ Q_DISABLE_COPY(QBoxPlotLegendMarker)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QBOXPLOTLEGENDMARKER_H
diff --git a/src/charts/legend/qboxplotlegendmarker_p.h b/src/charts/legend/qboxplotlegendmarker_p.h
new file mode 100644
index 00000000..cdabb688
--- /dev/null
+++ b/src/charts/legend/qboxplotlegendmarker_p.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QBOXPLOTLEGENDMARKER_P_H
+#define QBOXPLOTLEGENDMARKER_P_H
+
+#include "qchartglobal.h"
+#include "qlegendmarker_p.h"
+#include "legendmarkeritem_p.h"
+#include <QBoxPlotSeries>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QBoxPlotLegendMarker;
+
+class QBoxPlotLegendMarkerPrivate : public QLegendMarkerPrivate
+{
+ Q_OBJECT
+public:
+ explicit QBoxPlotLegendMarkerPrivate(QBoxPlotLegendMarker *q, QBoxPlotSeries *series, QLegend *legend);
+ virtual ~QBoxPlotLegendMarkerPrivate();
+
+ virtual QAbstractSeries *series();
+ virtual QObject *relatedObject();
+
+public Q_SLOTS:
+ virtual void updated();
+
+private:
+ QBoxPlotLegendMarker *q_ptr;
+ QBoxPlotSeries *m_series;
+
+ Q_DECLARE_PUBLIC(QBoxPlotLegendMarker)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QBOXPLOTLEGENDMARKER_P_H
diff --git a/src/charts/legend/qlegend.cpp b/src/charts/legend/qlegend.cpp
new file mode 100644
index 00000000..ead1fac8
--- /dev/null
+++ b/src/charts/legend/qlegend.cpp
@@ -0,0 +1,632 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+ **
+ ** $QT_BEGIN_LICENSE$
+ ** 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
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include "qlegend.h"
+#include "qlegend_p.h"
+#include "qabstractseries.h"
+#include "qabstractseries_p.h"
+#include "qchart_p.h"
+#include "legendlayout_p.h"
+#include "chartpresenter_p.h"
+#include "abstractchartlayout_p.h"
+#include "qlegendmarker.h"
+#include "qlegendmarker_p.h"
+#include "legendmarkeritem_p.h"
+#include "chartdataset_p.h"
+#include <QPainter>
+#include <QPen>
+#include <QGraphicsItemGroup>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QLegend
+ \inmodule Qt Charts
+ \brief Legend object.
+ \mainclass
+
+ QLegend is a graphical object for displaying the legend of the chart. Legend state is updated by QChart, when
+ series have been changed. By default, legend is drawn by QChart, but user can set a new parent to legend and
+ handle the drawing manually.
+ User isn't supposed to create or delete legend objects, but can reference it via QChart class.
+
+ \image examples_percentbarchart_legend.png
+
+ \sa QChart
+*/
+/*!
+ \qmltype Legend
+ \instantiates QLegend
+ \inqmlmodule QtCharts
+
+ \brief Legend is part of Qt Chart QML API.
+
+ Legend is a graphical object, whics displays legend of the chart. Legend state is updated by
+ ChartView, when series have been changed. Legend is used via ChartView class. For example:
+ \code
+ ChartView {
+ legend.visible: true
+ legend.alignment: Qt.AlignBottom
+ // Add a few series...
+ }
+ \endcode
+
+ \image examples_percentbarchart_legend.png
+
+ Please note that there is no QML API available for modifying legend markers, unlike in the Qt
+ API of Charts. The use case of modifying markers can be implemented for example by creating your
+ own custom legend. For an example on how to do this,
+ see \l {qmlcustomlegend}{Qml Custom Example} application.
+*/
+
+/*!
+ \property QLegend::alignment
+ \brief The alignment of the legend.
+
+ Legend paints on the defined position in the chart. The following alignments are supported:
+ Qt::AlignTop, Qt::AlignBottom, Qt::AlignLeft, Qt::AlignRight. If you set more than one flag the result is undefined.
+*/
+/*!
+ \qmlproperty Qt.Alignment Legend::alignment
+ \brief The alignment of the legend.
+
+ Legend paints on the defined position in the chart. The following alignments are supported:
+ Qt.AlignTop, Qt.AlignBottom, Qt.AlignLeft, Qt.AlignRight. If you set more than one flag the result is undefined.
+*/
+
+/*!
+ \property QLegend::backgroundVisible
+ Whether the legend background is visible or not.
+*/
+/*!
+ \qmlproperty bool Legend::backgroundVisible
+ Whether the legend background is visible or not.
+*/
+
+/*!
+ \property QLegend::color
+ The color of the legend, i.e. the background (brush) color. Note that if you change the color
+ of the legend, the style of the legend brush is set to Qt::SolidPattern.
+*/
+/*!
+ \qmlproperty color Legend::color
+ The color of the legend, i.e. the background (brush) color.
+*/
+
+/*!
+ \property QLegend::borderColor
+ The border color of the legend, i.e. the line color.
+*/
+/*!
+ \qmlproperty color Legend::borderColor
+ The border color of the legend, i.e. the line color.
+*/
+
+/*!
+ \property QLegend::font
+ The font of markers used by legend.
+*/
+/*!
+ \qmlproperty Font Legend::font
+ The font of markers used by legend.
+*/
+
+/*!
+ \property QLegend::labelColor
+ The color of brush used to draw labels.
+*/
+/*!
+ \qmlproperty color Legend::labelColor
+ The color of brush used to draw labels.
+*/
+
+/*!
+ \property QLegend::reverseMarkers
+ Whether reverse order is used for the markers in legend or not. False by default.
+*/
+/*!
+ \qmlproperty bool Legend::reverseMarkers
+ Whether reverse order is used for the markers in legend or not. False by default.
+*/
+
+/*!
+ \fn void QLegend::backgroundVisibleChanged(bool)
+ The visibility of the legend background changed to \a visible.
+*/
+
+/*!
+ \fn void QLegend::colorChanged(QColor)
+ The color of the legend background changed to \a color.
+*/
+
+/*!
+ \fn void QLegend::borderColorChanged(QColor)
+ The border color of the legend background changed to \a color.
+*/
+
+/*!
+ \fn void QLegend::fontChanged(QFont)
+ The font of markers of the legend changed to \a font.
+*/
+
+/*!
+ \fn void QLegend::labelColorChanged(QColor color)
+ This signal is emitted when the color of brush used to draw labels has changed to \a color.
+*/
+
+/*!
+ \fn void QLegend::reverseMarkersChanged(bool)
+ The use of reverse order for the markers in legend is changed to \a reverseMarkers.
+*/
+
+QLegend::QLegend(QChart *chart): QGraphicsWidget(chart),
+ d_ptr(new QLegendPrivate(chart->d_ptr->m_presenter, chart, this))
+{
+ setZValue(ChartPresenter::LegendZValue);
+ setFlags(QGraphicsItem::ItemClipsChildrenToShape);
+ QObject::connect(chart->d_ptr->m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), d_ptr.data(), SLOT(handleSeriesAdded(QAbstractSeries*)));
+ QObject::connect(chart->d_ptr->m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)), d_ptr.data(), SLOT(handleSeriesRemoved(QAbstractSeries*)));
+ setLayout(d_ptr->m_layout);
+}
+
+/*!
+ Destroys the legend object. Legend is always owned by a QChart, so an application should never call this.
+*/
+QLegend::~QLegend()
+{
+}
+
+/*!
+ \internal
+ */
+void QLegend::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option)
+ Q_UNUSED(widget)
+
+ if (!d_ptr->m_backgroundVisible)
+ return;
+
+ painter->setOpacity(opacity());
+ painter->setPen(d_ptr->m_pen);
+ painter->setBrush(d_ptr->m_brush);
+ painter->drawRoundRect(rect(), d_ptr->roundness(rect().width()), d_ptr->roundness(rect().height()));
+}
+
+
+/*!
+ Sets the \a brush of legend. Brush affects the background of legend.
+ */
+void QLegend::setBrush(const QBrush &brush)
+{
+ if (d_ptr->m_brush != brush) {
+ d_ptr->m_brush = brush;
+ update();
+ emit colorChanged(brush.color());
+ }
+}
+
+/*!
+ Returns the brush used by legend.
+ */
+QBrush QLegend::brush() const
+{
+ return d_ptr->m_brush;
+}
+
+void QLegend::setColor(QColor color)
+{
+ QBrush b = d_ptr->m_brush;
+ if (b.style() != Qt::SolidPattern || b.color() != color) {
+ b.setStyle(Qt::SolidPattern);
+ b.setColor(color);
+ setBrush(b);
+ }
+}
+
+QColor QLegend::color()
+{
+ return d_ptr->m_brush.color();
+}
+
+/*!
+ Sets the \a pen of legend. Pen affects the legend borders.
+ */
+void QLegend::setPen(const QPen &pen)
+{
+ if (d_ptr->m_pen != pen) {
+ d_ptr->m_pen = pen;
+ update();
+ emit borderColorChanged(pen.color());
+ }
+}
+
+/*!
+ Returns the pen used by legend.
+ */
+
+QPen QLegend::pen() const
+{
+ return d_ptr->m_pen;
+}
+
+void QLegend::setFont(const QFont &font)
+{
+ if (d_ptr->m_font != font) {
+ // Hide items to avoid flickering
+ d_ptr->items()->setVisible(false);
+ d_ptr->m_font = font;
+ foreach (QLegendMarker *marker, d_ptr->markers()) {
+ marker->setFont(d_ptr->m_font);
+ }
+ layout()->invalidate();
+ emit fontChanged(font);
+ }
+}
+
+QFont QLegend::font() const
+{
+ return d_ptr->m_font;
+}
+
+void QLegend::setBorderColor(QColor color)
+{
+ QPen p = d_ptr->m_pen;
+ if (p.color() != color) {
+ p.setColor(color);
+ setPen(p);
+ }
+}
+
+QColor QLegend::borderColor()
+{
+ return d_ptr->m_pen.color();
+}
+
+/*!
+ Set brush used to draw labels to \a brush.
+*/
+void QLegend::setLabelBrush(const QBrush &brush)
+{
+ if (d_ptr->m_labelBrush != brush) {
+ d_ptr->m_labelBrush = brush;
+ foreach (QLegendMarker *marker, d_ptr->markers()) {
+ marker->setLabelBrush(d_ptr->m_labelBrush);
+ // Note: The pen of the marker rectangle could be exposed in the public QLegend API
+ // instead of mapping it from label brush color
+ marker->setPen(brush.color());
+ }
+ emit labelColorChanged(brush.color());
+ }
+}
+
+/*!
+ Brush used to draw labels.
+*/
+QBrush QLegend::labelBrush() const
+{
+ return d_ptr->m_labelBrush;
+}
+
+void QLegend::setLabelColor(QColor color)
+{
+ QBrush b = d_ptr->m_labelBrush;
+ if (b.style() != Qt::SolidPattern || b.color() != color) {
+ b.setStyle(Qt::SolidPattern);
+ b.setColor(color);
+ setLabelBrush(b);
+ }
+}
+
+QColor QLegend::labelColor() const
+{
+ return d_ptr->m_labelBrush.color();
+}
+
+
+void QLegend::setAlignment(Qt::Alignment alignment)
+{
+ if (d_ptr->m_alignment != alignment) {
+ d_ptr->m_alignment = alignment;
+ layout()->invalidate();
+ }
+}
+
+Qt::Alignment QLegend::alignment() const
+{
+ return d_ptr->m_alignment;
+}
+
+/*!
+ Detaches the legend from chart. Chart won't change layout of the legend.
+ */
+void QLegend::detachFromChart()
+{
+ d_ptr->m_attachedToChart = false;
+// layout()->invalidate();
+ d_ptr->m_chart->layout()->invalidate();
+ setParent(0);
+
+}
+
+/*!
+ Attaches the legend to chart. Chart may change layout of the legend.
+ */
+void QLegend::attachToChart()
+{
+ d_ptr->m_attachedToChart = true;
+// layout()->invalidate();
+ d_ptr->m_chart->layout()->invalidate();
+ setParent(d_ptr->m_chart);
+}
+
+/*!
+ Returns true, if legend is attached to chart.
+ */
+bool QLegend::isAttachedToChart()
+{
+ return d_ptr->m_attachedToChart;
+}
+
+/*!
+ Sets the visibility of legend background to \a visible
+ */
+void QLegend::setBackgroundVisible(bool visible)
+{
+ if (d_ptr->m_backgroundVisible != visible) {
+ d_ptr->m_backgroundVisible = visible;
+ update();
+ emit backgroundVisibleChanged(visible);
+ }
+}
+
+/*!
+ Returns the visibility of legend background
+ */
+bool QLegend::isBackgroundVisible() const
+{
+ return d_ptr->m_backgroundVisible;
+}
+
+/*!
+ Returns the list of markers in legend. The list can be filtered with \a series parameter.
+ If \a series is given, only markers related to that series are returned.
+*/
+QList<QLegendMarker*> QLegend::markers(QAbstractSeries *series) const
+{
+ return d_ptr->markers(series);
+}
+
+bool QLegend::reverseMarkers()
+{
+ return d_ptr->m_reverseMarkers;
+}
+
+void QLegend::setReverseMarkers(bool reverseMarkers)
+{
+ if (d_ptr->m_reverseMarkers != reverseMarkers) {
+ d_ptr->m_reverseMarkers = reverseMarkers;
+ layout()->invalidate();
+ emit reverseMarkersChanged(reverseMarkers);
+ }
+}
+
+/*!
+ \internal \a event see QGraphicsWidget for details
+ */
+void QLegend::hideEvent(QHideEvent *event)
+{
+ if (isAttachedToChart())
+ d_ptr->m_presenter->layout()->invalidate();
+ QGraphicsWidget::hideEvent(event);
+}
+/*!
+ \internal \a event see QGraphicsWidget for details
+ */
+void QLegend::showEvent(QShowEvent *event)
+{
+ if (isAttachedToChart())
+ layout()->invalidate();
+ QGraphicsWidget::showEvent(event);
+ //layout activation will show the items
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QLegendPrivate::QLegendPrivate(ChartPresenter *presenter, QChart *chart, QLegend *q)
+ : q_ptr(q),
+ m_presenter(presenter),
+ m_layout(new LegendLayout(q)),
+ m_chart(chart),
+ m_items(new QGraphicsItemGroup(q)),
+ m_alignment(Qt::AlignTop),
+ m_brush(QBrush()),
+ m_pen(QPen()),
+ m_labelBrush(QBrush()),
+ m_diameter(5),
+ m_attachedToChart(true),
+ m_backgroundVisible(false),
+ m_reverseMarkers(false)
+{
+ m_items->setHandlesChildEvents(false);
+}
+
+QLegendPrivate::~QLegendPrivate()
+{
+
+}
+
+void QLegendPrivate::setOffset(const QPointF &offset)
+{
+ m_layout->setOffset(offset.x(), offset.y());
+}
+
+QPointF QLegendPrivate::offset() const
+{
+ return m_layout->offset();
+}
+
+int QLegendPrivate::roundness(qreal size)
+{
+ return 100 * m_diameter / int(size);
+}
+
+QList<QLegendMarker*> QLegendPrivate::markers(QAbstractSeries *series)
+{
+ // Return all markers
+ if (!series) {
+ return m_markers;
+ }
+
+ // Create filtered list
+ QList<QLegendMarker *> markers;
+ foreach (QLegendMarker *marker, m_markers) {
+ if (marker->series() == series) {
+ markers.append(marker);
+ }
+ }
+ return markers;
+}
+
+void QLegendPrivate::handleSeriesAdded(QAbstractSeries *series)
+{
+ if (m_series.contains(series)) {
+ return;
+ }
+
+ QList<QLegendMarker*> newMarkers = series->d_ptr->createLegendMarkers(q_ptr);
+ decorateMarkers(newMarkers);
+ addMarkers(newMarkers);
+
+ QObject::connect(series->d_ptr.data(), SIGNAL(countChanged()), this, SLOT(handleCountChanged()));
+ QObject::connect(series, SIGNAL(visibleChanged()), this, SLOT(handleSeriesVisibleChanged()));
+
+ m_series.append(series);
+ m_items->setVisible(false);
+ m_layout->invalidate();
+}
+
+void QLegendPrivate::handleSeriesRemoved(QAbstractSeries *series)
+{
+ if (m_series.contains(series)) {
+ m_series.removeOne(series);
+ }
+
+ // Find out, which markers to remove
+ QList<QLegendMarker *> removed;
+ foreach (QLegendMarker *m, m_markers) {
+ if (m->series() == series) {
+ removed << m;
+ }
+ }
+ removeMarkers(removed);
+
+ QObject::disconnect(series->d_ptr.data(), SIGNAL(countChanged()), this, SLOT(handleCountChanged()));
+ QObject::disconnect(series, SIGNAL(visibleChanged()), this, SLOT(handleSeriesVisibleChanged()));
+
+ m_layout->invalidate();
+}
+
+void QLegendPrivate::handleSeriesVisibleChanged()
+{
+ QAbstractSeries *series = qobject_cast<QAbstractSeries *> (sender());
+ Q_ASSERT(series);
+
+ foreach (QLegendMarker *marker, m_markers) {
+ if (marker->series() == series) {
+ marker->setVisible(series->isVisible());
+ }
+ }
+
+ if (m_chart->isVisible())
+ m_layout->invalidate();
+}
+
+void QLegendPrivate::handleCountChanged()
+{
+ // Here we handle the changes in marker count.
+ // Can happen for example when pieslice(s) have been added to or removed from pieseries.
+
+ QAbstractSeriesPrivate *series = qobject_cast<QAbstractSeriesPrivate *> (sender());
+ QList<QLegendMarker *> createdMarkers = series->createLegendMarkers(q_ptr);
+
+ // Find out removed markers and created markers
+ QList<QLegendMarker *> removedMarkers;
+ foreach (QLegendMarker *oldMarker, m_markers) {
+ // we have marker, which is related to sender.
+ if (oldMarker->series() == series->q_ptr) {
+ bool found = false;
+ foreach(QLegendMarker *newMarker, createdMarkers) {
+ // New marker considered existing if:
+ // - d_ptr->relatedObject() is same for both markers.
+ if (newMarker->d_ptr->relatedObject() == oldMarker->d_ptr->relatedObject()) {
+ // Delete the new marker, since we already have existing marker, that might be connected on user side.
+ found = true;
+ createdMarkers.removeOne(newMarker);
+ delete newMarker;
+ }
+ }
+ if (!found) {
+ // No related object found for marker, add to removedMarkers list
+ removedMarkers << oldMarker;
+ }
+ }
+ }
+
+ removeMarkers(removedMarkers);
+ decorateMarkers(createdMarkers);
+ addMarkers(createdMarkers);
+
+ q_ptr->layout()->invalidate();
+}
+
+void QLegendPrivate::addMarkers(QList<QLegendMarker *> markers)
+{
+ foreach (QLegendMarker *marker, markers) {
+ m_items->addToGroup(marker->d_ptr.data()->item());
+ m_markers << marker;
+ m_markerHash.insert(marker->d_ptr->item(), marker);
+ }
+}
+
+void QLegendPrivate::removeMarkers(QList<QLegendMarker *> markers)
+{
+ foreach (QLegendMarker *marker, markers) {
+ marker->d_ptr->item()->setVisible(false);
+ m_items->removeFromGroup(marker->d_ptr->item());
+ m_markers.removeOne(marker);
+ m_markerHash.remove(marker->d_ptr->item());
+ delete marker;
+ }
+}
+
+void QLegendPrivate::decorateMarkers(QList<QLegendMarker *> markers)
+{
+ foreach (QLegendMarker *marker, markers) {
+ marker->setFont(m_font);
+ marker->setLabelBrush(m_labelBrush);
+ }
+}
+
+
+#include "moc_qlegend.cpp"
+#include "moc_qlegend_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/legend/qlegend.h b/src/charts/legend/qlegend.h
new file mode 100644
index 00000000..c727e8f3
--- /dev/null
+++ b/src/charts/legend/qlegend.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLEGEND_H
+#define QLEGEND_H
+
+#include <QtCharts/qchartglobal.h>
+#include <QGraphicsWidget>
+#include <QPen>
+#include <QBrush>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QChart;
+class QLegendPrivate;
+class QLegendMarker;
+class QAbstractSeries;
+
+class QT_CHARTS_EXPORT QLegend : public QGraphicsWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment)
+ Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible NOTIFY backgroundVisibleChanged)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+ Q_PROPERTY(QColor borderColor READ borderColor WRITE setBorderColor NOTIFY borderColorChanged)
+ Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
+ Q_PROPERTY(QColor labelColor READ labelColor WRITE setLabelColor NOTIFY labelColorChanged)
+ Q_PROPERTY(bool reverseMarkers READ reverseMarkers WRITE setReverseMarkers NOTIFY reverseMarkersChanged)
+
+private:
+ explicit QLegend(QChart *chart);
+
+public:
+ ~QLegend();
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ void setBrush(const QBrush &brush);
+ QBrush brush() const;
+ void setColor(QColor color);
+ QColor color();
+
+ void setPen(const QPen &pen);
+ QPen pen() const;
+ void setBorderColor(QColor color);
+ QColor borderColor();
+
+ void setFont(const QFont &font);
+ QFont font() const;
+ void setLabelBrush(const QBrush &brush);
+ QBrush labelBrush() const;
+
+ void setLabelColor(QColor color);
+ QColor labelColor() const;
+
+ void setAlignment(Qt::Alignment alignment);
+ Qt::Alignment alignment() const;
+
+ void detachFromChart();
+ void attachToChart();
+ bool isAttachedToChart();
+
+ void setBackgroundVisible(bool visible = true);
+ bool isBackgroundVisible() const;
+
+ QList <QLegendMarker*> markers(QAbstractSeries *series = 0) const;
+
+ bool reverseMarkers();
+ void setReverseMarkers(bool reverseMarkers = true);
+
+protected:
+ void hideEvent(QHideEvent *event);
+ void showEvent(QShowEvent *event);
+
+Q_SIGNALS:
+ void backgroundVisibleChanged(bool visible);
+ void colorChanged(QColor color);
+ void borderColorChanged(QColor color);
+ void fontChanged(QFont font);
+ void labelColorChanged(QColor color);
+ void reverseMarkersChanged(bool reverseMarkers);
+
+private:
+ QScopedPointer<QLegendPrivate> d_ptr;
+ Q_DISABLE_COPY(QLegend)
+ friend class LegendScroller;
+ friend class LegendLayout;
+ friend class ChartLayout;
+ friend class LegendMarkerItem;
+ friend class QLegendMarkerPrivate;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QLEGEND_H
diff --git a/src/charts/legend/qlegend_p.h b/src/charts/legend/qlegend_p.h
new file mode 100644
index 00000000..655825c6
--- /dev/null
+++ b/src/charts/legend/qlegend_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QLEGEND_P_H
+#define QLEGEND_P_H
+
+#include "qlegend.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QChart;
+class ChartPresenter;
+class QAbstractSeries;
+class LegendLayout;
+class QLegendMarker;
+
+class QLegendPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QLegendPrivate(ChartPresenter *presenter, QChart *chart, QLegend *q);
+ ~QLegendPrivate();
+
+ void setOffset(const QPointF &offset);
+ QPointF offset() const;
+ int roundness(qreal size);
+
+ QGraphicsItemGroup* items() { return m_items; }
+
+ QList<QLegendMarker*> markers(QAbstractSeries *series = 0);
+
+public Q_SLOTS:
+ void handleSeriesAdded(QAbstractSeries *series);
+ void handleSeriesRemoved(QAbstractSeries *series);
+ void handleSeriesVisibleChanged();
+ void handleCountChanged();
+
+private:
+ // Internal helpers
+ void addMarkers(QList<QLegendMarker *> markers);
+ void removeMarkers(QList<QLegendMarker *> markers);
+ void decorateMarkers(QList<QLegendMarker *> markers);
+
+private:
+ QLegend *q_ptr;
+ ChartPresenter *m_presenter;
+ LegendLayout *m_layout;
+ QChart *m_chart;
+ QGraphicsItemGroup *m_items;
+ Qt::Alignment m_alignment;
+ QBrush m_brush;
+ QPen m_pen;
+ QFont m_font;
+ QBrush m_labelBrush;
+
+ qreal m_diameter;
+ bool m_attachedToChart;
+ bool m_backgroundVisible;
+ bool m_reverseMarkers;
+
+ QList<QLegendMarker *> m_markers;
+ QList<QAbstractSeries *> m_series;
+
+ QHash<QGraphicsItem *, QLegendMarker *> m_markerHash;
+
+ friend class QLegend;
+ friend class LegendMarkerItem;
+ friend class LegendLayout;
+ friend class QLegendMarkerPrivate;
+ friend class LegendScroller;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/legend/qlegendmarker.cpp b/src/charts/legend/qlegendmarker.cpp
new file mode 100644
index 00000000..e170cb4d
--- /dev/null
+++ b/src/charts/legend/qlegendmarker.cpp
@@ -0,0 +1,294 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+ **
+ ** $QT_BEGIN_LICENSE$
+ ** 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
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include "qlegendmarker.h"
+#include "qlegendmarker_p.h"
+#include "legendmarkeritem_p.h"
+#include "qlegend.h"
+#include "qlegend_p.h"
+#include "legendlayout_p.h"
+#include <QFontMetrics>
+#include <QGraphicsSceneEvent>
+#include <QAbstractSeries>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QLegendMarker
+ \inmodule Qt Charts
+ \brief LegendMarker object.
+ \mainclass
+
+ QLegendMarker is abstract object that can be used to access markers inside QLegend. Legend marker consists of two
+ items: The colored box, which reflects the color of series and label, which is the name of series (or label of slice/barset
+ in case of pie or bar series)
+ The QLegendMarker is always related to one series.
+
+ \image examples_percentbarchart_legend.png
+
+ \sa QLegend
+*/
+/*!
+ \enum QLegendMarker::LegendMarkerType
+
+ The type of the legendmarker object.
+
+ \value LegendMarkerTypeArea
+ \value LegendMarkerTypeBar
+ \value LegendMarkerTypePie
+ \value LegendMarkerTypeXY
+ \value LegendMarkerTypeBoxPlot
+*/
+
+/*!
+ \fn virtual LegendMarkerType QLegendMarker::type() = 0;
+ Returns the type of legendmarker. Type depends of the related series. LegendMarkerTypeXY is used for all QXYSeries derived
+ classes.
+*/
+
+/*!
+ \fn virtual QAbstractSeries* QLegendMarker::series() = 0;
+ Returns pointer to series, which is related to this marker. Marker is always related to some series.
+*/
+
+/*!
+ \fn void QLegendMarker::clicked();
+ This signal is emitted, when marker is clicked with mouse.
+*/
+
+/*!
+ \fn void QLegendMarker::hovered(bool status);
+ This signal is emitted, when mouse is hovered over marker. \a status is true, when mouse enters the marker
+ and false when it leaves the marker.
+*/
+
+/*!
+ \fn void QLegendMarker::labelChanged()
+ This signal is emitted when the label of the legend marker has changed.
+*/
+
+/*!
+ \fn void QLegendMarker::labelBrushChanged()
+ This signal is emitted when the label brush of the legend marker has changed.
+*/
+
+/*!
+ \fn void QLegendMarker::fontChanged()
+ This signal is emitted when the (label) font of the legend marker has changed.
+*/
+
+/*!
+ \fn void QLegendMarker::penChanged()
+ This signal is emitted when the pen of the legend marker has changed.
+*/
+
+/*!
+ \fn void QLegendMarker::brushChanged()
+ This signal is emitted when the brush of the legend marker has changed.
+*/
+
+/*!
+ \fn void QLegendMarker::visibleChanged()
+ This signal is emitted when the visibility of the legend marker has changed.
+*/
+
+/*!
+ \property QLegendMarker::label
+ Label of the marker. This is the text that is shown in legend.
+*/
+
+/*!
+ \property QLegendMarker::labelBrush
+ Brush of the label
+*/
+
+/*!
+ \property QLegendMarker::font
+ Font of the label
+*/
+
+/*!
+ \property QLegendMarker::pen
+ Pen of the marker. This is the outline of the colored square.
+*/
+
+/*!
+ \property QLegendMarker::brush
+ Brush of the marker. This is the inside of the colored square.
+*/
+
+/*!
+ \property QLegendMarker::visible
+ Visibility of the legend marker. Affects label and the colored square.
+*/
+
+
+/*!
+ \internal
+ */
+QLegendMarker::QLegendMarker(QLegendMarkerPrivate &d, QObject *parent) :
+ QObject(parent),
+ d_ptr(&d)
+{
+ d_ptr->m_item->setVisible(d_ptr->series()->isVisible());
+}
+
+/*!
+ Destructor of marker
+*/
+QLegendMarker::~QLegendMarker()
+{
+}
+
+/*!
+ Returns the label of the marker.
+*/
+QString QLegendMarker::label() const
+{
+ return d_ptr->m_item->label();
+}
+
+/*!
+ Sets the \a label of marker. Note that changing name of series will also change label of its marker.
+*/
+void QLegendMarker::setLabel(const QString &label)
+{
+ if (label.isEmpty()) {
+ d_ptr->m_customLabel = false;
+ } else {
+ d_ptr->m_customLabel = true;
+ d_ptr->m_item->setLabel(label);
+ }
+}
+/*!
+ Returns the brush which is used to draw label.
+*/
+QBrush QLegendMarker::labelBrush() const
+{
+ return d_ptr->m_item->labelBrush();
+}
+
+/*!
+ Sets the \a brush of label
+*/
+void QLegendMarker::setLabelBrush(const QBrush &brush)
+{
+ d_ptr->m_item->setLabelBrush(brush);
+}
+
+/*!
+ Retuns the font of label
+*/
+QFont QLegendMarker::font() const
+{
+ return d_ptr->m_item->font();
+}
+
+/*!
+ Sets the \a font of label
+*/
+void QLegendMarker::setFont(const QFont &font)
+{
+ d_ptr->m_item->setFont(font);
+}
+
+/*!
+ Returns the pen of marker item
+*/
+QPen QLegendMarker::pen() const
+{
+ return d_ptr->m_item->pen();
+}
+
+/*!
+ Sets the \a pen of marker item
+*/
+void QLegendMarker::setPen(const QPen &pen)
+{
+ if (pen == QPen(Qt::NoPen)) {
+ d_ptr->m_customPen = false;
+ } else {
+ d_ptr->m_customPen = true;
+ d_ptr->m_item->setPen(pen);
+ }
+}
+
+/*!
+ Returns the brush of marker item
+*/
+QBrush QLegendMarker::brush() const
+{
+ return d_ptr->m_item->brush();
+}
+
+/*!
+ Sets the \a brush of marker item. Note that changing color of the series also changes this.
+*/
+void QLegendMarker::setBrush(const QBrush &brush)
+{
+ if (brush == QBrush(Qt::NoBrush)) {
+ d_ptr->m_customBrush = false;
+ } else {
+ d_ptr->m_customBrush = true;
+ d_ptr->m_item->setBrush(brush);
+ }
+}
+
+/*!
+ Returns visibility of the marker
+*/
+bool QLegendMarker::isVisible() const
+{
+ return d_ptr->m_item->isVisible();
+}
+
+/*!
+ Sets markers visibility to \a visible
+*/
+void QLegendMarker::setVisible(bool visible)
+{
+ d_ptr->m_item->setVisible(visible);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+QLegendMarkerPrivate::QLegendMarkerPrivate(QLegendMarker *q, QLegend *legend) :
+ m_legend(legend),
+ m_customLabel(false),
+ m_customBrush(false),
+ m_customPen(false),
+ q_ptr(q)
+{
+ m_item = new LegendMarkerItem(this);
+}
+
+QLegendMarkerPrivate::~QLegendMarkerPrivate()
+{
+ delete m_item;
+}
+
+void QLegendMarkerPrivate::invalidateLegend()
+{
+ m_legend->d_ptr->m_layout->invalidate();
+}
+
+#include "moc_qlegendmarker.cpp"
+#include "moc_qlegendmarker_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/legend/qlegendmarker.h b/src/charts/legend/qlegendmarker.h
new file mode 100644
index 00000000..0d683886
--- /dev/null
+++ b/src/charts/legend/qlegendmarker.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+ **
+ ** $QT_BEGIN_LICENSE$
+ ** 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
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#ifndef QLEGENDMARKER_H
+#define QLEGENDMARKER_H
+
+#include <QtCharts/qchartglobal.h>
+#include <QObject>
+#include <QPen>
+#include <QBrush>
+#include <QFont>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QLegendMarkerPrivate;
+class QAbstractSeries;
+class QLegend;
+
+class QT_CHARTS_EXPORT QLegendMarker : public QObject
+{
+ Q_OBJECT
+
+public:
+ enum LegendMarkerType {
+ LegendMarkerTypeArea,
+ LegendMarkerTypeBar,
+ LegendMarkerTypePie,
+ LegendMarkerTypeXY,
+ LegendMarkerTypeBoxPlot
+ };
+
+ Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY labelChanged)
+ Q_PROPERTY(QBrush labelBrush READ labelBrush WRITE setLabelBrush NOTIFY labelBrushChanged)
+ Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
+ Q_PROPERTY(QPen pen READ pen WRITE setPen NOTIFY penChanged)
+ Q_PROPERTY(QBrush brush READ brush WRITE setBrush NOTIFY brushChanged)
+ Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged)
+ Q_ENUMS(LegendMarkerType)
+
+public:
+ virtual ~QLegendMarker();
+ virtual LegendMarkerType type() = 0;
+
+ QString label() const;
+ void setLabel(const QString &label);
+
+ QBrush labelBrush() const;
+ void setLabelBrush(const QBrush &brush);
+
+ QFont font() const;
+ void setFont(const QFont &font);
+
+ QPen pen() const;
+ void setPen(const QPen &pen);
+
+ QBrush brush() const;
+ void setBrush(const QBrush &brush);
+
+ bool isVisible() const;
+ void setVisible(bool visible);
+
+ virtual QAbstractSeries* series() = 0;
+
+Q_SIGNALS:
+ void clicked();
+ void hovered(bool status);
+ void labelChanged();
+ void labelBrushChanged();
+ void fontChanged();
+ void penChanged();
+ void brushChanged();
+ void visibleChanged();
+
+protected:
+ explicit QLegendMarker(QLegendMarkerPrivate &d, QObject *parent = 0);
+
+ QScopedPointer<QLegendMarkerPrivate> d_ptr;
+ Q_DISABLE_COPY(QLegendMarker)
+ friend class QLegendPrivate;
+ friend class QLegendMarkerPrivate;
+ friend class LegendMarkerItem;
+ friend class LegendLayout;
+ friend class LegendScroller;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QLEGENDMARKER_H
diff --git a/src/charts/legend/qlegendmarker_p.h b/src/charts/legend/qlegendmarker_p.h
new file mode 100644
index 00000000..09e46f09
--- /dev/null
+++ b/src/charts/legend/qlegendmarker_p.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QLEGENDMARKERPRIVATE_H
+#define QLEGENDMARKERPRIVATE_H
+
+#include "qchartglobal.h"
+#include <QGraphicsObject>
+#include <QBrush>
+#include <QPen>
+#include <QGraphicsLayoutItem>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QAbstractSeries;
+class QLegend;
+
+class QLegendMarker;
+class LegendMarkerItem;
+
+class QLegendMarkerPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QLegendMarkerPrivate(QLegendMarker *q, QLegend *legend);
+ virtual ~QLegendMarkerPrivate();
+
+ // Helper for now. (or declare LegendLayout as friend)
+ LegendMarkerItem* item() const { return m_item; }
+
+ virtual QAbstractSeries* series() = 0;
+ virtual QObject* relatedObject() = 0;
+
+ void invalidateLegend();
+
+public Q_SLOTS:
+ virtual void updated() = 0;
+
+protected:
+ LegendMarkerItem *m_item;
+ QLegend *m_legend;
+ bool m_customLabel;
+ bool m_customBrush;
+ bool m_customPen;
+
+private:
+ QLegendMarker *q_ptr;
+
+ friend class QLegendPrivate;
+ friend class LegendMarkerItem;
+ Q_DECLARE_PUBLIC(QLegendMarker)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QLEGENDMARKERPRIVATE_H
diff --git a/src/charts/legend/qpielegendmarker.cpp b/src/charts/legend/qpielegendmarker.cpp
new file mode 100644
index 00000000..e7bc7281
--- /dev/null
+++ b/src/charts/legend/qpielegendmarker.cpp
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpielegendmarker.h"
+#include "qpielegendmarker_p.h"
+#include <QPieSeries>
+#include <QPieSlice>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QPieLegendMarker
+ \inmodule Qt Charts
+ \brief QLegendMarker subclass for pie series.
+ \mainclass
+
+ QPieLegendMarker is related to QPieSeries. With QPieSeries, each slice of pie is related to one marker in QLegend.
+
+ \sa QLegend, QPieSeries, QPieSlice
+*/
+
+/*!
+ \fn virtual LegendMarkerType QPieLegendMarker::type()
+ Returns QLegendMarker::LegendMarkerTypePie
+*/
+
+/*!
+ \internal
+*/
+QPieLegendMarker::QPieLegendMarker(QPieSeries *series, QPieSlice *slice, QLegend *legend, QObject *parent) :
+ QLegendMarker(*new QPieLegendMarkerPrivate(this,series,slice,legend), parent)
+{
+ d_ptr->updated();
+}
+
+/*!
+ Destructor
+*/
+QPieLegendMarker::~QPieLegendMarker()
+{
+}
+
+/*!
+ \internal
+*/
+QPieLegendMarker::QPieLegendMarker(QPieLegendMarkerPrivate &d, QObject *parent) :
+ QLegendMarker(d, parent)
+{
+}
+
+/*!
+ Returns the related series of marker.
+*/
+QPieSeries* QPieLegendMarker::series()
+{
+ Q_D(QPieLegendMarker);
+ return d->m_series;
+}
+
+/*!
+ Returns the related slice of marker.
+*/
+QPieSlice* QPieLegendMarker::slice()
+{
+ Q_D(QPieLegendMarker);
+ return d->m_slice;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QPieLegendMarkerPrivate::QPieLegendMarkerPrivate(QPieLegendMarker *q, QPieSeries *series, QPieSlice *slice, QLegend *legend) :
+ QLegendMarkerPrivate(q,legend),
+ q_ptr(q),
+ m_series(series),
+ m_slice(slice)
+{
+ QObject::connect(m_slice, SIGNAL(labelChanged()), this, SLOT(updated()));
+ QObject::connect(m_slice, SIGNAL(brushChanged()), this, SLOT(updated()));
+ QObject::connect(m_slice, SIGNAL(penChanged()), this, SLOT(updated()));
+}
+
+QPieLegendMarkerPrivate::~QPieLegendMarkerPrivate()
+{
+}
+
+QPieSeries* QPieLegendMarkerPrivate::series()
+{
+ return m_series;
+}
+
+QObject* QPieLegendMarkerPrivate::relatedObject()
+{
+ return m_slice;
+}
+
+void QPieLegendMarkerPrivate::updated()
+{
+ bool labelChanged = false;
+ bool brushChanged = false;
+ bool penChanged = false;
+
+ if (!m_customPen && (m_item->pen() != m_slice->pen())) {
+ m_item->setPen(m_slice->pen());
+ penChanged = true;
+ }
+ if (!m_customBrush && (m_item->brush() != m_slice->brush())) {
+ m_item->setBrush(m_slice->brush());
+ brushChanged = true;
+ }
+ if (!m_customLabel && (m_item->label() != m_slice->label())) {
+ m_item->setLabel(m_slice->label());
+ labelChanged = true;
+ }
+ invalidateLegend();
+
+ if (labelChanged)
+ emit q_ptr->labelChanged();
+ if (brushChanged)
+ emit q_ptr->brushChanged();
+ if (penChanged)
+ emit q_ptr->penChanged();
+}
+
+#include "moc_qpielegendmarker.cpp"
+#include "moc_qpielegendmarker_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/legend/qpielegendmarker.h b/src/charts/legend/qpielegendmarker.h
new file mode 100644
index 00000000..c40fcf3a
--- /dev/null
+++ b/src/charts/legend/qpielegendmarker.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPIELEGENDMARKER_H
+#define QPIELEGENDMARKER_H
+
+#include <QtCharts/qchartglobal.h>
+#include <QtCharts/QLegendMarker>
+#include <QtCharts/QPieSeries>
+#include <QtCharts/QPieSlice>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QPieLegendMarkerPrivate;
+
+class QT_CHARTS_EXPORT QPieLegendMarker : public QLegendMarker
+{
+ Q_OBJECT
+
+public:
+ explicit QPieLegendMarker(QPieSeries *series, QPieSlice *slice, QLegend *legend, QObject *parent = 0);
+ virtual ~QPieLegendMarker();
+
+ virtual LegendMarkerType type() { return LegendMarkerTypePie; }
+
+ // Related series and slice
+ virtual QPieSeries* series();
+ QPieSlice* slice();
+
+protected:
+ QPieLegendMarker(QPieLegendMarkerPrivate &d, QObject *parent = 0);
+
+private:
+ Q_DECLARE_PRIVATE(QPieLegendMarker)
+ Q_DISABLE_COPY(QPieLegendMarker)
+
+};
+
+QT_CHARTS_END_NAMESPACE
+#endif // QPIELEGENDMARKER_H
diff --git a/src/charts/legend/qpielegendmarker_p.h b/src/charts/legend/qpielegendmarker_p.h
new file mode 100644
index 00000000..44faf50b
--- /dev/null
+++ b/src/charts/legend/qpielegendmarker_p.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QPIELEGENDMARKER_P_H
+#define QPIELEGENDMARKER_P_H
+
+#include "qchartglobal.h"
+#include "qlegendmarker_p.h"
+#include "legendmarkeritem_p.h"
+#include <QPieSeries>
+#include <QPieSlice>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QPieLegendMarker;
+
+class QPieLegendMarkerPrivate : public QLegendMarkerPrivate
+{
+ Q_OBJECT
+public:
+ explicit QPieLegendMarkerPrivate(QPieLegendMarker *q, QPieSeries *series, QPieSlice *slice, QLegend *legend);
+ virtual ~QPieLegendMarkerPrivate();
+
+ // internal
+ virtual QPieSeries* series();
+ virtual QObject* relatedObject();
+
+public Q_SLOTS:
+ virtual void updated();
+
+private:
+ QPieLegendMarker *q_ptr;
+
+ QPieSeries *m_series;
+ QPieSlice *m_slice;
+
+ Q_DECLARE_PUBLIC(QPieLegendMarker)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QPIELEGENDMARKER_P_H
diff --git a/src/charts/legend/qxylegendmarker.cpp b/src/charts/legend/qxylegendmarker.cpp
new file mode 100644
index 00000000..711e74c6
--- /dev/null
+++ b/src/charts/legend/qxylegendmarker.cpp
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qxylegendmarker.h"
+#include "qxylegendmarker_p.h"
+#include "qxyseries_p.h"
+#include <QXYSeries>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QXYLegendMarker
+ \inmodule Qt Charts
+ \brief QLegendMarker subclass for QXYSeries.
+ \mainclass
+
+ QXYLegendMarker is related to QXYSeries derived classes. Each marker is related to one series.
+
+ \sa QLegend, QXYSeries, QSplineSeries, QScatterSeries, QLineSeries
+*/
+
+/*!
+ \fn virtual LegendMarkerType QXYLegendMarker::type()
+ Returns QLegendMarker::LegendMarkerTypeXY
+*/
+
+/*!
+ \internal
+*/
+QXYLegendMarker::QXYLegendMarker(QXYSeries *series, QLegend *legend, QObject *parent) :
+ QLegendMarker(*new QXYLegendMarkerPrivate(this,series,legend), parent)
+{
+ d_ptr->updated();
+}
+
+/*!
+ Destructor
+*/
+QXYLegendMarker::~QXYLegendMarker()
+{
+}
+
+/*!
+ \internal
+*/
+QXYLegendMarker::QXYLegendMarker(QXYLegendMarkerPrivate &d, QObject *parent) :
+ QLegendMarker(d, parent)
+{
+}
+
+/*!
+ Returns the related series
+*/
+QXYSeries* QXYLegendMarker::series()
+{
+ Q_D(QXYLegendMarker);
+ return d->m_series;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QXYLegendMarkerPrivate::QXYLegendMarkerPrivate(QXYLegendMarker *q, QXYSeries *series, QLegend *legend) :
+ QLegendMarkerPrivate(q,legend),
+ q_ptr(q),
+ m_series(series)
+{
+ QObject::connect(m_series, SIGNAL(nameChanged()), this, SLOT(updated()));
+ QObject::connect(m_series->d_func(), SIGNAL(updated()), this, SLOT(updated()));
+}
+
+QXYLegendMarkerPrivate::~QXYLegendMarkerPrivate()
+{
+}
+
+QAbstractSeries* QXYLegendMarkerPrivate::series()
+{
+ return m_series;
+}
+
+QObject* QXYLegendMarkerPrivate::relatedObject()
+{
+ return m_series;
+}
+
+void QXYLegendMarkerPrivate::updated()
+{
+ bool labelChanged = false;
+ bool brushChanged = false;
+
+ if (!m_customLabel && (m_item->label() != m_series->name())) {
+ m_item->setLabel(m_series->name());
+ labelChanged = true;
+ }
+
+ if (m_series->type()== QAbstractSeries::SeriesTypeScatter) {
+ if (!m_customBrush && (m_item->brush() != m_series->brush())) {
+ m_item->setBrush(m_series->brush());
+ brushChanged = true;
+ }
+ } else {
+ QBrush emptyBrush;
+ if (!m_customBrush
+ && (m_item->brush() == emptyBrush
+ || m_item->brush().color() != m_series->pen().color())) {
+ m_item->setBrush(QBrush(m_series->pen().color()));
+ brushChanged = true;
+ }
+ }
+ invalidateLegend();
+
+ if (labelChanged)
+ emit q_ptr->labelChanged();
+ if (brushChanged)
+ emit q_ptr->brushChanged();
+}
+
+#include "moc_qxylegendmarker.cpp"
+#include "moc_qxylegendmarker_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
+
diff --git a/src/charts/legend/qxylegendmarker.h b/src/charts/legend/qxylegendmarker.h
new file mode 100644
index 00000000..24f0fa44
--- /dev/null
+++ b/src/charts/legend/qxylegendmarker.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QXYLEGENDMARKER_H
+#define QXYLEGENDMARKER_H
+
+#include <QtCharts/qchartglobal.h>
+#include <QtCharts/QLegendMarker>
+#include <QtCharts/QXYSeries>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QXYLegendMarkerPrivate;
+
+class QT_CHARTS_EXPORT QXYLegendMarker : public QLegendMarker
+{
+ Q_OBJECT
+public:
+ explicit QXYLegendMarker(QXYSeries *series, QLegend *legend, QObject *parent = 0);
+ virtual ~QXYLegendMarker();
+
+ virtual LegendMarkerType type() { return LegendMarkerTypeXY; }
+
+ // Related series
+ virtual QXYSeries* series();
+
+protected:
+ QXYLegendMarker(QXYLegendMarkerPrivate &d, QObject *parent = 0);
+
+private:
+ Q_DECLARE_PRIVATE(QXYLegendMarker)
+ Q_DISABLE_COPY(QXYLegendMarker)
+
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QXYLEGENDMARKER_H
diff --git a/src/charts/legend/qxylegendmarker_p.h b/src/charts/legend/qxylegendmarker_p.h
new file mode 100644
index 00000000..196d942f
--- /dev/null
+++ b/src/charts/legend/qxylegendmarker_p.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QXYLEGENDMARKER_P_H
+#define QXYLEGENDMARKER_P_H
+
+#include "qchartglobal.h"
+#include "qlegendmarker_p.h"
+#include "legendmarkeritem_p.h"
+#include <QXYSeries>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QXYLegendMarker;
+
+class QXYLegendMarkerPrivate : public QLegendMarkerPrivate
+{
+ Q_OBJECT
+public:
+ explicit QXYLegendMarkerPrivate(QXYLegendMarker *q, QXYSeries *series, QLegend *legend);
+ virtual ~QXYLegendMarkerPrivate();
+
+ virtual QAbstractSeries* series();
+ virtual QObject* relatedObject();
+
+public Q_SLOTS:
+ virtual void updated();
+
+private:
+ QXYLegendMarker *q_ptr;
+ QXYSeries *m_series;
+
+ Q_DECLARE_PUBLIC(QXYLegendMarker)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QXYLEGENDMARKER_P_H
diff --git a/src/charts/linechart/linechart.pri b/src/charts/linechart/linechart.pri
new file mode 100644
index 00000000..573b23d2
--- /dev/null
+++ b/src/charts/linechart/linechart.pri
@@ -0,0 +1,13 @@
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+
+SOURCES += \
+ $$PWD/linechartitem.cpp \
+ $$PWD/qlineseries.cpp
+
+PRIVATE_HEADERS += \
+ $$PWD/linechartitem_p.h \
+ $$PWD/qlineseries_p.h
+
+PUBLIC_HEADERS += \
+ $$PWD/qlineseries.h \ No newline at end of file
diff --git a/src/charts/linechart/linechartitem.cpp b/src/charts/linechart/linechartitem.cpp
new file mode 100644
index 00000000..1a87342e
--- /dev/null
+++ b/src/charts/linechart/linechartitem.cpp
@@ -0,0 +1,405 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "linechartitem_p.h"
+#include "qlineseries.h"
+#include "qlineseries_p.h"
+#include "chartpresenter_p.h"
+#include "polardomain_p.h"
+#include "chartthememanager_p.h"
+#include "charttheme_p.h"
+#include <QPainter>
+#include <QGraphicsSceneMouseEvent>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+const qreal mouseEventMinWidth(12);
+
+LineChartItem::LineChartItem(QLineSeries *series, QGraphicsItem *item)
+ : XYChart(series,item),
+ m_series(series),
+ m_pointsVisible(false),
+ m_chartType(QChart::ChartTypeUndefined),
+ m_pointLabelsVisible(false),
+ m_pointLabelsFormat(series->pointLabelsFormat()),
+ m_pointLabelsFont(series->pointLabelsFont()),
+ m_pointLabelsColor(series->pointLabelsColor())
+{
+ setAcceptHoverEvents(true);
+ setZValue(ChartPresenter::LineChartZValue);
+ QObject::connect(series->d_func(), SIGNAL(updated()), this, SLOT(handleUpdated()));
+ QObject::connect(series, SIGNAL(visibleChanged()), this, SLOT(handleUpdated()));
+ QObject::connect(series, SIGNAL(opacityChanged()), this, SLOT(handleUpdated()));
+ QObject::connect(series, SIGNAL(pointLabelsFormatChanged(QString)),
+ this, SLOT(handleUpdated()));
+ QObject::connect(series, SIGNAL(pointLabelsVisibilityChanged(bool)),
+ this, SLOT(handleUpdated()));
+ QObject::connect(series, SIGNAL(pointLabelsFontChanged(QFont)), this, SLOT(handleUpdated()));
+ QObject::connect(series, SIGNAL(pointLabelsColorChanged(QColor)), this, SLOT(handleUpdated()));
+ handleUpdated();
+}
+
+QRectF LineChartItem::boundingRect() const
+{
+ return m_rect;
+}
+
+QPainterPath LineChartItem::shape() const
+{
+ return m_shapePath;
+}
+
+void LineChartItem::updateGeometry()
+{
+ m_points = geometryPoints();
+ const QVector<QPointF> &points = m_points;
+
+ if (points.size() == 0) {
+ prepareGeometryChange();
+ m_fullPath = QPainterPath();
+ m_linePath = QPainterPath();
+ m_rect = QRect();
+ return;
+ }
+
+ QPainterPath linePath;
+ QPainterPath fullPath;
+ // Use worst case scenario to determine required margin.
+ qreal margin = m_linePen.width() * 1.42;
+
+ // Area series use component line series that aren't necessarily added to the chart themselves,
+ // so check if chart type is forced before trying to obtain it from the chart.
+ QChart::ChartType chartType = m_chartType;
+ if (chartType == QChart::ChartTypeUndefined)
+ chartType = m_series->chart()->chartType();
+
+ // For polar charts, we need special handling for angular (horizontal)
+ // points that are off-grid.
+ if (chartType == QChart::ChartTypePolar) {
+ QPainterPath linePathLeft;
+ QPainterPath linePathRight;
+ QPainterPath *currentSegmentPath = 0;
+ QPainterPath *previousSegmentPath = 0;
+ qreal minX = domain()->minX();
+ qreal maxX = domain()->maxX();
+ qreal minY = domain()->minY();
+ QPointF currentSeriesPoint = m_series->at(0);
+ QPointF currentGeometryPoint = points.at(0);
+ QPointF previousGeometryPoint = points.at(0);
+ int size = m_linePen.width();
+ bool pointOffGrid = false;
+ bool previousPointWasOffGrid = (currentSeriesPoint.x() < minX || currentSeriesPoint.x() > maxX);
+
+ qreal domainRadius = domain()->size().height() / 2.0;
+ const QPointF centerPoint(domainRadius, domainRadius);
+
+ if (!previousPointWasOffGrid) {
+ fullPath.moveTo(points.at(0));
+ if (m_pointsVisible && currentSeriesPoint.y() >= minY) {
+ // Do not draw ellipses for points below minimum Y.
+ linePath.addEllipse(points.at(0), size, size);
+ fullPath.addEllipse(points.at(0), size, size);
+ linePath.moveTo(points.at(0));
+ fullPath.moveTo(points.at(0));
+ }
+ }
+
+ qreal leftMarginLine = centerPoint.x() - margin;
+ qreal rightMarginLine = centerPoint.x() + margin;
+ qreal horizontal = centerPoint.y();
+
+ // See ScatterChartItem::updateGeometry() for explanation why seriesLastIndex is needed
+ const int seriesLastIndex = m_series->count() - 1;
+
+ for (int i = 1; i < points.size(); i++) {
+ // Interpolating line fragments would be ugly when thick pen is used,
+ // so we work around it by utilizing three separate
+ // paths for line segments and clip those with custom regions at paint time.
+ // "Right" path contains segments that cross the axis line with visible point on the
+ // right side of the axis line, as well as segments that have one point within the margin
+ // on the right side of the axis line and another point on the right side of the chart.
+ // "Left" path contains points with similarly on the left side.
+ // "Full" path contains rest of the points.
+ // This doesn't yield perfect results always. E.g. when segment covers more than 90
+ // degrees and both of the points are within the margin, one in the top half and one in the
+ // bottom half of the chart, the bottom one gets clipped incorrectly.
+ // However, this should be rare occurrence in any sensible chart.
+ currentSeriesPoint = m_series->at(qMin(seriesLastIndex, i));
+ currentGeometryPoint = points.at(i);
+ pointOffGrid = (currentSeriesPoint.x() < minX || currentSeriesPoint.x() > maxX);
+
+ // Draw something unless both off-grid
+ if (!pointOffGrid || !previousPointWasOffGrid) {
+ QPointF intersectionPoint;
+ qreal y;
+ if (pointOffGrid != previousPointWasOffGrid) {
+ if (currentGeometryPoint.x() == previousGeometryPoint.x()) {
+ y = currentGeometryPoint.y() + (currentGeometryPoint.y() - previousGeometryPoint.y()) / 2.0;
+ } else {
+ qreal ratio = (centerPoint.x() - currentGeometryPoint.x()) / (currentGeometryPoint.x() - previousGeometryPoint.x());
+ y = currentGeometryPoint.y() + (currentGeometryPoint.y() - previousGeometryPoint.y()) * ratio;
+ }
+ intersectionPoint = QPointF(centerPoint.x(), y);
+ }
+
+ bool dummyOk; // We know points are ok, but this is needed
+ qreal currentAngle = static_cast<PolarDomain *>(domain())->toAngularCoordinate(currentSeriesPoint.x(), dummyOk);
+ qreal previousAngle = static_cast<PolarDomain *>(domain())->toAngularCoordinate(m_series->at(i - 1).x(), dummyOk);
+
+ if ((qAbs(currentAngle - previousAngle) > 180.0)) {
+ // If the angle between two points is over 180 degrees (half X range),
+ // any direct segment between them becomes meaningless.
+ // In this case two line segments are drawn instead, from previous
+ // point to the center and from center to current point.
+ if ((previousAngle < 0.0 || (previousAngle <= 180.0 && previousGeometryPoint.x() < rightMarginLine))
+ && previousGeometryPoint.y() < horizontal) {
+ currentSegmentPath = &linePathRight;
+ } else if ((previousAngle > 360.0 || (previousAngle > 180.0 && previousGeometryPoint.x() > leftMarginLine))
+ && previousGeometryPoint.y() < horizontal) {
+ currentSegmentPath = &linePathLeft;
+ } else if (previousAngle > 0.0 && previousAngle < 360.0) {
+ currentSegmentPath = &linePath;
+ } else {
+ currentSegmentPath = 0;
+ }
+
+ if (currentSegmentPath) {
+ if (previousSegmentPath != currentSegmentPath)
+ currentSegmentPath->moveTo(previousGeometryPoint);
+ if (previousPointWasOffGrid)
+ fullPath.moveTo(intersectionPoint);
+
+ currentSegmentPath->lineTo(centerPoint);
+ fullPath.lineTo(centerPoint);
+ }
+
+ previousSegmentPath = currentSegmentPath;
+
+ if ((currentAngle < 0.0 || (currentAngle <= 180.0 && currentGeometryPoint.x() < rightMarginLine))
+ && currentGeometryPoint.y() < horizontal) {
+ currentSegmentPath = &linePathRight;
+ } else if ((currentAngle > 360.0 || (currentAngle > 180.0 &&currentGeometryPoint.x() > leftMarginLine))
+ && currentGeometryPoint.y() < horizontal) {
+ currentSegmentPath = &linePathLeft;
+ } else if (currentAngle > 0.0 && currentAngle < 360.0) {
+ currentSegmentPath = &linePath;
+ } else {
+ currentSegmentPath = 0;
+ }
+
+ if (currentSegmentPath) {
+ if (previousSegmentPath != currentSegmentPath)
+ currentSegmentPath->moveTo(centerPoint);
+ if (!previousSegmentPath)
+ fullPath.moveTo(centerPoint);
+
+ currentSegmentPath->lineTo(currentGeometryPoint);
+ if (pointOffGrid)
+ fullPath.lineTo(intersectionPoint);
+ else
+ fullPath.lineTo(currentGeometryPoint);
+ }
+ } else {
+ if (previousAngle < 0.0 || currentAngle < 0.0
+ || ((previousAngle <= 180.0 && currentAngle <= 180.0)
+ && ((previousGeometryPoint.x() < rightMarginLine && previousGeometryPoint.y() < horizontal)
+ || (currentGeometryPoint.x() < rightMarginLine && currentGeometryPoint.y() < horizontal)))) {
+ currentSegmentPath = &linePathRight;
+ } else if (previousAngle > 360.0 || currentAngle > 360.0
+ || ((previousAngle > 180.0 && currentAngle > 180.0)
+ && ((previousGeometryPoint.x() > leftMarginLine && previousGeometryPoint.y() < horizontal)
+ || (currentGeometryPoint.x() > leftMarginLine && currentGeometryPoint.y() < horizontal)))) {
+ currentSegmentPath = &linePathLeft;
+ } else {
+ currentSegmentPath = &linePath;
+ }
+
+ if (currentSegmentPath != previousSegmentPath)
+ currentSegmentPath->moveTo(previousGeometryPoint);
+ if (previousPointWasOffGrid)
+ fullPath.moveTo(intersectionPoint);
+
+ if (pointOffGrid)
+ fullPath.lineTo(intersectionPoint);
+ else
+ fullPath.lineTo(currentGeometryPoint);
+ currentSegmentPath->lineTo(currentGeometryPoint);
+ }
+ } else {
+ currentSegmentPath = 0;
+ }
+
+ previousPointWasOffGrid = pointOffGrid;
+ if (m_pointsVisible && !pointOffGrid && currentSeriesPoint.y() >= minY) {
+ linePath.addEllipse(points.at(i), size, size);
+ fullPath.addEllipse(points.at(i), size, size);
+ linePath.moveTo(points.at(i));
+ fullPath.moveTo(points.at(i));
+ }
+ previousSegmentPath = currentSegmentPath;
+ previousGeometryPoint = currentGeometryPoint;
+ }
+ m_linePathPolarRight = linePathRight;
+ m_linePathPolarLeft = linePathLeft;
+ // Note: This construction of m_fullpath is not perfect. The partial segments that are
+ // outside left/right clip regions at axis boundary still generate hover/click events,
+ // because shape doesn't get clipped. It doesn't seem possible to do sensibly.
+ } else { // not polar
+ linePath.moveTo(points.at(0));
+ if (m_pointsVisible) {
+ int size = m_linePen.width();
+ linePath.addEllipse(points.at(0), size, size);
+ linePath.moveTo(points.at(0));
+ for (int i = 1; i < points.size(); i++) {
+ linePath.lineTo(points.at(i));
+ linePath.addEllipse(points.at(i), size, size);
+ linePath.moveTo(points.at(i));
+ }
+ } else {
+ for (int i = 1; i < points.size(); i++)
+ linePath.lineTo(points.at(i));
+ }
+ fullPath = linePath;
+ }
+
+ QPainterPathStroker stroker;
+ // QPainter::drawLine does not respect join styles, for example BevelJoin becomes MiterJoin.
+ // This is why we are prepared for the "worst case" scenario, i.e. use always MiterJoin and
+ // multiply line width with square root of two when defining shape and bounding rectangle.
+ stroker.setWidth(margin);
+ stroker.setJoinStyle(Qt::MiterJoin);
+ stroker.setCapStyle(Qt::SquareCap);
+ stroker.setMiterLimit(m_linePen.miterLimit());
+
+ QPainterPath checkShapePath = stroker.createStroke(fullPath);
+
+ // Only zoom in if the bounding rects of the paths fit inside int limits. QWidget::update() uses
+ // a region that has to be compatible with QRect.
+ if (checkShapePath.boundingRect().height() <= INT_MAX
+ && checkShapePath.boundingRect().width() <= INT_MAX
+ && linePath.boundingRect().height() <= INT_MAX
+ && linePath.boundingRect().width() <= INT_MAX
+ && fullPath.boundingRect().height() <= INT_MAX
+ && fullPath.boundingRect().width() <= INT_MAX) {
+ prepareGeometryChange();
+
+ m_linePath = linePath;
+ m_fullPath = fullPath;
+ m_shapePath = checkShapePath;
+
+ m_rect = m_shapePath.boundingRect();
+ } else {
+ update();
+ }
+}
+
+void LineChartItem::handleUpdated()
+{
+ // If points visibility has changed, a geometry update is needed.
+ // Also, if pen changes when points are visible, geometry update is needed.
+ bool doGeometryUpdate =
+ (m_pointsVisible != m_series->pointsVisible())
+ || (m_series->pointsVisible() && (m_linePen != m_series->pen()));
+ setVisible(m_series->isVisible());
+ setOpacity(m_series->opacity());
+ m_pointsVisible = m_series->pointsVisible();
+ m_linePen = m_series->pen();
+ m_pointLabelsFormat = m_series->pointLabelsFormat();
+ m_pointLabelsVisible = m_series->pointLabelsVisible();
+ m_pointLabelsFont = m_series->pointLabelsFont();
+ m_pointLabelsColor = m_series->pointLabelsColor();
+ if (doGeometryUpdate)
+ updateGeometry();
+ update();
+}
+
+void LineChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(widget)
+ Q_UNUSED(option)
+
+ QRectF clipRect = QRectF(QPointF(0, 0), domain()->size());
+
+ painter->save();
+ painter->setPen(m_linePen);
+ bool alwaysUsePath = false;
+
+ if (m_series->chart()->chartType() == QChart::ChartTypePolar) {
+ qreal halfWidth = domain()->size().width() / 2.0;
+ QRectF clipRectLeft = QRectF(0, 0, halfWidth, domain()->size().height());
+ QRectF clipRectRight = QRectF(halfWidth, 0, halfWidth, domain()->size().height());
+ QRegion fullPolarClipRegion(clipRect.toRect(), QRegion::Ellipse);
+ QRegion clipRegionLeft(fullPolarClipRegion.intersected(clipRectLeft.toRect()));
+ QRegion clipRegionRight(fullPolarClipRegion.intersected(clipRectRight.toRect()));
+ painter->setClipRegion(clipRegionLeft);
+ painter->drawPath(m_linePathPolarLeft);
+ painter->setClipRegion(clipRegionRight);
+ painter->drawPath(m_linePathPolarRight);
+ painter->setClipRegion(fullPolarClipRegion);
+ alwaysUsePath = true; // required for proper clipping
+ } else {
+ painter->setClipRect(clipRect);
+ }
+
+ if (m_pointsVisible) {
+ painter->setBrush(m_linePen.color());
+ painter->drawPath(m_linePath);
+ } else {
+ painter->setBrush(QBrush(Qt::NoBrush));
+ if (m_linePen.style() != Qt::SolidLine || alwaysUsePath) {
+ // If pen style is not solid line, always fall back to path painting
+ // to ensure proper continuity of the pattern
+ painter->drawPath(m_linePath);
+ } else {
+ for (int i(1); i < m_points.size(); i++)
+ painter->drawLine(m_points.at(i - 1), m_points.at(i));
+ }
+ }
+
+ if (m_pointLabelsVisible)
+ m_series->d_func()->drawSeriesPointLabels(painter, m_points, m_linePen.width() / 2);
+
+ painter->restore();
+
+}
+
+void LineChartItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ emit XYChart::clicked(domain()->calculateDomainPoint(event->pos()));
+ QGraphicsItem::mousePressEvent(event);
+}
+
+void LineChartItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
+{
+ emit XYChart::hovered(domain()->calculateDomainPoint(event->pos()), true);
+// event->accept();
+ QGraphicsItem::hoverEnterEvent(event);
+}
+
+void LineChartItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
+{
+ emit XYChart::hovered(domain()->calculateDomainPoint(event->pos()), false);
+// event->accept();
+ QGraphicsItem::hoverEnterEvent(event);
+}
+
+#include "moc_linechartitem_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/linechart/linechartitem_p.h b/src/charts/linechart/linechartitem_p.h
new file mode 100644
index 00000000..08b304f2
--- /dev/null
+++ b/src/charts/linechart/linechartitem_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 LINECHARTITEM_H
+#define LINECHARTITEM_H
+
+#include "qchartglobal.h"
+#include "xychart_p.h"
+#include "qchart.h"
+#include <QPen>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QLineSeries;
+class ChartPresenter;
+
+class LineChartItem : public XYChart
+{
+ Q_OBJECT
+ Q_INTERFACES(QGraphicsItem)
+public:
+ explicit LineChartItem(QLineSeries *series, QGraphicsItem *item = 0);
+ ~LineChartItem() {}
+
+ //from QGraphicsItem
+ QRectF boundingRect() const;
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+ QPainterPath shape() const;
+
+ QPainterPath path() const { return m_fullPath; }
+
+public Q_SLOTS:
+ void handleUpdated();
+
+protected:
+ void updateGeometry();
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
+ void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
+ void suppressPoints() { m_pointsVisible = false; }
+ void forceChartType(QChart::ChartType chartType) { m_chartType = chartType; }
+
+private:
+ QLineSeries *m_series;
+ QPainterPath m_linePath;
+ QPainterPath m_linePathPolarRight;
+ QPainterPath m_linePathPolarLeft;
+ QPainterPath m_fullPath;
+ QPainterPath m_shapePath;
+
+ QVector<QPointF> m_points;
+ QRectF m_rect;
+ QPen m_linePen;
+ bool m_pointsVisible;
+ QChart::ChartType m_chartType;
+
+ bool m_pointLabelsVisible;
+ QString m_pointLabelsFormat;
+ QFont m_pointLabelsFont;
+ QColor m_pointLabelsColor;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/linechart/qlineseries.cpp b/src/charts/linechart/qlineseries.cpp
new file mode 100644
index 00000000..b4171b9c
--- /dev/null
+++ b/src/charts/linechart/qlineseries.cpp
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlineseries.h"
+#include "qlineseries_p.h"
+#include "linechartitem_p.h"
+#include "chartdataset_p.h"
+#include "charttheme_p.h"
+#include "qchart_p.h"
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QLineSeries
+ \inmodule Qt Charts
+ \brief The QLineSeries class is used for making line charts.
+
+ \mainclass
+
+ A line chart is used to show information as a series of data points
+ connected by straight lines.
+
+ \image examples_linechart.png
+
+ Creating basic line chart is simple:
+ \code
+ QLineSeries* series = new QLineSeries();
+ series->append(0, 6);
+ series->append(2, 4);
+ ...
+ chart->addSeries(series);
+ \endcode
+*/
+/*!
+ \qmltype LineSeries
+ \instantiates QLineSeries
+ \inqmlmodule QtCharts
+
+ \inherits XYSeries
+
+ \brief The LineSeries type is used for making line charts.
+
+ The following QML shows how to create a simple line chart:
+ \snippet qmlchart/qml/qmlchart/View2.qml 1
+ \beginfloatleft
+ \image examples_qmlchart2.png
+ \endfloat
+ \clearfloat
+*/
+
+/*!
+ \fn virtual SeriesType QLineSeries::type() const
+ \brief Returns type of series.
+ \sa QAbstractSeries, SeriesType
+*/
+
+/*!
+ \qmlproperty real LineSeries::width
+ The width of the line. By default the width is 2.0.
+*/
+
+/*!
+ \qmlproperty Qt::PenStyle LineSeries::style
+ Controls the style of the line. Set to one of Qt.NoPen, Qt.SolidLine, Qt.DashLine, Qt.DotLine,
+ Qt.DashDotLine or Qt.DashDotDotLine. Using Qt.CustomDashLine is not supported in the QML API.
+ By default the style is Qt.SolidLine.
+*/
+
+/*!
+ \qmlproperty Qt::PenCapStyle LineSeries::capStyle
+ Controls the cap style of the line. Set to one of Qt.FlatCap, Qt.SquareCap or Qt.RoundCap. By
+ default the cap style is Qt.SquareCap.
+*/
+
+/*!
+ Constructs empty series object which is a child of \a parent.
+ When series object is added to QChartView or QChart instance ownerships is transferred.
+*/
+QLineSeries::QLineSeries(QObject *parent)
+ : QXYSeries(*new QLineSeriesPrivate(this), parent)
+{
+
+}
+
+/*!
+ \internal
+*/
+QLineSeries::QLineSeries(QLineSeriesPrivate &d, QObject *parent)
+ : QXYSeries(d, parent)
+{
+
+}
+/*!
+ Destroys the object. Series added to QChartView or QChart instances are owned by those,
+ and are deleted when mentioned object are destroyed.
+*/
+QLineSeries::~QLineSeries()
+{
+ Q_D(QLineSeries);
+ if (d->m_chart)
+ d->m_chart->removeSeries(this);
+}
+
+QAbstractSeries::SeriesType QLineSeries::type() const
+{
+ return QAbstractSeries::SeriesTypeLine;
+}
+
+/*
+QDebug operator<< (QDebug debug, const QLineSeries series)
+{
+ Q_ASSERT(series.d_func()->m_x.size() == series.d_func()->m_y.size());
+ int size = series.d_func()->m_x.size();
+ for (int i=0; i<size; i++) {
+ debug.nospace() << "(" << series.d_func()->m_x.at(i) << ','<< series.d_func()->m_y.at(i) << ") ";
+ }
+ return debug.space();
+}
+*/
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QLineSeriesPrivate::QLineSeriesPrivate(QLineSeries *q)
+ : QXYSeriesPrivate(q)
+{
+
+};
+
+void QLineSeriesPrivate::initializeGraphics(QGraphicsItem *parent)
+{
+ Q_Q(QLineSeries);
+ LineChartItem *line = new LineChartItem(q,parent);
+ m_item.reset(line);
+ QAbstractSeriesPrivate::initializeGraphics(parent);
+}
+
+void QLineSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
+{
+ Q_Q(QLineSeries);
+ const QList<QColor> colors = theme->seriesColors();
+
+ if (forced || QChartPrivate::defaultPen() == m_pen) {
+ QPen pen;
+ pen.setColor(colors.at(index % colors.size()));
+ pen.setWidthF(2);
+ q->setPen(pen);
+ }
+
+ if (forced || QChartPrivate::defaultPen().color() == m_pointLabelsColor) {
+ QColor color = theme->labelBrush().color();
+ q->setPointLabelsColor(color);
+ }
+}
+
+#include "moc_qlineseries.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/linechart/qlineseries.h b/src/charts/linechart/qlineseries.h
new file mode 100644
index 00000000..02303c11
--- /dev/null
+++ b/src/charts/linechart/qlineseries.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLINESERIES_H
+#define QLINESERIES_H
+
+#include <QtCharts/qchartglobal.h>
+#include <QtCharts/qxyseries.h>
+#include <QPen>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QLineSeriesPrivate;
+
+class QT_CHARTS_EXPORT QLineSeries : public QXYSeries
+{
+ Q_OBJECT
+
+public:
+ explicit QLineSeries(QObject *parent = 0);
+ ~QLineSeries();
+ QAbstractSeries::SeriesType type() const;
+
+protected:
+ QLineSeries(QLineSeriesPrivate &d, QObject *parent = 0);
+
+private:
+ Q_DECLARE_PRIVATE(QLineSeries)
+ Q_DISABLE_COPY(QLineSeries)
+ friend class LineChartItem;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QLINESERIES_H
diff --git a/src/charts/linechart/qlineseries_p.h b/src/charts/linechart/qlineseries_p.h
new file mode 100644
index 00000000..4fc9b904
--- /dev/null
+++ b/src/charts/linechart/qlineseries_p.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QLINESERIES_P_H
+#define QLINESERIES_P_H
+
+#include "qxyseries_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+
+class QLineSeriesPrivate: public QXYSeriesPrivate
+{
+public:
+ QLineSeriesPrivate(QLineSeries *q);
+ void initializeGraphics(QGraphicsItem* parent);
+ void initializeTheme(int index, ChartTheme* theme, bool forced = false);
+
+private:
+ Q_DECLARE_PUBLIC(QLineSeries);
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/piechart/piechart.pri b/src/charts/piechart/piechart.pri
new file mode 100644
index 00000000..2c45c4e6
--- /dev/null
+++ b/src/charts/piechart/piechart.pri
@@ -0,0 +1,26 @@
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+
+SOURCES += \
+ $$PWD/qpieseries.cpp \
+ $$PWD/piesliceitem.cpp \
+ $$PWD/piechartitem.cpp \
+ $$PWD/qpieslice.cpp \
+ $$PWD/qpiemodelmapper.cpp \
+ $$PWD/qvpiemodelmapper.cpp \
+ $$PWD/qhpiemodelmapper.cpp
+
+PRIVATE_HEADERS += \
+ $$PWD/pieslicedata_p.h \
+ $$PWD/piechartitem_p.h \
+ $$PWD/piesliceitem_p.h \
+ $$PWD/qpieslice_p.h \
+ $$PWD/qpieseries_p.h \
+ $$PWD/qpiemodelmapper_p.h
+
+PUBLIC_HEADERS += \
+ $$PWD/qpieseries.h \
+ $$PWD/qpieslice.h \
+ $$PWD/qpiemodelmapper.h \
+ $$PWD/qvpiemodelmapper.h \
+ $$PWD/qhpiemodelmapper.h
diff --git a/src/charts/piechart/piechartitem.cpp b/src/charts/piechart/piechartitem.cpp
new file mode 100644
index 00000000..dbf7edf8
--- /dev/null
+++ b/src/charts/piechart/piechartitem.cpp
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "piechartitem_p.h"
+#include "piesliceitem_p.h"
+#include "qpieslice.h"
+#include "qpieslice_p.h"
+#include "qpieseries.h"
+#include "qpieseries_p.h"
+#include "chartpresenter_p.h"
+#include "chartdataset_p.h"
+#include "pieanimation_p.h"
+#include <QPainter>
+#include <QTimer>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+PieChartItem::PieChartItem(QPieSeries *series, QGraphicsItem* item)
+ : ChartItem(series->d_func(),item),
+ m_series(series),
+ m_animation(0)
+{
+ Q_ASSERT(series);
+
+ QPieSeriesPrivate *p = QPieSeriesPrivate::fromSeries(series);
+ connect(series, SIGNAL(visibleChanged()), this, SLOT(handleSeriesVisibleChanged()));
+ connect(series, SIGNAL(opacityChanged()), this, SLOT(handleOpacityChanged()));
+ connect(series, SIGNAL(added(QList<QPieSlice*>)), this, SLOT(handleSlicesAdded(QList<QPieSlice*>)));
+ connect(series, SIGNAL(removed(QList<QPieSlice*>)), this, SLOT(handleSlicesRemoved(QList<QPieSlice*>)));
+ connect(p, SIGNAL(horizontalPositionChanged()), this, SLOT(updateLayout()));
+ connect(p, SIGNAL(verticalPositionChanged()), this, SLOT(updateLayout()));
+ connect(p, SIGNAL(pieSizeChanged()), this, SLOT(updateLayout()));
+ connect(p, SIGNAL(calculatedDataChanged()), this, SLOT(updateLayout()));
+
+ // Note: the following does not affect as long as the item does not have anything to paint
+ setZValue(ChartPresenter::PieSeriesZValue);
+
+ // Note: will not create slice items until we have a proper rectangle to draw on.
+}
+
+PieChartItem::~PieChartItem()
+{
+ // slices deleted automatically through QGraphicsItem
+ if (m_series) {
+ m_series->disconnect(this);
+ QPieSeriesPrivate::fromSeries(m_series)->disconnect(this);
+ }
+ foreach (QPieSlice *slice, m_sliceItems.keys()) {
+ slice->disconnect(this);
+ QPieSlicePrivate::fromSlice(slice)->disconnect(this);
+ }
+}
+
+void PieChartItem::setAnimation(PieAnimation *animation)
+{
+ m_animation = animation;
+}
+
+ChartAnimation *PieChartItem::animation() const
+{
+ return m_animation;
+}
+
+void PieChartItem::handleDomainUpdated()
+{
+ QRectF rect(QPointF(0,0),domain()->size());
+ if(m_rect!=rect){
+ prepareGeometryChange();
+ m_rect = rect;
+ updateLayout();
+
+ if (m_sliceItems.isEmpty())
+ handleSlicesAdded(m_series->slices());
+ }
+}
+
+void PieChartItem::updateLayout()
+{
+ // find pie center coordinates
+ m_pieCenter.setX(m_rect.left() + (m_rect.width() * m_series->horizontalPosition()));
+ m_pieCenter.setY(m_rect.top() + (m_rect.height() * m_series->verticalPosition()));
+
+ // find maximum radius for pie
+ m_pieRadius = m_rect.height() / 2;
+ if (m_rect.width() < m_rect.height())
+ m_pieRadius = m_rect.width() / 2;
+
+ m_holeSize = m_pieRadius;
+ // apply size factor
+ m_pieRadius *= m_series->pieSize();
+ m_holeSize *= m_series->holeSize();
+
+ // set layouts for existing slice items
+ foreach (QPieSlice *slice, m_series->slices()) {
+ PieSliceItem *sliceItem = m_sliceItems.value(slice);
+ if (sliceItem) {
+ PieSliceData sliceData = updateSliceGeometry(slice);
+ if (m_animation)
+ presenter()->startAnimation(m_animation->updateValue(sliceItem, sliceData));
+ else
+ sliceItem->setLayout(sliceData);
+ }
+ }
+
+ update();
+}
+
+void PieChartItem::handleSlicesAdded(QList<QPieSlice *> slices)
+{
+ // delay creating slice items until there is a proper rectangle
+ if (!m_rect.isValid() && m_sliceItems.isEmpty())
+ return;
+
+ themeManager()->updateSeries(m_series);
+
+ bool startupAnimation = m_sliceItems.isEmpty();
+
+ foreach(QPieSlice * slice, slices) {
+ PieSliceItem *sliceItem = new PieSliceItem(this);
+ m_sliceItems.insert(slice, sliceItem);
+
+ // Note: no need to connect to slice valueChanged() etc.
+ // This is handled through calculatedDataChanged signal.
+ connect(slice, SIGNAL(labelChanged()), this, SLOT(handleSliceChanged()));
+ connect(slice, SIGNAL(labelVisibleChanged()), this, SLOT(handleSliceChanged()));
+ connect(slice, SIGNAL(penChanged()), this, SLOT(handleSliceChanged()));
+ connect(slice, SIGNAL(brushChanged()), this, SLOT(handleSliceChanged()));
+ connect(slice, SIGNAL(labelBrushChanged()), this, SLOT(handleSliceChanged()));
+ connect(slice, SIGNAL(labelFontChanged()), this, SLOT(handleSliceChanged()));
+
+ QPieSlicePrivate *p = QPieSlicePrivate::fromSlice(slice);
+ connect(p, SIGNAL(labelPositionChanged()), this, SLOT(handleSliceChanged()));
+ connect(p, SIGNAL(explodedChanged()), this, SLOT(handleSliceChanged()));
+ connect(p, SIGNAL(labelArmLengthFactorChanged()), this, SLOT(handleSliceChanged()));
+ connect(p, SIGNAL(explodeDistanceFactorChanged()), this, SLOT(handleSliceChanged()));
+
+ connect(sliceItem, SIGNAL(clicked(Qt::MouseButtons)), slice, SIGNAL(clicked()));
+ connect(sliceItem, SIGNAL(hovered(bool)), slice, SIGNAL(hovered(bool)));
+
+ PieSliceData sliceData = updateSliceGeometry(slice);
+ if (m_animation)
+ presenter()->startAnimation(m_animation->addSlice(sliceItem, sliceData, startupAnimation));
+ else
+ sliceItem->setLayout(sliceData);
+ }
+}
+
+void PieChartItem::handleSlicesRemoved(QList<QPieSlice *> slices)
+{
+ themeManager()->updateSeries(m_series);
+
+ foreach (QPieSlice *slice, slices) {
+
+ PieSliceItem *sliceItem = m_sliceItems.value(slice);
+
+ // this can happen if you call append() & remove() in a row so that PieSliceItem is not even created
+ if (!sliceItem)
+ continue;
+
+ m_sliceItems.remove(slice);
+ slice->disconnect(this);
+ QPieSlicePrivate::fromSlice(slice)->disconnect(this);
+
+ if (m_animation)
+ presenter()->startAnimation(m_animation->removeSlice(sliceItem)); // animator deletes the PieSliceItem
+ else
+ delete sliceItem;
+ }
+}
+
+void PieChartItem::handleSliceChanged()
+{
+ QPieSlice *slice = qobject_cast<QPieSlice *>(sender());
+ if (!slice) {
+ QPieSlicePrivate *slicep = qobject_cast<QPieSlicePrivate *>(sender());
+ slice = slicep->q_ptr;
+ }
+ Q_ASSERT(m_sliceItems.contains(slice));
+
+ PieSliceItem *sliceItem = m_sliceItems.value(slice);
+ PieSliceData sliceData = updateSliceGeometry(slice);
+ if (m_animation)
+ presenter()->startAnimation(m_animation->updateValue(sliceItem, sliceData));
+ else
+ sliceItem->setLayout(sliceData);
+
+ update();
+}
+
+void PieChartItem::handleSeriesVisibleChanged()
+{
+ setVisible(m_series->isVisible());
+}
+
+void PieChartItem::handleOpacityChanged()
+{
+ setOpacity(m_series->opacity());
+}
+
+PieSliceData PieChartItem::updateSliceGeometry(QPieSlice *slice)
+{
+ PieSliceData &sliceData = QPieSlicePrivate::fromSlice(slice)->m_data;
+ sliceData.m_center = PieSliceItem::sliceCenter(m_pieCenter, m_pieRadius, slice);
+ sliceData.m_radius = m_pieRadius;
+ sliceData.m_holeRadius = m_holeSize;
+ return sliceData;
+}
+
+#include "moc_piechartitem_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/piechart/piechartitem_p.h b/src/charts/piechart/piechartitem_p.h
new file mode 100644
index 00000000..a6511b42
--- /dev/null
+++ b/src/charts/piechart/piechartitem_p.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 PIECHARTITEM_H
+#define PIECHARTITEM_H
+
+#include "qpieseries.h"
+#include "chartitem_p.h"
+#include "piesliceitem_p.h"
+#include <QPointer>
+
+class QGraphicsItem;
+QT_CHARTS_BEGIN_NAMESPACE
+class QPieSlice;
+class ChartPresenter;
+class PieAnimation;
+
+class PieChartItem : public ChartItem
+{
+ Q_OBJECT
+
+public:
+ explicit PieChartItem(QPieSeries *series, QGraphicsItem* item = 0);
+ ~PieChartItem();
+
+ // from QGraphicsItem
+ QRectF boundingRect() const { return m_rect; }
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) {}
+
+public Q_SLOTS:
+ // from Chart
+ virtual void handleDomainUpdated();
+
+ void updateLayout();
+ void handleSlicesAdded(QList<QPieSlice *> slices);
+ void handleSlicesRemoved(QList<QPieSlice *> slices);
+ void handleSliceChanged();
+ void handleSeriesVisibleChanged();
+ void handleOpacityChanged();
+
+ void setAnimation(PieAnimation *animation);
+ ChartAnimation *animation() const;
+
+private:
+ PieSliceData updateSliceGeometry(QPieSlice *slice);
+
+private:
+ QHash<QPieSlice *, PieSliceItem *> m_sliceItems;
+ QPointer<QPieSeries> m_series;
+ QRectF m_rect;
+ QPointF m_pieCenter;
+ qreal m_pieRadius;
+ qreal m_holeSize;
+ PieAnimation *m_animation;
+
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // PIECHARTITEM_H
diff --git a/src/charts/piechart/pieslicedata_p.h b/src/charts/piechart/pieslicedata_p.h
new file mode 100644
index 00000000..37985121
--- /dev/null
+++ b/src/charts/piechart/pieslicedata_p.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 PIESLICEDATA_P_H
+#define PIESLICEDATA_P_H
+
+#include <qchartglobal.h>
+#include <qpieslice.h>
+#include <QPen>
+#include <QBrush>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+template <class T>
+class Themed : public T
+{
+public:
+ Themed(): m_isThemed(true) {}
+
+ inline T &operator=(const T &other) { return T::operator =(other); }
+
+ inline bool operator!=(const T &other) const { return T::operator !=(other); }
+ inline bool operator!=(const Themed &other) const
+ {
+ if (T::operator !=(other))
+ return true;
+
+ if (m_isThemed != other.m_isThemed)
+ return true;
+
+ return false;
+ }
+
+ inline void setThemed(bool state) { m_isThemed = state; }
+ inline bool isThemed() const { return m_isThemed; }
+
+private:
+ bool m_isThemed;
+};
+
+class PieSliceData
+{
+public:
+ PieSliceData() :
+ m_value(0),
+ m_isExploded(false),
+ m_explodeDistanceFactor(0.15),
+ m_isLabelVisible(false),
+ m_labelPosition(QPieSlice::LabelOutside),
+ m_labelArmLengthFactor(0.15),
+ m_percentage(0),
+ m_radius(0),
+ m_startAngle(0),
+ m_angleSpan(0),
+ m_holeRadius(0)
+ {
+ }
+
+ bool operator!=(const PieSliceData &other) const {
+ if (!qFuzzyIsNull(m_value - other.m_value))
+ return true;
+
+ if (m_slicePen != other.m_slicePen ||
+ m_sliceBrush != other.m_sliceBrush)
+ return true;
+
+ if (m_isExploded != other.m_isExploded ||
+ !qFuzzyIsNull(m_explodeDistanceFactor - other.m_explodeDistanceFactor))
+ return true;
+
+ if (m_isLabelVisible != other.m_isLabelVisible ||
+ m_labelText != other.m_labelText ||
+ m_labelFont != other.m_labelFont ||
+ m_labelPosition != other.m_labelPosition ||
+ !qFuzzyIsNull(m_labelArmLengthFactor - other.m_labelArmLengthFactor) ||
+ m_labelBrush != other.m_labelBrush)
+ return true;
+
+ if (!qFuzzyIsNull(m_percentage - other.m_percentage) ||
+ m_center != other.m_center ||
+ !qFuzzyIsNull(m_radius - other.m_radius) ||
+ !qFuzzyIsNull(m_startAngle - other.m_startAngle) ||
+ !qFuzzyIsNull(m_angleSpan - other.m_angleSpan))
+ return true;
+
+ return false;
+ }
+
+ qreal m_value;
+
+ Themed<QPen> m_slicePen;
+ Themed<QBrush> m_sliceBrush;
+
+ bool m_isExploded;
+ qreal m_explodeDistanceFactor;
+
+ bool m_isLabelVisible;
+ QString m_labelText;
+ Themed<QFont> m_labelFont;
+ QPieSlice::LabelPosition m_labelPosition;
+ qreal m_labelArmLengthFactor;
+ Themed<QBrush> m_labelBrush;
+
+ qreal m_percentage;
+ QPointF m_center;
+ qreal m_radius;
+ qreal m_startAngle;
+ qreal m_angleSpan;
+
+ qreal m_holeRadius;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // PIESLICEDATA_P_H
diff --git a/src/charts/piechart/piesliceitem.cpp b/src/charts/piechart/piesliceitem.cpp
new file mode 100644
index 00000000..70f03a94
--- /dev/null
+++ b/src/charts/piechart/piesliceitem.cpp
@@ -0,0 +1,319 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "piesliceitem_p.h"
+#include "piechartitem_p.h"
+#include "qpieseries.h"
+#include "qpieslice.h"
+#include "chartpresenter_p.h"
+#include <QPainter>
+#include <qmath.h>
+#include <QGraphicsSceneEvent>
+#include <QTime>
+#include <QTextDocument>
+#include <QDebug>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+QPointF offset(qreal angle, qreal length)
+{
+ qreal dx = qSin(angle * (M_PI / 180)) * length;
+ qreal dy = qCos(angle * (M_PI / 180)) * length;
+ return QPointF(dx, -dy);
+}
+
+PieSliceItem::PieSliceItem(QGraphicsItem *parent)
+ : QGraphicsObject(parent),
+ m_hovered(false)
+{
+ setAcceptHoverEvents(true);
+ setAcceptedMouseButtons(Qt::MouseButtonMask);
+ setZValue(ChartPresenter::PieSeriesZValue);
+ m_labelItem = new QGraphicsTextItem(this);
+ m_labelItem->document()->setDocumentMargin(1.0);
+}
+
+PieSliceItem::~PieSliceItem()
+{
+ // If user is hovering over the slice and it gets destroyed we do
+ // not get a hover leave event. So we must emit the signal here.
+ if (m_hovered)
+ emit hovered(false);
+}
+
+QRectF PieSliceItem::boundingRect() const
+{
+ return m_boundingRect;
+}
+
+QPainterPath PieSliceItem::shape() const
+{
+ // Don't include the label and label arm.
+ // This is used to detect a mouse clicks. We do not want clicks from label.
+ return m_slicePath;
+}
+
+void PieSliceItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
+{
+ painter->save();
+ painter->setClipRect(parentItem()->boundingRect());
+ painter->setPen(m_data.m_slicePen);
+ painter->setBrush(m_data.m_sliceBrush);
+ painter->drawPath(m_slicePath);
+ painter->restore();
+
+ if (m_data.m_isLabelVisible) {
+ painter->save();
+
+ // Pen for label arm not defined in the QPieSeries api, let's use brush's color instead
+ painter->setBrush(m_data.m_labelBrush);
+
+ if (m_data.m_labelPosition == QPieSlice::LabelOutside) {
+ painter->setClipRect(parentItem()->boundingRect());
+ painter->strokePath(m_labelArmPath, m_data.m_labelBrush.color());
+ }
+
+ painter->restore();
+ }
+}
+
+void PieSliceItem::hoverEnterEvent(QGraphicsSceneHoverEvent * /*event*/)
+{
+ m_hovered = true;
+ emit hovered(true);
+}
+
+void PieSliceItem::hoverLeaveEvent(QGraphicsSceneHoverEvent * /*event*/)
+{
+ m_hovered = false;
+ emit hovered(false);
+}
+
+void PieSliceItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ emit clicked(event->buttons());
+}
+
+void PieSliceItem::setLayout(const PieSliceData &sliceData)
+{
+ m_data = sliceData;
+ updateGeometry();
+ update();
+}
+
+void PieSliceItem::updateGeometry()
+{
+ if (m_data.m_radius <= 0)
+ return;
+
+ prepareGeometryChange();
+
+ // slice path
+ qreal centerAngle;
+ QPointF armStart;
+ m_slicePath = slicePath(m_data.m_center, m_data.m_radius, m_data.m_startAngle, m_data.m_angleSpan, &centerAngle, &armStart);
+
+ m_labelItem->setVisible(m_data.m_isLabelVisible);
+
+ if (m_data.m_isLabelVisible) {
+ // text rect
+ m_labelTextRect = ChartPresenter::textBoundingRect(m_data.m_labelFont,
+ m_data.m_labelText,
+ 0);
+
+ QString label(m_data.m_labelText);
+ m_labelItem->setDefaultTextColor(m_data.m_labelBrush.color());
+ m_labelItem->setFont(m_data.m_labelFont);
+
+ // text position
+ if (m_data.m_labelPosition == QPieSlice::LabelOutside) {
+ setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
+
+ // label arm path
+ QPointF labelTextStart;
+ m_labelArmPath = labelArmPath(armStart, centerAngle,
+ m_data.m_radius * m_data.m_labelArmLengthFactor,
+ m_labelTextRect.width(), &labelTextStart);
+
+ m_labelTextRect.moveBottomLeft(labelTextStart);
+ if (m_labelTextRect.left() < 0)
+ m_labelTextRect.setLeft(0);
+ else if (m_labelTextRect.left() < parentItem()->boundingRect().left())
+ m_labelTextRect.setLeft(parentItem()->boundingRect().left());
+ if (m_labelTextRect.right() > parentItem()->boundingRect().right())
+ m_labelTextRect.setRight(parentItem()->boundingRect().right());
+
+ label = ChartPresenter::truncatedText(m_data.m_labelFont, m_data.m_labelText,
+ qreal(0.0), m_labelTextRect.width(),
+ m_labelTextRect.height(), m_labelTextRect);
+ m_labelArmPath = labelArmPath(armStart, centerAngle,
+ m_data.m_radius * m_data.m_labelArmLengthFactor,
+ m_labelTextRect.width(), &labelTextStart);
+ m_labelTextRect.moveBottomLeft(labelTextStart);
+
+ m_labelItem->setTextWidth(m_labelTextRect.width()
+ + m_labelItem->document()->documentMargin());
+ m_labelItem->setHtml(label);
+ m_labelItem->setRotation(0);
+ m_labelItem->setPos(m_labelTextRect.x(), m_labelTextRect.y() + 1.0);
+ } else {
+ // label inside
+ setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ m_labelItem->setTextWidth(m_labelTextRect.width()
+ + m_labelItem->document()->documentMargin());
+ m_labelItem->setHtml(label);
+
+ QPointF textCenter;
+ if (m_data.m_holeRadius > 0) {
+ textCenter = m_data.m_center + offset(centerAngle, m_data.m_holeRadius
+ + (m_data.m_radius
+ - m_data.m_holeRadius) / 2);
+ } else {
+ textCenter = m_data.m_center + offset(centerAngle, m_data.m_radius / 2);
+ }
+ m_labelItem->setPos(textCenter.x() - m_labelItem->boundingRect().width() / 2,
+ textCenter.y() - m_labelTextRect.height() / 2);
+
+ QPointF labelCenter = m_labelItem->boundingRect().center();
+ m_labelItem->setTransformOriginPoint(labelCenter);
+
+ if (m_data.m_labelPosition == QPieSlice::LabelInsideTangential) {
+ m_labelItem->setRotation(m_data.m_startAngle + m_data.m_angleSpan / 2);
+ } else if (m_data.m_labelPosition == QPieSlice::LabelInsideNormal) {
+ if (m_data.m_startAngle + m_data.m_angleSpan / 2 < 180)
+ m_labelItem->setRotation(m_data.m_startAngle + m_data.m_angleSpan / 2 - 90);
+ else
+ m_labelItem->setRotation(m_data.m_startAngle + m_data.m_angleSpan / 2 + 90);
+ } else {
+ m_labelItem->setRotation(0);
+ }
+ }
+ // Hide label if it's outside the bounding rect of parent item
+ QRectF labelRect(m_labelItem->boundingRect());
+ labelRect.moveTopLeft(m_labelItem->pos());
+ if ((parentItem()->boundingRect().left()
+ < (labelRect.left() + m_labelItem->document()->documentMargin() + 1.0))
+ && (parentItem()->boundingRect().right()
+ > (labelRect.right() - m_labelItem->document()->documentMargin() - 1.0))
+ && (parentItem()->boundingRect().top()
+ < (labelRect.top() + m_labelItem->document()->documentMargin() + 1.0))
+ && (parentItem()->boundingRect().bottom()
+ > (labelRect.bottom() - m_labelItem->document()->documentMargin() - 1.0)))
+ m_labelItem->show();
+ else
+ m_labelItem->hide();
+ }
+
+ // bounding rect
+ if (m_data.m_isLabelVisible)
+ m_boundingRect = m_slicePath.boundingRect().united(m_labelArmPath.boundingRect()).united(m_labelTextRect);
+ else
+ m_boundingRect = m_slicePath.boundingRect();
+
+ // Inflate bounding rect by 2/3 pen width to make sure it encompasses whole slice also for thick pens
+ // and miter joins.
+ int penWidth = (m_data.m_slicePen.width() * 2) / 3;
+ m_boundingRect = m_boundingRect.adjusted(-penWidth, -penWidth, penWidth, penWidth);
+}
+
+QPointF PieSliceItem::sliceCenter(QPointF point, qreal radius, QPieSlice *slice)
+{
+ if (slice->isExploded()) {
+ qreal centerAngle = slice->startAngle() + (slice->angleSpan() / 2);
+ qreal len = radius * slice->explodeDistanceFactor();
+ point += offset(centerAngle, len);
+ }
+ return point;
+}
+
+QPainterPath PieSliceItem::slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, qreal *centerAngle, QPointF *armStart)
+{
+ // calculate center angle
+ *centerAngle = startAngle + (angleSpan / 2);
+
+ // calculate slice rectangle
+ QRectF rect(center.x() - radius, center.y() - radius, radius * 2, radius * 2);
+
+ // slice path
+ QPainterPath path;
+ if (m_data.m_holeRadius > 0) {
+ QRectF insideRect(center.x() - m_data.m_holeRadius, center.y() - m_data.m_holeRadius, m_data.m_holeRadius * 2, m_data.m_holeRadius * 2);
+ path.arcMoveTo(rect, -startAngle + 90);
+ path.arcTo(rect, -startAngle + 90, -angleSpan);
+ path.arcTo(insideRect, -startAngle + 90 - angleSpan, angleSpan);
+ path.closeSubpath();
+ } else {
+ path.moveTo(rect.center());
+ path.arcTo(rect, -startAngle + 90, -angleSpan);
+ path.closeSubpath();
+ }
+
+ // calculate label arm start point
+ *armStart = center;
+ *armStart += offset(*centerAngle, radius + PIESLICE_LABEL_GAP);
+
+ return path;
+}
+
+QPainterPath PieSliceItem::labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF *textStart)
+{
+ // Normalize the angle to 0-360 range
+ // NOTE: We are using int here on purpose. Depenging on platform and hardware
+ // qreal can be a double, float or something the user gives to the Qt configure
+ // (QT_COORD_TYPE). Compilers do not seem to support modulo for double or float
+ // but there are fmod() and fmodf() functions for that. So instead of some #ifdef
+ // that might break we just use int. Precision for this is just fine for our needs.
+ int normalized = angle * 10.0;
+ normalized = normalized % 3600;
+ if (normalized < 0)
+ normalized += 3600;
+ angle = (qreal) normalized / 10.0;
+
+ // prevent label arm pointing straight down because it will look bad
+ if (angle < 180 && angle > 170)
+ angle = 170;
+ if (angle > 180 && angle < 190)
+ angle = 190;
+
+ // line from slice to label
+ QPointF parm1 = start + offset(angle, length);
+
+ // line to underline the label
+ QPointF parm2 = parm1;
+ if (angle < 180) { // arm swings the other way on the left side
+ parm2 += QPointF(textWidth, 0);
+ *textStart = parm1;
+ } else {
+ parm2 += QPointF(-textWidth, 0);
+ *textStart = parm2;
+ }
+
+ QPainterPath path;
+ path.moveTo(start);
+ path.lineTo(parm1);
+ path.lineTo(parm2);
+
+ return path;
+}
+
+#include "moc_piesliceitem_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
+
diff --git a/src/charts/piechart/piesliceitem_p.h b/src/charts/piechart/piesliceitem_p.h
new file mode 100644
index 00000000..d6b7768c
--- /dev/null
+++ b/src/charts/piechart/piesliceitem_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 PIESLICEITEM_H
+#define PIESLICEITEM_H
+
+#include "qchartglobal.h"
+#include "charttheme_p.h"
+#include "qpieseries.h"
+#include "pieslicedata_p.h"
+#include <QGraphicsItem>
+#include <QRectF>
+#include <QColor>
+#include <QPen>
+
+#define PIESLICE_LABEL_GAP 5
+
+QT_CHARTS_BEGIN_NAMESPACE
+class PieChartItem;
+class PieSliceLabel;
+class QPieSlice;
+
+class PieSliceItem : public QGraphicsObject
+{
+ Q_OBJECT
+
+public:
+ PieSliceItem(QGraphicsItem *parent = 0);
+ ~PieSliceItem();
+
+ // from QGraphicsItem
+ QRectF boundingRect() const;
+ QPainterPath shape() const;
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+ void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
+ void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+
+ void setLayout(const PieSliceData &sliceData);
+ static QPointF sliceCenter(QPointF point, qreal radius, QPieSlice *slice);
+
+Q_SIGNALS:
+ void clicked(Qt::MouseButtons buttons);
+ void hovered(bool state);
+
+private:
+ void updateGeometry();
+ QPainterPath slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, qreal *centerAngle, QPointF *armStart);
+ QPainterPath labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF *textStart);
+
+private:
+ PieSliceData m_data;
+ QRectF m_boundingRect;
+ QPainterPath m_slicePath;
+ QPainterPath m_labelArmPath;
+ QRectF m_labelTextRect;
+ bool m_hovered;
+ QGraphicsTextItem *m_labelItem;
+
+ friend class PieSliceAnimation;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // PIESLICEITEM_H
diff --git a/src/charts/piechart/qhpiemodelmapper.cpp b/src/charts/piechart/qhpiemodelmapper.cpp
new file mode 100644
index 00000000..b1c7d84f
--- /dev/null
+++ b/src/charts/piechart/qhpiemodelmapper.cpp
@@ -0,0 +1,267 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhpiemodelmapper.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QHPieModelMapper
+ \inmodule Qt Charts
+ \brief Horizontal model mapper for pie series.
+ \mainclass
+
+ Model mappers allow you to use QAbstractItemModel derived models as a data source for a chart series.
+ Horizontal model mapper is used to create a connection between QPieSeries and QAbstractItemModel derived model object that keeps the consecutive pie slices data in rows.
+ It is possible to use both QAbstractItemModel and QPieSeries model API. QHPieModelMapper makes sure that Pie and the model are kept in sync.
+ \note Used model has to support adding/removing rows/columns and modifying the data of the cells.
+*/
+/*!
+ \qmltype HPieModelMapper
+ \instantiates QHPieModelMapper
+ \inqmlmodule QtCharts
+
+ \brief Horizontal model mapper for pie series.
+
+ HPieModelMapper allows you to use your own QAbstractItemModel derived model with data in rows as
+ a data source for a pie series. It is possible to use both QAbstractItemModel and PieSeries data
+ API to manipulate data. HPieModelMapper keeps the Pie and the model in sync.
+
+ The following QML example would create a pie series with four slices (assuming the model has
+ at least five columns). Each slice would contain a label from row 1 and a value from row 2.
+ \code
+ HPieModelMapper {
+ series: pieSeries
+ model: customModel
+ labelsRow: 1
+ valuesRow: 2
+ firstColumn: 1
+ columnCount: 4
+ }
+ \endcode
+*/
+
+/*!
+ \property QHPieModelMapper::series
+ \brief Defines the QPieSeries object that is used by the mapper.
+
+ All the data in the series is discarded when it is set to the mapper.
+ When new series is specified the old series is disconnected (it preserves its data)
+*/
+/*!
+ \qmlproperty PieSeries HPieModelMapper::series
+ Defines the PieSeries object that is used by the mapper. If you define the mapper element as a child for a
+ PieSeries, leave this property undefined. All the data in the series is discarded when it is set to the mapper.
+ When new series is specified the old series is disconnected (it preserves its data).
+*/
+
+/*!
+ \property QHPieModelMapper::model
+ \brief Defines the model that is used by the mapper.
+*/
+/*!
+ \qmlproperty SomeModel HPieModelMapper::model
+ The QAbstractItemModel based model that is used by the mapper. You need to implement the model
+ and expose it to QML. Note: the model has to support adding/removing rows/columns and modifying
+ the data of the cells.
+*/
+
+/*!
+ \property QHPieModelMapper::valuesRow
+ \brief Defines which row of the model is kept in sync with the values of the pie's slices.
+
+ Default value is: -1 (invalid mapping)
+*/
+/*!
+ \qmlproperty int HPieModelMapper::valuesRow
+ Defines which row of the model is kept in sync with the values of the pie's slices. Default value is: -1 (invalid
+ mapping).
+*/
+
+/*!
+ \property QHPieModelMapper::labelsRow
+ \brief Defines which row of the model is kept in sync with the labels of the pie's slices.
+
+ Default value is: -1 (invalid mapping)
+*/
+/*!
+ \qmlproperty int HPieModelMapper::labelsRow
+ Defines which row of the model is kept in sync with the labels of the pie's slices
+ Default value is: -1 (invalid mapping)
+*/
+
+/*!
+ \property QHPieModelMapper::firstColumn
+ \brief Defines which column of the model contains the first slice value.
+
+ Minimal and default value is: 0
+*/
+/*!
+ \qmlproperty int HPieModelMapper::firstColumn
+ Defines which column of the model contains the first slice value.
+ The default value is 0.
+*/
+
+/*!
+ \property QHPieModelMapper::columnCount
+ \brief Defines the number of columns of the model that are mapped as the data for QPieSeries.
+
+ Minimal and default value is: -1 (count limited by the number of columns in the model)
+*/
+/*!
+ \qmlproperty int HPieModelMapper::columnCount
+ Defines the number of columns of the model that are mapped as the data for QPieSeries. The default value is
+ -1 (count limited by the number of columns in the model)
+*/
+
+/*!
+ \fn void QHPieModelMapper::seriesReplaced()
+ Emitted when the series to which mapper is connected to has changed.
+*/
+
+/*!
+ \fn void QHPieModelMapper::modelReplaced()
+ Emitted when the model to which mapper is connected to has changed.
+*/
+
+/*!
+ \fn void QHPieModelMapper::valuesRowChanged()
+ Emitted when the valuesRow has changed.
+*/
+
+/*!
+ \fn void QHPieModelMapper::labelsRowChanged()
+ Emitted when the labelsRow has changed.
+*/
+
+/*!
+ \fn void QHPieModelMapper::firstColumnChanged()
+ Emitted when the firstColumn has changed.
+*/
+
+/*!
+ \fn void QHPieModelMapper::columnCountChanged()
+ Emitted when the columnCount has changed.
+*/
+
+/*!
+ Constructs a mapper object which is a child of \a parent.
+*/
+QHPieModelMapper::QHPieModelMapper(QObject *parent) :
+ QPieModelMapper(parent)
+{
+ setOrientation(Qt::Horizontal);
+}
+
+QAbstractItemModel *QHPieModelMapper::model() const
+{
+ return QPieModelMapper::model();
+}
+
+void QHPieModelMapper::setModel(QAbstractItemModel *model)
+{
+ if (model != QPieModelMapper::model()) {
+ QPieModelMapper::setModel(model);
+ emit modelReplaced();
+ }
+}
+
+QPieSeries *QHPieModelMapper::series() const
+{
+ return QPieModelMapper::series();
+}
+
+void QHPieModelMapper::setSeries(QPieSeries *series)
+{
+ if (series != QPieModelMapper::series()) {
+ QPieModelMapper::setSeries(series);
+ emit seriesReplaced();
+ }
+}
+
+/*!
+ Returns which row of the model is kept in sync with the values of the pie's slices
+*/
+int QHPieModelMapper::valuesRow() const
+{
+ return valuesSection();
+}
+
+/*!
+ Sets the model row that is kept in sync with the pie slices values.
+ Parameter \a valuesRow specifies the row of the model.
+*/
+void QHPieModelMapper::setValuesRow(int valuesRow)
+{
+ if (valuesRow != valuesSection()) {
+ setValuesSection(valuesRow);
+ emit valuesRowChanged();
+ }
+}
+
+/*!
+ Returns which row of the model is kept in sync with the labels of the pie's slices
+*/
+int QHPieModelMapper::labelsRow() const
+{
+ return labelsSection();
+}
+
+/*!
+ Sets the model row that is kept in sync with the pie's slices labels.
+ Parameter \a labelsRow specifies the row of the model.
+*/
+void QHPieModelMapper::setLabelsRow(int labelsRow)
+{
+ if (labelsRow != labelsSection()) {
+ setLabelsSection(labelsRow);
+ emit labelsRowChanged();
+ }
+}
+
+int QHPieModelMapper::firstColumn() const
+{
+ return first();
+}
+
+void QHPieModelMapper::setFirstColumn(int firstColumn)
+{
+ if (firstColumn != first()) {
+ setFirst(firstColumn);
+ emit firstColumnChanged();
+ }
+}
+
+int QHPieModelMapper::columnCount() const
+{
+ return count();
+}
+
+void QHPieModelMapper::setColumnCount(int columnCount)
+{
+ if (columnCount != count()) {
+ setCount(columnCount);
+ emit columnCountChanged();
+ }
+}
+
+#include "moc_qhpiemodelmapper.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/piechart/qhpiemodelmapper.h b/src/charts/piechart/qhpiemodelmapper.h
new file mode 100644
index 00000000..50b5c6f2
--- /dev/null
+++ b/src/charts/piechart/qhpiemodelmapper.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHPIEMODELMAPPER_H
+#define QHPIEMODELMAPPER_H
+
+#include <QtCharts/qpiemodelmapper.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+/* Comment line for syncqt to generate the fwd-include correctly, due to QTBUG-22432 */
+class QT_CHARTS_EXPORT QHPieModelMapper : public QPieModelMapper
+{
+ Q_OBJECT
+ Q_PROPERTY(QPieSeries *series READ series WRITE setSeries NOTIFY seriesReplaced)
+ Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelReplaced)
+ Q_PROPERTY(int valuesRow READ valuesRow WRITE setValuesRow NOTIFY valuesRowChanged)
+ Q_PROPERTY(int labelsRow READ labelsRow WRITE setLabelsRow NOTIFY labelsRowChanged)
+ Q_PROPERTY(int firstColumn READ firstColumn WRITE setFirstColumn NOTIFY firstColumnChanged)
+ Q_PROPERTY(int columnCount READ columnCount WRITE setColumnCount NOTIFY columnCountChanged)
+
+public:
+ explicit QHPieModelMapper(QObject *parent = 0);
+
+ QAbstractItemModel *model() const;
+ void setModel(QAbstractItemModel *model);
+
+ QPieSeries *series() const;
+ void setSeries(QPieSeries *series);
+
+ int valuesRow() const;
+ void setValuesRow(int valuesRow);
+
+ int labelsRow() const;
+ void setLabelsRow(int labelsRow);
+
+ int firstColumn() const;
+ void setFirstColumn(int firstColumn);
+
+ int columnCount() const;
+ void setColumnCount(int columnCount);
+
+Q_SIGNALS:
+ void seriesReplaced();
+ void modelReplaced();
+ void valuesRowChanged();
+ void labelsRowChanged();
+ void firstColumnChanged();
+ void columnCountChanged();
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QHPIEMODELMAPPER_H
diff --git a/src/charts/piechart/qpiemodelmapper.cpp b/src/charts/piechart/qpiemodelmapper.cpp
new file mode 100644
index 00000000..186be815
--- /dev/null
+++ b/src/charts/piechart/qpiemodelmapper.cpp
@@ -0,0 +1,568 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpiemodelmapper.h"
+#include "qpiemodelmapper_p.h"
+#include "qpieseries.h"
+#include "qpieslice.h"
+#include <QAbstractItemModel>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+QPieModelMapper::QPieModelMapper(QObject *parent)
+ : QObject(parent),
+ d_ptr(new QPieModelMapperPrivate(this))
+{
+}
+
+QAbstractItemModel *QPieModelMapper::model() const
+{
+ Q_D(const QPieModelMapper);
+ return d->m_model;
+}
+
+void QPieModelMapper::setModel(QAbstractItemModel *model)
+{
+ if (model == 0)
+ return;
+
+ Q_D(QPieModelMapper);
+ if (d->m_model) {
+ disconnect(d->m_model, 0, d, 0);
+ }
+
+ d->m_model = model;
+ d->initializePieFromModel();
+ // connect signals from the model
+ connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
+ connect(d->m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelRowsAdded(QModelIndex,int,int)));
+ connect(d->m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelRowsRemoved(QModelIndex,int,int)));
+ connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelColumnsAdded(QModelIndex,int,int)));
+ connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelColumnsRemoved(QModelIndex,int,int)));
+ connect(d->m_model, SIGNAL(destroyed()), d, SLOT(handleModelDestroyed()));
+}
+
+QPieSeries *QPieModelMapper::series() const
+{
+ Q_D(const QPieModelMapper);
+ return d->m_series;
+}
+
+void QPieModelMapper::setSeries(QPieSeries *series)
+{
+ Q_D(QPieModelMapper);
+ if (d->m_series) {
+ disconnect(d->m_series, 0, d, 0);
+ }
+
+ if (series == 0)
+ return;
+
+ d->m_series = series;
+ d->initializePieFromModel();
+ // connect the signals from the series
+ connect(d->m_series, SIGNAL(added(QList<QPieSlice*>)), d, SLOT(slicesAdded(QList<QPieSlice*>)));
+ connect(d->m_series, SIGNAL(removed(QList<QPieSlice*>)), d, SLOT(slicesRemoved(QList<QPieSlice*>)));
+ connect(d->m_series, SIGNAL(destroyed()), d, SLOT(handleSeriesDestroyed()));
+}
+
+/*!
+ Defines which row/column of the model contains the first slice value.
+ Minimal and default value is: 0
+*/
+int QPieModelMapper::first() const
+{
+ Q_D(const QPieModelMapper);
+ return d->m_first;
+}
+
+/*!
+ Sets which row/column of the model contains the \a first slice value.
+ Minimal and default value is: 0
+*/
+void QPieModelMapper::setFirst(int first)
+{
+ Q_D(QPieModelMapper);
+ d->m_first = qMax(first, 0);
+ d->initializePieFromModel();
+}
+
+/*!
+ Defines the number of rows/columns of the model that are mapped as the data for QPieSeries
+ Minimal and default value is: -1 (count limited by the number of rows/columns in the model)
+*/
+int QPieModelMapper::count() const
+{
+ Q_D(const QPieModelMapper);
+ return d->m_count;
+}
+
+/*!
+ Defines the \a count of rows/columns of the model that are mapped as the data for QPieSeries
+ Minimal and default value is: -1 (count limited by the number of rows/columns in the model)
+*/
+void QPieModelMapper::setCount(int count)
+{
+ Q_D(QPieModelMapper);
+ d->m_count = qMax(count, -1);
+ d->initializePieFromModel();
+}
+
+/*!
+ Returns the orientation that is used when QPieModelMapper accesses the model.
+ This mean whether the consecutive values/labels of the pie are read from row (Qt::Horizontal)
+ or from columns (Qt::Vertical)
+*/
+Qt::Orientation QPieModelMapper::orientation() const
+{
+ Q_D(const QPieModelMapper);
+ return d->m_orientation;
+}
+
+/*!
+ Returns the \a orientation that is used when QPieModelMapper accesses the model.
+ This mean whether the consecutive values/labels of the pie are read from row (Qt::Horizontal)
+ or from columns (Qt::Vertical)
+*/
+void QPieModelMapper::setOrientation(Qt::Orientation orientation)
+{
+ Q_D(QPieModelMapper);
+ d->m_orientation = orientation;
+ d->initializePieFromModel();
+}
+
+/*!
+ Returns which section of the model is kept in sync with the values of the pie's slices
+*/
+int QPieModelMapper::valuesSection() const
+{
+ Q_D(const QPieModelMapper);
+ return d->m_valuesSection;
+}
+
+/*!
+ Sets the model section that is kept in sync with the pie slices values.
+ Parameter \a valuesSection specifies the section of the model.
+*/
+void QPieModelMapper::setValuesSection(int valuesSection)
+{
+ Q_D(QPieModelMapper);
+ d->m_valuesSection = qMax(-1, valuesSection);
+ d->initializePieFromModel();
+}
+
+/*!
+ Returns which section of the model is kept in sync with the labels of the pie's slices
+*/
+int QPieModelMapper::labelsSection() const
+{
+ Q_D(const QPieModelMapper);
+ return d->m_labelsSection;
+}
+
+/*!
+ Sets the model section that is kept in sync with the pie slices labels.
+ Parameter \a labelsSection specifies the section of the model.
+*/
+void QPieModelMapper::setLabelsSection(int labelsSection)
+{
+ Q_D(QPieModelMapper);
+ d->m_labelsSection = qMax(-1, labelsSection);
+ d->initializePieFromModel();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QPieModelMapperPrivate::QPieModelMapperPrivate(QPieModelMapper *q) :
+ QObject(q),
+ m_series(0),
+ m_model(0),
+ m_first(0),
+ m_count(-1),
+ m_orientation(Qt::Vertical),
+ m_valuesSection(-1),
+ m_labelsSection(-1),
+ m_seriesSignalsBlock(false),
+ m_modelSignalsBlock(false),
+ q_ptr(q)
+{
+}
+
+void QPieModelMapperPrivate::blockModelSignals(bool block)
+{
+ m_modelSignalsBlock = block;
+}
+
+void QPieModelMapperPrivate::blockSeriesSignals(bool block)
+{
+ m_seriesSignalsBlock = block;
+}
+
+
+QPieSlice *QPieModelMapperPrivate::pieSlice(QModelIndex index) const
+{
+ if (!index.isValid())
+ return 0; // index is invalid
+
+ if (m_orientation == Qt::Vertical && (index.column() == m_valuesSection || index.column() == m_labelsSection)) {
+ if (index.row() >= m_first && (m_count == - 1 || index.row() < m_first + m_count)) {
+ if (m_model->index(index.row(), m_valuesSection).isValid() && m_model->index(index.row(), m_labelsSection).isValid())
+ return m_series->slices().at(index.row() - m_first);
+ else
+ return 0;
+ }
+ } else if (m_orientation == Qt::Horizontal && (index.row() == m_valuesSection || index.row() == m_labelsSection)) {
+ if (index.column() >= m_first && (m_count == - 1 || index.column() < m_first + m_count)) {
+ if (m_model->index(m_valuesSection, index.column()).isValid() && m_model->index(m_labelsSection, index.column()).isValid())
+ return m_series->slices().at(index.column() - m_first);
+ else
+ return 0;
+ }
+ }
+ return 0; // This part of model has not been mapped to any slice
+}
+
+QModelIndex QPieModelMapperPrivate::valueModelIndex(int slicePos)
+{
+ if (m_count != -1 && slicePos >= m_count)
+ return QModelIndex(); // invalid
+
+ if (m_orientation == Qt::Vertical)
+ return m_model->index(slicePos + m_first, m_valuesSection);
+ else
+ return m_model->index(m_valuesSection, slicePos + m_first);
+}
+
+QModelIndex QPieModelMapperPrivate::labelModelIndex(int slicePos)
+{
+ if (m_count != -1 && slicePos >= m_count)
+ return QModelIndex(); // invalid
+
+ if (m_orientation == Qt::Vertical)
+ return m_model->index(slicePos + m_first, m_labelsSection);
+ else
+ return m_model->index(m_labelsSection, slicePos + m_first);
+}
+
+bool QPieModelMapperPrivate::isLabelIndex(QModelIndex index) const
+{
+ if (m_orientation == Qt::Vertical && index.column() == m_labelsSection)
+ return true;
+ else if (m_orientation == Qt::Horizontal && index.row() == m_labelsSection)
+ return true;
+
+ return false;
+}
+
+bool QPieModelMapperPrivate::isValueIndex(QModelIndex index) const
+{
+ if (m_orientation == Qt::Vertical && index.column() == m_valuesSection)
+ return true;
+ else if (m_orientation == Qt::Horizontal && index.row() == m_valuesSection)
+ return true;
+
+ return false;
+}
+
+void QPieModelMapperPrivate::slicesAdded(QList<QPieSlice *> slices)
+{
+ if (m_seriesSignalsBlock)
+ return;
+
+ if (slices.count() == 0)
+ return;
+
+ int firstIndex = m_series->slices().indexOf(slices.at(0));
+ if (firstIndex == -1)
+ return;
+
+ if (m_count != -1)
+ m_count += slices.count();
+
+ for (int i = firstIndex; i < firstIndex + slices.count(); i++) {
+ m_slices.insert(i, slices.at(i - firstIndex));
+ connect(slices.at(i - firstIndex), SIGNAL(labelChanged()), this, SLOT(sliceLabelChanged()));
+ connect(slices.at(i - firstIndex), SIGNAL(valueChanged()), this, SLOT(sliceValueChanged()));
+ }
+
+ blockModelSignals();
+ if (m_orientation == Qt::Vertical)
+ m_model->insertRows(firstIndex + m_first, slices.count());
+ else
+ m_model->insertColumns(firstIndex + m_first, slices.count());
+
+ for (int i = firstIndex; i < firstIndex + slices.count(); i++) {
+ m_model->setData(valueModelIndex(i), slices.at(i - firstIndex)->value());
+ m_model->setData(labelModelIndex(i), slices.at(i - firstIndex)->label());
+ }
+ blockModelSignals(false);
+}
+
+void QPieModelMapperPrivate::slicesRemoved(QList<QPieSlice *> slices)
+{
+ if (m_seriesSignalsBlock)
+ return;
+
+ if (slices.count() == 0)
+ return;
+
+ int firstIndex = m_slices.indexOf(slices.at(0));
+ if (firstIndex == -1)
+ return;
+
+ if (m_count != -1)
+ m_count -= slices.count();
+
+ for (int i = firstIndex + slices.count() - 1; i >= firstIndex; i--)
+ m_slices.removeAt(i);
+
+ blockModelSignals();
+ if (m_orientation == Qt::Vertical)
+ m_model->removeRows(firstIndex + m_first, slices.count());
+ else
+ m_model->removeColumns(firstIndex + m_first, slices.count());
+ blockModelSignals(false);
+}
+
+void QPieModelMapperPrivate::sliceLabelChanged()
+{
+ if (m_seriesSignalsBlock)
+ return;
+
+ blockModelSignals();
+ QPieSlice *slice = qobject_cast<QPieSlice *>(QObject::sender());
+ m_model->setData(labelModelIndex(m_series->slices().indexOf(slice)), slice->label());
+ blockModelSignals(false);
+}
+
+void QPieModelMapperPrivate::sliceValueChanged()
+{
+ if (m_seriesSignalsBlock)
+ return;
+
+ blockModelSignals();
+ QPieSlice *slice = qobject_cast<QPieSlice *>(QObject::sender());
+ m_model->setData(valueModelIndex(m_series->slices().indexOf(slice)), slice->value());
+ blockModelSignals(false);
+}
+
+void QPieModelMapperPrivate::handleSeriesDestroyed()
+{
+ m_series = 0;
+}
+
+void QPieModelMapperPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
+{
+ if (m_model == 0 || m_series == 0)
+ return;
+
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ QModelIndex index;
+ QPieSlice *slice;
+ for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
+ for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
+ index = topLeft.sibling(row, column);
+ slice = pieSlice(index);
+ if (slice) {
+ if (isValueIndex(index))
+ slice->setValue(m_model->data(index, Qt::DisplayRole).toReal());
+ if (isLabelIndex(index))
+ slice->setLabel(m_model->data(index, Qt::DisplayRole).toString());
+ }
+ }
+ }
+ blockSeriesSignals(false);
+}
+
+
+void QPieModelMapperPrivate::modelRowsAdded(QModelIndex parent, int start, int end)
+{
+ Q_UNUSED(parent);
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ if (m_orientation == Qt::Vertical)
+ insertData(start, end);
+ else if (start <= m_valuesSection || start <= m_labelsSection) // if the changes affect the map - reinitialize the pie
+ initializePieFromModel();
+ blockSeriesSignals(false);
+}
+
+void QPieModelMapperPrivate::modelRowsRemoved(QModelIndex parent, int start, int end)
+{
+ Q_UNUSED(parent);
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ if (m_orientation == Qt::Vertical)
+ removeData(start, end);
+ else if (start <= m_valuesSection || start <= m_labelsSection) // if the changes affect the map - reinitialize the pie
+ initializePieFromModel();
+ blockSeriesSignals(false);
+}
+
+void QPieModelMapperPrivate::modelColumnsAdded(QModelIndex parent, int start, int end)
+{
+ Q_UNUSED(parent);
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ if (m_orientation == Qt::Horizontal)
+ insertData(start, end);
+ else if (start <= m_valuesSection || start <= m_labelsSection) // if the changes affect the map - reinitialize the pie
+ initializePieFromModel();
+ blockSeriesSignals(false);
+}
+
+void QPieModelMapperPrivate::modelColumnsRemoved(QModelIndex parent, int start, int end)
+{
+ Q_UNUSED(parent);
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ if (m_orientation == Qt::Horizontal)
+ removeData(start, end);
+ else if (start <= m_valuesSection || start <= m_labelsSection) // if the changes affect the map - reinitialize the pie
+ initializePieFromModel();
+ blockSeriesSignals(false);
+}
+
+void QPieModelMapperPrivate::handleModelDestroyed()
+{
+ m_model = 0;
+}
+
+void QPieModelMapperPrivate::insertData(int start, int end)
+{
+ if (m_model == 0 || m_series == 0)
+ return;
+
+ if (m_count != -1 && start >= m_first + m_count) {
+ return;
+ } else {
+ int addedCount = end - start + 1;
+ if (m_count != -1 && addedCount > m_count)
+ addedCount = m_count;
+ int first = qMax(start, m_first);
+ int last = qMin(first + addedCount - 1, m_orientation == Qt::Vertical ? m_model->rowCount() - 1 : m_model->columnCount() - 1);
+ for (int i = first; i <= last; i++) {
+ QModelIndex valueIndex = valueModelIndex(i - m_first);
+ QModelIndex labelIndex = labelModelIndex(i - m_first);
+ if (valueIndex.isValid() && labelIndex.isValid()) {
+ QPieSlice *slice = new QPieSlice;
+ slice->setValue(m_model->data(valueIndex, Qt::DisplayRole).toDouble());
+ slice->setLabel(m_model->data(labelIndex, Qt::DisplayRole).toString());
+ connect(slice, SIGNAL(labelChanged()), this, SLOT(sliceLabelChanged()));
+ connect(slice, SIGNAL(valueChanged()), this, SLOT(sliceValueChanged()));
+ m_series->insert(i - m_first, slice);
+ m_slices.insert(i - m_first, slice);
+ }
+ }
+
+ // remove excess of slices (abouve m_count)
+ if (m_count != -1 && m_series->slices().size() > m_count)
+ for (int i = m_series->slices().size() - 1; i >= m_count; i--) {
+ m_series->remove(m_series->slices().at(i));
+ m_slices.removeAt(i);
+ }
+ }
+}
+
+void QPieModelMapperPrivate::removeData(int start, int end)
+{
+ if (m_model == 0 || m_series == 0)
+ return;
+
+ int removedCount = end - start + 1;
+ if (m_count != -1 && start >= m_first + m_count) {
+ return;
+ } else {
+ int toRemove = qMin(m_series->slices().size(), removedCount); // first find how many items can actually be removed
+ int first = qMax(start, m_first); // get the index of the first item that will be removed.
+ int last = qMin(first + toRemove - 1, m_series->slices().size() + m_first - 1); // get the index of the last item that will be removed.
+ for (int i = last; i >= first; i--) {
+ m_series->remove(m_series->slices().at(i - m_first));
+ m_slices.removeAt(i - m_first);
+ }
+
+ if (m_count != -1) {
+ int itemsAvailable; // check how many are available to be added
+ if (m_orientation == Qt::Vertical)
+ itemsAvailable = m_model->rowCount() - m_first - m_series->slices().size();
+ else
+ itemsAvailable = m_model->columnCount() - m_first - m_series->slices().size();
+ int toBeAdded = qMin(itemsAvailable, m_count - m_series->slices().size()); // add not more items than there is space left to be filled.
+ int currentSize = m_series->slices().size();
+ if (toBeAdded > 0)
+ for (int i = m_series->slices().size(); i < currentSize + toBeAdded; i++) {
+ QModelIndex valueIndex = valueModelIndex(i - m_first);
+ QModelIndex labelIndex = labelModelIndex(i - m_first);
+ if (valueIndex.isValid() && labelIndex.isValid()) {
+ QPieSlice *slice = new QPieSlice;
+ slice->setValue(m_model->data(valueIndex, Qt::DisplayRole).toDouble());
+ slice->setLabel(m_model->data(labelIndex, Qt::DisplayRole).toString());
+ m_series->insert(i, slice);
+ m_slices.insert(i, slice);
+ }
+ }
+ }
+ }
+}
+
+void QPieModelMapperPrivate::initializePieFromModel()
+{
+ if (m_model == 0 || m_series == 0)
+ return;
+
+ blockSeriesSignals();
+ // clear current content
+ m_series->clear();
+ m_slices.clear();
+
+ // create the initial slices set
+ int slicePos = 0;
+ QModelIndex valueIndex = valueModelIndex(slicePos);
+ QModelIndex labelIndex = labelModelIndex(slicePos);
+ while (valueIndex.isValid() && labelIndex.isValid()) {
+ QPieSlice *slice = new QPieSlice;
+ slice->setLabel(m_model->data(labelIndex, Qt::DisplayRole).toString());
+ slice->setValue(m_model->data(valueIndex, Qt::DisplayRole).toDouble());
+ connect(slice, SIGNAL(labelChanged()), this, SLOT(sliceLabelChanged()));
+ connect(slice, SIGNAL(valueChanged()), this, SLOT(sliceValueChanged()));
+ m_series->append(slice);
+ m_slices.append(slice);
+ slicePos++;
+ valueIndex = valueModelIndex(slicePos);
+ labelIndex = labelModelIndex(slicePos);
+ }
+ blockSeriesSignals(false);
+}
+
+#include "moc_qpiemodelmapper_p.cpp"
+#include "moc_qpiemodelmapper.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/piechart/qpiemodelmapper.h b/src/charts/piechart/qpiemodelmapper.h
new file mode 100644
index 00000000..a4ab6a2c
--- /dev/null
+++ b/src/charts/piechart/qpiemodelmapper.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPIEMODELMAPPER_H
+#define QPIEMODELMAPPER_H
+
+#include <QtCharts/qchartglobal.h>
+#include <QObject>
+
+class QAbstractItemModel;
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QPieModelMapperPrivate;
+class QPieSeries;
+
+class QT_CHARTS_EXPORT QPieModelMapper : public QObject
+{
+ Q_OBJECT
+
+protected:
+ explicit QPieModelMapper(QObject *parent = 0);
+
+ QAbstractItemModel *model() const;
+ void setModel(QAbstractItemModel *model);
+
+ QPieSeries *series() const;
+ void setSeries(QPieSeries *series);
+
+ int first() const;
+ void setFirst(int first);
+
+ int count() const;
+ void setCount(int count);
+
+ int valuesSection() const;
+ void setValuesSection(int valuesSection);
+
+ int labelsSection() const;
+ void setLabelsSection(int labelsSection);
+
+ Qt::Orientation orientation() const;
+ void setOrientation(Qt::Orientation orientation);
+
+protected:
+ QPieModelMapperPrivate * const d_ptr;
+ Q_DECLARE_PRIVATE(QPieModelMapper)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QPIEMODELMAPPER_H
diff --git a/src/charts/piechart/qpiemodelmapper_p.h b/src/charts/piechart/qpiemodelmapper_p.h
new file mode 100644
index 00000000..a287497f
--- /dev/null
+++ b/src/charts/piechart/qpiemodelmapper_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QPIEMODELMAPPER_P_H
+#define QPIEMODELMAPPER_P_H
+
+#include <QObject>
+#include <qpiemodelmapper.h>
+
+class QModelIndex;
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QPieSlice;
+
+class QPieModelMapperPrivate : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit QPieModelMapperPrivate(QPieModelMapper *q);
+
+public Q_SLOTS:
+ // for the model
+ void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight);
+ void modelRowsAdded(QModelIndex parent, int start, int end);
+ void modelRowsRemoved(QModelIndex parent, int start, int end);
+ void modelColumnsAdded(QModelIndex parent, int start, int end);
+ void modelColumnsRemoved(QModelIndex parent, int start, int end);
+ void handleModelDestroyed();
+
+ // for the series
+ void slicesAdded(QList<QPieSlice *> slices);
+ void slicesRemoved(QList<QPieSlice *> slices);
+ void sliceLabelChanged();
+ void sliceValueChanged();
+ void handleSeriesDestroyed();
+
+ void initializePieFromModel();
+
+private:
+ QPieSlice *pieSlice(QModelIndex index) const;
+ bool isLabelIndex(QModelIndex index) const;
+ bool isValueIndex(QModelIndex index) const;
+ QModelIndex valueModelIndex(int slicePos);
+ QModelIndex labelModelIndex(int slicePos);
+ void insertData(int start, int end);
+ void removeData(int start, int end);
+
+ void blockModelSignals(bool block = true);
+ void blockSeriesSignals(bool block = true);
+
+private:
+ QPieSeries *m_series;
+ QList<QPieSlice *> m_slices;
+ QAbstractItemModel *m_model;
+ int m_first;
+ int m_count;
+ Qt::Orientation m_orientation;
+ int m_valuesSection;
+ int m_labelsSection;
+ bool m_seriesSignalsBlock;
+ bool m_modelSignalsBlock;
+
+private:
+
+ QPieModelMapper *q_ptr;
+ Q_DECLARE_PUBLIC(QPieModelMapper)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QPIEMODELMAPPER_P_H
diff --git a/src/charts/piechart/qpieseries.cpp b/src/charts/piechart/qpieseries.cpp
new file mode 100644
index 00000000..733429d1
--- /dev/null
+++ b/src/charts/piechart/qpieseries.cpp
@@ -0,0 +1,947 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpieseries.h"
+#include "qpieseries_p.h"
+#include "qpieslice.h"
+#include "qpieslice_p.h"
+#include "pieslicedata_p.h"
+#include "chartdataset_p.h"
+#include "charttheme_p.h"
+#include "qabstractaxis.h"
+#include "pieanimation_p.h"
+#include "charthelpers_p.h"
+
+#include "qpielegendmarker.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QPieSeries
+ \inmodule Qt Charts
+ \brief Pie series API for Qt Charts.
+
+ The pie series defines a pie chart which consists of pie slices which are defined as QPieSlice objects.
+ The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices.
+ The actual slice size is determined by that relative value.
+
+ Pie size and position on the chart is controlled by using relative values which range from 0.0 to 1.0.
+ These relate to the actual chart rectangle.
+
+ By default the pie is defined as a full pie but it can also be a partial pie.
+ This can be done by setting a starting angle and angle span to the series.
+ Full pie is 360 degrees where 0 is at 12 a'clock.
+
+ See the \l {PieChart Example} {pie chart example} or \l {DonutChart Example} {donut chart example} to learn how to use QPieSeries.
+ \table 100%
+ \row
+ \li \image examples_piechart.png
+ \li \image examples_donutchart.png
+ \endtable
+*/
+/*!
+ \qmltype PieSeries
+ \instantiates QPieSeries
+ \inqmlmodule QtCharts
+
+ \inherits AbstractSeries
+
+ \brief The PieSeries type is used for making pie charts.
+
+ The following QML shows how to create a simple pie chart.
+
+ \snippet qmlchart/qml/qmlchart/View1.qml 1
+
+ \beginfloatleft
+ \image examples_qmlchart1.png
+ \endfloat
+ \clearfloat
+*/
+
+/*!
+ \property QPieSeries::horizontalPosition
+ \brief Defines the horizontal position of the pie.
+
+ The value is a relative value to the chart rectangle where:
+
+ \list
+ \li 0.0 is the absolute left.
+ \li 1.0 is the absolute right.
+ \endlist
+ Default value is 0.5 (center).
+ \sa verticalPosition
+*/
+
+/*!
+ \qmlproperty real PieSeries::horizontalPosition
+
+ Defines the horizontal position of the pie.
+
+ The value is a relative value to the chart rectangle where:
+
+ \list
+ \li 0.0 is the absolute left.
+ \li 1.0 is the absolute right.
+ \endlist
+ Default value is 0.5 (center).
+ \sa verticalPosition
+*/
+
+/*!
+ \property QPieSeries::verticalPosition
+ \brief Defines the vertical position of the pie.
+
+ The value is a relative value to the chart rectangle where:
+
+ \list
+ \li 0.0 is the absolute top.
+ \li 1.0 is the absolute bottom.
+ \endlist
+ Default value is 0.5 (center).
+ \sa horizontalPosition
+*/
+
+/*!
+ \qmlproperty real PieSeries::verticalPosition
+
+ Defines the vertical position of the pie.
+
+ The value is a relative value to the chart rectangle where:
+
+ \list
+ \li 0.0 is the absolute top.
+ \li 1.0 is the absolute bottom.
+ \endlist
+ Default value is 0.5 (center).
+ \sa horizontalPosition
+*/
+
+/*!
+ \property QPieSeries::size
+ \brief Defines the pie size.
+
+ The value is a relative value to the chart rectangle where:
+
+ \list
+ \li 0.0 is the minimum size (pie not drawn).
+ \li 1.0 is the maximum size that can fit the chart.
+ \endlist
+
+ When setting this property the holeSize property is adjusted if necessary, to ensure that the hole size is not greater than the outer size.
+
+ Default value is 0.7.
+*/
+
+/*!
+ \qmlproperty real PieSeries::size
+
+ Defines the pie size.
+
+ The value is a relative value to the chart rectangle where:
+
+ \list
+ \li 0.0 is the minimum size (pie not drawn).
+ \li 1.0 is the maximum size that can fit the chart.
+ \endlist
+
+ Default value is 0.7.
+*/
+
+/*!
+ \property QPieSeries::holeSize
+ \brief Defines the donut hole size.
+
+ The value is a relative value to the chart rectangle where:
+
+ \list
+ \li 0.0 is the minimum size (full pie drawn, without any hole inside).
+ \li 1.0 is the maximum size that can fit the chart. (donut has no width)
+ \endlist
+
+ The value is never greater then size property.
+ Default value is 0.0.
+*/
+
+/*!
+ \qmlproperty real PieSeries::holeSize
+
+ Defines the donut hole size.
+
+ The value is a relative value to the chart rectangle where:
+
+ \list
+ \li 0.0 is the minimum size (full pie drawn, without any hole inside).
+ \li 1.0 is the maximum size that can fit the chart. (donut has no width)
+ \endlist
+
+ When setting this property the size property is adjusted if necessary, to ensure that the inner size is not greater than the outer size.
+
+ Default value is 0.0.
+*/
+
+/*!
+ \property QPieSeries::startAngle
+ \brief Defines the starting angle of the pie.
+
+ Full pie is 360 degrees where 0 degrees is at 12 a'clock.
+
+ Default is value is 0.
+*/
+
+/*!
+ \qmlproperty real PieSeries::startAngle
+
+ Defines the starting angle of the pie.
+
+ Full pie is 360 degrees where 0 degrees is at 12 a'clock.
+
+ Default is value is 0.
+*/
+
+/*!
+ \property QPieSeries::endAngle
+ \brief Defines the ending angle of the pie.
+
+ Full pie is 360 degrees where 0 degrees is at 12 a'clock.
+
+ Default is value is 360.
+*/
+
+/*!
+ \qmlproperty real PieSeries::endAngle
+
+ Defines the ending angle of the pie.
+
+ Full pie is 360 degrees where 0 degrees is at 12 a'clock.
+
+ Default is value is 360.
+*/
+
+/*!
+ \property QPieSeries::count
+
+ Number of slices in the series.
+*/
+
+/*!
+ \qmlproperty int PieSeries::count
+
+ Number of slices in the series.
+*/
+
+/*!
+ \fn void QPieSeries::countChanged()
+ Emitted when the slice count has changed.
+ \sa count
+*/
+/*!
+ \qmlsignal PieSeries::onCountChanged()
+ Emitted when the slice count has changed.
+*/
+
+/*!
+ \property QPieSeries::sum
+
+ Sum of all slices.
+
+ The series keeps track of the sum of all slices it holds.
+*/
+
+/*!
+ \qmlproperty real PieSeries::sum
+
+ Sum of all slices.
+
+ The series keeps track of the sum of all slices it holds.
+*/
+
+/*!
+ \fn void QPieSeries::sumChanged()
+ Emitted when the sum of all slices has changed.
+ \sa sum
+*/
+/*!
+ \qmlsignal PieSeries::onSumChanged()
+ Emitted when the sum of all slices has changed. This may happen for example if you add or remove slices, or if you
+ change value of a slice.
+*/
+
+/*!
+ \fn void QPieSeries::added(QList<QPieSlice*> slices)
+
+ This signal is emitted when \a slices have been added to the series.
+
+ \sa append(), insert()
+*/
+/*!
+ \qmlsignal PieSeries::onAdded(PieSlice slice)
+ Emitted when \a slice has been added to the series.
+*/
+
+/*!
+ \fn void QPieSeries::removed(QList<QPieSlice*> slices)
+ This signal is emitted when \a slices have been removed from the series.
+ \sa remove()
+*/
+/*!
+ \qmlsignal PieSeries::onRemoved(PieSlice slice)
+ Emitted when \a slice has been removed from the series.
+*/
+
+/*!
+ \fn void QPieSeries::clicked(QPieSlice* slice)
+ This signal is emitted when a \a slice has been clicked.
+ \sa QPieSlice::clicked()
+*/
+/*!
+ \qmlsignal PieSeries::onClicked(PieSlice slice)
+ This signal is emitted when a \a slice has been clicked.
+*/
+
+/*!
+ \fn void QPieSeries::hovered(QPieSlice* slice, bool state)
+ This signal is emitted when user has hovered over or away from the \a slice.
+ \a state is true when user has hovered over the slice and false when hover has moved away from the slice.
+ \sa QPieSlice::hovered()
+*/
+/*!
+ \qmlsignal PieSeries::onHovered(PieSlice slice, bool state)
+ This signal is emitted when user has hovered over or away from the \a slice. \a state is true when user has hovered
+ over the slice and false when hover has moved away from the slice.
+*/
+
+/*!
+ \qmlmethod PieSlice PieSeries::at(int index)
+ Returns slice at \a index. Returns null if the index is not valid.
+*/
+
+/*!
+ \qmlmethod PieSlice PieSeries::find(string label)
+ Returns the first slice with \a label. Returns null if the index is not valid.
+*/
+
+/*!
+ \qmlmethod PieSlice PieSeries::append(string label, real value)
+ Adds a new slice with \a label and \a value to the pie.
+*/
+
+/*!
+ \qmlmethod bool PieSeries::remove(PieSlice slice)
+ Removes the \a slice from the pie. Returns true if the removal was successful, false otherwise.
+*/
+
+/*!
+ \qmlmethod PieSeries::clear()
+ Removes all slices from the pie.
+*/
+
+/*!
+ Constructs a series object which is a child of \a parent.
+*/
+QPieSeries::QPieSeries(QObject *parent)
+ : QAbstractSeries(*new QPieSeriesPrivate(this), parent)
+{
+ Q_D(QPieSeries);
+ QObject::connect(this, SIGNAL(countChanged()), d, SIGNAL(countChanged()));
+}
+
+/*!
+ Destroys the series and its slices.
+*/
+QPieSeries::~QPieSeries()
+{
+ // NOTE: d_prt destroyed by QObject
+ clear();
+}
+
+/*!
+ Returns QAbstractSeries::SeriesTypePie.
+*/
+QAbstractSeries::SeriesType QPieSeries::type() const
+{
+ return QAbstractSeries::SeriesTypePie;
+}
+
+/*!
+ Appends a single \a slice to the series.
+ Slice ownership is passed to the series.
+
+ Returns true if append was succesfull.
+*/
+bool QPieSeries::append(QPieSlice *slice)
+{
+ return append(QList<QPieSlice *>() << slice);
+}
+
+/*!
+ Appends an array of \a slices to the series.
+ Slice ownership is passed to the series.
+
+ Returns true if append was successful.
+*/
+bool QPieSeries::append(QList<QPieSlice *> slices)
+{
+ Q_D(QPieSeries);
+
+ if (slices.count() == 0)
+ return false;
+
+ foreach (QPieSlice *s, slices) {
+ if (!s || d->m_slices.contains(s))
+ return false;
+ if (s->series()) // already added to some series
+ return false;
+ if (!isValidValue(s->value()))
+ return false;
+ }
+
+ foreach (QPieSlice *s, slices) {
+ s->setParent(this);
+ QPieSlicePrivate::fromSlice(s)->m_series = this;
+ d->m_slices << s;
+ }
+
+ d->updateDerivativeData();
+
+ foreach(QPieSlice * s, slices) {
+ connect(s, SIGNAL(valueChanged()), d, SLOT(sliceValueChanged()));
+ connect(s, SIGNAL(clicked()), d, SLOT(sliceClicked()));
+ connect(s, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
+ }
+
+ emit added(slices);
+ emit countChanged();
+
+ return true;
+}
+
+/*!
+ Appends a single \a slice to the series and returns a reference to the series.
+ Slice ownership is passed to the series.
+*/
+QPieSeries &QPieSeries::operator << (QPieSlice *slice)
+{
+ append(slice);
+ return *this;
+}
+
+
+/*!
+ Appends a single slice to the series with give \a value and \a label.
+ Slice ownership is passed to the series.
+ Returns NULL if value is NaN, Inf or -Inf and no slice is added to the series.
+*/
+QPieSlice *QPieSeries::append(QString label, qreal value)
+{
+ if (isValidValue(value)) {
+ QPieSlice *slice = new QPieSlice(label, value);
+ append(slice);
+ return slice;
+ } else {
+ return 0;
+ }
+}
+
+/*!
+ Inserts a single \a slice to the series before the slice at \a index position.
+ Slice ownership is passed to the series.
+
+ Returns true if insert was successful.
+*/
+bool QPieSeries::insert(int index, QPieSlice *slice)
+{
+ Q_D(QPieSeries);
+
+ if (index < 0 || index > d->m_slices.count())
+ return false;
+
+ if (!slice || d->m_slices.contains(slice))
+ return false;
+
+ if (slice->series()) // already added to some series
+ return false;
+
+ if (!isValidValue(slice->value()))
+ return false;
+
+ slice->setParent(this);
+ QPieSlicePrivate::fromSlice(slice)->m_series = this;
+ d->m_slices.insert(index, slice);
+
+ d->updateDerivativeData();
+
+ connect(slice, SIGNAL(valueChanged()), d, SLOT(sliceValueChanged()));
+ connect(slice, SIGNAL(clicked()), d, SLOT(sliceClicked()));
+ connect(slice, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
+
+ emit added(QList<QPieSlice *>() << slice);
+ emit countChanged();
+
+ return true;
+}
+
+/*!
+ Removes a single \a slice from the series and deletes the slice.
+
+ Do not reference the pointer after this call.
+
+ Returns true if remove was successful.
+*/
+bool QPieSeries::remove(QPieSlice *slice)
+{
+ Q_D(QPieSeries);
+
+ if (!d->m_slices.removeOne(slice))
+ return false;
+
+ d->updateDerivativeData();
+
+ emit removed(QList<QPieSlice *>() << slice);
+ emit countChanged();
+
+ delete slice;
+ slice = 0;
+
+ return true;
+}
+
+/*!
+ Takes a single \a slice from the series. Does not destroy the slice object.
+
+ \note The series remains as the slice's parent object. You must set the
+ parent object to take full ownership.
+
+ Returns true if take was successful.
+*/
+bool QPieSeries::take(QPieSlice *slice)
+{
+ Q_D(QPieSeries);
+
+ if (!d->m_slices.removeOne(slice))
+ return false;
+
+ QPieSlicePrivate::fromSlice(slice)->m_series = 0;
+ slice->disconnect(d);
+
+ d->updateDerivativeData();
+
+ emit removed(QList<QPieSlice *>() << slice);
+ emit countChanged();
+
+ return true;
+}
+
+/*!
+ Clears all slices from the series.
+*/
+void QPieSeries::clear()
+{
+ Q_D(QPieSeries);
+ if (d->m_slices.count() == 0)
+ return;
+
+ QList<QPieSlice *> slices = d->m_slices;
+ foreach (QPieSlice *s, d->m_slices)
+ d->m_slices.removeOne(s);
+
+ d->updateDerivativeData();
+
+ emit removed(slices);
+ emit countChanged();
+
+ foreach (QPieSlice *s, slices)
+ delete s;
+}
+
+/*!
+ Returns a list of slices that belong to this series.
+*/
+QList<QPieSlice *> QPieSeries::slices() const
+{
+ Q_D(const QPieSeries);
+ return d->m_slices;
+}
+
+/*!
+ returns the number of the slices in this series.
+*/
+int QPieSeries::count() const
+{
+ Q_D(const QPieSeries);
+ return d->m_slices.count();
+}
+
+/*!
+ Returns true is the series is empty.
+*/
+bool QPieSeries::isEmpty() const
+{
+ Q_D(const QPieSeries);
+ return d->m_slices.isEmpty();
+}
+
+/*!
+ Returns the sum of all slice values in this series.
+
+ \sa QPieSlice::value(), QPieSlice::setValue(), QPieSlice::percentage()
+*/
+qreal QPieSeries::sum() const
+{
+ Q_D(const QPieSeries);
+ return d->m_sum;
+}
+
+void QPieSeries::setHoleSize(qreal holeSize)
+{
+ Q_D(QPieSeries);
+ holeSize = qBound((qreal)0.0, holeSize, (qreal)1.0);
+ d->setSizes(holeSize, qMax(d->m_pieRelativeSize, holeSize));
+}
+
+qreal QPieSeries::holeSize() const
+{
+ Q_D(const QPieSeries);
+ return d->m_holeRelativeSize;
+}
+
+void QPieSeries::setHorizontalPosition(qreal relativePosition)
+{
+ Q_D(QPieSeries);
+
+ if (relativePosition < 0.0)
+ relativePosition = 0.0;
+ if (relativePosition > 1.0)
+ relativePosition = 1.0;
+
+ if (!qFuzzyCompare(d->m_pieRelativeHorPos, relativePosition)) {
+ d->m_pieRelativeHorPos = relativePosition;
+ emit d->horizontalPositionChanged();
+ }
+}
+
+qreal QPieSeries::horizontalPosition() const
+{
+ Q_D(const QPieSeries);
+ return d->m_pieRelativeHorPos;
+}
+
+void QPieSeries::setVerticalPosition(qreal relativePosition)
+{
+ Q_D(QPieSeries);
+
+ if (relativePosition < 0.0)
+ relativePosition = 0.0;
+ if (relativePosition > 1.0)
+ relativePosition = 1.0;
+
+ if (!qFuzzyCompare(d->m_pieRelativeVerPos, relativePosition)) {
+ d->m_pieRelativeVerPos = relativePosition;
+ emit d->verticalPositionChanged();
+ }
+}
+
+qreal QPieSeries::verticalPosition() const
+{
+ Q_D(const QPieSeries);
+ return d->m_pieRelativeVerPos;
+}
+
+void QPieSeries::setPieSize(qreal relativeSize)
+{
+ Q_D(QPieSeries);
+ relativeSize = qBound((qreal)0.0, relativeSize, (qreal)1.0);
+ d->setSizes(qMin(d->m_holeRelativeSize, relativeSize), relativeSize);
+
+}
+
+qreal QPieSeries::pieSize() const
+{
+ Q_D(const QPieSeries);
+ return d->m_pieRelativeSize;
+}
+
+
+void QPieSeries::setPieStartAngle(qreal angle)
+{
+ Q_D(QPieSeries);
+ if (qFuzzyCompare(d->m_pieStartAngle, angle))
+ return;
+ d->m_pieStartAngle = angle;
+ d->updateDerivativeData();
+ emit d->pieStartAngleChanged();
+}
+
+qreal QPieSeries::pieStartAngle() const
+{
+ Q_D(const QPieSeries);
+ return d->m_pieStartAngle;
+}
+
+/*!
+ Sets the end angle of the pie.
+
+ Full pie is 360 degrees where 0 degrees is at 12 a'clock.
+
+ \a angle must be greater than start angle.
+
+ \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
+*/
+void QPieSeries::setPieEndAngle(qreal angle)
+{
+ Q_D(QPieSeries);
+ if (qFuzzyCompare(d->m_pieEndAngle, angle))
+ return;
+ d->m_pieEndAngle = angle;
+ d->updateDerivativeData();
+ emit d->pieEndAngleChanged();
+}
+
+/*!
+ Returns the end angle of the pie.
+
+ Full pie is 360 degrees where 0 degrees is at 12 a'clock.
+
+ \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
+*/
+qreal QPieSeries::pieEndAngle() const
+{
+ Q_D(const QPieSeries);
+ return d->m_pieEndAngle;
+}
+
+/*!
+ Sets the all the slice labels \a visible or invisible.
+
+ Note that this affects only the current slices in the series.
+ If user adds a new slice the default label visibility is false.
+
+ \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
+*/
+void QPieSeries::setLabelsVisible(bool visible)
+{
+ Q_D(QPieSeries);
+ foreach (QPieSlice *s, d->m_slices)
+ s->setLabelVisible(visible);
+}
+
+/*!
+ Sets the all the slice labels \a position
+
+ Note that this affects only the current slices in the series.
+ If user adds a new slice the default label position is LabelOutside
+
+ \sa QPieSlice::labelPosition(), QPieSlice::setLabelPosition()
+*/
+void QPieSeries::setLabelsPosition(QPieSlice::LabelPosition position)
+{
+ Q_D(QPieSeries);
+ foreach (QPieSlice *s, d->m_slices)
+ s->setLabelPosition(position);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+QPieSeriesPrivate::QPieSeriesPrivate(QPieSeries *parent) :
+ QAbstractSeriesPrivate(parent),
+ m_pieRelativeHorPos(0.5),
+ m_pieRelativeVerPos(0.5),
+ m_pieRelativeSize(0.7),
+ m_pieStartAngle(0),
+ m_pieEndAngle(360),
+ m_sum(0),
+ m_holeRelativeSize(0.0)
+{
+}
+
+QPieSeriesPrivate::~QPieSeriesPrivate()
+{
+}
+
+void QPieSeriesPrivate::updateDerivativeData()
+{
+ // calculate sum of all slices
+ qreal sum = 0;
+ foreach (QPieSlice *s, m_slices)
+ sum += s->value();
+
+ if (!qFuzzyCompare(m_sum, sum)) {
+ m_sum = sum;
+ emit q_func()->sumChanged();
+ }
+
+ // nothing to show..
+ if (qFuzzyCompare(m_sum, 0))
+ return;
+
+ // update slice attributes
+ qreal sliceAngle = m_pieStartAngle;
+ qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
+ QVector<QPieSlice *> changed;
+ foreach (QPieSlice *s, m_slices) {
+ QPieSlicePrivate *d = QPieSlicePrivate::fromSlice(s);
+ d->setPercentage(s->value() / m_sum);
+ d->setStartAngle(sliceAngle);
+ d->setAngleSpan(pieSpan * s->percentage());
+ sliceAngle += s->angleSpan();
+ }
+
+
+ emit calculatedDataChanged();
+}
+
+void QPieSeriesPrivate::setSizes(qreal innerSize, qreal outerSize)
+{
+ bool changed = false;
+
+ if (!qFuzzyCompare(m_holeRelativeSize, innerSize)) {
+ m_holeRelativeSize = innerSize;
+ changed = true;
+ }
+
+ if (!qFuzzyCompare(m_pieRelativeSize, outerSize)) {
+ m_pieRelativeSize = outerSize;
+ changed = true;
+ }
+
+ if (changed)
+ emit pieSizeChanged();
+}
+
+QPieSeriesPrivate *QPieSeriesPrivate::fromSeries(QPieSeries *series)
+{
+ return series->d_func();
+}
+
+void QPieSeriesPrivate::sliceValueChanged()
+{
+ Q_ASSERT(m_slices.contains(qobject_cast<QPieSlice *>(sender())));
+ updateDerivativeData();
+}
+
+void QPieSeriesPrivate::sliceClicked()
+{
+ QPieSlice *slice = qobject_cast<QPieSlice *>(sender());
+ Q_ASSERT(m_slices.contains(slice));
+ Q_Q(QPieSeries);
+ emit q->clicked(slice);
+}
+
+void QPieSeriesPrivate::sliceHovered(bool state)
+{
+ QPieSlice *slice = qobject_cast<QPieSlice *>(sender());
+ if (!m_slices.isEmpty()) {
+ Q_ASSERT(m_slices.contains(slice));
+ Q_Q(QPieSeries);
+ emit q->hovered(slice, state);
+ }
+}
+
+void QPieSeriesPrivate::initializeDomain()
+{
+ // does not apply to pie
+}
+
+void QPieSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
+{
+ Q_Q(QPieSeries);
+ PieChartItem *pie = new PieChartItem(q,parent);
+ m_item.reset(pie);
+ QAbstractSeriesPrivate::initializeGraphics(parent);
+}
+
+void QPieSeriesPrivate::initializeAnimations(QtCharts::QChart::AnimationOptions options)
+{
+ PieChartItem *item = static_cast<PieChartItem *>(m_item.data());
+ Q_ASSERT(item);
+ if (item->animation())
+ item->animation()->stopAndDestroyLater();
+
+ if (options.testFlag(QChart::SeriesAnimations))
+ item->setAnimation(new PieAnimation(item));
+ else
+ item->setAnimation(0);
+ QAbstractSeriesPrivate::initializeAnimations(options);
+}
+
+QList<QLegendMarker*> QPieSeriesPrivate::createLegendMarkers(QLegend* legend)
+{
+ Q_Q(QPieSeries);
+ QList<QLegendMarker*> markers;
+ foreach(QPieSlice* slice, q->slices()) {
+ QPieLegendMarker* marker = new QPieLegendMarker(q,slice,legend);
+ markers << marker;
+ }
+ return markers;
+}
+
+void QPieSeriesPrivate::initializeAxes()
+{
+
+}
+
+QAbstractAxis::AxisType QPieSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
+{
+ Q_UNUSED(orientation);
+ return QAbstractAxis::AxisTypeNoAxis;
+}
+
+QAbstractAxis* QPieSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const
+{
+ Q_UNUSED(orientation);
+ return 0;
+}
+
+void QPieSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
+{
+ //Q_Q(QPieSeries);
+ //const QList<QColor>& colors = theme->seriesColors();
+ const QList<QGradient>& gradients = theme->seriesGradients();
+
+ for (int i(0); i < m_slices.count(); i++) {
+
+ QColor penColor = ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0.0);
+
+ // Get color for a slice from a gradient linearly, beginning from the start of the gradient
+ qreal pos = (qreal)(i + 1) / (qreal) m_slices.count();
+ QColor brushColor = ChartThemeManager::colorAt(gradients.at(index % gradients.size()), pos);
+
+ QPieSlice *s = m_slices.at(i);
+ QPieSlicePrivate *d = QPieSlicePrivate::fromSlice(s);
+
+ if (forced || d->m_data.m_slicePen.isThemed())
+ d->setPen(penColor, true);
+
+ if (forced || d->m_data.m_sliceBrush.isThemed())
+ d->setBrush(brushColor, true);
+
+ if (forced || d->m_data.m_labelBrush.isThemed())
+ d->setLabelBrush(theme->labelBrush().color(), true);
+
+ if (forced || d->m_data.m_labelFont.isThemed())
+ d->setLabelFont(theme->labelFont(), true);
+ }
+}
+
+
+#include "moc_qpieseries.cpp"
+#include "moc_qpieseries_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/piechart/qpieseries.h b/src/charts/piechart/qpieseries.h
new file mode 100644
index 00000000..27c8042b
--- /dev/null
+++ b/src/charts/piechart/qpieseries.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPIESERIES_H
+#define QPIESERIES_H
+
+#include <QtCharts/qabstractseries.h>
+#include <QtCharts/QPieSlice>
+
+QT_CHARTS_BEGIN_NAMESPACE
+class QPieSeriesPrivate;
+
+class QT_CHARTS_EXPORT QPieSeries : public QAbstractSeries
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal horizontalPosition READ horizontalPosition WRITE setHorizontalPosition)
+ Q_PROPERTY(qreal verticalPosition READ verticalPosition WRITE setVerticalPosition)
+ Q_PROPERTY(qreal size READ pieSize WRITE setPieSize)
+ Q_PROPERTY(qreal startAngle READ pieStartAngle WRITE setPieStartAngle)
+ Q_PROPERTY(qreal endAngle READ pieEndAngle WRITE setPieEndAngle)
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+ Q_PROPERTY(qreal sum READ sum NOTIFY sumChanged)
+ Q_PROPERTY(qreal holeSize READ holeSize WRITE setHoleSize)
+
+public:
+ explicit QPieSeries(QObject *parent = 0);
+ virtual ~QPieSeries();
+
+ QAbstractSeries::SeriesType type() const;
+
+ bool append(QPieSlice *slice);
+ bool append(QList<QPieSlice *> slices);
+ QPieSeries &operator << (QPieSlice *slice);
+ QPieSlice *append(QString label, qreal value);
+
+ bool insert(int index, QPieSlice *slice);
+
+ bool remove(QPieSlice *slice);
+ bool take(QPieSlice *slice);
+ void clear();
+
+ QList<QPieSlice *> slices() const;
+ int count() const;
+
+ bool isEmpty() const;
+
+ qreal sum() const;
+
+ void setHoleSize(qreal holeSize);
+ qreal holeSize() const;
+
+ void setHorizontalPosition(qreal relativePosition);
+ qreal horizontalPosition() const;
+
+ void setVerticalPosition(qreal relativePosition);
+ qreal verticalPosition() const;
+
+ void setPieSize(qreal relativeSize);
+ qreal pieSize() const;
+
+ void setPieStartAngle(qreal startAngle);
+ qreal pieStartAngle() const;
+
+ void setPieEndAngle(qreal endAngle);
+ qreal pieEndAngle() const;
+
+ void setLabelsVisible(bool visible = true);
+ void setLabelsPosition(QPieSlice::LabelPosition position);
+
+Q_SIGNALS:
+ void added(QList<QPieSlice *> slices);
+ void removed(QList<QPieSlice *> slices);
+ void clicked(QPieSlice *slice);
+ void hovered(QPieSlice *slice, bool state);
+ void countChanged();
+ void sumChanged();
+
+private:
+ Q_DECLARE_PRIVATE(QPieSeries)
+ Q_DISABLE_COPY(QPieSeries)
+ friend class PieChartItem;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QPIESERIES_H
diff --git a/src/charts/piechart/qpieseries_p.h b/src/charts/piechart/qpieseries_p.h
new file mode 100644
index 00000000..f2a52180
--- /dev/null
+++ b/src/charts/piechart/qpieseries_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QPIESERIES_P_H
+#define QPIESERIES_P_H
+
+#include "qpieseries.h"
+#include "qabstractseries_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+class QLegendPrivate;
+
+class QPieSeriesPrivate : public QAbstractSeriesPrivate
+{
+ Q_OBJECT
+
+public:
+ QPieSeriesPrivate(QPieSeries *parent);
+ ~QPieSeriesPrivate();
+
+ void initializeDomain();
+ void initializeAxes();
+ void initializeGraphics(QGraphicsItem* parent);
+ void initializeAnimations(QtCharts::QChart::AnimationOptions options);
+ void initializeTheme(int index, ChartTheme* theme, bool forced = false);
+
+ QList<QLegendMarker *> createLegendMarkers(QLegend *legend);
+
+ QAbstractAxis::AxisType defaultAxisType(Qt::Orientation orientation) const;
+ QAbstractAxis* createDefaultAxis(Qt::Orientation orientation) const;
+
+ void updateDerivativeData();
+ void setSizes(qreal innerSize, qreal outerSize);
+
+ static QPieSeriesPrivate *fromSeries(QPieSeries *series);
+
+signals:
+ void calculatedDataChanged();
+ void pieSizeChanged();
+ void pieStartAngleChanged();
+ void pieEndAngleChanged();
+ void horizontalPositionChanged();
+ void verticalPositionChanged();
+
+public Q_SLOTS:
+ void sliceValueChanged();
+ void sliceClicked();
+ void sliceHovered(bool state);
+
+private:
+ QList<QPieSlice *> m_slices;
+ qreal m_pieRelativeHorPos;
+ qreal m_pieRelativeVerPos;
+ qreal m_pieRelativeSize;
+ qreal m_pieStartAngle;
+ qreal m_pieEndAngle;
+ qreal m_sum;
+ qreal m_holeRelativeSize;
+
+public:
+ friend class QLegendPrivate;
+ Q_DECLARE_PUBLIC(QPieSeries)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QPIESERIES_P_H
diff --git a/src/charts/piechart/qpieslice.cpp b/src/charts/piechart/qpieslice.cpp
new file mode 100644
index 00000000..48227e26
--- /dev/null
+++ b/src/charts/piechart/qpieslice.cpp
@@ -0,0 +1,794 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpieslice.h"
+#include "qpieslice_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QPieSlice
+ \inmodule Qt Charts
+ \brief Defines a slice in pie series.
+
+ This object defines the properties of a single slice in a QPieSeries.
+
+ In addition to the obvious value and label properties the user can also control
+ the visual appearance of a slice. By modifying the visual appearance also means that
+ the user is overriding the default appearance set by the theme.
+
+ Note that if the user has customized slices and theme is changed all customizations will be lost.
+
+ To enable user interaction with the pie some basic signals are provided about clicking and hovering.
+*/
+
+/*!
+ \qmltype PieSlice
+ \instantiates QPieSlice
+ \inqmlmodule QtCharts
+
+ \brief Defines a slice in pie series.
+
+ PieSlice defines the properties of a single slice in a PieSeries. The element should be used
+ as a child for a PieSeries. For example:
+ \snippet qmlpiechart/qml/qmlpiechart/main.qml 2
+
+ An alternative (dynamic) method for adding slices to a PieSeries is using PieSeries.append
+ method.
+ \snippet qmlpiechart/qml/qmlpiechart/main.qml 4
+
+ In that case you may want to use PieSeries.at or PieSeries.find to access the properties of
+ an individual PieSlice instance.
+ \snippet qmlpiechart/qml/qmlpiechart/main.qml 5
+ \sa PieSeries
+*/
+
+/*!
+ \enum QPieSlice::LabelPosition
+
+ This enum describes the position of the slice label.
+
+ \value LabelOutside Label is outside the slice with an arm.
+ \value LabelInsideHorizontal Label is centered inside the slice and laid out horizontally.
+ \value LabelInsideTangential Label is centered inside the slice and rotated to be parallel to the tangential of the slice's arc.
+ \value LabelInsideNormal Label is centered inside the slice rotated to be parallel to the normal of the slice's arc.
+ */
+
+/*!
+ \property QPieSlice::label
+ Label of the slice.
+ \sa labelVisible, labelBrush, labelFont, labelArmLengthFactor
+*/
+/*!
+ \qmlproperty string PieSlice::label
+ Label (text) of the slice.
+*/
+
+/*!
+ \fn void QPieSlice::labelChanged()
+ This signal emitted when the slice label has been changed.
+ \sa label
+*/
+/*!
+ \qmlsignal PieSlice::onLabelChanged()
+ This signal emitted when the slice label has been changed.
+ \sa label
+*/
+
+/*!
+ \property QPieSlice::value
+ Value of the slice.
+ Note that if users sets a negative value it is converted to a positive value.
+ \sa percentage(), QPieSeries::sum()
+*/
+/*!
+ \qmlproperty real PieSlice::value
+ Value of the slice. Note that if users sets a negative value it is converted to a positive value.
+*/
+
+/*!
+ \fn void QPieSlice::valueChanged()
+ This signal is emitted when the slice value changes.
+ \sa value
+*/
+/*!
+ \qmlsignal PieSlice::onValueChanged()
+ This signal is emitted when the slice value changes.
+ \sa value
+*/
+
+/*!
+ \property QPieSlice::labelVisible
+ Defines the visibility of slice label. By default the label is not visible.
+ \sa label, labelBrush, labelFont, labelArmLengthFactor
+*/
+/*!
+ \qmlproperty bool PieSlice::labelVisible
+ Defines the visibility of slice label. By default the label is not visible.
+*/
+
+/*!
+ \fn void QPieSlice::labelVisibleChanged()
+ This signal emitted when visibility of the slice label has changed.
+ \sa labelVisible
+*/
+/*!
+ \qmlsignal PieSlice::onLabelVisibleChanged()
+ This signal emitted when visibility of the slice label has changed.
+ \sa labelVisible
+*/
+
+/*!
+ \property QPieSlice::exploded
+ If set to true the slice is "exploded" away from the pie.
+ \sa explodeDistanceFactor
+*/
+/*!
+ \qmlproperty bool PieSlice::exploded
+ If set to true the slice is "exploded" away from the pie.
+ \sa explodeDistanceFactor
+*/
+
+/*!
+ \property QPieSlice::pen
+ Pen used to draw the slice border.
+*/
+
+/*!
+ \fn void QPieSlice::penChanged()
+ This signal is emitted when the pen of the slice has changed.
+ \sa pen
+*/
+
+/*!
+ \property QPieSlice::borderColor
+ Color used to draw the slice border.
+ This is a convenience property for modifying the slice pen.
+ \sa pen, borderWidth
+*/
+/*!
+ \qmlproperty color PieSlice::borderColor
+ Color used to draw the slice border (pen color).
+ \sa borderWidth
+*/
+
+/*!
+ \fn void QPieSlice::borderColorChanged()
+ This signal is emitted when slice border color changes.
+ \sa pen, borderColor
+*/
+/*!
+ \qmlsignal PieSlice::onBorderColorChanged()
+ This signal is emitted when slice border color changes.
+ \sa borderColor
+*/
+
+/*!
+ \property QPieSlice::borderWidth
+ Width of the slice border.
+ This is a convenience property for modifying the slice pen.
+ \sa pen, borderColor
+*/
+/*!
+ \qmlproperty int PieSlice::borderWidth
+ Width of the slice border.
+ This is a convenience property for modifying the slice pen.
+ \sa borderColor
+*/
+
+/*!
+ \fn void QPieSlice::borderWidthChanged()
+ This signal is emitted when slice border width changes.
+ \sa pen, borderWidth
+*/
+/*!
+ \qmlsignal PieSlice::onBorderWidthChanged()
+ This signal is emitted when slice border width changes.
+ \sa borderWidth
+*/
+
+/*!
+ \property QPieSlice::brush
+ Brush used to draw the slice.
+*/
+
+/*!
+ \fn void QPieSlice::brushChanged()
+ This signal is emitted when the brush of the slice has changed.
+ \sa brush
+*/
+
+/*!
+ \qmlproperty QString PieSlice::brushFilename
+ The name of the file used as a brush for the slice.
+*/
+
+/*!
+ \property QPieSlice::color
+ Fill (brush) color of the slice.
+ This is a convenience property for modifying the slice brush.
+ \sa brush
+*/
+/*!
+ \qmlproperty color PieSlice::color
+ Fill (brush) color of the slice.
+*/
+
+/*!
+ \fn void QPieSlice::colorChanged()
+ This signal is emitted when slice color changes.
+ \sa brush
+*/
+/*!
+ \qmlsignal PieSlice::onColorChanged()
+ This signal is emitted when slice color changes.
+*/
+
+/*!
+ \property QPieSlice::labelBrush
+ Brush used to draw label and label arm of the slice.
+ \sa label, labelVisible, labelFont, labelArmLengthFactor
+*/
+
+/*!
+ \fn void QPieSlice::labelBrushChanged()
+ This signal is emitted when the label brush of the slice has changed.
+ \sa labelBrush
+*/
+
+/*!
+ \property QPieSlice::labelColor
+ Color used to draw the slice label.
+ This is a convenience property for modifying the slice label brush.
+ \sa labelBrush
+*/
+/*!
+ \qmlproperty color PieSlice::labelColor
+ Color used to draw the slice label.
+*/
+
+/*!
+ \fn void QPieSlice::labelColorChanged()
+ This signal is emitted when slice label color changes.
+ \sa labelColor
+*/
+/*!
+ \qmlsignal PieSlice::onLabelColorChanged()
+ This signal is emitted when slice label color changes.
+ \sa labelColor
+*/
+
+/*!
+ \property QPieSlice::labelFont
+ Font used for drawing label text.
+ \sa label, labelVisible, labelArmLengthFactor
+*/
+
+/*!
+ \fn void QPieSlice::labelFontChanged()
+ This signal is emitted when the label font of the slice has changed.
+ \sa labelFont
+*/
+
+/*!
+ \qmlproperty Font PieSlice::labelFont
+
+ Defines the font used for slice label.
+
+ See the Qt documentation for more details of Font.
+
+ \sa labelVisible, labelPosition
+*/
+
+/*!
+ \property QPieSlice::labelPosition
+ Position of the slice label.
+ \sa label, labelVisible
+*/
+/*!
+ \qmlproperty LabelPosition PieSlice::labelPosition
+ Position of the slice label. One of PieSlice.LabelOutside, PieSlice.LabelInsideHorizontal,
+ PieSlice.LabelInsideTangential or PieSlice.LabelInsideNormal. By default the position is
+ PieSlice.LabelOutside.
+ \sa labelVisible
+*/
+
+/*!
+ \property QPieSlice::labelArmLengthFactor
+ Defines the length of the label arm.
+ The factor is relative to pie radius. For example:
+ 1.0 means the length is the same as the radius.
+ 0.5 means the length is half of the radius.
+ By default the arm length is 0.15
+ \sa label, labelVisible, labelBrush, labelFont
+*/
+/*!
+ \qmlproperty real PieSlice::labelArmLengthFactor
+ Defines the length of the label arm.
+ The factor is relative to pie radius. For example:
+ 1.0 means the length is the same as the radius.
+ 0.5 means the length is half of the radius.
+ By default the arm length is 0.15
+ \sa labelVisible
+*/
+
+/*!
+ \property QPieSlice::explodeDistanceFactor
+ When the slice is exploded this factor defines how far the slice is exploded away from the pie.
+ The factor is relative to pie radius. For example:
+ 1.0 means the distance is the same as the radius.
+ 0.5 means the distance is half of the radius.
+ By default the distance is is 0.15
+ \sa exploded
+*/
+/*!
+ \qmlproperty real PieSlice::explodeDistanceFactor
+ When the slice is exploded this factor defines how far the slice is exploded away from the pie.
+ The factor is relative to pie radius. For example:
+ 1.0 means the distance is the same as the radius.
+ 0.5 means the distance is half of the radius.
+ By default the distance is is 0.15
+ \sa exploded
+*/
+
+/*!
+ \property QPieSlice::percentage
+ Percentage of the slice compared to the sum of all slices in the series.
+ The actual value ranges from 0.0 to 1.0.
+ Updated automatically once the slice is added to the series.
+ \sa value, QPieSeries::sum
+*/
+/*!
+ \qmlproperty real PieSlice::percentage
+ Percentage of the slice compared to the sum of all slices in the series.
+ The actual value ranges from 0.0 to 1.0.
+ Updated automatically once the slice is added to the series.
+*/
+
+/*!
+ \fn void QPieSlice::percentageChanged()
+ This signal is emitted when the percentage of the slice has changed.
+ \sa percentage
+*/
+/*!
+ \qmlsignal void PieSlice::onPercentageChanged()
+ This signal is emitted when the percentage of the slice has changed.
+ \sa percentage
+*/
+
+/*!
+ \property QPieSlice::startAngle
+ Defines the starting angle of this slice in the series it belongs to.
+ Full pie is 360 degrees where 0 degrees is at 12 a'clock.
+ Updated automatically once the slice is added to the series.
+*/
+/*!
+ \qmlproperty real PieSlice::startAngle
+ Defines the starting angle of this slice in the series it belongs to.
+ Full pie is 360 degrees where 0 degrees is at 12 a'clock.
+ Updated automatically once the slice is added to the series.
+*/
+
+/*!
+ \fn void QPieSlice::startAngleChanged()
+ This signal is emitted when the starting angle f the slice has changed.
+ \sa startAngle
+*/
+/*!
+ \qmlsignal PieSlice::onStartAngleChanged()
+ This signal is emitted when the starting angle f the slice has changed.
+ \sa startAngle
+*/
+
+/*!
+ \property QPieSlice::angleSpan
+ Span of the slice in degrees.
+ Full pie is 360 degrees where 0 degrees is at 12 a'clock.
+ Updated automatically once the slice is added to the series.
+*/
+/*!
+ \qmlproperty real PieSlice::angleSpan
+ Span of the slice in degrees.
+ Full pie is 360 degrees where 0 degrees is at 12 a'clock.
+ Updated automatically once the slice is added to the series.
+*/
+
+/*!
+ \fn void QPieSlice::angleSpanChanged()
+ This signal is emitted when the angle span of the slice has changed.
+ \sa angleSpan
+*/
+/*!
+ \qmlsignal PieSlice::onAngleSpanChanged()
+ This signal is emitted when the angle span of the slice has changed.
+ \sa angleSpan
+*/
+
+/*!
+ \fn void QPieSlice::clicked()
+ This signal is emitted when user has clicked the slice.
+ \sa QPieSeries::clicked()
+*/
+/*!
+ \qmlsignal PieSlice::onClicked()
+ This signal is emitted when user has clicked the slice.
+*/
+
+/*!
+ \fn void QPieSlice::hovered(bool state)
+ This signal is emitted when user has hovered over or away from the slice.
+ \a state is true when user has hovered over the slice and false when hover has moved away from the slice.
+ \sa QPieSeries::hovered()
+*/
+/*!
+ \qmlsignal PieSlice::onHovered(bool state)
+ This signal is emitted when user has hovered over or away from the slice.
+ \a state is true when user has hovered over the slice and false when hover has moved away from the slice.
+*/
+
+/*!
+ Constructs an empty slice with a \a parent.
+ \sa QPieSeries::append(), QPieSeries::insert()
+*/
+QPieSlice::QPieSlice(QObject *parent)
+ : QObject(parent),
+ d_ptr(new QPieSlicePrivate(this))
+{
+
+}
+
+/*!
+ Constructs an empty slice with given \a value, \a label and a \a parent.
+ \sa QPieSeries::append(), QPieSeries::insert()
+*/
+QPieSlice::QPieSlice(QString label, qreal value, QObject *parent)
+ : QObject(parent),
+ d_ptr(new QPieSlicePrivate(this))
+{
+ setValue(value);
+ setLabel(label);
+}
+
+/*!
+ Destroys the slice.
+ User should not delete the slice if it has been added to the series.
+*/
+QPieSlice::~QPieSlice()
+{
+
+}
+
+void QPieSlice::setLabel(QString label)
+{
+ if (d_ptr->m_data.m_labelText != label) {
+ d_ptr->m_data.m_labelText = label;
+ emit labelChanged();
+ }
+}
+
+QString QPieSlice::label() const
+{
+ return d_ptr->m_data.m_labelText;
+}
+
+void QPieSlice::setValue(qreal value)
+{
+ value = qAbs(value); // negative values not allowed
+ if (!qFuzzyCompare(d_ptr->m_data.m_value, value)) {
+ d_ptr->m_data.m_value = value;
+ emit valueChanged();
+ }
+}
+
+qreal QPieSlice::value() const
+{
+ return d_ptr->m_data.m_value;
+}
+
+void QPieSlice::setLabelVisible(bool visible)
+{
+ if (d_ptr->m_data.m_isLabelVisible != visible) {
+ d_ptr->m_data.m_isLabelVisible = visible;
+ emit labelVisibleChanged();
+ }
+}
+
+bool QPieSlice::isLabelVisible() const
+{
+ return d_ptr->m_data.m_isLabelVisible;
+}
+
+void QPieSlice::setExploded(bool exploded)
+{
+ if (d_ptr->m_data.m_isExploded != exploded) {
+ d_ptr->m_data.m_isExploded = exploded;
+ emit d_ptr->explodedChanged();
+ }
+}
+
+QPieSlice::LabelPosition QPieSlice::labelPosition()
+{
+ return d_ptr->m_data.m_labelPosition;
+}
+
+void QPieSlice::setLabelPosition(LabelPosition position)
+{
+ if (d_ptr->m_data.m_labelPosition != position) {
+ d_ptr->m_data.m_labelPosition = position;
+ emit d_ptr->labelPositionChanged();
+ }
+}
+
+bool QPieSlice::isExploded() const
+{
+ return d_ptr->m_data.m_isExploded;
+}
+
+void QPieSlice::setPen(const QPen &pen)
+{
+ d_ptr->setPen(pen, false);
+}
+
+QPen QPieSlice::pen() const
+{
+ return d_ptr->m_data.m_slicePen;
+}
+
+QColor QPieSlice::borderColor()
+{
+ return pen().color();
+}
+
+void QPieSlice::setBorderColor(QColor color)
+{
+ QPen p = pen();
+ if (color != p.color()) {
+ p.setColor(color);
+ setPen(p);
+ }
+}
+
+int QPieSlice::borderWidth()
+{
+ return pen().width();
+}
+
+void QPieSlice::setBorderWidth(int width)
+{
+ QPen p = pen();
+ if (width != p.width()) {
+ p.setWidth(width);
+ setPen(p);
+ }
+}
+
+void QPieSlice::setBrush(const QBrush &brush)
+{
+ d_ptr->setBrush(brush, false);
+}
+
+QBrush QPieSlice::brush() const
+{
+ return d_ptr->m_data.m_sliceBrush;
+}
+
+QColor QPieSlice::color()
+{
+ return brush().color();
+}
+
+void QPieSlice::setColor(QColor color)
+{
+ QBrush b = brush();
+
+ if (b == QBrush())
+ b.setStyle(Qt::SolidPattern);
+ b.setColor(color);
+ setBrush(b);
+}
+
+void QPieSlice::setLabelBrush(const QBrush &brush)
+{
+ d_ptr->setLabelBrush(brush, false);
+}
+
+QBrush QPieSlice::labelBrush() const
+{
+ return d_ptr->m_data.m_labelBrush;
+}
+
+QColor QPieSlice::labelColor()
+{
+ return labelBrush().color();
+}
+
+void QPieSlice::setLabelColor(QColor color)
+{
+ QBrush b = labelBrush();
+ if (color != b.color()) {
+ b.setColor(color);
+ setLabelBrush(b);
+ }
+}
+
+void QPieSlice::setLabelFont(const QFont &font)
+{
+ d_ptr->setLabelFont(font, false);
+}
+
+QFont QPieSlice::labelFont() const
+{
+ return d_ptr->m_data.m_labelFont;
+}
+
+void QPieSlice::setLabelArmLengthFactor(qreal factor)
+{
+ if (!qFuzzyCompare(d_ptr->m_data.m_labelArmLengthFactor, factor)) {
+ d_ptr->m_data.m_labelArmLengthFactor = factor;
+ emit d_ptr->labelArmLengthFactorChanged();
+ }
+}
+
+qreal QPieSlice::labelArmLengthFactor() const
+{
+ return d_ptr->m_data.m_labelArmLengthFactor;
+}
+
+void QPieSlice::setExplodeDistanceFactor(qreal factor)
+{
+ if (!qFuzzyCompare(d_ptr->m_data.m_explodeDistanceFactor, factor)) {
+ d_ptr->m_data.m_explodeDistanceFactor = factor;
+ emit d_ptr->explodeDistanceFactorChanged();
+ }
+}
+
+qreal QPieSlice::explodeDistanceFactor() const
+{
+ return d_ptr->m_data.m_explodeDistanceFactor;
+}
+
+qreal QPieSlice::percentage() const
+{
+ return d_ptr->m_data.m_percentage;
+}
+
+qreal QPieSlice::startAngle() const
+{
+ return d_ptr->m_data.m_startAngle;
+}
+
+qreal QPieSlice::angleSpan() const
+{
+ return d_ptr->m_data.m_angleSpan;
+}
+
+/*!
+ Returns the series that this slice belongs to.
+
+ \sa QPieSeries::append()
+*/
+QPieSeries *QPieSlice::series() const
+{
+ return d_ptr->m_series;
+}
+
+QPieSlicePrivate::QPieSlicePrivate(QPieSlice *parent)
+ : QObject(parent),
+ q_ptr(parent),
+ m_series(0)
+{
+
+}
+
+QPieSlicePrivate::~QPieSlicePrivate()
+{
+
+}
+
+QPieSlicePrivate *QPieSlicePrivate::fromSlice(QPieSlice *slice)
+{
+ return slice->d_func();
+}
+
+void QPieSlicePrivate::setPen(const QPen &pen, bool themed)
+{
+ if (m_data.m_slicePen != pen) {
+
+ QPen oldPen = m_data.m_slicePen;
+
+ m_data.m_slicePen = pen;
+ m_data.m_slicePen.setThemed(themed);
+
+ emit q_ptr->penChanged();
+ if (oldPen.color() != pen.color())
+ emit q_ptr->borderColorChanged();
+ if (oldPen.width() != pen.width())
+ emit q_ptr->borderWidthChanged();
+ }
+}
+
+void QPieSlicePrivate::setBrush(const QBrush &brush, bool themed)
+{
+ if (m_data.m_sliceBrush != brush) {
+
+ QBrush oldBrush = m_data.m_sliceBrush;
+
+ m_data.m_sliceBrush = brush;
+ m_data.m_sliceBrush.setThemed(themed);
+
+ emit q_ptr->brushChanged();
+ if (oldBrush.color() != brush.color())
+ emit q_ptr->colorChanged();
+ }
+}
+
+void QPieSlicePrivate::setLabelBrush(const QBrush &brush, bool themed)
+{
+ if (m_data.m_labelBrush != brush) {
+
+ QBrush oldBrush = m_data.m_labelBrush;
+
+ m_data.m_labelBrush = brush;
+ m_data.m_labelBrush.setThemed(themed);
+
+ emit q_ptr->labelBrushChanged();
+ if (oldBrush.color() != brush.color())
+ emit q_ptr->labelColorChanged();
+ }
+}
+
+void QPieSlicePrivate::setLabelFont(const QFont &font, bool themed)
+{
+ if (m_data.m_labelFont != font) {
+ m_data.m_labelFont = font;
+ m_data.m_labelFont.setThemed(themed);
+ emit q_ptr->labelFontChanged();
+ }
+}
+
+void QPieSlicePrivate::setPercentage(qreal percentage)
+{
+ if (!qFuzzyCompare(m_data.m_percentage, percentage)) {
+ m_data.m_percentage = percentage;
+ emit q_ptr->percentageChanged();
+ }
+}
+
+void QPieSlicePrivate::setStartAngle(qreal angle)
+{
+ if (!qFuzzyCompare(m_data.m_startAngle, angle)) {
+ m_data.m_startAngle = angle;
+ emit q_ptr->startAngleChanged();
+ }
+}
+
+void QPieSlicePrivate::setAngleSpan(qreal span)
+{
+ if (!qFuzzyCompare(m_data.m_angleSpan, span)) {
+ m_data.m_angleSpan = span;
+ emit q_ptr->angleSpanChanged();
+ }
+}
+
+QT_CHARTS_END_NAMESPACE
+
+QT_CHARTS_USE_NAMESPACE
+#include "moc_qpieslice.cpp"
+#include "moc_qpieslice_p.cpp"
diff --git a/src/charts/piechart/qpieslice.h b/src/charts/piechart/qpieslice.h
new file mode 100644
index 00000000..8be5d3cc
--- /dev/null
+++ b/src/charts/piechart/qpieslice.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPIESLICE_H
+#define QPIESLICE_H
+
+#include <QtCharts/qchartglobal.h>
+#include <QObject>
+#include <QPen>
+#include <QBrush>
+#include <QFont>
+
+QT_CHARTS_BEGIN_NAMESPACE
+class QPieSlicePrivate;
+class QPieSeries;
+
+class QT_CHARTS_EXPORT QPieSlice : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(LabelPosition)
+ Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY labelChanged)
+ Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged)
+ Q_PROPERTY(bool labelVisible READ isLabelVisible WRITE setLabelVisible NOTIFY labelVisibleChanged)
+ Q_PROPERTY(LabelPosition labelPosition READ labelPosition WRITE setLabelPosition)
+ Q_PROPERTY(bool exploded READ isExploded WRITE setExploded)
+ Q_PROPERTY(QPen pen READ pen WRITE setPen NOTIFY penChanged)
+ Q_PROPERTY(QColor borderColor READ borderColor WRITE setBorderColor NOTIFY borderColorChanged)
+ Q_PROPERTY(int borderWidth READ borderWidth WRITE setBorderWidth NOTIFY borderWidthChanged)
+ Q_PROPERTY(QBrush brush READ brush WRITE setBrush NOTIFY brushChanged)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+ Q_PROPERTY(QBrush labelBrush READ labelBrush WRITE setLabelBrush NOTIFY labelBrushChanged)
+ Q_PROPERTY(QColor labelColor READ labelColor WRITE setLabelColor NOTIFY labelColorChanged)
+ Q_PROPERTY(QFont labelFont READ labelFont WRITE setLabelFont NOTIFY labelFontChanged)
+ Q_PROPERTY(qreal labelArmLengthFactor READ labelArmLengthFactor WRITE setLabelArmLengthFactor)
+ Q_PROPERTY(qreal explodeDistanceFactor READ explodeDistanceFactor WRITE setExplodeDistanceFactor)
+ Q_PROPERTY(qreal percentage READ percentage NOTIFY percentageChanged)
+ Q_PROPERTY(qreal startAngle READ startAngle NOTIFY startAngleChanged)
+ Q_PROPERTY(qreal angleSpan READ angleSpan NOTIFY angleSpanChanged)
+
+public:
+ enum LabelPosition {
+ LabelOutside,
+ LabelInsideHorizontal,
+ LabelInsideTangential,
+ LabelInsideNormal
+ };
+
+public:
+ explicit QPieSlice(QObject *parent = 0);
+ QPieSlice(QString label, qreal value, QObject *parent = 0);
+ virtual ~QPieSlice();
+
+ void setLabel(QString label);
+ QString label() const;
+
+ void setValue(qreal value);
+ qreal value() const;
+
+ void setLabelVisible(bool visible = true);
+ bool isLabelVisible() const;
+
+ LabelPosition labelPosition();
+ void setLabelPosition(LabelPosition position);
+
+ void setExploded(bool exploded = true);
+ bool isExploded() const;
+
+ void setPen(const QPen &pen);
+ QPen pen() const;
+
+ QColor borderColor();
+ void setBorderColor(QColor color);
+
+ int borderWidth();
+ void setBorderWidth(int width);
+
+ void setBrush(const QBrush &brush);
+ QBrush brush() const;
+
+ QColor color();
+ void setColor(QColor color);
+
+ void setLabelBrush(const QBrush &brush);
+ QBrush labelBrush() const;
+
+ QColor labelColor();
+ void setLabelColor(QColor color);
+
+ void setLabelFont(const QFont &font);
+ QFont labelFont() const;
+
+ void setLabelArmLengthFactor(qreal factor);
+ qreal labelArmLengthFactor() const;
+
+ void setExplodeDistanceFactor(qreal factor);
+ qreal explodeDistanceFactor() const;
+
+ qreal percentage() const;
+ qreal startAngle() const;
+ qreal angleSpan() const;
+
+ QPieSeries *series() const;
+
+Q_SIGNALS:
+ void clicked();
+ void hovered(bool state);
+ void labelChanged();
+ void valueChanged();
+ void labelVisibleChanged();
+ void penChanged();
+ void brushChanged();
+ void labelBrushChanged();
+ void labelFontChanged();
+ void percentageChanged();
+ void startAngleChanged();
+ void angleSpanChanged();
+ void colorChanged();
+ void borderColorChanged();
+ void borderWidthChanged();
+ void labelColorChanged();
+
+private:
+ QPieSlicePrivate * const d_ptr;
+ Q_DECLARE_PRIVATE(QPieSlice)
+ Q_DISABLE_COPY(QPieSlice)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QPIESLICE_H
diff --git a/src/charts/piechart/qpieslice_p.h b/src/charts/piechart/qpieslice_p.h
new file mode 100644
index 00000000..340a4753
--- /dev/null
+++ b/src/charts/piechart/qpieslice_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QPIESLICE_P_H
+#define QPIESLICE_P_H
+
+#include <QObject>
+#include "qpieslice.h"
+#include "pieslicedata_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+class QPieSeries;
+
+class QPieSlicePrivate : public QObject
+{
+ Q_OBJECT
+
+public:
+ QPieSlicePrivate(QPieSlice *parent);
+ ~QPieSlicePrivate();
+
+ static QPieSlicePrivate *fromSlice(QPieSlice *slice);
+
+ void setPen(const QPen &pen, bool themed);
+ void setBrush(const QBrush &brush, bool themed);
+ void setLabelBrush(const QBrush &brush, bool themed);
+ void setLabelFont(const QFont &font, bool themed);
+
+ void setPercentage(qreal percentage);
+ void setStartAngle(qreal angle);
+ void setAngleSpan(qreal span);
+
+Q_SIGNALS:
+ void labelPositionChanged();
+ void explodedChanged();
+ void labelArmLengthFactorChanged();
+ void explodeDistanceFactorChanged();
+
+private:
+ friend class QPieSeries;
+ friend class QPieSeriesPrivate;
+ friend class ChartThemeManager;
+ friend class PieChartItem;
+
+ QPieSlice * const q_ptr;
+ Q_DECLARE_PUBLIC(QPieSlice)
+
+ PieSliceData m_data;
+ QPieSeries *m_series;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QPIESLICE_P_H
diff --git a/src/charts/piechart/qvpiemodelmapper.cpp b/src/charts/piechart/qvpiemodelmapper.cpp
new file mode 100644
index 00000000..7b9c0a0c
--- /dev/null
+++ b/src/charts/piechart/qvpiemodelmapper.cpp
@@ -0,0 +1,270 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvpiemodelmapper.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QVPieModelMapper
+ \inmodule Qt Charts
+ \brief Vertical model mapper for pie series.
+ \mainclass
+
+ Model mappers allow you to use QAbstractItemModel derived models as a data source for a chart series.
+ Vertical model mapper is used to create a connection between QPieSeries and QAbstractItemModel derived model object that keeps the consecutive pie slices data in columns.
+ It is possible to use both QAbstractItemModel and QPieSeries model API. QVPieModelMapper makes sure that Pie and the model are kept in sync.
+ \note Used model has to support adding/removing rows/columns and modifying the data of the cells.
+*/
+/*!
+ \qmltype VPieModelMapper
+ \instantiates QVPieModelMapper
+ \inqmlmodule QtCharts
+
+ \brief Vertical model mapper for pie series.
+
+ VPieModelMapper allows you to use your own QAbstractItemModel derived model with data in columns
+ as a data source for a pie series. It is possible to use both QAbstractItemModel and PieSeries
+ data API to manipulate data. VPieModelMapper keeps the Pie and the model in sync.
+
+ The following QML example would create a pie series with four slices (assuming the model has at
+ least five rows). Each slice would contain a label from column 1 and a value from column 2.
+ \code
+ VPieModelMapper {
+ series: pieSeries
+ model: customModel
+ labelsColumn: 1
+ valuesColumn: 2
+ firstRow: 1
+ rowCount: 4
+ }
+ \endcode
+*/
+
+/*!
+ \property QVPieModelMapper::series
+ \brief Defines the QPieSeries object that is used by the mapper.
+ All the data in the series is discarded when it is set to the mapper.
+ When new series is specified the old series is disconnected (it preserves its data)
+*/
+/*!
+ \qmlproperty PieSeries VPieModelMapper::series
+ Defines the PieSeries object that is used by the mapper. If you define the mapper element as a child for a
+ PieSeries, leave this property undefined. All the data in the series is discarded when it is set to the mapper.
+ When new series is specified the old series is disconnected (it preserves its data).
+*/
+
+/*!
+ \property QVPieModelMapper::model
+ \brief Defines the model that is used by the mapper.
+*/
+/*!
+ \qmlproperty SomeModel VPieModelMapper::model
+ The QAbstractItemModel based model that is used by the mapper. You need to implement the model
+ and expose it to QML. Note: the model has to support adding/removing rows/columns and modifying
+ the data of the cells.
+*/
+
+/*!
+ \property QVPieModelMapper::valuesColumn
+ \brief Defines which column of the model is kept in sync with the values of the pie's slices.
+
+ Default value is: -1 (invalid mapping)
+*/
+/*!
+ \qmlproperty int VPieModelMapper::valuesColumn
+ Defines which column of the model is kept in sync with the values of the pie's slices. Default value is -1 (invalid
+ mapping).
+*/
+
+/*!
+ \property QVPieModelMapper::labelsColumn
+ \brief Defines which column of the model is kept in sync with the labels of the pie's slices.
+
+ Default value is: -1 (invalid mapping)
+*/
+/*!
+ \qmlproperty int VPieModelMapper::labelsColumn
+ Defines which column of the model is kept in sync with the labels of the pie's slices. Default value is -1 (invalid
+ mapping).
+*/
+
+/*!
+ \property QVPieModelMapper::firstRow
+ \brief Defines which row of the model contains the first slice value.
+
+ Minimal and default value is: 0
+*/
+/*!
+ \qmlproperty int VPieModelMapper::firstRow
+ Defines which row of the model contains the first slice value.
+ The default value is 0.
+*/
+
+/*!
+ \property QVPieModelMapper::rowCount
+ \brief Defines the number of rows of the model that are mapped as the data for QPieSeries.
+
+ Minimal and default value is: -1 (count limited by the number of rows in the model)
+*/
+/*!
+ \qmlproperty int VPieModelMapper::columnCount
+ Defines the number of rows of the model that are mapped as the data for QPieSeries. The default value is
+ -1 (count limited by the number of rows in the model)
+*/
+
+/*!
+ \fn void QVPieModelMapper::seriesReplaced()
+
+ Emitted when the series to which mapper is connected to has changed.
+*/
+
+/*!
+ \fn void QVPieModelMapper::modelReplaced()
+
+ Emitted when the model to which mapper is connected to has changed.
+*/
+
+/*!
+ \fn void QVPieModelMapper::valuesColumnChanged()
+
+ Emitted when the valuesColumn has changed.
+*/
+
+/*!
+ \fn void QVPieModelMapper::labelsColumnChanged()
+
+ Emitted when the labelsColumn has changed.
+*/
+
+/*!
+ \fn void QVPieModelMapper::firstRowChanged()
+ Emitted when the firstRow has changed.
+*/
+
+/*!
+ \fn void QVPieModelMapper::rowCountChanged()
+ Emitted when the rowCount has changed.
+*/
+
+/*!
+ Constructs a mapper object which is a child of \a parent.
+*/
+QVPieModelMapper::QVPieModelMapper(QObject *parent) :
+ QPieModelMapper(parent)
+{
+ QPieModelMapper::setOrientation(Qt::Vertical);
+}
+
+QAbstractItemModel *QVPieModelMapper::model() const
+{
+ return QPieModelMapper::model();
+}
+
+void QVPieModelMapper::setModel(QAbstractItemModel *model)
+{
+ if (model != QPieModelMapper::model()) {
+ QPieModelMapper::setModel(model);
+ emit modelReplaced();
+ }
+}
+
+QPieSeries *QVPieModelMapper::series() const
+{
+ return QPieModelMapper::series();
+}
+
+void QVPieModelMapper::setSeries(QPieSeries *series)
+{
+ if (series != QPieModelMapper::series()) {
+ QPieModelMapper::setSeries(series);
+ emit seriesReplaced();
+ }
+}
+
+/*!
+ Returns which column of the model is kept in sync with the values of the pie's slices
+*/
+int QVPieModelMapper::valuesColumn() const
+{
+ return QPieModelMapper::valuesSection();
+}
+
+/*!
+ Sets the model column that is kept in sync with the pie slices values.
+ Parameter \a valuesColumn specifies the row of the model.
+*/
+void QVPieModelMapper::setValuesColumn(int valuesColumn)
+{
+ if (valuesColumn != valuesSection()) {
+ QPieModelMapper::setValuesSection(valuesColumn);
+ emit valuesColumnChanged();
+ }
+}
+
+/*!
+ Returns which column of the model is kept in sync with the labels of the pie's slices
+*/
+int QVPieModelMapper::labelsColumn() const
+{
+ return QPieModelMapper::labelsSection();
+}
+
+/*!
+ Sets the model column that is kept in sync with the pie's slices labels.
+ Parameter \a labelsColumn specifies the row of the model.
+*/
+void QVPieModelMapper::setLabelsColumn(int labelsColumn)
+{
+ if (labelsColumn != labelsSection()) {
+ QPieModelMapper::setLabelsSection(labelsColumn);
+ emit labelsColumnChanged();
+ }
+}
+
+int QVPieModelMapper::firstRow() const
+{
+ return first();
+}
+
+void QVPieModelMapper::setFirstRow(int firstRow)
+{
+ if (firstRow != first()) {
+ setFirst(firstRow);
+ emit firstRowChanged();
+ }
+}
+
+int QVPieModelMapper::rowCount() const
+{
+ return count();
+}
+
+void QVPieModelMapper::setRowCount(int rowCount)
+{
+ if (rowCount != count()) {
+ setCount(rowCount);
+ emit rowCountChanged();
+ }
+}
+
+#include "moc_qvpiemodelmapper.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/piechart/qvpiemodelmapper.h b/src/charts/piechart/qvpiemodelmapper.h
new file mode 100644
index 00000000..2135ff9b
--- /dev/null
+++ b/src/charts/piechart/qvpiemodelmapper.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVPIEMODELMAPPER_H
+#define QVPIEMODELMAPPER_H
+
+#include <QtCharts/qpiemodelmapper.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+/* Comment line for syncqt to generate the fwd-include correctly, due to QTBUG-22432 */
+class QT_CHARTS_EXPORT QVPieModelMapper : public QPieModelMapper
+{
+ Q_OBJECT
+ Q_PROPERTY(QPieSeries *series READ series WRITE setSeries NOTIFY seriesReplaced)
+ Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelReplaced)
+ Q_PROPERTY(int valuesColumn READ valuesColumn WRITE setValuesColumn NOTIFY valuesColumnChanged)
+ Q_PROPERTY(int labelsColumn READ labelsColumn WRITE setLabelsColumn NOTIFY labelsColumnChanged)
+ Q_PROPERTY(int firstRow READ firstRow WRITE setFirstRow NOTIFY firstRowChanged)
+ Q_PROPERTY(int rowCount READ rowCount WRITE setRowCount NOTIFY rowCountChanged)
+
+public:
+ explicit QVPieModelMapper(QObject *parent = 0);
+
+ QAbstractItemModel *model() const;
+ void setModel(QAbstractItemModel *model);
+
+ QPieSeries *series() const;
+ void setSeries(QPieSeries *series);
+
+ int valuesColumn() const;
+ void setValuesColumn(int valuesColumn);
+
+ int labelsColumn() const;
+ void setLabelsColumn(int labelsColumn);
+
+ int firstRow() const;
+ void setFirstRow(int firstRow);
+
+ int rowCount() const;
+ void setRowCount(int rowCount);
+
+Q_SIGNALS:
+ void seriesReplaced();
+ void modelReplaced();
+ void valuesColumnChanged();
+ void labelsColumnChanged();
+ void firstRowChanged();
+ void rowCountChanged();
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QVPIEMODELMAPPER_H
diff --git a/src/charts/qabstractseries.cpp b/src/charts/qabstractseries.cpp
new file mode 100644
index 00000000..1db799f2
--- /dev/null
+++ b/src/charts/qabstractseries.cpp
@@ -0,0 +1,328 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qabstractseries.h"
+#include "qabstractseries_p.h"
+#include "chartdataset_p.h"
+#include "qchart.h"
+#include "qchart_p.h"
+#include "chartitem_p.h"
+#include "xydomain_p.h"
+#include "xlogydomain_p.h"
+#include "logxydomain_p.h"
+#include "logxlogydomain_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QAbstractSeries
+ \inmodule Qt Charts
+ \brief Base class for all Qt Chart series.
+ \mainclass
+
+ Usually you use the series type specific inherited classes instead of the base class.
+ \sa QXYSeries, QLineSeries, QSplineSeries, QScatterSeries, QAreaSeries, QAbstractBarSeries, QStackedBarSeries,
+ QPercentBarSeries, QPieSeries
+*/
+/*!
+ \qmltype AbstractSeries
+ \instantiates QAbstractSeries
+ \inqmlmodule QtCharts
+
+ \brief Base class for all Qt Chart series.
+
+ AbstractSeries is the base class for all series.
+ The class cannot be instantiated by the user.
+*/
+
+/*!
+ \enum QAbstractSeries::SeriesType
+
+ The type of the series object.
+
+ \value SeriesTypeLine
+ \value SeriesTypeArea
+ \value SeriesTypeBar
+ \value SeriesTypeStackedBar
+ \value SeriesTypePercentBar
+ \value SeriesTypePie
+ \value SeriesTypeScatter
+ \value SeriesTypeSpline
+ \value SeriesTypeHorizontalBar
+ \value SeriesTypeHorizontalStackedBar
+ \value SeriesTypeHorizontalPercentBar
+ \value SeriesTypeBoxPlot
+*/
+
+/*!
+ \property QAbstractSeries::type
+ The type of the series.
+*/
+/*!
+ \qmlproperty ChartView.SeriesType AbstractSeries::type
+ The type of the series.
+*/
+
+/*!
+ \property QAbstractSeries::name
+ \brief name of the series property. The name is shown in legend for series and supports html formatting.
+*/
+/*!
+ \qmlproperty string AbstractSeries::name
+ Name of the series. The name is shown in legend for series and supports html formatting.
+*/
+
+/*!
+ \fn void QAbstractSeries::nameChanged()
+ This signal is emitted when the series name changes.
+*/
+/*!
+ \qmlsignal AbstractSeries::onNameChanged()
+ This signal is emitted when the series name changes.
+*/
+
+/*!
+ \property QAbstractSeries::visible
+ \brief whether the series is visible or not; true by default.
+*/
+/*!
+ \qmlproperty bool AbstractSeries::visible
+ Visibility of the series. True by default.
+*/
+
+/*!
+ \fn void QAbstractSeries::visibleChanged()
+ Emitted when the series visibility changes.
+*/
+/*!
+ \qmlsignal AbstractSeries::onVisibleChanged()
+ Emitted when the series visibility changes.
+*/
+
+/*!
+ \property QAbstractSeries::opacity
+ \brief The opacity of the series.
+
+ By default the opacity is 1.0. The valid values range from 0.0 (transparent) to 1.0 (opaque).
+*/
+/*!
+ \qmlproperty real AbstractSeries::opacity
+ The opacity of the series. By default the opacity is 1.0.
+ The valid values range from 0.0 (transparent) to 1.0 (opaque).
+*/
+
+/*!
+ \fn void QAbstractSeries::opacityChanged()
+ Emitted when the opacity of the series changes.
+*/
+/*!
+ \qmlsignal AbstractSeries::onOpacityChanged()
+ Emitted when the opacity of the series changes.
+*/
+
+/*!
+ \internal
+ \brief Constructs QAbstractSeries object with \a parent.
+*/
+QAbstractSeries::QAbstractSeries(QAbstractSeriesPrivate &d, QObject *parent) :
+ QObject(parent),
+ d_ptr(&d)
+{
+}
+
+/*!
+ \brief Virtual destructor for the chart series.
+*/
+QAbstractSeries::~QAbstractSeries()
+{
+ if (d_ptr->m_chart)
+ qFatal("Series still bound to a chart when destroyed!");
+}
+
+void QAbstractSeries::setName(const QString &name)
+{
+ if (name != d_ptr->m_name) {
+ d_ptr->m_name = name;
+ emit nameChanged();
+ }
+}
+
+QString QAbstractSeries::name() const
+{
+ return d_ptr->m_name;
+}
+
+void QAbstractSeries::setVisible(bool visible)
+{
+ if (visible != d_ptr->m_visible) {
+ d_ptr->m_visible = visible;
+ emit visibleChanged();
+ }
+}
+
+bool QAbstractSeries::isVisible() const
+{
+ return d_ptr->m_visible;
+}
+
+qreal QAbstractSeries::opacity() const
+{
+ return d_ptr->m_opacity;
+}
+
+void QAbstractSeries::setOpacity(qreal opacity)
+{
+ if (opacity != d_ptr->m_opacity) {
+ d_ptr->m_opacity = opacity;
+ emit opacityChanged();
+ }
+}
+
+/*!
+ \brief Returns the chart where series belongs to.
+
+ Set automatically when the series is added to the chart
+ and unset when the series is removed from the chart.
+*/
+QChart *QAbstractSeries::chart() const
+{
+ return d_ptr->m_chart;
+}
+
+/*!
+ \brief Sets the visibility of the series to true.
+
+ \sa setVisible(), isVisible()
+*/
+void QAbstractSeries::show()
+{
+ setVisible(true);
+}
+
+/*!
+ \brief Sets the visibility of the series to false.
+
+ \sa setVisible(), isVisible()
+*/
+void QAbstractSeries::hide()
+{
+ setVisible(false);
+}
+
+/*!
+ Attach \a axis to the series.
+ \return true if the axis was attached successfully, false otherwise.
+ \note If multiple axes of same orientation are attached to same series,
+ they will have same min/max ranges.
+ \sa QChart::addAxis(), QChart::createDefaultAxes()
+ */
+bool QAbstractSeries::attachAxis(QAbstractAxis* axis)
+{
+ if(d_ptr->m_chart) {
+ return d_ptr->m_chart->d_ptr->m_dataset->attachAxis(this, axis);
+ } else {
+ qWarning()<<"Series not in the chart. Please addSeries to chart first.";
+ return false;
+ }
+}
+
+/*!
+ Detach \a axis from the series.
+ \return true if the axis was detached successfully, false otherwise.
+ \sa QChart::removeAxis()
+ */
+bool QAbstractSeries::detachAxis(QAbstractAxis* axis)
+{
+ if(d_ptr->m_chart) {
+ return d_ptr->m_chart->d_ptr->m_dataset->detachAxis(this, axis);
+ }
+ else {
+ qWarning()<<"Series not in the chart. Please addSeries to chart first.";
+ return false;
+ }
+}
+
+/*!
+ Returns the list of axes attached to the series. Usually there is an x-axis and a y-axis attached to a series, except
+ in case of a QPieSeries, which does not have any axes attached.
+ \sa attachAxis(), detachAxis()
+ */
+QList<QAbstractAxis*> QAbstractSeries::attachedAxes()
+{
+ return d_ptr->m_axes;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+QAbstractSeriesPrivate::QAbstractSeriesPrivate(QAbstractSeries *q)
+ : q_ptr(q),
+ m_chart(0),
+ m_item(0),
+ m_domain(new XYDomain()),
+ m_visible(true),
+ m_opacity(1.0)
+{
+}
+
+QAbstractSeriesPrivate::~QAbstractSeriesPrivate()
+{
+}
+
+void QAbstractSeriesPrivate::setDomain(AbstractDomain* domain)
+{
+ Q_ASSERT(domain);
+ if(m_domain.data()!=domain) {
+ if(!m_item.isNull()) QObject::disconnect(m_domain.data(), SIGNAL(updated()), m_item.data(), SLOT(handleDomainUpdated()));
+ m_domain.reset(domain);
+ if(!m_item.isNull()) {
+ QObject::connect(m_domain.data(), SIGNAL(updated()),m_item.data(), SLOT(handleDomainUpdated()));
+ m_item->handleDomainUpdated();
+ }
+ }
+}
+
+void QAbstractSeriesPrivate::setPresenter(ChartPresenter *presenter)
+{
+ m_presenter = presenter;
+}
+
+ChartPresenter *QAbstractSeriesPrivate::presenter() const
+{
+ return m_presenter;
+}
+
+void QAbstractSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
+{
+ Q_ASSERT(!m_item.isNull());
+ Q_UNUSED(parent);
+ QObject::connect(m_domain.data(), SIGNAL(updated()),m_item.data(), SLOT(handleDomainUpdated()));
+}
+
+void QAbstractSeriesPrivate::initializeAnimations(QChart::AnimationOptions options)
+{
+ Q_UNUSED(options);
+}
+
+#include "moc_qabstractseries.cpp"
+#include "moc_qabstractseries_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
+
+
diff --git a/src/charts/qabstractseries.h b/src/charts/qabstractseries.h
new file mode 100644
index 00000000..43e726ac
--- /dev/null
+++ b/src/charts/qabstractseries.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTSERIES_H
+#define QABSTRACTSERIES_H
+
+#include <QtCharts/qchartglobal.h>
+#include <QtCharts/qabstractaxis.h>
+#include <QObject>
+#include <QPen>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QAbstractSeriesPrivate;
+class QChart;
+
+class QT_CHARTS_EXPORT QAbstractSeries : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+ Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged)
+ Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged)
+ Q_PROPERTY(SeriesType type READ type)
+ Q_ENUMS(SeriesType)
+
+public:
+ enum SeriesType {
+ SeriesTypeLine,
+ SeriesTypeArea,
+ SeriesTypeBar,
+ SeriesTypeStackedBar,
+ SeriesTypePercentBar,
+ SeriesTypePie,
+ SeriesTypeScatter,
+ SeriesTypeSpline,
+ SeriesTypeHorizontalBar,
+ SeriesTypeHorizontalStackedBar,
+ SeriesTypeHorizontalPercentBar,
+ SeriesTypeBoxPlot
+ };
+
+protected:
+ QAbstractSeries(QAbstractSeriesPrivate &d, QObject *parent = 0);
+
+public:
+ ~QAbstractSeries();
+ virtual SeriesType type() const = 0;
+
+ void setName(const QString &name);
+ QString name() const;
+ void setVisible(bool visible = true);
+ bool isVisible() const;
+ qreal opacity() const;
+ void setOpacity(qreal opacity);
+
+ QChart *chart() const;
+
+ bool attachAxis(QAbstractAxis *axis);
+ bool detachAxis(QAbstractAxis *axis);
+ QList<QAbstractAxis*> attachedAxes();
+
+ void show();
+ void hide();
+
+Q_SIGNALS:
+ void nameChanged();
+ void visibleChanged();
+ void opacityChanged();
+
+protected:
+ QScopedPointer<QAbstractSeriesPrivate> d_ptr;
+ friend class ChartDataSet;
+ friend class ChartPresenter;
+ friend class ChartThemeManager;
+ friend class QLegendPrivate;
+ friend class DeclarativeChart;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QABSTRACTSERIES_H
diff --git a/src/charts/qabstractseries_p.h b/src/charts/qabstractseries_p.h
new file mode 100644
index 00000000..3668829d
--- /dev/null
+++ b/src/charts/qabstractseries_p.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QABSTRACTSERIES_P_H
+#define QABSTRACTSERIES_P_H
+
+#include "qabstractseries.h"
+#include "qchart.h"
+#include "abstractdomain_p.h"
+
+class QGraphicsItem;
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class ChartPresenter;
+class ChartElement;
+class LegendMarker;
+class QLegend;
+class ChartDataSet;
+class QAbstractAxis;
+class QLegendMarker;
+class ChartTheme;
+class ChartAnimation;
+class ChartItem;
+class BoxPlotChartItem;
+
+class QAbstractSeriesPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QAbstractSeriesPrivate(QAbstractSeries *q);
+ ~QAbstractSeriesPrivate();
+
+ virtual void initializeDomain() = 0;
+ virtual void initializeAxes() = 0;
+ virtual void initializeTheme(int index, ChartTheme* theme, bool forced = false) = 0;
+ virtual void initializeGraphics(QGraphicsItem* parent) = 0;
+ virtual void initializeAnimations(QChart::AnimationOptions options) = 0;
+
+ virtual QList<QLegendMarker*> createLegendMarkers(QLegend* legend) = 0;
+
+ virtual QAbstractAxis::AxisType defaultAxisType(Qt::Orientation) const = 0;
+ virtual QAbstractAxis* createDefaultAxis(Qt::Orientation) const = 0;
+
+ ChartItem* chartItem() { return m_item.data(); }
+
+ virtual void setDomain(AbstractDomain* domain);
+ AbstractDomain* domain() { return m_domain.data(); }
+
+ virtual void setPresenter(ChartPresenter *presenter);
+ ChartPresenter *presenter() const;
+
+ QChart* chart() { return m_chart; }
+
+Q_SIGNALS:
+ void countChanged();
+
+protected:
+ QAbstractSeries *q_ptr;
+ QChart *m_chart;
+ QScopedPointer<ChartItem> m_item;
+ QList<QAbstractAxis*> m_axes;
+private:
+ QScopedPointer<AbstractDomain> m_domain;
+ QString m_name;
+ bool m_visible;
+ qreal m_opacity;
+ ChartPresenter *m_presenter;
+
+ friend class QAbstractSeries;
+ friend class ChartDataSet;
+ friend class ChartPresenter;
+ friend class QLegendPrivate;
+ friend class BoxPlotChartItem;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/qchart.cpp b/src/charts/qchart.cpp
new file mode 100644
index 00000000..9f26ffee
--- /dev/null
+++ b/src/charts/qchart.cpp
@@ -0,0 +1,872 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qchart.h"
+#include "qchart_p.h"
+#include "legendscroller_p.h"
+#include "qlegend_p.h"
+#include "chartbackground_p.h"
+#include "qabstractaxis.h"
+#include "abstractchartlayout_p.h"
+#include "charttheme_p.h"
+#include "chartpresenter_p.h"
+#include "chartdataset_p.h"
+#include <QGraphicsScene>
+#include <QGraphicsSceneResizeEvent>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \enum QChart::ChartTheme
+
+ This enum describes the theme used by the chart.
+
+ \value ChartThemeLight The default theme
+ \value ChartThemeBlueCerulean
+ \value ChartThemeDark
+ \value ChartThemeBrownSand
+ \value ChartThemeBlueNcs
+ \value ChartThemeHighContrast
+ \value ChartThemeBlueIcy
+ \value ChartThemeQt
+ */
+
+/*!
+ \enum QChart::AnimationOption
+
+ For enabling/disabling animations. Defaults to NoAnimation.
+
+ \value NoAnimation
+ \value GridAxisAnimations
+ \value SeriesAnimations
+ \value AllAnimations
+ */
+
+/*!
+ \enum QChart::ChartType
+
+ This enum describes the chart type.
+
+ \value ChartTypeUndefined
+ \value ChartTypeCartesian
+ \value ChartTypePolar
+ */
+
+/*!
+ \class QChart
+ \inmodule Qt Charts
+ \brief Main chart API for Qt Charts.
+
+ QChart is a QGraphicsWidget that you can show in a QGraphicsScene. It manages the graphical
+ representation of different types of series and other chart related objects like legend and
+ axes. If you simply want to show a chart in a layout, you can use the
+ convenience class QChartView instead of QChart.
+ \sa QChartView, QPolarChart
+ */
+
+/*!
+ \property QChart::animationOptions
+ The animation \a options for the chart. Animations are enabled/disabled based on this setting.
+ */
+
+/*!
+ \property QChart::backgroundVisible
+ Specifies whether the chart background is visible or not.
+ \sa setBackgroundBrush(), setBackgroundPen(), plotAreaBackgroundVisible
+ */
+
+/*!
+ \property QChart::dropShadowEnabled
+ If set to true, the background drop shadow effect is enabled. If set to false, it is disabled. Note that the drop
+ shadow effect depends on theme, which means the setting may be changed if you switch to another theme.
+ */
+
+/*!
+ \property QChart::backgroundRoundness
+ The diameter of the rounding cirle at the corners of the chart background.
+ */
+
+/*!
+ \property QChart::minimumMargins
+ Minimum margins between the plot area (axes) and the edge of the chart widget.
+ This property is deprecated; use margins property instead.
+
+ \sa margins
+ */
+
+/*!
+ \property QChart::margins
+ Margins between the plot area (axes) and the edge of the chart widget.
+ */
+
+/*!
+ \property QChart::theme
+ Theme is a built-in collection of UI style related settings applied for all visual elements of a chart, like colors,
+ pens, brushes, and fonts of series, axes, title, and legend. \l {Chart themes example} shows an example with a few
+ different themes.
+ \note Changing the theme will overwrite all customizations previously applied to the series.
+ */
+
+/*!
+ \property QChart::title
+ Title is the name (label) of a chart. It is shown as a headline on top of the chart. Chart title supports html formatting.
+ */
+
+/*!
+ \property QChart::chartType
+ Chart type indicates if the chart is a cartesian chart or a polar chart.
+ This property is set internally and it is read only.
+ \sa QPolarChart
+ */
+
+/*!
+ \property QChart::plotAreaBackgroundVisible
+ Specifies whether the chart plot area background is visible or not.
+ \note By default the plot area background is not visible and the plot area uses
+ the general chart background.
+ \sa setPlotAreaBackgroundBrush(), setPlotAreaBackgroundPen(), backgroundVisible
+ */
+
+/*!
+ \property QChart::localizeNumbers
+ \since QtCharts 2.0
+ When \c{true}, all generated numbers appearing in various series and axis labels will be
+ localized using the QLocale set with the locale property.
+ When \c{false}, the "C" locale is always used.
+ Defaults to \c{false}.
+ \note This property doesn't affect QDateTimeAxis labels, which always use the QLocale set with
+ the locale property.
+
+ \sa locale
+*/
+
+/*!
+ \property QChart::locale
+ \since QtCharts 2.0
+ Sets the locale used to format various chart labels when localizeNumbers is \c{true}.
+ This also determines the locale used to format QDateTimeAxis labels regardless of
+ localizeNumbers property.
+ Defaults to application default locale at the time the chart is constructed.
+
+ \sa localizeNumbers
+*/
+
+/*!
+ \internal
+ Constructs a chart object of \a type which is a child of a \a parent.
+ Parameter \a wFlags is passed to the QGraphicsWidget constructor.
+ This constructor is called only by subclasses.
+*/
+QChart::QChart(QChart::ChartType type, QGraphicsItem *parent, Qt::WindowFlags wFlags)
+ : QGraphicsWidget(parent, wFlags),
+ d_ptr(new QChartPrivate(this, type))
+{
+ d_ptr->init();
+}
+
+/*!
+ Constructs a chart object which is a child of a \a parent.
+ Parameter \a wFlags is passed to the QGraphicsWidget constructor.
+ */
+QChart::QChart(QGraphicsItem *parent, Qt::WindowFlags wFlags)
+ : QGraphicsWidget(parent, wFlags),
+ d_ptr(new QChartPrivate(this, ChartTypeCartesian))
+{
+ d_ptr->init();
+}
+
+/*!
+ Destroys the chart object and its children, like series and axis objects added to it.
+ */
+QChart::~QChart()
+{
+ //start by deleting dataset, it will remove all series and axes
+ delete d_ptr->m_dataset;
+ d_ptr->m_dataset = 0;
+}
+
+/*!
+ Adds the \a series onto the chart and takes the ownership of it.
+
+ \note A newly added series is attached to no axes by default, including any axes that were created for the chart
+ using createDefaultAxes() before the series was added to the chart. If no axes are attached to
+ the newly added series before the chart is shown, the series will get drawn as if it had axes with ranges
+ that exactly fit the series to the plot area of the chart. This can be confusing if the same chart also displays other
+ series that have properly attached axes, so always make sure you either call createDefaultAxes() after
+ a series has been added or explicitly attach axes for the series.
+
+ \sa removeSeries(), removeAllSeries(), createDefaultAxes(), QAbstractSeries::attachAxis()
+ */
+void QChart::addSeries(QAbstractSeries *series)
+{
+ Q_ASSERT(series);
+ d_ptr->m_dataset->addSeries(series);
+}
+
+/*!
+ Removes the \a series from the chart.
+ The chart releases its ownership of the specified \a series object.
+
+ \sa addSeries(), removeAllSeries()
+ */
+void QChart::removeSeries(QAbstractSeries *series)
+{
+ Q_ASSERT(series);
+ d_ptr->m_dataset->removeSeries(series);
+}
+
+/*!
+ Removes and deletes all series objects that have been added to the chart.
+
+ \sa addSeries(), removeSeries()
+ */
+void QChart::removeAllSeries()
+{
+ foreach (QAbstractSeries *s , d_ptr->m_dataset->series()){
+ removeSeries(s);
+ delete s;
+ }
+}
+
+/*!
+ Sets the \a brush that is used for painting the background of the chart area.
+ */
+void QChart::setBackgroundBrush(const QBrush &brush)
+{
+ d_ptr->m_presenter->setBackgroundBrush(brush);
+}
+
+/*!
+ Gets the brush that is used for painting the background of the chart area.
+ */
+QBrush QChart::backgroundBrush() const
+{
+ return d_ptr->m_presenter->backgroundBrush();
+}
+
+/*!
+ Sets the \a pen that is used for painting the background of the chart area.
+ */
+void QChart::setBackgroundPen(const QPen &pen)
+{
+ d_ptr->m_presenter->setBackgroundPen(pen);
+}
+
+/*!
+ Gets the pen that is used for painting the background of the chart area.
+ */
+QPen QChart::backgroundPen() const
+{
+ return d_ptr->m_presenter->backgroundPen();
+}
+
+void QChart::setTitle(const QString &title)
+{
+ d_ptr->m_presenter->setTitle(title);
+}
+
+QString QChart::title() const
+{
+ return d_ptr->m_presenter->title();
+}
+
+/*!
+ Sets the \a font that is used for drawing the chart title.
+ */
+void QChart::setTitleFont(const QFont &font)
+{
+ d_ptr->m_presenter->setTitleFont(font);
+}
+
+/*!
+ Gets the font that is used for drawing the chart title.
+ */
+QFont QChart::titleFont() const
+{
+ return d_ptr->m_presenter->titleFont();
+}
+
+/*!
+ Sets the \a brush used for drawing the title text.
+ */
+void QChart::setTitleBrush(const QBrush &brush)
+{
+ d_ptr->m_presenter->setTitleBrush(brush);
+}
+
+/*!
+ Returns the brush used for drawing the title text.
+ */
+QBrush QChart::titleBrush() const
+{
+ return d_ptr->m_presenter->titleBrush();
+}
+
+void QChart::setTheme(QChart::ChartTheme theme)
+{
+ d_ptr->m_themeManager->setTheme(theme);
+}
+
+QChart::ChartTheme QChart::theme() const
+{
+ return d_ptr->m_themeManager->theme()->id();
+}
+
+/*!
+ Zooms in the view by a factor of two.
+ */
+void QChart::zoomIn()
+{
+ d_ptr->zoomIn(2.0);
+}
+
+/*!
+ Zooms in the view to a maximum level at which \a rect is still fully visible.
+ \note This is not supported for polar charts.
+ */
+void QChart::zoomIn(const QRectF &rect)
+{
+ if (d_ptr->m_type == QChart::ChartTypePolar)
+ return;
+ d_ptr->zoomIn(rect);
+}
+
+/*!
+ Zooms out the view by a factor of two.
+ */
+void QChart::zoomOut()
+{
+ d_ptr->zoomOut(2.0);
+}
+
+/*!
+ Zooms in the view by a custom \a factor.
+
+ A factor over 1.0 zooms the view in and factor between 0.0 and 1.0 zooms out.
+ */
+void QChart::zoom(qreal factor)
+{
+ if (qFuzzyCompare(factor, 0))
+ return;
+
+ if (qFuzzyCompare(factor, (qreal)1.0))
+ return;
+
+ if (factor < 0)
+ return;
+
+ if (factor > 1.0)
+ d_ptr->zoomIn(factor);
+ else
+ d_ptr->zoomOut(1.0 / factor);
+}
+
+
+/*!
+ Resets the series domains to what they were before any zoom method was called.
+ Note that this will also reset any scrolls and explicit axis range settings done between
+ the first zoom operation and calling this method. If no zoom operation has been
+ done, this method does nothing.
+ */
+void QChart::zoomReset()
+{
+ d_ptr->zoomReset();
+}
+
+/*!
+ Returns true if any series has a zoomed domain.
+ */
+bool QChart::isZoomed()
+{
+ return d_ptr->isZoomed();
+}
+
+/*!
+ Returns a pointer to the horizontal axis attached to the specified \a series.
+ If no \a series is specified, the first horizontal axis added to the chart is returned.
+
+ \sa addAxis(), QAbstractSeries::attachAxis()
+ */
+QAbstractAxis *QChart::axisX(QAbstractSeries *series) const
+{
+ QList<QAbstractAxis *> axisList = axes(Qt::Horizontal, series);
+ if (axisList.count())
+ return axisList[0];
+ return 0;
+}
+
+/*!
+ Returns a pointer to the vertical axis attached to the specified \a series.
+ If no \a series is specified, the first vertical axis added to the chart is returned.
+
+ \sa addAxis(), QAbstractSeries::attachAxis()
+ */
+QAbstractAxis *QChart::axisY(QAbstractSeries *series) const
+{
+ QList<QAbstractAxis *> axisList = axes(Qt::Vertical, series);
+ if (axisList.count())
+ return axisList[0];
+ return 0;
+}
+
+/*!
+ Returns the axes attached to the \a series with \a orientation. If no \a series is provided,
+ then all axes added to the chart with the specified orientation are returned.
+ \sa addAxis(), createDefaultAxes()
+ */
+QList<QAbstractAxis *> QChart::axes(Qt::Orientations orientation, QAbstractSeries *series) const
+{
+ QList<QAbstractAxis *> result ;
+
+ if (series) {
+ foreach (QAbstractAxis *axis, series->attachedAxes()){
+ if (orientation.testFlag(axis->orientation()))
+ result << axis;
+ }
+ } else {
+ foreach (QAbstractAxis *axis, d_ptr->m_dataset->axes()){
+ if (orientation.testFlag(axis->orientation()) && !result.contains(axis))
+ result << axis;
+ }
+ }
+
+ return result;
+}
+
+/*!
+ Creates axes for the chart based on the series that have already been added to the chart. Any axes previously added to
+ the chart will be deleted.
+
+ \note This function has to be called after all series have been added to the chart. The axes created by this function
+ will NOT get automatically attached to any series added to the chart after this function has been called.
+ A series with no axes attached will by default scale to utilize the entire plot area of the chart, which can be confusing
+ if there are other series with properly attached axes also present.
+
+ \table
+ \header
+ \li Series type
+ \li X-axis
+ \li Y-axis
+ \row
+ \li QXYSeries
+ \li QValueAxis
+ \li QValueAxis
+ \row
+ \li QBarSeries
+ \li QBarCategoryAxis
+ \li QValueAxis
+ \row
+ \li QPieSeries
+ \li None
+ \li None
+ \endtable
+
+ If there are several QXYSeries derived series added to the chart and no series of other types have been added, then only one pair of axes is created.
+ If there are several series of different types added to the chart, then each series gets its own axes pair.
+
+ The axes specific to the series can be later obtained from the chart by providing the series as the parameter for axes() function call.
+ QPieSeries does not create any axes.
+
+ \sa axisX(), axisY(), axes(), setAxisX(), setAxisY(), QAbstractSeries::attachAxis()
+ */
+void QChart::createDefaultAxes()
+{
+ d_ptr->m_dataset->createDefaultAxes();
+}
+
+/*!
+ Returns the legend object of the chart. Ownership stays with the chart.
+ */
+QLegend *QChart::legend() const
+{
+ return d_ptr->m_legend;
+}
+
+void QChart::setMinimumMargins(const QMargins &margins)
+{
+ qWarning() << "QChart::setMinimumMargins is deprecated. Use QChart::setMargins instead.";
+ d_ptr->m_presenter->layout()->setMargins(margins);
+}
+
+QMargins QChart::minimumMargins() const
+{
+ qWarning() << "QChart::minimumMargins is deprecated. Use QChart::margins instead.";
+ return d_ptr->m_presenter->layout()->margins();
+}
+
+void QChart::setMargins(const QMargins &margins)
+{
+ d_ptr->m_presenter->layout()->setMargins(margins);
+}
+
+QMargins QChart::margins() const
+{
+ return d_ptr->m_presenter->layout()->margins();
+}
+
+QChart::ChartType QChart::chartType() const
+{
+ return d_ptr->m_type;
+}
+
+/*!
+ Returns the the rectangle within which the drawing of the chart is done.
+ It does not include the area defined by margins.
+ */
+QRectF QChart::plotArea() const
+{
+ return d_ptr->m_presenter->geometry();
+}
+
+/*!
+ Sets the \a brush for the background of the plot area of the chart.
+
+ \sa plotArea(), plotAreaBackgroundVisible, setPlotAreaBackgroundPen(), plotAreaBackgroundBrush()
+ */
+void QChart::setPlotAreaBackgroundBrush(const QBrush &brush)
+{
+ d_ptr->m_presenter->setPlotAreaBackgroundBrush(brush);
+}
+
+/*!
+ Returns the brush for the background of the plot area of the chart.
+
+ \sa plotArea(), plotAreaBackgroundVisible, plotAreaBackgroundPen(), setPlotAreaBackgroundBrush()
+ */
+QBrush QChart::plotAreaBackgroundBrush() const
+{
+ return d_ptr->m_presenter->plotAreaBackgroundBrush();
+}
+
+/*!
+ Sets the \a pen for the background of the plot area of the chart.
+
+ \sa plotArea(), plotAreaBackgroundVisible, setPlotAreaBackgroundBrush(), plotAreaBackgroundPen()
+ */
+void QChart::setPlotAreaBackgroundPen(const QPen &pen)
+{
+ d_ptr->m_presenter->setPlotAreaBackgroundPen(pen);
+}
+
+/*!
+ Returns the pen for the background of the plot area of the chart.
+
+ \sa plotArea(), plotAreaBackgroundVisible, plotAreaBackgroundBrush(), setPlotAreaBackgroundPen()
+ */
+QPen QChart::plotAreaBackgroundPen() const
+{
+ return d_ptr->m_presenter->plotAreaBackgroundPen();
+}
+
+void QChart::setPlotAreaBackgroundVisible(bool visible)
+{
+ d_ptr->m_presenter->setPlotAreaBackgroundVisible(visible);
+}
+
+bool QChart::isPlotAreaBackgroundVisible() const
+{
+ return d_ptr->m_presenter->isPlotAreaBackgroundVisible();
+}
+
+void QChart::setLocalizeNumbers(bool localize)
+{
+ d_ptr->m_presenter->setLocalizeNumbers(localize);
+}
+
+bool QChart::localizeNumbers() const
+{
+ return d_ptr->m_presenter->localizeNumbers();
+}
+
+void QChart::setLocale(const QLocale &locale)
+{
+ d_ptr->m_presenter->setLocale(locale);
+}
+
+QLocale QChart::locale() const
+{
+ return d_ptr->m_presenter->locale();
+}
+
+void QChart::setAnimationOptions(AnimationOptions options)
+{
+ d_ptr->m_presenter->setAnimationOptions(options);
+}
+
+QChart::AnimationOptions QChart::animationOptions() const
+{
+ return d_ptr->m_presenter->animationOptions();
+}
+
+/*!
+ Scrolls the visible area of the chart by the distance defined in the \a dx and \a dy.
+
+ For polar charts, \a dx indicates the angle along angular axis instead of distance.
+ */
+void QChart::scroll(qreal dx, qreal dy)
+{
+ d_ptr->scroll(dx,dy);
+}
+
+void QChart::setBackgroundVisible(bool visible)
+{
+ d_ptr->m_presenter->setBackgroundVisible(visible);
+}
+
+bool QChart::isBackgroundVisible() const
+{
+ return d_ptr->m_presenter->isBackgroundVisible();
+}
+
+void QChart::setDropShadowEnabled(bool enabled)
+{
+ d_ptr->m_presenter->setBackgroundDropShadowEnabled(enabled);
+}
+
+bool QChart::isDropShadowEnabled() const
+{
+ return d_ptr->m_presenter->isBackgroundDropShadowEnabled();
+}
+
+void QChart::setBackgroundRoundness(qreal diameter)
+{
+ d_ptr->m_presenter->setBackgroundRoundness(diameter);
+}
+
+qreal QChart::backgroundRoundness() const
+{
+ return d_ptr->m_presenter->backgroundRoundness();
+}
+
+/*!
+ Returns all series that are added to the chart.
+
+ \sa addSeries(), removeSeries(), removeAllSeries()
+*/
+QList<QAbstractSeries *> QChart::series() const
+{
+ return d_ptr->m_dataset->series();
+}
+
+/*!
+ Adds the \a axis to the chart and attaches it to the \a series as a bottom-aligned horizontal axis.
+ The chart takes ownership of both the \a axis and the \a series.
+ Any horizontal axes previously attached to the \a series are deleted.
+
+ \sa axisX(), axisY(), setAxisY(), createDefaultAxes(), QAbstractSeries::attachAxis()
+*/
+void QChart::setAxisX(QAbstractAxis *axis ,QAbstractSeries *series)
+{
+ QList<QAbstractAxis*> list = axes(Qt::Horizontal, series);
+
+ foreach (QAbstractAxis* a, list) {
+ d_ptr->m_dataset->removeAxis(a);
+ delete a;
+ }
+
+ if (!d_ptr->m_dataset->axes().contains(axis))
+ d_ptr->m_dataset->addAxis(axis, Qt::AlignBottom);
+ d_ptr->m_dataset->attachAxis(series, axis);
+}
+
+/*!
+ Adds the \a axis to the chart and attaches it to the \a series as a left-aligned vertical axis.
+ The chart takes ownership of both the \a axis and the \a series.
+ Any vertical axes previously attached to the \a series are deleted.
+
+ \sa axisX(), axisY(), setAxisX(), createDefaultAxes(), QAbstractSeries::attachAxis()
+*/
+void QChart::setAxisY(QAbstractAxis *axis ,QAbstractSeries *series)
+{
+ QList<QAbstractAxis*> list = axes(Qt::Vertical, series);
+
+ foreach (QAbstractAxis* a, list) {
+ d_ptr->m_dataset->removeAxis(a);
+ delete a;
+ }
+
+ if (!d_ptr->m_dataset->axes().contains(axis))
+ d_ptr->m_dataset->addAxis(axis, Qt::AlignLeft);
+ d_ptr->m_dataset->attachAxis(series, axis);
+}
+
+/*!
+ Adds the \a axis to the chart with \a alignment. The chart takes the ownership of the axis.
+
+ \sa removeAxis(), createDefaultAxes(), QAbstractSeries::attachAxis()
+*/
+void QChart::addAxis(QAbstractAxis *axis, Qt::Alignment alignment)
+{
+ d_ptr->m_dataset->addAxis(axis, alignment);
+}
+
+/*!
+ Removes the \a axis from the chart.
+ The chart releases its ownership of the specified \a axis object.
+
+ \sa addAxis(), createDefaultAxes(), QAbstractSeries::detachAxis()
+*/
+void QChart::removeAxis(QAbstractAxis *axis)
+{
+ d_ptr->m_dataset->removeAxis(axis);
+}
+
+/*!
+ Returns the value in the \a series domain that corresponds to the \a position relative to chart widget.
+*/
+QPointF QChart::mapToValue(const QPointF &position, QAbstractSeries *series)
+{
+ return d_ptr->m_dataset->mapToValue(position, series);
+}
+
+/*!
+ Returns the position on the chart widget that corresponds to the \a value in the \a series domain.
+*/
+QPointF QChart::mapToPosition(const QPointF &value, QAbstractSeries *series)
+{
+ return d_ptr->m_dataset->mapToPosition(value, series);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QChartPrivate::QChartPrivate(QChart *q, QChart::ChartType type):
+ q_ptr(q),
+ m_legend(0),
+ m_dataset(new ChartDataSet(q)),
+ m_presenter(new ChartPresenter(q, type)),
+ m_themeManager(new ChartThemeManager(q)),
+ m_type(type)
+{
+ QObject::connect(m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), m_presenter, SLOT(handleSeriesAdded(QAbstractSeries*)));
+ QObject::connect(m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)), m_presenter, SLOT(handleSeriesRemoved(QAbstractSeries*)));
+ QObject::connect(m_dataset, SIGNAL(axisAdded(QAbstractAxis*)), m_presenter, SLOT(handleAxisAdded(QAbstractAxis*)));
+ QObject::connect(m_dataset, SIGNAL(axisRemoved(QAbstractAxis*)), m_presenter, SLOT(handleAxisRemoved(QAbstractAxis*)));
+ QObject::connect(m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), m_themeManager, SLOT(handleSeriesAdded(QAbstractSeries*)));
+ QObject::connect(m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)), m_themeManager, SLOT(handleSeriesRemoved(QAbstractSeries*)));
+ QObject::connect(m_dataset, SIGNAL(axisAdded(QAbstractAxis*)), m_themeManager, SLOT(handleAxisAdded(QAbstractAxis*)));
+ QObject::connect(m_dataset, SIGNAL(axisRemoved(QAbstractAxis*)), m_themeManager, SLOT(handleAxisRemoved(QAbstractAxis*)));
+}
+
+QChartPrivate::~QChartPrivate()
+{
+}
+
+// Hackish solution to the problem of explicitly assigning the default pen/brush/font
+// to a series or axis and having theme override it:
+// Initialize pens, brushes, and fonts to something nobody is likely to ever use,
+// so that default theme initialization will always set these properly.
+QPen &QChartPrivate::defaultPen()
+{
+ static QPen defaultPen(QColor(1, 2, 0), 0.93247536);
+ return defaultPen;
+}
+
+QBrush &QChartPrivate::defaultBrush()
+{
+ static QBrush defaultBrush(QColor(1, 2, 0), Qt::Dense7Pattern);
+ return defaultBrush;
+}
+
+QFont &QChartPrivate::defaultFont()
+{
+ static bool defaultFontInitialized(false);
+ static QFont defaultFont;
+ if (!defaultFontInitialized) {
+ defaultFont.setPointSizeF(8.34563465);
+ defaultFontInitialized = true;
+ }
+ return defaultFont;
+}
+
+void QChartPrivate::init()
+{
+ m_legend = new LegendScroller(q_ptr);
+ q_ptr->setTheme(QChart::ChartThemeLight);
+ q_ptr->setLayout(m_presenter->layout());
+}
+
+void QChartPrivate::zoomIn(qreal factor)
+{
+ QRectF rect = m_presenter->geometry();
+ rect.setWidth(rect.width() / factor);
+ rect.setHeight(rect.height() / factor);
+ rect.moveCenter(m_presenter->geometry().center());
+ zoomIn(rect);
+}
+
+void QChartPrivate::zoomIn(const QRectF &rect)
+{
+ if (!rect.isValid())
+ return;
+
+ QRectF r = rect.normalized();
+ const QRectF geometry = m_presenter->geometry();
+ r.translate(-geometry.topLeft());
+
+ if (!r.isValid())
+ return;
+
+ QPointF zoomPoint(r.center().x() / geometry.width(), r.center().y() / geometry.height());
+ m_presenter->setState(ChartPresenter::ZoomInState,zoomPoint);
+ m_dataset->zoomInDomain(r);
+ m_presenter->setState(ChartPresenter::ShowState,QPointF());
+
+}
+
+void QChartPrivate::zoomReset()
+{
+ m_dataset->zoomResetDomain();
+}
+
+bool QChartPrivate::isZoomed()
+{
+ return m_dataset->isZoomedDomain();
+}
+
+void QChartPrivate::zoomOut(qreal factor)
+{
+ const QRectF geometry = m_presenter->geometry();
+
+ QRectF r;
+ r.setSize(geometry.size() / factor);
+ r.moveCenter(QPointF(geometry.size().width()/2 ,geometry.size().height()/2));
+ if (!r.isValid())
+ return;
+
+ QPointF zoomPoint(r.center().x() / geometry.width(), r.center().y() / geometry.height());
+ m_presenter->setState(ChartPresenter::ZoomOutState,zoomPoint);
+ m_dataset->zoomOutDomain(r);
+ m_presenter->setState(ChartPresenter::ShowState,QPointF());
+}
+
+void QChartPrivate::scroll(qreal dx, qreal dy)
+{
+ if (dx < 0) m_presenter->setState(ChartPresenter::ScrollLeftState,QPointF());
+ if (dx > 0) m_presenter->setState(ChartPresenter::ScrollRightState,QPointF());
+ if (dy < 0) m_presenter->setState(ChartPresenter::ScrollUpState,QPointF());
+ if (dy > 0) m_presenter->setState(ChartPresenter::ScrollDownState,QPointF());
+
+ m_dataset->scrollDomain(dx, dy);
+ m_presenter->setState(ChartPresenter::ShowState,QPointF());
+}
+
+#include "moc_qchart.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/qchart.h b/src/charts/qchart.h
new file mode 100644
index 00000000..9e8c869d
--- /dev/null
+++ b/src/charts/qchart.h
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCHART_H
+#define QCHART_H
+
+#include <QtCharts/QAbstractSeries>
+#include <QtCharts/QLegend>
+#include <QGraphicsWidget>
+#include <QMargins>
+
+class QGraphicsSceneResizeEvent;
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QAbstractSeries;
+class QAbstractAxis;
+class QLegend;
+class QChartPrivate;
+class QBoxPlotSeries;
+
+class QT_CHARTS_EXPORT QChart : public QGraphicsWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(QChart::ChartTheme theme READ theme WRITE setTheme)
+ Q_PROPERTY(QString title READ title WRITE setTitle)
+ Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible)
+ Q_PROPERTY(bool dropShadowEnabled READ isDropShadowEnabled WRITE setDropShadowEnabled)
+ Q_PROPERTY(qreal backgroundRoundness READ backgroundRoundness WRITE setBackgroundRoundness)
+ Q_PROPERTY(QChart::AnimationOptions animationOptions READ animationOptions WRITE setAnimationOptions)
+ Q_PROPERTY(QMargins minimumMargins READ minimumMargins WRITE setMinimumMargins)
+ Q_PROPERTY(QMargins margins READ margins WRITE setMargins)
+ Q_PROPERTY(QChart::ChartType chartType READ chartType)
+ Q_PROPERTY(bool plotAreaBackgroundVisible READ isPlotAreaBackgroundVisible WRITE setPlotAreaBackgroundVisible)
+ Q_PROPERTY(bool localizeNumbers READ localizeNumbers WRITE setLocalizeNumbers)
+ Q_PROPERTY(QLocale locale READ locale WRITE setLocale)
+ Q_ENUMS(ChartTheme)
+ Q_ENUMS(AnimationOption)
+ Q_ENUMS(ChartType)
+
+public:
+ enum ChartType {
+ ChartTypeUndefined = 0,
+ ChartTypeCartesian,
+ ChartTypePolar
+ };
+
+ enum ChartTheme {
+ ChartThemeLight = 0,
+ ChartThemeBlueCerulean,
+ ChartThemeDark,
+ ChartThemeBrownSand,
+ ChartThemeBlueNcs,
+ ChartThemeHighContrast,
+ ChartThemeBlueIcy,
+ ChartThemeQt
+ };
+
+ enum AnimationOption {
+ NoAnimation = 0x0,
+ GridAxisAnimations = 0x1,
+ SeriesAnimations = 0x2,
+ AllAnimations = 0x3
+ };
+
+ Q_DECLARE_FLAGS(AnimationOptions, AnimationOption)
+
+public:
+ explicit QChart(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0);
+ ~QChart();
+
+ void addSeries(QAbstractSeries *series);
+ void removeSeries(QAbstractSeries *series);
+ void removeAllSeries();
+ QList<QAbstractSeries *> series() const;
+
+ // *** deprecated ***
+ void setAxisX(QAbstractAxis *axis, QAbstractSeries *series = 0);
+ void setAxisY(QAbstractAxis *axis, QAbstractSeries *series = 0);
+ QAbstractAxis *axisX(QAbstractSeries *series = 0) const;
+ QAbstractAxis *axisY(QAbstractSeries *series = 0) const;
+ // ******************
+
+ void addAxis(QAbstractAxis *axis, Qt::Alignment alignment);
+ void removeAxis(QAbstractAxis *axis);
+ QList<QAbstractAxis*> axes(Qt::Orientations orientation = Qt::Horizontal|Qt::Vertical, QAbstractSeries *series = 0) const;
+
+ void createDefaultAxes();
+
+ void setTheme(QChart::ChartTheme theme);
+ QChart::ChartTheme theme() const;
+
+ void setTitle(const QString &title);
+ QString title() const;
+ void setTitleFont(const QFont &font);
+ QFont titleFont() const;
+ void setTitleBrush(const QBrush &brush);
+ QBrush titleBrush() const;
+
+ void setBackgroundBrush(const QBrush &brush);
+ QBrush backgroundBrush() const;
+ void setBackgroundPen(const QPen &pen);
+ QPen backgroundPen() const;
+ void setBackgroundVisible(bool visible = true);
+ bool isBackgroundVisible() const;
+
+ void setDropShadowEnabled(bool enabled = true);
+ bool isDropShadowEnabled() const;
+ void setBackgroundRoundness(qreal diameter);
+ qreal backgroundRoundness() const;
+ void setAnimationOptions(AnimationOptions options);
+ AnimationOptions animationOptions() const;
+
+ void zoomIn();
+ void zoomOut();
+
+ void zoomIn(const QRectF &rect);
+ void zoom(qreal factor);
+ void zoomReset();
+ bool isZoomed();
+
+ void scroll(qreal dx, qreal dy);
+
+ QLegend *legend() const;
+
+ void setMinimumMargins(const QMargins& margins);
+ QMargins minimumMargins() const;
+
+ void setMargins(const QMargins &margins);
+ QMargins margins() const;
+
+ QRectF plotArea() const;
+ void setPlotAreaBackgroundBrush(const QBrush &brush);
+ QBrush plotAreaBackgroundBrush() const;
+ void setPlotAreaBackgroundPen(const QPen &pen);
+ QPen plotAreaBackgroundPen() const;
+ void setPlotAreaBackgroundVisible(bool visible = true);
+ bool isPlotAreaBackgroundVisible() const;
+ void setLocalizeNumbers(bool localize);
+ bool localizeNumbers() const;
+ void setLocale(const QLocale &locale);
+ QLocale locale() const;
+
+ QPointF mapToValue(const QPointF &position, QAbstractSeries *series = 0);
+ QPointF mapToPosition(const QPointF &value, QAbstractSeries *series = 0);
+
+ ChartType chartType() const;
+
+protected:
+ explicit QChart(QChart::ChartType type, QGraphicsItem *parent, Qt::WindowFlags wFlags);
+ QScopedPointer<QChartPrivate> d_ptr;
+ friend class QLegend;
+ friend class DeclarativeChart;
+ friend class ChartDataSet;
+ friend class ChartPresenter;
+ friend class ChartThemeManager;
+ friend class QAbstractSeries;
+ friend class QBoxPlotSeriesPrivate;
+ Q_DISABLE_COPY(QChart)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QT_CHARTS_NAMESPACE::QChart::AnimationOptions)
+
+#endif // QCHART_H
diff --git a/src/charts/qchart_p.h b/src/charts/qchart_p.h
new file mode 100644
index 00000000..e43ae07d
--- /dev/null
+++ b/src/charts/qchart_p.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QCHART_P_H
+#define QCHART_P_H
+
+#include "qchartglobal.h"
+#include "qchart.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class ChartThemeManager;
+class ChartPresenter;
+class QLegend;
+class ChartDataSet;
+
+class QChartPrivate
+{
+
+public:
+ QChartPrivate(QChart *q, QChart::ChartType type);
+ ~QChartPrivate();
+ QChart *q_ptr;
+ QLegend *m_legend;
+ ChartDataSet *m_dataset;
+ ChartPresenter *m_presenter;
+ ChartThemeManager *m_themeManager;
+ QChart::ChartType m_type;
+
+ static QPen &defaultPen();
+ static QBrush &defaultBrush();
+ static QFont &defaultFont();
+
+ void init();
+ void zoomIn(qreal factor);
+ void zoomOut(qreal factor);
+ void zoomIn(const QRectF &rect);
+ void zoomReset();
+ bool isZoomed();
+ void scroll(qreal dx, qreal dy);
+};
+
+QT_CHARTS_END_NAMESPACE
+#endif
diff --git a/src/charts/qchartglobal.h b/src/charts/qchartglobal.h
new file mode 100644
index 00000000..ade1942e
--- /dev/null
+++ b/src/charts/qchartglobal.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCHARTGLOBAL_H
+#define QCHARTGLOBAL_H
+
+#include <qglobal.h>
+
+#define QT_CHARTS_VERSION_STR "2.0.0"
+/*
+ QT_CHARTS_VERSION is (major << 16) + (minor << 8) + patch.
+*/
+#define QT_CHARTS_VERSION 0x020000
+/*
+ can be used like #if (QT_CHARTS_VERSION >= QT_CHARTS_VERSION_CHECK(1, 1, 0))
+*/
+#define QT_CHARTS_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch))
+
+#if defined(QT_CHARTS_LIBRARY)
+# define QT_CHARTS_EXPORT Q_DECL_EXPORT
+#else
+# define QT_CHARTS_EXPORT Q_DECL_IMPORT
+#endif
+
+#if defined(BUILD_PRIVATE_UNIT_TESTS) && defined(QT_CHARTS_LIBRARY)
+# define QT_CHARTS_AUTOTEST_EXPORT Q_DECL_EXPORT
+#elif defined(BUILD_PRIVATE_UNIT_TESTS) && !defined(QT_CHARTS_LIBRARY)
+# define QT_CHARTS_AUTOTEST_EXPORT Q_DECL_IMPORT
+#else
+# define QT_CHARTS_AUTOTEST_EXPORT
+#endif
+
+#ifdef QT_CHARTS_STATICLIB
+# undef QT_CHARTS_EXPORT
+# undef QT_CHARTS_AUTOTEST_EXPORT
+# define QT_CHARTS_EXPORT
+# define QT_CHARTS_AUTOTEST_EXPORT
+#endif
+
+#define QT_CHARTS_NAMESPACE QtCharts
+
+#ifdef QT_CHARTS_NAMESPACE
+# define QT_CHARTS_BEGIN_NAMESPACE namespace QT_CHARTS_NAMESPACE {
+# define QT_CHARTS_END_NAMESPACE }
+# define QT_CHARTS_USE_NAMESPACE using namespace QT_CHARTS_NAMESPACE;
+#else
+# define QT_CHARTS_BEGIN_NAMESPACE
+# define QT_CHARTS_END_NAMESPACE
+# define QT_CHARTS_USE_NAMESPACE
+#endif
+
+/*
+ On Windows min and max conflict with standard macros
+*/
+#ifdef Q_OS_WIN
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+#endif
+
+#endif // QCHARTGLOBAL_H
diff --git a/src/charts/qchartview.cpp b/src/charts/qchartview.cpp
new file mode 100644
index 00000000..234ef080
--- /dev/null
+++ b/src/charts/qchartview.cpp
@@ -0,0 +1,317 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qchartview.h"
+#include "qchartview_p.h"
+#include "qchart_p.h"
+#include <QGraphicsScene>
+#include <QRubberBand>
+
+/*!
+ \enum QChartView::RubberBand
+
+ This enum describes the different types of rubber bands that can be used for zoom rect selection
+
+ \value NoRubberBand
+ \value VerticalRubberBand
+ \value HorizonalRubberBand
+ \value RectangleRubberBand
+*/
+
+/*!
+ \class QChartView
+ \inmodule Qt Charts
+ \brief Standalone charting widget.
+
+ QChartView is a standalone widget that can display charts. It does not require separate
+ QGraphicsScene to work. If you want to display a chart in your existing QGraphicsScene,
+ you need to use the QChart (or QPolarChart) class instead.
+
+ \sa QChart, QPolarChart
+*/
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ Constructs a chartView object with parent \a parent.
+*/
+
+QChartView::QChartView(QWidget *parent)
+ : QGraphicsView(parent),
+ d_ptr(new QChartViewPrivate(this))
+{
+
+}
+
+/*!
+ Constructs a chartview object with parent \a parent to display a \a chart.
+ Ownership of the \a chart is passed to chartview.
+*/
+
+QChartView::QChartView(QChart *chart, QWidget *parent)
+ : QGraphicsView(parent),
+ d_ptr(new QChartViewPrivate(this, chart))
+{
+
+}
+
+
+/*!
+ Destroys the chartview object and the associated chart.
+*/
+QChartView::~QChartView()
+{
+}
+
+/*!
+ Returns the pointer to the associated chart.
+*/
+QChart *QChartView::chart() const
+{
+ return d_ptr->m_chart;
+}
+
+/*!
+ Sets the current chart to \a chart. Ownership of the new chart is passed to chartview
+ and ownership of the previous chart is released.
+
+ To avoid memory leaks users need to make sure the previous chart is deleted.
+*/
+
+void QChartView::setChart(QChart *chart)
+{
+ d_ptr->setChart(chart);
+}
+
+/*!
+ Sets the rubber band flags to \a rubberBand.
+ Selected flags determine the way zooming is performed.
+
+ \note Rubber band zooming is not supported for polar charts.
+*/
+void QChartView::setRubberBand(const RubberBands &rubberBand)
+{
+#ifndef QT_NO_RUBBERBAND
+ d_ptr->m_rubberBandFlags = rubberBand;
+
+ if (!d_ptr->m_rubberBandFlags) {
+ delete d_ptr->m_rubberBand;
+ d_ptr->m_rubberBand = 0;
+ return;
+ }
+
+ if (!d_ptr->m_rubberBand) {
+ d_ptr->m_rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
+ d_ptr->m_rubberBand->setEnabled(true);
+ }
+#else
+ Q_UNUSED(rubberBand);
+ qWarning("Unable to set rubber band because Qt is configured without it.");
+#endif
+}
+
+/*!
+ Returns the rubber band flags that are currently being used by the widget.
+*/
+QChartView::RubberBands QChartView::rubberBand() const
+{
+ return d_ptr->m_rubberBandFlags;
+}
+
+/*!
+ If Left mouse button is pressed and the rubber band is enabled the \a event is accepted and the rubber band is displayed on the screen allowing the user to select the zoom area.
+ If different mouse button is pressed and/or the rubber band is disabled then the \a event is passed to QGraphicsView::mousePressEvent() implementation.
+*/
+void QChartView::mousePressEvent(QMouseEvent *event)
+{
+#ifndef QT_NO_RUBBERBAND
+ QRectF plotArea = d_ptr->m_chart->plotArea();
+ if (d_ptr->m_rubberBand && d_ptr->m_rubberBand->isEnabled()
+ && event->button() == Qt::LeftButton && plotArea.contains(event->pos())) {
+ d_ptr->m_rubberBandOrigin = event->pos();
+ d_ptr->m_rubberBand->setGeometry(QRect(d_ptr->m_rubberBandOrigin, QSize()));
+ d_ptr->m_rubberBand->show();
+ event->accept();
+ } else {
+#endif
+ QGraphicsView::mousePressEvent(event);
+#ifndef QT_NO_RUBBERBAND
+ }
+#endif
+}
+
+/*!
+ If the rubber band rectange has been displayed in pressEvent then \a event data is used to update the rubber band geometry.
+ Otherwise the default QGraphicsView::mouseMoveEvent implementation is called.
+*/
+void QChartView::mouseMoveEvent(QMouseEvent *event)
+{
+#ifndef QT_NO_RUBBERBAND
+ if (d_ptr->m_rubberBand && d_ptr->m_rubberBand->isVisible()) {
+ QRect rect = d_ptr->m_chart->plotArea().toRect();
+ int width = event->pos().x() - d_ptr->m_rubberBandOrigin.x();
+ int height = event->pos().y() - d_ptr->m_rubberBandOrigin.y();
+ if (!d_ptr->m_rubberBandFlags.testFlag(VerticalRubberBand)) {
+ d_ptr->m_rubberBandOrigin.setY(rect.top());
+ height = rect.height();
+ }
+ if (!d_ptr->m_rubberBandFlags.testFlag(HorizonalRubberBand)) {
+ d_ptr->m_rubberBandOrigin.setX(rect.left());
+ width = rect.width();
+ }
+ d_ptr->m_rubberBand->setGeometry(QRect(d_ptr->m_rubberBandOrigin.x(), d_ptr->m_rubberBandOrigin.y(), width, height).normalized());
+ } else {
+#endif
+ QGraphicsView::mouseMoveEvent(event);
+#ifndef QT_NO_RUBBERBAND
+ }
+#endif
+}
+
+/*!
+ If left mouse button is released and the rubber band is enabled then \a event is accepted and
+ the view is zoomed into the rect specified by the rubber band.
+ If it is a right mouse button \a event then the view is zoomed out.
+*/
+void QChartView::mouseReleaseEvent(QMouseEvent *event)
+{
+#ifndef QT_NO_RUBBERBAND
+ if (d_ptr->m_rubberBand && d_ptr->m_rubberBand->isVisible()) {
+ if (event->button() == Qt::LeftButton) {
+ d_ptr->m_rubberBand->hide();
+ QRectF rect = d_ptr->m_rubberBand->geometry();
+ // Since plotArea uses QRectF and rubberband uses QRect, we can't just blindly use
+ // rubberband's dimensions for vertical and horizontal rubberbands, where one
+ // dimension must match the corresponding plotArea dimension exactly.
+ if (d_ptr->m_rubberBandFlags == VerticalRubberBand) {
+ rect.setX(d_ptr->m_chart->plotArea().x());
+ rect.setWidth(d_ptr->m_chart->plotArea().width());
+ } else if (d_ptr->m_rubberBandFlags == HorizonalRubberBand) {
+ rect.setY(d_ptr->m_chart->plotArea().y());
+ rect.setHeight(d_ptr->m_chart->plotArea().height());
+ }
+ d_ptr->m_chart->zoomIn(rect);
+ event->accept();
+ }
+
+ } else if (d_ptr->m_rubberBand && event->button() == Qt::RightButton) {
+ // If vertical or horizontal rubberband mode, restrict zoom out to specified axis.
+ // Since there is no suitable API for that, use zoomIn with rect bigger than the
+ // plot area.
+ if (d_ptr->m_rubberBandFlags == VerticalRubberBand
+ || d_ptr->m_rubberBandFlags == HorizonalRubberBand) {
+ QRectF rect = d_ptr->m_chart->plotArea();
+ if (d_ptr->m_rubberBandFlags == VerticalRubberBand) {
+ qreal adjustment = rect.height() / 2;
+ rect.adjust(0, -adjustment, 0, adjustment);
+ } else if (d_ptr->m_rubberBandFlags == HorizonalRubberBand) {
+ qreal adjustment = rect.width() / 2;
+ rect.adjust(-adjustment, 0, adjustment, 0);
+ }
+ d_ptr->m_chart->zoomIn(rect);
+ } else {
+ d_ptr->m_chart->zoomOut();
+ }
+ event->accept();
+ } else {
+#endif
+ QGraphicsView::mouseReleaseEvent(event);
+#ifndef QT_NO_RUBBERBAND
+ }
+#endif
+}
+
+/*!
+ Resizes and updates the chart area using the \a event data
+*/
+void QChartView::resizeEvent(QResizeEvent *event)
+{
+ QGraphicsView::resizeEvent(event);
+ d_ptr->resize();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QChartViewPrivate::QChartViewPrivate(QChartView *q, QChart *chart)
+ : q_ptr(q),
+ m_scene(new QGraphicsScene(q)),
+ m_chart(chart),
+#ifndef QT_NO_RUBBERBAND
+ m_rubberBand(0),
+#endif
+ m_rubberBandFlags(QChartView::NoRubberBand)
+{
+ q_ptr->setFrameShape(QFrame::NoFrame);
+ q_ptr->setBackgroundRole(QPalette::Window);
+ q_ptr->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ q_ptr->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ q_ptr->setScene(m_scene);
+ q_ptr->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ if (!m_chart)
+ m_chart = new QChart();
+ m_scene->addItem(m_chart);
+}
+
+QChartViewPrivate::~QChartViewPrivate()
+{
+}
+
+void QChartViewPrivate::setChart(QChart *chart)
+{
+ Q_ASSERT(chart);
+
+ if (m_chart == chart)
+ return;
+
+ if (m_chart)
+ m_scene->removeItem(m_chart);
+
+ m_chart = chart;
+ m_scene->addItem(m_chart);
+
+ resize();
+}
+
+void QChartViewPrivate::resize()
+{
+ // Fit the chart into view if it has been rotated
+ qreal sinA = qAbs(q_ptr->transform().m21());
+ qreal cosA = qAbs(q_ptr->transform().m11());
+ QSize chartSize = q_ptr->size();
+
+ if (sinA == 1.0) {
+ chartSize.setHeight(q_ptr->size().width());
+ chartSize.setWidth(q_ptr->size().height());
+ } else if (sinA != 0.0) {
+ // Non-90 degree rotation, find largest square chart that can fit into the view.
+ qreal minDimension = qMin(q_ptr->size().width(), q_ptr->size().height());
+ qreal h = (minDimension - (minDimension / ((sinA / cosA) + 1.0))) / sinA;
+ chartSize.setHeight(h);
+ chartSize.setWidth(h);
+ }
+
+ m_chart->resize(chartSize);
+ q_ptr->setMinimumSize(m_chart->minimumSize().toSize());
+ q_ptr->setSceneRect(m_chart->geometry());
+}
+
+#include "moc_qchartview.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/qchartview.h b/src/charts/qchartview.h
new file mode 100644
index 00000000..89aca5d4
--- /dev/null
+++ b/src/charts/qchartview.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCHARTVIEW_H
+#define QCHARTVIEW_H
+
+#include <QtCharts/QAbstractAxis>
+#include <QtCharts/QAbstractSeries>
+#include <QtCharts/QChart>
+#include <QGraphicsView>
+
+class QGraphicsScene;
+class QRubberBand;
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QChartViewPrivate;
+
+class QT_CHARTS_EXPORT QChartView : public QGraphicsView
+{
+ Q_OBJECT
+ Q_ENUMS(RubberBand)
+public:
+
+ enum RubberBand {
+ NoRubberBand = 0x0,
+ VerticalRubberBand = 0x1,
+ HorizonalRubberBand = 0x2,
+ RectangleRubberBand = 0x3
+ };
+
+ Q_DECLARE_FLAGS(RubberBands, RubberBand)
+
+ explicit QChartView(QWidget *parent = 0);
+ explicit QChartView(QChart *chart, QWidget *parent = 0);
+ ~QChartView();
+
+ void setRubberBand(const RubberBands &rubberBands);
+ RubberBands rubberBand() const;
+
+ QChart *chart() const;
+ void setChart(QChart *chart);
+
+protected:
+ void resizeEvent(QResizeEvent *event);
+ void mousePressEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *event);
+
+protected:
+ QScopedPointer<QChartViewPrivate> d_ptr;
+ Q_DISABLE_COPY(QChartView)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QCHARTVIEW_H
diff --git a/src/charts/qchartview_p.h b/src/charts/qchartview_p.h
new file mode 100644
index 00000000..a6103de6
--- /dev/null
+++ b/src/charts/qchartview_p.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QCHARTVIEW_P_H
+#define QCHARTVIEW_P_H
+
+#include "qchartview.h"
+
+class QGraphicsScene;
+class ChartPresenter;
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QChart;
+class QChartView;
+
+class QChartViewPrivate
+{
+public:
+ explicit QChartViewPrivate(QChartView *q, QChart *chart = 0);
+ ~QChartViewPrivate();
+ void setChart(QChart *chart);
+ void resize();
+
+protected:
+ QChartView *q_ptr;
+
+public:
+ QGraphicsScene *m_scene;
+ QChart *m_chart;
+ QPoint m_rubberBandOrigin;
+#ifndef QT_NO_RUBBERBAND
+ QRubberBand *m_rubberBand;
+#endif
+ QChartView::RubberBands m_rubberBandFlags;
+};
+
+QT_CHARTS_END_NAMESPACE
+#endif
diff --git a/src/charts/qpolarchart.cpp b/src/charts/qpolarchart.cpp
new file mode 100644
index 00000000..b8ad49ee
--- /dev/null
+++ b/src/charts/qpolarchart.cpp
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpolarchart.h"
+#include "qabstractaxis.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \enum QPolarChart::PolarOrientation
+
+ This type is used to specify the polar orientation of an axis.
+
+ \value PolarOrientationRadial
+ \value PolarOrientationAngular
+*/
+
+/*!
+ \class QPolarChart
+ \inmodule Qt Charts
+ \brief Polar chart API for Qt Charts.
+
+ QPolarChart is a specialization of QChart to show a polar chart.
+
+ Polar charts support line, spline, area, and scatter series, and all axis types
+ supported by those series.
+
+ \note When setting ticks to an angular QValueAxis, keep in mind that the first and last tick
+ are co-located at 0/360 degree angle.
+
+ \note If the angular distance between two consecutive points in a series is more than 180 degrees,
+ any line connecting the two points becomes meaningless, so choose the axis ranges accordingly
+ when displaying line, spline, or area series. In such case series don't draw a direct line between
+ the two points, but instead draw a line to and from the center of the chart.
+
+ \note Polar charts draw all axes of same orientation in the same position, so using multiple
+ axes of same orientation can be confusing, unless the extra axes are only used to customize the
+ grid (e.g. you can display a highlighted range with a secondary shaded QCategoryAxis or provide
+ unlabeled subticks with a secondary QValueAxis that has its labels hidden).
+
+ \sa QChart
+ */
+
+/*!
+ Constructs a polar chart as a child of the \a parent.
+ Parameter \a wFlags is passed to the QChart constructor.
+ */
+QPolarChart::QPolarChart(QGraphicsItem *parent, Qt::WindowFlags wFlags)
+ : QChart(QChart::ChartTypePolar, parent, wFlags)
+{
+}
+
+/*!
+ Destroys the polar chart object and its children, like series and axis objects added to it.
+ */
+QPolarChart::~QPolarChart()
+{
+}
+
+/*!
+ Returns the axes added for the \a series with \a polarOrientation. If no series is provided, then any axis with the
+ specified polar orientation is returned.
+
+ \sa addAxis()
+ */
+QList<QAbstractAxis *> QPolarChart::axes(PolarOrientations polarOrientation, QAbstractSeries *series) const
+{
+ Qt::Orientations orientation(0);
+ if (polarOrientation.testFlag(PolarOrientationAngular))
+ orientation |= Qt::Horizontal;
+ if (polarOrientation.testFlag(PolarOrientationRadial))
+ orientation |= Qt::Vertical;
+
+ return QChart::axes(orientation, series);
+}
+
+/*!
+ This convenience method adds \a axis to the polar chart with \a polarOrientation.
+ The chart takes the ownership of the axis.
+
+ \note Axes can be added to a polar chart also with QChart::addAxis() instead of this method.
+ The specified alignment determines the polar orientation: horizontal alignments indicate angular
+ axis and vertical alignments indicate radial axis.
+
+ \sa QChart::removeAxis(), QChart::createDefaultAxes(), QAbstractSeries::attachAxis(), QChart::addAxis()
+*/
+void QPolarChart::addAxis(QAbstractAxis *axis, PolarOrientation polarOrientation)
+{
+ if (!axis || axis->type() == QAbstractAxis::AxisTypeBarCategory) {
+ qWarning("QAbstractAxis::AxisTypeBarCategory is not a supported axis type for polar charts.");
+ } else {
+ Qt::Alignment alignment = Qt::AlignLeft;
+ if (polarOrientation == PolarOrientationAngular)
+ alignment = Qt::AlignBottom;
+ QChart::addAxis(axis, alignment);
+ }
+}
+
+/*!
+ Angular axes of a polar chart report horizontal orientation and radial axes report
+ vertical orientation.
+ This function is a convenience function for converting the orientation of an \a axis to
+ corresponding polar orientation. If the \a axis is NULL or not added to a polar chart,
+ the return value is meaningless.
+*/
+QPolarChart::PolarOrientation QPolarChart::axisPolarOrientation(QAbstractAxis *axis)
+{
+ if (axis && axis->orientation() == Qt::Horizontal)
+ return PolarOrientationAngular;
+ else
+ return PolarOrientationRadial;
+}
+
+#include "moc_qpolarchart.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/qpolarchart.h b/src/charts/qpolarchart.h
new file mode 100644
index 00000000..e9512525
--- /dev/null
+++ b/src/charts/qpolarchart.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPOLARCHART_H
+#define QPOLARCHART_H
+
+#include <QtCharts/qchart.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QAbstractSeries;
+class QAbstractAxis;
+
+class QT_CHARTS_EXPORT QPolarChart : public QChart
+{
+ Q_OBJECT
+ Q_ENUMS(PolarOrientation)
+ Q_FLAGS(PolarOrientations)
+
+public:
+ enum PolarOrientation {
+ PolarOrientationRadial = 0x1,
+ PolarOrientationAngular = 0x2
+ };
+ Q_DECLARE_FLAGS(PolarOrientations, PolarOrientation)
+
+public:
+ explicit QPolarChart(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0);
+ ~QPolarChart();
+
+ void addAxis(QAbstractAxis *axis, PolarOrientation polarOrientation);
+
+ QList<QAbstractAxis*> axes(PolarOrientations polarOrientation = PolarOrientations(PolarOrientationRadial | PolarOrientationAngular), QAbstractSeries *series = 0) const;
+
+ static PolarOrientation axisPolarOrientation(QAbstractAxis *axis);
+
+protected:
+ Q_DISABLE_COPY(QPolarChart)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QCHART_H
diff --git a/src/charts/scatterchart/qscatterseries.cpp b/src/charts/scatterchart/qscatterseries.cpp
new file mode 100644
index 00000000..346ca83b
--- /dev/null
+++ b/src/charts/scatterchart/qscatterseries.cpp
@@ -0,0 +1,336 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscatterseries.h"
+#include "qscatterseries_p.h"
+#include "scatterchartitem_p.h"
+#include "chartdataset_p.h"
+#include "charttheme_p.h"
+#include "scatteranimation_p.h"
+#include "qchart_p.h"
+
+/*!
+ \class QScatterSeries
+ \inmodule Qt Charts
+ \brief The QScatterSeries class is used for making scatter charts.
+
+ \mainclass
+
+ The scatter data is displayed as a collection of points on the chart. Each point determines the position on the horizontal axis
+ and the vertical axis.
+
+ \image examples_scatterchart.png
+
+ Creating basic scatter chart is simple:
+ \code
+ QScatterSeries* series = new QScatterSeries();
+ series->append(0, 6);
+ series->append(2, 4);
+ ...
+ chart->addSeries(series);
+ \endcode
+*/
+/*!
+ \qmltype ScatterSeries
+ \instantiates QScatterSeries
+ \inqmlmodule QtCharts
+
+ \inherits XYSeries
+
+ \brief The ScatterSeries type is used for making scatter charts.
+
+ The following QML shows how to create a chart with two simple scatter series:
+ \snippet qmlchart/qml/qmlchart/View5.qml 1
+
+ \beginfloatleft
+ \image examples_qmlchart5.png
+ \endfloat
+ \clearfloat
+*/
+
+/*!
+ \enum QScatterSeries::MarkerShape
+
+ This enum describes the shape used when rendering marker items.
+
+ \value MarkerShapeCircle
+ \value MarkerShapeRectangle
+*/
+
+/*!
+ \property QScatterSeries::brush
+ Brush used to draw the series.
+*/
+
+/*!
+ \property QScatterSeries::color
+ Fill (brush) color of the series. This is a convenience property for modifying the color of brush.
+ \sa QScatterSeries::brush()
+*/
+
+/*!
+ \property QScatterSeries::borderColor
+ Line (pen) color of the series. This is a convenience property for modifying the color of pen.
+ \sa QScatterSeries::pen()
+*/
+/*!
+ \qmlproperty color ScatterSeries::borderColor
+ Border (pen) color of the series.
+*/
+
+/*!
+ \qmlproperty real ScatterSeries::borderWidth
+ The width of the border line. By default the width is 2.0.
+*/
+
+/*!
+ \property QScatterSeries::markerShape
+ Defines the shape of the marker used to draw the points in the series. The default shape is MarkerShapeCircle.
+*/
+/*!
+ \qmlproperty MarkerShape ScatterSeries::markerShape
+ Defines the shape of the marker used to draw the points in the series. One of ScatterSeries
+ ScatterSeries.MarkerShapeCircle or ScatterSeries.MarkerShapeRectangle.
+ The default shape is ScatterSeries.MarkerShapeCircle.
+*/
+
+/*!
+ \property QScatterSeries::markerSize
+ Defines the size of the marker used to draw the points in the series. The default size is 15.0.
+*/
+/*!
+ \qmlproperty real ScatterSeries::markerSize
+ Defines the size of the marker used to draw the points in the series. The default size is 15.0.
+*/
+
+/*!
+ \qmlproperty QString ScatterSeries::brushFilename
+ The name of the file used as a brush for the series.
+*/
+
+/*!
+ \fn void QScatterSeries::colorChanged(QColor color)
+ Signal is emitted when the fill (brush) color has changed to \a color.
+*/
+
+/*!
+ \fn void QScatterSeries::borderColorChanged(QColor color)
+ Signal is emitted when the line (pen) color has changed to \a color.
+*/
+/*!
+ \qmlsignal ScatterSeries::borderColorChanged(color color)
+ Signal is emitted when the line (pen) color has changed to \a color.
+*/
+
+/*!
+ \fn QAbstractSeries::SeriesType QScatterSeries::type() const
+ Returns QAbstractSeries::SeriesTypeScatter.
+ \sa QAbstractSeries, SeriesType
+*/
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ Constructs a series object which is a child of \a parent.
+*/
+QScatterSeries::QScatterSeries(QObject *parent)
+ : QXYSeries(*new QScatterSeriesPrivate(this), parent)
+{
+}
+
+/*!
+ Destroys the object. Note that adding series to QChart transfers the ownership to the chart.
+*/
+QScatterSeries::~QScatterSeries()
+{
+ Q_D(QScatterSeries);
+ if (d->m_chart)
+ d->m_chart->removeSeries(this);
+}
+
+QAbstractSeries::SeriesType QScatterSeries::type() const
+{
+ return QAbstractSeries::SeriesTypeScatter;
+}
+
+/*!
+ Sets \a pen used for drawing points' border on the chart. If the pen is not defined, the
+ pen from chart theme is used.
+ \sa QChart::setTheme()
+*/
+void QScatterSeries::setPen(const QPen &pen)
+{
+ Q_D(QXYSeries);
+ if (d->m_pen != pen) {
+ bool emitColorChanged = d->m_pen.color() != pen.color();
+ d->m_pen = pen;
+ emit d->updated();
+ if (emitColorChanged)
+ emit borderColorChanged(pen.color());
+ }
+}
+
+/*!
+ Sets \a brush used for drawing points on the chart. If the brush is not defined, brush
+ from chart theme setting is used.
+ \sa QChart::setTheme()
+*/
+void QScatterSeries::setBrush(const QBrush &brush)
+{
+ Q_D(QScatterSeries);
+ if (d->m_brush != brush) {
+ bool emitColorChanged = d->m_brush.color() != brush.color();
+ d->m_brush = brush;
+ emit d->updated();
+ if (emitColorChanged)
+ emit colorChanged(brush.color());
+ }
+}
+
+QBrush QScatterSeries::brush() const
+{
+ Q_D(const QScatterSeries);
+ if (d->m_brush == QChartPrivate::defaultBrush())
+ return QBrush();
+ else
+ return d->m_brush;
+}
+
+void QScatterSeries::setColor(const QColor &color)
+{
+ QBrush b = brush();
+ if (b == QChartPrivate::defaultBrush())
+ b = QBrush();
+ if (b == QBrush())
+ b.setStyle(Qt::SolidPattern);
+ b.setColor(color);
+ setBrush(b);
+}
+
+QColor QScatterSeries::color() const
+{
+ return brush().color();
+}
+
+void QScatterSeries::setBorderColor(const QColor &color)
+{
+ QPen p = pen();
+ if (p == QChartPrivate::defaultPen())
+ p = QPen();
+ p.setColor(color);
+ setPen(p);
+}
+
+QColor QScatterSeries::borderColor() const
+{
+ return pen().color();
+}
+
+QScatterSeries::MarkerShape QScatterSeries::markerShape() const
+{
+ Q_D(const QScatterSeries);
+ return d->m_shape;
+}
+
+void QScatterSeries::setMarkerShape(MarkerShape shape)
+{
+ Q_D(QScatterSeries);
+ if (d->m_shape != shape) {
+ d->m_shape = shape;
+ emit d->updated();
+ }
+}
+
+qreal QScatterSeries::markerSize() const
+{
+ Q_D(const QScatterSeries);
+ return d->m_size;
+}
+
+void QScatterSeries::setMarkerSize(qreal size)
+{
+ Q_D(QScatterSeries);
+
+ if (!qFuzzyCompare(d->m_size, size)) {
+ d->m_size = size;
+ emit d->updated();
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QScatterSeriesPrivate::QScatterSeriesPrivate(QScatterSeries *q)
+ : QXYSeriesPrivate(q),
+ m_shape(QScatterSeries::MarkerShapeCircle),
+ m_size(15.0)
+{
+}
+
+void QScatterSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
+{
+ Q_Q(QScatterSeries);
+ ScatterChartItem *scatter = new ScatterChartItem(q,parent);
+ m_item.reset(scatter);
+ QAbstractSeriesPrivate::initializeGraphics(parent);
+}
+
+void QScatterSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
+{
+ Q_Q(QScatterSeries);
+ const QList<QColor> colors = theme->seriesColors();
+ const QList<QGradient> gradients = theme->seriesGradients();
+
+ if (forced || QChartPrivate::defaultPen() == m_pen) {
+ QPen pen;
+ pen.setColor(ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0.0));
+ pen.setWidthF(2);
+ q->setPen(pen);
+ }
+
+ if (forced || QChartPrivate::defaultBrush() == m_brush) {
+ QBrush brush(colors.at(index % colors.size()));
+ q->setBrush(brush);
+ }
+
+ if (forced || QChartPrivate::defaultPen().color() == m_pointLabelsColor) {
+ QColor color = theme->labelBrush().color();
+ q->setPointLabelsColor(color);
+ }
+}
+
+void QScatterSeriesPrivate::initializeAnimations(QChart::AnimationOptions options)
+{
+ ScatterChartItem *item = static_cast<ScatterChartItem *>(m_item.data());
+ Q_ASSERT(item);
+
+ if (item->animation())
+ item->animation()->stopAndDestroyLater();
+
+ if (options.testFlag(QChart::SeriesAnimations))
+ item->setAnimation(new ScatterAnimation(item));
+ else
+ item->setAnimation(0);
+
+ QAbstractSeriesPrivate::initializeAnimations(options);
+}
+
+#include "moc_qscatterseries.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/scatterchart/qscatterseries.h b/src/charts/scatterchart/qscatterseries.h
new file mode 100644
index 00000000..d7f9504a
--- /dev/null
+++ b/src/charts/scatterchart/qscatterseries.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCATTERSERIES_H
+#define QSCATTERSERIES_H
+
+#include <QtCharts/qchartglobal.h>
+#include <QtCharts/qxyseries.h>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QScatterSeriesPrivate;
+
+class QT_CHARTS_EXPORT QScatterSeries : public QXYSeries
+{
+ Q_OBJECT
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+ Q_PROPERTY(QColor borderColor READ borderColor WRITE setBorderColor NOTIFY borderColorChanged)
+ Q_PROPERTY(MarkerShape markerShape READ markerShape WRITE setMarkerShape)
+ Q_PROPERTY(qreal markerSize READ markerSize WRITE setMarkerSize)
+ Q_PROPERTY(QBrush brush READ brush WRITE setBrush)
+ Q_ENUMS(MarkerShape)
+
+public:
+ enum MarkerShape {
+ MarkerShapeCircle,
+ MarkerShapeRectangle
+ };
+
+public:
+ explicit QScatterSeries(QObject *parent = 0);
+ ~QScatterSeries();
+ QAbstractSeries::SeriesType type() const;
+ void setPen(const QPen &pen);
+ void setBrush(const QBrush &brush);
+ QBrush brush() const;
+ void setColor(const QColor &color);
+ QColor color() const;
+ void setBorderColor(const QColor &color);
+ QColor borderColor() const;
+ MarkerShape markerShape() const;
+ void setMarkerShape(MarkerShape shape);
+ qreal markerSize() const;
+ void setMarkerSize(qreal size);
+
+Q_SIGNALS:
+ void colorChanged(QColor color);
+ void borderColorChanged(QColor color);
+
+private:
+ Q_DECLARE_PRIVATE(QScatterSeries)
+ Q_DISABLE_COPY(QScatterSeries)
+ friend class ScatterChartItem;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QSCATTERSERIES_H
diff --git a/src/charts/scatterchart/qscatterseries_p.h b/src/charts/scatterchart/qscatterseries_p.h
new file mode 100644
index 00000000..69e91655
--- /dev/null
+++ b/src/charts/scatterchart/qscatterseries_p.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QSCATTERSERIES_P_H
+#define QSCATTERSERIES_P_H
+
+#include "qxyseries_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QScatterSeriesPrivate: public QXYSeriesPrivate
+{
+public:
+ QScatterSeriesPrivate(QScatterSeries *q);
+ void initializeGraphics(QGraphicsItem* parent);
+ void initializeTheme(int index, ChartTheme* theme, bool forced = false);
+ void initializeAnimations(QtCharts::QChart::AnimationOptions options);
+
+private:
+ QScatterSeries::MarkerShape m_shape;
+ qreal m_size;
+ Q_DECLARE_PUBLIC(QScatterSeries)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/scatterchart/scatter.pri b/src/charts/scatterchart/scatter.pri
new file mode 100644
index 00000000..fcbd119d
--- /dev/null
+++ b/src/charts/scatterchart/scatter.pri
@@ -0,0 +1,13 @@
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+
+SOURCES += \
+ $$PWD/qscatterseries.cpp \
+ $$PWD/scatterchartitem.cpp
+
+PRIVATE_HEADERS += \
+ $$PWD/scatterchartitem_p.h \
+ $$PWD/qscatterseries_p.h
+
+PUBLIC_HEADERS += \
+ $$PWD/qscatterseries.h
diff --git a/src/charts/scatterchart/scatterchartitem.cpp b/src/charts/scatterchart/scatterchartitem.cpp
new file mode 100644
index 00000000..597d5d52
--- /dev/null
+++ b/src/charts/scatterchart/scatterchartitem.cpp
@@ -0,0 +1,237 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+ **
+ ** $QT_BEGIN_LICENSE$
+ ** 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
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include "scatterchartitem_p.h"
+#include "qscatterseries.h"
+#include "qscatterseries_p.h"
+#include "chartpresenter_p.h"
+#include "abstractdomain_p.h"
+#include "qchart.h"
+#include <QPainter>
+#include <QGraphicsScene>
+#include <QDebug>
+#include <QGraphicsSceneMouseEvent>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+ScatterChartItem::ScatterChartItem(QScatterSeries *series, QGraphicsItem *item)
+ : XYChart(series,item),
+ m_series(series),
+ m_items(this),
+ m_visible(true),
+ m_shape(QScatterSeries::MarkerShapeRectangle),
+ m_size(15),
+ m_pointLabelsVisible(false),
+ m_pointLabelsFormat(series->pointLabelsFormat()),
+ m_pointLabelsFont(series->pointLabelsFont()),
+ m_pointLabelsColor(series->pointLabelsColor())
+{
+ QObject::connect(m_series->d_func(), SIGNAL(updated()), this, SLOT(handleUpdated()));
+ QObject::connect(m_series, SIGNAL(visibleChanged()), this, SLOT(handleUpdated()));
+ QObject::connect(m_series, SIGNAL(opacityChanged()), this, SLOT(handleUpdated()));
+ QObject::connect(series, SIGNAL(pointLabelsFormatChanged(QString)),
+ this, SLOT(handleUpdated()));
+ QObject::connect(series, SIGNAL(pointLabelsVisibilityChanged(bool)),
+ this, SLOT(handleUpdated()));
+ QObject::connect(series, SIGNAL(pointLabelsFontChanged(QFont)), this, SLOT(handleUpdated()));
+ QObject::connect(series, SIGNAL(pointLabelsColorChanged(QColor)), this, SLOT(handleUpdated()));
+
+ setZValue(ChartPresenter::ScatterSeriesZValue);
+ setFlags(QGraphicsItem::ItemClipsChildrenToShape);
+
+ handleUpdated();
+
+ m_items.setHandlesChildEvents(false);
+}
+
+QRectF ScatterChartItem::boundingRect() const
+{
+ return m_rect;
+}
+
+void ScatterChartItem::createPoints(int count)
+{
+ for (int i = 0; i < count; ++i) {
+
+ QGraphicsItem *item = 0;
+
+ switch (m_shape) {
+ case QScatterSeries::MarkerShapeCircle: {
+ item = new CircleMarker(0, 0, m_size, m_size, this);
+ const QRectF &rect = item->boundingRect();
+ item->setPos(-rect.width() / 2, -rect.height() / 2);
+ break;
+ }
+ case QScatterSeries::MarkerShapeRectangle:
+ item = new RectangleMarker(0, 0, m_size, m_size, this);
+ item->setPos(-m_size / 2, -m_size / 2);
+ break;
+ default:
+ qWarning() << "Unsupported marker type";
+ break;
+ }
+ m_items.addToGroup(item);
+ }
+}
+
+void ScatterChartItem::deletePoints(int count)
+{
+ QList<QGraphicsItem *> items = m_items.childItems();
+
+ for (int i = 0; i < count; ++i) {
+ QGraphicsItem *item = items.takeLast();
+ m_markerMap.remove(item);
+ delete(item);
+ }
+}
+
+void ScatterChartItem::markerSelected(QGraphicsItem *marker)
+{
+ emit XYChart::clicked(m_markerMap[marker]);
+}
+
+void ScatterChartItem::markerHovered(QGraphicsItem *marker, bool state)
+{
+ emit XYChart::hovered(m_markerMap[marker], state);
+}
+
+void ScatterChartItem::updateGeometry()
+{
+
+ const QVector<QPointF>& points = geometryPoints();
+
+ if (points.size() == 0) {
+ deletePoints(m_items.childItems().count());
+ return;
+ }
+
+ int diff = m_items.childItems().size() - points.size();
+
+ if (diff > 0)
+ deletePoints(diff);
+ else if (diff < 0)
+ createPoints(-diff);
+
+ if (diff != 0)
+ handleUpdated();
+
+ QList<QGraphicsItem *> items = m_items.childItems();
+
+ QRectF clipRect(QPointF(0,0),domain()->size());
+
+ // Only zoom in if the clipRect fits inside int limits. QWidget::update() uses
+ // a region that has to be compatible with QRect.
+ if (clipRect.height() <= INT_MAX
+ && clipRect.width() <= INT_MAX) {
+ QVector<bool> offGridStatus = offGridStatusVector();
+ const int seriesLastIndex = m_series->count() - 1;
+
+ for (int i = 0; i < points.size(); i++) {
+ QGraphicsItem *item = items.at(i);
+ const QPointF &point = points.at(i);
+ const QRectF &rect = item->boundingRect();
+ // During remove animation series may have different number of points,
+ // so ensure we don't go over the index. Animation handling itself ensures that
+ // if there is actually no points in the series, then it won't generate a fake point,
+ // so we can be assured there is always at least one point in m_series here.
+ // Note that marker map values can be technically incorrect during the animation,
+ // if it was caused by an insert, but this shouldn't be a problem as the points are
+ // fake anyway. After remove animation stops, geometry is updated to correct one.
+ m_markerMap[item] = m_series->at(qMin(seriesLastIndex, i));
+ item->setPos(point.x() - rect.width() / 2, point.y() - rect.height() / 2);
+
+ if (!m_visible || offGridStatus.at(i))
+ item->setVisible(false);
+ else
+ item->setVisible(true);
+ }
+
+ prepareGeometryChange();
+ m_rect = clipRect;
+ }
+}
+
+void ScatterChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option)
+ Q_UNUSED(widget)
+
+ QRectF clipRect = QRectF(QPointF(0, 0), domain()->size());
+
+ painter->save();
+ painter->setClipRect(clipRect);
+
+ if (m_pointLabelsVisible) {
+ m_series->d_func()->drawSeriesPointLabels(painter, m_points,
+ m_series->markerSize() / 2
+ + m_series->pen().width());
+ }
+
+ painter->restore();
+}
+
+void ScatterChartItem::setPen(const QPen &pen)
+{
+ foreach (QGraphicsItem *item , m_items.childItems())
+ static_cast<QAbstractGraphicsShapeItem*>(item)->setPen(pen);
+}
+
+void ScatterChartItem::setBrush(const QBrush &brush)
+{
+ foreach (QGraphicsItem *item , m_items.childItems())
+ static_cast<QAbstractGraphicsShapeItem*>(item)->setBrush(brush);
+}
+
+void ScatterChartItem::handleUpdated()
+{
+ int count = m_items.childItems().count();
+
+ if (count == 0)
+ return;
+
+ bool recreate = m_visible != m_series->isVisible()
+ || m_size != m_series->markerSize()
+ || m_shape != m_series->markerShape();
+
+ m_visible = m_series->isVisible();
+ m_size = m_series->markerSize();
+ m_shape = m_series->markerShape();
+ setOpacity(m_series->opacity());
+ m_pointLabelsFormat = m_series->pointLabelsFormat();
+ m_pointLabelsVisible = m_series->pointLabelsVisible();
+ m_pointLabelsFont = m_series->pointLabelsFont();
+ m_pointLabelsColor = m_series->pointLabelsColor();
+
+ if (recreate) {
+ deletePoints(count);
+ createPoints(count);
+
+ // Updating geometry is now safe, because it won't call handleUpdated unless it creates/deletes points
+ updateGeometry();
+ }
+
+ setPen(m_series->pen());
+ setBrush(m_series->brush());
+ update();
+}
+
+#include "moc_scatterchartitem_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/scatterchart/scatterchartitem_p.h b/src/charts/scatterchart/scatterchartitem_p.h
new file mode 100644
index 00000000..3c18546e
--- /dev/null
+++ b/src/charts/scatterchart/scatterchartitem_p.h
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 SCATTERCHARTITEM_H
+#define SCATTERCHARTITEM_H
+
+#include "qchartglobal.h"
+#include "xychart_p.h"
+#include <QGraphicsEllipseItem>
+#include <QPen>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QScatterSeries;
+
+class ScatterChartItem : public XYChart
+{
+ Q_OBJECT
+ Q_INTERFACES(QGraphicsItem)
+public:
+ explicit ScatterChartItem(QScatterSeries *series, QGraphicsItem *item = 0);
+
+public:
+ //from QGraphicsItem
+ QRectF boundingRect() const;
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+
+ void setPen(const QPen &pen);
+ void setBrush(const QBrush &brush);
+
+ void markerSelected(QGraphicsItem *item);
+ void markerHovered(QGraphicsItem *item, bool state);
+
+public Q_SLOTS:
+ void handleUpdated();
+
+private:
+ void createPoints(int count);
+ void deletePoints(int count);
+
+protected:
+ void updateGeometry();
+
+private:
+ QScatterSeries *m_series;
+ QGraphicsItemGroup m_items;
+ bool m_visible;
+ int m_shape;
+ int m_size;
+ QRectF m_rect;
+ QMap<QGraphicsItem *, QPointF> m_markerMap;
+
+ bool m_pointLabelsVisible;
+ QString m_pointLabelsFormat;
+ QFont m_pointLabelsFont;
+ QColor m_pointLabelsColor;
+};
+
+class CircleMarker: public QGraphicsEllipseItem
+{
+
+public:
+ CircleMarker(qreal x, qreal y, qreal w, qreal h, ScatterChartItem *parent)
+ : QGraphicsEllipseItem(x, y, w, h, parent),
+ m_parent(parent)
+ {
+ setAcceptHoverEvents(true);
+ }
+
+protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent *event)
+ {
+ QGraphicsEllipseItem::mousePressEvent(event);
+ m_parent->markerSelected(this);
+ }
+ void hoverEnterEvent(QGraphicsSceneHoverEvent *event)
+ {
+ QGraphicsEllipseItem::hoverEnterEvent(event);
+ m_parent->markerHovered(this, true);
+ }
+ void hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
+ {
+ QGraphicsEllipseItem::hoverLeaveEvent(event);
+ m_parent->markerHovered(this, false);
+ }
+
+private:
+ ScatterChartItem *m_parent;
+};
+
+class RectangleMarker: public QGraphicsRectItem
+{
+
+public:
+ RectangleMarker(qreal x, qreal y, qreal w, qreal h, ScatterChartItem *parent)
+ : QGraphicsRectItem(x, y, w, h, parent),
+ m_parent(parent)
+ {
+ setAcceptHoverEvents(true);
+ }
+
+protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent *event)
+ {
+ QGraphicsRectItem::mousePressEvent(event);
+ m_parent->markerSelected(this);
+ }
+ void hoverEnterEvent(QGraphicsSceneHoverEvent *event)
+ {
+ QGraphicsRectItem::hoverEnterEvent(event);
+ m_parent->markerHovered(this, true);
+ }
+ void hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
+ {
+ QGraphicsRectItem::hoverLeaveEvent(event);
+ m_parent->markerHovered(this, false);
+ }
+
+private:
+ ScatterChartItem *m_parent;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // SCATTERPRESENTER_H
diff --git a/src/charts/scroller.cpp b/src/charts/scroller.cpp
new file mode 100644
index 00000000..add8f92a
--- /dev/null
+++ b/src/charts/scroller.cpp
@@ -0,0 +1,216 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "scroller_p.h"
+#include "qlegend.h"
+#include <QGraphicsSceneMouseEvent>
+#include <QDebug>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+Scroller::Scroller()
+ : m_ticker(this),
+ m_timeTresholdMin(50),
+ m_timeTresholdMax(300),
+ m_state(Idle),
+ m_treshold(10)
+{
+
+}
+
+Scroller::~Scroller()
+{
+}
+
+void Scroller::move(const QPointF &delta)
+{
+ switch (m_state) {
+ case Pressed:
+ m_timeStamp = QTime::currentTime();
+ break;
+ case Scroll:
+ stopTicker();
+ m_timeStamp = QTime::currentTime();
+ break;
+ default:
+ break;
+ }
+ setOffset(offset() - delta);
+}
+
+void Scroller::scrollTo(const QPointF &delta)
+{
+ // Starts scrolling, if at least m_timeTresholdMin msecs has gone since timestamp
+ // current time is no more than m_timeTresholdMax from timestamp
+
+ if ((m_timeStamp.elapsed() > m_timeTresholdMin) && (m_timeStamp.msecsTo(QTime::currentTime()) < m_timeTresholdMax)) {
+ // Release was quick enough. Start scrolling.
+ qreal interval = 25;
+ qreal time = m_timeStamp.msecsTo(QTime::currentTime());
+ if (qFuzzyCompare(time, 0)) {
+ m_speed = delta / 5;
+ } else {
+ m_speed = delta * interval / time;
+ }
+
+ qreal fraction = qMax(qAbs(m_speed.x()), qAbs(m_speed.y()));
+
+ if (!qFuzzyCompare(fraction, 0)) {
+ m_fraction.setX(qAbs(m_speed.x() / fraction));
+ m_fraction.setY(qAbs(m_speed.y() / fraction));
+ } else {
+ m_fraction.setX(1);
+ m_fraction.setY(1);
+ }
+ startTicker(interval);
+ } else {
+ stopTicker(); // Stop ticker, if one is running.
+ }
+}
+
+void Scroller::handleMousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ stopTicker();
+ m_pressPos = event->screenPos();
+ m_lastPos = m_pressPos;
+ m_state = Pressed;
+ event->accept();
+}
+
+void Scroller::handleMouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ QPointF delta = event->screenPos() - m_lastPos;
+
+ switch (m_state) {
+ case Pressed: {
+ // calculate treshold. If enough, change to move state and send out move deltas.
+ if (qAbs(delta.x()) > m_treshold || qAbs(delta.y()) > m_treshold) {
+ m_lastPos = event->screenPos();
+ move(delta);
+ m_state = Move;
+ }
+ event->accept();
+ break;
+ }
+ case Move: {
+ m_lastPos = event->screenPos();
+ move(delta);
+ event->accept();
+ break;
+ }
+ case Idle:
+ default: {
+ event->ignore();
+ break;
+ }
+ }
+}
+
+void Scroller::handleMouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ switch (m_state) {
+ case Move:
+ {
+ scrollTo(m_lastPos - m_pressPos);
+ event->accept();
+ break;
+ }
+ default:
+ {
+ m_state = Idle;
+ event->ignore();
+ break;
+ }
+ }
+}
+
+void Scroller::startTicker(int interval)
+{
+ m_state = Scroll;
+ m_ticker.start(interval);
+}
+
+void Scroller::stopTicker()
+{
+ m_state = Idle;
+ m_ticker.stop();
+}
+
+void Scroller::scrollTick()
+{
+ switch (m_state) {
+ case Scroll:
+ lowerSpeed(m_speed);
+ setOffset(offset() - m_speed);
+ if (m_speed == QPointF(0, 0)) {
+ m_state = Idle;
+ m_ticker.stop();
+ }
+ break;
+ default:
+ qWarning() << __FUNCTION__ << "Scroller unexpected state" << m_state;
+ m_ticker.stop();
+ m_state = Idle;
+ break;
+ }
+}
+
+void Scroller::lowerSpeed(QPointF &speed, qreal maxSpeed)
+{
+ qreal x = qBound(-maxSpeed, speed.x(), maxSpeed);
+ qreal y = qBound(-maxSpeed, speed.y(), maxSpeed);
+
+ x = (x == 0) ? x :
+ (x > 0) ? qMax(qreal(0), x - m_fraction.x()) : qMin(qreal(0), x + m_fraction.x());
+ y = (y == 0) ? y :
+ (y > 0) ? qMax(qreal(0), y - m_fraction.y()) : qMin(qreal(0), y + m_fraction.y());
+ speed.setX(x);
+ speed.setY(y);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ScrollTicker::ScrollTicker(Scroller *scroller, QObject *parent)
+ : QObject(parent),
+ m_scroller(scroller)
+{
+
+}
+
+void ScrollTicker::start(int interval)
+{
+ if (!m_timer.isActive())
+ m_timer.start(interval, this);
+}
+
+void ScrollTicker::stop()
+{
+ m_timer.stop();
+}
+
+void ScrollTicker::timerEvent(QTimerEvent *event)
+{
+ Q_UNUSED(event);
+ m_scroller->scrollTick();
+}
+
+#include "moc_scroller_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/scroller_p.h b/src/charts/scroller_p.h
new file mode 100644
index 00000000..35258fc7
--- /dev/null
+++ b/src/charts/scroller_p.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 SCROLLER_P_H
+#define SCROLLER_P_H
+
+#include "qchartglobal.h"
+#include <QBasicTimer>
+#include <QTime>
+#include <QPointF>
+
+class QGraphicsSceneMouseEvent;
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class Scroller;
+class QLegend;
+
+class ScrollTicker : public QObject
+{
+ Q_OBJECT
+public:
+ explicit ScrollTicker(Scroller *scroller, QObject *parent = 0);
+ void start(int interval);
+ void stop();
+protected:
+ void timerEvent(QTimerEvent *event);
+
+private:
+ QBasicTimer m_timer;
+ Scroller *m_scroller;
+};
+
+class Scroller
+{
+public:
+ enum State {
+ Idle,
+ Pressed,
+ Move,
+ Scroll
+ };
+
+ Scroller();
+ virtual ~Scroller();
+
+ virtual void setOffset(const QPointF &point) = 0;
+ virtual QPointF offset() const = 0;
+
+ void move(const QPointF &delta);
+ void scrollTo(const QPointF &delta);
+
+ void handleMousePressEvent(QGraphicsSceneMouseEvent *event);
+ void handleMouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ void handleMouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+
+ void scrollTick();
+
+private:
+ void startTicker(int interval);
+ void stopTicker();
+
+private:
+ void calculateSpeed(const QPointF &position);
+ void lowerSpeed(QPointF &speed, qreal maxSpeed = 100);
+
+private:
+ ScrollTicker m_ticker;
+ QTime m_timeStamp;
+ QPointF m_speed;
+ QPointF m_fraction;
+ int m_timeTresholdMin;
+ int m_timeTresholdMax;
+
+ State m_state;
+ QPointF m_pressPos;
+ QPointF m_lastPos;
+ qreal m_treshold;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif /* SCROLLER_P_H */
diff --git a/src/charts/splinechart/qsplineseries.cpp b/src/charts/splinechart/qsplineseries.cpp
new file mode 100644
index 00000000..2ac5cabf
--- /dev/null
+++ b/src/charts/splinechart/qsplineseries.cpp
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsplineseries.h"
+#include "qsplineseries_p.h"
+#include "splinechartitem_p.h"
+#include "chartdataset_p.h"
+#include "charttheme_p.h"
+#include "splineanimation_p.h"
+#include "qchart_p.h"
+
+/*!
+ \class QSplineSeries
+ \inmodule Qt Charts
+ \brief Series type used to store data needed to draw a spline.
+
+ QSplineSeries stores the data points along with the segment control points needed by QPainterPath to draw spline
+ Control points are automatically calculated when data changes. The algorithm computes the points so that the normal spline can be drawn.
+
+ \image examples_splinechart.png
+
+ Creating basic spline chart is simple:
+ \code
+ QSplineSeries* series = new QSplineSeries();
+ series->append(0, 6);
+ series->append(2, 4);
+ ...
+ chart->addSeries(series);
+ \endcode
+*/
+/*!
+ \qmltype SplineSeries
+ \instantiates QSplineSeries
+ \inqmlmodule QtCharts
+
+ \inherits XYSeries
+
+ \brief The SplineSeries type is used for making spline charts.
+
+ The following QML shows how to create a simple spline chart:
+ \snippet qmlchart/qml/qmlchart/View3.qml 1
+ \beginfloatleft
+ \image examples_qmlchart3.png
+ \endfloat
+ \clearfloat
+*/
+
+/*!
+ \fn QSeriesType QSplineSeries::type() const
+ Returns the type of the series
+*/
+
+/*!
+ \qmlproperty real SplineSeries::width
+ The width of the line. By default the width is 2.0.
+*/
+
+/*!
+ \qmlproperty Qt::PenStyle SplineSeries::style
+ Controls the style of the line. Set to one of Qt.NoPen, Qt.SolidLine, Qt.DashLine, Qt.DotLine,
+ Qt.DashDotLine or Qt.DashDotDotLine. Using Qt.CustomDashLine is not supported in the QML API.
+ By default the style is Qt.SolidLine.
+*/
+
+/*!
+ \qmlproperty Qt::PenCapStyle SplineSeries::capStyle
+ Controls the cap style of the line. Set to one of Qt.FlatCap, Qt.SquareCap or Qt.RoundCap. By
+ default the cap style is Qt.SquareCap.
+*/
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ Constructs empty series object which is a child of \a parent.
+ When series object is added to a QChart instance then the ownerships is transferred.
+ */
+
+QSplineSeries::QSplineSeries(QObject *parent)
+ : QLineSeries(*new QSplineSeriesPrivate(this), parent)
+{
+}
+
+/*!
+ Destroys the object.
+*/
+QSplineSeries::~QSplineSeries()
+{
+ Q_D(QSplineSeries);
+ if (d->m_chart)
+ d->m_chart->removeSeries(this);
+}
+
+QAbstractSeries::SeriesType QSplineSeries::type() const
+{
+ return QAbstractSeries::SeriesTypeSpline;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QSplineSeriesPrivate::QSplineSeriesPrivate(QSplineSeries *q)
+ : QLineSeriesPrivate(q)
+{
+}
+
+void QSplineSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
+{
+ Q_Q(QSplineSeries);
+ SplineChartItem *spline = new SplineChartItem(q,parent);
+ m_item.reset(spline);
+ QAbstractSeriesPrivate::initializeGraphics(parent);
+}
+
+void QSplineSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
+{
+ Q_Q(QSplineSeries);
+ const QList<QColor> colors = theme->seriesColors();
+
+ if (forced || QChartPrivate::defaultPen() == m_pen) {
+ QPen pen;
+ pen.setColor(colors.at(index % colors.size()));
+ pen.setWidthF(2);
+ q->setPen(pen);
+ }
+
+ if (forced || QChartPrivate::defaultPen().color() == m_pointLabelsColor) {
+ QColor color = theme->labelBrush().color();
+ q->setPointLabelsColor(color);
+ }
+}
+
+void QSplineSeriesPrivate::initializeAnimations(QtCharts::QChart::AnimationOptions options)
+{
+ SplineChartItem *item = static_cast<SplineChartItem *>(m_item.data());
+ Q_ASSERT(item);
+ if (item->animation())
+ item->animation()->stopAndDestroyLater();
+
+ if (options.testFlag(QChart::SeriesAnimations))
+ item->setAnimation(new SplineAnimation(item));
+ else
+ item->setAnimation(0);
+ QAbstractSeriesPrivate::initializeAnimations(options);
+}
+
+#include "moc_qsplineseries.cpp"
+#include "moc_qsplineseries_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/splinechart/qsplineseries.h b/src/charts/splinechart/qsplineseries.h
new file mode 100644
index 00000000..a427f02c
--- /dev/null
+++ b/src/charts/splinechart/qsplineseries.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSPLINESERIES_H
+#define QSPLINESERIES_H
+
+#include <QtCharts/qchartglobal.h>
+#include <QtCharts/qlineseries.h>
+#include <QList>
+#include <QPointF>
+#include <QtGlobal>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QSplineSeriesPrivate;
+
+class QT_CHARTS_EXPORT QSplineSeries : public QLineSeries
+{
+ Q_OBJECT
+
+public:
+ explicit QSplineSeries(QObject *parent = 0);
+ ~QSplineSeries();
+ QAbstractSeries::SeriesType type() const;
+
+private:
+ Q_DECLARE_PRIVATE(QSplineSeries)
+ Q_DISABLE_COPY(QSplineSeries)
+ friend class SplineChartItem;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QSPLINESERIES_H
diff --git a/src/charts/splinechart/qsplineseries_p.h b/src/charts/splinechart/qsplineseries_p.h
new file mode 100644
index 00000000..9a786009
--- /dev/null
+++ b/src/charts/splinechart/qsplineseries_p.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QSPLINESERIES_P_H
+#define QSPLINESERIES_P_H
+
+#include "qlineseries_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+
+class QSplineSeriesPrivate: public QLineSeriesPrivate
+{
+ Q_OBJECT
+public:
+ QSplineSeriesPrivate(QSplineSeries *q);
+
+ void initializeTheme(int index, ChartTheme* theme, bool forced = false);
+ void initializeGraphics(QGraphicsItem* parent);
+ void initializeAnimations(QtCharts::QChart::AnimationOptions options);
+
+private:
+ Q_DECLARE_PUBLIC(QSplineSeries)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/splinechart/splinechart.pri b/src/charts/splinechart/splinechart.pri
new file mode 100644
index 00000000..4038685f
--- /dev/null
+++ b/src/charts/splinechart/splinechart.pri
@@ -0,0 +1,13 @@
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+
+SOURCES += \
+ $$PWD/qsplineseries.cpp \
+ $$PWD/splinechartitem.cpp
+
+PRIVATE_HEADERS += \
+ $$PWD/splinechartitem_p.h \
+ $$PWD/qsplineseries_p.h
+
+PUBLIC_HEADERS += \
+ $$PWD/qsplineseries.h
diff --git a/src/charts/splinechart/splinechartitem.cpp b/src/charts/splinechart/splinechartitem.cpp
new file mode 100644
index 00000000..d47cd7ce
--- /dev/null
+++ b/src/charts/splinechart/splinechartitem.cpp
@@ -0,0 +1,485 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+ **
+ ** $QT_BEGIN_LICENSE$
+ ** 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
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include "splinechartitem_p.h"
+#include "qsplineseries_p.h"
+#include "chartpresenter_p.h"
+#include "splineanimation_p.h"
+#include "polardomain_p.h"
+#include <QPainter>
+#include <QGraphicsSceneMouseEvent>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+SplineChartItem::SplineChartItem(QSplineSeries *series, QGraphicsItem *item)
+ : XYChart(series,item),
+ m_series(series),
+ m_pointsVisible(false),
+ m_animation(0),
+ m_pointLabelsVisible(false),
+ m_pointLabelsFormat(series->pointLabelsFormat()),
+ m_pointLabelsFont(series->pointLabelsFont()),
+ m_pointLabelsColor(series->pointLabelsColor())
+{
+ setAcceptHoverEvents(true);
+ setZValue(ChartPresenter::SplineChartZValue);
+ QObject::connect(m_series->d_func(), SIGNAL(updated()), this, SLOT(handleUpdated()));
+ QObject::connect(series, SIGNAL(visibleChanged()), this, SLOT(handleUpdated()));
+ QObject::connect(series, SIGNAL(opacityChanged()), this, SLOT(handleUpdated()));
+ QObject::connect(series, SIGNAL(pointLabelsFormatChanged(QString)),
+ this, SLOT(handleUpdated()));
+ QObject::connect(series, SIGNAL(pointLabelsVisibilityChanged(bool)),
+ this, SLOT(handleUpdated()));
+ QObject::connect(series, SIGNAL(pointLabelsFontChanged(QFont)), this, SLOT(handleUpdated()));
+ QObject::connect(series, SIGNAL(pointLabelsColorChanged(QColor)), this, SLOT(handleUpdated()));
+ handleUpdated();
+}
+
+QRectF SplineChartItem::boundingRect() const
+{
+ return m_rect;
+}
+
+QPainterPath SplineChartItem::shape() const
+{
+ return m_fullPath;
+}
+
+void SplineChartItem::setAnimation(SplineAnimation *animation)
+{
+ m_animation = animation;
+ XYChart::setAnimation(animation);
+}
+
+ChartAnimation *SplineChartItem::animation() const
+{
+ return m_animation;
+}
+
+void SplineChartItem::setControlGeometryPoints(QVector<QPointF>& points)
+{
+ m_controlPoints = points;
+}
+
+QVector<QPointF> SplineChartItem::controlGeometryPoints() const
+{
+ return m_controlPoints;
+}
+
+void SplineChartItem::updateChart(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, int index)
+{
+ QVector<QPointF> controlPoints;
+ if (newPoints.count() >= 2)
+ controlPoints = calculateControlPoints(newPoints);
+
+ if (m_animation)
+ m_animation->setup(oldPoints, newPoints, m_controlPoints, controlPoints, index);
+
+ m_points = newPoints;
+ m_controlPoints = controlPoints;
+ setDirty(false);
+
+ if (m_animation)
+ presenter()->startAnimation(m_animation);
+ else
+ updateGeometry();
+}
+
+void SplineChartItem::updateGeometry()
+{
+ const QVector<QPointF> &points = m_points;
+ const QVector<QPointF> &controlPoints = m_controlPoints;
+
+ if ((points.size() < 2) || (controlPoints.size() < 2)) {
+ prepareGeometryChange();
+ m_path = QPainterPath();
+ m_rect = QRect();
+ return;
+ }
+
+ Q_ASSERT(points.count() * 2 - 2 == controlPoints.count());
+
+ QPainterPath splinePath;
+ QPainterPath fullPath;
+ // Use worst case scenario to determine required margin.
+ qreal margin = m_linePen.width() * 1.42;
+
+ if (m_series->chart()->chartType() == QChart::ChartTypePolar) {
+ QPainterPath splinePathLeft;
+ QPainterPath splinePathRight;
+ QPainterPath *currentSegmentPath = 0;
+ QPainterPath *previousSegmentPath = 0;
+ qreal minX = domain()->minX();
+ qreal maxX = domain()->maxX();
+ qreal minY = domain()->minY();
+ QPointF currentSeriesPoint = m_series->at(0);
+ QPointF currentGeometryPoint = points.at(0);
+ QPointF previousGeometryPoint = points.at(0);
+ bool pointOffGrid = false;
+ bool previousPointWasOffGrid = (currentSeriesPoint.x() < minX || currentSeriesPoint.x() > maxX);
+ m_visiblePoints.clear();
+ m_visiblePoints.reserve(points.size());
+
+ qreal domainRadius = domain()->size().height() / 2.0;
+ const QPointF centerPoint(domainRadius, domainRadius);
+
+ if (!previousPointWasOffGrid) {
+ fullPath.moveTo(points.at(0));
+ // Do not draw points for points below minimum Y.
+ if (m_pointsVisible && currentSeriesPoint.y() >= minY)
+ m_visiblePoints.append(currentGeometryPoint);
+ }
+
+ qreal leftMarginLine = centerPoint.x() - margin;
+ qreal rightMarginLine = centerPoint.x() + margin;
+ qreal horizontal = centerPoint.y();
+
+ // See ScatterChartItem::updateGeometry() for explanation why seriesLastIndex is needed
+ const int seriesLastIndex = m_series->count() - 1;
+
+ for (int i = 1; i < points.size(); i++) {
+ // Interpolating spline fragments accurately is not trivial, and would anyway be ugly
+ // when thick pen is used, so we work around it by utilizing three separate
+ // paths for spline segments and clip those with custom regions at paint time.
+ // "Right" path contains segments that cross the axis line with visible point on the
+ // right side of the axis line, as well as segments that have one point within the margin
+ // on the right side of the axis line and another point on the right side of the chart.
+ // "Left" path contains points with similarly on the left side.
+ // "Full" path contains rest of the points.
+ // This doesn't yield perfect results always. E.g. when segment covers more than 90
+ // degrees and both of the points are within the margin, one in the top half and one in the
+ // bottom half of the chart, the bottom one gets clipped incorrectly.
+ // However, this should be rare occurrence in any sensible chart.
+ currentSeriesPoint = m_series->at(qMin(seriesLastIndex, i));
+ currentGeometryPoint = points.at(i);
+ pointOffGrid = (currentSeriesPoint.x() < minX || currentSeriesPoint.x() > maxX);
+
+ // Draw something unless both off-grid
+ if (!pointOffGrid || !previousPointWasOffGrid) {
+ bool dummyOk; // We know points are ok, but this is needed
+ qreal currentAngle = static_cast<PolarDomain *>(domain())->toAngularCoordinate(currentSeriesPoint.x(), dummyOk);
+ qreal previousAngle = static_cast<PolarDomain *>(domain())->toAngularCoordinate(m_series->at(i - 1).x(), dummyOk);
+
+ if ((qAbs(currentAngle - previousAngle) > 180.0)) {
+ // If the angle between two points is over 180 degrees (half X range),
+ // any direct segment between them becomes meaningless.
+ // In this case two line segments are drawn instead, from previous
+ // point to the center and from center to current point.
+ if ((previousAngle < 0.0 || (previousAngle <= 180.0 && previousGeometryPoint.x() < rightMarginLine))
+ && previousGeometryPoint.y() < horizontal) {
+ currentSegmentPath = &splinePathRight;
+ } else if ((previousAngle > 360.0 || (previousAngle > 180.0 && previousGeometryPoint.x() > leftMarginLine))
+ && previousGeometryPoint.y() < horizontal) {
+ currentSegmentPath = &splinePathLeft;
+ } else if (previousAngle > 0.0 && previousAngle < 360.0) {
+ currentSegmentPath = &splinePath;
+ } else {
+ currentSegmentPath = 0;
+ }
+
+ if (currentSegmentPath) {
+ if (previousSegmentPath != currentSegmentPath)
+ currentSegmentPath->moveTo(previousGeometryPoint);
+ if (!previousSegmentPath)
+ fullPath.moveTo(previousGeometryPoint);
+
+ currentSegmentPath->lineTo(centerPoint);
+ fullPath.lineTo(centerPoint);
+ }
+
+ previousSegmentPath = currentSegmentPath;
+
+ if ((currentAngle < 0.0 || (currentAngle <= 180.0 && currentGeometryPoint.x() < rightMarginLine))
+ && currentGeometryPoint.y() < horizontal) {
+ currentSegmentPath = &splinePathRight;
+ } else if ((currentAngle > 360.0 || (currentAngle > 180.0 &&currentGeometryPoint.x() > leftMarginLine))
+ && currentGeometryPoint.y() < horizontal) {
+ currentSegmentPath = &splinePathLeft;
+ } else if (currentAngle > 0.0 && currentAngle < 360.0) {
+ currentSegmentPath = &splinePath;
+ } else {
+ currentSegmentPath = 0;
+ }
+
+ if (currentSegmentPath) {
+ if (previousSegmentPath != currentSegmentPath)
+ currentSegmentPath->moveTo(centerPoint);
+ if (!previousSegmentPath)
+ fullPath.moveTo(centerPoint);
+
+ currentSegmentPath->lineTo(currentGeometryPoint);
+ fullPath.lineTo(currentGeometryPoint);
+ }
+ } else {
+ QPointF cp1 = controlPoints[2 * (i - 1)];
+ QPointF cp2 = controlPoints[(2 * i) - 1];
+
+ if (previousAngle < 0.0 || currentAngle < 0.0
+ || ((previousAngle <= 180.0 && currentAngle <= 180.0)
+ && ((previousGeometryPoint.x() < rightMarginLine && previousGeometryPoint.y() < horizontal)
+ || (currentGeometryPoint.x() < rightMarginLine && currentGeometryPoint.y() < horizontal)))) {
+ currentSegmentPath = &splinePathRight;
+ } else if (previousAngle > 360.0 || currentAngle > 360.0
+ || ((previousAngle > 180.0 && currentAngle > 180.0)
+ && ((previousGeometryPoint.x() > leftMarginLine && previousGeometryPoint.y() < horizontal)
+ || (currentGeometryPoint.x() > leftMarginLine && currentGeometryPoint.y() < horizontal)))) {
+ currentSegmentPath = &splinePathLeft;
+ } else {
+ currentSegmentPath = &splinePath;
+ }
+
+ if (currentSegmentPath != previousSegmentPath)
+ currentSegmentPath->moveTo(previousGeometryPoint);
+ if (!previousSegmentPath)
+ fullPath.moveTo(previousGeometryPoint);
+
+ fullPath.cubicTo(cp1, cp2, currentGeometryPoint);
+ currentSegmentPath->cubicTo(cp1, cp2, currentGeometryPoint);
+ }
+ } else {
+ currentSegmentPath = 0;
+ }
+
+ previousPointWasOffGrid = pointOffGrid;
+ if (!pointOffGrid && m_pointsVisible && currentSeriesPoint.y() >= minY)
+ m_visiblePoints.append(currentGeometryPoint);
+ previousSegmentPath = currentSegmentPath;
+ previousGeometryPoint = currentGeometryPoint;
+ }
+
+ m_pathPolarRight = splinePathRight;
+ m_pathPolarLeft = splinePathLeft;
+ // Note: This construction of m_fullpath is not perfect. The partial segments that are
+ // outside left/right clip regions at axis boundary still generate hover/click events,
+ // because shape doesn't get clipped. It doesn't seem possible to do sensibly.
+ } else { // not polar
+ splinePath.moveTo(points.at(0));
+ for (int i = 0; i < points.size() - 1; i++) {
+ const QPointF &point = points.at(i + 1);
+ splinePath.cubicTo(controlPoints[2 * i], controlPoints[2 * i + 1], point);
+ }
+ fullPath = splinePath;
+ }
+
+ QPainterPathStroker stroker;
+ // The full path is comprised of three separate paths.
+ // This is why we are prepared for the "worst case" scenario, i.e. use always MiterJoin and
+ // multiply line width with square root of two when defining shape and bounding rectangle.
+ stroker.setWidth(margin);
+ stroker.setJoinStyle(Qt::MiterJoin);
+ stroker.setCapStyle(Qt::SquareCap);
+ stroker.setMiterLimit(m_linePen.miterLimit());
+
+ // Only zoom in if the bounding rects of the path fit inside int limits. QWidget::update() uses
+ // a region that has to be compatible with QRect.
+ QPainterPath checkShapePath = stroker.createStroke(fullPath);
+ if (checkShapePath.boundingRect().height() <= INT_MAX
+ && checkShapePath.boundingRect().width() <= INT_MAX
+ && splinePath.boundingRect().height() <= INT_MAX
+ && splinePath.boundingRect().width() <= INT_MAX) {
+ m_path = splinePath;
+
+ prepareGeometryChange();
+
+ m_fullPath = checkShapePath;
+ m_rect = m_fullPath.boundingRect();
+ }
+}
+
+/*!
+ Calculates control points which are needed by QPainterPath.cubicTo function to draw the cubic Bezier cureve between two points.
+ */
+QVector<QPointF> SplineChartItem::calculateControlPoints(const QVector<QPointF> &points)
+{
+ QVector<QPointF> controlPoints;
+ controlPoints.resize(points.count() * 2 - 2);
+
+ int n = points.count() - 1;
+
+ if (n == 1) {
+ //for n==1
+ controlPoints[0].setX((2 * points[0].x() + points[1].x()) / 3);
+ controlPoints[0].setY((2 * points[0].y() + points[1].y()) / 3);
+ controlPoints[1].setX(2 * controlPoints[0].x() - points[0].x());
+ controlPoints[1].setY(2 * controlPoints[0].y() - points[0].y());
+ return controlPoints;
+ }
+
+ // Calculate first Bezier control points
+ // Set of equations for P0 to Pn points.
+ //
+ // | 2 1 0 0 ... 0 0 0 ... 0 0 0 | | P1_1 | | P0 + 2 * P1 |
+ // | 1 4 1 0 ... 0 0 0 ... 0 0 0 | | P1_2 | | 4 * P1 + 2 * P2 |
+ // | 0 1 4 1 ... 0 0 0 ... 0 0 0 | | P1_3 | | 4 * P2 + 2 * P3 |
+ // | . . . . . . . . . . . . | | ... | | ... |
+ // | 0 0 0 0 ... 1 4 1 ... 0 0 0 | * | P1_i | = | 4 * P(i-1) + 2 * Pi |
+ // | . . . . . . . . . . . . | | ... | | ... |
+ // | 0 0 0 0 0 0 0 0 ... 1 4 1 | | P1_(n-1)| | 4 * P(n-2) + 2 * P(n-1) |
+ // | 0 0 0 0 0 0 0 0 ... 0 2 7 | | P1_n | | 8 * P(n-1) + Pn |
+ //
+ QVector<qreal> vector;
+ vector.resize(n);
+
+ vector[0] = points[0].x() + 2 * points[1].x();
+
+
+ for (int i = 1; i < n - 1; ++i)
+ vector[i] = 4 * points[i].x() + 2 * points[i + 1].x();
+
+ vector[n - 1] = (8 * points[n - 1].x() + points[n].x()) / 2.0;
+
+ QVector<qreal> xControl = firstControlPoints(vector);
+
+ vector[0] = points[0].y() + 2 * points[1].y();
+
+ for (int i = 1; i < n - 1; ++i)
+ vector[i] = 4 * points[i].y() + 2 * points[i + 1].y();
+
+ vector[n - 1] = (8 * points[n - 1].y() + points[n].y()) / 2.0;
+
+ QVector<qreal> yControl = firstControlPoints(vector);
+
+ for (int i = 0, j = 0; i < n; ++i, ++j) {
+
+ controlPoints[j].setX(xControl[i]);
+ controlPoints[j].setY(yControl[i]);
+
+ j++;
+
+ if (i < n - 1) {
+ controlPoints[j].setX(2 * points[i + 1].x() - xControl[i + 1]);
+ controlPoints[j].setY(2 * points[i + 1].y() - yControl[i + 1]);
+ } else {
+ controlPoints[j].setX((points[n].x() + xControl[n - 1]) / 2);
+ controlPoints[j].setY((points[n].y() + yControl[n - 1]) / 2);
+ }
+ }
+ return controlPoints;
+}
+
+QVector<qreal> SplineChartItem::firstControlPoints(const QVector<qreal>& vector)
+{
+ QVector<qreal> result;
+
+ int count = vector.count();
+ result.resize(count);
+ result[0] = vector[0] / 2.0;
+
+ QVector<qreal> temp;
+ temp.resize(count);
+ temp[0] = 0;
+
+ qreal b = 2.0;
+
+ for (int i = 1; i < count; i++) {
+ temp[i] = 1 / b;
+ b = (i < count - 1 ? 4.0 : 3.5) - temp[i];
+ result[i] = (vector[i] - result[i - 1]) / b;
+ }
+
+ for (int i = 1; i < count; i++)
+ result[count - i - 1] -= temp[count - i] * result[count - i];
+
+ return result;
+}
+
+//handlers
+
+void SplineChartItem::handleUpdated()
+{
+ setVisible(m_series->isVisible());
+ setOpacity(m_series->opacity());
+ m_pointsVisible = m_series->pointsVisible();
+ m_linePen = m_series->pen();
+ m_pointPen = m_series->pen();
+ m_pointPen.setWidthF(2 * m_pointPen.width());
+ m_pointLabelsFormat = m_series->pointLabelsFormat();
+ m_pointLabelsVisible = m_series->pointLabelsVisible();
+ m_pointLabelsFont = m_series->pointLabelsFont();
+ m_pointLabelsColor = m_series->pointLabelsColor();
+ update();
+}
+
+//painter
+
+void SplineChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(widget)
+ Q_UNUSED(option)
+
+ QRectF clipRect = QRectF(QPointF(0, 0), domain()->size());
+
+ painter->save();
+ painter->setPen(m_linePen);
+ painter->setBrush(Qt::NoBrush);
+
+ if (m_series->chart()->chartType() == QChart::ChartTypePolar) {
+ qreal halfWidth = domain()->size().width() / 2.0;
+ QRectF clipRectLeft = QRectF(0, 0, halfWidth, domain()->size().height());
+ QRectF clipRectRight = QRectF(halfWidth, 0, halfWidth, domain()->size().height());
+ QRegion fullPolarClipRegion(clipRect.toRect(), QRegion::Ellipse);
+ QRegion clipRegionLeft(fullPolarClipRegion.intersected(clipRectLeft.toRect()));
+ QRegion clipRegionRight(fullPolarClipRegion.intersected(clipRectRight.toRect()));
+ painter->setClipRegion(clipRegionLeft);
+ painter->drawPath(m_pathPolarLeft);
+ painter->setClipRegion(clipRegionRight);
+ painter->drawPath(m_pathPolarRight);
+ painter->setClipRegion(fullPolarClipRegion);
+ } else {
+ painter->setClipRect(clipRect);
+ }
+
+ painter->drawPath(m_path);
+
+ if (m_pointsVisible) {
+ painter->setPen(m_pointPen);
+ if (m_series->chart()->chartType() == QChart::ChartTypePolar)
+ painter->drawPoints(m_visiblePoints);
+ else
+ painter->drawPoints(geometryPoints());
+ }
+
+ if (m_pointLabelsVisible)
+ m_series->d_func()->drawSeriesPointLabels(painter, m_points, m_linePen.width() / 2);
+
+ painter->restore();
+}
+
+void SplineChartItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ emit XYChart::clicked(domain()->calculateDomainPoint(event->pos()));
+ QGraphicsItem::mousePressEvent(event);
+}
+
+void SplineChartItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
+{
+ emit XYChart::hovered(domain()->calculateDomainPoint(event->pos()), true);
+ QGraphicsItem::hoverEnterEvent(event);
+}
+
+void SplineChartItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
+{
+ emit XYChart::hovered(domain()->calculateDomainPoint(event->pos()), false);
+ QGraphicsItem::hoverLeaveEvent(event);
+}
+
+#include "moc_splinechartitem_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/splinechart/splinechartitem_p.h b/src/charts/splinechart/splinechartitem_p.h
new file mode 100644
index 00000000..ac323e59
--- /dev/null
+++ b/src/charts/splinechart/splinechartitem_p.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 SPLINECHARTITEM_P_H
+#define SPLINECHARTITEM_P_H
+
+#include "qsplineseries.h"
+#include "xychart_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class SplineAnimation;
+
+class SplineChartItem : public XYChart
+{
+ Q_OBJECT
+ Q_INTERFACES(QGraphicsItem)
+public:
+ SplineChartItem(QSplineSeries *series, QGraphicsItem *item = 0);
+
+ //from QGraphicsItem
+ QRectF boundingRect() const;
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+ QPainterPath shape() const;
+
+ void setControlGeometryPoints(QVector<QPointF>& points);
+ QVector<QPointF> controlGeometryPoints() const;
+
+ void setAnimation(SplineAnimation *animation);
+ ChartAnimation *animation() const;
+
+public Q_SLOTS:
+ void handleUpdated();
+
+protected:
+ void updateGeometry();
+ QVector<QPointF> calculateControlPoints(const QVector<QPointF> &points);
+ QVector<qreal> firstControlPoints(const QVector<qreal>& vector);
+ void updateChart(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, int index);
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
+ void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
+
+private:
+ QSplineSeries *m_series;
+ QPainterPath m_path;
+ QPainterPath m_pathPolarRight;
+ QPainterPath m_pathPolarLeft;
+ QPainterPath m_fullPath;
+ QRectF m_rect;
+ QPen m_linePen;
+ QPen m_pointPen;
+ bool m_pointsVisible;
+ QVector<QPointF> m_controlPoints;
+ QVector<QPointF> m_visiblePoints;
+ SplineAnimation *m_animation;
+
+ bool m_pointLabelsVisible;
+ QString m_pointLabelsFormat;
+ QFont m_pointLabelsFont;
+ QColor m_pointLabelsColor;
+
+ friend class SplineAnimation;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // SPLINECHARTITEM_P_H
diff --git a/src/charts/themes/charttheme_p.h b/src/charts/themes/charttheme_p.h
new file mode 100644
index 00000000..58510bd7
--- /dev/null
+++ b/src/charts/themes/charttheme_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTTHEME_H
+#define CHARTTHEME_H
+
+#include "chartthememanager_p.h"
+#include <QColor>
+#include <QGradientStops>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class ChartTheme
+{
+
+public:
+ enum BackgroundShadesMode {
+ BackgroundShadesNone = 0,
+ BackgroundShadesVertical,
+ BackgroundShadesHorizontal,
+ BackgroundShadesBoth
+ };
+
+protected:
+ explicit ChartTheme(QChart::ChartTheme id = QChart::ChartThemeLight):m_id(id),
+ m_backgroundShadesBrush(Qt::SolidPattern),
+ m_backgroundShades(BackgroundShadesNone),
+ m_backgroundDropShadowEnabled(false)
+ {};
+public:
+ QChart::ChartTheme id() const { return m_id; }
+ QList<QGradient> seriesGradients() const { return m_seriesGradients; }
+ QList<QColor> seriesColors() const { return m_seriesColors; }
+ QLinearGradient chartBackgroundGradient() const { return m_chartBackgroundGradient; }
+ QFont masterFont() const { return m_masterFont; }
+ QFont labelFont() const { return m_labelFont; }
+ QBrush labelBrush() const { return m_labelBrush; }
+ QPen axisLinePen() const { return m_axisLinePen; }
+ QPen backgroundShadesPen() const { return m_backgroundShadesPen; }
+ QPen outlinePen() const { return m_outlinePen; }
+ QBrush backgroundShadesBrush() const { return m_backgroundShadesBrush; }
+ BackgroundShadesMode backgroundShades() const { return m_backgroundShades; }
+ bool isBackgroundDropShadowEnabled() const { return m_backgroundDropShadowEnabled; }
+ QPen girdLinePen() const { return m_gridLinePen; }
+
+protected:
+ QChart::ChartTheme m_id;
+ QList<QColor> m_seriesColors;
+ QList<QGradient> m_seriesGradients;
+ QLinearGradient m_chartBackgroundGradient;
+
+ QFont m_masterFont;
+ QFont m_labelFont;
+ QBrush m_labelBrush;
+ QPen m_axisLinePen;
+ QPen m_backgroundShadesPen;
+ QPen m_outlinePen;
+ QBrush m_backgroundShadesBrush;
+ BackgroundShadesMode m_backgroundShades;
+ bool m_backgroundDropShadowEnabled;
+ QPen m_gridLinePen;
+
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // CHARTTHEME_H
diff --git a/src/charts/themes/chartthemebluecerulean_p.h b/src/charts/themes/chartthemebluecerulean_p.h
new file mode 100644
index 00000000..83f1441a
--- /dev/null
+++ b/src/charts/themes/chartthemebluecerulean_p.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTTHEMEBLUECERULEAN_P_H
+#define CHARTTHEMEBLUECERULEAN_P_H
+
+#include "charttheme_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class ChartThemeBlueCerulean: public ChartTheme
+{
+public:
+ ChartThemeBlueCerulean() : ChartTheme(QChart::ChartThemeBlueCerulean) {
+ // Series colors
+ m_seriesColors << QRgb(0xc7e85b);
+ m_seriesColors << QRgb(0x1cb54f);
+ m_seriesColors << QRgb(0x5cbf9b);
+ m_seriesColors << QRgb(0x009fbf);
+ m_seriesColors << QRgb(0xee7392);
+ m_seriesGradients = ChartThemeManager::generateSeriesGradients(m_seriesColors);
+
+ // Background
+ QLinearGradient backgroundGradient(0.5, 0.0, 0.5, 1.0);
+ backgroundGradient.setColorAt(0.0, QRgb(0x056189));
+ backgroundGradient.setColorAt(1.0, QRgb(0x101a31));
+ backgroundGradient.setCoordinateMode(QGradient::ObjectBoundingMode);
+ m_chartBackgroundGradient = backgroundGradient;
+
+ // Axes and other
+ m_labelBrush = QBrush(QRgb(0xffffff));
+ m_axisLinePen = QPen(QRgb(0xd6d6d6));
+ m_axisLinePen.setWidth(2);
+ m_gridLinePen = QPen(QRgb(0x84a2b0));
+ m_gridLinePen.setWidth(1);
+ m_backgroundShades = BackgroundShadesNone;
+ m_outlinePen = QPen(QRgb(0xebebeb));
+ m_outlinePen.setWidthF(2.0);
+ }
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/themes/chartthemeblueicy_p.h b/src/charts/themes/chartthemeblueicy_p.h
new file mode 100644
index 00000000..6dc6c9c4
--- /dev/null
+++ b/src/charts/themes/chartthemeblueicy_p.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTTHEMEBLUEICY_P_H
+#define CHARTTHEMEBLUEICY_P_H
+
+#include "charttheme_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class ChartThemeBlueIcy: public ChartTheme
+{
+public:
+ ChartThemeBlueIcy() : ChartTheme(QChart::ChartThemeBlueIcy)
+ {
+ // Series colors
+ m_seriesColors << QRgb(0x3daeda);
+ m_seriesColors << QRgb(0x2685bf);
+ m_seriesColors << QRgb(0x0c2673);
+ m_seriesColors << QRgb(0x5f3dba);
+ m_seriesColors << QRgb(0x2fa3b4);
+ m_seriesGradients = ChartThemeManager::generateSeriesGradients(m_seriesColors);
+
+ // Background
+ QLinearGradient backgroundGradient(0.5, 0.0, 0.5, 1.0);
+ backgroundGradient.setColorAt(0.0, QRgb(0xffffff));
+ backgroundGradient.setColorAt(1.0, QRgb(0xffffff));
+ backgroundGradient.setCoordinateMode(QGradient::ObjectBoundingMode);
+ m_chartBackgroundGradient = backgroundGradient;
+ m_backgroundDropShadowEnabled = true;
+
+ // Axes and other
+ m_labelBrush = QBrush(QRgb(0x404044));
+ m_axisLinePen = QPen(QRgb(0xd6d6d6));
+ m_axisLinePen.setWidth(2);
+ m_gridLinePen = QPen(QRgb(0xe2e2e2));
+ m_gridLinePen.setWidth(1);
+ m_backgroundShades = BackgroundShadesNone;
+ m_outlinePen = QPen(QRgb(0x474747));
+ m_outlinePen.setWidthF(2.0);
+ }
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/themes/chartthemebluencs_p.h b/src/charts/themes/chartthemebluencs_p.h
new file mode 100644
index 00000000..7806fd02
--- /dev/null
+++ b/src/charts/themes/chartthemebluencs_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTTHEMEBLUENCS_P_H
+#define CHARTTHEMEBLUENCS_P_H
+
+#include "charttheme_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class ChartThemeBlueNcs: public ChartTheme
+{
+public:
+ ChartThemeBlueNcs() : ChartTheme(QChart::ChartThemeBlueNcs)
+ {
+ // Series colors
+ m_seriesColors << QRgb(0x1db0da);
+ m_seriesColors << QRgb(0x1341a6);
+ m_seriesColors << QRgb(0x88d41e);
+ m_seriesColors << QRgb(0xff8e1a);
+ m_seriesColors << QRgb(0x398ca3);
+ m_seriesGradients = ChartThemeManager::generateSeriesGradients(m_seriesColors);
+
+ // Background
+ QLinearGradient backgroundGradient;
+ backgroundGradient.setColorAt(0.0, QRgb(0xffffff));
+ backgroundGradient.setColorAt(1.0, QRgb(0xffffff));
+ backgroundGradient.setCoordinateMode(QGradient::ObjectBoundingMode);
+ m_chartBackgroundGradient = backgroundGradient;
+
+ // Axes and other
+ m_labelBrush = QBrush(QRgb(0x404044));
+ m_axisLinePen = QPen(QRgb(0xd6d6d6));
+ m_axisLinePen.setWidth(2);
+ m_gridLinePen = QPen(QRgb(0xe2e2e2));
+ m_gridLinePen.setWidth(1);
+ m_backgroundShades = BackgroundShadesNone;
+ m_outlinePen = QPen(QRgb(0x474747));
+ m_outlinePen.setWidthF(2.0);
+ }
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/themes/chartthemebrownsand_p.h b/src/charts/themes/chartthemebrownsand_p.h
new file mode 100644
index 00000000..9a980855
--- /dev/null
+++ b/src/charts/themes/chartthemebrownsand_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTTHEMEBROWNSAND_P_H
+#define CHARTTHEMEBROWNSAND_P_H
+
+#include "charttheme_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class ChartThemeBrownSand: public ChartTheme
+{
+public:
+ ChartThemeBrownSand() : ChartTheme(QChart::ChartThemeBrownSand)
+ {
+ // Series colors
+ m_seriesColors << QRgb(0xb39b72);
+ m_seriesColors << QRgb(0xb3b376);
+ m_seriesColors << QRgb(0xc35660);
+ m_seriesColors << QRgb(0x536780);
+ m_seriesColors << QRgb(0x494345);
+ m_seriesGradients = ChartThemeManager::generateSeriesGradients(m_seriesColors);
+
+ // Background
+ QLinearGradient backgroundGradient;
+ backgroundGradient.setColorAt(0.0, QRgb(0xf3ece0));
+ backgroundGradient.setColorAt(1.0, QRgb(0xf3ece0));
+ backgroundGradient.setCoordinateMode(QGradient::ObjectBoundingMode);
+ m_chartBackgroundGradient = backgroundGradient;
+
+ // Axes and other
+ m_labelBrush = QBrush(QRgb(0x404044));
+ m_axisLinePen = QPen(QRgb(0xb5b0a7));
+ m_axisLinePen.setWidth(2);
+ m_gridLinePen = QPen(QRgb(0xd4cec3));
+ m_gridLinePen.setWidth(1);
+ m_backgroundShades = BackgroundShadesNone;
+ m_outlinePen = QPen(QRgb(0x222222));
+ m_outlinePen.setWidthF(2.0);
+ }
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/themes/chartthemedark_p.h b/src/charts/themes/chartthemedark_p.h
new file mode 100644
index 00000000..6ad3eaf7
--- /dev/null
+++ b/src/charts/themes/chartthemedark_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTTHEMEDARK_P_H
+#define CHARTTHEMEDARK_P_H
+
+#include "charttheme_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class ChartThemeDark : public ChartTheme
+{
+public:
+ ChartThemeDark() : ChartTheme(QChart::ChartThemeDark)
+ {
+ // Series colors
+ m_seriesColors << QRgb(0x38ad6b);
+ m_seriesColors << QRgb(0x3c84a7);
+ m_seriesColors << QRgb(0xeb8817);
+ m_seriesColors << QRgb(0x7b7f8c);
+ m_seriesColors << QRgb(0xbf593e);
+ m_seriesGradients = ChartThemeManager::generateSeriesGradients(m_seriesColors);
+
+ // Background
+ QLinearGradient backgroundGradient(0.5, 0.0, 0.5, 1.0);
+ backgroundGradient.setColorAt(0.0, QRgb(0x2e303a));
+ backgroundGradient.setColorAt(1.0, QRgb(0x121218));
+ backgroundGradient.setCoordinateMode(QGradient::ObjectBoundingMode);
+ m_chartBackgroundGradient = backgroundGradient;
+
+ // Axes and other
+ m_labelBrush = QBrush(QRgb(0xffffff));
+ m_axisLinePen = QPen(QRgb(0x86878c));
+ m_axisLinePen.setWidth(2);
+ m_gridLinePen = QPen(QRgb(0x86878c));
+ m_gridLinePen.setWidth(1);
+ m_backgroundShades = BackgroundShadesNone;
+ m_outlinePen = QPen(QRgb(0xd6d6d6));
+ m_outlinePen.setWidthF(2.0);
+ }
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/themes/chartthemehighcontrast_p.h b/src/charts/themes/chartthemehighcontrast_p.h
new file mode 100644
index 00000000..353cc659
--- /dev/null
+++ b/src/charts/themes/chartthemehighcontrast_p.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTTHEMEHIGHCONTRAST_P_H
+#define CHARTTHEMEHIGHCONTRAST_P_H
+
+#include "charttheme_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class ChartThemeHighContrast : public ChartTheme
+{
+public:
+ ChartThemeHighContrast() : ChartTheme(QChart::ChartThemeHighContrast)
+ {
+ // Series colors
+ m_seriesColors << QRgb(0x202020);
+ m_seriesColors << QRgb(0x596a74);
+ m_seriesColors << QRgb(0xffab03);
+ m_seriesColors << QRgb(0x038e9b);
+ m_seriesColors << QRgb(0xff4a41);
+ m_seriesGradients = ChartThemeManager::generateSeriesGradients(m_seriesColors);
+
+ // Background
+ QLinearGradient backgroundGradient(0.5, 0.0, 0.5, 1.0);
+ backgroundGradient.setColorAt(0.0, QRgb(0xffffff));
+ backgroundGradient.setColorAt(1.0, QRgb(0xffffff));
+ backgroundGradient.setCoordinateMode(QGradient::ObjectBoundingMode);
+ m_chartBackgroundGradient = backgroundGradient;
+ m_backgroundDropShadowEnabled = true;
+
+ // Axes and other
+ m_labelBrush = QBrush(QRgb(0x181818));
+ m_axisLinePen = QPen(QRgb(0x8c8c8c));
+ m_axisLinePen.setWidth(2);
+ m_gridLinePen = QPen(QRgb(0x8c8c8c));
+ m_gridLinePen.setWidth(1);
+ m_backgroundShadesBrush = QBrush(QRgb(0xffeecd));
+ m_backgroundShades = BackgroundShadesHorizontal;
+ m_outlinePen = QPen(QColor(Qt::black));
+ m_outlinePen.setWidthF(2.0);
+ }
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/themes/chartthemelight_p.h b/src/charts/themes/chartthemelight_p.h
new file mode 100644
index 00000000..161c3567
--- /dev/null
+++ b/src/charts/themes/chartthemelight_p.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTTHEMELIGHT_P_H
+#define CHARTTHEMELIGHT_P_H
+
+#include "charttheme_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class ChartThemeLight: public ChartTheme
+{
+public:
+ ChartThemeLight() : ChartTheme(QChart::ChartThemeLight)
+ {
+ // Series colors
+ m_seriesColors << QRgb(0x209fdf);
+ m_seriesColors << QRgb(0x99ca53);
+ m_seriesColors << QRgb(0xf6a625);
+ m_seriesColors << QRgb(0x6d5fd5);
+ m_seriesColors << QRgb(0xbf593e);
+ m_seriesGradients = ChartThemeManager::generateSeriesGradients(m_seriesColors);
+
+ // Background
+ QLinearGradient backgroundGradient;
+ backgroundGradient.setColorAt(0.0, QRgb(0xffffff));
+ backgroundGradient.setColorAt(1.0, QRgb(0xffffff));
+ backgroundGradient.setCoordinateMode(QGradient::ObjectBoundingMode);
+ m_chartBackgroundGradient = backgroundGradient;
+ // There is a performance issue in the drop shadow implementation, so disabled for now
+// m_backgroundDropShadowEnabled = true;
+
+ // Axes and other
+ m_axisLinePen = QPen(0xd6d6d6);
+ m_axisLinePen.setWidth(1);
+ m_labelBrush = QBrush(QRgb(0x404044));
+ m_gridLinePen = QPen(QRgb(0xe2e2e2));
+ m_gridLinePen.setWidth(1);
+ m_backgroundShades = BackgroundShadesNone;
+ m_outlinePen = QPen(0x4d4d4d);
+ m_outlinePen.setWidthF(2.0);
+ }
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/themes/chartthemeqt_p.h b/src/charts/themes/chartthemeqt_p.h
new file mode 100644
index 00000000..06c10eee
--- /dev/null
+++ b/src/charts/themes/chartthemeqt_p.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTTHEMEQT_P_H
+#define CHARTTHEMEQT_P_H
+
+#include "charttheme_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class ChartThemeQt : public ChartTheme
+{
+public:
+ ChartThemeQt() : ChartTheme(QChart::ChartThemeQt)
+ {
+ // Series colors
+ m_seriesColors << QRgb(0x80c342);
+ m_seriesColors << QRgb(0x328930);
+ m_seriesColors << QRgb(0x006325);
+ m_seriesColors << QRgb(0x35322f);
+ m_seriesColors << QRgb(0x5d5b59);
+ m_seriesColors << QRgb(0x868482);
+ m_seriesColors << QRgb(0xaeadac);
+ m_seriesColors << QRgb(0xd7d6d5);
+ m_seriesGradients = ChartThemeManager::generateSeriesGradients(m_seriesColors);
+
+ // Background
+ QLinearGradient backgroundGradient(0.5, 0.0, 0.5, 1.0);
+ backgroundGradient.setColorAt(0.0, QRgb(0xffffff));
+ backgroundGradient.setColorAt(1.0, QRgb(0xffffff));
+ backgroundGradient.setCoordinateMode(QGradient::ObjectBoundingMode);
+ m_chartBackgroundGradient = backgroundGradient;
+
+ // Axes and other
+ m_labelBrush = QBrush(QRgb(0x35322f));
+ m_axisLinePen = QPen(QRgb(0xd7d6d5));
+ m_axisLinePen.setWidth(1);
+ m_gridLinePen = QPen(QRgb(0xd7d6d5));
+ m_gridLinePen.setWidth(1);
+ m_backgroundShades = BackgroundShadesNone;
+ m_outlinePen = QPen(QRgb(0x35322f));
+ m_outlinePen.setWidthF(2.0);
+ }
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/themes/chartthemesystem_p.h b/src/charts/themes/chartthemesystem_p.h
new file mode 100644
index 00000000..8d99d5b1
--- /dev/null
+++ b/src/charts/themes/chartthemesystem_p.h
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 CHARTTHEMESYSTEM_P_H
+#define CHARTTHEMESYSTEM_P_H
+
+#include "charttheme_p.h"
+#ifdef Q_OS_WIN
+#include <windows.h>
+#include <stdio.h>
+#endif
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class ChartThemeSystem: public ChartTheme
+{
+public:
+ // System theme not used at the moment (the user is not able to select this theme)
+ ChartThemeSystem() : ChartTheme(QChart::ChartThemeLight /*QChart::ChartThemeSystem*/)
+ {
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+ // We could also use theme specific window frame color as a series base color (it would give more
+ // variation to the base colors in addition to the blue and black used now)
+
+ // First series base color from COLOR_HIGHLIGHT
+ DWORD colorHighlight;
+ colorHighlight = GetSysColor(COLOR_HIGHLIGHT);
+ m_seriesColors.append(QColor(GetRValue(colorHighlight),
+ GetGValue(colorHighlight),
+ GetBValue(colorHighlight)));
+
+ // Second series base color from COLOR_WINDOWFRAME
+ DWORD colorWindowFrame;
+ colorWindowFrame = GetSysColor(COLOR_WINDOWFRAME);
+ m_seriesColors.append(QColor(GetRValue(colorWindowFrame),
+ GetGValue(colorWindowFrame),
+ GetBValue(colorWindowFrame)));
+
+ // Third series base color from the middle of the COLOR_ACTIVECAPTION /
+ // COLOR_GRADIENTACTIVECAPTION gradient
+ DWORD colorGradientActiveCaptionLeft;
+ colorGradientActiveCaptionLeft = GetSysColor(COLOR_ACTIVECAPTION);
+ DWORD colorGradientActiveCaptionRight;
+ colorGradientActiveCaptionRight = GetSysColor(COLOR_GRADIENTACTIVECAPTION);
+ QLinearGradient g;
+ QColor start = QColor(GetRValue(colorGradientActiveCaptionLeft),
+ GetGValue(colorGradientActiveCaptionLeft),
+ GetBValue(colorGradientActiveCaptionLeft));
+ g.setColorAt(0.0, start);
+ QColor end = QColor(GetRValue(colorGradientActiveCaptionRight),
+ GetGValue(colorGradientActiveCaptionRight),
+ GetBValue(colorGradientActiveCaptionRight));
+ g.setColorAt(1.0, end);
+ m_seriesColors.append(ChartThemeManager::colorAt(g, 0.5));
+
+ // Generate gradients from the base colors
+ m_seriesGradients = ChartThemeManager::generateSeriesGradients(m_seriesColors);
+
+ // Background fill color from COLOR_WINDOW
+ QLinearGradient backgroundGradient;
+ DWORD colorWindow;
+ colorWindow = GetSysColor(COLOR_WINDOW);
+ backgroundGradient.setColorAt(0.0, QColor(GetRValue(colorWindow),
+ GetGValue(colorWindow),
+ GetBValue(colorWindow)));
+ backgroundGradient.setColorAt(1.0, QColor(GetRValue(colorWindow),
+ GetGValue(colorWindow),
+ GetBValue(colorWindow)));
+ // Axes and other
+ m_axisLinePen = QPen(0xd6d6d6);
+ m_axisLinePen.setWidth(1);
+ m_labelBrush = QBrush(QRgb(0x404044));
+ m_gridLinePen = QPen(QRgb(0xe2e2e2));
+ m_gridLinePen.setWidth(1);
+ m_backgroundShades = BackgroundShadesNone;
+
+#elif defined(Q_OS_LINUX)
+ // Using a hard coded theme for Linux system theme
+ m_seriesColors << QRgb(0x60a6e6);
+ m_seriesColors << QRgb(0x92ca66);
+ m_seriesColors << QRgb(0xeba85f);
+ m_seriesColors << QRgb(0xfc5751);
+ m_seriesGradients = ChartThemeManager::generateSeriesGradients(m_seriesColors);
+
+ // Background
+ QLinearGradient backgroundGradient;
+ backgroundGradient.setColorAt(0.0, QRgb(0xffffff));
+ backgroundGradient.setColorAt(1.0, QRgb(0xffffff));
+ backgroundGradient.setCoordinateMode(QGradient::ObjectBoundingMode);
+ m_chartBackgroundGradient = backgroundGradient;
+
+ // Axes and other
+ m_axisLinePen = QPen(0xd6d6d6);
+ m_axisLinePen.setWidth(1);
+ m_labelBrush = QBrush(QRgb(0x404044));
+ m_gridLinePen = QPen(QRgb(0xe2e2e2));
+ m_gridLinePen.setWidth(1);
+ m_backgroundShades = BackgroundShadesNone;
+
+#elif defined(Q_OS_MAC)
+ // Using a hard coded theme for OSX system theme; the colors match the OSX 10.7 colors
+ m_seriesColors << QRgb(0x60a6e6);
+ m_seriesColors << QRgb(0x92ca66);
+ m_seriesColors << QRgb(0xeba85f);
+ m_seriesColors << QRgb(0xfc5751);
+ m_seriesGradients = ChartThemeManager::generateSeriesGradients(m_seriesColors);
+
+ // Background
+ QLinearGradient backgroundGradient;
+ backgroundGradient.setColorAt(0.0, QRgb(0xffffff));
+ backgroundGradient.setColorAt(1.0, QRgb(0xffffff));
+ backgroundGradient.setCoordinateMode(QGradient::ObjectBoundingMode);
+ m_chartBackgroundGradient = backgroundGradient;
+
+ // Axes and other
+ m_axisLinePen = QPen(0xd6d6d6);
+ m_axisLinePen.setWidth(1);
+ m_labelBrush = QBrush(QRgb(0x404044));
+ m_gridLinePen = QPen(QRgb(0xe2e2e2));
+ m_gridLinePen.setWidth(1);
+ m_backgroundShades = BackgroundShadesNone;
+
+#else
+ // Hard coded theme
+ m_seriesColors << QRgb(0x60a6e6);
+ m_seriesColors << QRgb(0x92ca66);
+ m_seriesColors << QRgb(0xeba85f);
+ m_seriesColors << QRgb(0xfc5751);
+ m_seriesGradients = ChartThemeManager::generateSeriesGradients(m_seriesColors);
+
+ // Background
+ QLinearGradient backgroundGradient;
+ backgroundGradient.setColorAt(0.0, QRgb(0xffffff));
+ backgroundGradient.setColorAt(1.0, QRgb(0xffffff));
+ backgroundGradient.setCoordinateMode(QGradient::ObjectBoundingMode);
+ m_chartBackgroundGradient = backgroundGradient;
+
+ // Axes and other
+ m_axisLinePen = QPen(0xd6d6d6);
+ m_axisLinePen.setWidth(1);
+ m_labelBrush = QBrush(QRgb(0x404044));
+ m_gridLinePen = QPen(QRgb(0xe2e2e2));
+ m_gridLinePen.setWidth(1);
+ m_backgroundShades = BackgroundShadesNone;
+#endif
+ }
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // CHARTTHEMESYSTEM_P_H
diff --git a/src/charts/themes/themes.pri b/src/charts/themes/themes.pri
new file mode 100644
index 00000000..656552af
--- /dev/null
+++ b/src/charts/themes/themes.pri
@@ -0,0 +1,14 @@
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+
+THEMES += \
+ $$PWD/charttheme_p.h \
+ $$PWD/chartthemesystem_p.h \
+ $$PWD/chartthemelight_p.h \
+ $$PWD/chartthemebluecerulean_p.h \
+ $$PWD/chartthemedark_p.h \
+ $$PWD/chartthemebrownsand_p.h \
+ $$PWD/chartthemebluencs_p.h \
+ $$PWD/chartthemehighcontrast_p.h \
+ $$PWD/chartthemeblueicy_p.h \
+ $$PWD/chartthemeqt_p.h
diff --git a/src/charts/xychart/qhxymodelmapper.cpp b/src/charts/xychart/qhxymodelmapper.cpp
new file mode 100644
index 00000000..4edc8aeb
--- /dev/null
+++ b/src/charts/xychart/qhxymodelmapper.cpp
@@ -0,0 +1,243 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhxymodelmapper.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QHXYModelMapper
+ \inmodule Qt Charts
+ \brief Horizontal model mapper for QXYSeries.
+ \mainclass
+
+ Model mappers allow you to use QAbstractItemModel derived models as a data source for a chart series.
+ Horizontal model mapper is used to create a connection between QXYSeries and QAbstractItemModel derived model object.
+ It is possible to use both QAbstractItemModel and QXYSeries model API. QXYModelMapper makes sure that QXYSeries and the model are kept in sync.
+ Note: used model has to support adding/removing rows/columns and modifying the data of the cells.
+*/
+/*!
+ \qmltype HXYModelMapper
+ \instantiates QHXYModelMapper
+ \inqmlmodule QtCharts
+
+ \brief Horizontal model mapper for QXYSeries
+
+ HXYModelMapper allows you to use your own QAbstractItemModel derived model with data in rows as
+ a data source for XYSeries based series. It is possible to use both QAbstractItemModel and
+ XYSeries data API to manipulate data. HXYModelMapper keeps the series and the model in sync.
+*/
+
+/*!
+ \property QHXYModelMapper::series
+ \brief Defines the QXYSeries object that is used by the mapper.
+
+ All the data in the series is discarded when it is set to the mapper.
+ When new series is specified the old series is disconnected (it preserves its data)
+*/
+/*!
+ \qmlproperty XYSeries HXYModelMapper::series
+ Defines the XYSeries object that is used by the mapper. All the data in the series is discarded when it is set to
+ the mapper. When new series is specified the old series is disconnected (it preserves its data).
+*/
+
+/*!
+ \property QHXYModelMapper::model
+ \brief Defines the model that is used by the mapper.
+*/
+/*!
+ \qmlproperty SomeModel HXYModelMapper::model
+ The QAbstractItemModel based model that is used by the mapper. You need to implement the model
+ and expose it to QML. Note: the model has to support adding/removing rows/columns and modifying
+ the data of the cells.
+*/
+
+/*!
+ \property QHXYModelMapper::xRow
+ \brief Defines which row of the model is kept in sync with the x values of the QXYSeries.
+
+ Default value is: -1 (invalid mapping)
+*/
+/*!
+ \qmlproperty int HXYModelMapper::xRow
+ Defines which row of the model is kept in sync with the x values of the series. Default value is -1 (invalid
+ mapping).
+*/
+
+/*!
+ \property QHXYModelMapper::yRow
+ \brief Defines which row of the model is kept in sync with the y values of the QXYSeries.
+
+ Default value is: -1 (invalid mapping)
+*/
+/*!
+ \qmlproperty int HXYModelMapper::yRow
+ Defines which row of the model is kept in sync with the y values of the series. Default value is -1
+ (invalid mapping).
+*/
+
+/*!
+ \property QHXYModelMapper::firstColumn
+ \brief Defines which column of the model contains the data for the first point of the series.
+
+ Minimal and default value is: 0
+*/
+/*!
+ \qmlproperty int HXYModelMapper::firstColumn
+ Defines which column of the model contains the data for the first point of the series.
+ The default value is 0.
+*/
+
+/*!
+ \property QHXYModelMapper::columnCount
+ \brief Defines the number of columns of the model that are mapped as the data for series.
+
+ Minimal and default value is: -1 (count limited by the number of columns in the model)
+*/
+/*!
+ \qmlproperty int HXYModelMapper::columnCount
+ Defines the number of columns of the model that are mapped as the data for series. The default value is
+ -1 (count limited by the number of columns in the model)
+*/
+
+/*!
+ \fn void QHXYModelMapper::seriesReplaced()
+
+ Emitted when the series to which mapper is connected to has changed.
+*/
+
+/*!
+ \fn void QHXYModelMapper::modelReplaced()
+
+ Emitted when the model to which mapper is connected to has changed.
+*/
+
+/*!
+ \fn void QHXYModelMapper::xRowChanged()
+
+ Emitted when the xRow has changed.
+*/
+
+/*!
+ \fn void QHXYModelMapper::yRowChanged()
+
+ Emitted when the yRow has changed.
+*/
+
+/*!
+ \fn void QHXYModelMapper::firstColumnChanged()
+ Emitted when the firstColumn has changed.
+*/
+
+/*!
+ \fn void QHXYModelMapper::columnCountChanged()
+ Emitted when the columnCount has changed.
+*/
+
+/*!
+ Constructs a mapper object which is a child of \a parent.
+*/
+QHXYModelMapper::QHXYModelMapper(QObject *parent) :
+ QXYModelMapper(parent)
+{
+ QXYModelMapper::setOrientation(Qt::Horizontal);
+}
+
+QAbstractItemModel *QHXYModelMapper::model() const
+{
+ return QXYModelMapper::model();
+}
+
+void QHXYModelMapper::setModel(QAbstractItemModel *model)
+{
+ if (model != QXYModelMapper::model()) {
+ QXYModelMapper::setModel(model);
+ emit modelReplaced();
+ }
+}
+
+QXYSeries *QHXYModelMapper::series() const
+{
+ return QXYModelMapper::series();
+}
+
+void QHXYModelMapper::setSeries(QXYSeries *series)
+{
+ if (series != QXYModelMapper::series()) {
+ QXYModelMapper::setSeries(series);
+ emit seriesReplaced();
+ }
+}
+
+int QHXYModelMapper::xRow() const
+{
+ return QXYModelMapper::xSection();
+}
+
+void QHXYModelMapper::setXRow(int xRow)
+{
+ if (xRow != xSection()) {
+ QXYModelMapper::setXSection(xRow);
+ emit xRowChanged();
+ }
+}
+
+int QHXYModelMapper::yRow() const
+{
+ return QXYModelMapper::ySection();
+}
+
+void QHXYModelMapper::setYRow(int yRow)
+{
+ if (yRow != ySection()) {
+ QXYModelMapper::setYSection(yRow);
+ emit yRowChanged();
+ }
+}
+
+int QHXYModelMapper::firstColumn() const
+{
+ return first();
+}
+
+void QHXYModelMapper::setFirstColumn(int firstColumn)
+{
+ if (firstColumn != first()) {
+ setFirst(firstColumn);
+ emit firstColumnChanged();
+ }
+}
+
+int QHXYModelMapper::columnCount() const
+{
+ return count();
+}
+
+void QHXYModelMapper::setColumnCount(int columnCount)
+{
+ if (columnCount != count()) {
+ setCount(columnCount);
+ emit columnCountChanged();
+ }
+}
+
+#include "moc_qhxymodelmapper.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/xychart/qhxymodelmapper.h b/src/charts/xychart/qhxymodelmapper.h
new file mode 100644
index 00000000..cc95da4d
--- /dev/null
+++ b/src/charts/xychart/qhxymodelmapper.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHXYMODELMAPPER_H
+#define QHXYMODELMAPPER_H
+
+#include <QtCharts/QXYModelMapper>
+
+QT_CHARTS_BEGIN_NAMESPACE
+/* Comment line for syncqt to generate the fwd-include correctly, due to QTBUG-22432 */
+class QT_CHARTS_EXPORT QHXYModelMapper : public QXYModelMapper
+{
+ Q_OBJECT
+ Q_PROPERTY(QXYSeries *series READ series WRITE setSeries NOTIFY seriesReplaced)
+ Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelReplaced)
+ Q_PROPERTY(int xRow READ xRow WRITE setXRow NOTIFY xRowChanged)
+ Q_PROPERTY(int yRow READ yRow WRITE setYRow NOTIFY yRowChanged)
+ Q_PROPERTY(int firstColumn READ firstColumn WRITE setFirstColumn NOTIFY firstColumnChanged)
+ Q_PROPERTY(int columnCount READ columnCount WRITE setColumnCount NOTIFY columnCountChanged)
+
+public:
+ explicit QHXYModelMapper(QObject *parent = 0);
+
+ QAbstractItemModel *model() const;
+ void setModel(QAbstractItemModel *model);
+
+ QXYSeries *series() const;
+ void setSeries(QXYSeries *series);
+
+ int xRow() const;
+ void setXRow(int xRow);
+
+ int yRow() const;
+ void setYRow(int yRow);
+
+ int firstColumn() const;
+ void setFirstColumn(int firstColumn);
+
+ int columnCount() const;
+ void setColumnCount(int columnCount);
+
+Q_SIGNALS:
+ void seriesReplaced();
+ void modelReplaced();
+ void xRowChanged();
+ void yRowChanged();
+ void firstColumnChanged();
+ void columnCountChanged();
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QHXYMODELMAPPER_H
diff --git a/src/charts/xychart/qvxymodelmapper.cpp b/src/charts/xychart/qvxymodelmapper.cpp
new file mode 100644
index 00000000..6ede138e
--- /dev/null
+++ b/src/charts/xychart/qvxymodelmapper.cpp
@@ -0,0 +1,243 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvxymodelmapper.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QVXYModelMapper
+ \inmodule Qt Charts
+ \brief Vertical model mapper for QXYSeries.
+ \mainclass
+
+ Model mappers allow you to use QAbstractItemModel derived models as a data source for a chart series.
+ Vertical model mapper is used to create a connection between QXYSeries and QAbstractItemModel derived model object.
+ It is possible to use both QAbstractItemModel and QXYSeries model API. QXYModelMapper makes sure that QXYSeries and the model are kept in sync.
+ Note: used model has to support adding/removing rows/columns and modifying the data of the cells.
+*/
+/*!
+ \qmltype VXYModelMapper
+ \instantiates QVXYModelMapper
+ \inqmlmodule QtCharts
+
+ \brief Vertical model mapper for QXYSeries.
+
+ VXYModelMapper allows you to use your own QAbstractItemModel derived model with data in columns
+ as a data source for XYSeries based series. It is possible to use both QAbstractItemModel and
+ XYSeries data API to manipulate data. VXYModelMapper keeps the series and the model in sync.
+*/
+
+/*!
+ \property QVXYModelMapper::series
+ \brief Defines the QXYSeries object that is used by the mapper.
+
+ All the data in the series is discarded when it is set to the mapper.
+ When new series is specified the old series is disconnected (it preserves its data)
+*/
+/*!
+ \qmlproperty XYSeries VXYModelMapper::series
+ Defines the XYSeries object that is used by the mapper. All the data in the series is discarded when it is set to
+ the mapper. When new series is specified the old series is disconnected (it preserves its data).
+*/
+
+/*!
+ \property QVXYModelMapper::model
+ \brief Defines the model that is used by the mapper.
+*/
+/*!
+ \qmlproperty SomeModel VXYModelMapper::model
+ The QAbstractItemModel based model that is used by the mapper. You need to implement the model
+ and expose it to QML. Note: the model has to support adding/removing rows/columns and modifying
+ the data of the cells.
+*/
+
+/*!
+ \property QVXYModelMapper::xColumn
+ \brief Defines which column of the model is kept in sync with the x values of QXYSeries.
+
+ Default value is: -1 (invalid mapping)
+*/
+/*!
+ \qmlproperty int VXYModelMapper::xColumn
+ Defines which column of the model is kept in sync with the x values of the series. Default value is -1 (invalid
+ mapping).
+*/
+
+/*!
+ \property QVXYModelMapper::yColumn
+ \brief Defines which column of the model is kept in sync with the y values of QXYSeries.
+
+ Default value is: -1 (invalid mapping)
+*/
+/*!
+ \qmlproperty int VXYModelMapper::yColumn
+ Defines which column of the model is kept in sync with the y values of the series. Default value is -1 (invalid
+ mapping).
+*/
+
+/*!
+ \property QVXYModelMapper::firstRow
+ \brief Defines which row of the model contains the data for the first point of the series.
+
+ Minimal and default value is: 0
+*/
+/*!
+ \qmlproperty int VXYModelMapper::firstRow
+ Defines which row of the model contains the data for the first point of the series.
+ The default value is 0.
+*/
+
+/*!
+ \property QVXYModelMapper::rowCount
+ \brief Defines the number of rows of the model that are mapped as the data for series.
+
+ Minimal and default value is: -1 (count limited by the number of rows in the model)
+*/
+/*!
+ \qmlproperty int VXYModelMapper::columnCount
+ Defines the number of rows of the model that are mapped as the data for series. The default value is
+ -1 (count limited by the number of rows in the model).
+*/
+
+/*!
+ \fn void QVXYModelMapper::seriesReplaced()
+
+ Emitted when the series to which mapper is connected to has changed.
+*/
+
+/*!
+ \fn void QVXYModelMapper::modelReplaced()
+
+ Emitted when the model to which mapper is connected to has changed.
+*/
+
+/*!
+ \fn void QVXYModelMapper::xColumnChanged()
+
+ Emitted when the xColumn has changed.
+*/
+
+/*!
+ \fn void QVXYModelMapper::yColumnChanged()
+
+ Emitted when the yColumn has changed.
+*/
+
+/*!
+ \fn void QVXYModelMapper::firstRowChanged()
+ Emitted when the firstRow has changed.
+*/
+
+/*!
+ \fn void QVXYModelMapper::rowCountChanged()
+ Emitted when the rowCount has changed.
+*/
+
+/*!
+ Constructs a mapper object which is a child of \a parent.
+*/
+QVXYModelMapper::QVXYModelMapper(QObject *parent) :
+ QXYModelMapper(parent)
+{
+ QXYModelMapper::setOrientation(Qt::Vertical);
+}
+
+QAbstractItemModel *QVXYModelMapper::model() const
+{
+ return QXYModelMapper::model();
+}
+
+void QVXYModelMapper::setModel(QAbstractItemModel *model)
+{
+ if (model != QXYModelMapper::model()) {
+ QXYModelMapper::setModel(model);
+ emit modelReplaced();
+ }
+}
+
+QXYSeries *QVXYModelMapper::series() const
+{
+ return QXYModelMapper::series();
+}
+
+void QVXYModelMapper::setSeries(QXYSeries *series)
+{
+ if (series != QXYModelMapper::series()) {
+ QXYModelMapper::setSeries(series);
+ emit seriesReplaced();
+ }
+}
+
+int QVXYModelMapper::xColumn() const
+{
+ return QXYModelMapper::xSection();
+}
+
+void QVXYModelMapper::setXColumn(int xColumn)
+{
+ if (xColumn != xSection()) {
+ QXYModelMapper::setXSection(xColumn);
+ emit xColumnChanged();
+ }
+}
+
+int QVXYModelMapper::yColumn() const
+{
+ return QXYModelMapper::ySection();
+}
+
+void QVXYModelMapper::setYColumn(int yColumn)
+{
+ if (yColumn != ySection()) {
+ QXYModelMapper::setYSection(yColumn);
+ emit yColumnChanged();
+ }
+}
+
+int QVXYModelMapper::firstRow() const
+{
+ return first();
+}
+
+void QVXYModelMapper::setFirstRow(int firstRow)
+{
+ if (firstRow != first()) {
+ setFirst(firstRow);
+ emit firstRowChanged();
+ }
+}
+
+int QVXYModelMapper::rowCount() const
+{
+ return count();
+}
+
+void QVXYModelMapper::setRowCount(int rowCount)
+{
+ if (rowCount != count()) {
+ setCount(rowCount);
+ emit rowCountChanged();
+ }
+}
+
+#include "moc_qvxymodelmapper.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/xychart/qvxymodelmapper.h b/src/charts/xychart/qvxymodelmapper.h
new file mode 100644
index 00000000..fa6301d0
--- /dev/null
+++ b/src/charts/xychart/qvxymodelmapper.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVXYMODELMAPPER_H
+#define QVXYMODELMAPPER_H
+
+#include <QtCharts/QXYModelMapper>
+
+QT_CHARTS_BEGIN_NAMESPACE
+/* Comment line for syncqt to generate the fwd-include correctly, due to QTBUG-22432 */
+class QT_CHARTS_EXPORT QVXYModelMapper : public QXYModelMapper
+{
+ Q_OBJECT
+ Q_PROPERTY(QXYSeries *series READ series WRITE setSeries NOTIFY seriesReplaced)
+ Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelReplaced)
+ Q_PROPERTY(int xColumn READ xColumn WRITE setXColumn NOTIFY xColumnChanged)
+ Q_PROPERTY(int yColumn READ yColumn WRITE setYColumn NOTIFY yColumnChanged)
+ Q_PROPERTY(int firstRow READ firstRow WRITE setFirstRow NOTIFY firstRowChanged)
+ Q_PROPERTY(int rowCount READ rowCount WRITE setRowCount NOTIFY rowCountChanged)
+
+public:
+ explicit QVXYModelMapper(QObject *parent = 0);
+
+ QAbstractItemModel *model() const;
+ void setModel(QAbstractItemModel *model);
+
+ QXYSeries *series() const;
+ void setSeries(QXYSeries *series);
+
+ int xColumn() const;
+ void setXColumn(int xColumn);
+
+ int yColumn() const;
+ void setYColumn(int yColumn);
+
+ int firstRow() const;
+ void setFirstRow(int firstRow);
+
+ int rowCount() const;
+ void setRowCount(int rowCount);
+
+Q_SIGNALS:
+ void seriesReplaced();
+ void modelReplaced();
+ void xColumnChanged();
+ void yColumnChanged();
+ void firstRowChanged();
+ void rowCountChanged();
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QVXYMODELMAPPER_H
diff --git a/src/charts/xychart/qxymodelmapper.cpp b/src/charts/xychart/qxymodelmapper.cpp
new file mode 100644
index 00000000..3907326d
--- /dev/null
+++ b/src/charts/xychart/qxymodelmapper.cpp
@@ -0,0 +1,533 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qxymodelmapper.h"
+#include "qxymodelmapper_p.h"
+#include "qxyseries.h"
+#include <QAbstractItemModel>
+#include <QDateTime>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ Constructs a mapper object which is a child of \a parent.
+*/
+QXYModelMapper::QXYModelMapper(QObject *parent)
+ : QObject(parent),
+ d_ptr(new QXYModelMapperPrivate(this))
+{
+}
+
+/*!
+ \internal
+*/
+QAbstractItemModel *QXYModelMapper::model() const
+{
+ Q_D(const QXYModelMapper);
+ return d->m_model;
+}
+
+/*!
+ \internal
+*/
+void QXYModelMapper::setModel(QAbstractItemModel *model)
+{
+ if (model == 0)
+ return;
+
+ Q_D(QXYModelMapper);
+ if (d->m_model)
+ disconnect(d->m_model, 0, d, 0);
+
+ d->m_model = model;
+ d->initializeXYFromModel();
+ // connect signals from the model
+ connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
+ connect(d->m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelRowsAdded(QModelIndex,int,int)));
+ connect(d->m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelRowsRemoved(QModelIndex,int,int)));
+ connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelColumnsAdded(QModelIndex,int,int)));
+ connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelColumnsRemoved(QModelIndex,int,int)));
+ connect(d->m_model, SIGNAL(destroyed()), d, SLOT(handleModelDestroyed()));
+}
+
+/*!
+ \internal
+*/
+QXYSeries *QXYModelMapper::series() const
+{
+ Q_D(const QXYModelMapper);
+ return d->m_series;
+}
+
+/*!
+ \internal
+*/
+void QXYModelMapper::setSeries(QXYSeries *series)
+{
+ Q_D(QXYModelMapper);
+ if (d->m_series)
+ disconnect(d->m_series, 0, d, 0);
+
+ if (series == 0)
+ return;
+
+ d->m_series = series;
+ d->initializeXYFromModel();
+ // connect the signals from the series
+ connect(d->m_series, SIGNAL(pointAdded(int)), d, SLOT(handlePointAdded(int)));
+ connect(d->m_series, SIGNAL(pointRemoved(int)), d, SLOT(handlePointRemoved(int)));
+ connect(d->m_series, SIGNAL(pointReplaced(int)), d, SLOT(handlePointReplaced(int)));
+ connect(d->m_series, SIGNAL(destroyed()), d, SLOT(handleSeriesDestroyed()));
+}
+
+/*!
+ \internal
+*/
+int QXYModelMapper::first() const
+{
+ Q_D(const QXYModelMapper);
+ return d->m_first;
+}
+
+/*!
+ \internal
+*/
+void QXYModelMapper::setFirst(int first)
+{
+ Q_D(QXYModelMapper);
+ d->m_first = qMax(first, 0);
+ d->initializeXYFromModel();
+}
+
+/*!
+ \internal
+*/
+int QXYModelMapper::count() const
+{
+ Q_D(const QXYModelMapper);
+ return d->m_count;
+}
+
+/*!
+ \internal
+*/
+void QXYModelMapper::setCount(int count)
+{
+ Q_D(QXYModelMapper);
+ d->m_count = qMax(count, -1);
+ d->initializeXYFromModel();
+}
+
+/*!
+ Returns the orientation that is used when QXYModelMapper accesses the model.
+ This mean whether the consecutive x/y values of the QXYSeries are read from rows (Qt::Horizontal)
+ or from columns (Qt::Vertical)
+*/
+Qt::Orientation QXYModelMapper::orientation() const
+{
+ Q_D(const QXYModelMapper);
+ return d->m_orientation;
+}
+
+/*!
+ Returns the \a orientation that is used when QXYModelMapper accesses the model.
+ This mean whether the consecutive x/y values of the QXYSeries are read from rows (Qt::Horizontal)
+ or from columns (Qt::Vertical)
+*/
+void QXYModelMapper::setOrientation(Qt::Orientation orientation)
+{
+ Q_D(QXYModelMapper);
+ d->m_orientation = orientation;
+ d->initializeXYFromModel();
+}
+
+/*!
+ Returns which section of the model is kept in sync with the x values of the QXYSeries
+*/
+int QXYModelMapper::xSection() const
+{
+ Q_D(const QXYModelMapper);
+ return d->m_xSection;
+}
+
+/*!
+ Sets the model section that is kept in sync with the x values of the QXYSeries.
+ Parameter \a xSection specifies the section of the model.
+*/
+void QXYModelMapper::setXSection(int xSection)
+{
+ Q_D(QXYModelMapper);
+ d->m_xSection = qMax(-1, xSection);
+ d->initializeXYFromModel();
+}
+
+/*!
+ Returns which section of the model is kept in sync with the y values of the QXYSeries
+*/
+int QXYModelMapper::ySection() const
+{
+ Q_D(const QXYModelMapper);
+ return d->m_ySection;
+}
+
+/*!
+ Sets the model section that is kept in sync with the y values of the QXYSeries.
+ Parameter \a ySection specifies the section of the model.
+*/
+void QXYModelMapper::setYSection(int ySection)
+{
+ Q_D(QXYModelMapper);
+ d->m_ySection = qMax(-1, ySection);
+ d->initializeXYFromModel();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QXYModelMapperPrivate::QXYModelMapperPrivate(QXYModelMapper *q) :
+ QObject(q),
+ m_series(0),
+ m_model(0),
+ m_first(0),
+ m_count(-1),
+ m_orientation(Qt::Vertical),
+ m_xSection(-1),
+ m_ySection(-1),
+ m_seriesSignalsBlock(false),
+ m_modelSignalsBlock(false),
+ q_ptr(q)
+{
+}
+
+void QXYModelMapperPrivate::blockModelSignals(bool block)
+{
+ m_modelSignalsBlock = block;
+}
+
+void QXYModelMapperPrivate::blockSeriesSignals(bool block)
+{
+ m_seriesSignalsBlock = block;
+}
+
+QModelIndex QXYModelMapperPrivate::xModelIndex(int xPos)
+{
+ if (m_count != -1 && xPos >= m_count)
+ return QModelIndex(); // invalid
+
+ if (m_orientation == Qt::Vertical)
+ return m_model->index(xPos + m_first, m_xSection);
+ else
+ return m_model->index(m_xSection, xPos + m_first);
+}
+
+QModelIndex QXYModelMapperPrivate::yModelIndex(int yPos)
+{
+ if (m_count != -1 && yPos >= m_count)
+ return QModelIndex(); // invalid
+
+ if (m_orientation == Qt::Vertical)
+ return m_model->index(yPos + m_first, m_ySection);
+ else
+ return m_model->index(m_ySection, yPos + m_first);
+}
+
+qreal QXYModelMapperPrivate::valueFromModel(QModelIndex index)
+{
+ QVariant value = m_model->data(index, Qt::DisplayRole);
+ switch (value.type()) {
+ case QVariant::DateTime:
+ return value.toDateTime().toMSecsSinceEpoch();
+ case QVariant::Date:
+ return QDateTime(value.toDate()).toMSecsSinceEpoch();
+ default:
+ return value.toReal();
+ }
+}
+
+void QXYModelMapperPrivate::setValueToModel(QModelIndex index, qreal value)
+{
+ QVariant oldValue = m_model->data(index, Qt::DisplayRole);
+ switch (oldValue.type()) {
+ case QVariant::DateTime:
+ m_model->setData(index, QDateTime::fromMSecsSinceEpoch(value));
+ break;
+ case QVariant::Date:
+ m_model->setData(index, QDateTime::fromMSecsSinceEpoch(value).date());
+ break;
+ default:
+ m_model->setData(index, value);
+ }
+}
+
+void QXYModelMapperPrivate::handlePointAdded(int pointPos)
+{
+ if (m_seriesSignalsBlock)
+ return;
+
+ if (m_count != -1)
+ m_count += 1;
+
+ blockModelSignals();
+ if (m_orientation == Qt::Vertical)
+ m_model->insertRows(pointPos + m_first, 1);
+ else
+ m_model->insertColumns(pointPos + m_first, 1);
+
+ setValueToModel(xModelIndex(pointPos), m_series->points().at(pointPos).x());
+ setValueToModel(yModelIndex(pointPos), m_series->points().at(pointPos).y());
+ blockModelSignals(false);
+}
+
+void QXYModelMapperPrivate::handlePointRemoved(int pointPos)
+{
+ if (m_seriesSignalsBlock)
+ return;
+
+ if (m_count != -1)
+ m_count -= 1;
+
+ blockModelSignals();
+ if (m_orientation == Qt::Vertical)
+ m_model->removeRow(pointPos + m_first);
+ else
+ m_model->removeColumn(pointPos + m_first);
+ blockModelSignals(false);
+}
+
+void QXYModelMapperPrivate::handlePointReplaced(int pointPos)
+{
+ if (m_seriesSignalsBlock)
+ return;
+
+ blockModelSignals();
+ setValueToModel(xModelIndex(pointPos), m_series->points().at(pointPos).x());
+ setValueToModel(yModelIndex(pointPos), m_series->points().at(pointPos).y());
+ blockModelSignals(false);
+}
+
+void QXYModelMapperPrivate::handleSeriesDestroyed()
+{
+ m_series = 0;
+}
+
+void QXYModelMapperPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
+{
+ if (m_model == 0 || m_series == 0)
+ return;
+
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ QModelIndex index;
+ QPointF oldPoint;
+ QPointF newPoint;
+ for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
+ for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
+ index = topLeft.sibling(row, column);
+ if (m_orientation == Qt::Vertical && (index.column() == m_xSection || index.column() == m_ySection)) {
+ if (index.row() >= m_first && (m_count == - 1 || index.row() < m_first + m_count)) {
+ QModelIndex xIndex = xModelIndex(index.row() - m_first);
+ QModelIndex yIndex = yModelIndex(index.row() - m_first);
+ if (xIndex.isValid() && yIndex.isValid()) {
+ oldPoint = m_series->points().at(index.row() - m_first);
+ newPoint.setX(valueFromModel(xIndex));
+ newPoint.setY(valueFromModel(yIndex));
+ }
+ }
+ } else if (m_orientation == Qt::Horizontal && (index.row() == m_xSection || index.row() == m_ySection)) {
+ if (index.column() >= m_first && (m_count == - 1 || index.column() < m_first + m_count)) {
+ QModelIndex xIndex = xModelIndex(index.column() - m_first);
+ QModelIndex yIndex = yModelIndex(index.column() - m_first);
+ if (xIndex.isValid() && yIndex.isValid()) {
+ oldPoint = m_series->points().at(index.column() - m_first);
+ newPoint.setX(valueFromModel(xIndex));
+ newPoint.setY(valueFromModel(yIndex));
+ }
+ }
+ } else {
+ continue;
+ }
+ m_series->replace(oldPoint, newPoint);
+ }
+ }
+ blockSeriesSignals(false);
+}
+
+void QXYModelMapperPrivate::modelRowsAdded(QModelIndex parent, int start, int end)
+{
+ Q_UNUSED(parent);
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ if (m_orientation == Qt::Vertical)
+ insertData(start, end);
+ else if (start <= m_xSection || start <= m_ySection) // if the changes affect the map - reinitialize the xy
+ initializeXYFromModel();
+ blockSeriesSignals(false);
+}
+
+void QXYModelMapperPrivate::modelRowsRemoved(QModelIndex parent, int start, int end)
+{
+ Q_UNUSED(parent);
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ if (m_orientation == Qt::Vertical)
+ removeData(start, end);
+ else if (start <= m_xSection || start <= m_ySection) // if the changes affect the map - reinitialize the xy
+ initializeXYFromModel();
+ blockSeriesSignals(false);
+}
+
+void QXYModelMapperPrivate::modelColumnsAdded(QModelIndex parent, int start, int end)
+{
+ Q_UNUSED(parent);
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ if (m_orientation == Qt::Horizontal)
+ insertData(start, end);
+ else if (start <= m_xSection || start <= m_ySection) // if the changes affect the map - reinitialize the xy
+ initializeXYFromModel();
+ blockSeriesSignals(false);
+}
+
+void QXYModelMapperPrivate::modelColumnsRemoved(QModelIndex parent, int start, int end)
+{
+ Q_UNUSED(parent);
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ if (m_orientation == Qt::Horizontal)
+ removeData(start, end);
+ else if (start <= m_xSection || start <= m_ySection) // if the changes affect the map - reinitialize the xy
+ initializeXYFromModel();
+ blockSeriesSignals(false);
+}
+
+void QXYModelMapperPrivate::handleModelDestroyed()
+{
+ m_model = 0;
+}
+
+void QXYModelMapperPrivate::insertData(int start, int end)
+{
+ if (m_model == 0 || m_series == 0)
+ return;
+
+ if (m_count != -1 && start >= m_first + m_count) {
+ return;
+ } else {
+ int addedCount = end - start + 1;
+ if (m_count != -1 && addedCount > m_count)
+ addedCount = m_count;
+ int first = qMax(start, m_first);
+ int last = qMin(first + addedCount - 1, m_orientation == Qt::Vertical ? m_model->rowCount() - 1 : m_model->columnCount() - 1);
+ for (int i = first; i <= last; i++) {
+ QPointF point;
+ QModelIndex xIndex = xModelIndex(i - m_first);
+ QModelIndex yIndex = yModelIndex(i - m_first);
+ if (xIndex.isValid() && yIndex.isValid()) {
+ point.setX(valueFromModel(xIndex));
+ point.setY(valueFromModel(yIndex));
+ m_series->insert(i - m_first, point);
+ }
+ }
+
+ // remove excess of points (above m_count)
+ if (m_count != -1 && m_series->points().size() > m_count)
+ for (int i = m_series->points().size() - 1; i >= m_count; i--) {
+ m_series->remove(m_series->points().at(i));
+ }
+ }
+}
+
+void QXYModelMapperPrivate::removeData(int start, int end)
+{
+ if (m_model == 0 || m_series == 0)
+ return;
+
+ int removedCount = end - start + 1;
+ if (m_count != -1 && start >= m_first + m_count) {
+ return;
+ } else {
+ int toRemove = qMin(m_series->count(), removedCount); // first find how many items can actually be removed
+ int first = qMax(start, m_first); // get the index of the first item that will be removed.
+ int last = qMin(first + toRemove - 1, m_series->count() + m_first - 1); // get the index of the last item that will be removed.
+ for (int i = last; i >= first; i--) {
+ m_series->remove(m_series->points().at(i - m_first));
+ }
+
+ if (m_count != -1) {
+ int itemsAvailable; // check how many are available to be added
+ if (m_orientation == Qt::Vertical)
+ itemsAvailable = m_model->rowCount() - m_first - m_series->count();
+ else
+ itemsAvailable = m_model->columnCount() - m_first - m_series->count();
+ int toBeAdded = qMin(itemsAvailable, m_count - m_series->count()); // add not more items than there is space left to be filled.
+ int currentSize = m_series->count();
+ if (toBeAdded > 0)
+ for (int i = m_series->count(); i < currentSize + toBeAdded; i++) {
+ QPointF point;
+ QModelIndex xIndex = xModelIndex(i);
+ QModelIndex yIndex = yModelIndex(i);
+ if (xIndex.isValid() && yIndex.isValid()) {
+ point.setX(valueFromModel(xIndex));
+ point.setY(valueFromModel(yIndex));
+ m_series->insert(i, point);
+ }
+ }
+ }
+ }
+}
+
+void QXYModelMapperPrivate::initializeXYFromModel()
+{
+ if (m_model == 0 || m_series == 0)
+ return;
+
+ blockSeriesSignals();
+ // clear current content
+ m_series->clear();
+
+ // create the initial points set
+ int pointPos = 0;
+ QModelIndex xIndex = xModelIndex(pointPos);
+ QModelIndex yIndex = yModelIndex(pointPos);
+ while (xIndex.isValid() && yIndex.isValid()) {
+ QPointF point;
+ point.setX(valueFromModel(xIndex));
+ point.setY(valueFromModel(yIndex));
+ m_series->append(point);
+ pointPos++;
+ xIndex = xModelIndex(pointPos);
+ yIndex = yModelIndex(pointPos);
+ }
+ blockSeriesSignals(false);
+}
+
+#include "moc_qxymodelmapper.cpp"
+#include "moc_qxymodelmapper_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/xychart/qxymodelmapper.h b/src/charts/xychart/qxymodelmapper.h
new file mode 100644
index 00000000..0cb6c11a
--- /dev/null
+++ b/src/charts/xychart/qxymodelmapper.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QXYMODELMAPPER_H
+#define QXYMODELMAPPER_H
+
+#include <QtCharts/qchartglobal.h>
+#include <QObject>
+
+class QAbstractItemModel;
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QXYModelMapperPrivate;
+class QXYSeries;
+
+class QT_CHARTS_EXPORT QXYModelMapper : public QObject
+{
+ Q_OBJECT
+
+protected:
+ explicit QXYModelMapper(QObject *parent = 0);
+
+ QAbstractItemModel *model() const;
+ void setModel(QAbstractItemModel *model);
+
+ QXYSeries *series() const;
+ void setSeries(QXYSeries *series);
+
+ int first() const;
+ void setFirst(int first);
+
+ int count() const;
+ void setCount(int count);
+
+ Qt::Orientation orientation() const;
+ void setOrientation(Qt::Orientation orientation);
+
+ int xSection() const;
+ void setXSection(int xSection);
+
+ int ySection() const;
+ void setYSection(int ySection);
+
+protected:
+ QXYModelMapperPrivate *const d_ptr;
+ Q_DECLARE_PRIVATE(QXYModelMapper)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QXYMODELMAPPER_H
diff --git a/src/charts/xychart/qxymodelmapper_p.h b/src/charts/xychart/qxymodelmapper_p.h
new file mode 100644
index 00000000..390dcaf7
--- /dev/null
+++ b/src/charts/xychart/qxymodelmapper_p.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QXYMODELMAPPER_P_H
+#define QXYMODELMAPPER_P_H
+
+#include "qxymodelmapper.h"
+#include <QObject>
+
+class QModelIndex;
+class QAbstractItemModel;
+class QPointF;
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QXYModelMapper;
+class QXYSeries;
+
+class QXYModelMapperPrivate : public QObject
+{
+ Q_OBJECT
+
+public:
+ QXYModelMapperPrivate(QXYModelMapper *q);
+
+public Q_SLOTS:
+ // for the model
+ void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight);
+ void modelRowsAdded(QModelIndex parent, int start, int end);
+ void modelRowsRemoved(QModelIndex parent, int start, int end);
+ void modelColumnsAdded(QModelIndex parent, int start, int end);
+ void modelColumnsRemoved(QModelIndex parent, int start, int end);
+ void handleModelDestroyed();
+
+ // for the series
+ void handlePointAdded(int pointPos);
+ void handlePointRemoved(int pointPos);
+ void handlePointReplaced(int pointPos);
+ void handleSeriesDestroyed();
+
+ void initializeXYFromModel();
+
+private:
+ QModelIndex xModelIndex(int xPos);
+ QModelIndex yModelIndex(int yPos);
+ void insertData(int start, int end);
+ void removeData(int start, int end);
+ void blockModelSignals(bool block = true);
+ void blockSeriesSignals(bool block = true);
+ qreal valueFromModel(QModelIndex index);
+ void setValueToModel(QModelIndex index, qreal value);
+
+private:
+ QXYSeries *m_series;
+ QAbstractItemModel *m_model;
+ int m_first;
+ int m_count;
+ Qt::Orientation m_orientation;
+ int m_xSection;
+ int m_ySection;
+ bool m_seriesSignalsBlock;
+ bool m_modelSignalsBlock;
+
+private:
+ QXYModelMapper *q_ptr;
+ Q_DECLARE_PUBLIC(QXYModelMapper)
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QXYMODELMAPPER_P_H
diff --git a/src/charts/xychart/qxyseries.cpp b/src/charts/xychart/qxyseries.cpp
new file mode 100644
index 00000000..6805a1c7
--- /dev/null
+++ b/src/charts/xychart/qxyseries.cpp
@@ -0,0 +1,801 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qxyseries.h"
+#include "qxyseries_p.h"
+#include "abstractdomain_p.h"
+#include "qvalueaxis.h"
+#include "xychart_p.h"
+#include "qxylegendmarker.h"
+#include "charthelpers_p.h"
+#include "qchart_p.h"
+#include <QPainter>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QXYSeries
+ \inmodule Qt Charts
+ \brief The QXYSeries class is a base class for line, spline and scatter series.
+*/
+/*!
+ \qmltype XYSeries
+ \instantiates QXYSeries
+ \inqmlmodule QtCharts
+
+ \inherits AbstractSeries
+
+ \brief The XYSeries type is a base type for line, spline and scatter series.
+
+ The XYSeries class is a base class for line, spline and scatter series.
+ The class cannot be instantiated directly.
+*/
+
+/*!
+ \qmlproperty AbstractAxis XYSeries::axisX
+ The x axis used for the series. If you leave both axisX and axisXTop undefined, a ValueAxis is created for
+ the series.
+ \sa axisXTop
+*/
+
+/*!
+ \qmlproperty AbstractAxis XYSeries::axisY
+ The y axis used for the series. If you leave both axisY and axisYRight undefined, a ValueAxis is created for
+ the series.
+ \sa axisYRight
+*/
+
+/*!
+ \qmlproperty AbstractAxis XYSeries::axisXTop
+ The x axis used for the series, drawn on top of the chart view. Note that you can only provide either axisX or
+ axisXTop, but not both.
+ \sa axisX
+*/
+
+/*!
+ \qmlproperty AbstractAxis XYSeries::axisYRight
+ The y axis used for the series, drawn to the right on the chart view. Note that you can only provide either axisY
+ or axisYRight, but not both.
+ \sa axisY
+*/
+
+/*!
+ \qmlproperty AbstractAxis XYSeries::axisAngular
+ The angular axis used for the series, drawn around the polar chart view.
+ \sa axisX
+*/
+
+/*!
+ \qmlproperty AbstractAxis XYSeries::axisRadial
+ The radial axis used for the series, drawn inside the polar chart view.
+ \sa axisY
+*/
+
+/*!
+ \property QXYSeries::pointsVisible
+ Controls if the data points are visible and should be drawn.
+*/
+/*!
+ \qmlproperty bool XYSeries::pointsVisible
+ Controls if the data points are visible and should be drawn.
+*/
+
+/*!
+ \fn QPen QXYSeries::pen() const
+ \brief Returns pen used to draw points for series.
+ \sa setPen()
+*/
+
+/*!
+ \fn QBrush QXYSeries::brush() const
+ \brief Returns brush used to draw points for series.
+ \sa setBrush()
+*/
+
+/*!
+ \property QXYSeries::color
+ The color of the series. This is line (pen) color in case of QLineSeries or QSplineSeries and
+ fill (brush) color in case of QScatterSeries or QAreaSeries.
+ \sa QXYSeries::pen(), QXYSeries::brush()
+*/
+/*!
+ \qmlproperty color XYSeries::color
+ The color of the series. This is line (pen) color in case of LineSeries or SplineSeries and
+ fill (brush) color in case of ScatterSeries or AreaSeries.
+*/
+
+/*!
+ \property QXYSeries::pointLabelsFormat
+ The \a format used for showing labels with series points.
+
+ QXYSeries supports the following format tags:
+ \table
+ \row
+ \li @xPoint \li The x value of the data point
+ \row
+ \li @yPoint \li The y value of the data point
+ \endtable
+
+ For example, the following usage of the format tags would produce labels that have the data
+ point (x, y) shown inside brackets separated by a comma:
+ \code
+ series->setPointLabelsFormat("(@xPoint, @yPoint)");
+ \endcode
+
+ By default, the labels format is set to '@xPoint, @yPoint'. The labels are shown on the plot
+ area, labels on the edge of the plot area are cut. If the points are close to each other the
+ labels may overlap.
+
+ \sa QXYSeries::pointLabelsVisible, QXYSeries::pointLabelsFont, QXYSeries::pointLabelsColor
+*/
+/*!
+ \qmlproperty string XYSeries::pointLabelsFormat
+ The \a format used for showing labels with series points.
+
+ \sa QXYSeries::pointLabelsFormat, pointLabelsVisible, pointLabelsFont, pointLabelsColor
+*/
+/*!
+ \fn void QXYSeries::pointLabelsFormatChanged(const QString &format)
+ Signal is emitted when the \a format of data point labels is changed.
+*/
+/*!
+ \qmlsignal XYSeries::onPointLabelsFormatChanged(string format)
+ Signal is emitted when the \a format of data point labels is changed.
+*/
+
+/*!
+ \property QXYSeries::pointLabelsVisible
+ Defines the visibility for data point labels. False by default.
+
+ \sa QXYSeries::pointLabelsFormat
+*/
+/*!
+ \qmlproperty bool XYSeries::pointLabelsVisible
+ Defines the visibility for data point labels.
+
+ \sa pointLabelsFormat
+*/
+/*!
+ \fn void QXYSeries::pointLabelsVisibilityChanged(bool visible)
+ The visibility of the data point labels is changed to \a visible.
+*/
+/*!
+ \qmlsignal XYSeries::onPointLabelsVisibilityChanged(bool visible)
+ The visibility of the data point labels is changed to \a visible.
+*/
+
+/*!
+ \property QXYSeries::pointLabelsFont
+ Defines the font used for data point labels.
+
+ \sa QXYSeries::pointLabelsFormat
+*/
+/*!
+ \qmlproperty font XYSeries::pointLabelsFont
+ Defines the font used for data point labels.
+
+ \sa pointLabelsFormat
+*/
+/*!
+ \fn void QXYSeries::pointLabelsFontChanged(const QFont &font);
+ The font used for data point labels is changed to \a font.
+*/
+/*!
+ \qmlsignal XYSeries::onPointLabelsFontChanged(Font font)
+ The font used for data point labels is changed to \a font.
+*/
+
+/*!
+ \property QXYSeries::pointLabelsColor
+ Defines the color used for data point labels. By default, the color is the color of the brush
+ defined in theme for labels.
+
+ \sa QXYSeries::pointLabelsFormat
+*/
+/*!
+ \qmlproperty font XYSeries::pointLabelsColor
+ Defines the color used for data point labels. By default, the color is the color of the brush
+ defined in theme for labels.
+
+ \sa pointLabelsFormat
+*/
+/*!
+ \fn void QXYSeries::pointLabelsColorChanged(const QColor &color);
+ The color used for data point labels is changed to \a color.
+*/
+/*!
+ \qmlsignal XYSeries::onPointLabelsColorChanged(Color color)
+ The color used for data point labels is changed to \a color.
+*/
+
+/*!
+ \fn void QXYSeries::clicked(const QPointF& point)
+ \brief Signal is emitted when user clicks the \a point on chart.
+*/
+/*!
+ \qmlsignal XYSeries::onClicked(QPointF point)
+ Signal is emitted when user clicks the \a point on chart. For example:
+ \code
+ LineSeries {
+ XYPoint { x: 0; y: 0 }
+ XYPoint { x: 1.1; y: 2.1 }
+ onClicked: console.log("onClicked: " + point.x + ", " + point.y);
+ }
+ \endcode
+*/
+
+/*!
+ \fn void QXYSeries::hovered(const QPointF &point, bool state)
+ This signal is emitted when user has hovered over or away from the series. \a point shows the origin (coordinate)
+ of the hover event. \a state is true when user has hovered over the series and false when hover has moved away from
+ the series.
+*/
+/*!
+ \qmlsignal XYSeries::onHovered(point point, bool state)
+ This signal is emitted when user has hovered over or away from the series. \a point shows the origin (coordinate)
+ of the hover event. \a state is true when user has hovered over the series and false when hover has moved away from
+ the series.
+*/
+
+/*!
+ \fn void QXYSeries::pointReplaced(int index)
+ Signal is emitted when a point has been replaced at \a index.
+ \sa replace()
+*/
+/*!
+ \qmlsignal XYSeries::onPointReplaced(int index)
+ Signal is emitted when a point has been replaced at \a index.
+*/
+
+/*!
+ \fn void QXYSeries::pointsReplaced()
+ Signal is emitted when all points have been replaced with other points.
+ \sa replace()
+*/
+/*!
+ \qmlsignal XYSeries::onPointsReplaced()
+*/
+
+/*!
+ \fn void QXYSeries::pointAdded(int index)
+ Signal is emitted when a point has been added at \a index.
+ \sa append(), insert()
+*/
+/*!
+ \qmlsignal XYSeries::onPointAdded(int index)
+ Signal is emitted when a point has been added at \a index.
+*/
+
+/*!
+ \fn void QXYSeries::pointRemoved(int index)
+ Signal is emitted when a point has been removed from \a index.
+ \sa remove()
+*/
+/*!
+ \qmlsignal XYSeries::onPointRemoved(int index)
+ Signal is emitted when a point has been removed from \a index.
+*/
+
+/*!
+ \fn void QXYSeries::colorChanged(QColor color)
+ \brief Signal is emitted when the line (pen) color has changed to \a color.
+*/
+/*!
+ \qmlsignal XYSeries::onColorChanged(color color)
+ Signal is emitted when the line (pen) color has changed to \a color.
+*/
+
+/*!
+ \fn void QXYSeriesPrivate::updated()
+ \brief \internal
+*/
+
+/*!
+ \qmlmethod XYSeries::append(real x, real y)
+ Append point (\a x, \a y) to the series
+*/
+
+/*!
+ \qmlmethod XYSeries::replace(real oldX, real oldY, real newX, real newY)
+ Replaces point (\a oldX, \a oldY) with point (\a newX, \a newY). Does nothing, if point (oldX, oldY) does not
+ exist.
+*/
+
+/*!
+ \qmlmethod XYSeries::remove(real x, real y)
+ Removes point (\a x, \a y) from the series. Does nothing, if point (x, y) does not exist.
+*/
+
+/*!
+ \qmlmethod XYSeries::insert(int index, real x, real y)
+ Inserts point (\a x, \a y) to the \a index. If index is 0 or smaller than 0 the point is prepended to the list of
+ points. If index is the same as or bigger than count, the point is appended to the list of points.
+*/
+
+/*!
+ \qmlmethod QPointF XYSeries::at(int index)
+ Returns point at \a index. Returns (0, 0) if the index is not valid.
+*/
+
+/*!
+ \internal
+
+ Constructs empty series object which is a child of \a parent.
+ When series object is added to QChart instance ownerships is transferred.
+*/
+QXYSeries::QXYSeries(QXYSeriesPrivate &d, QObject *parent)
+ : QAbstractSeries(d, parent)
+{
+}
+
+/*!
+ Destroys the object. Series added to QChart instances are owned by those,
+ and are destroyed when QChart instances are destroyed.
+*/
+QXYSeries::~QXYSeries()
+{
+}
+
+/*!
+ Adds data point (\a x, \a y) to the series.
+ */
+void QXYSeries::append(qreal x, qreal y)
+{
+ append(QPointF(x, y));
+}
+
+/*!
+ This is an overloaded function.
+ Adds data \a point to the series.
+ */
+void QXYSeries::append(const QPointF &point)
+{
+ Q_D(QXYSeries);
+
+ if (isValidValue(point)) {
+ d->m_points << point;
+ emit pointAdded(d->m_points.count() - 1);
+ }
+}
+
+/*!
+ This is an overloaded function.
+ Adds list of data \a points to the series.
+ */
+void QXYSeries::append(const QList<QPointF> &points)
+{
+ foreach (const QPointF &point , points)
+ append(point);
+}
+
+/*!
+ Replaces data point (\a oldX, \a oldY) with data point (\a newX, \a newY).
+ \sa QXYSeries::pointReplaced()
+*/
+void QXYSeries::replace(qreal oldX, qreal oldY, qreal newX, qreal newY)
+{
+ replace(QPointF(oldX, oldY), QPointF(newX, newY));
+}
+
+/*!
+ Replaces \a oldPoint with \a newPoint.
+ \sa QXYSeries::pointReplaced()
+*/
+void QXYSeries::replace(const QPointF &oldPoint, const QPointF &newPoint)
+{
+ Q_D(QXYSeries);
+ int index = d->m_points.indexOf(oldPoint);
+ if (index == -1)
+ return;
+ replace(index, newPoint);
+}
+
+/*!
+ Replaces the point at \a index with data point (\a newX, \a newY).
+ \sa QXYSeries::pointReplaced()
+*/
+void QXYSeries::replace(int index, qreal newX, qreal newY)
+{
+ replace(index, QPointF(newX, newY));
+}
+
+/*!
+ Replaces the point at \a index with \a newPoint.
+ \sa QXYSeries::pointReplaced()
+*/
+void QXYSeries::replace(int index, const QPointF &newPoint)
+{
+ Q_D(QXYSeries);
+ if (isValidValue(newPoint)) {
+ d->m_points[index] = newPoint;
+ emit pointReplaced(index);
+ }
+}
+
+/*!
+ Replaces the current points with \a points.
+ \note This is much faster than replacing data points one by one,
+ or first clearing all data, and then appending the new data. Emits QXYSeries::pointsReplaced()
+ when the points have been replaced.
+ \sa QXYSeries::pointsReplaced()
+*/
+void QXYSeries::replace(QList<QPointF> points)
+{
+ Q_D(QXYSeries);
+ d->m_points = points.toVector();
+ emit pointsReplaced();
+}
+
+/*!
+ Removes the point (\a x, \a y) from the series.
+*/
+void QXYSeries::remove(qreal x, qreal y)
+{
+ remove(QPointF(x, y));
+}
+
+/*!
+ Removes the \a point from the series.
+*/
+void QXYSeries::remove(const QPointF &point)
+{
+ Q_D(QXYSeries);
+ int index = d->m_points.indexOf(point);
+ if (index == -1)
+ return;
+ remove(index);
+}
+
+/*!
+ Removes the point at \a index from the series.
+*/
+void QXYSeries::remove(int index)
+{
+ Q_D(QXYSeries);
+ d->m_points.remove(index);
+ emit pointRemoved(index);
+}
+
+/*!
+ Inserts a \a point in the series at \a index position.
+*/
+void QXYSeries::insert(int index, const QPointF &point)
+{
+ Q_D(QXYSeries);
+ if (isValidValue(point)) {
+ d->m_points.insert(index, point);
+ emit pointAdded(index);
+ }
+}
+
+/*!
+ Removes all points from the series.
+*/
+void QXYSeries::clear()
+{
+ Q_D(QXYSeries);
+ for (int i = d->m_points.size() - 1; i >= 0; i--)
+ remove(d->m_points.at(i));
+}
+
+/*!
+ Returns list of points in the series.
+*/
+QList<QPointF> QXYSeries::points() const
+{
+ Q_D(const QXYSeries);
+ return d->m_points.toList();
+}
+
+/*!
+ Returns point at \a index in internal points vector.
+*/
+const QPointF &QXYSeries::at(int index) const
+{
+ Q_D(const QXYSeries);
+ return d->m_points.at(index);
+}
+
+/*!
+ Returns number of data points within series.
+*/
+int QXYSeries::count() const
+{
+ Q_D(const QXYSeries);
+ return d->m_points.count();
+}
+
+
+/*!
+ Sets \a pen used for drawing points on the chart. If the pen is not defined, the
+ pen from chart theme is used.
+ \sa QChart::setTheme()
+*/
+void QXYSeries::setPen(const QPen &pen)
+{
+ Q_D(QXYSeries);
+ if (d->m_pen != pen) {
+ bool emitColorChanged = d->m_pen.color() != pen.color();
+ d->m_pen = pen;
+ emit d->updated();
+ if (emitColorChanged)
+ emit colorChanged(pen.color());
+ }
+}
+
+QPen QXYSeries::pen() const
+{
+ Q_D(const QXYSeries);
+ if (d->m_pen == QChartPrivate::defaultPen())
+ return QPen();
+ else
+ return d->m_pen;
+}
+
+/*!
+ Sets \a brush used for drawing points on the chart. If the brush is not defined, brush
+ from chart theme setting is used.
+ \sa QChart::setTheme()
+*/
+void QXYSeries::setBrush(const QBrush &brush)
+{
+ Q_D(QXYSeries);
+ if (d->m_brush != brush) {
+ d->m_brush = brush;
+ emit d->updated();
+ }
+}
+
+QBrush QXYSeries::brush() const
+{
+ Q_D(const QXYSeries);
+ if (d->m_brush == QChartPrivate::defaultBrush())
+ return QBrush();
+ else
+ return d->m_brush;
+}
+
+void QXYSeries::setColor(const QColor &color)
+{
+ QPen p = pen();
+ if (p.color() != color) {
+ p.setColor(color);
+ setPen(p);
+ }
+}
+
+QColor QXYSeries::color() const
+{
+ return pen().color();
+}
+
+void QXYSeries::setPointsVisible(bool visible)
+{
+ Q_D(QXYSeries);
+ if (d->m_pointsVisible != visible) {
+ d->m_pointsVisible = visible;
+ emit d->updated();
+ }
+}
+
+bool QXYSeries::pointsVisible() const
+{
+ Q_D(const QXYSeries);
+ return d->m_pointsVisible;
+}
+
+void QXYSeries::setPointLabelsFormat(const QString &format)
+{
+ Q_D(QXYSeries);
+ if (d->m_pointLabelsFormat != format) {
+ d->m_pointLabelsFormat = format;
+ emit pointLabelsFormatChanged(format);
+ }
+}
+
+QString QXYSeries::pointLabelsFormat() const
+{
+ Q_D(const QXYSeries);
+ return d->m_pointLabelsFormat;
+}
+
+void QXYSeries::setPointLabelsVisible(bool visible)
+{
+ Q_D(QXYSeries);
+ if (d->m_pointLabelsVisible != visible) {
+ d->m_pointLabelsVisible = visible;
+ emit pointLabelsVisibilityChanged(visible);
+ }
+}
+
+bool QXYSeries::pointLabelsVisible() const
+{
+ Q_D(const QXYSeries);
+ return d->m_pointLabelsVisible;
+}
+
+void QXYSeries::setPointLabelsFont(const QFont &font)
+{
+ Q_D(QXYSeries);
+ if (d->m_pointLabelsFont != font) {
+ d->m_pointLabelsFont = font;
+ emit pointLabelsFontChanged(font);
+ }
+}
+
+QFont QXYSeries::pointLabelsFont() const
+{
+ Q_D(const QXYSeries);
+ return d->m_pointLabelsFont;
+}
+
+void QXYSeries::setPointLabelsColor(const QColor &color)
+{
+ Q_D(QXYSeries);
+ if (d->m_pointLabelsColor != color) {
+ d->m_pointLabelsColor = color;
+ emit pointLabelsColorChanged(color);
+ }
+}
+
+QColor QXYSeries::pointLabelsColor() const
+{
+ Q_D(const QXYSeries);
+ if (d->m_pointLabelsColor == QChartPrivate::defaultPen().color())
+ return QPen().color();
+ else
+ return d->m_pointLabelsColor;
+}
+
+/*!
+ Stream operator for adding a data \a point to the series.
+ \sa append()
+*/
+QXYSeries &QXYSeries::operator<< (const QPointF &point)
+{
+ append(point);
+ return *this;
+}
+
+
+/*!
+ Stream operator for adding a list of \a points to the series.
+ \sa append()
+*/
+
+QXYSeries &QXYSeries::operator<< (const QList<QPointF>& points)
+{
+ append(points);
+ return *this;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+QXYSeriesPrivate::QXYSeriesPrivate(QXYSeries *q)
+ : QAbstractSeriesPrivate(q),
+ m_pen(QChartPrivate::defaultPen()),
+ m_brush(QChartPrivate::defaultBrush()),
+ m_pointsVisible(false),
+ m_pointLabelsFormat(QLatin1String("@xPoint, @yPoint")),
+ m_pointLabelsVisible(false),
+ m_pointLabelsFont(QChartPrivate::defaultFont()),
+ m_pointLabelsColor(QChartPrivate::defaultPen().color())
+{
+}
+
+void QXYSeriesPrivate::initializeDomain()
+{
+ qreal minX(0);
+ qreal minY(0);
+ qreal maxX(1);
+ qreal maxY(1);
+
+ Q_Q(QXYSeries);
+
+ const QList<QPointF>& points = q->points();
+
+ if (!points.isEmpty()) {
+ minX = points[0].x();
+ minY = points[0].y();
+ maxX = minX;
+ maxY = minY;
+
+ for (int i = 0; i < points.count(); i++) {
+ qreal x = points[i].x();
+ qreal y = points[i].y();
+ minX = qMin(minX, x);
+ minY = qMin(minY, y);
+ maxX = qMax(maxX, x);
+ maxY = qMax(maxY, y);
+ }
+ }
+
+ domain()->setRange(minX, maxX, minY, maxY);
+}
+
+QList<QLegendMarker*> QXYSeriesPrivate::createLegendMarkers(QLegend* legend)
+{
+ Q_Q(QXYSeries);
+ QList<QLegendMarker*> list;
+ return list << new QXYLegendMarker(q,legend);
+}
+
+void QXYSeriesPrivate::initializeAxes()
+{
+
+}
+
+QAbstractAxis::AxisType QXYSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
+{
+ Q_UNUSED(orientation);
+ return QAbstractAxis::AxisTypeValue;
+}
+
+QAbstractAxis* QXYSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const
+{
+ Q_UNUSED(orientation);
+ return new QValueAxis;
+}
+
+void QXYSeriesPrivate::initializeAnimations(QtCharts::QChart::AnimationOptions options)
+{
+ XYChart *item = static_cast<XYChart *>(m_item.data());
+ Q_ASSERT(item);
+ if (item->animation())
+ item->animation()->stopAndDestroyLater();
+
+ if (options.testFlag(QChart::SeriesAnimations))
+ item->setAnimation(new XYAnimation(item));
+ else
+ item->setAnimation(0);
+ QAbstractSeriesPrivate::initializeAnimations(options);
+}
+
+void QXYSeriesPrivate::drawSeriesPointLabels(QPainter *painter, const QVector<QPointF> &points,
+ const int offset)
+{
+ static const QString xPointTag(QLatin1String("@xPoint"));
+ static const QString yPointTag(QLatin1String("@yPoint"));
+ const int labelOffset = offset + 2;
+
+ painter->setFont(m_pointLabelsFont);
+ painter->setPen(QPen(m_pointLabelsColor));
+ QFontMetrics fm(painter->font());
+
+ for (int i(0); i < m_points.size(); i++) {
+ QString pointLabel = m_pointLabelsFormat;
+ pointLabel.replace(xPointTag, presenter()->numberToString(m_points.at(i).x()));
+ pointLabel.replace(yPointTag, presenter()->numberToString(m_points.at(i).y()));
+
+ // Position text in relation to the point
+ int pointLabelWidth = fm.width(pointLabel);
+ QPointF position(points.at(i));
+ position.setX(position.x() - pointLabelWidth / 2);
+ position.setY(position.y() - labelOffset);
+
+ painter->drawText(position, pointLabel);
+ }
+}
+
+#include "moc_qxyseries.cpp"
+#include "moc_qxyseries_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/xychart/qxyseries.h b/src/charts/xychart/qxyseries.h
new file mode 100644
index 00000000..4c73bf07
--- /dev/null
+++ b/src/charts/xychart/qxyseries.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QXYSERIES_H
+#define QXYSERIES_H
+
+#include <QtCharts/qchartglobal.h>
+#include <QtCharts/qabstractseries.h>
+#include <QPen>
+#include <QBrush>
+
+class QModelIndex;
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QXYSeriesPrivate;
+class QXYModelMapper;
+
+class QT_CHARTS_EXPORT QXYSeries : public QAbstractSeries
+{
+ Q_OBJECT
+ Q_PROPERTY(bool pointsVisible READ pointsVisible WRITE setPointsVisible)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+ Q_PROPERTY(QString pointLabelsFormat READ pointLabelsFormat WRITE setPointLabelsFormat NOTIFY pointLabelsFormatChanged)
+ Q_PROPERTY(bool pointLabelsVisible READ pointLabelsVisible WRITE setPointLabelsVisible NOTIFY pointLabelsVisibilityChanged)
+ Q_PROPERTY(QFont pointLabelsFont READ pointLabelsFont WRITE setPointLabelsFont NOTIFY pointLabelsFontChanged)
+ Q_PROPERTY(QColor pointLabelsColor READ pointLabelsColor WRITE setPointLabelsColor NOTIFY pointLabelsColorChanged)
+
+protected:
+ explicit QXYSeries(QXYSeriesPrivate &d, QObject *parent = 0);
+
+public:
+ ~QXYSeries();
+ void append(qreal x, qreal y);
+ void append(const QPointF &point);
+ void append(const QList<QPointF> &points);
+ void replace(qreal oldX, qreal oldY, qreal newX, qreal newY);
+ void replace(const QPointF &oldPoint, const QPointF &newPoint);
+ void replace(int index, qreal newX, qreal newY);
+ void replace(int index, const QPointF &newPoint);
+ void remove(qreal x, qreal y);
+ void remove(const QPointF &point);
+ void remove(int index);
+ void insert(int index, const QPointF &point);
+ void clear();
+
+ int count() const;
+ QList<QPointF> points() const;
+ const QPointF &at(int index) const;
+
+ QXYSeries &operator << (const QPointF &point);
+ QXYSeries &operator << (const QList<QPointF> &points);
+
+ virtual void setPen(const QPen &pen);
+ QPen pen() const;
+
+ virtual void setBrush(const QBrush &brush);
+ QBrush brush() const;
+
+ virtual void setColor(const QColor &color);
+ virtual QColor color() const;
+
+ void setPointsVisible(bool visible = true);
+ bool pointsVisible() const;
+
+ void setPointLabelsFormat(const QString &format);
+ QString pointLabelsFormat() const;
+
+ void setPointLabelsVisible(bool visible = true);
+ bool pointLabelsVisible() const;
+
+ void setPointLabelsFont(const QFont &font);
+ QFont pointLabelsFont() const;
+
+ void setPointLabelsColor(const QColor &color);
+ QColor pointLabelsColor() const;
+
+ void replace(QList<QPointF> points);
+
+Q_SIGNALS:
+ void clicked(const QPointF &point);
+ void hovered(const QPointF &point, bool state);
+ void pointReplaced(int index);
+ void pointRemoved(int index);
+ void pointAdded(int index);
+ void colorChanged(QColor color);
+ void pointsReplaced();
+ void pointLabelsFormatChanged(const QString &format);
+ void pointLabelsVisibilityChanged(bool visible);
+ void pointLabelsFontChanged(const QFont &font);
+ void pointLabelsColorChanged(const QColor &color);
+
+private:
+ Q_DECLARE_PRIVATE(QXYSeries)
+ Q_DISABLE_COPY(QXYSeries)
+ friend class QXYLegendMarkerPrivate;
+ friend class XYLegendMarker;
+ friend class XYChart;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif // QXYSERIES_H
diff --git a/src/charts/xychart/qxyseries_p.h b/src/charts/xychart/qxyseries_p.h
new file mode 100644
index 00000000..cee78a08
--- /dev/null
+++ b/src/charts/xychart/qxyseries_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 QXYSERIES_P_H
+#define QXYSERIES_P_H
+
+#include "qabstractseries_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class QXYSeries;
+class QAbstractAxis;
+
+class QXYSeriesPrivate: public QAbstractSeriesPrivate
+{
+ Q_OBJECT
+
+public:
+ QXYSeriesPrivate(QXYSeries *q);
+
+ void initializeDomain();
+ void initializeAxes();
+ void initializeAnimations(QtCharts::QChart::AnimationOptions options);
+
+ QList<QLegendMarker*> createLegendMarkers(QLegend* legend);
+
+ QAbstractAxis::AxisType defaultAxisType(Qt::Orientation orientation) const;
+ QAbstractAxis* createDefaultAxis(Qt::Orientation orientation) const;
+
+ void drawSeriesPointLabels(QPainter *painter, const QVector<QPointF> &points,
+ const int offset = 0);
+
+Q_SIGNALS:
+ void updated();
+
+protected:
+ QVector<QPointF> m_points;
+ QPen m_pen;
+ QBrush m_brush;
+ bool m_pointsVisible;
+ QString m_pointLabelsFormat;
+ bool m_pointLabelsVisible;
+ QFont m_pointLabelsFont;
+ QColor m_pointLabelsColor;
+
+private:
+ Q_DECLARE_PUBLIC(QXYSeries)
+ friend class QScatterSeries;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif
diff --git a/src/charts/xychart/xychart.cpp b/src/charts/xychart/xychart.cpp
new file mode 100644
index 00000000..18347d26
--- /dev/null
+++ b/src/charts/xychart/xychart.cpp
@@ -0,0 +1,189 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+ **
+ ** $QT_BEGIN_LICENSE$
+ ** 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
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include "xychart_p.h"
+#include "qxyseries.h"
+#include "qxyseries_p.h"
+#include "chartpresenter_p.h"
+#include "abstractdomain_p.h"
+#include "qxymodelmapper.h"
+#include "qabstractaxis_p.h"
+#include <QPainter>
+#include <QAbstractItemModel>
+
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+XYChart::XYChart(QXYSeries *series, QGraphicsItem *item):
+ ChartItem(series->d_func(),item),
+ m_series(series),
+ m_animation(0),
+ m_dirty(true)
+{
+ QObject::connect(series, SIGNAL(pointReplaced(int)), this, SLOT(handlePointReplaced(int)));
+ QObject::connect(series, SIGNAL(pointsReplaced()), this, SLOT(handlePointsReplaced()));
+ QObject::connect(series, SIGNAL(pointAdded(int)), this, SLOT(handlePointAdded(int)));
+ QObject::connect(series, SIGNAL(pointRemoved(int)), this, SLOT(handlePointRemoved(int)));
+ QObject::connect(this, SIGNAL(clicked(QPointF)), series, SIGNAL(clicked(QPointF)));
+ QObject::connect(this, SIGNAL(hovered(QPointF,bool)), series, SIGNAL(hovered(QPointF,bool)));
+}
+
+void XYChart::setGeometryPoints(const QVector<QPointF> &points)
+{
+ m_points = points;
+}
+
+void XYChart::setAnimation(XYAnimation *animation)
+{
+ m_animation = animation;
+}
+
+void XYChart::setDirty(bool dirty)
+{
+ m_dirty = dirty;
+}
+
+// Returns a vector with same size as geometryPoints vector, indicating
+// the off grid status of points.
+QVector<bool> XYChart::offGridStatusVector()
+{
+ qreal minX = domain()->minX();
+ qreal maxX = domain()->maxX();
+ qreal minY = domain()->minY();
+ qreal maxY = domain()->maxY();
+
+ QVector<bool> returnVector;
+ returnVector.resize(m_points.size());
+ // During remove animation series may have different number of points,
+ // so ensure we don't go over the index. No need to check for zero points, this
+ // will not be called in such a situation.
+ const int seriesLastIndex = m_series->count() - 1;
+
+ for (int i = 0; i < m_points.size(); i++) {
+ const QPointF &seriesPoint = m_series->at(qMin(seriesLastIndex, i));
+ if (seriesPoint.x() < minX
+ || seriesPoint.x() > maxX
+ || seriesPoint.y() < minY
+ || seriesPoint.y() > maxY) {
+ returnVector[i] = true;
+ } else {
+ returnVector[i] = false;
+ }
+ }
+ return returnVector;
+}
+
+void XYChart::updateChart(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, int index)
+{
+
+ if (m_animation) {
+ m_animation->setup(oldPoints, newPoints, index);
+ m_points = newPoints;
+ setDirty(false);
+ presenter()->startAnimation(m_animation);
+ } else {
+ m_points = newPoints;
+ updateGeometry();
+ }
+}
+
+//handlers
+
+void XYChart::handlePointAdded(int index)
+{
+ Q_ASSERT(index < m_series->count());
+ Q_ASSERT(index >= 0);
+
+ QVector<QPointF> points;
+
+ if (m_dirty || m_points.isEmpty()) {
+ points = domain()->calculateGeometryPoints(m_series->points());
+ } else {
+ points = m_points;
+ QPointF point = domain()->calculateGeometryPoint(m_series->points()[index], m_validData);
+ if (!m_validData)
+ m_points.clear();
+ else
+ points.insert(index, point);
+ }
+
+ updateChart(m_points, points, index);
+}
+
+void XYChart::handlePointRemoved(int index)
+{
+ Q_ASSERT(index <= m_series->count());
+ Q_ASSERT(index >= 0);
+
+ QVector<QPointF> points;
+
+ if (m_dirty || m_points.isEmpty()) {
+ points = domain()->calculateGeometryPoints(m_series->points());
+ } else {
+ points = m_points;
+ points.remove(index);
+ }
+
+ updateChart(m_points, points, index);
+}
+
+void XYChart::handlePointReplaced(int index)
+{
+ Q_ASSERT(index < m_series->count());
+ Q_ASSERT(index >= 0);
+
+ QVector<QPointF> points;
+
+ if (m_dirty || m_points.isEmpty()) {
+ points = domain()->calculateGeometryPoints(m_series->points());
+ } else {
+ QPointF point = domain()->calculateGeometryPoint(m_series->points()[index], m_validData);
+ if (!m_validData)
+ m_points.clear();
+ points = m_points;
+ if (m_validData)
+ points.replace(index, point);
+ }
+
+ updateChart(m_points, points, index);
+}
+
+void XYChart::handlePointsReplaced()
+{
+ // All the points were replaced -> recalculate
+ QVector<QPointF> points = domain()->calculateGeometryPoints(m_series->points());
+ updateChart(m_points, points, -1);
+}
+
+void XYChart::handleDomainUpdated()
+{
+ if (isEmpty()) return;
+ QVector<QPointF> points = domain()->calculateGeometryPoints(m_series->points());
+ updateChart(m_points, points);
+}
+
+bool XYChart::isEmpty()
+{
+ return domain()->isEmpty() || m_series->points().isEmpty();
+}
+
+#include "moc_xychart_p.cpp"
+
+QT_CHARTS_END_NAMESPACE
diff --git a/src/charts/xychart/xychart.pri b/src/charts/xychart/xychart.pri
new file mode 100644
index 00000000..e7af66e5
--- /dev/null
+++ b/src/charts/xychart/xychart.pri
@@ -0,0 +1,20 @@
+#INCLUDEPATH += $$PWD
+#DEPENDPATH += $$PWD
+
+SOURCES += \
+ $$PWD/xychart.cpp \
+ $$PWD/qxyseries.cpp \
+ $$PWD/qxymodelmapper.cpp \
+ $$PWD/qvxymodelmapper.cpp \
+ $$PWD/qhxymodelmapper.cpp
+
+PRIVATE_HEADERS += \
+ $$PWD/xychart_p.h \
+ $$PWD/qxyseries_p.h \
+ $$PWD/qxymodelmapper_p.h
+
+PUBLIC_HEADERS += \
+ $$PWD/qxyseries.h \
+ $$PWD/qxymodelmapper.h \
+ $$PWD/qvxymodelmapper.h \
+ $$PWD/qhxymodelmapper.h
diff --git a/src/charts/xychart/xychart_p.h b/src/charts/xychart/xychart_p.h
new file mode 100644
index 00000000..78689045
--- /dev/null
+++ b/src/charts/xychart/xychart_p.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** 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
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Enterprise Chart 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 XYCHART_H
+#define XYCHART_H
+
+#include <qchartglobal.h>
+#include "chartitem_p.h"
+#include "xyanimation_p.h"
+#include "qvalueaxis.h"
+#include <QPen>
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+class ChartPresenter;
+class QXYSeries;
+
+class XYChart : public ChartItem
+{
+ Q_OBJECT
+public:
+ explicit XYChart(QXYSeries *series,QGraphicsItem *item = 0);
+ ~XYChart() {}
+
+ void setGeometryPoints(const QVector<QPointF> &points);
+ QVector<QPointF> geometryPoints() const { return m_points; }
+
+ void setAnimation(XYAnimation *animation);
+ ChartAnimation *animation() const { return m_animation; }
+ virtual void updateGeometry() = 0;
+
+ bool isDirty() const { return m_dirty; }
+ void setDirty(bool dirty);
+
+ void getSeriesRanges(qreal &minX, qreal &maxX, qreal &minY, qreal &maxY);
+ QVector<bool> offGridStatusVector();
+
+public Q_SLOTS:
+ void handlePointAdded(int index);
+ void handlePointRemoved(int index);
+ void handlePointReplaced(int index);
+ void handlePointsReplaced();
+ void handleDomainUpdated();
+
+Q_SIGNALS:
+ void clicked(const QPointF &point);
+ void hovered(const QPointF &point, bool state);
+
+protected:
+ virtual void updateChart(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, int index = -1);
+
+private:
+ inline bool isEmpty();
+
+protected:
+ QXYSeries *m_series;
+ QVector<QPointF> m_points;
+ XYAnimation *m_animation;
+ bool m_dirty;
+
+ friend class AreaChartItem;
+};
+
+QT_CHARTS_END_NAMESPACE
+
+#endif