summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 \