summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@digia.com>2013-04-16 10:07:13 +0300
committerMiikka Heikkinen <miikka.heikkinen@digia.com>2013-04-17 10:14:43 +0300
commitf494279b6366b06e3eeeb4f8c006ce76b08f10d7 (patch)
tree26951efa14e26eb0791d13ea32624e9afcf48851
parent56fd46a395765db6818f890676e42cc59a9f4a81 (diff)
Add Polar chart support
This commit also heavily refactors things as polar chart needs separate implementation of various classes that previously only needed one, such as ChartAxis and ChartLayout. Task-number: QTRD-1757 Change-Id: I3d3db23920314987ceef3ae92879960b833b7136 Reviewed-by: Miikka Heikkinen <miikka.heikkinen@digia.com>
-rw-r--r--demos/chartinteractions/chart.cpp2
-rw-r--r--demos/demos.pro3
-rw-r--r--demos/dynamicspline/chart.cpp2
-rw-r--r--demos/qmlpolarchart/main.cpp36
-rw-r--r--demos/qmlpolarchart/qml/qmlpolarchart/View1.qml68
-rw-r--r--demos/qmlpolarchart/qml/qmlpolarchart/View2.qml89
-rw-r--r--demos/qmlpolarchart/qml/qmlpolarchart/View3.qml76
-rw-r--r--demos/qmlpolarchart/qml/qmlpolarchart/loader.qml37
-rw-r--r--demos/qmlpolarchart/qml/qmlpolarchart/main.qml90
-rw-r--r--demos/qmlpolarchart/qmlapplicationviewer/qmlapplicationviewer.cpp177
-rw-r--r--demos/qmlpolarchart/qmlapplicationviewer/qmlapplicationviewer.h46
-rw-r--r--demos/qmlpolarchart/qmlapplicationviewer/qmlapplicationviewer.pri13
-rw-r--r--demos/qmlpolarchart/qmlpolarchart.pro9
-rw-r--r--demos/qmlpolarchart/resources.qrc9
-rw-r--r--doc/images/demos_qmlpolarchart1.pngbin0 -> 41088 bytes
-rw-r--r--doc/images/demos_qmlpolarchart2.pngbin0 -> 42741 bytes
-rw-r--r--doc/images/demos_qmlpolarchart3.pngbin0 -> 35469 bytes
-rw-r--r--doc/images/examples_polarchart.pngbin0 -> 116120 bytes
-rw-r--r--doc/src/classes.qdoc1
-rw-r--r--doc/src/demos-qmlpolarchart.qdoc33
-rw-r--r--doc/src/demos.qdoc20
-rw-r--r--doc/src/examples-polarchart.qdoc33
-rw-r--r--doc/src/examples.qdoc14
-rw-r--r--doc/src/qml.qdoc1
-rw-r--r--examples/donutbreakdown/donutbreakdownchart.cpp2
-rw-r--r--examples/examples.pro3
-rw-r--r--examples/piechartdrilldown/drilldownchart.cpp2
-rw-r--r--examples/polarchart/chartview.cpp111
-rw-r--r--examples/polarchart/chartview.h41
-rw-r--r--examples/polarchart/main.cpp137
-rw-r--r--examples/polarchart/polarchart.pro6
-rw-r--r--examples/stackedbarchartdrilldown/drilldownchart.cpp2
-rw-r--r--examples/zoomlinechart/chart.cpp2
-rw-r--r--plugins/declarative/declarative.pro6
-rw-r--r--plugins/declarative/declarativeareaseries.cpp2
-rw-r--r--plugins/declarative/declarativeareaseries.h8
-rw-r--r--plugins/declarative/declarativechart.cpp20
-rw-r--r--plugins/declarative/declarativechart.h4
-rw-r--r--plugins/declarative/declarativelineseries.cpp2
-rw-r--r--plugins/declarative/declarativelineseries.h8
-rw-r--r--plugins/declarative/declarativepolarchart.cpp64
-rw-r--r--plugins/declarative/declarativepolarchart.h40
-rw-r--r--plugins/declarative/declarativescatterseries.cpp2
-rw-r--r--plugins/declarative/declarativescatterseries.h8
-rw-r--r--plugins/declarative/declarativesplineseries.cpp2
-rw-r--r--plugins/declarative/declarativesplineseries.h8
-rw-r--r--plugins/declarative/plugin.cpp9
-rw-r--r--src/animations/axisanimation.cpp13
-rw-r--r--src/animations/axisanimation_p.h6
-rw-r--r--src/areachart/areachartitem.cpp24
-rw-r--r--src/areachart/areachartitem_p.h10
-rw-r--r--src/axis/axis.pri38
-rw-r--r--src/axis/barcategoryaxis/chartbarcategoryaxisx.cpp6
-rw-r--r--src/axis/barcategoryaxis/chartbarcategoryaxisy.cpp6
-rw-r--r--src/axis/barcategoryaxis/qbarcategoryaxis.cpp4
-rw-r--r--src/axis/cartesianchartaxis.cpp197
-rw-r--r--src/axis/cartesianchartaxis_p.h79
-rw-r--r--src/axis/categoryaxis/chartcategoryaxisx.cpp17
-rw-r--r--src/axis/categoryaxis/chartcategoryaxisx_p.h8
-rw-r--r--src/axis/categoryaxis/chartcategoryaxisy.cpp17
-rw-r--r--src/axis/categoryaxis/chartcategoryaxisy_p.h8
-rw-r--r--src/axis/categoryaxis/polarchartcategoryaxisangular.cpp80
-rw-r--r--src/axis/categoryaxis/polarchartcategoryaxisangular_p.h56
-rw-r--r--src/axis/categoryaxis/polarchartcategoryaxisradial.cpp79
-rw-r--r--src/axis/categoryaxis/polarchartcategoryaxisradial_p.h56
-rw-r--r--src/axis/categoryaxis/qcategoryaxis.cpp40
-rw-r--r--src/axis/categoryaxis/qcategoryaxis.h3
-rw-r--r--src/axis/categoryaxis/qcategoryaxis_p.h3
-rw-r--r--src/axis/chartaxis.cpp547
-rw-r--r--src/axis/chartaxis_p.h201
-rw-r--r--src/axis/chartaxiselement.cpp349
-rw-r--r--src/axis/chartaxiselement_p.h151
-rw-r--r--src/axis/datetimeaxis/chartdatetimeaxisx.cpp24
-rw-r--r--src/axis/datetimeaxis/chartdatetimeaxisx_p.h1
-rw-r--r--src/axis/datetimeaxis/chartdatetimeaxisy.cpp22
-rw-r--r--src/axis/datetimeaxis/chartdatetimeaxisy_p.h1
-rw-r--r--src/axis/datetimeaxis/polarchartdatetimeaxisangular.cpp80
-rw-r--r--src/axis/datetimeaxis/polarchartdatetimeaxisangular_p.h56
-rw-r--r--src/axis/datetimeaxis/polarchartdatetimeaxisradial.cpp79
-rw-r--r--src/axis/datetimeaxis/polarchartdatetimeaxisradial_p.h56
-rw-r--r--src/axis/datetimeaxis/qdatetimeaxis.cpp21
-rw-r--r--src/axis/horizontalaxis.cpp42
-rw-r--r--src/axis/horizontalaxis_p.h6
-rw-r--r--src/axis/linearrowitem_p.h76
-rw-r--r--src/axis/logvalueaxis/chartlogvalueaxisx.cpp14
-rw-r--r--src/axis/logvalueaxis/chartlogvalueaxisx_p.h4
-rw-r--r--src/axis/logvalueaxis/chartlogvalueaxisy.cpp14
-rw-r--r--src/axis/logvalueaxis/chartlogvalueaxisy_p.h4
-rw-r--r--src/axis/logvalueaxis/polarchartlogvalueaxisangular.cpp90
-rw-r--r--src/axis/logvalueaxis/polarchartlogvalueaxisangular_p.h57
-rw-r--r--src/axis/logvalueaxis/polarchartlogvalueaxisradial.cpp95
-rw-r--r--src/axis/logvalueaxis/polarchartlogvalueaxisradial_p.h57
-rw-r--r--src/axis/logvalueaxis/qlogvalueaxis.cpp28
-rw-r--r--src/axis/polarchartaxis.cpp120
-rw-r--r--src/axis/polarchartaxis_p.h70
-rw-r--r--src/axis/polarchartaxisangular.cpp428
-rw-r--r--src/axis/polarchartaxisangular_p.h63
-rw-r--r--src/axis/polarchartaxisradial.cpp301
-rw-r--r--src/axis/polarchartaxisradial_p.h60
-rw-r--r--src/axis/qabstractaxis.cpp10
-rw-r--r--src/axis/qabstractaxis.h25
-rw-r--r--src/axis/qabstractaxis_p.h8
-rw-r--r--src/axis/valueaxis/chartvalueaxisx.cpp14
-rw-r--r--src/axis/valueaxis/chartvalueaxisx_p.h3
-rw-r--r--src/axis/valueaxis/chartvalueaxisy.cpp12
-rw-r--r--src/axis/valueaxis/chartvalueaxisy_p.h3
-rw-r--r--src/axis/valueaxis/polarchartvalueaxisangular.cpp80
-rw-r--r--src/axis/valueaxis/polarchartvalueaxisangular_p.h56
-rw-r--r--src/axis/valueaxis/polarchartvalueaxisradial.cpp79
-rw-r--r--src/axis/valueaxis/polarchartvalueaxisradial_p.h56
-rw-r--r--src/axis/valueaxis/qvalueaxis.cpp36
-rw-r--r--src/axis/verticalaxis.cpp56
-rw-r--r--src/axis/verticalaxis_p.h6
-rw-r--r--src/chartdataset.cpp207
-rw-r--r--src/chartpresenter.cpp38
-rw-r--r--src/chartpresenter_p.h19
-rw-r--r--src/domain/abstractdomain.cpp37
-rw-r--r--src/domain/abstractdomain_p.h20
-rw-r--r--src/domain/domain.pri14
-rw-r--r--src/domain/logxlogydomain.cpp31
-rw-r--r--src/domain/logxlogydomain_p.h6
-rw-r--r--src/domain/logxlogypolardomain.cpp267
-rw-r--r--src/domain/logxlogypolardomain_p.h81
-rw-r--r--src/domain/logxydomain.cpp26
-rw-r--r--src/domain/logxydomain_p.h6
-rw-r--r--src/domain/logxypolardomain.cpp236
-rw-r--r--src/domain/logxypolardomain_p.h77
-rw-r--r--src/domain/polardomain.cpp91
-rw-r--r--src/domain/polardomain_p.h62
-rw-r--r--src/domain/xlogydomain.cpp26
-rw-r--r--src/domain/xlogydomain_p.h6
-rw-r--r--src/domain/xlogypolardomain.cpp231
-rw-r--r--src/domain/xlogypolardomain_p.h77
-rw-r--r--src/domain/xydomain.cpp10
-rw-r--r--src/domain/xydomain_p.h2
-rw-r--r--src/domain/xypolardomain.cpp178
-rw-r--r--src/domain/xypolardomain_p.h65
-rw-r--r--src/layout/abstractchartlayout.cpp197
-rw-r--r--src/layout/abstractchartlayout_p.h (renamed from src/chartlayout_p.h)49
-rw-r--r--src/layout/cartesianchartlayout.cpp (renamed from src/chartlayout.cpp)188
-rw-r--r--src/layout/cartesianchartlayout_p.h50
-rw-r--r--src/layout/layout.pri12
-rw-r--r--src/layout/polarchartlayout.cpp83
-rw-r--r--src/layout/polarchartlayout_p.h50
-rw-r--r--src/legend/legendlayout.cpp2
-rw-r--r--src/legend/qlegend.cpp2
-rw-r--r--src/linechart/linechartitem.cpp249
-rw-r--r--src/linechart/linechartitem_p.h13
-rw-r--r--src/qchart.cpp71
-rw-r--r--src/qchart.h13
-rw-r--r--src/qchart_p.h6
-rw-r--r--src/qpolarchart.cpp126
-rw-r--r--src/qpolarchart.h60
-rw-r--r--src/scatterchart/scatterchartitem.cpp14
-rw-r--r--src/scatterchart/scatterchartitem_p.h2
-rw-r--r--src/splinechart/splinechartitem.cpp212
-rw-r--r--src/splinechart/splinechartitem_p.h6
-rw-r--r--src/src.pro9
-rw-r--r--src/xychart/qxyseries.cpp21
-rw-r--r--src/xychart/qxyseries.h1
-rw-r--r--src/xychart/xychart.cpp31
-rw-r--r--src/xychart/xychart_p.h7
-rw-r--r--tests/auto/README9
-rw-r--r--tests/auto/inc/tst_definitions.h44
-rw-r--r--tests/auto/qabstractaxis/tst_qabstractaxis.cpp2
-rw-r--r--tests/auto/qchart/tst_qchart.cpp81
-rw-r--r--tests/auto/qchartview/tst_qchartview.cpp17
-rw-r--r--tests/auto/qlegend/tst_qlegend.cpp19
-rw-r--r--tests/auto/qml/tst_qml.cpp66
-rw-r--r--tests/auto/qxymodelmapper/tst_qxymodelmapper.cpp3
-rw-r--r--tests/auto/qxyseries/tst_qxyseries.cpp2
-rw-r--r--tests/polarcharttest/chartview.cpp58
-rw-r--r--tests/polarcharttest/chartview.h38
-rw-r--r--tests/polarcharttest/main.cpp31
-rw-r--r--tests/polarcharttest/mainwindow.cpp1136
-rw-r--r--tests/polarcharttest/mainwindow.h155
-rw-r--r--tests/polarcharttest/mainwindow.ui929
-rw-r--r--tests/polarcharttest/polarcharttest.pro20
-rw-r--r--tests/tests.pro3
179 files changed, 9957 insertions, 1502 deletions
diff --git a/demos/chartinteractions/chart.cpp b/demos/chartinteractions/chart.cpp
index 17ee90f0..6043c9bb 100644
--- a/demos/chartinteractions/chart.cpp
+++ b/demos/chartinteractions/chart.cpp
@@ -24,7 +24,7 @@
#include <cmath>
Chart::Chart(QGraphicsItem *parent, Qt::WindowFlags wFlags, QLineSeries *series)
- : QChart(parent, wFlags), m_series(series)
+ : QChart(QChart::ChartTypeCartesian, parent, wFlags), m_series(series)
{
m_clicked = false;
}
diff --git a/demos/demos.pro b/demos/demos.pro
index 43f6c933..76a53c50 100644
--- a/demos/demos.pro
+++ b/demos/demos.pro
@@ -15,7 +15,8 @@ SUBDIRS += piechartcustomization \
chartinteractions \
qmlaxes \
qmlcustomlegend \
- callout
+ callout \
+ qmlpolarchart
contains(QT_CONFIG, opengl) {
SUBDIRS += chartthemes \
diff --git a/demos/dynamicspline/chart.cpp b/demos/dynamicspline/chart.cpp
index c7e111b5..28457778 100644
--- a/demos/dynamicspline/chart.cpp
+++ b/demos/dynamicspline/chart.cpp
@@ -26,7 +26,7 @@
#include <QDebug>
Chart::Chart(QGraphicsItem *parent, Qt::WindowFlags wFlags):
- QChart(parent, wFlags),
+ QChart(QChart::ChartTypeCartesian, parent, wFlags),
m_series(0),
m_axis(new QValueAxis),
m_step(0),
diff --git a/demos/qmlpolarchart/main.cpp b/demos/qmlpolarchart/main.cpp
new file mode 100644
index 00000000..f5f00ccd
--- /dev/null
+++ b/demos/qmlpolarchart/main.cpp
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 <QApplication>
+#include <QtDeclarative/QDeclarativeEngine>
+#include "qmlapplicationviewer.h"
+
+Q_DECL_EXPORT int main(int argc, char *argv[])
+{
+ QScopedPointer<QApplication> app(createApplication(argc, argv));
+ QScopedPointer<QmlApplicationViewer> viewer(QmlApplicationViewer::create());
+
+ // // viewer->setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
+ viewer->setSource(QUrl("qrc:/qml/qmlpolarchart/loader.qml"));
+ viewer->setRenderHint(QPainter::Antialiasing, true);
+ viewer->showExpanded();
+
+ return app->exec();
+}
diff --git a/demos/qmlpolarchart/qml/qmlpolarchart/View1.qml b/demos/qmlpolarchart/qml/qmlpolarchart/View1.qml
new file mode 100644
index 00000000..c3b849b7
--- /dev/null
+++ b/demos/qmlpolarchart/qml/qmlpolarchart/View1.qml
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 1.0
+import QtCommercial.Chart 1.3
+
+Rectangle {
+ anchors.fill: parent
+ //![1]
+ PolarChartView {
+ title: "Two Series, Common Axes"
+ anchors.fill: parent
+ legend.visible: false
+
+ ValueAxis {
+ id: axisAngular
+ min: 0
+ max: 20
+ tickCount: 9
+ }
+
+ ValueAxis {
+ id: axisRadial
+ min: -0.5
+ max: 1.5
+ }
+
+ SplineSeries {
+ id: series1
+ axisAngular: axisAngular
+ axisRadial: axisRadial
+ pointsVisible: true
+ }
+
+ ScatterSeries {
+ id: series2
+ axisAngular: axisAngular
+ axisRadial: axisRadial
+ markerSize: 10
+ }
+ }
+
+ // Add data dynamically to the series
+ Component.onCompleted: {
+ for (var i = 0; i <= 20; i++) {
+ series1.append(i, Math.random());
+ series2.append(i, Math.random());
+ }
+ }
+ //![1]
+}
diff --git a/demos/qmlpolarchart/qml/qmlpolarchart/View2.qml b/demos/qmlpolarchart/qml/qmlpolarchart/View2.qml
new file mode 100644
index 00000000..ff8ac326
--- /dev/null
+++ b/demos/qmlpolarchart/qml/qmlpolarchart/View2.qml
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 1.0
+import QtCommercial.Chart 1.3
+
+Rectangle {
+ anchors.fill: parent
+
+ //![1]
+ PolarChartView {
+ title: "Historical Area Series"
+ anchors.fill: parent
+ legend.visible: false
+
+ DateTimeAxis {
+ id: axis1
+ format: "yyyy MMM"
+ tickCount: 13
+ }
+ ValueAxis {
+ id: axis2
+ }
+ LineSeries {
+ id: lowerLine
+ axisAngular: axis1
+ axisRadial: axis2
+
+ // Please note that month in JavaScript months are zero based, so 2 means March
+ XYPoint { x: toMsecsSinceEpoch(new Date(1950, 0, 1)); y: 15 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(1962, 4, 1)); y: 35 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(1970, 0, 1)); y: 50 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(1978, 2, 1)); y: 75 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(1987, 11, 1)); y: 102 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(1992, 1, 1)); y: 132 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(1998, 7, 1)); y: 100 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(2002, 4, 1)); y: 120 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(2012, 8, 1)); y: 140 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(2013, 5, 1)); y: 150 }
+ }
+ LineSeries {
+ id: upperLine
+ axisAngular: axis1
+ axisRadial: axis2
+
+ // Please note that month in JavaScript months are zero based, so 2 means March
+ XYPoint { x: toMsecsSinceEpoch(new Date(1950, 0, 1)); y: 30 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(1962, 4, 1)); y: 55 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(1970, 0, 1)); y: 80 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(1978, 2, 1)); y: 105 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(1987, 11, 1)); y: 125 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(1992, 1, 1)); y: 160 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(1998, 7, 1)); y: 140 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(2002, 4, 1)); y: 140 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(2012, 8, 1)); y: 170 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(2013, 5, 1)); y: 200 }
+ }
+ AreaSeries {
+ axisAngular: axis1
+ axisRadial: axis2
+ lowerSeries: lowerLine
+ upperSeries: upperLine
+ }
+ }
+ // DateTimeAxis is based on QDateTimes so we must convert our JavaScript dates to
+ // milliseconds since epoch to make them match the DateTimeAxis values
+ function toMsecsSinceEpoch(date) {
+ var msecs = date.getTime();
+ return msecs;
+ }
+ //![1]
+}
diff --git a/demos/qmlpolarchart/qml/qmlpolarchart/View3.qml b/demos/qmlpolarchart/qml/qmlpolarchart/View3.qml
new file mode 100644
index 00000000..27c12107
--- /dev/null
+++ b/demos/qmlpolarchart/qml/qmlpolarchart/View3.qml
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 1.0
+import QtCommercial.Chart 1.3
+
+Rectangle {
+ anchors.fill: parent
+
+ //![1]
+ PolarChartView {
+ title: "Numerical Data for Dummies"
+ anchors.fill: parent
+ legend.visible: false
+
+ LineSeries {
+ axisRadial: CategoryAxis {
+ min: 0
+ max: 30
+ CategoryRange {
+ label: "critical"
+ endValue: 2
+ }
+ CategoryRange {
+ label: "low"
+ endValue: 4
+ }
+ CategoryRange {
+ label: "normal"
+ endValue: 7
+ }
+ CategoryRange {
+ label: "high"
+ endValue: 15
+ }
+ CategoryRange {
+ label: "extremely high"
+ endValue: 30
+ }
+ }
+
+ axisAngular: ValueAxis {
+ tickCount: 13
+ }
+
+ XYPoint { x: 0; y: 4.3 }
+ XYPoint { x: 1; y: 4.1 }
+ XYPoint { x: 2; y: 4.7 }
+ XYPoint { x: 3; y: 3.9 }
+ XYPoint { x: 4; y: 5.2 }
+ XYPoint { x: 5; y: 5.3 }
+ XYPoint { x: 6; y: 6.1 }
+ XYPoint { x: 7; y: 7.7 }
+ XYPoint { x: 8; y: 12.9 }
+ XYPoint { x: 9; y: 19.2 }
+ }
+ }
+ //![1]
+}
diff --git a/demos/qmlpolarchart/qml/qmlpolarchart/loader.qml b/demos/qmlpolarchart/qml/qmlpolarchart/loader.qml
new file mode 100644
index 00000000..20627ab3
--- /dev/null
+++ b/demos/qmlpolarchart/qml/qmlpolarchart/loader.qml
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 1.0
+
+Item {
+ id: container
+ width: 400
+ height: 300
+ Component.onCompleted: {
+ var co = Qt.createComponent("main.qml")
+ if (co.status == Component.Ready) {
+ var o = co.createObject(container)
+ } else {
+ console.log(co.errorString())
+ console.log("QtCommercial.Chart 1.3 not available")
+ console.log("Please use correct QML_IMPORT_PATH export")
+ }
+ }
+}
diff --git a/demos/qmlpolarchart/qml/qmlpolarchart/main.qml b/demos/qmlpolarchart/qml/qmlpolarchart/main.qml
new file mode 100644
index 00000000..e6ce6569
--- /dev/null
+++ b/demos/qmlpolarchart/qml/qmlpolarchart/main.qml
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 1.0
+
+Rectangle {
+ width: parent.width
+ height: parent.height
+ property int viewNumber: 1
+ property int viewCount: 3
+
+ Loader {
+ id: loader
+ anchors.fill: parent
+ source: "View" + viewNumber + ".qml";
+ }
+
+ Rectangle {
+ id: infoText
+ anchors.centerIn: parent
+ width: parent.width
+ height: 40
+ color: "black"
+ Text {
+ color: "white"
+ anchors.centerIn: parent
+ text: "Use left and right arrow keys to navigate"
+ }
+
+ Behavior on opacity {
+ NumberAnimation { duration: 400 }
+ }
+ }
+
+ MouseArea {
+ focus: true
+ anchors.fill: parent
+ onClicked: {
+ if (infoText.opacity > 0) {
+ infoText.opacity = 0.0;
+ } else {
+ nextView();
+ }
+ }
+ Keys.onPressed: {
+ if (infoText.opacity > 0) {
+ infoText.opacity = 0.0;
+ } else {
+ if (event.key == Qt.Key_Left) {
+ previousView();
+ } else {
+ nextView();
+ }
+ }
+ }
+ }
+
+ function nextView() {
+ var i = viewNumber + 1;
+ if (i > viewCount)
+ viewNumber = 1;
+ else
+ viewNumber = i;
+ }
+
+ function previousView() {
+ var i = viewNumber - 1;
+ if (i <= 0)
+ viewNumber = viewCount;
+ else
+ viewNumber = i;
+ }
+}
diff --git a/demos/qmlpolarchart/qmlapplicationviewer/qmlapplicationviewer.cpp b/demos/qmlpolarchart/qmlapplicationviewer/qmlapplicationviewer.cpp
new file mode 100644
index 00000000..0f12265e
--- /dev/null
+++ b/demos/qmlpolarchart/qmlapplicationviewer/qmlapplicationviewer.cpp
@@ -0,0 +1,177 @@
+// checksum 0xbd34 version 0x80016
+/*
+ This file was generated by the Qt Quick Application wizard of Qt Creator.
+ QmlApplicationViewer is a convenience class containing mobile device specific
+ code such as screen orientation handling. Also QML paths and debugging are
+ handled here.
+ It is recommended not to modify this file, since newer versions of Qt Creator
+ may offer an updated version of it.
+*/
+
+#include "qmlapplicationviewer.h"
+
+#include <QDir>
+#include <QFileInfo>
+#include <QApplication>
+#include <QDeclarativeComponent>
+#include <QDeclarativeEngine>
+#include <QDeclarativeContext>
+
+#include <qplatformdefs.h> // MEEGO_EDITION_HARMATTAN
+
+#ifdef HARMATTAN_BOOSTER
+#include <MDeclarativeCache>
+#endif
+
+#if defined(QMLJSDEBUGGER) && QT_VERSION < 0x040800
+
+#include <qt_private/qdeclarativedebughelper_p.h>
+
+#if !defined(NO_JSDEBUGGER)
+#include <jsdebuggeragent.h>
+#endif
+#if !defined(NO_QMLOBSERVER)
+#include <qdeclarativeviewobserver.h>
+#endif
+
+// Enable debugging before any QDeclarativeEngine is created
+struct QmlJsDebuggingEnabler
+{
+ QmlJsDebuggingEnabler()
+ {
+ QDeclarativeDebugHelper::enableDebugging();
+ }
+};
+
+// Execute code in constructor before first QDeclarativeEngine is instantiated
+static QmlJsDebuggingEnabler enableDebuggingHelper;
+
+#endif // QMLJSDEBUGGER
+
+class QmlApplicationViewerPrivate
+{
+ QString mainQmlFile;
+ friend class QmlApplicationViewer;
+ static QString adjustPath(const QString &path);
+};
+
+QString QmlApplicationViewerPrivate::adjustPath(const QString &path)
+{
+#ifdef Q_OS_MAC
+ if (!QDir::isAbsolutePath(path))
+ return QString::fromLatin1("%1/../Resources/%2")
+ .arg(QCoreApplication::applicationDirPath(), path);
+#elif defined(Q_OS_QNX)
+ if (!QDir::isAbsolutePath(path))
+ return QString::fromLatin1("app/native/%1").arg(path);
+#elif !defined(Q_OS_ANDROID)
+ QString pathInInstallDir =
+ QString::fromLatin1("%1/../%2").arg(QCoreApplication::applicationDirPath(), path);
+ if (QFileInfo(pathInInstallDir).exists())
+ return pathInInstallDir;
+ pathInInstallDir =
+ QString::fromLatin1("%1/%2").arg(QCoreApplication::applicationDirPath(), path);
+ if (QFileInfo(pathInInstallDir).exists())
+ return pathInInstallDir;
+#endif
+ return path;
+}
+
+QmlApplicationViewer::QmlApplicationViewer(QWidget *parent)
+ : QDeclarativeView(parent)
+ , d(new QmlApplicationViewerPrivate())
+{
+ connect(engine(), SIGNAL(quit()), SLOT(close()));
+ setResizeMode(QDeclarativeView::SizeRootObjectToView);
+
+ // Qt versions prior to 4.8.0 don't have QML/JS debugging services built in
+#if defined(QMLJSDEBUGGER) && QT_VERSION < 0x040800
+#if !defined(NO_JSDEBUGGER)
+ new QmlJSDebugger::JSDebuggerAgent(engine());
+#endif
+#if !defined(NO_QMLOBSERVER)
+ new QmlJSDebugger::QDeclarativeViewObserver(this, this);
+#endif
+#endif
+}
+
+QmlApplicationViewer::~QmlApplicationViewer()
+{
+ delete d;
+}
+
+QmlApplicationViewer *QmlApplicationViewer::create()
+{
+ return new QmlApplicationViewer();
+}
+
+void QmlApplicationViewer::setMainQmlFile(const QString &file)
+{
+ d->mainQmlFile = QmlApplicationViewerPrivate::adjustPath(file);
+#ifdef Q_OS_ANDROID
+ setSource(QUrl(QLatin1String("assets:/")+d->mainQmlFile));
+#else
+ setSource(QUrl::fromLocalFile(d->mainQmlFile));
+#endif
+}
+
+void QmlApplicationViewer::addImportPath(const QString &path)
+{
+ engine()->addImportPath(QmlApplicationViewerPrivate::adjustPath(path));
+}
+
+void QmlApplicationViewer::setOrientation(ScreenOrientation orientation)
+{
+#if QT_VERSION < 0x050000
+ Qt::WidgetAttribute attribute;
+ switch (orientation) {
+#if QT_VERSION < 0x040702
+ // Qt < 4.7.2 does not yet have the Qt::WA_*Orientation attributes
+ case ScreenOrientationLockPortrait:
+ attribute = static_cast<Qt::WidgetAttribute>(128);
+ break;
+ case ScreenOrientationLockLandscape:
+ attribute = static_cast<Qt::WidgetAttribute>(129);
+ break;
+ default:
+ case ScreenOrientationAuto:
+ attribute = static_cast<Qt::WidgetAttribute>(130);
+ break;
+#else // QT_VERSION < 0x040702
+ case ScreenOrientationLockPortrait:
+ attribute = Qt::WA_LockPortraitOrientation;
+ break;
+ case ScreenOrientationLockLandscape:
+ attribute = Qt::WA_LockLandscapeOrientation;
+ break;
+ default:
+ case ScreenOrientationAuto:
+ attribute = Qt::WA_AutoOrientation;
+ break;
+#endif // QT_VERSION < 0x040702
+ };
+ setAttribute(attribute, true);
+#else // QT_VERSION < 0x050000
+ Q_UNUSED(orientation)
+#endif // QT_VERSION < 0x050000
+}
+
+void QmlApplicationViewer::showExpanded()
+{
+#if defined(MEEGO_EDITION_HARMATTAN) || defined(Q_WS_SIMULATOR)
+ showFullScreen();
+#elif defined(Q_WS_MAEMO_5) || defined(Q_OS_QNX)
+ showMaximized();
+#else
+ show();
+#endif
+}
+
+QApplication *createApplication(int &argc, char **argv)
+{
+#ifdef HARMATTAN_BOOSTER
+ return MDeclarativeCache::qApplication(argc, argv);
+#else
+ return new QApplication(argc, argv);
+#endif
+}
diff --git a/demos/qmlpolarchart/qmlapplicationviewer/qmlapplicationviewer.h b/demos/qmlpolarchart/qmlapplicationviewer/qmlapplicationviewer.h
new file mode 100644
index 00000000..fba2d52a
--- /dev/null
+++ b/demos/qmlpolarchart/qmlapplicationviewer/qmlapplicationviewer.h
@@ -0,0 +1,46 @@
+// checksum 0xc67a version 0x80016
+/*
+ This file was generated by the Qt Quick Application wizard of Qt Creator.
+ QmlApplicationViewer is a convenience class containing mobile device specific
+ code such as screen orientation handling. Also QML paths and debugging are
+ handled here.
+ It is recommended not to modify this file, since newer versions of Qt Creator
+ may offer an updated version of it.
+*/
+
+#ifndef QMLAPPLICATIONVIEWER_H
+#define QMLAPPLICATIONVIEWER_H
+
+#include <QDeclarativeView>
+
+class QmlApplicationViewer : public QDeclarativeView
+{
+ Q_OBJECT
+
+public:
+ enum ScreenOrientation {
+ ScreenOrientationLockPortrait,
+ ScreenOrientationLockLandscape,
+ ScreenOrientationAuto
+ };
+
+ explicit QmlApplicationViewer(QWidget *parent = 0);
+ virtual ~QmlApplicationViewer();
+
+ static QmlApplicationViewer *create();
+
+ void setMainQmlFile(const QString &file);
+ void addImportPath(const QString &path);
+
+ // Note that this will only have an effect on Fremantle.
+ void setOrientation(ScreenOrientation orientation);
+
+ void showExpanded();
+
+private:
+ class QmlApplicationViewerPrivate *d;
+};
+
+QApplication *createApplication(int &argc, char **argv);
+
+#endif // QMLAPPLICATIONVIEWER_H
diff --git a/demos/qmlpolarchart/qmlapplicationviewer/qmlapplicationviewer.pri b/demos/qmlpolarchart/qmlapplicationviewer/qmlapplicationviewer.pri
new file mode 100644
index 00000000..567c6dc6
--- /dev/null
+++ b/demos/qmlpolarchart/qmlapplicationviewer/qmlapplicationviewer.pri
@@ -0,0 +1,13 @@
+QT += declarative
+
+SOURCES += $$PWD/qmlapplicationviewer.cpp
+HEADERS += $$PWD/qmlapplicationviewer.h
+INCLUDEPATH += $$PWD
+
+# Include JS debugger library if QMLJSDEBUGGER_PATH is set
+!isEmpty(QMLJSDEBUGGER_PATH) {
+ include($$QMLJSDEBUGGER_PATH/qmljsdebugger-lib.pri)
+} else {
+ DEFINES -= QMLJSDEBUGGER
+}
+
diff --git a/demos/qmlpolarchart/qmlpolarchart.pro b/demos/qmlpolarchart/qmlpolarchart.pro
new file mode 100644
index 00000000..f661312b
--- /dev/null
+++ b/demos/qmlpolarchart/qmlpolarchart.pro
@@ -0,0 +1,9 @@
+!include( ../demos.pri ) {
+ error( "Couldn't find the demos.pri file!" )
+}
+
+RESOURCES += resources.qrc
+SOURCES += main.cpp
+OTHER_FILES += qml/qmlpolarchart/*
+
+include(qmlapplicationviewer/qmlapplicationviewer.pri)
diff --git a/demos/qmlpolarchart/resources.qrc b/demos/qmlpolarchart/resources.qrc
new file mode 100644
index 00000000..854acbef
--- /dev/null
+++ b/demos/qmlpolarchart/resources.qrc
@@ -0,0 +1,9 @@
+<RCC>
+ <qresource prefix="/">
+ <file>qml/qmlpolarchart/loader.qml</file>
+ <file>qml/qmlpolarchart/main.qml</file>
+ <file>qml/qmlpolarchart/View1.qml</file>
+ <file>qml/qmlpolarchart/View2.qml</file>
+ <file>qml/qmlpolarchart/View3.qml</file>
+ </qresource>
+</RCC>
diff --git a/doc/images/demos_qmlpolarchart1.png b/doc/images/demos_qmlpolarchart1.png
new file mode 100644
index 00000000..58be80e6
--- /dev/null
+++ b/doc/images/demos_qmlpolarchart1.png
Binary files differ
diff --git a/doc/images/demos_qmlpolarchart2.png b/doc/images/demos_qmlpolarchart2.png
new file mode 100644
index 00000000..35c3521a
--- /dev/null
+++ b/doc/images/demos_qmlpolarchart2.png
Binary files differ
diff --git a/doc/images/demos_qmlpolarchart3.png b/doc/images/demos_qmlpolarchart3.png
new file mode 100644
index 00000000..31a68dc6
--- /dev/null
+++ b/doc/images/demos_qmlpolarchart3.png
Binary files differ
diff --git a/doc/images/examples_polarchart.png b/doc/images/examples_polarchart.png
new file mode 100644
index 00000000..f5ea517a
--- /dev/null
+++ b/doc/images/examples_polarchart.png
Binary files differ
diff --git a/doc/src/classes.qdoc b/doc/src/classes.qdoc
index 89f4d070..07be9dd8 100644
--- a/doc/src/classes.qdoc
+++ b/doc/src/classes.qdoc
@@ -30,6 +30,7 @@
<td valign="top">
<ul>
<li><a href="qchart.html">QChart</a></li>
+ <li><a href="qpolarchart.html">QPolarChart</a></li>
<li><a href="qchartview.html">QChartView</a></li>
<li><a href="qabstractaxis.html">QAbstractAxis</a></li>
<li><a href="qvalueaxis.html">QValueAxis</a></li>
diff --git a/doc/src/demos-qmlpolarchart.qdoc b/doc/src/demos-qmlpolarchart.qdoc
new file mode 100644
index 00000000..04c7037e
--- /dev/null
+++ b/doc/src/demos-qmlpolarchart.qdoc
@@ -0,0 +1,33 @@
+/*!
+ \example demos/qmlpolarchart
+ \title Qml Polar Chart
+ \subtitle
+
+ This is a demonstration of how to use polar chart in your QML application.
+
+ \table
+ \row
+ \o \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 ../demos/qmlpolarchart/qml/qmlpolarchart/View1.qml 1
+ \o \inlineimage demos_qmlpolarchart1.png
+ \row
+ \o \br
+ The next example shows a chart with some accurate historical data that makes us to use a DateTimeAxis
+ and AreaSeries.
+ \br
+ \br
+ \snippet ../demos/qmlpolarchart/qml/qmlpolarchart/View2.qml 1
+ \o \inlineimage demos_qmlpolarchart2.png
+ \row
+ \o \br
+ And the final example with a chart that uses a CategoryAxis to make the data easier to understand.
+ \br
+ \br
+ \snippet ../demos/qmlpolarchart/qml/qmlpolarchart/View3.qml 1
+ \o \inlineimage demos_qmlpolarchart3.png
+ \endtable
+*/
diff --git a/doc/src/demos.qdoc b/doc/src/demos.qdoc
index 573b416a..6316617a 100644
--- a/doc/src/demos.qdoc
+++ b/doc/src/demos.qdoc
@@ -8,6 +8,14 @@
<table>
<tr>
+ <td><a href="demos-audio.html">Audio</a></td>
+ <td><a href="demos-callout.html">Callout</a></td>
+ </tr>
+ <tr>
+ <td><a href="demos-audio.html"><img src="images/demos_audio.png" width="300" alt="Audio" /></a></td>
+ <td><a href="demos-callout.html"><img src="images/demos_callout.png" width="300" alt="Callout" /></a></td>
+ </tr>
+ <tr>
<td><a href="demos-chartthemes.html">Chart Themes</a></td>
<td><a href="demos-dynamicspline.html">Dynamic Spline Chart</a></td>
</tr>
@@ -15,7 +23,6 @@
<td><a href="demos-chartthemes.html"><img src="images/demo_chartthemes_blue_cerulean.png" width="300" alt="Chart Themes" /></a></td>
<td><a href="demos-dynamicspline.html"><img src="images/demos_dynamicspline2.png" width="300" alt="Dynamic Spline" /></a></td>
</tr>
-
<tr>
<td><a href="demos-nesteddonuts.html">Nested Donuts Chart</a></td>
<td><a href="demos-piechartcustomization.html">Pie Chart Customization</a></td>
@@ -24,7 +31,6 @@
<td><a href="demos-nesteddonuts.html"><img src="images/demos_nesteddonuts.png" width="300" alt="Nested Donuts Chart" /></a></td>
<td><a href="demos-piechartcustomization.html"><img src="images/piechart_customization.png" width="300" alt="Pie Chart Customization" /></a></td>
</tr>
-
<tr>
<td><a href="demos-qmlchart.html">Qml Basic Charts</a></td>
<td><a href="demos-qmlaxes.html">Qml Axes</a></td>
@@ -33,7 +39,6 @@
<td><a href="demos-qmlchart.html"><img src="images/demos_qmlchart1.png" width="300" alt="Qml Basic Charts" /></a></td>
<td><a href="demos-qmlaxes.html"><img src="images/demos_qmlaxes1.png" width="300" alt="Qml Axes" /></a></td>
</tr>
-
<tr>
<td><a href="demos-qmlcustomizations.html">Qml Customizations</a></td>
<td><a href="demos-qmlcustommodel.html">Qml Custom Model</a></td>
@@ -42,7 +47,6 @@
<td><a href="demos-qmlcustomizations.html"><img src="images/demos_qmlcustomizations.png" width="300" alt="Qml Customizations" /></a></td>
<td><a href="demos-qmlcustommodel.html"><img src="images/demos_qmlcustommodel.png" width="300" alt="Qml Custom Model" /></a></td>
</tr>
-
<tr>
<td><a href="demos-qmlf1legends.html">Qml F1 Legends</a></td>
<td><a href="demos-qmloscilloscope.html">Qml Oscilloscope</a></td>
@@ -51,7 +55,6 @@
<td><a href="demos-qmlf1legends.html"><img src="images/demos_qmlf1legends.png" width="300" alt="Qml F1 Legends" /></a></td>
<td><a href="demos-qmloscilloscope.html"><img src="images/demos_qmloscilloscope.png" width="300" alt="Qml Oscilloscope" /></a></td>
</tr>
-
<tr>
<td><a href="demos-qmlweather.html">Qml Weather</a></td>
<td><a href="demos-qmlcustomlegend.html">Qml Custom Legend</a></td>
@@ -61,14 +64,11 @@
<td><a href="demos-qmlcustomlegend.html"><img src="images/demos-qmlcustomlegend1.png" width="300" alt="Qml Custom Legend" /></a></td>
</tr>
<tr>
- <td><a href="demos-callout.html">Callout</a></td>
- <td><a href="demos-audio.html">Audio</a></td>
+ <td><a href="demos-qmlpolarchart.html">Qml Polar Chart</a></td>
</tr>
<tr>
- <td><a href="demos-callout.html"><img src="images/demos_callout.png" width="300" alt="Callout" /></a></td>
- <td><a href="demos-audio.html"><img src="images/demos_audio.png" width="300" alt="Audio" /></a></td>
+ <td><a href="demos-qmlpolarchart.html"><img src="images/demos_qmlpolarchart1.png" width="300" alt="Qml Polar Chart" /></a></td>
</tr>
-
</table>
</div>
\endraw
diff --git a/doc/src/examples-polarchart.qdoc b/doc/src/examples-polarchart.qdoc
new file mode 100644
index 00000000..d9f976d6
--- /dev/null
+++ b/doc/src/examples-polarchart.qdoc
@@ -0,0 +1,33 @@
+/*!
+ \example examples/polarchart
+ \title Polar chart example
+ \subtitle
+
+ The example shows how to create 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 chart and cartesian chart relate to each other.
+
+ \image examples_polarchart.png
+
+ Creating polar chart is done via QPolarChart instance instead of QChart.
+
+ \snippet ../examples/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 ../examples/polarchart/main.cpp 2
+
+ Zooming and scrolling of the polar chart is logically nearly identical to zooming and scrolling of cartesian chart.
+ The main difference is that when scrolling along X-axis (angular axis), angle is used instead of number of pixels.
+ Another difference is that zooming to a rectangle cannot be done.
+
+ \snippet ../examples/polarchart/chartview.cpp 1
+
+ Same axes and series can be used in both cartesian and polar charts, though not simultaneously.
+ To switch between chart types, you need to first remove series and axes from the old chart and then add
+ them to the new chart. If you want to preserve axis ranges, those need to be copied, too.
+
+ \snippet ../examples/polarchart/chartview.cpp 2
+
+*/
diff --git a/doc/src/examples.qdoc b/doc/src/examples.qdoc
index f0588bec..f5c736eb 100644
--- a/doc/src/examples.qdoc
+++ b/doc/src/examples.qdoc
@@ -98,36 +98,38 @@
</tr>
<tr>
+ <td><a href="examples-polarchart.html">Polar chart</a></td>
<td><a href="examples-scatterchart.html">Scatter chart</a></td>
- <td><a href="examples-scatterinteractions.html">Scatter Interactions</a></td>
</tr>
<tr>
+ <td><a href="examples-polarchart.html"><img src="images/examples_polarchart.png" width="300" alt="Polar chart" /></a></td>
<td><a href="examples-scatterchart.html"><img src="images/examples_scatterchart.png" width="300" alt="Scatter chart" /></a></td>
- <td><a href="examples-scatterinteractions.html"><img src="images/examples_scatterinteractions.png" width="300" alt="Scatter Interactions" /></a></td>
</tr>
<tr>
+ <td><a href="examples-scatterinteractions.html">Scatter Interactions</a></td>
<td><a href="examples-splinechart.html">Spline Chart</a></td>
- <td><a href="examples-stackedbarchart.html">Stacked Bar Chart</a></td>
</tr>
<tr>
+ <td><a href="examples-scatterinteractions.html"><img src="images/examples_scatterinteractions.png" width="300" alt="Scatter Interactions" /></a></td>
<td><a href="examples-splinechart.html"><img src="images/examples_splinechart.png" width="300" alt="Spline Chart" /></a></td>
- <td><a href="examples-stackedbarchart.html"><img src="images/examples_stackedbarchart.png" width="300" alt="Stacked Bar Chart" /></a></td>
</tr>
<tr>
+ <td><a href="examples-stackedbarchart.html">Stacked Bar Chart</a></td>
<td><a href="examples-stackedbarchartdrilldown.html">Stacked Bar Chart Drilldown</a></td>
- <td><a href="examples-temperaturerecords.html">Temperature Records</a></td>
</tr>
<tr>
+ <td><a href="examples-stackedbarchart.html"><img src="images/examples_stackedbarchart.png" width="300" alt="Stacked Bar Chart" /></a></td>
<td><a href="examples-stackedbarchartdrilldown.html"><img src="images/examples_stackedbarchartdrilldown1.png" width="300" alt="Stacked Bar Chart Drilldown" /></a></td>
- <td><a href="examples-temperaturerecords.html"><img src="images/examples_temperaturerecords.png" width="300" alt="Temperature Records" /></a></td>
</tr>
<tr>
+ <td><a href="examples-temperaturerecords.html">Temperature Records</a></td>
<td><a href="examples-zoomlinechart.html">Zoom Line</a></td>
</tr>
<tr>
+ <td><a href="examples-temperaturerecords.html"><img src="images/examples_temperaturerecords.png" width="300" alt="Temperature Records" /></a></td>
<td><a href="examples-zoomlinechart.html"><img src="images/examples_zoomlinechart1.png" width="300" alt="Zoom Line" /></a></td>
</tr>
diff --git a/doc/src/qml.qdoc b/doc/src/qml.qdoc
index 9fbb9fee..d7fae7e6 100644
--- a/doc/src/qml.qdoc
+++ b/doc/src/qml.qdoc
@@ -27,6 +27,7 @@
<td valign="top">
<ul>
<li><a href="qml-chartview.html">ChartView</a></li>
+ <li><a href="qml-polarchartview.html">PolarChartView</a></li>
<li><a href="qml-abstractaxis.html">AbstractAxis</a></li>
<li><a href="qml-valueaxis.html">ValueAxis</a></li>
<li><a href="qml-categoryaxis.html">CategoryAxis</a></li>
diff --git a/examples/donutbreakdown/donutbreakdownchart.cpp b/examples/donutbreakdown/donutbreakdownchart.cpp
index 6509e464..37130f01 100644
--- a/examples/donutbreakdown/donutbreakdownchart.cpp
+++ b/examples/donutbreakdown/donutbreakdownchart.cpp
@@ -26,7 +26,7 @@ QTCOMMERCIALCHART_USE_NAMESPACE
//![1]
DonutBreakdownChart::DonutBreakdownChart(QGraphicsItem *parent, Qt::WindowFlags wFlags)
- : QChart(parent, wFlags)
+ : QChart(QChart::ChartTypeCartesian, parent, wFlags)
{
// create the series for main center pie
m_mainSeries = new QPieSeries();
diff --git a/examples/examples.pro b/examples/examples.pro
index ab406af3..716dce54 100644
--- a/examples/examples.pro
+++ b/examples/examples.pro
@@ -31,7 +31,8 @@ SUBDIRS += \
donutchart \
multiaxis \
legendmarkers \
- logvalueaxis
+ logvalueaxis \
+ polarchart
!linux-arm*: {
SUBDIRS += \
diff --git a/examples/piechartdrilldown/drilldownchart.cpp b/examples/piechartdrilldown/drilldownchart.cpp
index 96de458c..47d83ade 100644
--- a/examples/piechartdrilldown/drilldownchart.cpp
+++ b/examples/piechartdrilldown/drilldownchart.cpp
@@ -23,7 +23,7 @@
QTCOMMERCIALCHART_USE_NAMESPACE
DrilldownChart::DrilldownChart(QGraphicsItem *parent, Qt::WindowFlags wFlags)
- : QChart(parent, wFlags),
+ : QChart(QChart::ChartTypeCartesian, parent, wFlags),
m_currentSeries(0)
{
diff --git a/examples/polarchart/chartview.cpp b/examples/polarchart/chartview.cpp
new file mode 100644
index 00000000..fc53a536
--- /dev/null
+++ b/examples/polarchart/chartview.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 "chartview.h"
+#include <QMouseEvent>
+#include <QDebug>
+#include <QAbstractAxis>
+#include <QValueAxis>
+
+QTCOMMERCIALCHART_USE_NAMESPACE
+
+ChartView::ChartView(QWidget *parent)
+ : QChartView(parent)
+{
+}
+
+//![1]
+void ChartView::keyPressEvent(QKeyEvent *event)
+{
+ switch (event->key()) {
+ case Qt::Key_Plus:
+ chart()->zoomIn();
+ break;
+ case Qt::Key_Minus:
+ chart()->zoomOut();
+ break;
+ case Qt::Key_Left:
+ chart()->scroll(-1.0, 0);
+ break;
+ case Qt::Key_Right:
+ chart()->scroll(1.0, 0);
+ break;
+ case Qt::Key_Up:
+ chart()->scroll(0, 1.0);
+ break;
+ case Qt::Key_Down:
+ chart()->scroll(0, -1.0);
+ break;
+ case Qt::Key_Space:
+ switchChartType();
+ break;
+ default:
+ QGraphicsView::keyPressEvent(event);
+ break;
+ }
+}
+//![1]
+
+//![2]
+void ChartView::switchChartType()
+{
+ QChart *newChart;
+ QChart *oldChart = chart();
+
+ if (oldChart->chartType() == QChart::ChartTypeCartesian)
+ newChart = new QPolarChart();
+ else
+ newChart = new QChart();
+
+ // Move series and axes from old chart to new one
+ QList<QAbstractSeries *> seriesList = oldChart->series();
+ QList<QAbstractAxis *> axisList = oldChart->axes();
+ QList<QPair<qreal, qreal>> axisRanges;
+
+ foreach (QAbstractAxis *axis, axisList) {
+ QValueAxis *valueAxis = static_cast<QValueAxis *>(axis);
+ axisRanges.append(QPair<qreal, qreal>(valueAxis->min(), valueAxis->max()));
+ }
+
+ foreach (QAbstractSeries *series, seriesList)
+ oldChart->removeSeries(series);
+
+ foreach (QAbstractAxis *axis, axisList) {
+ oldChart->removeAxis(axis);
+ newChart->addAxis(axis, axis->alignment());
+ }
+
+ foreach (QAbstractSeries *series, seriesList) {
+ newChart->addSeries(series);
+ foreach (QAbstractAxis *axis, axisList)
+ series->attachAxis(axis);
+ }
+
+ int count = 0;
+ foreach (QAbstractAxis *axis, axisList) {
+ axis->setRange(axisRanges[count].first, axisRanges[count].second);
+ count++;
+ }
+
+ newChart->setTitle(oldChart->title());
+ setChart(newChart);
+ delete oldChart;
+}
+//![2]
diff --git a/examples/polarchart/chartview.h b/examples/polarchart/chartview.h
new file mode 100644
index 00000000..c4584ac8
--- /dev/null
+++ b/examples/polarchart/chartview.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 CHARTVIEW_H
+#define CHARTVIEW_H
+
+#include <QChartView>
+#include <QPolarChart>
+
+QTCOMMERCIALCHART_USE_NAMESPACE
+
+class ChartView : public QChartView
+{
+public:
+ ChartView(QWidget *parent = 0);
+
+protected:
+ void keyPressEvent(QKeyEvent *event);
+
+private:
+ void switchChartType();
+};
+
+#endif
diff --git a/examples/polarchart/main.cpp b/examples/polarchart/main.cpp
new file mode 100644
index 00000000..7b3b38d8
--- /dev/null
+++ b/examples/polarchart/main.cpp
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 "chartview.h"
+#include <QApplication>
+#include <QMainWindow>
+#include <QScatterSeries>
+#include <QLineSeries>
+#include <QSplineSeries>
+#include <QAreaSeries>
+#include <QValueAxis>
+#include <QPolarChart>
+#include <QDebug>
+
+QTCOMMERCIALCHART_USE_NAMESPACE
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+
+ const qreal angularMin = -100;
+ const qreal angularMax = 100;
+
+ const qreal radialMin = -100;
+ const qreal radialMax = 100;
+
+ QScatterSeries *series1 = new QScatterSeries();
+ series1->setName("scatter");
+ for (int i = angularMin; i <= angularMax; i += 10)
+ series1->append(i, (i / radialMax) * radialMax + 8.0);
+
+ QSplineSeries *series2 = new QSplineSeries();
+ series2->setName("spline");
+ for (int i = angularMin; i <= angularMax; i += 10)
+ series2->append(i, (i / radialMax) * radialMax);
+
+ QLineSeries *series3 = new QLineSeries();
+ series3->setName("star outer");
+ qreal ad = (angularMax - angularMin) / 8;
+ qreal rd = (radialMax - radialMin) / 3 * 1.3;
+ series3->append(angularMin, radialMax);
+ series3->append(angularMin + ad*1, radialMin + rd);
+ series3->append(angularMin + ad*2, radialMax);
+ series3->append(angularMin + ad*3, radialMin + rd);
+ series3->append(angularMin + ad*4, radialMax);
+ series3->append(angularMin + ad*5, radialMin + rd);
+ series3->append(angularMin + ad*6, radialMax);
+ series3->append(angularMin + ad*7, radialMin + rd);
+ series3->append(angularMin + ad*8, radialMax);
+
+ QLineSeries *series4 = new QLineSeries();
+ series4->setName("star inner");
+ ad = (angularMax - angularMin) / 8;
+ rd = (radialMax - radialMin) / 3;
+ series4->append(angularMin, radialMax);
+ series4->append(angularMin + ad*1, radialMin + rd);
+ series4->append(angularMin + ad*2, radialMax);
+ series4->append(angularMin + ad*3, radialMin + rd);
+ series4->append(angularMin + ad*4, radialMax);
+ series4->append(angularMin + ad*5, radialMin + rd);
+ series4->append(angularMin + ad*6, radialMax);
+ series4->append(angularMin + ad*7, radialMin + rd);
+ series4->append(angularMin + ad*8, radialMax);
+
+ QAreaSeries *series5 = new QAreaSeries();
+ series5->setName("star area");
+ series5->setUpperSeries(series3);
+ series5->setLowerSeries(series4);
+ series5->setOpacity(0.5);
+
+ //![1]
+ QPolarChart *chart = new QPolarChart();
+ //![1]
+ chart->addSeries(series1);
+ chart->addSeries(series2);
+ chart->addSeries(series3);
+ chart->addSeries(series4);
+ chart->addSeries(series5);
+
+ chart->setTitle("Use arrow keys to scroll, +/- to zoom, and space to switch chart type.");
+
+ //![2]
+ QValueAxis *angularAxis = new QValueAxis();
+ angularAxis->setTickCount(9); // First and last ticks are co-located on 0/360 angle.
+ angularAxis->setLabelFormat("%.1f");
+ angularAxis->setShadesVisible(true);
+ angularAxis->setShadesBrush(QBrush(QColor(249, 249, 255)));
+ chart->addAxis(angularAxis, QPolarChart::PolarOrientationAngular);
+
+ QValueAxis *radialAxis = new QValueAxis();
+ radialAxis->setTickCount(9);
+ radialAxis->setLabelFormat("%d");
+ chart->addAxis(radialAxis, QPolarChart::PolarOrientationRadial);
+ //![2]
+
+ series1->attachAxis(radialAxis);
+ series1->attachAxis(angularAxis);
+ series2->attachAxis(radialAxis);
+ series2->attachAxis(angularAxis);
+ series3->attachAxis(radialAxis);
+ series3->attachAxis(angularAxis);
+ series4->attachAxis(radialAxis);
+ series4->attachAxis(angularAxis);
+ series5->attachAxis(radialAxis);
+ series5->attachAxis(angularAxis);
+
+ radialAxis->setRange(radialMin, radialMax);
+ angularAxis->setRange(angularMin, angularMax);
+
+ ChartView *chartView = new ChartView();
+ chartView->setChart(chart);
+ chartView->setRenderHint(QPainter::Antialiasing);
+
+ QMainWindow window;
+ window.setCentralWidget(chartView);
+ window.resize(800, 600);
+ window.show();
+
+ return a.exec();
+}
diff --git a/examples/polarchart/polarchart.pro b/examples/polarchart/polarchart.pro
new file mode 100644
index 00000000..8759c1ce
--- /dev/null
+++ b/examples/polarchart/polarchart.pro
@@ -0,0 +1,6 @@
+!include( ../examples.pri ) {
+ error( "Couldn't find the examples.pri file!" )
+}
+TARGET = polarchart
+SOURCES += main.cpp chartview.cpp
+HEADERS += chartview.h
diff --git a/examples/stackedbarchartdrilldown/drilldownchart.cpp b/examples/stackedbarchartdrilldown/drilldownchart.cpp
index 51c9147a..b2f5120d 100644
--- a/examples/stackedbarchartdrilldown/drilldownchart.cpp
+++ b/examples/stackedbarchartdrilldown/drilldownchart.cpp
@@ -24,7 +24,7 @@
QTCOMMERCIALCHART_USE_NAMESPACE
DrilldownChart::DrilldownChart(QGraphicsItem *parent, Qt::WindowFlags wFlags)
- : QChart(parent, wFlags),
+ : QChart(QChart::ChartTypeCartesian, parent, wFlags),
m_currentSeries(0)
{
}
diff --git a/examples/zoomlinechart/chart.cpp b/examples/zoomlinechart/chart.cpp
index aa109f2c..40834346 100644
--- a/examples/zoomlinechart/chart.cpp
+++ b/examples/zoomlinechart/chart.cpp
@@ -24,7 +24,7 @@
#include <QGraphicsView>
Chart::Chart(QGraphicsItem *parent, Qt::WindowFlags wFlags)
- : QChart(parent, wFlags)
+ : QChart(QChart::ChartTypeCartesian, parent, wFlags)
{
// Seems that QGraphicsView (QChartView) does not grab gestures.
// They can only be grabbed here in the QGraphicsWidget (QChart).
diff --git a/plugins/declarative/declarative.pro b/plugins/declarative/declarative.pro
index 7641b2b5..12d48832 100644
--- a/plugins/declarative/declarative.pro
+++ b/plugins/declarative/declarative.pro
@@ -25,7 +25,8 @@ SOURCES += \
declarativebarseries.cpp \
declarativecategoryaxis.cpp \
declarativemargins.cpp \
- declarativeaxes.cpp
+ declarativeaxes.cpp \
+ declarativepolarchart.cpp
HEADERS += \
declarativechart.h \
@@ -39,7 +40,8 @@ HEADERS += \
declarativebarseries.h \
declarativecategoryaxis.h \
declarativemargins.h \
- declarativeaxes.h
+ declarativeaxes.h \
+ declarativepolarchart.h
TARGETPATH = QtCommercial/Chart
target.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH
diff --git a/plugins/declarative/declarativeareaseries.cpp b/plugins/declarative/declarativeareaseries.cpp
index cda4db60..fabbc612 100644
--- a/plugins/declarative/declarativeareaseries.cpp
+++ b/plugins/declarative/declarativeareaseries.cpp
@@ -31,6 +31,8 @@ DeclarativeAreaSeries::DeclarativeAreaSeries(QObject *parent) :
connect(m_axes, SIGNAL(axisYChanged(QAbstractAxis*)), this, SIGNAL(axisYChanged(QAbstractAxis*)));
connect(m_axes, SIGNAL(axisXTopChanged(QAbstractAxis*)), this, SIGNAL(axisXTopChanged(QAbstractAxis*)));
connect(m_axes, SIGNAL(axisYRightChanged(QAbstractAxis*)), this, SIGNAL(axisYRightChanged(QAbstractAxis*)));
+ connect(m_axes, SIGNAL(axisXChanged(QAbstractAxis*)), this, SIGNAL(axisAngularChanged(QAbstractAxis*)));
+ connect(m_axes, SIGNAL(axisYChanged(QAbstractAxis*)), this, SIGNAL(axisRadialChanged(QAbstractAxis*)));
}
void DeclarativeAreaSeries::setUpperSeries(DeclarativeLineSeries *series)
diff --git a/plugins/declarative/declarativeareaseries.h b/plugins/declarative/declarativeareaseries.h
index 3b3fc118..7c1c0abe 100644
--- a/plugins/declarative/declarativeareaseries.h
+++ b/plugins/declarative/declarativeareaseries.h
@@ -36,6 +36,8 @@ class DeclarativeAreaSeries : public QAreaSeries
Q_PROPERTY(QAbstractAxis *axisY READ axisY WRITE setAxisY NOTIFY axisYChanged REVISION 1)
Q_PROPERTY(QAbstractAxis *axisXTop READ axisXTop WRITE setAxisXTop NOTIFY axisXTopChanged REVISION 2)
Q_PROPERTY(QAbstractAxis *axisYRight READ axisYRight WRITE setAxisYRight NOTIFY axisYRightChanged REVISION 2)
+ Q_PROPERTY(QAbstractAxis *axisAngular READ axisAngular WRITE setAxisAngular NOTIFY axisAngularChanged REVISION 3)
+ Q_PROPERTY(QAbstractAxis *axisRadial READ axisRadial WRITE setAxisRadial NOTIFY axisRadialChanged REVISION 3)
Q_PROPERTY(qreal borderWidth READ borderWidth WRITE setBorderWidth NOTIFY borderWidthChanged REVISION 1)
public:
@@ -52,6 +54,10 @@ public:
Q_REVISION(2) void setAxisXTop(QAbstractAxis *axis) { m_axes->setAxisXTop(axis); }
Q_REVISION(2) QAbstractAxis *axisYRight() { return m_axes->axisYRight(); }
Q_REVISION(2) void setAxisYRight(QAbstractAxis *axis) { m_axes->setAxisYRight(axis); }
+ Q_REVISION(3) QAbstractAxis *axisAngular() { return m_axes->axisX(); }
+ Q_REVISION(3) void setAxisAngular(QAbstractAxis *axis) { m_axes->setAxisX(axis); }
+ Q_REVISION(3) QAbstractAxis *axisRadial() { return m_axes->axisY(); }
+ Q_REVISION(3) void setAxisRadial(QAbstractAxis *axis) { m_axes->setAxisY(axis); }
qreal borderWidth() const;
void setBorderWidth(qreal borderWidth);
@@ -61,6 +67,8 @@ Q_SIGNALS:
Q_REVISION(1) void borderWidthChanged(qreal width);
Q_REVISION(2) void axisXTopChanged(QAbstractAxis *axis);
Q_REVISION(2) void axisYRightChanged(QAbstractAxis *axis);
+ Q_REVISION(3) void axisAngularChanged(QAbstractAxis *axis);
+ Q_REVISION(3) void axisRadialChanged(QAbstractAxis *axis);
public:
DeclarativeAxes *m_axes;
diff --git a/plugins/declarative/declarativechart.cpp b/plugins/declarative/declarativechart.cpp
index 7e5500b8..344f5e62 100644
--- a/plugins/declarative/declarativechart.cpp
+++ b/plugins/declarative/declarativechart.cpp
@@ -35,6 +35,7 @@
#include "chartdataset_p.h"
#include "declarativeaxes.h"
#include "qchart_p.h"
+#include "qpolarchart.h"
#ifndef QT_ON_ARM
#include "qdatetimeaxis.h"
@@ -235,9 +236,24 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE
*/
DeclarativeChart::DeclarativeChart(QDeclarativeItem *parent)
- : QDeclarativeItem(parent),
- m_chart(new QChart(this))
+ : QDeclarativeItem(parent)
{
+ initChart(QChart::ChartTypeCartesian);
+}
+
+DeclarativeChart::DeclarativeChart(QChart::ChartType type, QDeclarativeItem *parent)
+ : QDeclarativeItem(parent)
+{
+ initChart(type);
+}
+
+void DeclarativeChart::initChart(QChart::ChartType type)
+{
+ if (type == QChart::ChartTypePolar)
+ m_chart = new QPolarChart(this);
+ else
+ m_chart = new QChart(this);
+
setFlag(QGraphicsItem::ItemHasNoContents, false);
m_margins = new DeclarativeMargins(this);
m_margins->setTop(m_chart->margins().top());
diff --git a/plugins/declarative/declarativechart.h b/plugins/declarative/declarativechart.h
index 69116063..cc6295e7 100644
--- a/plugins/declarative/declarativechart.h
+++ b/plugins/declarative/declarativechart.h
@@ -170,7 +170,11 @@ private Q_SLOTS:
void handleAxisYRightSet(QAbstractAxis *axis);
void handleSeriesAdded(QAbstractSeries *series);
+protected:
+ explicit DeclarativeChart(QChart::ChartType type, QDeclarativeItem *parent);
+
private:
+ void initChart(QChart::ChartType type);
// Extending QChart with DeclarativeChart is not possible because QObject does not support
// multi inheritance, so we now have a QChart as a member instead
QChart *m_chart;
diff --git a/plugins/declarative/declarativelineseries.cpp b/plugins/declarative/declarativelineseries.cpp
index aae3eedf..735b2962 100644
--- a/plugins/declarative/declarativelineseries.cpp
+++ b/plugins/declarative/declarativelineseries.cpp
@@ -30,6 +30,8 @@ DeclarativeLineSeries::DeclarativeLineSeries(QObject *parent) :
connect(m_axes, SIGNAL(axisYChanged(QAbstractAxis*)), this, SIGNAL(axisYChanged(QAbstractAxis*)));
connect(m_axes, SIGNAL(axisXTopChanged(QAbstractAxis*)), this, SIGNAL(axisXTopChanged(QAbstractAxis*)));
connect(m_axes, SIGNAL(axisYRightChanged(QAbstractAxis*)), this, SIGNAL(axisYRightChanged(QAbstractAxis*)));
+ connect(m_axes, SIGNAL(axisXChanged(QAbstractAxis*)), this, SIGNAL(axisAngularChanged(QAbstractAxis*)));
+ connect(m_axes, SIGNAL(axisYChanged(QAbstractAxis*)), this, SIGNAL(axisRadialChanged(QAbstractAxis*)));
connect(this, SIGNAL(pointAdded(int)), this, SLOT(handleCountChanged(int)));
connect(this, SIGNAL(pointRemoved(int)), this, SLOT(handleCountChanged(int)));
}
diff --git a/plugins/declarative/declarativelineseries.h b/plugins/declarative/declarativelineseries.h
index 21e2ac19..05222a6d 100644
--- a/plugins/declarative/declarativelineseries.h
+++ b/plugins/declarative/declarativelineseries.h
@@ -38,6 +38,8 @@ class DeclarativeLineSeries : public QLineSeries, public DeclarativeXySeries, pu
Q_PROPERTY(QAbstractAxis *axisY READ axisY WRITE setAxisY NOTIFY axisYChanged REVISION 1)
Q_PROPERTY(QAbstractAxis *axisXTop READ axisXTop WRITE setAxisXTop NOTIFY axisXTopChanged REVISION 2)
Q_PROPERTY(QAbstractAxis *axisYRight READ axisYRight WRITE setAxisYRight NOTIFY axisYRightChanged REVISION 2)
+ Q_PROPERTY(QAbstractAxis *axisAngular READ axisAngular WRITE setAxisAngular NOTIFY axisAngularChanged REVISION 3)
+ Q_PROPERTY(QAbstractAxis *axisRadial READ axisRadial WRITE setAxisRadial NOTIFY axisRadialChanged REVISION 3)
Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY widthChanged REVISION 1)
Q_PROPERTY(Qt::PenStyle style READ style WRITE setStyle NOTIFY styleChanged REVISION 1)
Q_PROPERTY(Qt::PenCapStyle capStyle READ capStyle WRITE setCapStyle NOTIFY capStyleChanged REVISION 1)
@@ -55,6 +57,10 @@ public:
Q_REVISION(2) void setAxisXTop(QAbstractAxis *axis) { m_axes->setAxisXTop(axis); }
Q_REVISION(2) QAbstractAxis *axisYRight() { return m_axes->axisYRight(); }
Q_REVISION(2) void setAxisYRight(QAbstractAxis *axis) { m_axes->setAxisYRight(axis); }
+ Q_REVISION(3) QAbstractAxis *axisAngular() { return m_axes->axisX(); }
+ Q_REVISION(3) void setAxisAngular(QAbstractAxis *axis) { m_axes->setAxisX(axis); }
+ Q_REVISION(3) QAbstractAxis *axisRadial() { return m_axes->axisY(); }
+ Q_REVISION(3) void setAxisRadial(QAbstractAxis *axis) { m_axes->setAxisY(axis); }
qreal width() const;
void setWidth(qreal width);
Qt::PenStyle style() const;
@@ -81,6 +87,8 @@ Q_SIGNALS:
Q_REVISION(1) void axisYChanged(QAbstractAxis *axis);
Q_REVISION(2) void axisXTopChanged(QAbstractAxis *axis);
Q_REVISION(2) void axisYRightChanged(QAbstractAxis *axis);
+ Q_REVISION(3) void axisAngularChanged(QAbstractAxis *axis);
+ Q_REVISION(3) void axisRadialChanged(QAbstractAxis *axis);
Q_REVISION(1) void widthChanged(qreal width);
Q_REVISION(1) void styleChanged(Qt::PenStyle style);
Q_REVISION(1) void capStyleChanged(Qt::PenCapStyle capStyle);
diff --git a/plugins/declarative/declarativepolarchart.cpp b/plugins/declarative/declarativepolarchart.cpp
new file mode 100644
index 00000000..3be90d78
--- /dev/null
+++ b/plugins/declarative/declarativepolarchart.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 "declarativepolarchart.h"
+#include "qchart.h"
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+/*!
+ \qmlclass PolarChartView DeclarativePolarChart
+
+ PolarChartView element is the parent that is responsible for showing different chart series types
+ in 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 ValueAxis, 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.
+
+ \note Polar charts do not support multiple axes of same orientation.
+
+ The following QML shows how to create a polar chart with two series:
+ \snippet ../demos/qmlpolarchart/qml/qmlpolarchart/view1.qml 1
+
+ \beginfloatleft
+ \image demos_qmlpolarchart1.png
+ \endfloat
+ \clearfloat
+*/
+
+DeclarativePolarChart::DeclarativePolarChart(QDeclarativeItem *parent)
+ : DeclarativeChart(QChart::ChartTypePolar, parent)
+{
+}
+
+DeclarativePolarChart::~DeclarativePolarChart()
+{
+}
+
+#include "moc_declarativepolarchart.cpp"
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/plugins/declarative/declarativepolarchart.h b/plugins/declarative/declarativepolarchart.h
new file mode 100644
index 00000000..598de6ea
--- /dev/null
+++ b/plugins/declarative/declarativepolarchart.h
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 DECLARATIVEPOLARCHART_H
+#define DECLARATIVEPOLARCHART_H
+
+#include <QtCore/QtGlobal>
+#include <QtDeclarative/QDeclarativeItem>
+#include "declarativechart.h"
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+class DeclarativePolarChart : public DeclarativeChart
+{
+ Q_OBJECT
+public:
+ DeclarativePolarChart(QDeclarativeItem *parent = 0);
+ ~DeclarativePolarChart();
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // DECLARATIVEPOLARCHART_H
diff --git a/plugins/declarative/declarativescatterseries.cpp b/plugins/declarative/declarativescatterseries.cpp
index 209333e5..af7b41a6 100644
--- a/plugins/declarative/declarativescatterseries.cpp
+++ b/plugins/declarative/declarativescatterseries.cpp
@@ -30,6 +30,8 @@ DeclarativeScatterSeries::DeclarativeScatterSeries(QObject *parent) :
connect(m_axes, SIGNAL(axisYChanged(QAbstractAxis*)), this, SIGNAL(axisYChanged(QAbstractAxis*)));
connect(m_axes, SIGNAL(axisXTopChanged(QAbstractAxis*)), this, SIGNAL(axisXTopChanged(QAbstractAxis*)));
connect(m_axes, SIGNAL(axisYRightChanged(QAbstractAxis*)), this, SIGNAL(axisYRightChanged(QAbstractAxis*)));
+ connect(m_axes, SIGNAL(axisXChanged(QAbstractAxis*)), this, SIGNAL(axisAngularChanged(QAbstractAxis*)));
+ connect(m_axes, SIGNAL(axisYChanged(QAbstractAxis*)), this, SIGNAL(axisRadialChanged(QAbstractAxis*)));
connect(this, SIGNAL(pointAdded(int)), this, SLOT(handleCountChanged(int)));
connect(this, SIGNAL(pointRemoved(int)), this, SLOT(handleCountChanged(int)));
}
diff --git a/plugins/declarative/declarativescatterseries.h b/plugins/declarative/declarativescatterseries.h
index a6b4b1b8..2400242c 100644
--- a/plugins/declarative/declarativescatterseries.h
+++ b/plugins/declarative/declarativescatterseries.h
@@ -38,6 +38,8 @@ class DeclarativeScatterSeries : public QScatterSeries, public DeclarativeXySeri
Q_PROPERTY(QAbstractAxis *axisY READ axisY WRITE setAxisY NOTIFY axisYChanged REVISION 1)
Q_PROPERTY(QAbstractAxis *axisXTop READ axisXTop WRITE setAxisXTop NOTIFY axisXTopChanged REVISION 2)
Q_PROPERTY(QAbstractAxis *axisYRight READ axisYRight WRITE setAxisYRight NOTIFY axisYRightChanged REVISION 2)
+ Q_PROPERTY(QAbstractAxis *axisAngular READ axisAngular WRITE setAxisAngular NOTIFY axisAngularChanged REVISION 3)
+ Q_PROPERTY(QAbstractAxis *axisRadial READ axisRadial WRITE setAxisRadial NOTIFY axisRadialChanged REVISION 3)
Q_PROPERTY(qreal borderWidth READ borderWidth WRITE setBorderWidth NOTIFY borderWidthChanged REVISION 1)
Q_PROPERTY(QDeclarativeListProperty<QObject> declarativeChildren READ declarativeChildren)
Q_CLASSINFO("DefaultProperty", "declarativeChildren")
@@ -53,6 +55,10 @@ public:
Q_REVISION(2) void setAxisXTop(QAbstractAxis *axis) { m_axes->setAxisXTop(axis); }
Q_REVISION(2) QAbstractAxis *axisYRight() { return m_axes->axisYRight(); }
Q_REVISION(2) void setAxisYRight(QAbstractAxis *axis) { m_axes->setAxisYRight(axis); }
+ Q_REVISION(3) QAbstractAxis *axisAngular() { return m_axes->axisX(); }
+ Q_REVISION(3) void setAxisAngular(QAbstractAxis *axis) { m_axes->setAxisX(axis); }
+ Q_REVISION(3) QAbstractAxis *axisRadial() { return m_axes->axisY(); }
+ Q_REVISION(3) void setAxisRadial(QAbstractAxis *axis) { m_axes->setAxisY(axis); }
qreal borderWidth() const;
void setBorderWidth(qreal borderWidth);
QDeclarativeListProperty<QObject> declarativeChildren();
@@ -76,6 +82,8 @@ Q_SIGNALS:
Q_REVISION(1) void borderWidthChanged(qreal width);
Q_REVISION(2) void axisXTopChanged(QAbstractAxis *axis);
Q_REVISION(2) void axisYRightChanged(QAbstractAxis *axis);
+ Q_REVISION(3) void axisAngularChanged(QAbstractAxis *axis);
+ Q_REVISION(3) void axisRadialChanged(QAbstractAxis *axis);
public Q_SLOTS:
static void appendDeclarativeChildren(QDeclarativeListProperty<QObject> *list, QObject *element);
diff --git a/plugins/declarative/declarativesplineseries.cpp b/plugins/declarative/declarativesplineseries.cpp
index 7825b59b..f3900413 100644
--- a/plugins/declarative/declarativesplineseries.cpp
+++ b/plugins/declarative/declarativesplineseries.cpp
@@ -30,6 +30,8 @@ DeclarativeSplineSeries::DeclarativeSplineSeries(QObject *parent) :
connect(m_axes, SIGNAL(axisYChanged(QAbstractAxis*)), this, SIGNAL(axisYChanged(QAbstractAxis*)));
connect(m_axes, SIGNAL(axisXTopChanged(QAbstractAxis*)), this, SIGNAL(axisXTopChanged(QAbstractAxis*)));
connect(m_axes, SIGNAL(axisYRightChanged(QAbstractAxis*)), this, SIGNAL(axisYRightChanged(QAbstractAxis*)));
+ connect(m_axes, SIGNAL(axisXChanged(QAbstractAxis*)), this, SIGNAL(axisAngularChanged(QAbstractAxis*)));
+ connect(m_axes, SIGNAL(axisYChanged(QAbstractAxis*)), this, SIGNAL(axisRadialChanged(QAbstractAxis*)));
connect(this, SIGNAL(pointAdded(int)), this, SLOT(handleCountChanged(int)));
connect(this, SIGNAL(pointRemoved(int)), this, SLOT(handleCountChanged(int)));
}
diff --git a/plugins/declarative/declarativesplineseries.h b/plugins/declarative/declarativesplineseries.h
index f9e1a3e7..cfa0a7ee 100644
--- a/plugins/declarative/declarativesplineseries.h
+++ b/plugins/declarative/declarativesplineseries.h
@@ -38,6 +38,8 @@ class DeclarativeSplineSeries : public QSplineSeries, public DeclarativeXySeries
Q_PROPERTY(QAbstractAxis *axisY READ axisY WRITE setAxisY NOTIFY axisYChanged REVISION 1)
Q_PROPERTY(QAbstractAxis *axisXTop READ axisXTop WRITE setAxisXTop NOTIFY axisXTopChanged REVISION 2)
Q_PROPERTY(QAbstractAxis *axisYRight READ axisYRight WRITE setAxisYRight NOTIFY axisYRightChanged REVISION 2)
+ Q_PROPERTY(QAbstractAxis *axisAngular READ axisAngular WRITE setAxisAngular NOTIFY axisAngularChanged REVISION 3)
+ Q_PROPERTY(QAbstractAxis *axisRadial READ axisRadial WRITE setAxisRadial NOTIFY axisRadialChanged REVISION 3)
Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY widthChanged REVISION 1)
Q_PROPERTY(Qt::PenStyle style READ style WRITE setStyle NOTIFY styleChanged REVISION 1)
Q_PROPERTY(Qt::PenCapStyle capStyle READ capStyle WRITE setCapStyle NOTIFY capStyleChanged REVISION 1)
@@ -55,6 +57,10 @@ public:
Q_REVISION(2) void setAxisXTop(QAbstractAxis *axis) { m_axes->setAxisXTop(axis); }
Q_REVISION(2) QAbstractAxis *axisYRight() { return m_axes->axisYRight(); }
Q_REVISION(2) void setAxisYRight(QAbstractAxis *axis) { m_axes->setAxisYRight(axis); }
+ Q_REVISION(3) QAbstractAxis *axisAngular() { return m_axes->axisX(); }
+ Q_REVISION(3) void setAxisAngular(QAbstractAxis *axis) { m_axes->setAxisX(axis); }
+ Q_REVISION(3) QAbstractAxis *axisRadial() { return m_axes->axisY(); }
+ Q_REVISION(3) void setAxisRadial(QAbstractAxis *axis) { m_axes->setAxisY(axis); }
qreal width() const;
void setWidth(qreal width);
Qt::PenStyle style() const;
@@ -81,6 +87,8 @@ Q_SIGNALS:
Q_REVISION(1) void axisYChanged(QAbstractAxis *axis);
Q_REVISION(2) void axisXTopChanged(QAbstractAxis *axis);
Q_REVISION(2) void axisYRightChanged(QAbstractAxis *axis);
+ Q_REVISION(3) void axisAngularChanged(QAbstractAxis *axis);
+ Q_REVISION(3) void axisRadialChanged(QAbstractAxis *axis);
Q_REVISION(1) void widthChanged(qreal width);
Q_REVISION(1) void styleChanged(Qt::PenStyle style);
Q_REVISION(1) void capStyleChanged(Qt::PenCapStyle capStyle);
diff --git a/plugins/declarative/plugin.cpp b/plugins/declarative/plugin.cpp
index 2b4fd0aa..bf560e59 100644
--- a/plugins/declarative/plugin.cpp
+++ b/plugins/declarative/plugin.cpp
@@ -24,6 +24,7 @@
#include "declarativecategoryaxis.h"
#include "qbarcategoryaxis.h"
#include "declarativechart.h"
+#include "declarativepolarchart.h"
#include "declarativexypoint.h"
#include "declarativelineseries.h"
#include "declarativesplineseries.h"
@@ -62,6 +63,7 @@ Q_DECLARE_METATYPE(QList<QAbstractAxis *>)
// These should not be needed or at least they are not needed in Qt4.
Q_DECLARE_METATYPE(DeclarativeChart *)
+Q_DECLARE_METATYPE(DeclarativePolarChart *)
Q_DECLARE_METATYPE(DeclarativeMargins *)
Q_DECLARE_METATYPE(DeclarativeAreaSeries *)
Q_DECLARE_METATYPE(DeclarativeBarSeries *)
@@ -213,6 +215,13 @@ public:
qmlRegisterType<DeclarativeHorizontalBarSeries, 2>(uri, 1, 2, "HorizontalBarSeries");
qmlRegisterType<DeclarativeHorizontalStackedBarSeries, 2>(uri, 1, 2, "HorizontalStackedBarSeries");
qmlRegisterType<DeclarativeHorizontalPercentBarSeries, 2>(uri, 1, 2, "HorizontalPercentBarSeries");
+
+ // QtCommercial.Chart 1.3
+ qmlRegisterType<DeclarativePolarChart, 1>(uri, 1, 3, "PolarChartView");
+ qmlRegisterType<DeclarativeSplineSeries, 3>(uri, 1, 3, "SplineSeries");
+ qmlRegisterType<DeclarativeScatterSeries, 3>(uri, 1, 3, "ScatterSeries");
+ qmlRegisterType<DeclarativeLineSeries, 3>(uri, 1, 3, "LineSeries");
+ qmlRegisterType<DeclarativeAreaSeries, 3>(uri, 1, 3, "AreaSeries");
}
};
diff --git a/src/animations/axisanimation.cpp b/src/animations/axisanimation.cpp
index e59d9aae..fab017e1 100644
--- a/src/animations/axisanimation.cpp
+++ b/src/animations/axisanimation.cpp
@@ -19,14 +19,15 @@
****************************************************************************/
#include "axisanimation_p.h"
-#include "chartaxis_p.h"
+#include "chartaxiselement_p.h"
+#include "qabstractaxis_p.h"
Q_DECLARE_METATYPE(QVector<qreal>)
QTCOMMERCIALCHART_BEGIN_NAMESPACE
-AxisAnimation::AxisAnimation(ChartAxis *axis)
+AxisAnimation::AxisAnimation(ChartAxisElement *axis)
: ChartAnimation(axis),
m_axis(axis),
m_type(DefaultAnimation)
@@ -68,13 +69,13 @@ void AxisAnimation::setValues(QVector<qreal> &oldLayout, QVector<qreal> &newLayo
oldLayout.resize(newLayout.count());
for (int i = 0, j = oldLayout.count() - 1; i < (oldLayout.count() + 1) / 2; ++i, --j) {
- oldLayout[i] = m_axis->orientation() == Qt::Horizontal ? rect.left() : rect.bottom();
- oldLayout[j] = m_axis->orientation() == Qt::Horizontal ? rect.right() : rect.top();
+ 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->orientation() == Qt::Horizontal ? m_point.x() : (1 - m_point.y())), newLayout.count() - (qreal)1.0);
+ 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++)
@@ -99,7 +100,7 @@ void AxisAnimation::setValues(QVector<qreal> &oldLayout, QVector<qreal> &newLayo
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->orientation() == Qt::Horizontal ? rect.left() : rect.top();
+ oldLayout[i] = m_axis->axis()->orientation() == Qt::Horizontal ? rect.left() : rect.top();
}
break;
}
diff --git a/src/animations/axisanimation_p.h b/src/animations/axisanimation_p.h
index 6a213eae..d25cceda 100644
--- a/src/animations/axisanimation_p.h
+++ b/src/animations/axisanimation_p.h
@@ -35,13 +35,13 @@
QTCOMMERCIALCHART_BEGIN_NAMESPACE
-class ChartAxis;
+class ChartAxisElement;
class AxisAnimation: public ChartAnimation
{
public:
enum Animation { DefaultAnimation, ZoomOutAnimation, ZoomInAnimation, MoveForwardAnimation, MoveBackwordAnimation};
- AxisAnimation(ChartAxis *axis);
+ AxisAnimation(ChartAxisElement *axis);
~AxisAnimation();
void setAnimationType(Animation type);
void setAnimationPoint(const QPointF &point);
@@ -50,7 +50,7 @@ protected:
QVariant interpolated(const QVariant &from, const QVariant &to, qreal progress) const;
void updateCurrentValue(const QVariant &value);
private:
- ChartAxis *m_axis;
+ ChartAxisElement *m_axis;
Animation m_type;
QPointF m_point;
};
diff --git a/src/areachart/areachartitem.cpp b/src/areachart/areachartitem.cpp
index 92f89999..10adfa6f 100644
--- a/src/areachart/areachartitem.cpp
+++ b/src/areachart/areachartitem.cpp
@@ -88,12 +88,26 @@ void AreaChartItem::updatePath()
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);
- path.lineTo(last.x(), rect.bottom());
- path.lineTo(first.x(), rect.bottom());
+ 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();
prepareGeometryChange();
@@ -137,7 +151,11 @@ void AreaChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt
painter->save();
painter->setPen(m_linePen);
painter->setBrush(m_brush);
- painter->setClipRect(QRectF(QPointF(0,0),domain()->size()));
+ 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);
diff --git a/src/areachart/areachartitem_p.h b/src/areachart/areachartitem_p.h
index 0c09bade..60d3e07f 100644
--- a/src/areachart/areachartitem_p.h
+++ b/src/areachart/areachartitem_p.h
@@ -32,11 +32,11 @@
#include "qchartglobal.h"
#include "linechartitem_p.h"
+#include "qareaseries.h"
#include <QPen>
QTCOMMERCIALCHART_BEGIN_NAMESPACE
-class QAreaSeries;
class AreaChartItem;
class AreaChartItem : public ChartItem
@@ -57,6 +57,8 @@ public:
void updatePath();
void setPresenter(ChartPresenter *presenter);
+ QAreaSeries *series() const { return m_series; }
+
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
@@ -89,6 +91,9 @@ 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() {}
@@ -97,6 +102,9 @@ public:
// 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();
}
diff --git a/src/axis/axis.pri b/src/axis/axis.pri
index 264ed896..6f706aac 100644
--- a/src/axis/axis.pri
+++ b/src/axis/axis.pri
@@ -13,7 +13,8 @@ DEPENDPATH += $$PWD \
$$PWD/logvalueaxis
SOURCES += \
- $$PWD/chartaxis.cpp \
+ $$PWD/chartaxiselement.cpp \
+ $$PWD/cartesianchartaxis.cpp \
$$PWD/qabstractaxis.cpp \
$$PWD/verticalaxis.cpp \
$$PWD/horizontalaxis.cpp \
@@ -31,10 +32,12 @@ SOURCES += \
$$PWD/logvalueaxis/qlogvalueaxis.cpp
PRIVATE_HEADERS += \
- $$PWD/chartaxis_p.h \
+ $$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 \
@@ -55,6 +58,29 @@ PUBLIC_HEADERS += \
$$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
@@ -65,12 +91,16 @@ DEPENDPATH += \
SOURCES += \
$$PWD/datetimeaxis/chartdatetimeaxisx.cpp \
$$PWD/datetimeaxis/chartdatetimeaxisy.cpp \
- $$PWD/datetimeaxis/qdatetimeaxis.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/qdatetimeaxis_p.h \
+ $$PWD/datetimeaxis/polarchartdatetimeaxisangular_p.h \
+ $$PWD/datetimeaxis/polarchartdatetimeaxisradial_p.h
PUBLIC_HEADERS += \
$$PWD/datetimeaxis/qdatetimeaxis.h
diff --git a/src/axis/barcategoryaxis/chartbarcategoryaxisx.cpp b/src/axis/barcategoryaxis/chartbarcategoryaxisx.cpp
index 8d86b120..9d09aebf 100644
--- a/src/axis/barcategoryaxis/chartbarcategoryaxisx.cpp
+++ b/src/axis/barcategoryaxis/chartbarcategoryaxisx.cpp
@@ -21,7 +21,7 @@
#include "chartbarcategoryaxisx_p.h"
#include "chartpresenter_p.h"
#include "qbarcategoryaxis_p.h"
-#include "chartlayout_p.h"
+#include "abstractchartlayout_p.h"
#include <QFontMetrics>
#include <QDebug>
#include <qmath.h>
@@ -87,7 +87,7 @@ QStringList ChartBarCategoryAxisX::createCategoryLabels(const QVector<qreal>& la
void ChartBarCategoryAxisX::updateGeometry()
{
- const QVector<qreal>& layout = ChartAxis::layout();
+ const QVector<qreal>& layout = ChartAxisElement::layout();
if (layout.isEmpty())
return;
setLabels(createCategoryLabels(layout));
@@ -104,7 +104,7 @@ QSizeF ChartBarCategoryAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constra
{
Q_UNUSED(constraint)
- QFontMetrics fn(font());
+ QFontMetrics fn(axis()->labelsFont());
QSizeF sh;
QSizeF base = HorizontalAxis::sizeHint(which, constraint);
QStringList ticksList = m_categoriesAxis->categories();
diff --git a/src/axis/barcategoryaxis/chartbarcategoryaxisy.cpp b/src/axis/barcategoryaxis/chartbarcategoryaxisy.cpp
index 0ca8116c..20194bbc 100644
--- a/src/axis/barcategoryaxis/chartbarcategoryaxisy.cpp
+++ b/src/axis/barcategoryaxis/chartbarcategoryaxisy.cpp
@@ -21,7 +21,7 @@
#include "chartbarcategoryaxisy_p.h"
#include "chartpresenter_p.h"
#include "qbarcategoryaxis_p.h"
-#include "chartlayout_p.h"
+#include "abstractchartlayout_p.h"
#include <qmath.h>
#include <QFontMetrics>
#include <QDebug>
@@ -86,7 +86,7 @@ QStringList ChartBarCategoryAxisY::createCategoryLabels(const QVector<qreal>& la
void ChartBarCategoryAxisY::updateGeometry()
{
- const QVector<qreal>& layout = ChartAxis::layout();
+ const QVector<qreal>& layout = ChartAxisElement::layout();
if (layout.isEmpty())
return;
setLabels(createCategoryLabels(layout));
@@ -103,7 +103,7 @@ QSizeF ChartBarCategoryAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constra
{
Q_UNUSED(constraint)
- QFontMetrics fn(font());
+ QFontMetrics fn(axis()->labelsFont());
QSizeF sh;
QSizeF base = VerticalAxis::sizeHint(which, constraint);
QStringList ticksList = m_categoriesAxis->categories();
diff --git a/src/axis/barcategoryaxis/qbarcategoryaxis.cpp b/src/axis/barcategoryaxis/qbarcategoryaxis.cpp
index 0dffff0d..0dfbea1f 100644
--- a/src/axis/barcategoryaxis/qbarcategoryaxis.cpp
+++ b/src/axis/barcategoryaxis/qbarcategoryaxis.cpp
@@ -111,7 +111,7 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE
/*!
\fn void QBarCategoryAxis::categoriesChanged()
- Axis emits signal when the categories of the axis has changed.
+ Axis emits signal when the categories of the axis have changed.
*/
/*!
@@ -550,7 +550,7 @@ void QBarCategoryAxisPrivate::setRange(const QString &minCategory, const QStrin
void QBarCategoryAxisPrivate::initializeGraphics(QGraphicsItem* parent)
{
Q_Q(QBarCategoryAxis);
- ChartAxis* axis(0);
+ ChartAxisElement* axis(0);
if (orientation() == Qt::Vertical)
axis = new ChartBarCategoryAxisY(q,parent);
if (orientation() == Qt::Horizontal)
diff --git a/src/axis/cartesianchartaxis.cpp b/src/axis/cartesianchartaxis.cpp
new file mode 100644
index 00000000..85978202
--- /dev/null
+++ b/src/axis/cartesianchartaxis.cpp
@@ -0,0 +1,197 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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>
+
+QTCOMMERCIALCHART_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);
+ }
+ }
+
+ for (int i = 0; i < count; ++i) {
+ QGraphicsLineItem *arrow = new QGraphicsLineItem(this);
+ QGraphicsLineItem *grid = new QGraphicsLineItem(this);
+ QGraphicsSimpleTextItem *label = new QGraphicsSimpleTextItem(this);
+ QGraphicsSimpleTextItem *title = titleItem();
+ arrow->setPen(axis()->linePen());
+ grid->setPen(axis()->gridLinePen());
+ label->setFont(axis()->labelsFont());
+ label->setPen(axis()->labelsPen());
+ label->setBrush(axis()->labelsBrush());
+ label->setRotation(axis()->labelsAngle());
+ title->setFont(axis()->titleFont());
+ title->setPen(axis()->titlePen());
+ title->setBrush(axis()->titleBrush());
+ title->setText(axis()->titleText());
+ 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"
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/axis/cartesianchartaxis_p.h b/src/axis/cartesianchartaxis_p.h
new file mode 100644
index 00000000..51ed1326
--- /dev/null
+++ b/src/axis/cartesianchartaxis_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 QtCommercial 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"
+
+QTCOMMERCIALCHART_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;
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif /* CARTESIANCHARTAXIS_H */
diff --git a/src/axis/categoryaxis/chartcategoryaxisx.cpp b/src/axis/categoryaxis/chartcategoryaxisx.cpp
index 9c9813c4..cb1ede68 100644
--- a/src/axis/categoryaxis/chartcategoryaxisx.cpp
+++ b/src/axis/categoryaxis/chartcategoryaxisx.cpp
@@ -22,6 +22,7 @@
#include "qcategoryaxis.h"
#include "qabstractaxis.h"
#include "chartpresenter_p.h"
+#include "abstractchartlayout_p.h"
#include <QGraphicsLayout>
#include <QFontMetrics>
#include <qmath.h>
@@ -32,6 +33,7 @@ ChartCategoryAxisX::ChartCategoryAxisX(QCategoryAxis *axis, QGraphicsItem* item)
: HorizontalAxis(axis, item, true),
m_axis(axis)
{
+ QObject::connect(axis, SIGNAL(categoriesChanged()), this, SLOT(handleCategoriesChanged()));
}
ChartCategoryAxisX::~ChartCategoryAxisX()
@@ -72,16 +74,11 @@ void ChartCategoryAxisX::updateGeometry()
HorizontalAxis::updateGeometry();
}
-void ChartCategoryAxisX::handleAxisUpdated()
-{
- updateGeometry();
-}
-
QSizeF ChartCategoryAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
Q_UNUSED(constraint)
- QFontMetrics fn(font());
+ QFontMetrics fn(axis()->labelsFont());
QSizeF sh;
QSizeF base = HorizontalAxis::sizeHint(which, constraint);
QStringList ticksList = m_axis->categoriesLabels();
@@ -114,4 +111,12 @@ QSizeF ChartCategoryAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint
return sh;
}
+void ChartCategoryAxisX::handleCategoriesChanged()
+{
+ QGraphicsLayoutItem::updateGeometry();
+ presenter()->layout()->invalidate();
+}
+
+#include "moc_chartcategoryaxisx_p.cpp"
+
QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/axis/categoryaxis/chartcategoryaxisx_p.h b/src/axis/categoryaxis/chartcategoryaxisx_p.h
index df338cc5..2fced9cf 100644
--- a/src/axis/categoryaxis/chartcategoryaxisx_p.h
+++ b/src/axis/categoryaxis/chartcategoryaxisx_p.h
@@ -35,23 +35,23 @@
QTCOMMERCIALCHART_BEGIN_NAMESPACE
class QCategoryAxis;
-class ChartPresenter;
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();
-public Q_SLOTS:
- void handleAxisUpdated();
-
private:
QCategoryAxis *m_axis;
};
diff --git a/src/axis/categoryaxis/chartcategoryaxisy.cpp b/src/axis/categoryaxis/chartcategoryaxisy.cpp
index ea86b561..96f5a2d8 100644
--- a/src/axis/categoryaxis/chartcategoryaxisy.cpp
+++ b/src/axis/categoryaxis/chartcategoryaxisy.cpp
@@ -22,6 +22,7 @@
#include "qcategoryaxis.h"
#include "qabstractaxis.h"
#include "chartpresenter_p.h"
+#include "abstractchartlayout_p.h"
#include <QGraphicsLayout>
#include <QFontMetrics>
#include <qmath.h>
@@ -33,6 +34,7 @@ ChartCategoryAxisY::ChartCategoryAxisY(QCategoryAxis *axis, QGraphicsItem* item)
: VerticalAxis(axis, item, true),
m_axis(axis)
{
+ QObject::connect(axis, SIGNAL(categoriesChanged()), this, SLOT(handleCategoriesChanged()));
}
ChartCategoryAxisY::~ChartCategoryAxisY()
@@ -72,16 +74,11 @@ void ChartCategoryAxisY::updateGeometry()
VerticalAxis::updateGeometry();
}
-void ChartCategoryAxisY::handleAxisUpdated()
-{
- updateGeometry();
-}
-
QSizeF ChartCategoryAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
Q_UNUSED(constraint)
- QFontMetrics fn(font());
+ QFontMetrics fn(axis()->labelsFont());
QSizeF sh;
QSizeF base = VerticalAxis::sizeHint(which, constraint);
QStringList ticksList = m_axis->categoriesLabels();
@@ -113,4 +110,12 @@ QSizeF ChartCategoryAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint
return sh;
}
+void ChartCategoryAxisY::handleCategoriesChanged()
+{
+ QGraphicsLayoutItem::updateGeometry();
+ presenter()->layout()->invalidate();
+}
+
+#include "moc_chartcategoryaxisy_p.cpp"
+
QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/axis/categoryaxis/chartcategoryaxisy_p.h b/src/axis/categoryaxis/chartcategoryaxisy_p.h
index a9dcbd81..20760b82 100644
--- a/src/axis/categoryaxis/chartcategoryaxisy_p.h
+++ b/src/axis/categoryaxis/chartcategoryaxisy_p.h
@@ -35,23 +35,23 @@
QTCOMMERCIALCHART_BEGIN_NAMESPACE
class QCategoryAxis;
-class ChartPresenter;
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();
-public Q_SLOTS:
- void handleAxisUpdated();
-
private:
QCategoryAxis *m_axis;
};
diff --git a/src/axis/categoryaxis/polarchartcategoryaxisangular.cpp b/src/axis/categoryaxis/polarchartcategoryaxisangular.cpp
new file mode 100644
index 00000000..ead087f8
--- /dev/null
+++ b/src/axis/categoryaxis/polarchartcategoryaxisangular.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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>
+
+QTCOMMERCIALCHART_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() << "");
+}
+
+void PolarChartCategoryAxisAngular::handleCategoriesChanged()
+{
+ QGraphicsLayoutItem::updateGeometry();
+ presenter()->layout()->invalidate();
+}
+
+
+#include "moc_polarchartcategoryaxisangular_p.cpp"
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/axis/categoryaxis/polarchartcategoryaxisangular_p.h b/src/axis/categoryaxis/polarchartcategoryaxisangular_p.h
new file mode 100644
index 00000000..40d8d923
--- /dev/null
+++ b/src/axis/categoryaxis/polarchartcategoryaxisangular_p.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 QtCommercial 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"
+
+QTCOMMERCIALCHART_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();
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // POLARCHARTCATEGORYAXISANGULAR_P_H
diff --git a/src/axis/categoryaxis/polarchartcategoryaxisradial.cpp b/src/axis/categoryaxis/polarchartcategoryaxisradial.cpp
new file mode 100644
index 00000000..f4fe3b7b
--- /dev/null
+++ b/src/axis/categoryaxis/polarchartcategoryaxisradial.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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>
+
+QTCOMMERCIALCHART_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() << "");
+}
+
+void PolarChartCategoryAxisRadial::handleCategoriesChanged()
+{
+ QGraphicsLayoutItem::updateGeometry();
+ presenter()->layout()->invalidate();
+}
+
+#include "moc_polarchartcategoryaxisradial_p.cpp"
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/axis/categoryaxis/polarchartcategoryaxisradial_p.h b/src/axis/categoryaxis/polarchartcategoryaxisradial_p.h
new file mode 100644
index 00000000..83be8d8a
--- /dev/null
+++ b/src/axis/categoryaxis/polarchartcategoryaxisradial_p.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 QtCommercial 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"
+
+QTCOMMERCIALCHART_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();
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // POLARCHARTCATEGORYAXISRADIAL_P_H
diff --git a/src/axis/categoryaxis/qcategoryaxis.cpp b/src/axis/categoryaxis/qcategoryaxis.cpp
index 40d8cc25..d187da84 100644
--- a/src/axis/categoryaxis/qcategoryaxis.cpp
+++ b/src/axis/categoryaxis/qcategoryaxis.cpp
@@ -22,6 +22,8 @@
#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>
@@ -103,6 +105,12 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE
*/
/*!
+ \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):
@@ -151,10 +159,12 @@ void QCategoryAxis::append(const QString &categoryLabel, qreal categoryEndValue)
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();
}
}
}
@@ -169,10 +179,13 @@ 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)
+ if (min < range.second) {
d->m_categoriesMap.insert(d->m_categories.first(), Range(min, range.second));
+ emit categoriesChanged();
+ }
}
}
@@ -227,7 +240,7 @@ void QCategoryAxis::remove(const QString &categoryLabel)
d->m_categoriesMap.insert(label, range);
}
}
- //TODO:: d->emitUpdated();
+ emit categoriesChanged();
}
}
@@ -251,7 +264,7 @@ void QCategoryAxis::replaceLabel(const QString &oldLabel, const QString &newLabe
Range range = d->m_categoriesMap.value(oldLabel);
d->m_categoriesMap.remove(oldLabel);
d->m_categoriesMap.insert(newLabel, range);
- //TODO:: d->emitUpdated();
+ emit categoriesChanged();
}
}
@@ -300,14 +313,23 @@ int QCategoryAxisPrivate::ticksCount() const
return m_categories.count() + 1;
}
-void QCategoryAxisPrivate::initializeGraphics(QGraphicsItem* parent)
+void QCategoryAxisPrivate::initializeGraphics(QGraphicsItem *parent)
{
Q_Q(QCategoryAxis);
- ChartAxis* axis(0);
- if (orientation() == Qt::Vertical)
- axis = new ChartCategoryAxisY(q,parent);
- else if(orientation() == Qt::Horizontal)
- axis = new ChartCategoryAxisX(q,parent);
+ 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);
diff --git a/src/axis/categoryaxis/qcategoryaxis.h b/src/axis/categoryaxis/qcategoryaxis.h
index a7789275..73a33e21 100644
--- a/src/axis/categoryaxis/qcategoryaxis.h
+++ b/src/axis/categoryaxis/qcategoryaxis.h
@@ -57,6 +57,9 @@ public:
QStringList categoriesLabels();
int count() const;
+Q_SIGNALS:
+ void categoriesChanged();
+
private:
Q_DECLARE_PRIVATE(QCategoryAxis)
Q_DISABLE_COPY(QCategoryAxis)
diff --git a/src/axis/categoryaxis/qcategoryaxis_p.h b/src/axis/categoryaxis/qcategoryaxis_p.h
index 09d80a57..466deaef 100644
--- a/src/axis/categoryaxis/qcategoryaxis_p.h
+++ b/src/axis/categoryaxis/qcategoryaxis_p.h
@@ -48,9 +48,6 @@ public:
void initializeGraphics(QGraphicsItem* parent);
int ticksCount() const;
-Q_SIGNALS:
- void changed(qreal min, qreal max, int tickCount, bool niceNumbers);
-
private:
QMap<QString , Range> m_categoriesMap;
QStringList m_categories;
diff --git a/src/axis/chartaxis.cpp b/src/axis/chartaxis.cpp
deleted file mode 100644
index 7e565acc..00000000
--- a/src/axis/chartaxis.cpp
+++ /dev/null
@@ -1,547 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use contact form at http://qt.digia.com
-**
-** This file is part of the Qt Commercial Charts Add-on.
-**
-** $QT_BEGIN_LICENSE$
-** Licensees holding valid Qt Commercial licenses may use this file in
-** accordance with the Qt Commercial License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you 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 "chartaxis_p.h"
-#include "qabstractaxis.h"
-#include "qabstractaxis_p.h"
-#include "chartpresenter_p.h"
-#include "chartlayout_p.h"
-#include "abstractdomain_p.h"
-#include <qmath.h>
-#include <QDateTime>
-#include <QValueAxis>
-#include <QLogValueAxis>
-#include <QGraphicsLayout>
-#include <QFontMetrics>
-
-QTCOMMERCIALCHART_BEGIN_NAMESPACE
-
-ChartAxis::ChartAxis(QAbstractAxis *axis, QGraphicsItem* item , bool intervalAxis)
- : ChartElement(item),
- m_axis(axis),
- m_labelsAngle(axis->labelsAngle()),
- m_grid(new QGraphicsItemGroup(item)),
- m_arrow(new QGraphicsItemGroup(item)),
- m_shades(new QGraphicsItemGroup(item)),
- m_labels(new QGraphicsItemGroup(item)),
- m_title(new QGraphicsSimpleTextItem(item)),
- m_animation(0),
- m_labelPadding(5),
- m_intervalAxis(intervalAxis),
- m_titlePadding(3)
-{
- Q_ASSERT(item);
- //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);
- handleVisibleChanged(m_axis->isVisible());
- connectSlots();
-
- setFlag(QGraphicsItem::ItemHasNoContents,true);
-}
-
-void ChartAxis::connectSlots()
-{
- QObject::connect(m_axis,SIGNAL(visibleChanged(bool)),this,SLOT(handleVisibleChanged(bool)));
- QObject::connect(m_axis,SIGNAL(lineVisibleChanged(bool)),this,SLOT(handleArrowVisibleChanged(bool)));
- QObject::connect(m_axis,SIGNAL(gridVisibleChanged(bool)),this,SLOT(handleGridVisibleChanged(bool)));
- QObject::connect(m_axis,SIGNAL(labelsVisibleChanged(bool)),this,SLOT(handleLabelsVisibleChanged(bool)));
- QObject::connect(m_axis,SIGNAL(shadesVisibleChanged(bool)),this,SLOT(handleShadesVisibleChanged(bool)));
- QObject::connect(m_axis,SIGNAL(labelsAngleChanged(int)),this,SLOT(handleLabelsAngleChanged(int)));
- QObject::connect(m_axis,SIGNAL(linePenChanged(const QPen&)),this,SLOT(handleArrowPenChanged(const QPen&)));
- QObject::connect(m_axis,SIGNAL(labelsPenChanged(const QPen&)),this,SLOT(handleLabelsPenChanged(const QPen&)));
- QObject::connect(m_axis,SIGNAL(labelsBrushChanged(const QBrush&)),this,SLOT(handleLabelsBrushChanged(const QBrush&)));
- QObject::connect(m_axis,SIGNAL(labelsFontChanged(const QFont&)),this,SLOT(handleLabelsFontChanged(const QFont&)));
- QObject::connect(m_axis,SIGNAL(gridLinePenChanged(const QPen&)),this,SLOT(handleGridPenChanged(const QPen&)));
- QObject::connect(m_axis,SIGNAL(shadesPenChanged(const QPen&)),this,SLOT(handleShadesPenChanged(const QPen&)));
- QObject::connect(m_axis,SIGNAL(shadesBrushChanged(const QBrush&)),this,SLOT(handleShadesBrushChanged(const QBrush&)));
- QObject::connect(m_axis,SIGNAL(titleTextChanged(const QString&)),this,SLOT(handleTitleTextChanged(const QString&)));
- QObject::connect(m_axis,SIGNAL(titleFontChanged(const QFont&)),this,SLOT(handleTitleFontChanged(const QFont&)));
- QObject::connect(m_axis,SIGNAL(titlePenChanged(const QPen&)),this,SLOT(handleTitlePenChanged(const QPen&)));
- QObject::connect(m_axis,SIGNAL(titleBrushChanged(const QBrush&)),this,SLOT(handleTitleBrushChanged(const QBrush&)));
- QObject::connect(m_axis,SIGNAL(titleVisibleChanged(bool)),this,SLOT(handleTitleVisibleChanged(bool)));
- QObject::connect(m_axis->d_ptr.data(),SIGNAL(rangeChanged(qreal,qreal)),this,SLOT(handleRangeChanged(qreal,qreal)));
-}
-
-ChartAxis::~ChartAxis()
-{
-}
-
-void ChartAxis::setAnimation(AxisAnimation *animation)
-{
- m_animation = animation;
-}
-
-void ChartAxis::setLayout(QVector<qreal> &layout)
-{
- m_layoutVector = layout;
-}
-
-void ChartAxis::createItems(int count)
-{
- if (m_arrow->childItems().size() == 0){
- QGraphicsLineItem* arrow = new ArrowItem(this, this);
- arrow->setPen(m_axis->linePen());
- m_arrow->addToGroup(arrow);
- }
-
- if (m_intervalAxis && m_grid->childItems().size() == 0) {
- for (int i = 0 ; i < 2 ; i ++){
- QGraphicsLineItem* item = new QGraphicsLineItem(this);
- item->setPen(m_axis->gridLinePen());
- m_grid->addToGroup(item);
- }
- }
-
- for (int i = 0; i < count; ++i) {
- QGraphicsLineItem* arrow = new QGraphicsLineItem(this);
- arrow->setPen(m_axis->linePen());
- QGraphicsLineItem* grid = new QGraphicsLineItem(this);
- grid->setPen(m_axis->gridLinePen());
- QGraphicsSimpleTextItem* label = new QGraphicsSimpleTextItem(this);
- label->setFont(m_axis->labelsFont());
- label->setPen(m_axis->labelsPen());
- label->setBrush(m_axis->labelsBrush());
- label->setRotation(m_labelsAngle);
- m_arrow->addToGroup(arrow);
- m_grid->addToGroup(grid);
- m_labels->addToGroup(label);
-
- if ((m_grid->childItems().size()) % 2 && m_grid->childItems().size() > 2){
- QGraphicsRectItem* shades = new QGraphicsRectItem(this);
- shades->setPen(m_axis->shadesPen());
- shades->setBrush(m_axis->shadesBrush());
- m_shades->addToGroup(shades);
- }
- }
-
-}
-
-void ChartAxis::deleteItems(int count)
-{
- QList<QGraphicsItem *> lines = m_grid->childItems();
- QList<QGraphicsItem *> labels = m_labels->childItems();
- QList<QGraphicsItem *> shades = m_shades->childItems();
- QList<QGraphicsItem *> axis = m_arrow->childItems();
-
- 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 ChartAxis::updateLayout(QVector<qreal> &layout)
-{
- int diff = m_layoutVector.size() - layout.size();
-
- if (diff > 0)
- deleteItems(diff);
- else if (diff < 0)
- createItems(-diff);
-
- if (m_animation) {
- switch (presenter()->state()) {
- case ChartPresenter::ZoomInState:
- m_animation->setAnimationType(AxisAnimation::ZoomInAnimation);
- m_animation->setAnimationPoint(presenter()->statePoint());
- break;
- case ChartPresenter::ZoomOutState:
- m_animation->setAnimationType(AxisAnimation::ZoomOutAnimation);
- m_animation->setAnimationPoint(presenter()->statePoint());
- break;
- case ChartPresenter::ScrollUpState:
- case ChartPresenter::ScrollLeftState:
- m_animation->setAnimationType(AxisAnimation::MoveBackwordAnimation);
- break;
- case ChartPresenter::ScrollDownState:
- case ChartPresenter::ScrollRightState:
- m_animation->setAnimationType(AxisAnimation::MoveForwardAnimation);
- break;
- case ChartPresenter::ShowState:
- m_animation->setAnimationType(AxisAnimation::DefaultAnimation);
- break;
- }
- m_animation->setValues(m_layoutVector, layout);
- presenter()->startAnimation(m_animation);
- } else {
- setLayout(layout);
- updateGeometry();
- }
-}
-
-void ChartAxis::setLabelPadding(int padding)
-{
- m_labelPadding = padding;
-}
-
-void ChartAxis::setTitlePadding(int padding)
-{
- m_titlePadding = padding;
-}
-
-bool ChartAxis::isEmpty()
-{
- return m_axisRect.isEmpty() || m_gridRect.isEmpty() || qFuzzyCompare(min(),max());
-}
-
-void ChartAxis::setGeometry(const QRectF &axis, const QRectF &grid)
-{
- m_gridRect = grid;
- m_axisRect = axis;
-
- if (isEmpty())
- return;
-
- QVector<qreal> layout = calculateLayout();
- updateLayout(layout);
-}
-
-qreal ChartAxis::min() const
-{
- return m_axis->d_ptr->min();
-}
-
-qreal ChartAxis::max() const
-{
- return m_axis->d_ptr->max();
-}
-
-QFont ChartAxis::font() const
-{
- return m_axis->labelsFont();
-}
-
-QFont ChartAxis::titleFont() const
-{
- return m_axis->titleFont();
-}
-
-QString ChartAxis::titleText() const
-{
- return m_axis->titleText();
-}
-
-void ChartAxis::axisSelected()
-{
- emit clicked();
-}
-
-Qt::Orientation ChartAxis::orientation() const
-{
- return m_axis->orientation();
-}
-
-Qt::Alignment ChartAxis::alignment() const
-{
- return m_axis->alignment();
-}
-
-void ChartAxis::setLabels(const QStringList &labels)
-{
- m_labelsList = labels;
-}
-
-QSizeF ChartAxis::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
-{
- Q_UNUSED(which);
- Q_UNUSED(constraint);
- return QSizeF();
-}
-
-//handlers
-
-void ChartAxis::handleArrowVisibleChanged(bool visible)
-{
- m_arrow->setVisible(visible);
-}
-
-void ChartAxis::handleGridVisibleChanged(bool visible)
-{
- m_grid->setVisible(visible);
-}
-
-void ChartAxis::handleLabelsVisibleChanged(bool visible)
-{
- m_labels->setVisible(visible);
-}
-
-void ChartAxis::handleShadesVisibleChanged(bool visible)
-{
- m_shades->setVisible(visible);
-}
-
-void ChartAxis::handleTitleVisibleChanged(bool visible)
-{
- QGraphicsLayoutItem::updateGeometry();
- presenter()->layout()->invalidate();
- m_title->setVisible(visible);
-}
-
-void ChartAxis::handleLabelsAngleChanged(int angle)
-{
- foreach (QGraphicsItem *item, m_labels->childItems())
- item->setRotation(angle);
-
- m_labelsAngle = angle;
-}
-
-void ChartAxis::handleLabelsPenChanged(const QPen &pen)
-{
- foreach (QGraphicsItem *item , m_labels->childItems())
- static_cast<QGraphicsSimpleTextItem *>(item)->setPen(pen);
-}
-
-void ChartAxis::handleLabelsBrushChanged(const QBrush &brush)
-{
- foreach (QGraphicsItem *item , m_labels->childItems())
- static_cast<QGraphicsSimpleTextItem *>(item)->setBrush(brush);
-}
-
-void ChartAxis::handleLabelsFontChanged(const QFont &font)
-{
- foreach (QGraphicsItem *item , m_labels->childItems())
- static_cast<QGraphicsSimpleTextItem *>(item)->setFont(font);
- QGraphicsLayoutItem::updateGeometry();
- presenter()->layout()->invalidate();
-}
-
-void ChartAxis::handleShadesBrushChanged(const QBrush &brush)
-{
- foreach (QGraphicsItem *item , m_shades->childItems())
- static_cast<QGraphicsRectItem *>(item)->setBrush(brush);
-}
-
-void ChartAxis::handleShadesPenChanged(const QPen &pen)
-{
- foreach (QGraphicsItem *item , m_shades->childItems())
- static_cast<QGraphicsRectItem *>(item)->setPen(pen);
-}
-
-void ChartAxis::handleArrowPenChanged(const QPen &pen)
-{
- foreach (QGraphicsItem *item , m_arrow->childItems())
- static_cast<QGraphicsLineItem *>(item)->setPen(pen);
-}
-
-void ChartAxis::handleGridPenChanged(const QPen &pen)
-{
- foreach (QGraphicsItem *item , m_grid->childItems())
- static_cast<QGraphicsLineItem *>(item)->setPen(pen);
-}
-
-void ChartAxis::handleTitleTextChanged(const QString &title)
-{
- QGraphicsLayoutItem::updateGeometry();
- presenter()->layout()->invalidate();
- m_title->setText(title);
-}
-
-
-void ChartAxis::handleTitlePenChanged(const QPen &pen)
-{
- m_title->setPen(pen);
-}
-
-void ChartAxis::handleTitleBrushChanged(const QBrush &brush)
-{
- m_title->setBrush(brush);
-}
-
-void ChartAxis::handleTitleFontChanged(const QFont &font)
-{
- if(m_title->font() != font){
- m_title->setFont(font);
- QGraphicsLayoutItem::updateGeometry();
- presenter()->layout()->invalidate();
- }
-}
-
-void ChartAxis::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(m_axis->isGridLineVisible());
- m_arrow->setVisible(m_axis->isLineVisible());
- m_shades->setVisible(m_axis->shadesVisible());
- m_labels->setVisible(m_axis->labelsVisible());
- m_title->setVisible(m_axis->isTitleVisible());
- }
-
- if(presenter()) presenter()->layout()->invalidate();
-}
-
-void ChartAxis::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());
- }
- }
-
-}
-
-//helpers
-
-QStringList ChartAxis::createValueLabels(qreal min, qreal max, int ticks,const QString& format)
-{
- QStringList labels;
-
- if (max <= min || ticks < 1)
- return labels;
-
- int n = qMax(int(-qFloor(log10((max - min) / (ticks - 1)))), 0);
- n++;
-
- if (format.isNull()) {
- for (int i = 0; i < ticks; i++) {
- qreal value = min + (i * (max - min) / (ticks - 1));
- labels << QString::number(value, 'f', n);
- }
- } else {
- QByteArray array = format.toLatin1();
- for (int i = 0; i < ticks; i++) {
- qreal value = min + (i * (max - min) / (ticks - 1));
- if (format.contains("d")
- || format.contains("i")
- || format.contains("c"))
- labels << QString().sprintf(array, (qint64)value);
- else if (format.contains("u")
- || format.contains("o")
- || format.contains("x", Qt::CaseInsensitive))
- labels << QString().sprintf(array, (quint64)value);
- else if (format.contains("f", Qt::CaseInsensitive)
- || format.contains("e", Qt::CaseInsensitive)
- || format.contains("g", Qt::CaseInsensitive))
- labels << QString().sprintf(array, value);
- else
- labels << QString();
- }
- }
-
- return labels;
-}
-
-QStringList ChartAxis::createLogValueLabels(qreal min, qreal max, qreal base, int ticks, const QString& format)
-{
-// Q_ASSERT(m_max > m_min);
- // Q_ASSERT(ticks > 1);
-
- QStringList labels;
-
- int n = 0;
- if (ticks > 1)
- n = qMax(int(-qFloor(log10((max - min) / (ticks - 1)))), 0);
- n++;
-
- int firstTick;
- if (base > 1)
- firstTick = ceil(log10(min) / log10(base));
- else
- firstTick = ceil(log10(max) / log10(base));
-
- if (format.isNull()) {
- for (int i = firstTick; i < ticks + firstTick; i++) {
- qreal value = qPow(base, i);
- labels << QString::number(value, 'f', n);
- }
- } else {
- QByteArray array = format.toLatin1();
- for (int i = firstTick; i < ticks + firstTick; i++) {
- qreal value = qPow(base, i);
- if (format.contains("d")
- || format.contains("i")
- || format.contains("c"))
- labels << QString().sprintf(array, (qint64)value);
- else if (format.contains("u")
- || format.contains("o")
- || format.contains("x", Qt::CaseInsensitive))
- labels << QString().sprintf(array, (quint64)value);
- else if (format.contains("f", Qt::CaseInsensitive)
- || format.contains("e", Qt::CaseInsensitive)
- || format.contains("g", Qt::CaseInsensitive))
- labels << QString().sprintf(array, value);
- else
- labels << QString();
- }
- }
-
- return labels;
-}
-
-QStringList ChartAxis::createDateTimeLabels(qreal min, qreal max,int ticks,const QString& format)
-{
- 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 << QDateTime::fromMSecsSinceEpoch(value).toString(format);
- }
- return labels;
-}
-
-QRect ChartAxis::labelBoundingRect(const QFontMetrics &fn, const QString &label) const
-{
- QRect boundingRect = fn.boundingRect(label);
-
- // Take label rotation into account
- if (m_labelsAngle) {
- QTransform transform;
- transform.rotate(m_labelsAngle);
- boundingRect = transform.mapRect(boundingRect);
- }
-
- return boundingRect;
-}
-
-#include "moc_chartaxis_p.cpp"
-
-QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/axis/chartaxis_p.h b/src/axis/chartaxis_p.h
deleted file mode 100644
index 681613f8..00000000
--- a/src/axis/chartaxis_p.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use contact form at http://qt.digia.com
-**
-** This file is part of the Qt Commercial Charts Add-on.
-**
-** $QT_BEGIN_LICENSE$
-** Licensees holding valid Qt Commercial licenses may use this file in
-** accordance with the Qt Commercial License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you 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 QtCommercial 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 CHARTAXIS_H
-#define CHARTAXIS_H
-
-#include "qchartglobal.h"
-#include "chartelement_p.h"
-#include "axisanimation_p.h"
-#include <QGraphicsItem>
-#include <QGraphicsLayoutItem>
-#include <QFont>
-
-QTCOMMERCIALCHART_BEGIN_NAMESPACE
-
-class QAbstractAxis;
-class ChartPresenter;
-
-class ChartAxis : public ChartElement, public QGraphicsLayoutItem
-{
- Q_OBJECT
- Q_INTERFACES(QGraphicsLayoutItem)
-public:
-
- ChartAxis(QAbstractAxis *axis, QGraphicsItem* item = 0, bool intervalAxis = false);
- ~ChartAxis();
-
- QAbstractAxis* axis() const { return m_axis; }
-
- void setLabelPadding(int padding);
- int labelPadding() const { return m_labelPadding;};
-
- void setTitlePadding(int padding);
- int titlePadding() const { return m_titlePadding;};
-
- QFont titleFont() const;
- QString titleText() const;
-
- void setLayout(QVector<qreal> &layout);
- QVector<qreal> layout() const { return m_layoutVector; }
-
- void setAnimation(AxisAnimation *animation);
- ChartAnimation *animation() const { return m_animation; };
-
- Qt::Orientation orientation() const;
- Qt::Alignment alignment() const;
-
- void setGeometry(const QRectF &axis, const QRectF &grid);
- QRectF axisGeometry() const { return m_axisRect; }
- QRectF gridGeometry() const { return m_gridRect; }
-
- void setLabels(const QStringList &labels);
- QStringList labels() const { return m_labelsList; }
-
- //this flag indicates that axis is used to show intervals it means labels are in between ticks
- bool intervalAxis() const { return m_intervalAxis; }
-
- virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
-
-
- QRectF boundingRect() const{
- return QRectF();
- }
-
- void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*)
- {
-
- }
-
-//helpers
- static QStringList createValueLabels(qreal max, qreal min, int ticks, const QString &format);
- static QStringList createLogValueLabels(qreal min, qreal max, qreal base, int ticks, const QString& format);
- static QStringList createDateTimeLabels(qreal max, qreal min, int ticks, const QString &format);
-
-protected:
- void setGeometry(const QRectF &size) { Q_UNUSED(size);};
- virtual void updateGeometry() = 0;
- virtual QVector<qreal> calculateLayout() const = 0;
-
- QList<QGraphicsItem *> lineItems() { 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();};
- QGraphicsSimpleTextItem* titleItem() const { return m_title.data();}
-
- QFont font() const;
- qreal min() const;
- qreal max() const;
- QRect labelBoundingRect(const QFontMetrics &fn, const QString &label) const;
-
-//handlers
-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);
- void handleShadesBrushChanged(const QBrush &brush);
- void handleShadesPenChanged(const QPen &pen);
- void handleArrowPenChanged(const QPen &pen);
- void handleGridPenChanged(const QPen &pen);
- 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:
- inline bool isEmpty();
- void createItems(int count);
- void deleteItems(int count);
- void updateLayout(QVector<qreal> &layout);
- void axisSelected();
- void connectSlots();
-
-private:
- QAbstractAxis *m_axis;
- int m_labelsAngle;
- QRectF m_axisRect;
- QRectF m_gridRect;
- QScopedPointer<QGraphicsItemGroup> m_grid;
- QScopedPointer<QGraphicsItemGroup> m_arrow;
- QScopedPointer<QGraphicsItemGroup> m_shades;
- QScopedPointer<QGraphicsItemGroup> m_labels;
- QScopedPointer<QGraphicsSimpleTextItem> m_title;
- QVector<qreal> m_layoutVector;
- AxisAnimation *m_animation;
- int m_labelPadding;
- QStringList m_labelsList;
- bool m_intervalAxis;
- int m_titlePadding;
-
- friend class AxisAnimation;
- friend class ArrowItem;
-
-};
-
-class ArrowItem: public QGraphicsLineItem
-{
-
-public:
- explicit ArrowItem(ChartAxis *axis, QGraphicsItem *parent = 0) : QGraphicsLineItem(parent), m_axis(axis) {}
-
-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_axis->orientation() != Qt::Horizontal ? 8 : 0, m_axis->orientation() != Qt::Vertical ? 8 : 0));
- return path;
- }
-
-private:
- ChartAxis *m_axis;
-};
-
-QTCOMMERCIALCHART_END_NAMESPACE
-
-#endif /* CHARTAXI_H */
diff --git a/src/axis/chartaxiselement.cpp b/src/axis/chartaxiselement.cpp
new file mode 100644
index 00000000..19fa8e17
--- /dev/null
+++ b/src/axis/chartaxiselement.cpp
@@ -0,0 +1,349 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 <QFontMetrics>
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+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 QGraphicsSimpleTextItem(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);
+ 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)
+{
+ foreach (QGraphicsItem *item, m_labels->childItems())
+ static_cast<QGraphicsSimpleTextItem *>(item)->setPen(pen);
+}
+
+void ChartAxisElement::handleLabelsBrushChanged(const QBrush &brush)
+{
+ foreach (QGraphicsItem *item, m_labels->childItems())
+ static_cast<QGraphicsSimpleTextItem *>(item)->setBrush(brush);
+}
+
+void ChartAxisElement::handleLabelsFontChanged(const QFont &font)
+{
+ foreach (QGraphicsItem *item, m_labels->childItems())
+ static_cast<QGraphicsSimpleTextItem *>(item)->setFont(font);
+ QGraphicsLayoutItem::updateGeometry();
+ presenter()->layout()->invalidate();
+}
+
+void ChartAxisElement::handleTitleTextChanged(const QString &title)
+{
+ QGraphicsLayoutItem::updateGeometry();
+ presenter()->layout()->invalidate();
+ m_title->setText(title);
+}
+
+void ChartAxisElement::handleTitlePenChanged(const QPen &pen)
+{
+ m_title->setPen(pen);
+}
+
+void ChartAxisElement::handleTitleBrushChanged(const QBrush &brush)
+{
+ m_title->setBrush(brush);
+}
+
+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();
+}
+
+QRect ChartAxisElement::labelBoundingRect(const QFontMetrics &fn, const QString &label) const
+{
+ QRect boundingRect = fn.boundingRect(label);
+ // Take label rotation into account
+ if (axis()->labelsAngle()) {
+ QTransform transform;
+ transform.rotate(axis()->labelsAngle());
+ boundingRect = transform.mapRect(boundingRect);
+ }
+
+ return boundingRect;
+}
+
+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();
+}
+
+QStringList ChartAxisElement::createValueLabels(qreal min, qreal max, int ticks, const QString &format)
+{
+ QStringList labels;
+
+ if (max <= min || ticks < 1)
+ return labels;
+
+ int n = qMax(int(-qFloor(log10((max - min) / (ticks - 1)))), 0);
+ n++;
+
+ if (format.isNull()) {
+ for (int i = 0; i < ticks; i++) {
+ qreal value = min + (i * (max - min) / (ticks - 1));
+ labels << QString::number(value, 'f', n);
+ }
+ } else {
+ QByteArray array = format.toLatin1();
+ for (int i = 0; i < ticks; i++) {
+ qreal value = min + (i * (max - min) / (ticks - 1));
+ if (format.contains("d")
+ || format.contains("i")
+ || format.contains("c")) {
+ labels << QString().sprintf(array, (qint64)value);
+ } else if (format.contains("u")
+ || format.contains("o")
+ || format.contains("x", Qt::CaseInsensitive)) {
+ labels << QString().sprintf(array, (quint64)value);
+ } else if (format.contains("f", Qt::CaseInsensitive)
+ || format.contains("e", Qt::CaseInsensitive)
+ || format.contains("g", Qt::CaseInsensitive)) {
+ labels << QString().sprintf(array, value);
+ } else {
+ labels << QString();
+ }
+ }
+ }
+
+ return labels;
+}
+
+QStringList ChartAxisElement::createLogValueLabels(qreal min, qreal max, qreal base, int ticks, const QString &format)
+{
+ QStringList labels;
+
+ if (max <= min || ticks < 1)
+ return labels;
+
+ int n = 0;
+ if (ticks > 1)
+ n = qMax(int(-qFloor(log10((max - min) / (ticks - 1)))), 0);
+ n++;
+
+ int firstTick;
+ if (base > 1)
+ firstTick = ceil(log10(min) / log10(base));
+ else
+ firstTick = ceil(log10(max) / log10(base));
+
+ if (format.isNull()) {
+ for (int i = firstTick; i < ticks + firstTick; i++) {
+ qreal value = qPow(base, i);
+ labels << QString::number(value, 'f', n);
+ }
+ } else {
+ QByteArray array = format.toLatin1();
+ for (int i = firstTick; i < ticks + firstTick; i++) {
+ qreal value = qPow(base, i);
+ if (format.contains("d")
+ || format.contains("i")
+ || format.contains("c")) {
+ labels << QString().sprintf(array, (qint64)value);
+ } else if (format.contains("u")
+ || format.contains("o")
+ || format.contains("x", Qt::CaseInsensitive)) {
+ labels << QString().sprintf(array, (quint64)value);
+ } else if (format.contains("f", Qt::CaseInsensitive)
+ || format.contains("e", Qt::CaseInsensitive)
+ || format.contains("g", Qt::CaseInsensitive)) {
+ labels << QString().sprintf(array, value);
+ } else {
+ labels << QString();
+ }
+ }
+ }
+
+ return labels;
+}
+
+QStringList ChartAxisElement::createDateTimeLabels(qreal min, qreal max,int ticks,const QString &format)
+{
+ 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 << QDateTime::fromMSecsSinceEpoch(value).toString(format);
+ }
+ return labels;
+}
+
+void ChartAxisElement::axisSelected()
+{
+ emit clicked();
+}
+
+#include "moc_chartaxiselement_p.cpp"
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/axis/chartaxiselement_p.h b/src/axis/chartaxiselement_p.h
new file mode 100644
index 00000000..0fdd207d
--- /dev/null
+++ b/src/axis/chartaxiselement_p.h
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 QtCommercial 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>
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+class ChartPresenter;
+class QAbstractAxis;
+
+class ChartAxisElement : public ChartElement, public QGraphicsLayoutItem
+{
+ Q_OBJECT
+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
+ int labelPadding() const { return 5; }
+ int titlePadding() const { return 3; }
+ 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; }
+
+ QRect labelBoundingRect(const QFontMetrics &fn, const QString &label) const;
+
+ 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; }
+
+ static QStringList createValueLabels(qreal max, qreal min, int ticks, const QString &format);
+ static QStringList createLogValueLabels(qreal min, qreal max, qreal base, int ticks, const QString &format);
+ static QStringList createDateTimeLabels(qreal max, qreal min, int ticks, const QString &format);
+
+ // 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(); }
+ QGraphicsSimpleTextItem *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();
+
+ 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<QGraphicsSimpleTextItem> m_title;
+ bool m_intervalAxis;
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif /* CHARTAXISELEMENT_H */
diff --git a/src/axis/datetimeaxis/chartdatetimeaxisx.cpp b/src/axis/datetimeaxis/chartdatetimeaxisx.cpp
index 39fc3ba7..6ff32c5e 100644
--- a/src/axis/datetimeaxis/chartdatetimeaxisx.cpp
+++ b/src/axis/datetimeaxis/chartdatetimeaxisx.cpp
@@ -21,7 +21,7 @@
#include "chartdatetimeaxisx_p.h"
#include "chartpresenter_p.h"
#include "qdatetimeaxis.h"
-#include "chartlayout_p.h"
+#include "abstractchartlayout_p.h"
#include <QGraphicsLayout>
#include <QDateTime>
#include <QFontMetrics>
@@ -29,12 +29,12 @@
QTCOMMERCIALCHART_BEGIN_NAMESPACE
-ChartDateTimeAxisX::ChartDateTimeAxisX(QDateTimeAxis *axis, QGraphicsItem* item)
+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)));
+ QObject::connect(m_axis, SIGNAL(tickCountChanged(int)), this, SLOT(handleTickCountChanged(int)));
+ QObject::connect(m_axis, SIGNAL(formatChanged(QString)), this, SLOT(handleFormatChanged(QString)));
}
ChartDateTimeAxisX::~ChartDateTimeAxisX()
@@ -58,10 +58,10 @@ QVector<qreal> ChartDateTimeAxisX::calculateLayout() const
void ChartDateTimeAxisX::updateGeometry()
{
- const QVector<qreal>& layout = ChartAxis::layout();
+ const QVector<qreal>& layout = ChartAxisElement::layout();
if (layout.isEmpty())
return;
- setLabels(createDateTimeLabels(min(),max(), layout.size(),m_axis->format()));
+ setLabels(createDateTimeLabels(min(), max(), layout.size(), m_axis->format()));
HorizontalAxis::updateGeometry();
}
@@ -69,25 +69,27 @@ void ChartDateTimeAxisX::handleTickCountChanged(int tick)
{
Q_UNUSED(tick)
QGraphicsLayoutItem::updateGeometry();
- if(presenter()) presenter()->layout()->invalidate();
+ if (presenter())
+ presenter()->layout()->invalidate();
}
void ChartDateTimeAxisX::handleFormatChanged(const QString &format)
{
Q_UNUSED(format);
QGraphicsLayoutItem::updateGeometry();
- if(presenter()) presenter()->layout()->invalidate();
+ if (presenter())
+ presenter()->layout()->invalidate();
}
QSizeF ChartDateTimeAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
Q_UNUSED(constraint)
- QFontMetrics fn(font());
+ QFontMetrics fn(axis()->labelsFont());
QSizeF sh;
QSizeF base = HorizontalAxis::sizeHint(which, constraint);
- QStringList ticksList = createDateTimeLabels(min(),max(),m_axis->tickCount(),m_axis->format());
+ 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;
@@ -97,7 +99,7 @@ QSizeF ChartDateTimeAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint
return sh;
switch (which) {
- case Qt::MinimumSize:{
+ case Qt::MinimumSize: {
QRectF boundingRect = labelBoundingRect(fn, "...");
width = boundingRect.width() / 2.0;
height = boundingRect.height() + labelPadding();
diff --git a/src/axis/datetimeaxis/chartdatetimeaxisx_p.h b/src/axis/datetimeaxis/chartdatetimeaxisx_p.h
index 841ae1ea..03fe98bb 100644
--- a/src/axis/datetimeaxis/chartdatetimeaxisx_p.h
+++ b/src/axis/datetimeaxis/chartdatetimeaxisx_p.h
@@ -35,7 +35,6 @@
QTCOMMERCIALCHART_BEGIN_NAMESPACE
class QDateTimeAxis;
-class ChartPresenter;
class ChartDateTimeAxisX : public HorizontalAxis
{
diff --git a/src/axis/datetimeaxis/chartdatetimeaxisy.cpp b/src/axis/datetimeaxis/chartdatetimeaxisy.cpp
index a534617f..a8fe58a2 100644
--- a/src/axis/datetimeaxis/chartdatetimeaxisy.cpp
+++ b/src/axis/datetimeaxis/chartdatetimeaxisy.cpp
@@ -21,7 +21,7 @@
#include "chartdatetimeaxisy_p.h"
#include "chartpresenter_p.h"
#include "qdatetimeaxis.h"
-#include "chartlayout_p.h"
+#include "abstractchartlayout_p.h"
#include <QGraphicsLayout>
#include <QFontMetrics>
#include <QDateTime>
@@ -29,12 +29,12 @@
QTCOMMERCIALCHART_BEGIN_NAMESPACE
-ChartDateTimeAxisY::ChartDateTimeAxisY(QDateTimeAxis *axis, QGraphicsItem* item)
+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)));
+ QObject::connect(m_axis, SIGNAL(tickCountChanged(int)), this, SLOT(handleTickCountChanged(int)));
+ QObject::connect(m_axis, SIGNAL(formatChanged(QString)), this, SLOT(handleFormatChanged(QString)));
}
ChartDateTimeAxisY::~ChartDateTimeAxisY()
@@ -59,10 +59,10 @@ QVector<qreal> ChartDateTimeAxisY::calculateLayout() const
void ChartDateTimeAxisY::updateGeometry()
{
- const QVector<qreal> &layout = ChartAxis::layout();
+ const QVector<qreal> &layout = ChartAxisElement::layout();
if (layout.isEmpty())
return;
- setLabels(createDateTimeLabels(min(),max(), layout.size(),m_axis->format()));
+ setLabels(createDateTimeLabels(min(), max(), layout.size(), m_axis->format()));
VerticalAxis::updateGeometry();
}
@@ -70,25 +70,27 @@ void ChartDateTimeAxisY::handleTickCountChanged(int tick)
{
Q_UNUSED(tick)
QGraphicsLayoutItem::updateGeometry();
- if(presenter()) presenter()->layout()->invalidate();
+ if (presenter())
+ presenter()->layout()->invalidate();
}
void ChartDateTimeAxisY::handleFormatChanged(const QString &format)
{
Q_UNUSED(format);
QGraphicsLayoutItem::updateGeometry();
- if(presenter()) presenter()->layout()->invalidate();
+ if (presenter())
+ presenter()->layout()->invalidate();
}
QSizeF ChartDateTimeAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
Q_UNUSED(constraint)
- QFontMetrics fn(font());
+ QFontMetrics fn(axis()->labelsFont());
QSizeF sh;
QSizeF base = VerticalAxis::sizeHint(which, constraint);
- QStringList ticksList = createDateTimeLabels(min(),max(),m_axis->tickCount(),m_axis->format());
+ 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.
diff --git a/src/axis/datetimeaxis/chartdatetimeaxisy_p.h b/src/axis/datetimeaxis/chartdatetimeaxisy_p.h
index 0bbe0d5a..be3adc54 100644
--- a/src/axis/datetimeaxis/chartdatetimeaxisy_p.h
+++ b/src/axis/datetimeaxis/chartdatetimeaxisy_p.h
@@ -35,7 +35,6 @@
QTCOMMERCIALCHART_BEGIN_NAMESPACE
class QDateTimeAxis;
-class ChartPresenter;
class ChartDateTimeAxisY : public VerticalAxis
{
diff --git a/src/axis/datetimeaxis/polarchartdatetimeaxisangular.cpp b/src/axis/datetimeaxis/polarchartdatetimeaxisangular.cpp
new file mode 100644
index 00000000..6b1d86af
--- /dev/null
+++ b/src/axis/datetimeaxis/polarchartdatetimeaxisangular.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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"
+
+QTCOMMERCIALCHART_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"
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/axis/datetimeaxis/polarchartdatetimeaxisangular_p.h b/src/axis/datetimeaxis/polarchartdatetimeaxisangular_p.h
new file mode 100644
index 00000000..9a7ecffe
--- /dev/null
+++ b/src/axis/datetimeaxis/polarchartdatetimeaxisangular_p.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 QtCommercial 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"
+
+QTCOMMERCIALCHART_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);
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // POLARCHARTDATETIMEAXISANGULAR_P_H
diff --git a/src/axis/datetimeaxis/polarchartdatetimeaxisradial.cpp b/src/axis/datetimeaxis/polarchartdatetimeaxisradial.cpp
new file mode 100644
index 00000000..bcd04283
--- /dev/null
+++ b/src/axis/datetimeaxis/polarchartdatetimeaxisradial.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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"
+
+QTCOMMERCIALCHART_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"
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/axis/datetimeaxis/polarchartdatetimeaxisradial_p.h b/src/axis/datetimeaxis/polarchartdatetimeaxisradial_p.h
new file mode 100644
index 00000000..e10e9194
--- /dev/null
+++ b/src/axis/datetimeaxis/polarchartdatetimeaxisradial_p.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 QtCommercial 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"
+
+QTCOMMERCIALCHART_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);
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // POLARCHARTDATETIMEAXISRADIAL_P_H
diff --git a/src/axis/datetimeaxis/qdatetimeaxis.cpp b/src/axis/datetimeaxis/qdatetimeaxis.cpp
index 3e00ee90..ed1b4a1c 100644
--- a/src/axis/datetimeaxis/qdatetimeaxis.cpp
+++ b/src/axis/datetimeaxis/qdatetimeaxis.cpp
@@ -22,6 +22,8 @@
#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>
@@ -342,11 +344,20 @@ void QDateTimeAxisPrivate::setRange(const QVariant &min, const QVariant &max)
void QDateTimeAxisPrivate::initializeGraphics(QGraphicsItem* parent)
{
Q_Q(QDateTimeAxis);
- ChartAxis* axis(0);
- if (orientation() == Qt::Vertical)
- axis = new ChartDateTimeAxisY(q,parent);
- if (orientation() == Qt::Horizontal)
- axis = new ChartDateTimeAxisX(q,parent);
+ 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);
diff --git a/src/axis/horizontalaxis.cpp b/src/axis/horizontalaxis.cpp
index 9dcd7750..7068d597 100644
--- a/src/axis/horizontalaxis.cpp
+++ b/src/axis/horizontalaxis.cpp
@@ -19,15 +19,15 @@
****************************************************************************/
#include "horizontalaxis_p.h"
-#include "qabstractaxis.h"
+#include "qabstractaxis_p.h"
#include <QFontMetrics>
#include <qmath.h>
#include <QDebug>
QTCOMMERCIALCHART_BEGIN_NAMESPACE
-HorizontalAxis::HorizontalAxis(QAbstractAxis *axis, QGraphicsItem* item , bool intervalAxis)
- : ChartAxis(axis, item, intervalAxis)
+HorizontalAxis::HorizontalAxis(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
+ : CartesianChartAxis(axis, item, intervalAxis)
{
}
@@ -37,18 +37,18 @@ HorizontalAxis::~HorizontalAxis()
void HorizontalAxis::updateGeometry()
{
- const QVector<qreal>& layout = ChartAxis::layout();
+ const QVector<qreal> &layout = ChartAxisElement::layout();
if (layout.isEmpty())
return;
QStringList labelList = labels();
- QList<QGraphicsItem *> lines = lineItems();
+ QList<QGraphicsItem *> lines = gridItems();
QList<QGraphicsItem *> labels = labelItems();
QList<QGraphicsItem *> shades = shadeItems();
- QList<QGraphicsItem *> axis = arrowItems();
- QGraphicsSimpleTextItem* title = titleItem();
+ QList<QGraphicsItem *> arrow = arrowItems();
+ QGraphicsSimpleTextItem *title = titleItem();
Q_ASSERT(labels.size() == labelList.size());
Q_ASSERT(layout.size() == labelList.size());
@@ -57,24 +57,24 @@ void HorizontalAxis::updateGeometry()
const QRectF &gridRect = gridGeometry();
//arrow
- QGraphicsLineItem *arrowItem = static_cast<QGraphicsLineItem *>(axis.at(0));
+ QGraphicsLineItem *arrowItem = static_cast<QGraphicsLineItem *>(arrow.at(0));
- if (alignment() == Qt::AlignTop)
+ if (axis()->alignment() == Qt::AlignTop)
arrowItem->setLine(gridRect.left(), axisRect.bottom(), gridRect.right(), axisRect.bottom());
- else if (alignment() == Qt::AlignBottom)
+ else if (axis()->alignment() == Qt::AlignBottom)
arrowItem->setLine(gridRect.left(), axisRect.top(), gridRect.right(), axisRect.top());
qreal width = 0;
- QFontMetrics fn(font());
+ QFontMetrics fn(axis()->labelsFont());
//title
int titlePad = 0;
QRectF titleBoundingRect;
- if (!titleText().isEmpty() && titleItem()->isVisible()) {
+ QString titleText = axis()->titleText();
+ if (!titleText.isEmpty() && titleItem()->isVisible()) {
QFontMetrics fn(title->font());
int size(0);
size = gridRect.width();
- QString titleText = this->titleText();
if (fn.boundingRect(titleText).width() > size) {
QString string = titleText + "...";
@@ -89,9 +89,9 @@ void HorizontalAxis::updateGeometry()
titleBoundingRect = title->boundingRect();
QPointF center = gridRect.center() - titleBoundingRect.center();
- if (alignment() == Qt::AlignTop) {
+ if (axis()->alignment() == Qt::AlignTop) {
title->setPos(center.x(), axisRect.top() + titlePad);
- } else if (alignment() == Qt::AlignBottom) {
+ } else if (axis()->alignment() == Qt::AlignBottom) {
title->setPos(center.x(), axisRect.bottom() - titleBoundingRect.height() - titlePad);
}
}
@@ -100,7 +100,7 @@ void HorizontalAxis::updateGeometry()
//items
QGraphicsLineItem *gridItem = static_cast<QGraphicsLineItem*>(lines.at(i));
- QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem*>(axis.at(i + 1));
+ QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem*>(arrow.at(i + 1));
QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem *>(labels.at(i));
//grid line
@@ -128,10 +128,10 @@ void HorizontalAxis::updateGeometry()
int heightDiff = rect.height() - boundingRect.height();
//ticks and label position
- if (alignment() == Qt::AlignTop) {
+ if (axis()->alignment() == Qt::AlignTop) {
labelItem->setPos(layout[i] - center.x(), axisRect.bottom() - rect.height() + (heightDiff / 2) - labelPadding());
tickItem->setLine(layout[i], axisRect.bottom(), layout[i], axisRect.bottom() - labelPadding());
- } else if (alignment() == Qt::AlignBottom) {
+ } else if (axis()->alignment() == Qt::AlignBottom) {
labelItem->setPos(layout[i] - center.x(), axisRect.top() - (heightDiff / 2) + labelPadding());
tickItem->setLine(layout[i], axisRect.top(), layout[i], axisRect.top() + labelPadding());
}
@@ -178,7 +178,7 @@ void HorizontalAxis::updateGeometry()
if (x < gridRect.left() || x > gridRect.right()) {
gridItem->setVisible(false);
tickItem->setVisible(false);
- }else{
+ } else {
gridItem->setVisible(true);
tickItem->setVisible(true);
}
@@ -200,10 +200,10 @@ void HorizontalAxis::updateGeometry()
QSizeF HorizontalAxis::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
Q_UNUSED(constraint);
- QFontMetrics fn(titleFont());
+ QFontMetrics fn(axis()->titleFont());
QSizeF sh(0,0);
- if (titleText().isEmpty() || !titleItem()->isVisible())
+ if (axis()->titleText().isEmpty() || !titleItem()->isVisible())
return sh;
switch (which) {
diff --git a/src/axis/horizontalaxis_p.h b/src/axis/horizontalaxis_p.h
index 02aa2587..23116792 100644
--- a/src/axis/horizontalaxis_p.h
+++ b/src/axis/horizontalaxis_p.h
@@ -30,14 +30,14 @@
#ifndef HORIZONTALAXIS_P_H_
#define HORIZONTALAXIS_P_H_
-#include "chartaxis_p.h"
+#include "cartesianchartaxis_p.h"
QTCOMMERCIALCHART_BEGIN_NAMESPACE
-class HorizontalAxis : public ChartAxis
+class HorizontalAxis : public CartesianChartAxis
{
public:
- HorizontalAxis(QAbstractAxis *axis, QGraphicsItem* item = 0, bool intervalAxis = false);
+ HorizontalAxis(QAbstractAxis *axis, QGraphicsItem *item = 0, bool intervalAxis = false);
~HorizontalAxis();
QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
protected:
diff --git a/src/axis/linearrowitem_p.h b/src/axis/linearrowitem_p.h
new file mode 100644
index 00000000..1adfd3bb
--- /dev/null
+++ b/src/axis/linearrowitem_p.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 QtCommercial 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>
+
+QTCOMMERCIALCHART_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;
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif /* LINEARROWITEM_P_H */
diff --git a/src/axis/logvalueaxis/chartlogvalueaxisx.cpp b/src/axis/logvalueaxis/chartlogvalueaxisx.cpp
index 3edc6d95..ac8f1f08 100644
--- a/src/axis/logvalueaxis/chartlogvalueaxisx.cpp
+++ b/src/axis/logvalueaxis/chartlogvalueaxisx.cpp
@@ -21,7 +21,7 @@
#include "chartlogvalueaxisx_p.h"
#include "chartpresenter_p.h"
#include "qlogvalueaxis.h"
-#include "chartlayout_p.h"
+#include "abstractchartlayout_p.h"
#include <QGraphicsLayout>
#include <QFontMetrics>
#include <qmath.h>
@@ -29,12 +29,12 @@
QTCOMMERCIALCHART_BEGIN_NAMESPACE
-ChartLogValueAxisX::ChartLogValueAxisX(QLogValueAxis *axis, QGraphicsItem* item)
+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)));
+ QObject::connect(m_axis, SIGNAL(baseChanged(qreal)), this, SLOT(handleBaseChanged(qreal)));
+ QObject::connect(m_axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
}
ChartLogValueAxisX::~ChartLogValueAxisX()
@@ -55,14 +55,14 @@ QVector<qreal> ChartLogValueAxisX::calculateLayout() const
const QRectF &gridRect = gridGeometry();
const qreal deltaX = gridRect.width() / qAbs(logMax - logMin);
for (int i = 0; i < tickCount; ++i)
- points[i] = (ceilEdge + i) * deltaX - leftEdge * deltaX + gridRect.left();
+ points[i] = (ceilEdge + qreal(i)) * deltaX - leftEdge * deltaX + gridRect.left();
return points;
}
void ChartLogValueAxisX::updateGeometry()
{
- const QVector<qreal>& layout = ChartAxis::layout();
+ 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()));
@@ -87,7 +87,7 @@ QSizeF ChartLogValueAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint
{
Q_UNUSED(constraint)
- QFontMetrics fn(font());
+ QFontMetrics fn(axis()->labelsFont());
QSizeF sh;
QSizeF base = HorizontalAxis::sizeHint(which, constraint);
diff --git a/src/axis/logvalueaxis/chartlogvalueaxisx_p.h b/src/axis/logvalueaxis/chartlogvalueaxisx_p.h
index c0b24a58..3017e260 100644
--- a/src/axis/logvalueaxis/chartlogvalueaxisx_p.h
+++ b/src/axis/logvalueaxis/chartlogvalueaxisx_p.h
@@ -35,20 +35,18 @@
QTCOMMERCIALCHART_BEGIN_NAMESPACE
class QLogValueAxis;
-class ChartPresenter;
class ChartLogValueAxisX : public HorizontalAxis
{
Q_OBJECT
public:
- ChartLogValueAxisX(QLogValueAxis *axis, QGraphicsItem* item);
+ ChartLogValueAxisX(QLogValueAxis *axis, QGraphicsItem *item);
~ChartLogValueAxisX();
QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const;
protected:
- void handleAxisUpdated();
QVector<qreal> calculateLayout() const;
void updateGeometry();
diff --git a/src/axis/logvalueaxis/chartlogvalueaxisy.cpp b/src/axis/logvalueaxis/chartlogvalueaxisy.cpp
index ec474e2f..42ae875c 100644
--- a/src/axis/logvalueaxis/chartlogvalueaxisy.cpp
+++ b/src/axis/logvalueaxis/chartlogvalueaxisy.cpp
@@ -21,7 +21,7 @@
#include "chartlogvalueaxisy_p.h"
#include "chartpresenter_p.h"
#include "qlogvalueaxis.h"
-#include "chartlayout_p.h"
+#include "abstractchartlayout_p.h"
#include <QGraphicsLayout>
#include <QFontMetrics>
#include <qmath.h>
@@ -29,12 +29,12 @@
QTCOMMERCIALCHART_BEGIN_NAMESPACE
-ChartLogValueAxisY::ChartLogValueAxisY(QLogValueAxis *axis, QGraphicsItem* item)
+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)));
+ QObject::connect(m_axis, SIGNAL(baseChanged(qreal)), this, SLOT(handleBaseChanged(qreal)));
+ QObject::connect(m_axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
}
ChartLogValueAxisY::~ChartLogValueAxisY()
@@ -54,7 +54,7 @@ QVector<qreal> ChartLogValueAxisY::calculateLayout() const
const QRectF &gridRect = gridGeometry();
const qreal deltaY = gridRect.height() / qAbs(logMax - logMin);
for (int i = 0; i < tickCount; ++i)
- points[i] = (ceilEdge + i) * -deltaY - leftEdge * -deltaY + gridRect.bottom();
+ points[i] = (ceilEdge + qreal(i)) * -deltaY - leftEdge * -deltaY + gridRect.bottom();
return points;
}
@@ -62,7 +62,7 @@ QVector<qreal> ChartLogValueAxisY::calculateLayout() const
void ChartLogValueAxisY::updateGeometry()
{
- const QVector<qreal> &layout = ChartAxis::layout();
+ 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()));
@@ -87,7 +87,7 @@ QSizeF ChartLogValueAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint
{
Q_UNUSED(constraint)
- QFontMetrics fn(font());
+ QFontMetrics fn(axis()->labelsFont());
QSizeF sh;
QSizeF base = VerticalAxis::sizeHint(which, constraint);
diff --git a/src/axis/logvalueaxis/chartlogvalueaxisy_p.h b/src/axis/logvalueaxis/chartlogvalueaxisy_p.h
index 8506cc29..39750976 100644
--- a/src/axis/logvalueaxis/chartlogvalueaxisy_p.h
+++ b/src/axis/logvalueaxis/chartlogvalueaxisy_p.h
@@ -35,20 +35,18 @@
QTCOMMERCIALCHART_BEGIN_NAMESPACE
class QLogValueAxis;
-class ChartPresenter;
class ChartLogValueAxisY : public VerticalAxis
{
Q_OBJECT
public:
- ChartLogValueAxisY(QLogValueAxis *axis, QGraphicsItem* item);
+ ChartLogValueAxisY(QLogValueAxis *axis, QGraphicsItem *item);
~ChartLogValueAxisY();
QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const;
protected:
- void handleAxisUpdated();
QVector<qreal> calculateLayout() const;
void updateGeometry();
diff --git a/src/axis/logvalueaxis/polarchartlogvalueaxisangular.cpp b/src/axis/logvalueaxis/polarchartlogvalueaxisangular.cpp
new file mode 100644
index 00000000..ddbd9fe6
--- /dev/null
+++ b/src/axis/logvalueaxis/polarchartlogvalueaxisangular.cpp
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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>
+
+QTCOMMERCIALCHART_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"
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/axis/logvalueaxis/polarchartlogvalueaxisangular_p.h b/src/axis/logvalueaxis/polarchartlogvalueaxisangular_p.h
new file mode 100644
index 00000000..231172aa
--- /dev/null
+++ b/src/axis/logvalueaxis/polarchartlogvalueaxisangular_p.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 QtCommercial 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"
+
+QTCOMMERCIALCHART_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);
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // POLARCHARTLOGVALUEAXISANGULAR_P_H
diff --git a/src/axis/logvalueaxis/polarchartlogvalueaxisradial.cpp b/src/axis/logvalueaxis/polarchartlogvalueaxisradial.cpp
new file mode 100644
index 00000000..d0719dbc
--- /dev/null
+++ b/src/axis/logvalueaxis/polarchartlogvalueaxisradial.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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>
+
+QTCOMMERCIALCHART_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"
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/axis/logvalueaxis/polarchartlogvalueaxisradial_p.h b/src/axis/logvalueaxis/polarchartlogvalueaxisradial_p.h
new file mode 100644
index 00000000..bc7e8982
--- /dev/null
+++ b/src/axis/logvalueaxis/polarchartlogvalueaxisradial_p.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 QtCommercial 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"
+
+QTCOMMERCIALCHART_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);
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // POLARCHARTLOGVALUEAXISRADIAL_P_H
diff --git a/src/axis/logvalueaxis/qlogvalueaxis.cpp b/src/axis/logvalueaxis/qlogvalueaxis.cpp
index 12170b8b..27896b51 100644
--- a/src/axis/logvalueaxis/qlogvalueaxis.cpp
+++ b/src/axis/logvalueaxis/qlogvalueaxis.cpp
@@ -22,6 +22,8 @@
#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>
@@ -287,14 +289,24 @@ void QLogValueAxisPrivate::setRange(qreal min, qreal max)
}
}
-void QLogValueAxisPrivate::initializeGraphics(QGraphicsItem* parent)
+void QLogValueAxisPrivate::initializeGraphics(QGraphicsItem *parent)
{
Q_Q(QLogValueAxis);
- ChartAxis* axis(0);
- if (orientation() == Qt::Vertical)
- axis = new ChartLogValueAxisY(q,parent);
- if (orientation() == Qt::Horizontal)
- axis = new ChartLogValueAxisX(q,parent);
+ 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);
@@ -304,7 +316,7 @@ void QLogValueAxisPrivate::initializeGraphics(QGraphicsItem* parent)
void QLogValueAxisPrivate::initializeDomain(AbstractDomain *domain)
{
if (orientation() == Qt::Vertical) {
- if(!qFuzzyCompare(m_max, m_min)) {
+ if (!qFuzzyCompare(m_max, m_min)) {
domain->setRangeY(m_min, m_max);
} else if ( domain->minY() > 0) {
setRange(domain->minY(), domain->maxY());
@@ -315,7 +327,7 @@ void QLogValueAxisPrivate::initializeDomain(AbstractDomain *domain)
}
}
if (orientation() == Qt::Horizontal) {
- if(!qFuzzyCompare(m_max, m_min)) {
+ if (!qFuzzyCompare(m_max, m_min)) {
domain->setRangeX(m_min, m_max);
} else if (domain->minX() > 0){
setRange(domain->minX(), domain->maxX());
diff --git a/src/axis/polarchartaxis.cpp b/src/axis/polarchartaxis.cpp
new file mode 100644
index 00000000..8bb80420
--- /dev/null
+++ b/src/axis/polarchartaxis.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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"
+
+QTCOMMERCIALCHART_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::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"
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/axis/polarchartaxis_p.h b/src/axis/polarchartaxis_p.h
new file mode 100644
index 00000000..605b8fee
--- /dev/null
+++ b/src/axis/polarchartaxis_p.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 QtCommercial 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"
+
+QTCOMMERCIALCHART_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);
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // POLARCHARTAXIS_P_H
diff --git a/src/axis/polarchartaxisangular.cpp b/src/axis/polarchartaxisangular.cpp
new file mode 100644
index 00000000..8eed1f9d
--- /dev/null
+++ b/src/axis/polarchartaxisangular.cpp
@@ -0,0 +1,428 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 <QFontMetrics>
+#include <QDebug>
+
+QTCOMMERCIALCHART_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();
+ QGraphicsSimpleTextItem *title = titleItem();
+
+ QGraphicsEllipseItem *axisLine = static_cast<QGraphicsEllipseItem *>(arrowItemList.at(0));
+ axisLine->setRect(axisGeometry());
+
+ qreal radius = axisGeometry().height() / 2.0;
+
+ QFontMetrics fn(axis()->labelsFont());
+ 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));
+ QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem *>(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(360.0, layout.at(i + 1));
+
+ // Adjust the labelCoordinate to show it if next tick is visible
+ if (nextTickVisible)
+ labelCoordinate = qMax(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) {
+ labelItem->setText(labelList.at(i));
+ const QRectF &rect = labelItem->boundingRect();
+ QPointF labelCenter = rect.center();
+ labelItem->setTransformOriginPoint(labelCenter.x(), labelCenter.y());
+ QRectF boundingRect = labelBoundingRect(fn, labelList.at(i));
+ 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()) {
+ int size(0);
+ size = axisGeometry().width();
+
+ QFontMetrics titleMetrics(axis()->titleFont());
+ if (titleMetrics.boundingRect(titleText).width() > size) {
+ QString string = titleText + "...";
+ while (titleMetrics.boundingRect(string).width() > size && string.length() > 3)
+ string.remove(string.length() - 4, 1);
+ title->setText(string);
+ } else {
+ title->setText(titleText);
+ }
+
+ QRectF titleBoundingRect;
+ titleBoundingRect = title->boundingRect();
+ QPointF titleCenter = center - titleBoundingRect.center();
+ title->setPos(titleCenter.x(), axisGeometry().top() - qreal(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
+ // TODO: need class similar to LineArrowItem for click handling?
+ QGraphicsEllipseItem *arrow = new QGraphicsEllipseItem(presenter()->rootItem());
+ arrow->setPen(axis()->linePen());
+ arrowGroup()->addToGroup(arrow);
+ }
+
+ for (int i = 0; i < count; ++i) {
+ QGraphicsLineItem *arrow = new QGraphicsLineItem(presenter()->rootItem());
+ QGraphicsLineItem *grid = new QGraphicsLineItem(presenter()->rootItem());
+ QGraphicsSimpleTextItem *label = new QGraphicsSimpleTextItem(presenter()->rootItem());
+ QGraphicsSimpleTextItem *title = titleItem();
+ arrow->setPen(axis()->linePen());
+ grid->setPen(axis()->gridLinePen());
+ label->setFont(axis()->labelsFont());
+ label->setPen(axis()->labelsPen());
+ label->setBrush(axis()->labelsBrush());
+ label->setRotation(axis()->labelsAngle());
+ title->setFont(axis()->titleFont());
+ title->setPen(axis()->titlePen());
+ title->setBrush(axis()->titleBrush());
+ title->setText(axis()->titleText());
+ 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;
+
+ int labelHeight = 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.
+ QFontMetrics fm(font);
+ 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(360.0, layout.at(i + 1));
+
+ // Adjust the labelCoordinate to show it if next tick is visible
+ if (nextTickVisible)
+ labelCoordinate = qMax(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 = labelBoundingRect(fm, labelList.at(i));
+ labelHeight = boundingRect.height();
+ QPointF labelPoint = QLineF::fromPolar(radius + tickWidth(), 90.0 - labelCoordinate).p2();
+
+ boundingRect = moveLabelToPosition(labelCoordinate, labelPoint, boundingRect);
+ if (boundingRect.isEmpty() || maxRect.intersected(boundingRect) == boundingRect) {
+ i++;
+ } else {
+ radius -= 1.0;
+ if (radius < 1.0) // safeguard
+ return 1.0;
+ }
+ }
+ }
+
+ if (!axis()->titleText().isEmpty() && axis()->isTitleVisible()) {
+ QFontMetrics titleMetrics(axis()->titleFont());
+ int titleHeight = titleMetrics.boundingRect(axis()->titleText()).height();
+ radius -= titlePadding() + (titleHeight / 2);
+ if (radius < 1.0) // safeguard
+ return 1.0;
+ }
+
+ return radius;
+}
+
+QRectF PolarChartAxisAngular::moveLabelToPosition(qreal angularCoordinate, QPointF labelPoint, QRectF labelRect) const
+{
+ // TODO use fuzzy compare for "==" cases?
+ // TODO Adjust the rect position near 0, 90, 180, and 270 angles for smoother animation?
+ 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"
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/axis/polarchartaxisangular_p.h b/src/axis/polarchartaxisangular_p.h
new file mode 100644
index 00000000..7e7b292d
--- /dev/null
+++ b/src/axis/polarchartaxisangular_p.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 QtCommercial 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"
+
+QTCOMMERCIALCHART_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;
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // POLARCHARTAXISANGULAR_P_H
diff --git a/src/axis/polarchartaxisradial.cpp b/src/axis/polarchartaxisradial.cpp
new file mode 100644
index 00000000..55923985
--- /dev/null
+++ b/src/axis/polarchartaxisradial.cpp
@@ -0,0 +1,301 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 <QFontMetrics>
+
+QTCOMMERCIALCHART_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();
+ QGraphicsSimpleTextItem* 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);
+
+ QFontMetrics fn(axis()->labelsFont());
+ 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));
+ QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem *>(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(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) {
+ labelItem->setText(labelList.at(i));
+ QRectF labelRect = labelItem->boundingRect();
+ QPointF labelCenter = labelRect.center();
+ labelItem->setTransformOriginPoint(labelCenter.x(), labelCenter.y());
+ QRectF boundingRect = labelBoundingRect(fn, labelList.at(i));
+ 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()) {
+ QFontMetrics titleMetrics(axis()->titleFont());
+ if (titleMetrics.boundingRect(titleText).width() > radius) {
+ QString string = titleText + "...";
+ while (titleMetrics.boundingRect(string).width() > radius && string.length() > 3)
+ string.remove(string.length() - 4, 1);
+ title->setText(string);
+ } else {
+ title->setText(titleText);
+ }
+
+ QRectF titleBoundingRect;
+ titleBoundingRect = title->boundingRect();
+ QPointF titleCenter = titleBoundingRect.center();
+ QPointF arrowCenter = axisLine->boundingRect().center();
+ QPointF titleCenterDiff = arrowCenter - titleCenter;
+ title->setPos(titleCenterDiff.x() - qreal(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);
+ }
+
+ for (int i = 0; i < count; ++i) {
+ QGraphicsLineItem *arrow = new QGraphicsLineItem(presenter()->rootItem());
+ QGraphicsEllipseItem *grid = new QGraphicsEllipseItem(presenter()->rootItem());
+ QGraphicsSimpleTextItem *label = new QGraphicsSimpleTextItem(presenter()->rootItem());
+ QGraphicsSimpleTextItem *title = titleItem();
+ arrow->setPen(axis()->linePen());
+ grid->setPen(axis()->gridLinePen());
+ label->setFont(axis()->labelsFont());
+ label->setPen(axis()->labelsPen());
+ label->setBrush(axis()->labelsBrush());
+ label->setRotation(axis()->labelsAngle());
+ title->setFont(axis()->titleFont());
+ title->setPen(axis()->titlePen());
+ title->setBrush(axis()->titleBrush());
+ title->setText(axis()->titleText());
+ 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"
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/axis/polarchartaxisradial_p.h b/src/axis/polarchartaxisradial_p.h
new file mode 100644
index 00000000..9874f28a
--- /dev/null
+++ b/src/axis/polarchartaxisradial_p.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 QtCommercial 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"
+
+QTCOMMERCIALCHART_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);
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // POLARCHARTAXISRADIAL_P_H
diff --git a/src/axis/qabstractaxis.cpp b/src/axis/qabstractaxis.cpp
index 60e071d6..77c89b53 100644
--- a/src/axis/qabstractaxis.cpp
+++ b/src/axis/qabstractaxis.cpp
@@ -254,11 +254,11 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE
/*!
\property QAbstractAxis::alignment
- The alignment of the axis. Either Qt::AlignLeft or Qt::AlignBottom.
+ 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. Either Qt.AlignLeft or Qt.AlignBottom.
+ The alignment of the axis. Can be Qt.AlignLeft, Qt.AlignRight, Qt.AlignBottom, or Qt.AlignTop.
*/
/*!
@@ -990,11 +990,11 @@ void QAbstractAxisPrivate::initializeGraphics(QGraphicsItem* parent)
void QAbstractAxisPrivate::initializeAnimations(QChart::AnimationOptions options)
{
- ChartAxis* axis = m_item.data();
+ ChartAxisElement *axis = m_item.data();
Q_ASSERT(axis);
- if(options.testFlag(QChart::GridAxisAnimations)) {
+ if (options.testFlag(QChart::GridAxisAnimations)) {
axis->setAnimation(new AxisAnimation(axis));
- }else{
+ } else {
axis->setAnimation(0);
}
}
diff --git a/src/axis/qabstractaxis.h b/src/axis/qabstractaxis.h
index 5ebd7974..e29325de 100644
--- a/src/axis/qabstractaxis.h
+++ b/src/axis/qabstractaxis.h
@@ -155,36 +155,37 @@ public:
Q_SIGNALS:
void visibleChanged(bool visible);
- void linePenChanged(const QPen& pen);
+ 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 labelsPenChanged(const QPen &pen);
+ void labelsBrushChanged(const QBrush &brush);
+ void labelsFontChanged(const QFont &pen);
void labelsAngleChanged(int angle);
- void gridLinePenChanged(const QPen& pen);
+ 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 titleTextChanged(const QString &title);
+ void titlePenChanged(const QPen &pen);
+ void titleBrushChanged(const QBrush &brush);
void titleVisibleChanged(bool visible);
- void titleFontChanged(const QFont& font);
+ 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);
+ void shadesPenChanged(const QPen &pen);
+ void shadesBrushChanged(const QBrush &brush);
protected:
QScopedPointer<QAbstractAxisPrivate> d_ptr;
Q_DISABLE_COPY(QAbstractAxis)
friend class ChartDataSet;
- friend class ChartAxis;
friend class ChartPresenter;
friend class ChartThemeManager;
friend class AbstractDomain;
+ friend class ChartAxisElement;
+ friend class XYChart;
};
QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/axis/qabstractaxis_p.h b/src/axis/qabstractaxis_p.h
index a284d46f..9ab993de 100644
--- a/src/axis/qabstractaxis_p.h
+++ b/src/axis/qabstractaxis_p.h
@@ -31,7 +31,7 @@
#define QABSTRACTAXIS_P_H
#include "qabstractaxis.h"
-#include "chartaxis_p.h"
+#include "chartaxiselement_p.h"
#include "qchart.h"
#include <QDebug>
@@ -59,7 +59,7 @@ public:
void setAlignment( Qt::Alignment alignment);
virtual void initializeDomain(AbstractDomain *domain) = 0;
- virtual void initializeGraphics(QGraphicsItem* parent) = 0;
+ virtual void initializeGraphics(QGraphicsItem *parent) = 0;
virtual void initializeTheme(ChartTheme* theme, bool forced = false);
virtual void initializeAnimations(QChart::AnimationOptions options);
@@ -73,7 +73,7 @@ public:
virtual qreal min() = 0;
virtual qreal max() = 0;
- ChartAxis* axisItem() { return m_item.data(); }
+ ChartAxisElement *axisItem() { return m_item.data(); }
public Q_SLOTS:
void handleRangeChanged(qreal min, qreal max);
@@ -84,7 +84,7 @@ Q_SIGNALS:
protected:
QAbstractAxis *q_ptr;
QChart *m_chart;
- QScopedPointer<ChartAxis> m_item;
+ QScopedPointer<ChartAxisElement> m_item;
private:
QList<QAbstractSeries*> m_series;
diff --git a/src/axis/valueaxis/chartvalueaxisx.cpp b/src/axis/valueaxis/chartvalueaxisx.cpp
index a084ac32..da6055f1 100644
--- a/src/axis/valueaxis/chartvalueaxisx.cpp
+++ b/src/axis/valueaxis/chartvalueaxisx.cpp
@@ -22,7 +22,7 @@
#include "qabstractaxis.h"
#include "chartpresenter_p.h"
#include "qvalueaxis.h"
-#include "chartlayout_p.h"
+#include "abstractchartlayout_p.h"
#include <QGraphicsLayout>
#include <QFontMetrics>
#include <qmath.h>
@@ -31,12 +31,12 @@
QTCOMMERCIALCHART_BEGIN_NAMESPACE
-ChartValueAxisX::ChartValueAxisX(QValueAxis *axis, QGraphicsItem* item )
+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)));
+ QObject::connect(m_axis, SIGNAL(tickCountChanged(int)), this, SLOT(handleTickCountChanged(int)));
+ QObject::connect(m_axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
}
ChartValueAxisX::~ChartValueAxisX()
@@ -61,10 +61,10 @@ QVector<qreal> ChartValueAxisX::calculateLayout() const
void ChartValueAxisX::updateGeometry()
{
- const QVector<qreal>& layout = ChartAxis::layout();
+ const QVector<qreal>& layout = ChartAxisElement::layout();
if (layout.isEmpty())
return;
- setLabels(createValueLabels(min(),max(),layout.size(),m_axis->labelFormat()));
+ setLabels(createValueLabels(min(), max(), layout.size(), m_axis->labelFormat()));
HorizontalAxis::updateGeometry();
}
@@ -86,7 +86,7 @@ QSizeF ChartValueAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) c
{
Q_UNUSED(constraint)
- QFontMetrics fn(font());
+ QFontMetrics fn(axis()->labelsFont());
QSizeF sh;
QSizeF base = HorizontalAxis::sizeHint(which, constraint);
diff --git a/src/axis/valueaxis/chartvalueaxisx_p.h b/src/axis/valueaxis/chartvalueaxisx_p.h
index e0556b60..bebfdb38 100644
--- a/src/axis/valueaxis/chartvalueaxisx_p.h
+++ b/src/axis/valueaxis/chartvalueaxisx_p.h
@@ -35,13 +35,12 @@
QTCOMMERCIALCHART_BEGIN_NAMESPACE
class QValueAxis;
-class ChartPresenter;
class ChartValueAxisX : public HorizontalAxis
{
Q_OBJECT
public:
- ChartValueAxisX(QValueAxis *axis, QGraphicsItem* item = 0);
+ ChartValueAxisX(QValueAxis *axis, QGraphicsItem *item = 0);
~ChartValueAxisX();
QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const;
diff --git a/src/axis/valueaxis/chartvalueaxisy.cpp b/src/axis/valueaxis/chartvalueaxisy.cpp
index 14b2d207..54b58242 100644
--- a/src/axis/valueaxis/chartvalueaxisy.cpp
+++ b/src/axis/valueaxis/chartvalueaxisy.cpp
@@ -22,7 +22,7 @@
#include "qabstractaxis.h"
#include "chartpresenter_p.h"
#include "qvalueaxis.h"
-#include "chartlayout_p.h"
+#include "abstractchartlayout_p.h"
#include <QGraphicsLayout>
#include <QFontMetrics>
#include <qmath.h>
@@ -30,12 +30,12 @@
QTCOMMERCIALCHART_BEGIN_NAMESPACE
-ChartValueAxisY::ChartValueAxisY(QValueAxis *axis, QGraphicsItem* item)
+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)));
+ QObject::connect(m_axis, SIGNAL(tickCountChanged(int)), this, SLOT(handleTickCountChanged(int)));
+ QObject::connect(m_axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
}
ChartValueAxisY::~ChartValueAxisY()
@@ -62,7 +62,7 @@ QVector<qreal> ChartValueAxisY::calculateLayout() const
void ChartValueAxisY::updateGeometry()
{
- const QVector<qreal> &layout = ChartAxis::layout();
+ const QVector<qreal> &layout = ChartAxisElement::layout();
if (layout.isEmpty())
return;
setLabels(createValueLabels(min(),max(),layout.size(),m_axis->labelFormat()));
@@ -87,7 +87,7 @@ QSizeF ChartValueAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) c
{
Q_UNUSED(constraint)
- QFontMetrics fn(font());
+ QFontMetrics fn(axis()->labelsFont());
QSizeF sh;
QSizeF base = VerticalAxis::sizeHint(which, constraint);
QStringList ticksList = createValueLabels(min(),max(),m_axis->tickCount(),m_axis->labelFormat());
diff --git a/src/axis/valueaxis/chartvalueaxisy_p.h b/src/axis/valueaxis/chartvalueaxisy_p.h
index 5a01b9b2..3b586698 100644
--- a/src/axis/valueaxis/chartvalueaxisy_p.h
+++ b/src/axis/valueaxis/chartvalueaxisy_p.h
@@ -35,13 +35,12 @@
QTCOMMERCIALCHART_BEGIN_NAMESPACE
class QValueAxis;
-class ChartPresenter;
class ChartValueAxisY : public VerticalAxis
{
Q_OBJECT
public:
- ChartValueAxisY(QValueAxis *axis, QGraphicsItem* item = 0);
+ ChartValueAxisY(QValueAxis *axis, QGraphicsItem *item = 0);
~ChartValueAxisY();
QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const;
diff --git a/src/axis/valueaxis/polarchartvalueaxisangular.cpp b/src/axis/valueaxis/polarchartvalueaxisangular.cpp
new file mode 100644
index 00000000..5fdbcb4b
--- /dev/null
+++ b/src/axis/valueaxis/polarchartvalueaxisangular.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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"
+
+QTCOMMERCIALCHART_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"
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/axis/valueaxis/polarchartvalueaxisangular_p.h b/src/axis/valueaxis/polarchartvalueaxisangular_p.h
new file mode 100644
index 00000000..afe5192a
--- /dev/null
+++ b/src/axis/valueaxis/polarchartvalueaxisangular_p.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 QtCommercial 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"
+
+QTCOMMERCIALCHART_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);
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // POLARCHARTVALUEAXISANGULAR_P_H
diff --git a/src/axis/valueaxis/polarchartvalueaxisradial.cpp b/src/axis/valueaxis/polarchartvalueaxisradial.cpp
new file mode 100644
index 00000000..f11e9265
--- /dev/null
+++ b/src/axis/valueaxis/polarchartvalueaxisradial.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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"
+
+QTCOMMERCIALCHART_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"
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/axis/valueaxis/polarchartvalueaxisradial_p.h b/src/axis/valueaxis/polarchartvalueaxisradial_p.h
new file mode 100644
index 00000000..f443d1dc
--- /dev/null
+++ b/src/axis/valueaxis/polarchartvalueaxisradial_p.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 QtCommercial 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"
+
+QTCOMMERCIALCHART_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);
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // POLARCHARTVALUEAXISRADIAL_P_H
diff --git a/src/axis/valueaxis/qvalueaxis.cpp b/src/axis/valueaxis/qvalueaxis.cpp
index 032fb4e1..80aa25ce 100644
--- a/src/axis/valueaxis/qvalueaxis.cpp
+++ b/src/axis/valueaxis/qvalueaxis.cpp
@@ -23,6 +23,8 @@
#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"
@@ -387,14 +389,24 @@ void QValueAxisPrivate::setRange(qreal min, qreal max)
}
}
-void QValueAxisPrivate::initializeGraphics(QGraphicsItem* parent)
+void QValueAxisPrivate::initializeGraphics(QGraphicsItem *parent)
{
Q_Q(QValueAxis);
- ChartAxis* axis(0);
- if (orientation() == Qt::Vertical)
- axis = new ChartValueAxisY(q,parent);
- if (orientation() == Qt::Horizontal)
- axis = new ChartValueAxisX(q,parent);
+ 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);
@@ -404,20 +416,16 @@ void QValueAxisPrivate::initializeGraphics(QGraphicsItem* parent)
void QValueAxisPrivate::initializeDomain(AbstractDomain *domain)
{
if (orientation() == Qt::Vertical) {
- if(!qFuzzyIsNull(m_max - m_min)) {
+ if (!qFuzzyIsNull(m_max - m_min))
domain->setRangeY(m_min, m_max);
- }
- else {
+ else
setRange(domain->minY(), domain->maxY());
- }
}
if (orientation() == Qt::Horizontal) {
- if(!qFuzzyIsNull(m_max - m_min)) {
+ if (!qFuzzyIsNull(m_max - m_min))
domain->setRangeX(m_min, m_max);
- }
- else {
+ else
setRange(domain->minX(), domain->maxX());
- }
}
}
diff --git a/src/axis/verticalaxis.cpp b/src/axis/verticalaxis.cpp
index d3c5efa6..3726359b 100644
--- a/src/axis/verticalaxis.cpp
+++ b/src/axis/verticalaxis.cpp
@@ -25,31 +25,29 @@
QTCOMMERCIALCHART_BEGIN_NAMESPACE
-VerticalAxis::VerticalAxis(QAbstractAxis *axis, QGraphicsItem* item, bool intervalAxis)
- : ChartAxis(axis, item, intervalAxis)
+VerticalAxis::VerticalAxis(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
+ : CartesianChartAxis(axis, item, intervalAxis)
{
-
}
VerticalAxis::~VerticalAxis()
{
-
}
void VerticalAxis::updateGeometry()
{
- const QVector<qreal> &layout = ChartAxis::layout();
+ const QVector<qreal> &layout = ChartAxisElement::layout();
if (layout.isEmpty())
return;
QStringList labelList = labels();
- QList<QGraphicsItem *> lines = lineItems();
+ QList<QGraphicsItem *> lines = gridItems();
QList<QGraphicsItem *> labels = labelItems();
QList<QGraphicsItem *> shades = shadeItems();
- QList<QGraphicsItem *> axis = arrowItems();
- QGraphicsSimpleTextItem* title = titleItem();
+ QList<QGraphicsItem *> arrow = arrowItems();
+ QGraphicsSimpleTextItem *title = titleItem();
Q_ASSERT(labels.size() == labelList.size());
Q_ASSERT(layout.size() == labelList.size());
@@ -61,32 +59,31 @@ void VerticalAxis::updateGeometry()
//arrow
- QGraphicsLineItem *arrowItem = static_cast<QGraphicsLineItem*>(axis.at(0));
+ QGraphicsLineItem *arrowItem = static_cast<QGraphicsLineItem*>(arrow.at(0));
//arrow position
- if (alignment()==Qt::AlignLeft)
- arrowItem->setLine( axisRect.right() , gridRect.top(), axisRect.right(), gridRect.bottom());
- else if(alignment()==Qt::AlignRight)
- arrowItem->setLine( axisRect.left() , gridRect.top(), axisRect.left(), gridRect.bottom());
+ 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());
- QFontMetrics fn(font());
+ QFontMetrics fn(axis()->labelsFont());
//title
int titlePad = 0;
QRectF titleBoundingRect;
- if (!titleText().isEmpty() && titleItem()->isVisible()) {
+ QString titleText = axis()->titleText();
+ if (!titleText.isEmpty() && titleItem()->isVisible()) {
QFontMetrics fn(title->font());
int size(0);
size = gridRect.height();
- QString titleText = this->titleText();
if (fn.boundingRect(titleText).width() > size) {
QString string = titleText + "...";
while (fn.boundingRect(string).width() > size && string.length() > 3)
- string.remove(string.length() - 4, 1);
+ string.remove(string.length() - 4, 1);
title->setText(string);
- }
- else {
+ } else {
title->setText(titleText);
}
@@ -94,10 +91,10 @@ void VerticalAxis::updateGeometry()
titleBoundingRect = title->boundingRect();
QPointF center = gridRect.center() - titleBoundingRect.center();
- if (alignment() == Qt::AlignLeft) {
+ if (axis()->alignment() == Qt::AlignLeft) {
title->setPos(axisRect.left() - titleBoundingRect.width() / 2 + titleBoundingRect.height() / 2 + titlePad, center.y());
}
- else if (alignment() == Qt::AlignRight) {
+ else if (axis()->alignment() == Qt::AlignRight) {
title->setPos(axisRect.right() - titleBoundingRect.width() / 2 - titleBoundingRect.height() / 2 - titlePad, center.y());
}
title->setTransformOriginPoint(titleBoundingRect.center());
@@ -105,14 +102,13 @@ void VerticalAxis::updateGeometry()
}
for (int i = 0; i < layout.size(); ++i) {
-
//items
QGraphicsLineItem *gridItem = static_cast<QGraphicsLineItem *>(lines.at(i));
- QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem *>(axis.at(i + 1));
+ QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem *>(arrow.at(i + 1));
QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem *>(labels.at(i));
//grid line
- gridItem->setLine(gridRect.left() , layout[i], gridRect.right(), layout[i]);
+ gridItem->setLine(gridRect.left(), layout[i], gridRect.right(), layout[i]);
//label text wrapping
QString text = labelList.at(i);
@@ -138,10 +134,10 @@ void VerticalAxis::updateGeometry()
int widthDiff = rect.width() - boundingRect.width();
//ticks and label position
- if (alignment() == Qt::AlignLeft) {
+ if (axis()->alignment() == Qt::AlignLeft) {
labelItem->setPos(axisRect.right() - rect.width() + (widthDiff / 2) - labelPadding(), layout[i] - center.y());
tickItem->setLine(axisRect.right() - labelPadding(), layout[i], axisRect.right(), layout[i]);
- } else if (alignment() == Qt::AlignRight) {
+ } else if (axis()->alignment() == Qt::AlignRight) {
labelItem->setPos(axisRect.left() + labelPadding() - (widthDiff / 2), layout[i] - center.y());
tickItem->setLine(axisRect.left(), layout[i], axisRect.left() + labelPadding(), layout[i]);
}
@@ -202,7 +198,7 @@ void VerticalAxis::updateGeometry()
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 = static_cast<QGraphicsLineItem*>(lines.at(layout.size() + 1));
gridLine->setLine(gridRect.left(), gridRect.bottom(), gridRect.right(), gridRect.bottom());
gridLine->setVisible(true);
}
@@ -212,10 +208,10 @@ QSizeF VerticalAxis::sizeHint(Qt::SizeHint which, const QSizeF &constraint) cons
{
Q_UNUSED(constraint);
- QFontMetrics fn(titleFont());
- QSizeF sh(0,0);
+ QFontMetrics fn(axis()->titleFont());
+ QSizeF sh(0, 0);
- if (titleText().isEmpty() || !titleItem()->isVisible())
+ if (axis()->titleText().isEmpty() || !titleItem()->isVisible())
return sh;
switch (which) {
diff --git a/src/axis/verticalaxis_p.h b/src/axis/verticalaxis_p.h
index 4d186c44..159bba63 100644
--- a/src/axis/verticalaxis_p.h
+++ b/src/axis/verticalaxis_p.h
@@ -30,14 +30,14 @@
#ifndef VERTICALAXIS_P_H_
#define VERTICALAXIS_P_H_
-#include "chartaxis_p.h"
+#include "cartesianchartaxis_p.h"
QTCOMMERCIALCHART_BEGIN_NAMESPACE
-class VerticalAxis : public ChartAxis
+class VerticalAxis : public CartesianChartAxis
{
public:
- VerticalAxis(QAbstractAxis *axis, QGraphicsItem* item = 0, bool intervalAxis = false);
+ VerticalAxis(QAbstractAxis *axis, QGraphicsItem *item = 0, bool intervalAxis = false);
~VerticalAxis();
QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
protected:
diff --git a/src/chartdataset.cpp b/src/chartdataset.cpp
index d5401663..4d7e1a09 100644
--- a/src/chartdataset.cpp
+++ b/src/chartdataset.cpp
@@ -33,9 +33,13 @@
#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"
@@ -66,6 +70,20 @@ void ChartDataSet::addSeries(QAbstractSeries *series)
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);
@@ -78,7 +96,7 @@ void ChartDataSet::addSeries(QAbstractSeries *series)
/*
* This method adds axis to chartdataset, axis ownership is taken from caller.
*/
-void ChartDataSet::addAxis(QAbstractAxis *axis,Qt::Alignment aligment)
+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.");
@@ -87,12 +105,25 @@ void ChartDataSet::addAxis(QAbstractAxis *axis,Qt::Alignment aligment)
axis->d_ptr->setAlignment(aligment);
- if(!axis->alignment()) {
- qWarning()<< QObject::tr("No alignment specified !");
+ if (!axis->alignment()) {
+ qWarning() << QObject::tr("No alignment specified !");
return;
};
- QSharedPointer<AbstractDomain> domain(new XYDomain());
+ AbstractDomain *newDomain;
+ if (m_chart && m_chart->chartType() == QChart::ChartTypePolar) {
+ foreach (QAbstractAxis *existingAxis, axes()) {
+ if (existingAxis->orientation() == axis->orientation()) {
+ qWarning() << QObject::tr("Cannot add multiple axes of same orientation to a polar chart!");
+ return;
+ }
+ }
+ newDomain = new XYPolarDomain();
+ } else {
+ newDomain = new XYDomain();
+ }
+
+ QSharedPointer<AbstractDomain> domain(newDomain);
axis->d_ptr->initializeDomain(domain.data());
axis->setParent(this);
@@ -122,6 +153,8 @@ void ChartDataSet::removeSeries(QAbstractSeries *series)
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;
}
@@ -152,13 +185,13 @@ void ChartDataSet::removeAxis(QAbstractAxis *axis)
/*
* This method attaches axis to series, return true if success.
*/
-bool ChartDataSet::attachAxis(QAbstractSeries* series,QAbstractAxis *axis)
+bool ChartDataSet::attachAxis(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;
+ 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.");
@@ -180,25 +213,42 @@ bool ChartDataSet::attachAxis(QAbstractSeries* series,QAbstractAxis *axis)
return false;
}
- AbstractDomain* domain = series->d_ptr->domain();
+ AbstractDomain *domain = series->d_ptr->domain();
AbstractDomain::DomainType type = selectDomain(attachedAxisList<<axis);
- if(type == AbstractDomain::UndefinedDomain) return false;
+ if (type == AbstractDomain::UndefinedDomain) return false;
- if(domain->type()!=type){
+ if (domain->type() != type) {
AbstractDomain *old = domain;
- domain = createDomain(type);
+ 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)
+ return false;
+
+ if (!domain->attachAxis(axis))
+ 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){
+ 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();
@@ -210,6 +260,9 @@ bool ChartDataSet::attachAxis(QAbstractSeries* series,QAbstractAxis *axis)
series->d_ptr->initializeAxes();
axis->d_ptr->initializeDomain(domain);
+ foreach (AbstractDomain *blockedDomain, blockedDomains)
+ blockedDomain->blockRangeSignals(false);
+
return true;
}
@@ -327,12 +380,12 @@ void ChartDataSet::findMinMaxForSeries(QList<QAbstractSeries *> series,Qt::Orien
{
Q_ASSERT(!series.isEmpty());
- AbstractDomain* domain = series.first()->d_ptr->domain();
+ 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();
+ 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);
}
@@ -437,7 +490,7 @@ QPointF ChartDataSet::mapToPosition(const QPointF &value, QAbstractSeries *serie
return point;
}
-QList<QAbstractAxis*> ChartDataSet::axes() const
+QList<QAbstractAxis *> ChartDataSet::axes() const
{
return m_axisList;
}
@@ -447,7 +500,7 @@ QList<QAbstractSeries *> ChartDataSet::series() const
return m_seriesList;
}
-AbstractDomain::DomainType ChartDataSet::selectDomain(QList<QAbstractAxis*> axes)
+AbstractDomain::DomainType ChartDataSet::selectDomain(QList<QAbstractAxis *> axes)
{
enum Type {
Undefined = 0,
@@ -458,75 +511,95 @@ AbstractDomain::DomainType ChartDataSet::selectDomain(QList<QAbstractAxis*> axes
int horizontal(Undefined);
int vertical(Undefined);
- foreach(QAbstractAxis* axis, axes)
- {
- switch(axis->type()) {
- case QAbstractAxis::AxisTypeLogValue:
-
- if(axis->orientation()==Qt::Horizontal) {
- horizontal|=LogType;
- }
- if(axis->orientation()==Qt::Vertical) {
- vertical|=LogType;
- }
+ // 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;
- }
+ 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";
+ default:
+ qWarning() << "Undefined type";
break;
}
}
- if(vertical==Undefined) vertical=ValueType;
- if(horizontal==Undefined) horizontal=ValueType;
+ if (vertical == Undefined)
+ vertical = ValueType;
+ if (horizontal == Undefined)
+ horizontal = ValueType;
- if(vertical==ValueType && horizontal== ValueType) {
- return AbstractDomain::XYDomain;
+ 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) {
- return AbstractDomain::XLogYDomain;
+ if (vertical == LogType && horizontal == ValueType) {
+ if (chartType == QChart::ChartTypeCartesian)
+ return AbstractDomain::XLogYDomain;
+ if (chartType == QChart::ChartTypePolar)
+ return AbstractDomain::XLogYPolarDomain;
}
- if(vertical==ValueType && horizontal== LogType) {
- return AbstractDomain::LogXYDomain;
+ 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) {
- return AbstractDomain::LogXLogYDomain;
+ 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();
- default:
- return 0;
- }
+ 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"
diff --git a/src/chartpresenter.cpp b/src/chartpresenter.cpp
index 8194f084..f8242aac 100644
--- a/src/chartpresenter.cpp
+++ b/src/chartpresenter.cpp
@@ -27,24 +27,28 @@
#include "chartanimation_p.h"
#include "qabstractseries_p.h"
#include "qareaseries.h"
-#include "chartaxis_p.h"
+#include "chartaxiselement_p.h"
#include "chartbackground_p.h"
-#include "chartlayout_p.h"
+#include "cartesianchartlayout_p.h"
+#include "polarchartlayout_p.h"
#include "charttitle_p.h"
#include <QTimer>
QTCOMMERCIALCHART_BEGIN_NAMESPACE
-ChartPresenter::ChartPresenter(QChart *chart)
+ChartPresenter::ChartPresenter(QChart *chart, QChart::ChartType type)
: QObject(chart),
m_chart(chart),
m_options(QChart::NoAnimation),
m_state(ShowState),
- m_layout(new ChartLayout(this)),
m_background(0),
m_title(0)
{
-
+ 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()
@@ -54,25 +58,25 @@ 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());
- }
- }
+ 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;
+ return m_rect;
}
void ChartPresenter::handleAxisAdded(QAbstractAxis *axis)
{
axis->d_ptr->initializeGraphics(rootItem());
axis->d_ptr->initializeAnimations(m_options);
- ChartAxis *item = axis->d_ptr->axisItem();
+ ChartAxisElement *item = axis->d_ptr->axisItem();
item->setPresenter(this);
item->setThemeManager(m_chart->d_ptr->m_themeManager);
m_axisItems<<item;
@@ -82,7 +86,7 @@ void ChartPresenter::handleAxisAdded(QAbstractAxis *axis)
void ChartPresenter::handleAxisRemoved(QAbstractAxis *axis)
{
- ChartAxis *item = axis->d_ptr->m_item.take();
+ ChartAxisElement *item = axis->d_ptr->m_item.take();
item->hide();
item->disconnect();
item->deleteLater();
@@ -275,7 +279,7 @@ bool ChartPresenter::isBackgroundDropShadowEnabled() const
}
-ChartLayout *ChartPresenter::layout()
+AbstractChartLayout *ChartPresenter::layout()
{
return m_layout;
}
@@ -295,7 +299,7 @@ ChartBackground *ChartPresenter::backgroundElement()
return m_background;
}
-QList<ChartAxis *> ChartPresenter::axisItems() const
+QList<ChartAxisElement *> ChartPresenter::axisItems() const
{
return m_axisItems;
}
diff --git a/src/chartpresenter_p.h b/src/chartpresenter_p.h
index 9f1c8b89..19bc5c42 100644
--- a/src/chartpresenter_p.h
+++ b/src/chartpresenter_p.h
@@ -42,12 +42,12 @@ class AxisItem;
class QAbstractSeries;
class ChartDataSet;
class AbstractDomain;
-class ChartAxis;
+class ChartAxisElement;
class ChartAnimator;
class ChartBackground;
class ChartTitle;
class ChartAnimation;
-class ChartLayout;
+class AbstractChartLayout;
class ChartPresenter: public QObject
{
@@ -78,7 +78,7 @@ public:
ZoomOutState
};
- ChartPresenter(QChart *chart);
+ ChartPresenter(QChart *chart, QChart::ChartType type);
virtual ~ChartPresenter();
@@ -88,12 +88,9 @@ public:
QGraphicsItem *rootItem(){ return m_chart; }
ChartBackground *backgroundElement();
ChartTitle *titleElement();
- QList<ChartAxis *> axisItems() const;
+ QList<ChartAxisElement *> axisItems() const;
QList<ChartItem *> chartItems() const;
- ChartItem* chartElement(QAbstractSeries* series) const;
- ChartAxis* chartElement(QAbstractAxis* axis) const;
-
QLegend *legend();
void setBackgroundBrush(const QBrush &brush);
@@ -128,7 +125,9 @@ public:
void setState(State state,QPointF point);
State state() const { return m_state; }
QPointF statePoint() const { return m_statePoint; }
- ChartLayout *layout();
+ AbstractChartLayout *layout();
+
+ QChart::ChartType chartType() const { return m_chart->chartType(); }
private:
void createBackgroundItem();
@@ -149,14 +148,14 @@ Q_SIGNALS:
private:
QChart *m_chart;
QList<ChartItem *> m_chartItems;
- QList<ChartAxis *> m_axisItems;
+ QList<ChartAxisElement *> m_axisItems;
QList<QAbstractSeries *> m_series;
QList<QAbstractAxis *> m_axes;
QChart::AnimationOptions m_options;
State m_state;
QPointF m_statePoint;
QList<ChartAnimation *> m_animations;
- ChartLayout *m_layout;
+ AbstractChartLayout *m_layout;
ChartBackground *m_background;
ChartTitle *m_title;
QRectF m_rect;
diff --git a/src/domain/abstractdomain.cpp b/src/domain/abstractdomain.cpp
index bcaa5164..277472d1 100644
--- a/src/domain/abstractdomain.cpp
+++ b/src/domain/abstractdomain.cpp
@@ -38,7 +38,7 @@ AbstractDomain::~AbstractDomain()
{
}
-void AbstractDomain::setSize(const QSizeF& size)
+void AbstractDomain::setSize(const QSizeF &size)
{
if(m_size!=size)
{
@@ -122,9 +122,9 @@ void AbstractDomain::handleHorizontalAxisRangeChanged(qreal min, qreal max)
void AbstractDomain::blockRangeSignals(bool block)
{
- if(m_signalsBlocked!=block){
+ if (m_signalsBlocked!=block) {
m_signalsBlocked=block;
- if(!block) {
+ if (!block) {
emit rangeHorizontalChanged(m_minX,m_maxX);
emit rangeVerticalChanged(m_minY,m_maxY);
}
@@ -165,14 +165,14 @@ qreal AbstractDomain::niceNumber(qreal x, bool ceiling)
return q * z;
}
-bool AbstractDomain::attachAxis(QAbstractAxis* axis)
+bool AbstractDomain::attachAxis(QAbstractAxis *axis)
{
- if(axis->orientation()==Qt::Vertical) {
+ 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) {
+ 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)));
}
@@ -180,14 +180,14 @@ bool AbstractDomain::attachAxis(QAbstractAxis* axis)
return true;
}
-bool AbstractDomain::detachAxis(QAbstractAxis* axis)
+bool AbstractDomain::detachAxis(QAbstractAxis *axis)
{
- if(axis->orientation()==Qt::Vertical) {
+ 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) {
+ 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)));
}
@@ -199,10 +199,10 @@ bool AbstractDomain::detachAxis(QAbstractAxis* axis)
bool QTCOMMERCIALCHART_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));
+ 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));
}
@@ -218,6 +218,17 @@ QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const AbstractDo
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"
QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/domain/abstractdomain_p.h b/src/domain/abstractdomain_p.h
index 907cccff..cf7c2bac 100644
--- a/src/domain/abstractdomain_p.h
+++ b/src/domain/abstractdomain_p.h
@@ -42,12 +42,20 @@ class QTCOMMERCIALCHART_AUTOTEST_EXPORT AbstractDomain: public QObject
{
Q_OBJECT
public:
- enum DomainType { UndefinedDomain, XYDomain, XLogYDomain, LogXYDomain, LogXLogYDomain };
+ enum DomainType { UndefinedDomain,
+ XYDomain,
+ XLogYDomain,
+ LogXYDomain,
+ LogXLogYDomain,
+ XYPolarDomain,
+ XLogYPolarDomain,
+ LogXYPolarDomain,
+ LogXLogYPolarDomain };
public:
explicit AbstractDomain(QObject *object = 0);
virtual ~AbstractDomain();
- void setSize(const QSizeF& size);
+ virtual void setSize(const QSizeF &size);
QSizeF size() const;
virtual DomainType type() = 0;
@@ -82,10 +90,10 @@ public:
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 QVector<QPointF> calculateGeometryPoints(const QList<QPointF> &vector) const = 0;
- virtual bool attachAxis(QAbstractAxis* axis);
- virtual bool detachAxis(QAbstractAxis* axis);
+ 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);
@@ -100,6 +108,8 @@ public Q_SLOTS:
void handleHorizontalAxisRangeChanged(qreal min,qreal max);
protected:
+ void adjustLogDomainRanges(qreal &min, qreal &max);
+
qreal m_minX;
qreal m_maxX;
qreal m_minY;
diff --git a/src/domain/domain.pri b/src/domain/domain.pri
index 1d5823d1..ab4fcfce 100644
--- a/src/domain/domain.pri
+++ b/src/domain/domain.pri
@@ -5,14 +5,24 @@ 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/logxlogydomain.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/logxlogydomain_p.h
+ $$PWD/logxypolardomain_p.h \
+ $$PWD/logxlogydomain_p.h \
+ $$PWD/logxlogypolardomain_p.h
diff --git a/src/domain/logxlogydomain.cpp b/src/domain/logxlogydomain.cpp
index 7032d137..adb9bc1d 100644
--- a/src/domain/logxlogydomain.cpp
+++ b/src/domain/logxlogydomain.cpp
@@ -45,6 +45,9 @@ 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;
@@ -65,7 +68,7 @@ void LogXLogYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
- if(!m_signalsBlocked)
+ if (!m_signalsBlocked)
emit rangeVerticalChanged(m_minY, m_maxY);
}
@@ -141,13 +144,13 @@ QPointF LogXLogYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) c
ok = true;
return QPointF(x, y);
} else {
- qWarning() << "Logarithm of negative value is undefined. Empty layout returned";
+ qWarning() << "Logarithm of negative value is undefined. Empty layout returned.";
ok = false;
return QPointF();
}
}
-QVector<QPointF> LogXLogYDomain::calculateGeometryPoints(const QList<QPointF>& vector) const
+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);
@@ -162,7 +165,7 @@ QVector<QPointF> LogXLogYDomain::calculateGeometryPoints(const QList<QPointF>& v
result[i].setX(x);
result[i].setY(y);
} else {
- qWarning() << "Logarithm of negative value is undefined. Empty layout returned";
+ qWarning() << "Logarithm of negative value is undefined. Empty layout returned.";
return QVector<QPointF>();
}
}
@@ -178,17 +181,17 @@ QPointF LogXLogYDomain::calculateDomainPoint(const QPointF &point) const
return QPointF(x, y);
}
-bool LogXLogYDomain::attachAxis(QAbstractAxis* axis)
+bool LogXLogYDomain::attachAxis(QAbstractAxis *axis)
{
AbstractDomain::attachAxis(axis);
QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
- if(logAxis && logAxis->orientation()==Qt::Vertical) {
+ 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) {
+ if (logAxis && logAxis->orientation() == Qt::Horizontal) {
QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
handleHorizontalAxisBaseChanged(logAxis->base());
}
@@ -196,15 +199,15 @@ bool LogXLogYDomain::attachAxis(QAbstractAxis* axis)
return true;
}
-bool LogXLogYDomain::detachAxis(QAbstractAxis* axis)
+bool LogXLogYDomain::detachAxis(QAbstractAxis *axis)
{
AbstractDomain::detachAxis(axis);
QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
- if(logAxis && logAxis->orientation()==Qt::Vertical)
+ if (logAxis && logAxis->orientation() == Qt::Vertical)
QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
- if(logAxis && logAxis->orientation()==Qt::Horizontal)
+ if (logAxis && logAxis->orientation() == Qt::Horizontal)
QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
return true;
@@ -234,10 +237,10 @@ void LogXLogYDomain::handleHorizontalAxisBaseChanged(qreal baseX)
bool QTCOMMERCIALCHART_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));
+ 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));
}
diff --git a/src/domain/logxlogydomain_p.h b/src/domain/logxlogydomain_p.h
index 2d604163..014bf803 100644
--- a/src/domain/logxlogydomain_p.h
+++ b/src/domain/logxlogydomain_p.h
@@ -56,10 +56,10 @@ public:
QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const;
QPointF calculateDomainPoint(const QPointF &point) const;
- QVector<QPointF> calculateGeometryPoints(const QList<QPointF>& vector) const;
+ QVector<QPointF> calculateGeometryPoints(const QList<QPointF> &vector) const;
- bool attachAxis(QAbstractAxis* axis);
- bool detachAxis(QAbstractAxis* axis);
+ bool attachAxis(QAbstractAxis *axis);
+ bool detachAxis(QAbstractAxis *axis);
public Q_SLOTS:
void handleVerticalAxisBaseChanged(qreal baseY);
diff --git a/src/domain/logxlogypolardomain.cpp b/src/domain/logxlogypolardomain.cpp
new file mode 100644
index 00000000..a193ce11
--- /dev/null
+++ b/src/domain/logxlogypolardomain.cpp
@@ -0,0 +1,267 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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>
+
+QTCOMMERCIALCHART_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)
+{
+ 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)
+{
+ 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 QTCOMMERCIALCHART_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 QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const LogXLogYPolarDomain &domain1, const LogXLogYPolarDomain &domain2)
+{
+ return !(domain1 == domain2);
+}
+
+
+QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXLogYPolarDomain &domain)
+{
+ dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
+ return dbg.maybeSpace();
+}
+
+#include "moc_logxlogypolardomain_p.cpp"
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/domain/logxlogypolardomain_p.h b/src/domain/logxlogypolardomain_p.h
new file mode 100644
index 00000000..106f58a6
--- /dev/null
+++ b/src/domain/logxlogypolardomain_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 QtCommercial 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>
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+class QTCOMMERCIALCHART_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 QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const LogXLogYPolarDomain &domain1, const LogXLogYPolarDomain &domain2);
+ friend bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const LogXLogYPolarDomain &domain1, const LogXLogYPolarDomain &domain2);
+ friend QDebug QTCOMMERCIALCHART_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;
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // LOGXLOGYPOLARDOMAIN_H
diff --git a/src/domain/logxydomain.cpp b/src/domain/logxydomain.cpp
index ffa739bf..da6e210a 100644
--- a/src/domain/logxydomain.cpp
+++ b/src/domain/logxydomain.cpp
@@ -42,6 +42,8 @@ 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;
@@ -58,7 +60,7 @@ void LogXYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
m_minY = minY;
m_maxY = maxY;
axisYChanged = true;
- if(!m_signalsBlocked)
+ if (!m_signalsBlocked)
emit rangeVerticalChanged(m_minY, m_maxY);
}
@@ -137,13 +139,13 @@ QPointF LogXYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) cons
ok = true;
return QPointF(x, y);
} else {
- qWarning() << "Logarithm of negative value is undefined. Empty layout returned";
+ qWarning() << "Logarithm of negative value is undefined. Empty layout returned.";
ok = false;
return QPointF();
}
}
-QVector<QPointF> LogXYDomain::calculateGeometryPoints(const QList<QPointF>& vector) const
+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);
@@ -158,7 +160,7 @@ QVector<QPointF> LogXYDomain::calculateGeometryPoints(const QList<QPointF>& vect
result[i].setX(x);
result[i].setY(y);
} else {
- qWarning() << "Logarithm of negative value is undefined. Empty layout returned";
+ qWarning() << "Logarithm of negative value is undefined. Empty layout returned.";
return QVector<QPointF>();
}
}
@@ -174,12 +176,12 @@ QPointF LogXYDomain::calculateDomainPoint(const QPointF &point) const
return QPointF(x, y);
}
-bool LogXYDomain::attachAxis(QAbstractAxis* axis)
+bool LogXYDomain::attachAxis(QAbstractAxis *axis)
{
AbstractDomain::attachAxis(axis);
QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
- if(logAxis && logAxis->orientation()==Qt::Horizontal) {
+ if (logAxis && logAxis->orientation() == Qt::Horizontal) {
QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
handleHorizontalAxisBaseChanged(logAxis->base());
}
@@ -187,12 +189,12 @@ bool LogXYDomain::attachAxis(QAbstractAxis* axis)
return true;
}
-bool LogXYDomain::detachAxis(QAbstractAxis* axis)
+bool LogXYDomain::detachAxis(QAbstractAxis *axis)
{
AbstractDomain::detachAxis(axis);
QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
- if(logAxis && logAxis->orientation()==Qt::Horizontal)
+ if (logAxis && logAxis->orientation() == Qt::Horizontal)
QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
return true;
@@ -212,10 +214,10 @@ void LogXYDomain::handleHorizontalAxisBaseChanged(qreal baseX)
bool QTCOMMERCIALCHART_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));
+ 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));
}
diff --git a/src/domain/logxydomain_p.h b/src/domain/logxydomain_p.h
index cbc59e18..2f0e49ea 100644
--- a/src/domain/logxydomain_p.h
+++ b/src/domain/logxydomain_p.h
@@ -56,10 +56,10 @@ public:
QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const;
QPointF calculateDomainPoint(const QPointF &point) const;
- QVector<QPointF> calculateGeometryPoints(const QList<QPointF>& vector) const;
+ QVector<QPointF> calculateGeometryPoints(const QList<QPointF> &vector) const;
- bool attachAxis(QAbstractAxis* axis);
- bool detachAxis(QAbstractAxis* axis);
+ bool attachAxis(QAbstractAxis *axis);
+ bool detachAxis(QAbstractAxis *axis);
public Q_SLOTS:
void handleHorizontalAxisBaseChanged(qreal baseX);
diff --git a/src/domain/logxypolardomain.cpp b/src/domain/logxypolardomain.cpp
new file mode 100644
index 00000000..b08f6a04
--- /dev/null
+++ b/src/domain/logxypolardomain.cpp
@@ -0,0 +1,236 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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>
+
+QTCOMMERCIALCHART_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)
+{
+ 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)
+{
+ 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 QTCOMMERCIALCHART_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 QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const LogXYPolarDomain &domain1, const LogXYPolarDomain &domain2)
+{
+ return !(domain1 == domain2);
+}
+
+
+QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXYPolarDomain &domain)
+{
+ dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
+ return dbg.maybeSpace();
+}
+
+#include "moc_logxypolardomain_p.cpp"
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/domain/logxypolardomain_p.h b/src/domain/logxypolardomain_p.h
new file mode 100644
index 00000000..c7468ab9
--- /dev/null
+++ b/src/domain/logxypolardomain_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 QtCommercial 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>
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+class QTCOMMERCIALCHART_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 QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const LogXYPolarDomain &domain1, const LogXYPolarDomain &domain2);
+ friend bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const LogXYPolarDomain &domain1, const LogXYPolarDomain &domain2);
+ friend QDebug QTCOMMERCIALCHART_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;
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // LOGXYPOLARDOMAIN_H
diff --git a/src/domain/polardomain.cpp b/src/domain/polardomain.cpp
new file mode 100644
index 00000000..d9a9d48f
--- /dev/null
+++ b/src/domain/polardomain.cpp
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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>
+
+QTCOMMERCIALCHART_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;
+ m_center = QPointF(m_radius, m_radius);
+ AbstractDomain::setSize(size);
+}
+
+QPointF PolarDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
+{
+ qreal r;
+ 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;
+ qreal a;
+
+ 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"
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/domain/polardomain_p.h b/src/domain/polardomain_p.h
new file mode 100644
index 00000000..81e921d5
--- /dev/null
+++ b/src/domain/polardomain_p.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 QtCommercial 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>
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+class QTCOMMERCIALCHART_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;
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // POLARDOMAIN_H
diff --git a/src/domain/xlogydomain.cpp b/src/domain/xlogydomain.cpp
index 42e7edae..850eb99b 100644
--- a/src/domain/xlogydomain.cpp
+++ b/src/domain/xlogydomain.cpp
@@ -42,6 +42,8 @@ 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;
@@ -58,7 +60,7 @@ void XLogYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
- if(!m_signalsBlocked)
+ if (!m_signalsBlocked)
emit rangeVerticalChanged(m_minY, m_maxY);
}
@@ -136,13 +138,13 @@ QPointF XLogYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) cons
ok = true;
return QPointF(x, y);
} else {
- qWarning() << "Logarithm of negative value is undefined. Empty layout returned";
+ qWarning() << "Logarithm of negative value is undefined. Empty layout returned.";
ok = false;
return QPointF();
}
}
-QVector<QPointF> XLogYDomain::calculateGeometryPoints(const QList<QPointF>& vector) const
+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);
@@ -157,7 +159,7 @@ QVector<QPointF> XLogYDomain::calculateGeometryPoints(const QList<QPointF>& vect
result[i].setX(x);
result[i].setY(y);
} else {
- qWarning() << "Logarithm of negative value is undefined. Empty layout returned";
+ qWarning() << "Logarithm of negative value is undefined. Empty layout returned.";
return QVector<QPointF>();
}
}
@@ -173,22 +175,22 @@ QPointF XLogYDomain::calculateDomainPoint(const QPointF &point) const
return QPointF(x, y);
}
-bool XLogYDomain::attachAxis(QAbstractAxis* axis)
+bool XLogYDomain::attachAxis(QAbstractAxis *axis)
{
QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
- if(logAxis && logAxis->orientation()==Qt::Vertical){
+ 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)
+bool XLogYDomain::detachAxis(QAbstractAxis *axis)
{
QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
- if(logAxis && logAxis->orientation()==Qt::Vertical)
+ if (logAxis && logAxis->orientation() == Qt::Vertical)
QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
return AbstractDomain::detachAxis(axis);
@@ -208,10 +210,10 @@ void XLogYDomain::handleVerticalAxisBaseChanged(qreal baseY)
bool QTCOMMERCIALCHART_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));
+ 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));
}
diff --git a/src/domain/xlogydomain_p.h b/src/domain/xlogydomain_p.h
index 88dd989f..68ac6f81 100644
--- a/src/domain/xlogydomain_p.h
+++ b/src/domain/xlogydomain_p.h
@@ -56,10 +56,10 @@ public:
QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const;
QPointF calculateDomainPoint(const QPointF &point) const;
- QVector<QPointF> calculateGeometryPoints(const QList<QPointF>& vector) const;
+ QVector<QPointF> calculateGeometryPoints(const QList<QPointF> &vector) const;
- bool attachAxis(QAbstractAxis* axis);
- bool detachAxis(QAbstractAxis* axis);
+ bool attachAxis(QAbstractAxis *axis);
+ bool detachAxis(QAbstractAxis *axis);
public Q_SLOTS:
void handleVerticalAxisBaseChanged(qreal baseY);
diff --git a/src/domain/xlogypolardomain.cpp b/src/domain/xlogypolardomain.cpp
new file mode 100644
index 00000000..730a9dcd
--- /dev/null
+++ b/src/domain/xlogypolardomain.cpp
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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>
+
+QTCOMMERCIALCHART_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)
+{
+ 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)
+{
+ 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 QTCOMMERCIALCHART_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 QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const XLogYPolarDomain &domain1, const XLogYPolarDomain &domain2)
+{
+ return !(domain1 == domain2);
+}
+
+
+QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const XLogYPolarDomain &domain)
+{
+ dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
+ return dbg.maybeSpace();
+}
+
+#include "moc_xlogypolardomain_p.cpp"
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/domain/xlogypolardomain_p.h b/src/domain/xlogypolardomain_p.h
new file mode 100644
index 00000000..3c3a45b7
--- /dev/null
+++ b/src/domain/xlogypolardomain_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 QtCommercial 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>
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+class QTCOMMERCIALCHART_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 QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const XLogYPolarDomain &domain1, const XLogYPolarDomain &domain2);
+ friend bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const XLogYPolarDomain &domain1, const XLogYPolarDomain &domain2);
+ friend QDebug QTCOMMERCIALCHART_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;
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // XLOGYPOLARDOMAIN_H
diff --git a/src/domain/xydomain.cpp b/src/domain/xydomain.cpp
index 26f82a15..8ac1f0a0 100644
--- a/src/domain/xydomain.cpp
+++ b/src/domain/xydomain.cpp
@@ -126,7 +126,7 @@ QPointF XYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
return QPointF(x, y);
}
-QVector<QPointF> XYDomain::calculateGeometryPoints(const QList<QPointF>& vector) const
+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);
@@ -156,10 +156,10 @@ QPointF XYDomain::calculateDomainPoint(const QPointF &point) const
bool QTCOMMERCIALCHART_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));
+ 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));
}
diff --git a/src/domain/xydomain_p.h b/src/domain/xydomain_p.h
index 0a990388..657377b2 100644
--- a/src/domain/xydomain_p.h
+++ b/src/domain/xydomain_p.h
@@ -56,7 +56,7 @@ public:
QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const;
QPointF calculateDomainPoint(const QPointF &point) const;
- QVector<QPointF> calculateGeometryPoints(const QList<QPointF>& vector) const;
+ QVector<QPointF> calculateGeometryPoints(const QList<QPointF> &vector) const;
};
QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/domain/xypolardomain.cpp b/src/domain/xypolardomain.cpp
new file mode 100644
index 00000000..e9471293
--- /dev/null
+++ b/src/domain/xypolardomain.cpp
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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>
+
+QTCOMMERCIALCHART_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)
+{
+ 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)
+{
+ 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 QTCOMMERCIALCHART_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 QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const XYPolarDomain &domain1, const XYPolarDomain &domain2)
+{
+ return !(domain1 == domain2);
+}
+
+
+QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const XYPolarDomain &domain)
+{
+ dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
+ return dbg.maybeSpace();
+}
+
+#include "moc_xypolardomain_p.cpp"
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/domain/xypolardomain_p.h b/src/domain/xypolardomain_p.h
new file mode 100644
index 00000000..662cc5ee
--- /dev/null
+++ b/src/domain/xypolardomain_p.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 QtCommercial 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>
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+class QTCOMMERCIALCHART_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 QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const XYPolarDomain &Domain1, const XYPolarDomain &Domain2);
+ friend bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const XYPolarDomain &Domain1, const XYPolarDomain &Domain2);
+ friend QDebug QTCOMMERCIALCHART_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;
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // XYPOLARDOMAIN_H
diff --git a/src/layout/abstractchartlayout.cpp b/src/layout/abstractchartlayout.cpp
new file mode 100644
index 00000000..092e8c0c
--- /dev/null
+++ b/src/layout/abstractchartlayout.cpp
@@ -0,0 +1,197 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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>
+
+QTCOMMERCIALCHART_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;
+
+ 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);
+
+ 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;
+}
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/chartlayout_p.h b/src/layout/abstractchartlayout_p.h
index 5b8d38a8..d28af3d2 100644
--- a/src/chartlayout_p.h
+++ b/src/layout/abstractchartlayout_p.h
@@ -27,51 +27,50 @@
//
// We mean it.
-#ifndef CHARTLAYOUT_H
-#define CHARTLAYOUT_H
+#ifndef ABSTRACTCHARTLAYOUT_H
+#define ABSTRACTCHARTLAYOUT_H
+
#include <QGraphicsLayout>
#include <QMargins>
#include "qchartglobal.h"
QTCOMMERCIALCHART_BEGIN_NAMESPACE
-class ChartPresenter;
class ChartTitle;
+class ChartAxisElement;
+class ChartPresenter;
class QLegend;
-class ChartAxis;
class ChartBackground;
-class ChartLayout : public QGraphicsLayout
+class AbstractChartLayout : public QGraphicsLayout
{
public:
+ AbstractChartLayout(ChartPresenter *presenter);
+ virtual ~AbstractChartLayout();
- ChartLayout(ChartPresenter *presenter);
- virtual ~ChartLayout();
+ virtual void setMargins(const QMargins &margins);
+ virtual QMargins margins() const;
+ virtual void setGeometry(const QRectF &rect);
- void setMargins(const QMargins &margins);
- QMargins margins() const;
+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;
- void setGeometry(const QRectF &rect);
+ virtual QRectF calculateAxisGeometry(const QRectF &geometry, const QList<ChartAxisElement *>& axes) const = 0;
+ virtual QRectF calculateAxisMinimum(const QRectF &minimum, const QList<ChartAxisElement *>& axes) const = 0;
-protected:
+ // 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) {};
-private:
- QRectF calculateBackgroundGeometry(const QRectF &geometry, ChartBackground *background) const;
- QRectF calculateContentGeometry(const QRectF &geometry) const;
- QRectF calculateTitleGeometry(const QRectF &geometry, ChartTitle *title) const;
- QRectF calculateLegendGeometry(const QRectF &geometry, QLegend *legend) const;
- QRectF calculateAxisGeometry(const QRectF &geometry, const QList<ChartAxis *>& axes) const;
- QRectF calculateBackgroundMinimum(const QRectF &minimum) const;
- QRectF calculateContentMinimum(const QRectF &minimum) const;
- QRectF calculateTitleMinimum(const QRectF &minimum, ChartTitle *title) const;
- QRectF calculateAxisMinimum(const QRectF &minimum, const QList<ChartAxis *>& axes) const;
- QRectF calculateLegendMinimum(const QRectF &minimum, QLegend *legend) const;
-
-private:
ChartPresenter *m_presenter;
QMargins m_margins;
QRectF m_minChartRect;
@@ -80,4 +79,4 @@ private:
QTCOMMERCIALCHART_END_NAMESPACE
-#endif
+#endif // ABSTRACTCHARTLAYOUT_H
diff --git a/src/chartlayout.cpp b/src/layout/cartesianchartlayout.cpp
index bd885ba9..f5317752 100644
--- a/src/chartlayout.cpp
+++ b/src/layout/cartesianchartlayout.cpp
@@ -18,88 +18,25 @@
**
****************************************************************************/
-#include "chartlayout_p.h"
+#include "cartesianchartlayout_p.h"
#include "chartpresenter_p.h"
-#include "qlegend_p.h"
-#include "chartaxis_p.h"
-#include "charttitle_p.h"
-#include "chartbackground_p.h"
+#include "chartaxiselement_p.h"
#include <QDebug>
QTCOMMERCIALCHART_BEGIN_NAMESPACE
static const qreal maxAxisPortion = 0.4;
-ChartLayout::ChartLayout(ChartPresenter *presenter)
- : m_presenter(presenter),
- m_margins(20, 20, 20, 20),
- m_minChartRect(0, 0, 200, 200)
+CartesianChartLayout::CartesianChartLayout(ChartPresenter *presenter)
+ : AbstractChartLayout(presenter)
{
-
-}
-
-ChartLayout::~ChartLayout()
-{
-
-}
-
-void ChartLayout::setGeometry(const QRectF &rect)
-{
- if (!rect.isValid())
- return;
-
- QList<ChartAxis *> 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);
-
- QGraphicsLayout::setGeometry(rect);
}
-QRectF ChartLayout::calculateContentGeometry(const QRectF &geometry) const
+CartesianChartLayout::~CartesianChartLayout()
{
- return geometry.adjusted(m_margins.left(), m_margins.top(), -m_margins.right(), -m_margins.bottom());
}
-QRectF ChartLayout::calculateContentMinimum(const QRectF &minimum) const
-{
- return minimum.adjusted(0, 0, m_margins.left() + m_margins.right(), m_margins.top() + m_margins.bottom());
-}
-
-
-QRectF ChartLayout::calculateBackgroundGeometry(const QRectF &geometry, ChartBackground *background) const
-{
- qreal left, top, right, bottom;
- getContentsMargins(&left, &top, &right, &bottom);
- QRectF backgroundGeometry = geometry.adjusted(left, top, -right, -bottom);
- if (background)
- background->setRect(backgroundGeometry);
- return backgroundGeometry;
-}
-
-QRectF ChartLayout::calculateBackgroundMinimum(const QRectF &minimum) const
-{
- qreal left, top, right, bottom;
- getContentsMargins(&left, &top, &right, &bottom);
- return minimum.adjusted(0, 0, left + right, top + bottom);
-}
-
-
-QRectF ChartLayout::calculateAxisGeometry(const QRectF &geometry, const QList<ChartAxis *>& axes) const
+QRectF CartesianChartLayout::calculateAxisGeometry(const QRectF &geometry, const QList<ChartAxisElement *> &axes) const
{
QSizeF left(0,0);
QSizeF minLeft(0,0);
@@ -115,16 +52,17 @@ QRectF ChartLayout::calculateAxisGeometry(const QRectF &geometry, const QList<Ch
int topCount = 0;
int bottomCount = 0;
- foreach (ChartAxis *axis , axes) {
+ 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->alignment()) {
+ switch (axis->axis()->alignment()) {
case Qt::AlignLeft:
left.setWidth(left.width()+size.width());
left.setHeight(qMax(left.height(),size.height()));
@@ -163,7 +101,7 @@ QRectF ChartLayout::calculateAxisGeometry(const QRectF &geometry, const QList<Ch
}
}
- int totalVerticalAxes = leftCount + rightCount;
+ qreal totalVerticalAxes = leftCount + rightCount;
qreal leftSqueezeRatio = 1.0;
qreal rightSqueezeRatio = 1.0;
qreal vratio = 0;
@@ -186,7 +124,7 @@ QRectF ChartLayout::calculateAxisGeometry(const QRectF &geometry, const QList<Ch
}
}
- int totalHorizontalAxes = topCount + bottomCount;
+ qreal totalHorizontalAxes = topCount + bottomCount;
qreal topSqueezeRatio = 1.0;
qreal bottomSqueezeRatio = 1.0;
qreal hratio = 0;
@@ -225,15 +163,14 @@ QRectF ChartLayout::calculateAxisGeometry(const QRectF &geometry, const QList<Ch
qreal topOffset = 0;
qreal bottomOffset = 0;
- foreach(ChartElement *axisElement , axes) {
- ChartAxis* axis = qobject_cast<ChartAxis*>(axisElement);
+ foreach (ChartAxisElement *axis , axes) {
if (!axis->isVisible())
continue;
QSizeF size = axis->effectiveSizeHint(Qt::PreferredSize);
- switch(axis->alignment()){
+ switch (axis->axis()->alignment()){
case Qt::AlignLeft:{
qreal width = size.width();
if (leftSqueezeRatio < 1.0)
@@ -271,21 +208,20 @@ QRectF ChartLayout::calculateAxisGeometry(const QRectF &geometry, const QList<Ch
return chartRect;
}
-QRectF ChartLayout::calculateAxisMinimum(const QRectF &minimum, const QList<ChartAxis *>& axes) const
+QRectF CartesianChartLayout::calculateAxisMinimum(const QRectF &minimum, const QList<ChartAxisElement *> &axes) const
{
QSizeF left;
QSizeF right;
QSizeF bottom;
QSizeF top;
- foreach (ChartAxis *axis, axes) {
-
+ foreach (ChartAxisElement *axis, axes) {
QSizeF size = axis->effectiveSizeHint(Qt::MinimumSize);
if (!axis->isVisible())
continue;
- switch (axis->alignment()) {
+ switch (axis->axis()->alignment()) {
case Qt::AlignLeft:
left.setWidth(left.width() + size.width());
left.setHeight(qMax(left.height() * 2, size.height()));
@@ -307,96 +243,4 @@ QRectF ChartLayout::calculateAxisMinimum(const QRectF &minimum, const QList<Char
return minimum.adjusted(0, 0, left.width() + right.width() + qMax(top.width(), bottom.width()), top.height() + bottom.height() + qMax(left.height(), right.height()));
}
-QRectF ChartLayout::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() * maxAxisPortion);
- 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() * maxAxisPortion);
- 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 ChartLayout::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 ChartLayout::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 ChartLayout::calculateTitleMinimum(const QRectF &minimum, ChartTitle *title) const
-{
- QSizeF min = title->sizeHint(Qt::MinimumSize);
- return minimum.adjusted(0, 0, min.width(), min.height());
-}
-
-QSizeF ChartLayout::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
-{
- Q_UNUSED(constraint);
- if (which == Qt::MinimumSize) {
- QList<ChartAxis *> 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 ChartLayout::setMargins(const QMargins &margins)
-{
- if (m_margins != margins) {
- m_margins = margins;
- updateGeometry();
- }
-}
-
-QMargins ChartLayout::margins() const
-{
- return m_margins;
-}
-
QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/layout/cartesianchartlayout_p.h b/src/layout/cartesianchartlayout_p.h
new file mode 100644
index 00000000..88d540b0
--- /dev/null
+++ b/src/layout/cartesianchartlayout_p.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 QtCommercial 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"
+
+QTCOMMERCIALCHART_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;
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // CARTESIANCHARTLAYOUT_H
diff --git a/src/layout/layout.pri b/src/layout/layout.pri
new file mode 100644
index 00000000..159eab13
--- /dev/null
+++ b/src/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/layout/polarchartlayout.cpp b/src/layout/polarchartlayout.cpp
new file mode 100644
index 00000000..ad48244a
--- /dev/null
+++ b/src/layout/polarchartlayout.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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>
+#include <QFontMetrics>
+
+QTCOMMERCIALCHART_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
+ QFontMetrics titleMetrics(chartAxis->axis()->titleFont());
+ titleHeight = (titleMetrics.boundingRect(chartAxis->axis()->titleText()).height() / 2) + 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;
+}
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/layout/polarchartlayout_p.h b/src/layout/polarchartlayout_p.h
new file mode 100644
index 00000000..e8d5db44
--- /dev/null
+++ b/src/layout/polarchartlayout_p.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 QtCommercial 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"
+
+QTCOMMERCIALCHART_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;
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // POLARCHARTLAYOUT_H
diff --git a/src/legend/legendlayout.cpp b/src/legend/legendlayout.cpp
index e405c793..6d5f8328 100644
--- a/src/legend/legendlayout.cpp
+++ b/src/legend/legendlayout.cpp
@@ -21,7 +21,7 @@
#include "legendlayout_p.h"
#include "chartpresenter_p.h"
#include "qlegend_p.h"
-#include "chartlayout_p.h"
+#include "abstractchartlayout_p.h"
#include "qlegendmarker_p.h"
#include "legendmarkeritem_p.h"
diff --git a/src/legend/qlegend.cpp b/src/legend/qlegend.cpp
index 8a34afe3..1920d258 100644
--- a/src/legend/qlegend.cpp
+++ b/src/legend/qlegend.cpp
@@ -25,7 +25,7 @@
#include "qchart_p.h"
#include "legendlayout_p.h"
#include "chartpresenter_p.h"
-#include "chartlayout_p.h"
+#include "abstractchartlayout_p.h"
#include "qlegendmarker.h"
#include "qlegendmarker_p.h"
#include "legendmarkeritem_p.h"
diff --git a/src/linechart/linechartitem.cpp b/src/linechart/linechartitem.cpp
index 1f10d53e..dd5f540d 100644
--- a/src/linechart/linechartitem.cpp
+++ b/src/linechart/linechartitem.cpp
@@ -22,7 +22,7 @@
#include "qlineseries.h"
#include "qlineseries_p.h"
#include "chartpresenter_p.h"
-#include "abstractdomain_p.h"
+#include "polardomain_p.h"
#include <QPainter>
#include <QGraphicsSceneMouseEvent>
@@ -30,10 +30,11 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE
const qreal mouseEventMinWidth(12);
-LineChartItem::LineChartItem(QLineSeries *series,QGraphicsItem* item)
+LineChartItem::LineChartItem(QLineSeries *series, QGraphicsItem *item)
: XYChart(series,item),
m_series(series),
- m_pointsVisible(false)
+ m_pointsVisible(false),
+ m_chartType(QChart::ChartTypeUndefined)
{
setAcceptHoverEvents(true);
setZValue(ChartPresenter::LineChartZValue);
@@ -50,54 +51,235 @@ QRectF LineChartItem::boundingRect() const
QPainterPath LineChartItem::shape() const
{
- return m_path;
+ return m_shapePath;
}
void LineChartItem::updateGeometry()
{
m_points = geometryPoints();
+ const QVector<QPointF> &points = m_points;
- if (m_points.size() == 0) {
+ if (points.size() == 0) {
prepareGeometryChange();
- m_path = QPainterPath();
+ m_fullPath = QPainterPath();
m_linePath = QPainterPath();
m_rect = QRect();
return;
}
- QPainterPath linePath(m_points.at(0));
+ QPainterPath linePath;
+ QPainterPath fullPath;
+ // Use worst case scenario to determine required margin.
+ qreal margin = m_linePen.width() * 1.42;
- if (m_pointsVisible) {
+ // 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->pointAt(0);
+ QPointF currentGeometryPoint = points.at(0);
+ QPointF previousGeometryPoint = points.at(0);
int size = m_linePen.width();
- linePath.addEllipse(m_points.at(0), size, size);
- linePath.moveTo(m_points.at(0));
- for (int i = 1; i < m_points.size(); i++) {
- linePath.lineTo(m_points.at(i));
- linePath.addEllipse(m_points.at(i), size, size);
- linePath.moveTo(m_points.at(i));
+ 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));
+ }
}
- } else {
- for (int i = 1; i < m_points.size(); i++)
- linePath.lineTo(m_points.at(i));
- }
+ qreal leftMarginLine = centerPoint.x() - margin;
+ qreal rightMarginLine = centerPoint.x() + margin;
+ qreal horizontal = centerPoint.y();
- m_linePath = linePath;
+ 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->pointAt(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->pointAt(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(m_linePen.width() * 1.42);
+ stroker.setWidth(margin);
stroker.setJoinStyle(Qt::MiterJoin);
stroker.setCapStyle(Qt::SquareCap);
stroker.setMiterLimit(m_linePen.miterLimit());
prepareGeometryChange();
- m_path = stroker.createStroke(linePath);
- m_rect = m_path.boundingRect();
+ m_linePath = linePath;
+ m_fullPath = fullPath;
+ m_shapePath = stroker.createStroke(fullPath);
+
+ m_rect = m_shapePath.boundingRect();
}
void LineChartItem::handleUpdated()
@@ -121,16 +303,35 @@ void LineChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt
Q_UNUSED(widget)
Q_UNUSED(option)
+ QRectF clipRect = QRectF(QPointF(0, 0), domain()->size());
+
painter->save();
painter->setPen(m_linePen);
- painter->setClipRect(QRectF(QPointF(0,0),domain()->size()));
+ 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) {
+ 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);
diff --git a/src/linechart/linechartitem_p.h b/src/linechart/linechartitem_p.h
index 6db4ccfb..2a728f3b 100644
--- a/src/linechart/linechartitem_p.h
+++ b/src/linechart/linechartitem_p.h
@@ -32,6 +32,7 @@
#include "qchartglobal.h"
#include "xychart_p.h"
+#include "qchart.h"
#include <QPen>
QTCOMMERCIALCHART_BEGIN_NAMESPACE
@@ -44,7 +45,7 @@ class LineChartItem : public XYChart
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
public:
- explicit LineChartItem(QLineSeries *series, QGraphicsItem* item = 0);
+ explicit LineChartItem(QLineSeries *series, QGraphicsItem *item = 0);
~LineChartItem() {}
//from QGraphicsItem
@@ -52,7 +53,7 @@ public:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
QPainterPath shape() const;
- QPainterPath path() const { return m_linePath; }
+ QPainterPath path() const { return m_fullPath; }
public Q_SLOTS:
void handleUpdated();
@@ -63,15 +64,21 @@ protected:
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_path;
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;
};
QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/qchart.cpp b/src/qchart.cpp
index 8ab736ec..f2fd1b67 100644
--- a/src/qchart.cpp
+++ b/src/qchart.cpp
@@ -24,7 +24,7 @@
#include "qlegend_p.h"
#include "chartbackground_p.h"
#include "qabstractaxis.h"
-#include "chartlayout_p.h"
+#include "abstractchartlayout_p.h"
#include "charttheme_p.h"
#include "chartpresenter_p.h"
#include "chartdataset_p.h"
@@ -59,6 +59,16 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE
*/
/*!
+ \enum QChart::ChartType
+
+ This enum describes the chart type.
+
+ \value ChartTypeUndefined
+ \value ChartTypeCartesian
+ \value ChartTypePolar
+ */
+
+/*!
\class QChart
\brief QtCommercial chart API.
@@ -110,15 +120,34 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE
*/
/*!
- Constructs a chart object which is a child of a\a parent. Parameter \a wFlags is passed to the QGraphicsWidget constructor.
+ \property QChart::chartType
+ Chart type indicates if the chart is a cartesian chart or a polar chart.
+ This property is set internally and is read only.
+ \sa QPolarChart
+ */
+
+/*!
+ \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))
+ d_ptr(new QChartPrivate(this, ChartTypeCartesian))
{
- d_ptr->m_legend = new LegendScroller(this);
- setTheme(QChart::ChartThemeLight);
- setLayout(d_ptr->m_presenter->layout());
+ d_ptr->init();
}
/*!
@@ -269,9 +298,12 @@ void QChart::zoomIn()
/*!
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);
}
@@ -306,8 +338,8 @@ void QChart::zoom(qreal factor)
}
/*!
- Returns the pointer to the x axis object of the chart asociated with the specified \a series
- If no series is provided then pointer to currently visible axis is provided
+ Returns the pointer to the x axis object of the chart associated with the specified \a series.
+ If no series is provided then pointer to currently visible axis is provided.
*/
QAbstractAxis *QChart::axisX(QAbstractSeries *series) const
{
@@ -318,8 +350,8 @@ QAbstractAxis *QChart::axisX(QAbstractSeries *series) const
}
/*!
- Returns the pointer to the y axis object of the chart asociated with the specified \a series
- If no series is provided then pointer to currently visible axis is provided
+ Returns the pointer to the y axis object of the chart associated with the specified \a series.
+ If no series is provided then pointer to currently visible axis is provided.
*/
QAbstractAxis *QChart::axisY(QAbstractSeries *series) const
{
@@ -438,6 +470,11 @@ QMargins QChart::margins() const
return d_ptr->m_presenter->layout()->margins();
}
+QChart::ChartType QChart::chartType() const
+{
+ return d_ptr->m_type;
+}
+
/*!
Returns the the rect within which the drawing of the chart is done.
It does not include the area defines by margins.
@@ -471,6 +508,8 @@ QChart::AnimationOptions QChart::animationOptions() const
/*!
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)
{
@@ -581,11 +620,12 @@ QPointF QChart::mapToPosition(const QPointF &value, QAbstractSeries *series)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-QChartPrivate::QChartPrivate(QChart *q):
+QChartPrivate::QChartPrivate(QChart *q, QChart::ChartType type):
q_ptr(q),
+ m_type(type),
m_legend(0),
m_dataset(new ChartDataSet(q)),
- m_presenter(new ChartPresenter(q)),
+ m_presenter(new ChartPresenter(q, type)),
m_themeManager(new ChartThemeManager(q))
{
QObject::connect(m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), m_presenter, SLOT(handleSeriesAdded(QAbstractSeries*)));
@@ -603,6 +643,13 @@ QChartPrivate::~QChartPrivate()
}
+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();
diff --git a/src/qchart.h b/src/qchart.h
index e18b127f..3f026732 100644
--- a/src/qchart.h
+++ b/src/qchart.h
@@ -45,10 +45,18 @@ class QTCOMMERCIALCHART_EXPORT QChart : public QGraphicsWidget
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_ENUMS(ChartTheme)
Q_ENUMS(AnimationOption)
+ Q_ENUMS(ChartType)
public:
+ enum ChartType {
+ ChartTypeUndefined = 0,
+ ChartTypeCartesian,
+ ChartTypePolar
+ };
+
enum ChartTheme {
ChartThemeLight = 0,
ChartThemeBlueCerulean,
@@ -84,7 +92,7 @@ public:
QAbstractAxis *axisY(QAbstractSeries *series = 0) const;
// ******************
- void addAxis(QAbstractAxis *axis,Qt::Alignment alignment);
+ 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;
@@ -133,7 +141,10 @@ public:
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;
diff --git a/src/qchart_p.h b/src/qchart_p.h
index f26a3600..e715bc63 100644
--- a/src/qchart_p.h
+++ b/src/qchart_p.h
@@ -31,10 +31,10 @@
#define QCHART_P_H
#include "qchartglobal.h"
+#include "qchart.h"
QTCOMMERCIALCHART_BEGIN_NAMESPACE
-class QChart;
class ChartThemeManager;
class ChartPresenter;
class QLegend;
@@ -44,14 +44,16 @@ class QChartPrivate
{
public:
- QChartPrivate(QChart *q);
+ 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;
+ void init();
void zoomIn(qreal factor);
void zoomOut(qreal factor);
void zoomIn(const QRectF &rect);
diff --git a/src/qpolarchart.cpp b/src/qpolarchart.cpp
new file mode 100644
index 00000000..1d93d35e
--- /dev/null
+++ b/src/qpolarchart.cpp
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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"
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+/*!
+ \enum QPolarChart::PolarOrientation
+
+ This type is used to signify the polar orientation of an axis.
+
+ \value PolarOrientationRadial
+ \value PolarOrientationAngular
+*/
+
+/*!
+ \class QPolarChart
+ \brief QtCommercial chart API.
+
+ 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.
+
+ \note Polar charts do not support multiple axes of same orientation.
+
+ \sa QChart
+ */
+
+/*!
+ Constructs a polar chart as a child of a \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 object and it's 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"
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/qpolarchart.h b/src/qpolarchart.h
new file mode 100644
index 00000000..123eb578
--- /dev/null
+++ b/src/qpolarchart.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 "qchart.h"
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+class QAbstractSeries;
+class QAbstractAxis;
+
+class QTCOMMERCIALCHART_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)
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // QCHART_H
diff --git a/src/scatterchart/scatterchartitem.cpp b/src/scatterchart/scatterchartitem.cpp
index 93761ed1..fecbeb1b 100644
--- a/src/scatterchart/scatterchartitem.cpp
+++ b/src/scatterchart/scatterchartitem.cpp
@@ -23,6 +23,7 @@
#include "qscatterseries_p.h"
#include "chartpresenter_p.h"
#include "abstractdomain_p.h"
+#include "qchart.h"
#include <QPainter>
#include <QGraphicsScene>
#include <QDebug>
@@ -30,7 +31,7 @@
QTCOMMERCIALCHART_BEGIN_NAMESPACE
-ScatterChartItem::ScatterChartItem(QScatterSeries *series, QGraphicsItem* item)
+ScatterChartItem::ScatterChartItem(QScatterSeries *series, QGraphicsItem *item)
: XYChart(series,item),
m_series(series),
m_items(this),
@@ -93,12 +94,12 @@ void ScatterChartItem::deletePoints(int count)
void ScatterChartItem::markerSelected(QGraphicsItem *marker)
{
- emit XYChart::clicked(domain()->calculateDomainPoint(m_markerMap[marker]));
+ emit XYChart::clicked(m_markerMap[marker]);
}
void ScatterChartItem::markerHovered(QGraphicsItem *marker, bool state)
{
- emit XYChart::hovered(domain()->calculateDomainPoint(m_markerMap[marker]), state);
+ emit XYChart::hovered(m_markerMap[marker], state);
}
void ScatterChartItem::updateGeometry()
@@ -125,13 +126,16 @@ void ScatterChartItem::updateGeometry()
QRectF clipRect(QPointF(0,0),domain()->size());
+ QVector<bool> offGridStatus = offGridStatusVector();
+
for (int i = 0; i < points.size(); i++) {
QGraphicsItem *item = items.at(i);
const QPointF &point = points.at(i);
const QRectF &rect = item->boundingRect();
- m_markerMap[item] = point;
+ m_markerMap[item] = m_series->pointAt(i);
item->setPos(point.x() - rect.width() / 2, point.y() - rect.height() / 2);
- if (!m_visible || !clipRect.contains(point))
+
+ if (!m_visible || offGridStatus.at(i))
item->setVisible(false);
else
item->setVisible(true);
diff --git a/src/scatterchart/scatterchartitem_p.h b/src/scatterchart/scatterchartitem_p.h
index 6e8010bc..e00404a4 100644
--- a/src/scatterchart/scatterchartitem_p.h
+++ b/src/scatterchart/scatterchartitem_p.h
@@ -44,7 +44,7 @@ class ScatterChartItem : public XYChart
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
public:
- explicit ScatterChartItem(QScatterSeries *series, QGraphicsItem* item = 0);
+ explicit ScatterChartItem(QScatterSeries *series, QGraphicsItem *item = 0);
public:
//from QGraphicsItem
diff --git a/src/splinechart/splinechartitem.cpp b/src/splinechart/splinechartitem.cpp
index 261a753f..4a46a724 100644
--- a/src/splinechart/splinechartitem.cpp
+++ b/src/splinechart/splinechartitem.cpp
@@ -22,13 +22,13 @@
#include "qsplineseries_p.h"
#include "chartpresenter_p.h"
#include "splineanimation_p.h"
-#include "abstractdomain_p.h"
+#include "polardomain_p.h"
#include <QPainter>
#include <QGraphicsSceneMouseEvent>
QTCOMMERCIALCHART_BEGIN_NAMESPACE
-SplineChartItem::SplineChartItem(QSplineSeries *series, QGraphicsItem* item)
+SplineChartItem::SplineChartItem(QSplineSeries *series, QGraphicsItem *item)
: XYChart(series,item),
m_series(series),
m_pointsVisible(false),
@@ -49,8 +49,7 @@ QRectF SplineChartItem::boundingRect() const
QPainterPath SplineChartItem::shape() const
{
- QPainterPathStroker stroker;
- return stroker.createStroke(m_path);
+ return m_fullPath;
}
void SplineChartItem::setAnimation(SplineAnimation *animation)
@@ -107,20 +106,179 @@ void SplineChartItem::updateGeometry()
Q_ASSERT(points.count() * 2 - 2 == controlPoints.count());
- QPainterPath splinePath(points.at(0));
+ 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->pointAt(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();
+
+ 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->pointAt(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->pointAt(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;
+ }
- 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);
+ 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;
}
+ m_path = 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());
prepareGeometryChange();
- // QPainterPathStroker stroker;
- // stroker.setWidth(m_linePen.width() / 2.0);
- // m_path = stroker.createStroke(splinePath);
- m_path = splinePath;
- m_rect = splinePath.boundingRect();
+ m_fullPath = stroker.createStroke(fullPath);
+ m_rect = m_fullPath.boundingRect();
}
/*!
@@ -240,16 +398,38 @@ void SplineChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *o
Q_UNUSED(widget)
Q_UNUSED(option)
+ QRectF clipRect = QRectF(QPointF(0, 0), domain()->size());
+
painter->save();
- painter->setClipRect(QRectF(QPointF(0,0),domain()->size()));
painter->setPen(m_linePen);
- // painter->setBrush(m_linePen.color());
+ 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);
- painter->drawPoints(geometryPoints());
+ if (m_series->chart()->chartType() == QChart::ChartTypePolar)
+ painter->drawPoints(m_visiblePoints);
+ else
+ painter->drawPoints(geometryPoints());
}
+
painter->restore();
}
diff --git a/src/splinechart/splinechartitem_p.h b/src/splinechart/splinechartitem_p.h
index a15b6c6a..37e1b52d 100644
--- a/src/splinechart/splinechartitem_p.h
+++ b/src/splinechart/splinechartitem_p.h
@@ -42,7 +42,7 @@ class SplineChartItem : public XYChart
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
public:
- SplineChartItem(QSplineSeries *series, QGraphicsItem* item = 0);
+ SplineChartItem(QSplineSeries *series, QGraphicsItem *item = 0);
//from QGraphicsItem
QRectF boundingRect() const;
@@ -70,11 +70,15 @@ protected:
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;
friend class SplineAnimation;
diff --git a/src/src.pro b/src/src.pro
index bfb90ba0..a60a6cf2 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -39,8 +39,8 @@ SOURCES += \
$$PWD/chartelement.cpp \
$$PWD/chartitem.cpp \
$$PWD/scroller.cpp \
- $$PWD/chartlayout.cpp \
- $$PWD/charttitle.cpp
+ $$PWD/charttitle.cpp \
+ $$PWD/qpolarchart.cpp
PRIVATE_HEADERS += \
$$PWD/chartdataset_p.h \
$$PWD/chartitem_p.h \
@@ -53,7 +53,6 @@ PRIVATE_HEADERS += \
$$PWD/qchartview_p.h \
$$PWD/scroller_p.h \
$$PWD/qabstractseries_p.h \
- $$PWD/chartlayout_p.h \
$$PWD/charttitle_p.h \
$$PWD/charthelpers_p.h
PUBLIC_HEADERS += \
@@ -61,7 +60,8 @@ PUBLIC_HEADERS += \
$$PWD/qchartglobal.h \
$$PWD/qabstractseries.h \
$$PWD/qchartview.h \
- $$PWD/chartsnamespace.h
+ $$PWD/chartsnamespace.h \
+ $$PWD/qpolarchart.h
include(animations/animations.pri)
include(areachart/areachart.pri)
@@ -75,6 +75,7 @@ include(scatterchart/scatter.pri)
include(splinechart/splinechart.pri)
include(themes/themes.pri)
include(xychart/xychart.pri)
+include(layout/layout.pri)
HEADERS += $$PUBLIC_HEADERS
HEADERS += $$PRIVATE_HEADERS
diff --git a/src/xychart/qxyseries.cpp b/src/xychart/qxyseries.cpp
index 3d5f7eec..285c078d 100644
--- a/src/xychart/qxyseries.cpp
+++ b/src/xychart/qxyseries.cpp
@@ -69,6 +69,18 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE
*/
/*!
+ \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.
*/
@@ -354,6 +366,15 @@ QList<QPointF> QXYSeries::points() const
}
/*!
+ Returns point at \a index in internal points vector.
+*/
+const QPointF &QXYSeries::pointAt(int index) const
+{
+ Q_D(const QXYSeries);
+ return d->m_points.at(index);
+}
+
+/*!
Returns number of data points within series.
*/
int QXYSeries::count() const
diff --git a/src/xychart/qxyseries.h b/src/xychart/qxyseries.h
index d0e6bb48..8eff380e 100644
--- a/src/xychart/qxyseries.h
+++ b/src/xychart/qxyseries.h
@@ -56,6 +56,7 @@ public:
int count() const;
QList<QPointF> points() const;
+ const QPointF &pointAt(int index) const;
QXYSeries &operator << (const QPointF &point);
QXYSeries &operator << (const QList<QPointF> &points);
diff --git a/src/xychart/xychart.cpp b/src/xychart/xychart.cpp
index ecadf676..3d442c5a 100644
--- a/src/xychart/xychart.cpp
+++ b/src/xychart/xychart.cpp
@@ -24,6 +24,7 @@
#include "chartpresenter_p.h"
#include "abstractdomain_p.h"
#include "qxymodelmapper.h"
+#include "qabstractaxis_p.h"
#include <QPainter>
#include <QAbstractItemModel>
@@ -32,7 +33,7 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE
//TODO: optimize : remove points which are not visible
-XYChart::XYChart(QXYSeries *series,QGraphicsItem* item):
+XYChart::XYChart(QXYSeries *series, QGraphicsItem *item):
ChartItem(series->d_func(),item),
m_series(series),
m_animation(0),
@@ -46,7 +47,7 @@ XYChart::XYChart(QXYSeries *series,QGraphicsItem* item):
QObject::connect(this, SIGNAL(hovered(QPointF,bool)), series, SIGNAL(hovered(QPointF,bool)));
}
-void XYChart::setGeometryPoints(const QVector<QPointF>& points)
+void XYChart::setGeometryPoints(const QVector<QPointF> &points)
{
m_points = points;
}
@@ -61,6 +62,32 @@ 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());
+
+ for (int i = 0; i < m_points.size(); i++) {
+ const QPointF &seriesPoint = m_series->pointAt(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)
{
diff --git a/src/xychart/xychart_p.h b/src/xychart/xychart_p.h
index cfdb296b..49c57bc3 100644
--- a/src/xychart/xychart_p.h
+++ b/src/xychart/xychart_p.h
@@ -45,10 +45,10 @@ class XYChart : public ChartItem
{
Q_OBJECT
public:
- explicit XYChart(QXYSeries *series,QGraphicsItem* item = 0);
+ explicit XYChart(QXYSeries *series,QGraphicsItem *item = 0);
~XYChart() {}
- void setGeometryPoints(const QVector<QPointF>& points);
+ void setGeometryPoints(const QVector<QPointF> &points);
QVector<QPointF> geometryPoints() const { return m_points; }
void setAnimation(XYAnimation *animation);
@@ -58,6 +58,9 @@ public:
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);
diff --git a/tests/auto/README b/tests/auto/README
new file mode 100644
index 00000000..6ecc179e
--- /dev/null
+++ b/tests/auto/README
@@ -0,0 +1,9 @@
+Testing polar chart:
+
+Since the tests typically initialize the chart once for the whole test case,
+it is difficult to test the components against polar chart unless all tests
+are duplicated or massively refactored. Neither option is desirable, so instead
+we check environment variable TEST_POLAR_CHART. If it is not empty, we run
+the tests that are relevant for polar chart against polar chart. Unfortunately
+This means two runs of the tests with different environment are required for
+full coverage.
diff --git a/tests/auto/inc/tst_definitions.h b/tests/auto/inc/tst_definitions.h
index d5802235..32ddf103 100644
--- a/tests/auto/inc/tst_definitions.h
+++ b/tests/auto/inc/tst_definitions.h
@@ -21,6 +21,7 @@
#ifndef TST_DEFINITIONS_H
#define TST_DEFINITIONS_H
+#include "qpolarchart.h"
#include <QtTest/QtTest>
#include <QPushButton>
@@ -63,6 +64,16 @@ namespace QTest
QSKIP("Cannot test mouse events in this environment"); \
} while (0); \
}
+
+ #define SKIP_ON_POLAR() { \
+ if (isPolarTest()) \
+ QSKIP("Test not supported by polar chart"); \
+ }
+
+ #define SKIP_ON_CARTESIAN() { \
+ if (!isPolarTest()) \
+ QSKIP("Test not supported by cartesian chart"); \
+ }
#else
#define SKIP_IF_CANNOT_TEST_MOUSE_EVENTS() { \
do { \
@@ -76,6 +87,39 @@ namespace QTest
QSKIP("Cannot test mouse events in this environment", SkipAll); \
} while (0); \
}
+
+ #define SKIP_ON_POLAR() { \
+ if (isPolarTest()) \
+ QSKIP("Test not supported by polar chart", SkipAll); \
+ }
+
+ #define SKIP_ON_CARTESIAN() { \
+ if (!isPolarTest()) \
+ QSKIP("Test not supported by cartesian chart", SkipAll); \
+ }
#endif
+static inline bool isPolarTest()
+{
+ static bool isPolar = false;
+ static bool polarEnvChecked = false;
+ if (!polarEnvChecked) {
+ isPolar = !(qgetenv("TEST_POLAR_CHART").isEmpty());
+ polarEnvChecked = true;
+ if (isPolar)
+ qDebug() << "TEST_POLAR_CHART found -> Testing polar chart!";
+ }
+ return isPolar;
+}
+
+static inline QtCommercialChart::QChart *newQChartOrQPolarChart()
+{
+ if (isPolarTest())
+ return new QtCommercialChart::QPolarChart();
+ else
+ return new QtCommercialChart::QChart();
+}
+
+
+
#endif // TST_DEFINITIONS_H
diff --git a/tests/auto/qabstractaxis/tst_qabstractaxis.cpp b/tests/auto/qabstractaxis/tst_qabstractaxis.cpp
index a66c21d7..99f39d88 100644
--- a/tests/auto/qabstractaxis/tst_qabstractaxis.cpp
+++ b/tests/auto/qabstractaxis/tst_qabstractaxis.cpp
@@ -35,7 +35,7 @@ void tst_QAbstractAxis::init(QAbstractAxis* axis, QAbstractSeries* series)
{
m_axis = axis;
m_series = series;
- m_view = new QChartView(new QChart());
+ m_view = new QChartView(newQChartOrQPolarChart());
m_chart = m_view->chart();
}
diff --git a/tests/auto/qchart/tst_qchart.cpp b/tests/auto/qchart/tst_qchart.cpp
index 0558ad68..f92be649 100644
--- a/tests/auto/qchart/tst_qchart.cpp
+++ b/tests/auto/qchart/tst_qchart.cpp
@@ -101,6 +101,7 @@ private slots:
void zoomOut();
void createDefaultAxesForLineSeries_data();
void createDefaultAxesForLineSeries();
+ void axisPolarOrientation();
private:
void createTestData();
@@ -121,7 +122,7 @@ void tst_QChart::cleanupTestCase()
void tst_QChart::init()
{
- m_view = new QChartView(new QChart());
+ m_view = new QChartView(newQChartOrQPolarChart());
m_chart = m_view->chart();
}
@@ -191,20 +192,22 @@ void tst_QChart::addSeries_data()
QAbstractSeries* area = new QAreaSeries(static_cast<QLineSeries*>(line));
QAbstractSeries* scatter = new QScatterSeries(this);
QAbstractSeries* spline = new QSplineSeries(this);
- QAbstractSeries* pie = new QPieSeries(this);
- QAbstractSeries* bar = new QBarSeries(this);
- QAbstractSeries* percent = new QPercentBarSeries(this);
- QAbstractSeries* stacked = new QStackedBarSeries(this);
QTest::newRow("lineSeries") << line;
QTest::newRow("areaSeries") << area;
QTest::newRow("scatterSeries") << scatter;
QTest::newRow("splineSeries") << spline;
- QTest::newRow("pieSeries") << pie;
- QTest::newRow("barSeries") << bar;
- QTest::newRow("percentBarSeries") << percent;
- QTest::newRow("stackedBarSeries") << stacked;
+ if (!isPolarTest()) {
+ QAbstractSeries* pie = new QPieSeries(this);
+ QAbstractSeries* bar = new QBarSeries(this);
+ QAbstractSeries* percent = new QPercentBarSeries(this);
+ QAbstractSeries* stacked = new QStackedBarSeries(this);
+ QTest::newRow("pieSeries") << pie;
+ QTest::newRow("barSeries") << bar;
+ QTest::newRow("percentBarSeries") << percent;
+ QTest::newRow("stackedBarSeries") << stacked;
+ }
}
void tst_QChart::addSeries()
@@ -258,20 +261,23 @@ void tst_QChart::axisX_data()
QTest::newRow("categories,areaSeries") << (QAbstractAxis*) new QBarCategoryAxis() << (QAbstractSeries*) new QAreaSeries(new QLineSeries(this));
QTest::newRow("categories,scatterSeries") << (QAbstractAxis*) new QBarCategoryAxis() << (QAbstractSeries*) new QScatterSeries(this);
QTest::newRow("categories,splineSeries") << (QAbstractAxis*) new QBarCategoryAxis() << (QAbstractSeries*) new QSplineSeries(this);
- QTest::newRow("categories,pieSeries") << (QAbstractAxis*) new QBarCategoryAxis() << (QAbstractSeries*) new QPieSeries(this);
- QTest::newRow("categories,barSeries") << (QAbstractAxis*) new QBarCategoryAxis() << (QAbstractSeries*) new QBarSeries(this);
- QTest::newRow("categories,percentBarSeries") << (QAbstractAxis*) new QBarCategoryAxis() << (QAbstractSeries*) new QPercentBarSeries(this);
- QTest::newRow("categories,stackedBarSeries") << (QAbstractAxis*) new QBarCategoryAxis() << (QAbstractSeries*) new QStackedBarSeries(this);
+ if (!isPolarTest()) {
+ QTest::newRow("categories,pieSeries") << (QAbstractAxis*) new QBarCategoryAxis() << (QAbstractSeries*) new QPieSeries(this);
+ QTest::newRow("categories,barSeries") << (QAbstractAxis*) new QBarCategoryAxis() << (QAbstractSeries*) new QBarSeries(this);
+ QTest::newRow("categories,percentBarSeries") << (QAbstractAxis*) new QBarCategoryAxis() << (QAbstractSeries*) new QPercentBarSeries(this);
+ QTest::newRow("categories,stackedBarSeries") << (QAbstractAxis*) new QBarCategoryAxis() << (QAbstractSeries*) new QStackedBarSeries(this);
+ }
QTest::newRow("value,lineSeries") << (QAbstractAxis*) new QValueAxis() << (QAbstractSeries*) new QLineSeries(this);
QTest::newRow("value,areaSeries") << (QAbstractAxis*) new QValueAxis() << (QAbstractSeries*) new QAreaSeries(new QLineSeries(this));
QTest::newRow("value,scatterSeries") << (QAbstractAxis*) new QValueAxis() << (QAbstractSeries*) new QScatterSeries(this);
QTest::newRow("value,splineSeries") << (QAbstractAxis*) new QValueAxis() << (QAbstractSeries*) new QSplineSeries(this);
- QTest::newRow("value,pieSeries") << (QAbstractAxis*) new QValueAxis() << (QAbstractSeries*) new QPieSeries(this);
- QTest::newRow("value,barSeries") << (QAbstractAxis*) new QValueAxis() << (QAbstractSeries*) new QBarSeries(this);
- QTest::newRow("value,percentBarSeries") << (QAbstractAxis*) new QValueAxis() << (QAbstractSeries*) new QPercentBarSeries(this);
- QTest::newRow("value,stackedBarSeries") << (QAbstractAxis*) new QValueAxis() << (QAbstractSeries*) new QStackedBarSeries(this);
-
+ if (!isPolarTest()) {
+ QTest::newRow("value,pieSeries") << (QAbstractAxis*) new QValueAxis() << (QAbstractSeries*) new QPieSeries(this);
+ QTest::newRow("value,barSeries") << (QAbstractAxis*) new QValueAxis() << (QAbstractSeries*) new QBarSeries(this);
+ QTest::newRow("value,percentBarSeries") << (QAbstractAxis*) new QValueAxis() << (QAbstractSeries*) new QPercentBarSeries(this);
+ QTest::newRow("value,stackedBarSeries") << (QAbstractAxis*) new QValueAxis() << (QAbstractSeries*) new QStackedBarSeries(this);
+ }
}
void tst_QChart::axisX()
@@ -850,14 +856,14 @@ void tst_QChart::createDefaultAxesForLineSeries()
series2->append(series2minX, series2minY);
series2->append(series2midX, series2midY);
series2->append(series2maxX, series2maxY);
- QChart chart;
- chart.addSeries(series1);
- chart.addSeries(series2);
- chart.createDefaultAxes();
- QValueAxis *xAxis = (QValueAxis *)chart.axisX();
+ QChart *chart = newQChartOrQPolarChart();
+ chart->addSeries(series1);
+ chart->addSeries(series2);
+ chart->createDefaultAxes();
+ QValueAxis *xAxis = (QValueAxis *)chart->axisX();
QCOMPARE(xAxis->min(), overallminX);
QCOMPARE(xAxis->max(), overallmaxX);
- QValueAxis *yAxis = (QValueAxis *)chart.axisY();
+ QValueAxis *yAxis = (QValueAxis *)chart->axisY();
QCOMPARE(yAxis->min(), overallminY);
QCOMPARE(yAxis->max(), overallmaxY);
QLineSeries *series3 = new QLineSeries(this);
@@ -865,12 +871,37 @@ void tst_QChart::createDefaultAxesForLineSeries()
series3->append(0, 0);
series3->append(100, 100);
// Adding a new series should not change the axes as they have not been told to update
- chart.addSeries(series3);
+ chart->addSeries(series3);
QCOMPARE(xAxis->min(), overallminX);
QCOMPARE(xAxis->max(), overallmaxX);
QCOMPARE(yAxis->min(), overallminY);
QCOMPARE(yAxis->max(), overallmaxY);
+}
+
+void tst_QChart::axisPolarOrientation()
+{
+ QLineSeries* series1 = new QLineSeries(this);
+ series1->append(1, 2);
+ series1->append(2, 4);
+ series1->append(3, 8);
+ QPolarChart chart;
+ chart.addSeries(series1);
+
+ QValueAxis *xAxis = new QValueAxis();
+ QValueAxis *yAxis = new QValueAxis();
+ chart.addAxis(xAxis, QPolarChart::PolarOrientationAngular);
+ chart.addAxis(yAxis, QPolarChart::PolarOrientationRadial);
+
+ QList<QAbstractAxis *> xAxes = chart.axes(QPolarChart::PolarOrientationAngular);
+ QList<QAbstractAxis *> yAxes = chart.axes(QPolarChart::PolarOrientationRadial);
+
+ QCOMPARE(xAxes.size(), 1);
+ QCOMPARE(yAxes.size(), 1);
+ QCOMPARE(xAxes[0], xAxis);
+ QCOMPARE(yAxes[0], yAxis);
+ QCOMPARE(chart.axisPolarOrientation(xAxes[0]), QPolarChart::PolarOrientationAngular);
+ QCOMPARE(chart.axisPolarOrientation(yAxes[0]), QPolarChart::PolarOrientationRadial);
}
QTEST_MAIN(tst_QChart)
diff --git a/tests/auto/qchartview/tst_qchartview.cpp b/tests/auto/qchartview/tst_qchartview.cpp
index d8019717..878b2757 100644
--- a/tests/auto/qchartview/tst_qchartview.cpp
+++ b/tests/auto/qchartview/tst_qchartview.cpp
@@ -67,7 +67,7 @@ void tst_QChartView::cleanupTestCase()
void tst_QChartView::init()
{
- m_view = new QChartView(new QChart());
+ m_view = new QChartView(newQChartOrQPolarChart());
m_view->chart()->legend()->setVisible(false);
}
@@ -120,9 +120,15 @@ void tst_QChartView::rubberBand_data()
QTest::addColumn<QPoint>("min");
QTest::addColumn<QPoint>("max");
- QTest::newRow("HorizonalRubberBand") << QChartView::RubberBands(QChartView::HorizonalRubberBand) << 0 << 1 << QPoint(5,5) << QPoint(5,5);
- QTest::newRow("VerticalRubberBand") << QChartView::RubberBands(QChartView::VerticalRubberBand) << 1 << 0 << QPoint(5,5) << QPoint(5,5);
- QTest::newRow("RectangleRubberBand") << QChartView::RubberBands(QChartView::RectangleRubberBand) << 1 << 1 << QPoint(5,5) << QPoint(5,5);
+ if (isPolarTest()) {
+ QTest::newRow("HorizonalRubberBand") << QChartView::RubberBands(QChartView::HorizonalRubberBand) << 0 << 0 << QPoint(5,5) << QPoint(5,5);
+ QTest::newRow("VerticalRubberBand") << QChartView::RubberBands(QChartView::VerticalRubberBand) << 0 << 0 << QPoint(5,5) << QPoint(5,5);
+ QTest::newRow("RectangleRubberBand") << QChartView::RubberBands(QChartView::RectangleRubberBand) << 0 << 0 << QPoint(5,5) << QPoint(5,5);
+ } else {
+ QTest::newRow("HorizonalRubberBand") << QChartView::RubberBands(QChartView::HorizonalRubberBand) << 0 << 1 << QPoint(5,5) << QPoint(5,5);
+ QTest::newRow("VerticalRubberBand") << QChartView::RubberBands(QChartView::VerticalRubberBand) << 1 << 0 << QPoint(5,5) << QPoint(5,5);
+ QTest::newRow("RectangleRubberBand") << QChartView::RubberBands(QChartView::RectangleRubberBand) << 1 << 1 << QPoint(5,5) << QPoint(5,5);
+ }
}
void tst_QChartView::rubberBand()
@@ -194,7 +200,8 @@ void tst_QChartView::setChart()
series1->append(1,1);
oldChart->addSeries(series1);
- QPointer<QChart> newChart = new QChart();
+ QPointer<QChart> newChart = newQChartOrQPolarChart();
+
QLineSeries *series2 = new QLineSeries();
series2->append(0,1);
series2->append(1,0);
diff --git a/tests/auto/qlegend/tst_qlegend.cpp b/tests/auto/qlegend/tst_qlegend.cpp
index 5eb6e245..de493565 100644
--- a/tests/auto/qlegend/tst_qlegend.cpp
+++ b/tests/auto/qlegend/tst_qlegend.cpp
@@ -63,7 +63,6 @@ private slots:
private:
QChart *m_chart;
-
};
void tst_QLegend::initTestCase()
@@ -76,7 +75,7 @@ void tst_QLegend::cleanupTestCase()
void tst_QLegend::init()
{
- m_chart = new QChart();
+ m_chart = newQChartOrQPolarChart();
}
void tst_QLegend::cleanup()
@@ -98,6 +97,8 @@ void tst_QLegend::qlegend()
void tst_QLegend::qpieLegendMarker()
{
+ SKIP_ON_POLAR();
+
QVERIFY(m_chart);
QLegend *legend = m_chart->legend();
@@ -190,6 +191,8 @@ void tst_QLegend::qxyLegendMarker()
void tst_QLegend::qbarLegendMarker()
{
+ SKIP_ON_POLAR();
+
QVERIFY(m_chart);
QLegend *legend = m_chart->legend();
@@ -230,6 +233,8 @@ void tst_QLegend::qbarLegendMarker()
void tst_QLegend::markers()
{
+ SKIP_ON_POLAR();
+
QVERIFY(m_chart);
QLegend *legend = m_chart->legend();
@@ -270,6 +275,8 @@ void tst_QLegend::markers()
void tst_QLegend::addAndRemoveSeries()
{
+ SKIP_ON_POLAR();
+
QVERIFY(m_chart);
QLegend *legend = m_chart->legend();
@@ -291,6 +298,8 @@ void tst_QLegend::addAndRemoveSeries()
void tst_QLegend::pieMarkerProperties()
{
+ SKIP_ON_POLAR();
+
QVERIFY(m_chart);
QLegend *legend = m_chart->legend();
@@ -327,6 +336,8 @@ void tst_QLegend::pieMarkerProperties()
void tst_QLegend::barMarkerProperties()
{
+ SKIP_ON_POLAR();
+
QVERIFY(m_chart);
QLegend *legend = m_chart->legend();
@@ -482,8 +493,10 @@ void tst_QLegend::xyMarkerPropertiesScatter()
void tst_QLegend::markerSignals()
{
+ SKIP_ON_POLAR();
+
SKIP_IF_CANNOT_TEST_MOUSE_EVENTS();
- QChart *chart = new QChart();
+ QChart *chart = newQChartOrQPolarChart();
QLegend *legend = chart->legend();
QBarSeries *bar = new QBarSeries();
diff --git a/tests/auto/qml/tst_qml.cpp b/tests/auto/qml/tst_qml.cpp
index 2c57036f..98880afd 100644
--- a/tests/auto/qml/tst_qml.cpp
+++ b/tests/auto/qml/tst_qml.cpp
@@ -36,7 +36,8 @@ private slots:
void checkPlugin();
private:
QString componentErrors(const QDeclarativeComponent* component) const;
- QString imports();
+ QString imports_1_1();
+ QString imports_1_3();
};
@@ -53,12 +54,18 @@ QString tst_QML::componentErrors(const QDeclarativeComponent* component) const
return errors.join("\n");
}
-QString tst_QML::imports()
+QString tst_QML::imports_1_1()
{
return "import QtQuick 1.0 \n"
"import QtCommercial.Chart 1.1 \n";
}
+QString tst_QML::imports_1_3()
+{
+ return "import QtQuick 1.0 \n"
+ "import QtCommercial.Chart 1.3 \n";
+}
+
void tst_QML::initTestCase()
{
@@ -82,34 +89,37 @@ void tst_QML::checkPlugin_data()
{
QTest::addColumn<QString>("source");
- QTest::newRow("createChartView") << imports() + "ChartView{}";
- QTest::newRow("XYPoint") << imports() + "XYPoint{}";
- QTest::newRow("scatterSeries") << imports() + "ScatterSeries{}";
- QTest::newRow("lineSeries") << imports() + "LineSeries{}";
- QTest::newRow("splineSeries") << imports() + "SplineSeries{}";
- QTest::newRow("areaSeries") << imports() + "AreaSeries{}";
- QTest::newRow("barSeries") << imports() + "BarSeries{}";
- QTest::newRow("stackedBarSeries") << imports() + "StackedBarSeries{}";
- QTest::newRow("precentBarSeries") << imports() + "PercentBarSeries{}";
- QTest::newRow("horizonatlBarSeries") << imports() + "HorizontalBarSeries{}";
- QTest::newRow("horizonatlStackedBarSeries") << imports() + "HorizontalStackedBarSeries{}";
- QTest::newRow("horizonatlstackedBarSeries") << imports() + "HorizontalPercentBarSeries{}";
- QTest::newRow("pieSeries") << imports() + "PieSeries{}";
- QTest::newRow("PieSlice") << imports() + "PieSlice{}";
- QTest::newRow("BarSet") << imports() + "BarSet{}";
- QTest::newRow("HXYModelMapper") << imports() + "HXYModelMapper{}";
- QTest::newRow("VXYModelMapper") << imports() + "VXYModelMapper{}";
- QTest::newRow("HPieModelMapper") << imports() + "HPieModelMapper{}";
- QTest::newRow("HPieModelMapper") << imports() + "HPieModelMapper{}";
- QTest::newRow("HBarModelMapper") << imports() + "HBarModelMapper{}";
- QTest::newRow("VBarModelMapper") << imports() + "VBarModelMapper{}";
- QTest::newRow("ValueAxis") << imports() + "ValueAxis{}";
+ QTest::newRow("createChartView") << imports_1_1() + "ChartView{}";
+ QTest::newRow("XYPoint") << imports_1_1() + "XYPoint{}";
+ QTest::newRow("scatterSeries") << imports_1_1() + "ScatterSeries{}";
+ QTest::newRow("lineSeries") << imports_1_1() + "LineSeries{}";
+ QTest::newRow("splineSeries") << imports_1_1() + "SplineSeries{}";
+ QTest::newRow("areaSeries") << imports_1_1() + "AreaSeries{}";
+ QTest::newRow("barSeries") << imports_1_1() + "BarSeries{}";
+ QTest::newRow("stackedBarSeries") << imports_1_1() + "StackedBarSeries{}";
+ QTest::newRow("precentBarSeries") << imports_1_1() + "PercentBarSeries{}";
+ QTest::newRow("horizonatlBarSeries") << imports_1_1() + "HorizontalBarSeries{}";
+ QTest::newRow("horizonatlStackedBarSeries") << imports_1_1() + "HorizontalStackedBarSeries{}";
+ QTest::newRow("horizonatlstackedBarSeries") << imports_1_1() + "HorizontalPercentBarSeries{}";
+ QTest::newRow("pieSeries") << imports_1_1() + "PieSeries{}";
+ QTest::newRow("PieSlice") << imports_1_1() + "PieSlice{}";
+ QTest::newRow("BarSet") << imports_1_1() + "BarSet{}";
+ QTest::newRow("HXYModelMapper") << imports_1_1() + "HXYModelMapper{}";
+ QTest::newRow("VXYModelMapper") << imports_1_1() + "VXYModelMapper{}";
+ QTest::newRow("HPieModelMapper") << imports_1_1() + "HPieModelMapper{}";
+ QTest::newRow("HPieModelMapper") << imports_1_1() + "HPieModelMapper{}";
+ QTest::newRow("HBarModelMapper") << imports_1_1() + "HBarModelMapper{}";
+ QTest::newRow("VBarModelMapper") << imports_1_1() + "VBarModelMapper{}";
+ QTest::newRow("ValueAxis") << imports_1_1() + "ValueAxis{}";
#ifndef QT_ON_ARM
- QTest::newRow("DateTimeAxis") << imports() + "DateTimeAxis{}";
+ QTest::newRow("DateTimeAxis") << imports_1_1() + "DateTimeAxis{}";
#endif
- QTest::newRow("CategoryAxis") << imports() + "CategoryAxis{}";
- QTest::newRow("CategoryRange") << imports() + "CategoryRange{}";
- QTest::newRow("BarCategoryAxis") << imports() + "BarCategoryAxis{}";
+ QTest::newRow("CategoryAxis") << imports_1_1() + "CategoryAxis{}";
+ QTest::newRow("CategoryRange") << imports_1_1() + "CategoryRange{}";
+ QTest::newRow("BarCategoryAxis") << imports_1_1() + "BarCategoryAxis{}";
+
+ QTest::newRow("createPolarChartView") << imports_1_3() + "PolarChartView{}";
+ //QTest::newRow("LogValueAxis") << imports_1_3() + "LogValueAxis{}";
}
void tst_QML::checkPlugin()
diff --git a/tests/auto/qxymodelmapper/tst_qxymodelmapper.cpp b/tests/auto/qxymodelmapper/tst_qxymodelmapper.cpp
index e553f5e4..f4c36200 100644
--- a/tests/auto/qxymodelmapper/tst_qxymodelmapper.cpp
+++ b/tests/auto/qxymodelmapper/tst_qxymodelmapper.cpp
@@ -28,6 +28,7 @@
#include <qvxymodelmapper.h>
#include <qhxymodelmapper.h>
#include <QStandardItemModel>
+#include "tst_definitions.h"
QTCOMMERCIALCHART_USE_NAMESPACE
@@ -145,7 +146,7 @@ void tst_qxymodelmapper::cleanup()
void tst_qxymodelmapper::initTestCase()
{
- m_chart = new QChart;
+ m_chart = newQChartOrQPolarChart();
QChartView *chartView = new QChartView(m_chart);
chartView->show();
}
diff --git a/tests/auto/qxyseries/tst_qxyseries.cpp b/tests/auto/qxyseries/tst_qxyseries.cpp
index 9a357b76..7988e9b7 100644
--- a/tests/auto/qxyseries/tst_qxyseries.cpp
+++ b/tests/auto/qxyseries/tst_qxyseries.cpp
@@ -32,7 +32,7 @@ void tst_QXYSeries::cleanupTestCase()
void tst_QXYSeries::init()
{
- m_view = new QChartView(new QChart());
+ m_view = new QChartView(newQChartOrQPolarChart());
m_chart = m_view->chart();
}
diff --git a/tests/polarcharttest/chartview.cpp b/tests/polarcharttest/chartview.cpp
new file mode 100644
index 00000000..4c8c5779
--- /dev/null
+++ b/tests/polarcharttest/chartview.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 "chartview.h"
+#include <QMouseEvent>
+#include <QDebug>
+#include <QAbstractAxis>
+
+QTCOMMERCIALCHART_USE_NAMESPACE
+
+ChartView::ChartView(QWidget *parent) :
+ QChartView(parent)
+{
+}
+
+void ChartView::keyPressEvent(QKeyEvent *event)
+{
+ switch (event->key()) {
+ case Qt::Key_Plus:
+ chart()->zoomIn();
+ break;
+ case Qt::Key_Minus:
+ chart()->zoomOut();
+ break;
+ case Qt::Key_Left:
+ chart()->scroll(-1.0, 0);
+ break;
+ case Qt::Key_Right:
+ chart()->scroll(1.0, 0);
+ break;
+ case Qt::Key_Up:
+ chart()->scroll(0, 1.0);
+ break;
+ case Qt::Key_Down:
+ chart()->scroll(0, -1.0);
+ break;
+ default:
+ QGraphicsView::keyPressEvent(event);
+ break;
+ }
+}
diff --git a/tests/polarcharttest/chartview.h b/tests/polarcharttest/chartview.h
new file mode 100644
index 00000000..82528c29
--- /dev/null
+++ b/tests/polarcharttest/chartview.h
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 CHARTVIEW_H
+#define CHARTVIEW_H
+
+#include <QChartView>
+#include <QPolarChart>
+
+QTCOMMERCIALCHART_USE_NAMESPACE
+
+class ChartView : public QChartView
+{
+public:
+ ChartView(QWidget *parent = 0);
+
+protected:
+ void keyPressEvent(QKeyEvent *event);
+};
+
+#endif
diff --git a/tests/polarcharttest/main.cpp b/tests/polarcharttest/main.cpp
new file mode 100644
index 00000000..30db2e25
--- /dev/null
+++ b/tests/polarcharttest/main.cpp
@@ -0,0 +1,31 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 "mainwindow.h"
+#include <QApplication>
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+ MainWindow w;
+ w.show();
+
+ return a.exec();
+}
diff --git a/tests/polarcharttest/mainwindow.cpp b/tests/polarcharttest/mainwindow.cpp
new file mode 100644
index 00000000..7e6cef04
--- /dev/null
+++ b/tests/polarcharttest/mainwindow.cpp
@@ -0,0 +1,1136 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 "mainwindow.h"
+#include "chartview.h"
+#include <QScatterSeries>
+#include <QLineSeries>
+#include <QSplineSeries>
+#include <QAreaSeries>
+#include <QBarSeries>
+#include <QBarSet>
+#include <QValueAxis>
+#include <QLogValueAxis>
+#include <QDateTimeAxis>
+#include <QCategoryAxis>
+#include <QPolarChart>
+#include <QDebug>
+#include <qmath.h>
+#include <QDateTime>
+
+QTCOMMERCIALCHART_USE_NAMESPACE
+#include "ui_mainwindow.h"
+
+MainWindow::MainWindow(QWidget *parent) :
+ QMainWindow(parent),
+ ui(new Ui::MainWindow),
+ m_angularTickCount(9),
+ m_radialTickCount(11),
+ m_labelsAngle(0),
+ m_angularMin(0.0),
+ m_angularMax(40000.0),
+ m_radialMin(0.0),
+ m_radialMax(30000.0),
+ m_angularShadesVisible(false),
+ m_radialShadesVisible(false),
+ m_labelsVisible(true),
+ m_titleVisible(true),
+ m_gridVisible(true),
+ m_arrowVisible(true),
+ m_angularShadesBrush(new QBrush(Qt::NoBrush)),
+ m_radialShadesBrush(new QBrush(Qt::NoBrush)),
+ m_labelBrush(new QBrush(Qt::black)),
+ m_titleBrush(new QBrush(Qt::black)),
+ m_angularShadesPen(new QPen(Qt::NoPen)),
+ m_radialShadesPen(new QPen(Qt::NoPen)),
+ m_labelPen(new QPen(Qt::NoPen)),
+ m_titlePen(new QPen(Qt::NoPen)),
+ m_gridPen(new QPen(QRgb(0x010101))), // Note: Pure black is default color, so it gets overridden by
+ m_arrowPen(new QPen(QRgb(0x010101))), // default theme if set to that initially. This is an example of workaround.
+ m_labelFormat(QString("%.2f")),
+ m_animationOptions(QChart::NoAnimation),
+ m_angularTitle(QString("Angular Title")),
+ m_radialTitle(QString("Radial Title")),
+ m_base(2.0),
+ m_chart(0),
+ m_angularAxis(0),
+ m_radialAxis(0),
+ m_angularAxisMode(AxisModeNone),
+ m_radialAxisMode(AxisModeNone),
+ m_series1(0),
+ m_series2(0),
+ m_series3(0),
+ m_series4(0),
+ m_series5(0),
+ m_series6(0),
+ m_series7(0),
+ m_dateFormat(QString("mm-ss-zzz")),
+ m_moreCategories(false)
+{
+ ui->setupUi(this);
+
+ ui->angularTicksSpin->setValue(m_angularTickCount);
+ ui->radialTicksSpin->setValue(m_radialTickCount);
+ ui->anglesSpin->setValue(m_labelsAngle);
+ ui->radialMinSpin->setValue(m_radialMin);
+ ui->radialMaxSpin->setValue(m_radialMax);
+ ui->angularMinSpin->setValue(m_angularMin);
+ ui->angularMaxSpin->setValue(m_angularMax);
+ ui->angularShadesComboBox->setCurrentIndex(0);
+ ui->radialShadesComboBox->setCurrentIndex(0);
+ ui->labelFormatEdit->setText(m_labelFormat);
+ ui->dateFormatEdit->setText(m_dateFormat);
+ ui->moreCategoriesCheckBox->setChecked(m_moreCategories);
+
+ ui->series1checkBox->setChecked(true);
+ ui->series2checkBox->setChecked(true);
+ ui->series3checkBox->setChecked(true);
+ ui->series4checkBox->setChecked(true);
+ ui->series5checkBox->setChecked(true);
+ ui->series6checkBox->setChecked(true);
+ ui->series7checkBox->setChecked(true);
+
+ m_currentLabelFont.setFamily(ui->labelFontComboBox->currentFont().family());
+ m_currentLabelFont.setPixelSize(15);
+ m_currentTitleFont.setFamily(ui->titleFontComboBox->currentFont().family());
+ m_currentTitleFont.setPixelSize(30);
+
+ ui->labelFontSizeSpin->setValue(m_currentLabelFont.pixelSize());
+ ui->titleFontSizeSpin->setValue(m_currentTitleFont.pixelSize());
+
+ ui->logBaseSpin->setValue(m_base);
+
+ initXYValueChart();
+ setAngularAxis(AxisModeValue);
+ setRadialAxis(AxisModeValue);
+
+ ui->angularAxisComboBox->setCurrentIndex(int(m_angularAxisMode));
+ ui->radialAxisComboBox->setCurrentIndex(int(m_radialAxisMode));
+
+ connect(ui->angularTicksSpin, SIGNAL(valueChanged(int)), this, SLOT(angularTicksChanged(int)));
+ connect(ui->radialTicksSpin, SIGNAL(valueChanged(int)), this, SLOT(radialTicksChanged(int)));
+ connect(ui->anglesSpin, SIGNAL(valueChanged(int)), this, SLOT(anglesChanged(int)));
+ connect(ui->radialMinSpin, SIGNAL(valueChanged(double)), this, SLOT(radialMinChanged(double)));
+ connect(ui->radialMaxSpin, SIGNAL(valueChanged(double)), this, SLOT(radialMaxChanged(double)));
+ connect(ui->angularMinSpin, SIGNAL(valueChanged(double)), this, SLOT(angularMinChanged(double)));
+ connect(ui->angularMaxSpin, SIGNAL(valueChanged(double)), this, SLOT(angularMaxChanged(double)));
+ connect(ui->angularShadesComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(angularShadesIndexChanged(int)));
+ connect(ui->radialShadesComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(radialShadesIndexChanged(int)));
+ connect(ui->animationsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(animationIndexChanged(int)));
+ connect(ui->labelFormatEdit, SIGNAL(textEdited(QString)), this, SLOT(labelFormatEdited(QString)));
+ connect(ui->labelFontComboBox, SIGNAL(currentFontChanged(QFont)), this, SLOT(labelFontChanged(QFont)));
+ connect(ui->labelFontSizeSpin, SIGNAL(valueChanged(int)), this, SLOT(labelFontSizeChanged(int)));
+ connect(ui->labelComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(labelsIndexChanged(int)));
+ connect(ui->titleFontComboBox, SIGNAL(currentFontChanged(QFont)), this, SLOT(titleFontChanged(QFont)));
+ connect(ui->titleFontSizeSpin, SIGNAL(valueChanged(int)), this, SLOT(titleFontSizeChanged(int)));
+ connect(ui->titleComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(titleIndexChanged(int)));
+ connect(ui->gridComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(gridIndexChanged(int)));
+ connect(ui->arrowComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(arrowIndexChanged(int)));
+ connect(ui->logBaseSpin, SIGNAL(valueChanged(double)), this, SLOT(logBaseChanged(double)));
+ connect(ui->angularAxisComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(angularAxisIndexChanged(int)));
+ connect(ui->radialAxisComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(radialAxisIndexChanged(int)));
+ connect(ui->niceNumbersCheckBox, SIGNAL(clicked()), this, SLOT(niceNumbersChecked()));
+ connect(ui->dateFormatEdit, SIGNAL(textEdited(QString)), this, SLOT(dateFormatEdited(QString)));
+ connect(ui->moreCategoriesCheckBox, SIGNAL(clicked()), this, SLOT(moreCategoriesChecked()));
+ connect(ui->series1checkBox, SIGNAL(clicked()), this, SLOT(series1CheckBoxChecked()));
+ connect(ui->series2checkBox, SIGNAL(clicked()), this, SLOT(series2CheckBoxChecked()));
+ connect(ui->series3checkBox, SIGNAL(clicked()), this, SLOT(series3CheckBoxChecked()));
+ connect(ui->series4checkBox, SIGNAL(clicked()), this, SLOT(series4CheckBoxChecked()));
+ connect(ui->series5checkBox, SIGNAL(clicked()), this, SLOT(series5CheckBoxChecked()));
+ connect(ui->series6checkBox, SIGNAL(clicked()), this, SLOT(series6CheckBoxChecked()));
+ connect(ui->series7checkBox, SIGNAL(clicked()), this, SLOT(series7CheckBoxChecked()));
+ connect(ui->themeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(themeIndexChanged(int)));
+
+ ui->chartView->setChart(m_chart);
+ ui->chartView->setRenderHint(QPainter::Antialiasing);
+}
+
+MainWindow::~MainWindow()
+{
+ delete ui;
+ delete m_angularShadesBrush;
+ delete m_radialShadesBrush;
+ delete m_angularShadesPen;
+ delete m_radialShadesPen;
+}
+
+void MainWindow::initXYValueChart()
+{
+ qreal seriesAngularMin = 1;
+ qreal seriesAngularMax = 46000;
+ qreal seriesRadialMin = 1;
+ qreal seriesRadialMax = 23500;
+ qreal radialDimension = seriesRadialMax - seriesRadialMin;
+ qreal angularDimension = seriesAngularMax - seriesAngularMin;
+
+ // Scatter series, points outside min-max ranges should not be drawn
+ m_series1 = new QScatterSeries();
+ m_series1->setName("scatter");
+ qreal scatterCount = 10;
+ qreal scatterAngularStep = angularDimension / scatterCount;
+ qreal scatterRadialStep = radialDimension / scatterCount;
+ for (qreal i = 0.0; i < scatterCount; i++) {
+ m_series1->append((i * scatterAngularStep) + seriesAngularMin, (i * scatterRadialStep) + seriesRadialMin);
+ //qDebug() << m_series1->points().last();
+ }
+ m_series1->setMarkerSize(10);
+ *m_series1 << QPointF(50, 50) << QPointF(150, 150) << QPointF(250, 250) << QPointF(350, 350) << QPointF(450, 450);
+ *m_series1 << QPointF(1050, 0.50) << QPointF(1150, 0.25) << QPointF(1250, 0.12) << QPointF(1350, 0.075) << QPointF(1450, 0.036);
+ *m_series1 << QPointF(0.50, 2000) << QPointF(0.25, 3500) << QPointF(0.12, 5000) << QPointF(0.075, 6500) << QPointF(0.036, 8000);
+
+ // Line series, points outside min-max ranges should not be drawn,
+ // but lines should be properly interpolated at chart edges
+ m_series2 = new QLineSeries();
+ m_series2->setName("line 1");
+ qreal lineCount = 100;
+ qreal lineAngularStep = angularDimension / lineCount;
+ qreal lineRadialStep = radialDimension / lineCount;
+ for (qreal i = 0.0; i < lineCount; i++) {
+ m_series2->append((i * lineAngularStep) + seriesAngularMin, (i * lineRadialStep) + seriesRadialMin);
+ //qDebug() << m_series2->points().last();
+ }
+ QPen series2Pen = QPen(Qt::blue, 10);
+ //series2Pen.setStyle(Qt::DashDotDotLine);
+ m_series2->setPen(series2Pen);
+
+ m_series3 = new QLineSeries();
+ m_series3->setName("Area upper");
+ lineCount = 87;
+ lineAngularStep = angularDimension / lineCount;
+ lineRadialStep = radialDimension / lineCount;
+ for (qreal i = 1.0; i <= lineCount; i++) {
+ m_series3->append((i * lineAngularStep) + seriesAngularMin, (i * lineRadialStep) + seriesRadialMin + 200.0);
+ //qDebug() << m_series3->points().last();
+ }
+
+ m_series4 = new QLineSeries();
+ m_series4->setName("Area lower");
+ lineCount = 89;
+ lineAngularStep = angularDimension / lineCount;
+ lineRadialStep = radialDimension / lineCount;
+ for (qreal i = 1.0; i <= lineCount; i++) {
+ m_series4->append((i * lineAngularStep) + seriesAngularMin + 100.0, (i * lineRadialStep) + seriesRadialMin + i * 300.0);
+ //qDebug() << m_series4->points().last();
+ }
+
+ m_series5 = new QAreaSeries();
+ m_series5->setName("area");
+ m_series5->setUpperSeries(m_series3);
+ m_series5->setLowerSeries(m_series4);
+ m_series5->setOpacity(0.5);
+
+ m_series6 = new QSplineSeries();
+ m_series6->setName("spline");
+ qreal ad = angularDimension / 20;
+ qreal rd = radialDimension / 10;
+ m_series6->append(seriesAngularMin, seriesRadialMin + rd * 2);
+ m_series6->append(seriesAngularMin + ad, seriesRadialMin + rd * 5);
+ m_series6->append(seriesAngularMin + ad * 2, seriesRadialMin + rd * 4);
+ m_series6->append(seriesAngularMin + ad * 3, seriesRadialMin + rd * 9);
+ m_series6->append(seriesAngularMin + ad * 4, seriesRadialMin + rd * 11);
+ m_series6->append(seriesAngularMin + ad * 5, seriesRadialMin + rd * 12);
+ m_series6->append(seriesAngularMin + ad * 6, seriesRadialMin + rd * 9);
+ m_series6->append(seriesAngularMin + ad * 7, seriesRadialMin + rd * 11);
+ m_series6->append(seriesAngularMin + ad * 8, seriesRadialMin + rd * 12);
+ m_series6->append(seriesAngularMin + ad * 9, seriesRadialMin + rd * 6);
+ m_series6->append(seriesAngularMin + ad * 10, seriesRadialMin + rd * 4);
+ m_series6->append(seriesAngularMin + ad * 10, seriesRadialMin + rd * 8);
+ m_series6->append(seriesAngularMin + ad * 11, seriesRadialMin + rd * 9);
+ m_series6->append(seriesAngularMin + ad * 12, seriesRadialMin + rd * 11);
+ m_series6->append(seriesAngularMin + ad * 13, seriesRadialMin + rd * 12);
+ m_series6->append(seriesAngularMin + ad * 14, seriesRadialMin + rd * 6);
+ m_series6->append(seriesAngularMin + ad * 15, seriesRadialMin + rd * 3);
+ m_series6->append(seriesAngularMin + ad * 16, seriesRadialMin + rd * 2);
+ m_series6->append(seriesAngularMin + ad * 17, seriesRadialMin + rd * 6);
+ m_series6->append(seriesAngularMin + ad * 18, seriesRadialMin + rd * 6);
+ m_series6->append(seriesAngularMin + ad * 19, seriesRadialMin + rd * 6);
+ m_series6->append(seriesAngularMin + ad * 20, seriesRadialMin + rd * 6);
+ m_series6->append(seriesAngularMin + ad * 19, seriesRadialMin + rd * 2);
+ m_series6->append(seriesAngularMin + ad * 18, seriesRadialMin + rd * 9);
+ m_series6->append(seriesAngularMin + ad * 17, seriesRadialMin + rd * 7);
+ m_series6->append(seriesAngularMin + ad * 16, seriesRadialMin + rd * 3);
+ m_series6->append(seriesAngularMin + ad * 15, seriesRadialMin + rd * 1);
+ m_series6->append(seriesAngularMin + ad * 14, seriesRadialMin + rd * 7);
+ m_series6->append(seriesAngularMin + ad * 13, seriesRadialMin + rd * 5);
+ m_series6->append(seriesAngularMin + ad * 12, seriesRadialMin + rd * 9);
+ m_series6->append(seriesAngularMin + ad * 11, seriesRadialMin + rd * 1);
+ m_series6->append(seriesAngularMin + ad * 10, seriesRadialMin + rd * 4);
+ m_series6->append(seriesAngularMin + ad * 9, seriesRadialMin + rd * 1);
+ m_series6->append(seriesAngularMin + ad * 8, seriesRadialMin + rd * 2);
+ m_series6->append(seriesAngularMin + ad * 7, seriesRadialMin + rd * 4);
+ m_series6->append(seriesAngularMin + ad * 6, seriesRadialMin + rd * 8);
+ m_series6->append(seriesAngularMin + ad * 5, seriesRadialMin + rd * 12);
+ m_series6->append(seriesAngularMin + ad * 4, seriesRadialMin + rd * 9);
+ m_series6->append(seriesAngularMin + ad * 3, seriesRadialMin + rd * 8);
+ m_series6->append(seriesAngularMin + ad * 2, seriesRadialMin + rd * 7);
+ m_series6->append(seriesAngularMin + ad, seriesRadialMin + rd * 4);
+ m_series6->append(seriesAngularMin, seriesRadialMin + rd * 10);
+
+ m_series6->setPointsVisible(true);
+ QPen series6Pen = QPen(Qt::red, 10);
+ //series6Pen.setStyle(Qt::DashDotDotLine);
+ m_series6->setPen(series6Pen);
+
+ // m_series7 shows points at category intersections
+ m_series7 = new QScatterSeries();
+ m_series7->setName("Category check");
+ m_series7->setMarkerSize(7);
+ m_series7->setBrush(QColor(Qt::red));
+ m_series7->setMarkerShape(QScatterSeries::MarkerShapeRectangle);
+ *m_series7 << QPointF(1000, 1000)
+ << QPointF(1000, 2000)
+ << QPointF(1000, 4000)
+ << QPointF(1000, 9000)
+ << QPointF(1000, 14000)
+ << QPointF(1000, 16500)
+ << QPointF(1000, 19000)
+
+ << QPointF(4000, 1000)
+ << QPointF(4000, 2000)
+ << QPointF(4000, 4000)
+ << QPointF(4000, 9000)
+ << QPointF(4000, 14000)
+ << QPointF(4000, 16500)
+ << QPointF(4000, 19000)
+
+ << QPointF(7000, 1000)
+ << QPointF(7000, 2000)
+ << QPointF(7000, 4000)
+ << QPointF(7000, 9000)
+ << QPointF(7000, 14000)
+ << QPointF(7000, 16500)
+ << QPointF(7000, 19000)
+
+ << QPointF(12000, 1000)
+ << QPointF(12000, 2000)
+ << QPointF(12000, 4000)
+ << QPointF(12000, 9000)
+ << QPointF(12000, 14000)
+ << QPointF(12000, 16500)
+ << QPointF(12000, 19000)
+
+ << QPointF(17000, 1000)
+ << QPointF(17000, 2000)
+ << QPointF(17000, 4000)
+ << QPointF(17000, 9000)
+ << QPointF(17000, 14000)
+ << QPointF(17000, 16500)
+ << QPointF(17000, 19000)
+
+ << QPointF(22000, 1000)
+ << QPointF(22000, 2000)
+ << QPointF(22000, 4000)
+ << QPointF(22000, 9000)
+ << QPointF(22000, 14000)
+ << QPointF(22000, 16500)
+ << QPointF(22000, 19000)
+
+ << QPointF(28000, 1000)
+ << QPointF(28000, 2000)
+ << QPointF(28000, 4000)
+ << QPointF(28000, 9000)
+ << QPointF(28000, 14000)
+ << QPointF(28000, 16500)
+ << QPointF(28000, 19000);
+
+ m_chart = new QPolarChart();
+
+ m_chart->addSeries(m_series1);
+ m_chart->addSeries(m_series2);
+ m_chart->addSeries(m_series3);
+ m_chart->addSeries(m_series4);
+ m_chart->addSeries(m_series5);
+ m_chart->addSeries(m_series6);
+ m_chart->addSeries(m_series7);
+
+ connect(m_series1, SIGNAL(clicked(QPointF)), this, SLOT(seriesClicked(QPointF)));
+ connect(m_series2, SIGNAL(clicked(QPointF)), this, SLOT(seriesClicked(QPointF)));
+ connect(m_series3, SIGNAL(clicked(QPointF)), this, SLOT(seriesClicked(QPointF)));
+ connect(m_series4, SIGNAL(clicked(QPointF)), this, SLOT(seriesClicked(QPointF)));
+ connect(m_series5, SIGNAL(clicked(QPointF)), this, SLOT(seriesClicked(QPointF)));
+ connect(m_series6, SIGNAL(clicked(QPointF)), this, SLOT(seriesClicked(QPointF)));
+ connect(m_series7, SIGNAL(clicked(QPointF)), this, SLOT(seriesClicked(QPointF)));
+ connect(m_series1, SIGNAL(hovered(QPointF, bool)), this, SLOT(seriesHovered(QPointF, bool)));
+ connect(m_series2, SIGNAL(hovered(QPointF, bool)), this, SLOT(seriesHovered(QPointF, bool)));
+ connect(m_series3, SIGNAL(hovered(QPointF, bool)), this, SLOT(seriesHovered(QPointF, bool)));
+ connect(m_series4, SIGNAL(hovered(QPointF, bool)), this, SLOT(seriesHovered(QPointF, bool)));
+ connect(m_series5, SIGNAL(hovered(QPointF, bool)), this, SLOT(seriesHovered(QPointF, bool)));
+ connect(m_series6, SIGNAL(hovered(QPointF, bool)), this, SLOT(seriesHovered(QPointF, bool)));
+ connect(m_series7, SIGNAL(hovered(QPointF, bool)), this, SLOT(seriesHovered(QPointF, bool)));
+
+ m_chart->setTitle("Use arrow keys to scroll and +/- to zoom");
+ m_chart->setAnimationOptions(m_animationOptions);
+ //m_chart->legend()->setVisible(false);
+ m_chart->setAcceptHoverEvents(true);
+}
+
+void MainWindow::setAngularAxis(MainWindow::AxisMode mode)
+{
+ if (m_angularAxis) {
+ m_chart->removeAxis(m_angularAxis);
+ delete m_angularAxis;
+ m_angularAxis = 0;
+ }
+
+ m_angularAxisMode = mode;
+
+ switch (m_angularAxisMode) {
+ case AxisModeNone:
+ return;
+ case AxisModeValue:
+ m_angularAxis = new QValueAxis();
+ static_cast<QValueAxis *>(m_angularAxis)->setTickCount(m_angularTickCount);
+ static_cast<QValueAxis *>(m_angularAxis)->setLabelFormat(m_labelFormat);
+ break;
+ case AxisModeLogValue:
+ m_angularAxis = new QLogValueAxis();
+ static_cast<QLogValueAxis *>(m_angularAxis)->setBase(m_base);
+ static_cast<QLogValueAxis *>(m_angularAxis)->setLabelFormat(m_labelFormat);
+ break;
+ case AxisModeDateTime:
+ m_angularAxis = new QDateTimeAxis();
+ static_cast<QDateTimeAxis *>(m_angularAxis)->setTickCount(m_angularTickCount);
+ static_cast<QDateTimeAxis *>(m_angularAxis)->setFormat(m_dateFormat);
+ break;
+ case AxisModeCategory:
+ m_angularAxis = new QCategoryAxis();
+ applyCategories();
+ break;
+ default:
+ qWarning() << "Unsupported AxisMode";
+ break;
+ }
+
+ m_angularAxis->setLabelsAngle(m_labelsAngle);
+ m_angularAxis->setLabelsFont(m_currentLabelFont);
+ m_angularAxis->setLabelsBrush(*m_labelBrush);
+ m_angularAxis->setLabelsPen(*m_labelPen);
+ m_angularAxis->setLabelsVisible(m_labelsVisible);
+ m_angularAxis->setShadesBrush(*m_angularShadesBrush);
+ m_angularAxis->setShadesPen(*m_angularShadesPen);
+ m_angularAxis->setShadesVisible(m_angularShadesVisible);
+ m_angularAxis->setTitleFont(m_currentTitleFont);
+ m_angularAxis->setTitleBrush(*m_titleBrush);
+ m_angularAxis->setTitlePen(*m_titlePen);
+ m_angularAxis->setTitleVisible(m_titleVisible);
+ m_angularAxis->setTitleText(m_angularTitle);
+ m_angularAxis->setGridLinePen(*m_gridPen);
+ m_angularAxis->setGridLineVisible(m_gridVisible);
+ m_angularAxis->setLinePen(*m_arrowPen);
+ m_angularAxis->setLineVisible(m_arrowVisible);
+
+ m_chart->addAxis(m_angularAxis, QPolarChart::PolarOrientationAngular);
+
+ m_series1->attachAxis(m_angularAxis);
+ m_series2->attachAxis(m_angularAxis);
+ m_series3->attachAxis(m_angularAxis);
+ m_series4->attachAxis(m_angularAxis);
+ m_series5->attachAxis(m_angularAxis);
+ m_series6->attachAxis(m_angularAxis);
+ m_series7->attachAxis(m_angularAxis);
+
+ applyRanges();
+
+ //connect(m_angularAxis, SIGNAL(rangeChanged(qreal, qreal)), this, SLOT(angularRangeChanged(qreal, qreal)));
+}
+
+void MainWindow::setRadialAxis(MainWindow::AxisMode mode)
+{
+ if (m_radialAxis) {
+ m_chart->removeAxis(m_radialAxis);
+ delete m_radialAxis;
+ m_radialAxis = 0;
+ }
+
+ m_radialAxisMode = mode;
+
+ switch (m_radialAxisMode) {
+ case AxisModeNone:
+ return;
+ case AxisModeValue:
+ m_radialAxis = new QValueAxis();
+ static_cast<QValueAxis *>(m_radialAxis)->setTickCount(m_radialTickCount);
+ static_cast<QValueAxis *>(m_radialAxis)->setLabelFormat(m_labelFormat);
+ break;
+ case AxisModeLogValue:
+ m_radialAxis = new QLogValueAxis();
+ static_cast<QLogValueAxis *>(m_radialAxis)->setBase(m_base);
+ static_cast<QLogValueAxis *>(m_radialAxis)->setLabelFormat(m_labelFormat);
+ break;
+ case AxisModeDateTime:
+ m_radialAxis = new QDateTimeAxis();
+ static_cast<QDateTimeAxis *>(m_radialAxis)->setTickCount(m_radialTickCount);
+ static_cast<QDateTimeAxis *>(m_radialAxis)->setFormat(m_dateFormat);
+ break;
+ case AxisModeCategory:
+ m_radialAxis = new QCategoryAxis();
+ applyCategories();
+ break;
+ default:
+ qWarning() << "Unsupported AxisMode";
+ break;
+ }
+
+ m_radialAxis->setLabelsAngle(m_labelsAngle);
+ m_radialAxis->setLabelsFont(m_currentLabelFont);
+ m_radialAxis->setLabelsBrush(*m_labelBrush);
+ m_radialAxis->setLabelsPen(*m_labelPen);
+ m_radialAxis->setLabelsVisible(m_labelsVisible);
+ m_radialAxis->setShadesBrush(*m_radialShadesBrush);
+ m_radialAxis->setShadesPen(*m_radialShadesPen);
+ m_radialAxis->setShadesVisible(m_radialShadesVisible);
+ m_radialAxis->setTitleFont(m_currentTitleFont);
+ m_radialAxis->setTitleBrush(*m_titleBrush);
+ m_radialAxis->setTitlePen(*m_titlePen);
+ m_radialAxis->setTitleVisible(m_titleVisible);
+ m_radialAxis->setTitleText(m_radialTitle);
+ m_radialAxis->setGridLinePen(*m_gridPen);
+ m_radialAxis->setGridLineVisible(m_gridVisible);
+ m_radialAxis->setLinePen(*m_arrowPen);
+ m_radialAxis->setLineVisible(m_arrowVisible);
+
+ m_chart->addAxis(m_radialAxis, QPolarChart::PolarOrientationRadial);
+
+ m_series1->attachAxis(m_radialAxis);
+ m_series2->attachAxis(m_radialAxis);
+ m_series3->attachAxis(m_radialAxis);
+ m_series4->attachAxis(m_radialAxis);
+ m_series5->attachAxis(m_radialAxis);
+ m_series6->attachAxis(m_radialAxis);
+ m_series7->attachAxis(m_radialAxis);
+
+ applyRanges();
+
+ series1CheckBoxChecked();
+ series2CheckBoxChecked();
+ series3CheckBoxChecked();
+ series4CheckBoxChecked();
+ series5CheckBoxChecked();
+ series6CheckBoxChecked();
+ series7CheckBoxChecked();
+
+ //connect(m_radialAxis, SIGNAL(rangeChanged(qreal, qreal)), this, SLOT(radialRangeChanged(qreal, qreal)));
+}
+
+void MainWindow::applyRanges()
+{
+ if (ui->niceNumbersCheckBox->isChecked()) {
+ if (m_angularAxisMode == AxisModeValue) {
+ static_cast<QValueAxis *>(m_angularAxis)->applyNiceNumbers();
+ m_angularMin = static_cast<QValueAxis *>(m_angularAxis)->min();
+ m_angularMax = static_cast<QValueAxis *>(m_angularAxis)->max();
+ m_angularTickCount = static_cast<QValueAxis *>(m_angularAxis)->tickCount();
+ }
+ if (m_radialAxisMode == AxisModeValue) {
+ static_cast<QValueAxis *>(m_radialAxis)->applyNiceNumbers();
+ m_radialMin = static_cast<QValueAxis *>(m_radialAxis)->min();
+ m_radialMax = static_cast<QValueAxis *>(m_radialAxis)->max();
+ m_radialTickCount = static_cast<QValueAxis *>(m_radialAxis)->tickCount();
+ }
+ }
+
+ if (m_angularAxis)
+ m_angularAxis->setRange(m_angularMin, m_angularMax);
+ if (m_radialAxis)
+ m_radialAxis->setRange(m_radialMin, m_radialMax);
+}
+
+void MainWindow::angularTicksChanged(int value)
+{
+ m_angularTickCount = value;
+ if (m_angularAxisMode == AxisModeValue)
+ static_cast<QValueAxis *>(m_angularAxis)->setTickCount(m_angularTickCount);
+ else if (m_angularAxisMode == AxisModeDateTime)
+ static_cast<QDateTimeAxis *>(m_angularAxis)->setTickCount(m_angularTickCount);
+}
+
+void MainWindow::radialTicksChanged(int value)
+{
+ m_radialTickCount = value;
+ if (m_radialAxisMode == AxisModeValue)
+ static_cast<QValueAxis *>(m_radialAxis)->setTickCount(m_radialTickCount);
+ else if (m_radialAxisMode == AxisModeDateTime)
+ static_cast<QDateTimeAxis *>(m_radialAxis)->setTickCount(m_radialTickCount);
+}
+
+void MainWindow::anglesChanged(int value)
+{
+ m_labelsAngle = value;
+ m_radialAxis->setLabelsAngle(m_labelsAngle);
+ m_angularAxis->setLabelsAngle(m_labelsAngle);
+}
+
+void MainWindow::angularMinChanged(double value)
+{
+ m_angularMin = value;
+ if (m_angularAxisMode != AxisModeDateTime) {
+ m_angularAxis->setMin(m_angularMin);
+ } else {
+ QDateTime dateTime;
+ dateTime.setMSecsSinceEpoch(qint64(m_angularMin));
+ m_angularAxis->setMin(dateTime);
+ }
+}
+
+void MainWindow::angularMaxChanged(double value)
+{
+ m_angularMax = value;
+ if (m_angularAxisMode != AxisModeDateTime) {
+ m_angularAxis->setMax(m_angularMax);
+ } else {
+ QDateTime dateTime;
+ dateTime.setMSecsSinceEpoch(qint64(m_angularMax));
+ m_angularAxis->setMax(dateTime);
+ }
+}
+
+void MainWindow::radialMinChanged(double value)
+{
+ m_radialMin = value;
+ if (m_radialAxisMode != AxisModeDateTime) {
+ m_radialAxis->setMin(m_radialMin);
+ } else {
+ QDateTime dateTime;
+ dateTime.setMSecsSinceEpoch(qint64(m_radialMin));
+ m_radialAxis->setMin(dateTime);
+ }
+}
+
+void MainWindow::radialMaxChanged(double value)
+{
+ m_radialMax = value;
+ if (m_radialAxisMode != AxisModeDateTime) {
+ m_radialAxis->setMax(m_radialMax);
+ } else {
+ QDateTime dateTime;
+ dateTime.setMSecsSinceEpoch(qint64(m_radialMax));
+ m_radialAxis->setMax(dateTime);
+ }
+}
+
+void MainWindow::angularShadesIndexChanged(int index)
+{
+ delete m_angularShadesBrush;
+ delete m_angularShadesPen;
+
+ switch (index) {
+ case 0:
+ m_angularShadesBrush = new QBrush(Qt::NoBrush);
+ m_angularShadesPen = new QPen(Qt::NoPen);
+ m_angularShadesVisible = false;
+ break;
+ case 1:
+ m_angularShadesBrush = new QBrush(Qt::lightGray);
+ m_angularShadesPen = new QPen(Qt::NoPen);
+ m_angularShadesVisible = true;
+ break;
+ case 2:
+ m_angularShadesBrush = new QBrush(Qt::yellow);
+ m_angularShadesPen = new QPen(Qt::DotLine);
+ m_angularShadesPen->setWidth(2);
+ m_angularShadesVisible = true;
+ break;
+ default:
+ break;
+ }
+
+ m_angularAxis->setShadesBrush(*m_angularShadesBrush);
+ m_angularAxis->setShadesPen(*m_angularShadesPen);
+ m_angularAxis->setShadesVisible(m_angularShadesVisible);
+}
+
+void MainWindow::radialShadesIndexChanged(int index)
+{
+ delete m_radialShadesBrush;
+ delete m_radialShadesPen;
+
+ switch (index) {
+ case 0:
+ m_radialShadesBrush = new QBrush(Qt::NoBrush);
+ m_radialShadesPen = new QPen(Qt::NoPen);
+ m_radialShadesVisible = false;
+ break;
+ case 1:
+ m_radialShadesBrush = new QBrush(Qt::green);
+ m_radialShadesPen = new QPen(Qt::NoPen);
+ m_radialShadesVisible = true;
+ break;
+ case 2:
+ m_radialShadesBrush = new QBrush(Qt::blue);
+ m_radialShadesPen = new QPen(Qt::DotLine);
+ m_radialShadesPen->setWidth(2);
+ m_radialShadesVisible = true;
+ break;
+ default:
+ break;
+ }
+
+ m_radialAxis->setShadesBrush(*m_radialShadesBrush);
+ m_radialAxis->setShadesPen(*m_radialShadesPen);
+ m_radialAxis->setShadesVisible(m_radialShadesVisible);
+}
+
+void MainWindow::labelFormatEdited(const QString &text)
+{
+ m_labelFormat = text;
+ if (m_angularAxisMode == AxisModeValue)
+ static_cast<QValueAxis *>(m_angularAxis)->setLabelFormat(m_labelFormat);
+ else if (m_angularAxisMode == AxisModeLogValue)
+ static_cast<QLogValueAxis *>(m_angularAxis)->setLabelFormat(m_labelFormat);
+
+ if (m_radialAxisMode == AxisModeValue)
+ static_cast<QValueAxis *>(m_radialAxis)->setLabelFormat(m_labelFormat);
+ else if (m_radialAxisMode == AxisModeLogValue)
+ static_cast<QLogValueAxis *>(m_radialAxis)->setLabelFormat(m_labelFormat);
+}
+
+void MainWindow::labelFontChanged(const QFont &font)
+{
+ m_currentLabelFont = font;
+ m_currentLabelFont.setPixelSize(ui->labelFontSizeSpin->value());
+ m_angularAxis->setLabelsFont(m_currentLabelFont);
+ m_radialAxis->setLabelsFont(m_currentLabelFont);
+}
+
+void MainWindow::labelFontSizeChanged(int value)
+{
+ m_currentLabelFont = ui->labelFontComboBox->currentFont();
+ m_currentLabelFont.setPixelSize(value);
+ m_angularAxis->setLabelsFont(m_currentLabelFont);
+ m_radialAxis->setLabelsFont(m_currentLabelFont);
+}
+
+void MainWindow::animationIndexChanged(int index)
+{
+ switch (index) {
+ case 0:
+ m_animationOptions = QChart::NoAnimation;
+ break;
+ case 1:
+ m_animationOptions = QChart::SeriesAnimations;
+ break;
+ case 2:
+ m_animationOptions = QChart::GridAxisAnimations;
+ break;
+ case 3:
+ m_animationOptions = QChart::AllAnimations;
+ break;
+ default:
+ break;
+ }
+
+ m_chart->setAnimationOptions(m_animationOptions);
+}
+
+void MainWindow::labelsIndexChanged(int index)
+{
+ delete m_labelBrush;
+ delete m_labelPen;
+
+ switch (index) {
+ case 0:
+ m_labelBrush = new QBrush(Qt::NoBrush);
+ m_labelPen = new QPen(Qt::NoPen);
+ m_labelsVisible = false;
+ break;
+ case 1:
+ m_labelBrush = new QBrush(Qt::black);
+ m_labelPen = new QPen(Qt::NoPen);
+ m_labelsVisible = true;
+ break;
+ case 2:
+ m_labelBrush = new QBrush(Qt::white);
+ m_labelPen = new QPen(Qt::blue);
+ m_labelsVisible = true;
+ break;
+ default:
+ break;
+ }
+
+ m_radialAxis->setLabelsBrush(*m_labelBrush);
+ m_radialAxis->setLabelsPen(*m_labelPen);
+ m_radialAxis->setLabelsVisible(m_labelsVisible);
+ m_angularAxis->setLabelsBrush(*m_labelBrush);
+ m_angularAxis->setLabelsPen(*m_labelPen);
+ m_angularAxis->setLabelsVisible(m_labelsVisible);
+}
+
+void MainWindow::titleIndexChanged(int index)
+{
+ delete m_titleBrush;
+ delete m_titlePen;
+
+ switch (index) {
+ case 0:
+ m_titleBrush = new QBrush(Qt::NoBrush);
+ m_titlePen = new QPen(Qt::NoPen);
+ m_titleVisible = false;
+ m_angularTitle = QString();
+ m_radialTitle = QString();
+ break;
+ case 1:
+ m_titleBrush = new QBrush(Qt::NoBrush);
+ m_titlePen = new QPen(Qt::NoPen);
+ m_titleVisible = true;
+ m_angularTitle = QString();
+ m_radialTitle = QString();
+ break;
+ case 2:
+ m_titleBrush = new QBrush(Qt::NoBrush);
+ m_titlePen = new QPen(Qt::NoPen);
+ m_titleVisible = false;
+ m_angularTitle = QString("Invisible Ang. Title!");
+ m_radialTitle = QString("Invisible Rad. Title!");
+ break;
+ case 3:
+ m_titleBrush = new QBrush(Qt::black);
+ m_titlePen = new QPen(Qt::NoPen);
+ m_titleVisible = true;
+ m_angularTitle = QString("Angular Title");
+ m_radialTitle = QString("Radial Title");
+ break;
+ case 4:
+ m_titleBrush = new QBrush(Qt::white);
+ m_titlePen = new QPen(Qt::blue);
+ m_titleVisible = true;
+ m_angularTitle = QString("Angular Blue Title");
+ m_radialTitle = QString("Radial Blue Title");
+ break;
+ default:
+ break;
+ }
+
+ m_radialAxis->setTitleBrush(*m_titleBrush);
+ m_radialAxis->setTitlePen(*m_titlePen);
+ m_radialAxis->setTitleVisible(m_titleVisible);
+ m_radialAxis->setTitleText(m_radialTitle);
+ m_angularAxis->setTitleBrush(*m_titleBrush);
+ m_angularAxis->setTitlePen(*m_titlePen);
+ m_angularAxis->setTitleVisible(m_titleVisible);
+ m_angularAxis->setTitleText(m_angularTitle);
+}
+
+void MainWindow::titleFontChanged(const QFont &font)
+{
+ m_currentTitleFont = font;
+ m_currentTitleFont.setPixelSize(ui->titleFontSizeSpin->value());
+ m_angularAxis->setTitleFont(m_currentTitleFont);
+ m_radialAxis->setTitleFont(m_currentTitleFont);
+}
+
+void MainWindow::titleFontSizeChanged(int value)
+{
+ m_currentTitleFont = ui->titleFontComboBox->currentFont();
+ m_currentTitleFont.setPixelSize(value);
+ m_angularAxis->setTitleFont(m_currentTitleFont);
+ m_radialAxis->setTitleFont(m_currentTitleFont);
+}
+
+void MainWindow::gridIndexChanged(int index)
+{
+ delete m_gridPen;
+
+ switch (index) {
+ case 0:
+ m_gridPen = new QPen(Qt::NoPen);
+ m_gridVisible = false;
+ break;
+ case 1:
+ m_gridPen = new QPen(Qt::black);
+ m_gridVisible = true;
+ break;
+ case 2:
+ m_gridPen = new QPen(Qt::red);
+ m_gridPen->setStyle(Qt::DashDotLine);
+ m_gridPen->setWidth(3);
+ m_gridVisible = true;
+ break;
+ default:
+ break;
+ }
+
+ m_angularAxis->setGridLinePen(*m_gridPen);
+ m_angularAxis->setGridLineVisible(m_gridVisible);
+ m_radialAxis->setGridLinePen(*m_gridPen);
+ m_radialAxis->setGridLineVisible(m_gridVisible);
+}
+
+void MainWindow::arrowIndexChanged(int index)
+{
+ delete m_arrowPen;
+
+ switch (index) {
+ case 0:
+ m_arrowPen = new QPen(Qt::NoPen);
+ m_arrowVisible = false;
+ break;
+ case 1:
+ m_arrowPen = new QPen(Qt::black);
+ m_arrowVisible = true;
+ break;
+ case 2:
+ m_arrowPen = new QPen(Qt::red);
+ m_arrowPen->setStyle(Qt::DashDotLine);
+ m_arrowPen->setWidth(3);
+ m_arrowVisible = true;
+ break;
+ default:
+ break;
+ }
+
+ m_angularAxis->setLinePen(*m_arrowPen);
+ m_angularAxis->setLineVisible(m_arrowVisible);
+ m_radialAxis->setLinePen(*m_arrowPen);
+ m_radialAxis->setLineVisible(m_arrowVisible);
+}
+
+void MainWindow::angularRangeChanged(qreal min, qreal max)
+{
+ if (!qFuzzyCompare(ui->angularMinSpin->value(), min))
+ ui->angularMinSpin->setValue(min);
+ if (!qFuzzyCompare(ui->angularMaxSpin->value(), max))
+ ui->angularMaxSpin->setValue(max);
+}
+
+void MainWindow::radialRangeChanged(qreal min, qreal max)
+{
+ if (!qFuzzyCompare(ui->radialMinSpin->value(), min))
+ ui->radialMinSpin->setValue(min);
+ if (!qFuzzyCompare(ui->radialMaxSpin->value(), max))
+ ui->radialMaxSpin->setValue(max);
+}
+
+void MainWindow::angularAxisIndexChanged(int index)
+{
+ switch (index) {
+ case 0:
+ setAngularAxis(AxisModeNone);
+ break;
+ case 1:
+ setAngularAxis(AxisModeValue);
+ break;
+ case 2:
+ setAngularAxis(AxisModeLogValue);
+ break;
+ case 3:
+ setAngularAxis(AxisModeDateTime);
+ break;
+ case 4:
+ setAngularAxis(AxisModeCategory);
+ break;
+ default:
+ qWarning("Invalid Index!");
+ }
+}
+
+void MainWindow::radialAxisIndexChanged(int index)
+{
+ switch (index) {
+ case 0:
+ setRadialAxis(AxisModeNone);
+ break;
+ case 1:
+ setRadialAxis(AxisModeValue);
+ break;
+ case 2:
+ setRadialAxis(AxisModeLogValue);
+ break;
+ case 3:
+ setRadialAxis(AxisModeDateTime);
+ break;
+ case 4:
+ setRadialAxis(AxisModeCategory);
+ break;
+ default:
+ qWarning("Invalid Index!");
+ }
+}
+
+void MainWindow::logBaseChanged(double value)
+{
+ m_base = value;
+ if (m_angularAxisMode == AxisModeLogValue)
+ static_cast<QLogValueAxis *>(m_angularAxis)->setBase(m_base);
+ if (m_radialAxisMode == AxisModeLogValue)
+ static_cast<QLogValueAxis *>(m_radialAxis)->setBase(m_base);
+}
+
+void MainWindow::niceNumbersChecked()
+{
+ if (ui->niceNumbersCheckBox->isChecked())
+ applyRanges();
+}
+
+void MainWindow::dateFormatEdited(const QString &text)
+{
+ m_dateFormat = text;
+ if (m_angularAxisMode == AxisModeDateTime)
+ static_cast<QDateTimeAxis *>(m_angularAxis)->setFormat(m_dateFormat);
+ if (m_radialAxisMode == AxisModeDateTime)
+ static_cast<QDateTimeAxis *>(m_radialAxis)->setFormat(m_dateFormat);
+}
+
+void MainWindow::moreCategoriesChecked()
+{
+ applyCategories();
+ m_moreCategories = ui->moreCategoriesCheckBox->isChecked();
+}
+
+void MainWindow::series1CheckBoxChecked()
+{
+ if (ui->series1checkBox->isChecked())
+ m_series1->setVisible(true);
+ else
+ m_series1->setVisible(false);
+}
+
+void MainWindow::series2CheckBoxChecked()
+{
+ if (ui->series2checkBox->isChecked())
+ m_series2->setVisible(true);
+ else
+ m_series2->setVisible(false);
+}
+
+void MainWindow::series3CheckBoxChecked()
+{
+ if (ui->series3checkBox->isChecked())
+ m_series3->setVisible(true);
+ else
+ m_series3->setVisible(false);
+}
+
+void MainWindow::series4CheckBoxChecked()
+{
+ if (ui->series4checkBox->isChecked())
+ m_series4->setVisible(true);
+ else
+ m_series4->setVisible(false);
+}
+
+void MainWindow::series5CheckBoxChecked()
+{
+ if (ui->series5checkBox->isChecked())
+ m_series5->setVisible(true);
+ else
+ m_series5->setVisible(false);
+}
+
+void MainWindow::series6CheckBoxChecked()
+{
+ if (ui->series6checkBox->isChecked())
+ m_series6->setVisible(true);
+ else
+ m_series6->setVisible(false);
+}
+
+void MainWindow::series7CheckBoxChecked()
+{
+ if (ui->series7checkBox->isChecked())
+ m_series7->setVisible(true);
+ else
+ m_series7->setVisible(false);
+}
+
+void MainWindow::themeIndexChanged(int index)
+{
+ m_chart->setTheme(QChart::ChartTheme(index));
+}
+
+void MainWindow::seriesHovered(QPointF point, bool state)
+{
+ QAbstractSeries *series = qobject_cast<QAbstractSeries *>(sender());
+ if (series) {
+ if (state) {
+ QString str("'%3' - %1 x %2");
+ ui->hoverLabel->setText(str.arg(point.x()).arg(point.y()).arg(series->name()));
+ } else {
+ ui->hoverLabel->setText("No hover");
+ }
+ } else {
+ qDebug() << "seriesHovered - invalid sender!";
+ }
+}
+
+void MainWindow::seriesClicked(const QPointF &point)
+{
+ QAbstractSeries *series = qobject_cast<QAbstractSeries *>(sender());
+ if (series) {
+ QString str("'%3' clicked at: %1 x %2");
+ m_angularTitle = str.arg(point.x()).arg(point.y()).arg(series->name());
+ m_angularAxis->setTitleText(m_angularTitle);
+ } else {
+ qDebug() << "seriesClicked - invalid sender!";
+ }
+}
+
+void MainWindow::applyCategories()
+{
+ // Basic layout is three categories, extended has five
+ if (m_angularAxisMode == AxisModeCategory) {
+ QCategoryAxis *angCatAxis = static_cast<QCategoryAxis *>(m_angularAxis);
+ if (angCatAxis->count() == 0) {
+ angCatAxis->setStartValue(4000);
+ angCatAxis->append("Category A", 7000);
+ angCatAxis->append("Category B", 12000);
+ angCatAxis->append("Category C", 17000);
+ }
+ if (angCatAxis->count() == 3 && ui->moreCategoriesCheckBox->isChecked()) {
+ angCatAxis->setStartValue(1000);
+ angCatAxis->replaceLabel("Category A", "Cat A");
+ angCatAxis->replaceLabel("Category B", "Cat B");
+ angCatAxis->replaceLabel("Category C", "Cat C");
+ angCatAxis->append("Cat D", 22000);
+ angCatAxis->append("Cat E", 28000);
+ } else if (angCatAxis->count() == 5 && !ui->moreCategoriesCheckBox->isChecked()) {
+ angCatAxis->setStartValue(4000);
+ angCatAxis->replaceLabel("Cat A", "Category A");
+ angCatAxis->replaceLabel("Cat B", "Category B");
+ angCatAxis->replaceLabel("Cat C", "Category C");
+ angCatAxis->remove("Cat D");
+ angCatAxis->remove("Cat E");
+ }
+ }
+
+ if (m_radialAxisMode == AxisModeCategory) {
+ QCategoryAxis *radCatAxis = static_cast<QCategoryAxis *>(m_radialAxis);
+ if (radCatAxis->count() == 0) {
+ radCatAxis->setStartValue(2000);
+ radCatAxis->append("Category 1", 4000);
+ radCatAxis->append("Category 2", 9000);
+ radCatAxis->append("Category 3", 14000);
+ }
+ if (radCatAxis->count() == 3 && ui->moreCategoriesCheckBox->isChecked()) {
+ radCatAxis->setStartValue(1000);
+ radCatAxis->replaceLabel("Category 1", "Cat 1");
+ radCatAxis->replaceLabel("Category 2", "Cat 2");
+ radCatAxis->replaceLabel("Category 3", "Cat 3");
+ radCatAxis->append("Cat 4", 16500);
+ radCatAxis->append("Cat 5", 19000);
+ } else if (radCatAxis->count() == 5 && !ui->moreCategoriesCheckBox->isChecked()) {
+ radCatAxis->setStartValue(2000);
+ radCatAxis->replaceLabel("Cat 1", "Category 1");
+ radCatAxis->replaceLabel("Cat 2", "Category 2");
+ radCatAxis->replaceLabel("Cat 3", "Category 3");
+ radCatAxis->remove("Cat 4");
+ radCatAxis->remove("Cat 5");
+ }
+ }
+}
diff --git a/tests/polarcharttest/mainwindow.h b/tests/polarcharttest/mainwindow.h
new file mode 100644
index 00000000..94aa7d84
--- /dev/null
+++ b/tests/polarcharttest/mainwindow.h
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Commercial Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you 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 MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QPolarChart>
+#include <QMainWindow>
+#include <QFont>
+#include <QChart>
+#include <QScatterSeries>
+#include <QLineSeries>
+#include <QSplineSeries>
+#include <QAreaSeries>
+
+namespace Ui {
+class MainWindow;
+}
+
+QTCOMMERCIALCHART_USE_NAMESPACE
+
+class QBrush;
+class QPen;
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindow(QWidget *parent = 0);
+ ~MainWindow();
+
+public slots:
+ void angularTicksChanged(int value);
+ void radialTicksChanged(int value);
+ void anglesChanged(int value);
+ void angularMinChanged(double value);
+ void angularMaxChanged(double value);
+ void radialMinChanged(double value);
+ void radialMaxChanged(double value);
+ void angularShadesIndexChanged(int index);
+ void radialShadesIndexChanged(int index);
+ void labelFormatEdited(const QString &text);
+ void labelFontChanged(const QFont &font);
+ void labelFontSizeChanged(int value);
+ void animationIndexChanged(int index);
+ void labelsIndexChanged(int index);
+ void titleIndexChanged(int index);
+ void titleFontChanged(const QFont &font);
+ void titleFontSizeChanged(int value);
+ void gridIndexChanged(int index);
+ void arrowIndexChanged(int index);
+ void angularRangeChanged(qreal min, qreal max);
+ void radialRangeChanged(qreal min, qreal max);
+ void angularAxisIndexChanged(int index);
+ void radialAxisIndexChanged(int index);
+ void logBaseChanged(double value);
+ void niceNumbersChecked();
+ void dateFormatEdited(const QString &text);
+ void moreCategoriesChecked();
+ void series1CheckBoxChecked();
+ void series2CheckBoxChecked();
+ void series3CheckBoxChecked();
+ void series4CheckBoxChecked();
+ void series5CheckBoxChecked();
+ void series6CheckBoxChecked();
+ void series7CheckBoxChecked();
+ void themeIndexChanged(int index);
+ void seriesHovered(QPointF point, bool state);
+ void seriesClicked(const QPointF &point);
+
+private:
+ enum AxisMode {
+ AxisModeNone,
+ AxisModeValue,
+ AxisModeLogValue,
+ AxisModeDateTime,
+ AxisModeCategory
+ };
+
+ void initXYValueChart();
+ void setAngularAxis(AxisMode mode);
+ void setRadialAxis(AxisMode mode);
+
+ void applyRanges();
+ void applyCategories();
+
+ Ui::MainWindow *ui;
+
+ int m_angularTickCount;
+ int m_radialTickCount;
+ qreal m_labelsAngle;
+ qreal m_angularMin;
+ qreal m_angularMax;
+ qreal m_radialMin;
+ qreal m_radialMax;
+ bool m_angularShadesVisible;
+ bool m_radialShadesVisible;
+ bool m_labelsVisible;
+ bool m_titleVisible;
+ bool m_gridVisible;
+ bool m_arrowVisible;
+ QBrush *m_angularShadesBrush;
+ QBrush *m_radialShadesBrush;
+ QBrush *m_labelBrush;
+ QBrush *m_titleBrush;
+ QPen *m_angularShadesPen;
+ QPen *m_radialShadesPen;
+ QPen *m_labelPen;
+ QPen *m_titlePen;
+ QPen *m_gridPen;
+ QPen *m_arrowPen;
+ QString m_labelFormat;
+ QFont m_currentLabelFont;
+ QFont m_currentTitleFont;
+ QChart::AnimationOptions m_animationOptions;
+ QString m_angularTitle;
+ QString m_radialTitle;
+ qreal m_base;
+ QString m_dateFormat;
+
+ QPolarChart *m_chart;
+ QAbstractAxis *m_angularAxis;
+ QAbstractAxis *m_radialAxis;
+ AxisMode m_angularAxisMode;
+ AxisMode m_radialAxisMode;
+ bool m_moreCategories;
+
+ QScatterSeries *m_series1;
+ QLineSeries *m_series2;
+ QLineSeries *m_series3;
+ QLineSeries *m_series4;
+ QAreaSeries *m_series5;
+ QSplineSeries *m_series6;
+ QScatterSeries *m_series7;
+};
+
+#endif // MAINWINDOW_H
diff --git a/tests/polarcharttest/mainwindow.ui b/tests/polarcharttest/mainwindow.ui
new file mode 100644
index 00000000..79cf3793
--- /dev/null
+++ b/tests/polarcharttest/mainwindow.ui
@@ -0,0 +1,929 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>1207</width>
+ <height>905</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>MainWindow</string>
+ </property>
+ <widget class="QWidget" name="centralWidget">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="ChartView" name="chartView"/>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="settingsBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>200</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="title">
+ <string>Settings</string>
+ </property>
+ <widget class="QSpinBox" name="radialTicksSpin">
+ <property name="geometry">
+ <rect>
+ <x>110</x>
+ <y>90</y>
+ <width>71</width>
+ <height>22</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>90</y>
+ <width>101</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Radial Tick count</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label_2">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>120</y>
+ <width>101</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Angular Tick count</string>
+ </property>
+ </widget>
+ <widget class="QSpinBox" name="angularTicksSpin">
+ <property name="geometry">
+ <rect>
+ <x>110</x>
+ <y>120</y>
+ <width>71</width>
+ <height>22</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QSpinBox" name="anglesSpin">
+ <property name="geometry">
+ <rect>
+ <x>110</x>
+ <y>150</y>
+ <width>71</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="minimum">
+ <number>-9999</number>
+ </property>
+ <property name="maximum">
+ <number>9999</number>
+ </property>
+ <property name="singleStep">
+ <number>5</number>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label_3">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>150</y>
+ <width>101</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Label angles</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label_4">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>180</y>
+ <width>101</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Angular min</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label_5">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>210</y>
+ <width>101</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Angular max</string>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="angularMinSpin">
+ <property name="geometry">
+ <rect>
+ <x>90</x>
+ <y>180</y>
+ <width>91</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="decimals">
+ <number>5</number>
+ </property>
+ <property name="minimum">
+ <double>-999999999.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>999999999.000000000000000</double>
+ </property>
+ <property name="singleStep">
+ <double>10.000000000000000</double>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="angularMaxSpin">
+ <property name="geometry">
+ <rect>
+ <x>90</x>
+ <y>210</y>
+ <width>91</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="decimals">
+ <number>5</number>
+ </property>
+ <property name="minimum">
+ <double>-999999999.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>999999999.000000000000000</double>
+ </property>
+ <property name="singleStep">
+ <double>10.000000000000000</double>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="radialMaxSpin">
+ <property name="geometry">
+ <rect>
+ <x>90</x>
+ <y>270</y>
+ <width>91</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="decimals">
+ <number>5</number>
+ </property>
+ <property name="minimum">
+ <double>-999999999.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>999999999.000000000000000</double>
+ </property>
+ <property name="singleStep">
+ <double>10.000000000000000</double>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="radialMinSpin">
+ <property name="geometry">
+ <rect>
+ <x>90</x>
+ <y>240</y>
+ <width>91</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="decimals">
+ <number>5</number>
+ </property>
+ <property name="minimum">
+ <double>-999999999.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>999999999.000000000000000</double>
+ </property>
+ <property name="singleStep">
+ <double>10.000000000000000</double>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label_11">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>270</y>
+ <width>101</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Radial max</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label_12">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>240</y>
+ <width>101</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Radial min</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" name="angularShadesComboBox">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>300</y>
+ <width>171</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <item>
+ <property name="text">
+ <string>No angular shades</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Gray angular shades</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Yellow ang. shades + custom pen</string>
+ </property>
+ </item>
+ </widget>
+ <widget class="QComboBox" name="radialShadesComboBox">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>330</y>
+ <width>171</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <item>
+ <property name="text">
+ <string>No radial shades</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Green radial shades</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Blue rad. shades + custom pen</string>
+ </property>
+ </item>
+ </widget>
+ <widget class="QLabel" name="label_13">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>360</y>
+ <width>101</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Label format</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" name="labelFormatEdit">
+ <property name="geometry">
+ <rect>
+ <x>100</x>
+ <y>360</y>
+ <width>81</width>
+ <height>20</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label_14">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>390</y>
+ <width>101</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Label font size</string>
+ </property>
+ </widget>
+ <widget class="QFontComboBox" name="labelFontComboBox">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>420</y>
+ <width>171</width>
+ <height>22</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QSpinBox" name="labelFontSizeSpin">
+ <property name="geometry">
+ <rect>
+ <x>100</x>
+ <y>390</y>
+ <width>81</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="minimum">
+ <number>-100000</number>
+ </property>
+ <property name="maximum">
+ <number>100000</number>
+ </property>
+ </widget>
+ <widget class="QComboBox" name="animationsComboBox">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>480</y>
+ <width>171</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <item>
+ <property name="text">
+ <string>No animations</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Series animation</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Grid animation</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>All animations</string>
+ </property>
+ </item>
+ </widget>
+ <widget class="QComboBox" name="labelComboBox">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>450</y>
+ <width>171</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="currentIndex">
+ <number>1</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>No labels</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Black label</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>White label + blue pen</string>
+ </property>
+ </item>
+ </widget>
+ <widget class="QSpinBox" name="titleFontSizeSpin">
+ <property name="geometry">
+ <rect>
+ <x>100</x>
+ <y>510</y>
+ <width>81</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="minimum">
+ <number>-100000</number>
+ </property>
+ <property name="maximum">
+ <number>100000</number>
+ </property>
+ </widget>
+ <widget class="QComboBox" name="titleComboBox">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>570</y>
+ <width>171</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="currentIndex">
+ <number>3</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>Invisible empty title</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Visible empty title</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Invisible title</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Black title</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>White title + blue pen</string>
+ </property>
+ </item>
+ </widget>
+ <widget class="QFontComboBox" name="titleFontComboBox">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>540</y>
+ <width>171</width>
+ <height>22</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label_15">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>510</y>
+ <width>101</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Title font size</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" name="gridComboBox">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>600</y>
+ <width>171</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="currentIndex">
+ <number>1</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>Invisible grid</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Black grid</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Custom grid pen</string>
+ </property>
+ </item>
+ </widget>
+ <widget class="QComboBox" name="arrowComboBox">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>630</y>
+ <width>171</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="currentIndex">
+ <number>1</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>Invisible arrow</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Black arrow</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Custom arrow pen</string>
+ </property>
+ </item>
+ </widget>
+ <widget class="QComboBox" name="angularAxisComboBox">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>20</y>
+ <width>171</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="currentIndex">
+ <number>1</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>No Angular Axis</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Angular Value Axis</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Angular Log Axis</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Angular DateTime Axis</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Angular Category Axis</string>
+ </property>
+ </item>
+ </widget>
+ <widget class="QComboBox" name="radialAxisComboBox">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>50</y>
+ <width>171</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="currentIndex">
+ <number>1</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>No Radial Axis</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Radial Value Axis</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Radial Log Axis</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Radial DateTime Axis</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Radial Category Axis</string>
+ </property>
+ </item>
+ </widget>
+ <widget class="QLabel" name="label_16">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>660</y>
+ <width>101</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Log Base</string>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="logBaseSpin">
+ <property name="geometry">
+ <rect>
+ <x>90</x>
+ <y>660</y>
+ <width>91</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="decimals">
+ <number>5</number>
+ </property>
+ <property name="minimum">
+ <double>-999999999.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>999999999.000000000000000</double>
+ </property>
+ <property name="value">
+ <double>8.000000000000000</double>
+ </property>
+ </widget>
+ <widget class="QCheckBox" name="niceNumbersCheckBox">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>690</y>
+ <width>91</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Nice Numbers</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" name="dateFormatEdit">
+ <property name="geometry">
+ <rect>
+ <x>100</x>
+ <y>710</y>
+ <width>81</width>
+ <height>20</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label_17">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>710</y>
+ <width>101</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>DateTime format</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" name="moreCategoriesCheckBox">
+ <property name="geometry">
+ <rect>
+ <x>100</x>
+ <y>690</y>
+ <width>141</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>More Categories</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" name="series1checkBox">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>730</y>
+ <width>31</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>1</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" name="series2checkBox">
+ <property name="geometry">
+ <rect>
+ <x>40</x>
+ <y>730</y>
+ <width>31</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>2</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" name="series3checkBox">
+ <property name="geometry">
+ <rect>
+ <x>70</x>
+ <y>730</y>
+ <width>31</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>3</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" name="series4checkBox">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>750</y>
+ <width>31</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>4</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" name="series5checkBox">
+ <property name="geometry">
+ <rect>
+ <x>40</x>
+ <y>750</y>
+ <width>31</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>5</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" name="series6checkBox">
+ <property name="geometry">
+ <rect>
+ <x>70</x>
+ <y>750</y>
+ <width>31</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>6</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" name="series7checkBox">
+ <property name="geometry">
+ <rect>
+ <x>100</x>
+ <y>740</y>
+ <width>31</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>7</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" name="themeComboBox">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>770</y>
+ <width>171</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>Theme: Light</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Theme: Blue Cerulean</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Theme: Dark</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Theme: Brown Sand</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Theme: Blue Ncs</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Theme: High Contrast</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Theme: Blue Icy</string>
+ </property>
+ </item>
+ </widget>
+ <widget class="QLabel" name="hoverLabel">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>800</y>
+ <width>171</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Hover coordinates here!</string>
+ </property>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QMenuBar" name="menuBar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>1207</width>
+ <height>21</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QToolBar" name="mainToolBar">
+ <attribute name="toolBarArea">
+ <enum>TopToolBarArea</enum>
+ </attribute>
+ <attribute name="toolBarBreak">
+ <bool>false</bool>
+ </attribute>
+ </widget>
+ <widget class="QStatusBar" name="statusBar"/>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <customwidgets>
+ <customwidget>
+ <class>ChartView</class>
+ <extends>QGraphicsView</extends>
+ <header>chartview.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tests/polarcharttest/polarcharttest.pro b/tests/polarcharttest/polarcharttest.pro
new file mode 100644
index 00000000..25f4b4e3
--- /dev/null
+++ b/tests/polarcharttest/polarcharttest.pro
@@ -0,0 +1,20 @@
+!include( ../tests.pri ) {
+ error( "Couldn't find the test.pri file!" )
+}
+
+QT += core gui
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+TARGET = polarcharttest
+TEMPLATE = app
+
+
+SOURCES += main.cpp \
+ mainwindow.cpp \
+ chartview.cpp
+
+HEADERS += mainwindow.h \
+ chartview.h
+
+FORMS += mainwindow.ui
diff --git a/tests/tests.pro b/tests/tests.pro
index 068ad6f3..f57bd3e0 100644
--- a/tests/tests.pro
+++ b/tests/tests.pro
@@ -7,7 +7,8 @@ SUBDIRS += \
auto \
qmlchartproperties \
qmlchartaxis \
- presenterchart
+ presenterchart \
+ polarcharttest
contains(QT_CONFIG, opengl) {
SUBDIRS += chartwidgettest \