summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMika Salmela <mika.salmela@digia.com>2013-06-03 15:01:25 +0300
committerMika Salmela <mika.salmela@digia.com>2013-06-03 15:08:00 +0300
commitb76baa838f46089ff6d50a2f003b7903594fd443 (patch)
tree8a4c55272934f9d0b741806bfa3ce829081dd1b8
parent1ed4427c0b81a534f6318c037115164138073706 (diff)
A new box-and-whiskers series type added to charts.
Change-Id: Iab7a05c44026db9925fa0d68afd2b533b3ea2f91 Reviewed-by: Miikka Heikkinen <miikka.heikkinen@digia.com>
-rw-r--r--doc/images/examples_boxplotchart.pngbin0 -> 52376 bytes
-rw-r--r--doc/images/examples_qmlboxplot.pngbin0 -> 38202 bytes
-rw-r--r--doc/src/classes.qdoc3
-rw-r--r--doc/src/examples-boxplotchart.qdoc38
-rw-r--r--doc/src/qml.qdoc2
-rw-r--r--examples/boxplotchart/boxdatareader.cpp67
-rw-r--r--examples/boxplotchart/boxdatareader.h42
-rw-r--r--examples/boxplotchart/boxplotchart.pro13
-rw-r--r--examples/boxplotchart/boxplotdata.qrc5
-rw-r--r--examples/boxplotchart/main.cpp85
-rw-r--r--examples/boxplotchart/stock_data.txt13
-rw-r--r--examples/examples.pro2
-rw-r--r--examples/qmlboxplot/main.cpp42
-rw-r--r--examples/qmlboxplot/qml/qmlboxplot/main.qml40
-rw-r--r--examples/qmlboxplot/qmlapplicationviewer/qmlapplicationviewer.cpp177
-rw-r--r--examples/qmlboxplot/qmlapplicationviewer/qmlapplicationviewer.h46
-rw-r--r--examples/qmlboxplot/qmlapplicationviewer/qmlapplicationviewer.pri13
-rw-r--r--examples/qmlboxplot/qmlboxplot.pro11
-rw-r--r--examples/qmlboxplot/resources.qrc5
-rw-r--r--plugins/declarative/declarative.pri6
-rw-r--r--plugins/declarative/declarativeboxplotseries.cpp124
-rw-r--r--plugins/declarative/declarativeboxplotseries.h119
-rw-r--r--plugins/declarative/declarativechart.cpp6
-rw-r--r--plugins/declarative/declarativechart.h1
-rw-r--r--plugins/declarative/plugin.cpp5
-rw-r--r--src/animations/animations.pri8
-rw-r--r--src/animations/boxplotanimation.cpp78
-rw-r--r--src/animations/boxplotanimation_p.h61
-rw-r--r--src/animations/boxwhiskersanimation.cpp107
-rw-r--r--src/animations/boxwhiskersanimation_p.h69
-rw-r--r--src/barchart/qabstractbarseries.cpp24
-rw-r--r--src/barchart/qabstractbarseries.h1
-rw-r--r--src/barchart/qbarset.h1
-rw-r--r--src/barchart/qvbarmodelmapper.cpp2
-rw-r--r--src/boxplotchart/boxplotchart.pri25
-rw-r--r--src/boxplotchart/boxplotchartitem.cpp210
-rw-r--r--src/boxplotchart/boxplotchartitem_p.h87
-rw-r--r--src/boxplotchart/boxwhiskers.cpp167
-rw-r--r--src/boxplotchart/boxwhiskers_p.h96
-rw-r--r--src/boxplotchart/boxwhiskersdata_p.h80
-rw-r--r--src/boxplotchart/qboxplotmodelmapper.cpp532
-rw-r--r--src/boxplotchart/qboxplotmodelmapper.h69
-rw-r--r--src/boxplotchart/qboxplotmodelmapper_p.h95
-rw-r--r--src/boxplotchart/qboxplotseries.cpp680
-rw-r--r--src/boxplotchart/qboxplotseries.h72
-rw-r--r--src/boxplotchart/qboxplotseries_p.h95
-rw-r--r--src/boxplotchart/qboxset.cpp400
-rw-r--r--src/boxplotchart/qboxset.h94
-rw-r--r--src/boxplotchart/qboxset_p.h81
-rw-r--r--src/boxplotchart/qvboxplotmodelmapper.cpp253
-rw-r--r--src/boxplotchart/qvboxplotmodelmapper.h70
-rw-r--r--src/chartpresenter_p.h1
-rw-r--r--src/legend/legend.pri9
-rw-r--r--src/legend/qboxplotlegendmarker.cpp126
-rw-r--r--src/legend/qboxplotlegendmarker.h55
-rw-r--r--src/legend/qboxplotlegendmarker_p.h64
-rw-r--r--src/legend/qlegendmarker.cpp1
-rw-r--r--src/legend/qlegendmarker.h3
-rw-r--r--src/qabstractseries.cpp1
-rw-r--r--src/qabstractseries.h7
-rw-r--r--src/qabstractseries_p.h2
-rw-r--r--src/qchart.h2
-rw-r--r--src/src.pro1
-rw-r--r--src/themes/charttheme_p.h2
-rw-r--r--src/themes/chartthemebluecerulean_p.h2
-rw-r--r--src/themes/chartthemeblueicy_p.h2
-rw-r--r--src/themes/chartthemebluencs_p.h2
-rw-r--r--src/themes/chartthemebrownsand_p.h2
-rw-r--r--src/themes/chartthemedark_p.h2
-rw-r--r--src/themes/chartthemehighcontrast_p.h2
-rw-r--r--src/themes/chartthemelight_p.h2
-rw-r--r--tests/boxplottester/boxplottester.pro18
-rw-r--r--tests/boxplottester/customtablemodel.cpp142
-rw-r--r--tests/boxplottester/customtablemodel.h51
-rw-r--r--tests/boxplottester/main.cpp38
-rw-r--r--tests/boxplottester/mainwidget.cpp416
-rw-r--r--tests/boxplottester/mainwidget.h80
-rw-r--r--tests/tests.pro3
78 files changed, 5334 insertions, 24 deletions
diff --git a/doc/images/examples_boxplotchart.png b/doc/images/examples_boxplotchart.png
new file mode 100644
index 00000000..4a2b6123
--- /dev/null
+++ b/doc/images/examples_boxplotchart.png
Binary files differ
diff --git a/doc/images/examples_qmlboxplot.png b/doc/images/examples_qmlboxplot.png
new file mode 100644
index 00000000..f9ddc489
--- /dev/null
+++ b/doc/images/examples_qmlboxplot.png
Binary files differ
diff --git a/doc/src/classes.qdoc b/doc/src/classes.qdoc
index 07be9dd8..2c12133f 100644
--- a/doc/src/classes.qdoc
+++ b/doc/src/classes.qdoc
@@ -44,6 +44,7 @@
<li><a href="qxylegendmarker.html">QXYLegendMarker</a></li>
<li><a href="qbarlegendmarker.html">QBarLegendMarker</a></li>
<li><a href="qarealegendmarker.html">QAreaLegendMarker</a></li>
+ <li><a href="qboxplotlegendmarker.html">QBoxPlotLegendMarker</a></li>
<li><a href="qabstractseries.html">QAbstractSeries</a></li>
</ul>
</td>
@@ -83,6 +84,8 @@
<li><a href="qbarset.html">QBarSet</a></li>
<li><a href="qpercentbarseries.html">QPercentBarSeries</a></li>
<li><a href="qstackedbarseries.html">QStackedBarSeries</a></li>
+ <li><a href="qboxplotseries.html">QBoxPlotSeries</a></li>
+ <li><a href="qboxset.html">QBoxSet</a></li>
<li><a href="qhbarmodelmapper.html">QHBarModelMapper</a></li>
<li><a href="qvbarmodelmapper.html">QVBarModelMapper</a></li>
<li><a href="qhorizontalbarseries.html">QHorizontalBarSeries</a></li>
diff --git a/doc/src/examples-boxplotchart.qdoc b/doc/src/examples-boxplotchart.qdoc
new file mode 100644
index 00000000..b9bde2b6
--- /dev/null
+++ b/doc/src/examples-boxplotchart.qdoc
@@ -0,0 +1,38 @@
+/*!
+ \example examples/boxplotchart
+ \title Box and Whiskers Example
+ \subtitle
+
+ The example shows how to create a box-and-whiskers chart.
+
+ \image examples_barchart.png
+
+ Introduction here
+
+ \snippet ../examples/barchart/main.cpp 1
+
+ Ykköskohta
+
+ \snippet ../examples/barchart/main.cpp 2
+
+ Kakkoskohta
+
+ \snippet ../examples/barchart/main.cpp 3
+
+ Kolmoskohta
+
+ \snippet ../examples/barchart/main.cpp 4
+
+ Neloskohta
+
+ \snippet ../examples/barchart/main.cpp 5
+
+ Tarkista numerointi. Finally we add the chart onto a view. We also turn on the antialiasing for the chartView.
+
+ \snippet ../examples/barchart/main.cpp 6
+
+ Tarkista numerointi. Chart is ready to be shown. We set the chart to be central widget of the window.
+ We also set the size for the chart window and show it.
+
+ \snippet ../examples/barchart/main.cpp 7
+*/
diff --git a/doc/src/qml.qdoc b/doc/src/qml.qdoc
index 85ce2f12..862d7e36 100644
--- a/doc/src/qml.qdoc
+++ b/doc/src/qml.qdoc
@@ -92,6 +92,8 @@
<li><a href="qml-horizontalstackedbarseries.html">HorizontalStackedBarSeries</a></li>
<li><a href="qml-horizontalpercentbarseries.html">HorizontalPercentBarSeries</a></li>
<li><a href="qml-barset.html">BarSet</a></li>
+ <li><a href="qml-boxplotseries.html">BoxPlotSeries</a></li>
+ <li><a href="qml-boxset.html">BoxSet</a></li>
<li><a href="qml-hbarmodelmapper.html">HBarModelMapper</a></li>
<li><a href="qml-vbarmodelmapper.html">VBarModelMapper</a></li>
</ul>
diff --git a/examples/boxplotchart/boxdatareader.cpp b/examples/boxplotchart/boxdatareader.cpp
new file mode 100644
index 00000000..4bc2d404
--- /dev/null
+++ b/examples/boxplotchart/boxdatareader.cpp
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** 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 "boxdatareader.h"
+
+BoxDataReader::BoxDataReader(QIODevice *device) :
+ QTextStream(device)
+{
+}
+
+QBoxSet* BoxDataReader::readBox()
+{
+ QString line = readLine();
+ if (line.startsWith("#"))
+ return 0;
+
+ QStringList strList = line.split(" ", QString::SkipEmptyParts);
+ sortedList.clear();
+
+ for (int i = 1; i < strList.count(); i++)
+ sortedList.append(strList.at(i).toDouble());
+
+ qSort(sortedList.begin(), sortedList.end());
+
+ int count = sortedList.count();
+
+ QBoxSet *box = new QBoxSet(strList.first());
+ box->setValue(QBoxSet::LowerExtreme, sortedList.first());
+ box->setValue(QBoxSet::UpperExtreme, sortedList.last());
+ box->setValue(QBoxSet::Median, findMedian(0, count));
+ box->setValue(QBoxSet::LowerQuartile, findMedian(0, count / 2));
+ if (count % 2)
+ box->setValue(QBoxSet::UpperQuartile, findMedian(count / 2 + 1, count));
+ else // even amount of numbers
+ box->setValue(QBoxSet::UpperQuartile, findMedian(count / 2, count));
+
+ return box;
+}
+
+qreal BoxDataReader::findMedian(int begin, int end)
+{
+ int count = end - begin;
+ if (count % 2 ) {
+ return sortedList.at(int(count/2) + begin);
+ } else {
+ qreal right = sortedList.at(count / 2 + begin);
+ qreal left = sortedList.at(count / 2 - 1 + begin);
+ return (right + left) / 2.0;
+ }
+}
diff --git a/examples/boxplotchart/boxdatareader.h b/examples/boxplotchart/boxdatareader.h
new file mode 100644
index 00000000..bdaae1bd
--- /dev/null
+++ b/examples/boxplotchart/boxdatareader.h
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** 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 BOXDATAREADER_H
+#define BOXDATAREADER_H
+
+#include <QTextStream>
+#include <QBoxSet>
+
+QTCOMMERCIALCHART_USE_NAMESPACE
+
+class BoxDataReader : public QTextStream
+{
+public:
+ explicit BoxDataReader(QIODevice *device);
+ QBoxSet* readBox();
+
+protected:
+ qreal findMedian(int begin, int end);
+
+private:
+ QList<qreal> sortedList;
+};
+
+#endif // BOXDATAREADER_H
diff --git a/examples/boxplotchart/boxplotchart.pro b/examples/boxplotchart/boxplotchart.pro
new file mode 100644
index 00000000..c2483511
--- /dev/null
+++ b/examples/boxplotchart/boxplotchart.pro
@@ -0,0 +1,13 @@
+!include( ../examples.pri ) {
+ error( "Couldn't find the examples.pri file!" )
+}
+
+TARGET = boxplotchart
+SOURCES += main.cpp \
+ boxdatareader.cpp
+
+RESOURCES += \
+ boxplotdata.qrc
+
+HEADERS += \
+ boxdatareader.h
diff --git a/examples/boxplotchart/boxplotdata.qrc b/examples/boxplotchart/boxplotdata.qrc
new file mode 100644
index 00000000..4cea4ba1
--- /dev/null
+++ b/examples/boxplotchart/boxplotdata.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file alias="stock">stock_data.txt</file>
+ </qresource>
+</RCC>
diff --git a/examples/boxplotchart/main.cpp b/examples/boxplotchart/main.cpp
new file mode 100644
index 00000000..7ebb6093
--- /dev/null
+++ b/examples/boxplotchart/main.cpp
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** 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 <QMainWindow>
+#include <QChartView>
+#include <QBoxPlotSeries>
+#include <QBoxSet>
+#include <QLegend>
+#include <QBarCategoryAxis>
+
+#include "boxdatareader.h"
+
+QTCOMMERCIALCHART_USE_NAMESPACE
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+//![1]
+
+//![2]
+ QBoxPlotSeries *series = new QBoxPlotSeries();
+ series->setName("Acme Ltd");
+//![2]
+
+ QFile stockData(":stock");
+ if (!stockData.open(QIODevice::ReadOnly | QIODevice::Text))
+ return 1;
+
+ BoxDataReader dataReader(&stockData);
+ while (!dataReader.atEnd()) {
+ QBoxSet *set = dataReader.readBox();
+ if (set)
+ series->append(set);
+ }
+
+//![3]
+ QChart *chart = new QChart();
+ chart->addSeries(series);
+ chart->setTitle("Acme's share deviation in 2012");
+ chart->setAnimationOptions(QChart::SeriesAnimations);
+//![3]
+
+//![4]
+ chart->createDefaultAxes();
+ chart->axisY()->setMin(15.0);
+//![4]
+
+//![5]
+ chart->legend()->setVisible(true);
+ chart->legend()->setAlignment(Qt::AlignBottom);
+//![5]
+
+//![6]
+ QChartView *chartView = new QChartView(chart);
+ chartView->setRenderHint(QPainter::Antialiasing);
+//![6]
+
+//![7]
+ QMainWindow window;
+ window.setCentralWidget(chartView);
+ window.resize(600, 400);
+ window.show();
+//![7]
+
+ return a.exec();
+}
+
diff --git a/examples/boxplotchart/stock_data.txt b/examples/boxplotchart/stock_data.txt
new file mode 100644
index 00000000..9511418d
--- /dev/null
+++ b/examples/boxplotchart/stock_data.txt
@@ -0,0 +1,13 @@
+# Acme Ltd share deviation in 2012
+Jan 27.74 27.28 27.86 28.05 28.64 27.47 28.30 28.22 28.72 26.50 26.62 26.50 26.15 26.47 26.41 25.78 24.82 24.89 24.88 24.60 23.85
+Feb 31.79 30.62 30.67 31.37 31.16 31.22 32.02 32.70 31.60 31.24 30.98 30.79 31.10 30.79 31.53 30.92 30.00 30.58 30.37 29.40 28.60
+Mar 28.64 28.34 29.13 29.43 30.75 29.77 29.72 30.52 31.12 33.05 32.51 32.69 31.83 32.47 31.41 31.39 31.78 30.08 29.46 31.58 31.39 31.41
+Apr 25.96 26.62 26.19 30.37 28.78 27.50 28.90 28.40 28.86 28.90 27.91 27.32 27.99 26.86 26.68 27.57 27.50 28.96 28.50
+May 20.85 21.08 21.98 21.61 21.45 21.73 21.71 22.27 21.14 20.65 21.95 22.23 23.17 24.26 24.17 22.97 23.53 24.49 24.51 25.46 25.65
+Jun 18.08 17.19 17.36 17.21 17.31 18.19 18.30 17.53 17.35 17.80 17.17 16.95 18.25 20.52 20.61 21.40 20.45 19.43 19.11 19.74
+Jul 17.75 18.24 17.57 16.53 15.98 16.06 16.64 17.69 17.91 18.00 18.03 18.14 18.10 17.86 18.12 18.53 18.43 18.30 19.03 18.76 18.79 18.33
+Aug 18.69 18.54 18.39 18.49 18.96 18.72 19.25 19.70 20.13 19.74 19.27 18.25 17.72 18.02 18.20 18.24 18.60 18.22 18.60 17.98 17.27 16.70 17.19
+Sep 18.35 18.82 18.96 19.96 19.75 20.55 20.68 21.19 21.14 21.48 21.45 20.74 20.97 20.18 19.66 19.54 18.89 18.39 18.26 18.86
+Oct 16.95 16.80 16.45 16.89 17.38 17.12 16.85 17.59 17.65 17.46 17.43 17.30 17.87 18.61 18.55 18.59 19.27 19.54 20.02 19.23 18.05 18.52 18.71
+Now 19.36 19.29 18.22 18.74 19.05 19.13 18.67 18.19 17.94 18.04 17.49 17.53 17.64 18.00 18.21 18.19 18.30 18.11 18.17 17.76 17.80 17.52
+Dec 19.95 20.19 20.15 20.42 20.39 20.65 20.39 19.86 19.48 19.70 19.94 19.82 20.25 20.21 19.63 19.55
diff --git a/examples/examples.pro b/examples/examples.pro
index 716dce54..f6a63bb5 100644
--- a/examples/examples.pro
+++ b/examples/examples.pro
@@ -19,8 +19,10 @@ SUBDIRS += \
zoomlinechart \
modeldata \
barchart \
+ boxplotchart \
legend \
barmodelmapper \
+ qmlboxplot \
qmlpiechart \
lineandbar \
horizontalbarchart \
diff --git a/examples/qmlboxplot/main.cpp b/examples/qmlboxplot/main.cpp
new file mode 100644
index 00000000..eab3b643
--- /dev/null
+++ b/examples/qmlboxplot/main.cpp
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** 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());
+#ifdef Q_OS_ANDROID
+ viewer->addImportPath(QString::fromLatin1("assets:/imports"));
+ viewer->engine()->addPluginPath(QString::fromLatin1("%1/../%2").arg(QDir::homePath(), QString::fromLatin1("lib")));
+#else
+ viewer->addImportPath(QString::fromLatin1("%1/%2").arg(QCoreApplication::applicationDirPath(), QString::fromLatin1("imports")));
+#endif
+
+ // // viewer->setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
+ viewer->setSource(QUrl("qrc:/qml/qmlboxplot/main.qml"));
+ viewer->setRenderHint(QPainter::Antialiasing, true);
+ viewer->showExpanded();
+
+ return app->exec();
+}
diff --git a/examples/qmlboxplot/qml/qmlboxplot/main.qml b/examples/qmlboxplot/qml/qmlboxplot/main.qml
new file mode 100644
index 00000000..8bbedf93
--- /dev/null
+++ b/examples/qmlboxplot/qml/qmlboxplot/main.qml
@@ -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$
+**
+****************************************************************************/
+
+import QtQuick 1.0
+import QtCommercial.Chart 1.3
+
+ChartView {
+ title: "Box Plot series"
+ width: 400
+ height: 300
+ theme: ChartView.ChartThemeBrownSand
+ legend.alignment: Qt.AlignBottom
+
+ BoxPlotSeries {
+ id: plotSeries
+ name: "Income"
+ BoxSet { label: "Jan"; values: [3, 4, 5.1, 6.2, 8.5] }
+ BoxSet { label: "Feb"; values: [5, 6, 7.5, 8.6, 11.8] }
+ BoxSet { label: "Mar"; values: [3.2, 5, 5.7, 8, 9.2] }
+ BoxSet { label: "Apr"; values: [3.8, 5, 6.4, 7, 8] }
+ BoxSet { label: "May"; values: [4, 5, 5.2, 6, 7] }
+ }
+}
diff --git a/examples/qmlboxplot/qmlapplicationviewer/qmlapplicationviewer.cpp b/examples/qmlboxplot/qmlapplicationviewer/qmlapplicationviewer.cpp
new file mode 100644
index 00000000..cb227056
--- /dev/null
+++ b/examples/qmlboxplot/qmlapplicationviewer/qmlapplicationviewer.cpp
@@ -0,0 +1,177 @@
+// checksum 0xaa72 version 0x90018
+/*
+ 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_BLACKBERRY)
+ if (!QDir::isAbsolutePath(path))
+ return QString::fromLatin1("app/native/%1").arg(path);
+#elif !defined(Q_OS_ANDROID)
+ QString pathInInstallDir =
+ QString::fromLatin1("%1/../%2").arg(QCoreApplication::applicationDirPath(), path);
+ if (QFileInfo(pathInInstallDir).exists())
+ return pathInInstallDir;
+ pathInInstallDir =
+ QString::fromLatin1("%1/%2").arg(QCoreApplication::applicationDirPath(), path);
+ if (QFileInfo(pathInInstallDir).exists())
+ return pathInInstallDir;
+#endif
+ return path;
+}
+
+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/examples/qmlboxplot/qmlapplicationviewer/qmlapplicationviewer.h b/examples/qmlboxplot/qmlapplicationviewer/qmlapplicationviewer.h
new file mode 100644
index 00000000..fba2d52a
--- /dev/null
+++ b/examples/qmlboxplot/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/examples/qmlboxplot/qmlapplicationviewer/qmlapplicationviewer.pri b/examples/qmlboxplot/qmlapplicationviewer/qmlapplicationviewer.pri
new file mode 100644
index 00000000..567c6dc6
--- /dev/null
+++ b/examples/qmlboxplot/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/examples/qmlboxplot/qmlboxplot.pro b/examples/qmlboxplot/qmlboxplot.pro
new file mode 100644
index 00000000..194aef38
--- /dev/null
+++ b/examples/qmlboxplot/qmlboxplot.pro
@@ -0,0 +1,11 @@
+!include( ../examples.pri ) {
+ error( "Couldn't find the examples.pri file!" )
+}
+
+RESOURCES += resources.qrc
+SOURCES += main.cpp
+
+include(qmlapplicationviewer/qmlapplicationviewer.pri)
+
+OTHER_FILES += \
+ qml/qmlboxplot/main.qml
diff --git a/examples/qmlboxplot/resources.qrc b/examples/qmlboxplot/resources.qrc
new file mode 100644
index 00000000..49a98f16
--- /dev/null
+++ b/examples/qmlboxplot/resources.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>qml/qmlboxplot/main.qml</file>
+ </qresource>
+</RCC>
diff --git a/plugins/declarative/declarative.pri b/plugins/declarative/declarative.pri
index 305e6861..d183549a 100644
--- a/plugins/declarative/declarative.pri
+++ b/plugins/declarative/declarative.pri
@@ -29,7 +29,8 @@ SOURCES += \
../declarative/declarativecategoryaxis.cpp \
../declarative/declarativemargins.cpp \
../declarative/declarativeaxes.cpp \
- ../declarative/declarativepolarchart.cpp
+ ../declarative/declarativepolarchart.cpp \
+ ../declarative/declarativeboxplotseries.cpp
HEADERS += \
../declarative/declarativechart.h \
@@ -45,7 +46,8 @@ HEADERS += \
../declarative/declarativemargins.h \
../declarative/declarativeaxes.h \
../declarative/declarativepolarchart.h \
- ../declarative/shared_defines.h
+ ../declarative/shared_defines.h \
+ ../declarative/declarativeboxplotseries.h
TARGETPATH = QtCommercial/Chart
target.path = $$IMPORT_INSTALL_PATH/$$TARGETPATH
diff --git a/plugins/declarative/declarativeboxplotseries.cpp b/plugins/declarative/declarativeboxplotseries.cpp
new file mode 100644
index 00000000..64507efe
--- /dev/null
+++ b/plugins/declarative/declarativeboxplotseries.cpp
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** 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 "declarativebarseries.h"
+#include "declarativeboxplotseries.h"
+#include "qboxset.h"
+#include "qvboxplotmodelmapper.h"
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+DeclarativeBoxSet::DeclarativeBoxSet(const QString label, QObject *parent)
+ : QBoxSet(label, parent)
+{
+ connect(this, SIGNAL(valuesChanged()), this, SIGNAL(changedValues()));
+ connect(this, SIGNAL(valueChanged(int)), this, SIGNAL(changedValue(int)));
+}
+
+QVariantList DeclarativeBoxSet::values()
+{
+ QVariantList values;
+ for (int i(0); i < 5; i++)
+ values.append(QVariant(QBoxSet::at(i)));
+ return values;
+}
+
+void DeclarativeBoxSet::setValues(QVariantList values)
+{
+ for (int i(0); i < values.count(); i++) {
+ if (values.at(i).canConvert(QVariant::Double))
+ QBoxSet::append(values[i].toDouble());
+ }
+}
+
+// =====================================================
+
+DeclarativeBoxPlotSeries::DeclarativeBoxPlotSeries(QDeclarativeItem *parent) :
+ QBoxPlotSeries(parent),
+ m_axes(new DeclarativeAxes(this))
+{
+ connect(m_axes, SIGNAL(axisXChanged(QAbstractAxis*)), this, SIGNAL(axisXChanged(QAbstractAxis*)));
+ 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(this, SIGNAL(hovered(bool, QBoxSet*)), this, SLOT(onHovered(bool, QBoxSet*)));
+ connect(this, SIGNAL(clicked(QBoxSet*)), this, SLOT(onClicked(QBoxSet*)));
+}
+
+void DeclarativeBoxPlotSeries::classBegin()
+{
+}
+
+void DeclarativeBoxPlotSeries::componentComplete()
+{
+ foreach (QObject *child, children()) {
+ if (qobject_cast<DeclarativeBoxSet *>(child)) {
+ QBoxPlotSeries::append(qobject_cast<DeclarativeBoxSet *>(child));
+ } else if (qobject_cast<QVBoxPlotModelMapper *>(child)) {
+ QVBoxPlotModelMapper *mapper = qobject_cast<QVBoxPlotModelMapper *>(child);
+ mapper->setSeries(this);
+ }
+ }
+}
+
+QDeclarativeListProperty<QObject> DeclarativeBoxPlotSeries::seriesChildren()
+{
+ return QDeclarativeListProperty<QObject>(this, 0, &DeclarativeBoxPlotSeries::appendSeriesChildren);
+}
+
+void DeclarativeBoxPlotSeries::appendSeriesChildren(QDeclarativeListProperty<QObject> *list, QObject *element)
+{
+ // Empty implementation; the children are parsed in componentComplete instead
+ Q_UNUSED(list);
+ Q_UNUSED(element);
+}
+
+DeclarativeBoxSet *DeclarativeBoxPlotSeries::at(int index)
+{
+ QList<QBoxSet *> setList = boxSets();
+ if (index >= 0 && index < setList.count())
+ return qobject_cast<DeclarativeBoxSet *>(setList[index]);
+
+ return 0;
+}
+
+DeclarativeBoxSet *DeclarativeBoxPlotSeries::insert(int index, const QString label, QVariantList values)
+{
+ DeclarativeBoxSet *barset = new DeclarativeBoxSet(label, this);
+ barset->setValues(values);
+ if (QBoxPlotSeries::insert(index, barset))
+ return barset;
+ delete barset;
+ return 0;
+}
+
+void DeclarativeBoxPlotSeries::onHovered(bool status, QBoxSet *boxset)
+{
+ emit hovered(status, qobject_cast<DeclarativeBoxSet *>(boxset));
+}
+
+void DeclarativeBoxPlotSeries::onClicked(QBoxSet *boxset)
+{
+ emit clicked(qobject_cast<DeclarativeBoxSet *>(boxset));
+}
+
+#include "moc_declarativeboxplotseries.cpp"
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/plugins/declarative/declarativeboxplotseries.h b/plugins/declarative/declarativeboxplotseries.h
new file mode 100644
index 00000000..4822b717
--- /dev/null
+++ b/plugins/declarative/declarativeboxplotseries.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** 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 DECLARATIVEBOXPLOT_H
+#define DECLARATIVEBOXPLOT_H
+
+#include "qboxset.h"
+#include "declarativeaxes.h"
+#include "qboxplotseries.h"
+#include <QtDeclarative/QDeclarativeItem>
+#include <QtDeclarative/QDeclarativeParserStatus>
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+class DeclarativeBoxSet : public QBoxSet
+{
+ Q_OBJECT
+ Q_PROPERTY(QVariantList values READ values WRITE setValues)
+ Q_PROPERTY(QString label READ label WRITE setLabel)
+ Q_PROPERTY(int count READ count)
+ Q_ENUMS(ValuePositions)
+
+public: // duplicate from QBoxSet
+ enum ValuePositions {
+ LowerExtreme = 0x0,
+ LowerQuartile,
+ Median,
+ UpperQuartile,
+ UpperExtreme
+ };
+
+public:
+ explicit DeclarativeBoxSet(const QString label = "", QObject *parent = 0);
+ QVariantList values();
+ void setValues(QVariantList values);
+
+public: // From QBoxSet
+ Q_INVOKABLE void append(qreal value) { QBoxSet::append(value); }
+ Q_INVOKABLE void clear() {QBoxSet::clear(); }
+ Q_INVOKABLE qreal at(int index) { return QBoxSet::at(index); }
+ Q_INVOKABLE void setValue(int index, qreal value) { QBoxSet::setValue(index, value); }
+
+Q_SIGNALS:
+ void changedValues();
+ void changedValue(int index);
+};
+
+class DeclarativeBoxPlotSeries : public QBoxPlotSeries, public QDeclarativeParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QDeclarativeParserStatus)
+ Q_PROPERTY(QAbstractAxis *axisX READ axisX WRITE setAxisX NOTIFY axisXChanged)
+ Q_PROPERTY(QAbstractAxis *axisY READ axisY WRITE setAxisY NOTIFY axisYChanged)
+ Q_PROPERTY(QAbstractAxis *axisXTop READ axisXTop WRITE setAxisXTop NOTIFY axisXTopChanged)
+ Q_PROPERTY(QAbstractAxis *axisYRight READ axisYRight WRITE setAxisYRight NOTIFY axisYRightChanged)
+ Q_PROPERTY(QDeclarativeListProperty<QObject> seriesChildren READ seriesChildren)
+ Q_CLASSINFO("DefaultProperty", "seriesChildren")
+
+public:
+ explicit DeclarativeBoxPlotSeries(QDeclarativeItem *parent = 0);
+ QAbstractAxis *axisX() { return m_axes->axisX(); }
+ void setAxisX(QAbstractAxis *axis) { m_axes->setAxisX(axis); }
+ QAbstractAxis *axisY() { return m_axes->axisY(); }
+ void setAxisY(QAbstractAxis *axis) { m_axes->setAxisY(axis); }
+ QAbstractAxis *axisXTop() { return m_axes->axisXTop(); }
+ void setAxisXTop(QAbstractAxis *axis) { m_axes->setAxisXTop(axis); }
+ QAbstractAxis *axisYRight() { return m_axes->axisYRight(); }
+ void setAxisYRight(QAbstractAxis *axis) { m_axes->setAxisYRight(axis); }
+ QDeclarativeListProperty<QObject> seriesChildren();
+
+public:
+ Q_INVOKABLE DeclarativeBoxSet *at(int index);
+ Q_INVOKABLE DeclarativeBoxSet *append(const QString label, QVariantList values) { return insert(count(), label, values); }
+ Q_INVOKABLE void append(DeclarativeBoxSet *box) { QBoxPlotSeries::append(box); }
+ Q_INVOKABLE DeclarativeBoxSet *insert(int index, const QString label, QVariantList values);
+ Q_INVOKABLE bool remove(DeclarativeBoxSet *box) { return QBoxPlotSeries::remove(qobject_cast<QBoxSet *>(box)); }
+ Q_INVOKABLE void clear() { return QBoxPlotSeries::clear(); }
+
+public: // from QDeclarativeParserStatus
+ void classBegin();
+ void componentComplete();
+
+Q_SIGNALS:
+ void axisXChanged(QAbstractAxis *axis);
+ void axisYChanged(QAbstractAxis *axis);
+ void axisXTopChanged(QAbstractAxis *axis);
+ void axisYRightChanged(QAbstractAxis *axis);
+ void clicked(DeclarativeBoxSet *boxset);
+ void hovered(bool status, DeclarativeBoxSet *boxset);
+
+public Q_SLOTS:
+ static void appendSeriesChildren(QDeclarativeListProperty<QObject> *list, QObject *element);
+ void onHovered(bool status, QBoxSet *boxset);
+ void onClicked(QBoxSet *boxset);
+
+public:
+ DeclarativeAxes *m_axes;
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // DECLARATIVEBOXPLOT_H
diff --git a/plugins/declarative/declarativechart.cpp b/plugins/declarative/declarativechart.cpp
index 3caeb39b..bb62e077 100644
--- a/plugins/declarative/declarativechart.cpp
+++ b/plugins/declarative/declarativechart.cpp
@@ -25,6 +25,7 @@
#include "declarativebarseries.h"
#include "declarativepieseries.h"
#include "declarativesplineseries.h"
+#include "declarativeboxplotseries.h"
#include "declarativescatterseries.h"
#include "qbarcategoryaxis.h"
#include "qvalueaxis.h"
@@ -849,6 +850,9 @@ QAbstractSeries *DeclarativeChart::createSeries(int type, QString name, QAbstrac
case DeclarativeChart::SeriesTypeHorizontalStackedBar:
series = new DeclarativeHorizontalStackedBarSeries();
break;
+ case DeclarativeChart::SeriesTypeBoxPlot:
+ series = new DeclarativeBoxPlotSeries();
+ break;
case DeclarativeChart::SeriesTypePie:
series = new DeclarativePieSeries();
break;
@@ -964,6 +968,8 @@ void DeclarativeChart::initializeAxes(QAbstractSeries *series)
doInitializeAxes(series, qobject_cast<DeclarativeHorizontalStackedBarSeries *>(series)->m_axes);
else if (qobject_cast<DeclarativeHorizontalPercentBarSeries *>(series))
doInitializeAxes(series, qobject_cast<DeclarativeHorizontalPercentBarSeries *>(series)->m_axes);
+ else if (qobject_cast<DeclarativeBoxPlotSeries *>(series))
+ doInitializeAxes(series, qobject_cast<DeclarativeBoxPlotSeries *>(series)->m_axes);
// else: do nothing
}
diff --git a/plugins/declarative/declarativechart.h b/plugins/declarative/declarativechart.h
index ae4c5362..2717ee06 100644
--- a/plugins/declarative/declarativechart.h
+++ b/plugins/declarative/declarativechart.h
@@ -95,6 +95,7 @@ public:
SeriesTypeBar,
SeriesTypeStackedBar,
SeriesTypePercentBar,
+ SeriesTypeBoxPlot,
SeriesTypePie,
SeriesTypeScatter,
SeriesTypeSpline,
diff --git a/plugins/declarative/plugin.cpp b/plugins/declarative/plugin.cpp
index 029e6df9..52cfc555 100644
--- a/plugins/declarative/plugin.cpp
+++ b/plugins/declarative/plugin.cpp
@@ -32,6 +32,7 @@
#include "declarativeareaseries.h"
#include "declarativescatterseries.h"
#include "declarativebarseries.h"
+#include "declarativeboxplotseries.h"
#include "declarativepieseries.h"
#include "declarativeaxes.h"
#include "qvxymodelmapper.h"
@@ -74,6 +75,8 @@ Q_DECLARE_METATYPE(DeclarativeMargins *)
Q_DECLARE_METATYPE(DeclarativeAreaSeries *)
Q_DECLARE_METATYPE(DeclarativeBarSeries *)
Q_DECLARE_METATYPE(DeclarativeBarSet *)
+Q_DECLARE_METATYPE(DeclarativeBoxPlotSeries *)
+Q_DECLARE_METATYPE(DeclarativeBoxSet *)
Q_DECLARE_METATYPE(DeclarativeLineSeries *)
Q_DECLARE_METATYPE(DeclarativePieSeries *)
Q_DECLARE_METATYPE(DeclarativeScatterSeries *)
@@ -236,6 +239,8 @@ public:
qmlRegisterType<DeclarativeLineSeries, 3>(uri, 1, 3, "LineSeries");
qmlRegisterType<DeclarativeAreaSeries, 3>(uri, 1, 3, "AreaSeries");
qmlRegisterType<QLogValueAxis>(uri, 1, 3, "LogValueAxis");
+ qmlRegisterType<DeclarativeBoxPlotSeries>(uri, 1, 3, "BoxPlotSeries");
+ qmlRegisterType<DeclarativeBoxSet>(uri, 1, 3, "BoxSet");
}
};
diff --git a/src/animations/animations.pri b/src/animations/animations.pri
index 93239425..1a0870fa 100644
--- a/src/animations/animations.pri
+++ b/src/animations/animations.pri
@@ -8,7 +8,9 @@ SOURCES += \
$$PWD/piesliceanimation.cpp \
$$PWD/splineanimation.cpp \
$$PWD/baranimation.cpp \
- $$PWD/scatteranimation.cpp
+ $$PWD/scatteranimation.cpp \
+ $$PWD/boxplotanimation.cpp \
+ $$PWD/boxwhiskersanimation.cpp
PRIVATE_HEADERS += \
$$PWD/axisanimation_p.h \
@@ -18,4 +20,6 @@ PRIVATE_HEADERS += \
$$PWD/piesliceanimation_p.h \
$$PWD/splineanimation_p.h \
$$PWD/baranimation_p.h \
- $$PWD/scatteranimation_p.h
+ $$PWD/scatteranimation_p.h \
+ $$PWD/boxplotanimation_p.h \
+ $$PWD/boxwhiskersanimation_p.h
diff --git a/src/animations/boxplotanimation.cpp b/src/animations/boxplotanimation.cpp
new file mode 100644
index 00000000..1bd88d21
--- /dev/null
+++ b/src/animations/boxplotanimation.cpp
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** 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 "boxplotanimation_p.h"
+#include "boxplotchartitem_p.h"
+#include "boxwhiskersdata_p.h"
+#include "boxwhiskersanimation_p.h"
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+BoxPlotAnimation::BoxPlotAnimation(BoxPlotChartItem *item)
+ : m_item(item)
+{
+}
+
+BoxPlotAnimation::~BoxPlotAnimation()
+{
+}
+
+void BoxPlotAnimation::addBox(BoxWhiskers *box)
+{
+ BoxWhiskersAnimation *animation = m_animations.value(box);
+ if (!animation) {
+ animation = new BoxWhiskersAnimation(box);
+ m_animations.insert(box, animation);
+ BoxWhiskersData start;
+ start.m_median = box->m_data.m_median;
+ animation->setup(start, box->m_data);
+ } else {
+ animation->stop();
+ animation->setEndData(box->m_data);
+ }
+}
+
+ChartAnimation *BoxPlotAnimation::boxAnimation(BoxWhiskers *box)
+{
+ BoxWhiskersAnimation *animation = m_animations.value(box);
+ if (animation)
+ animation->m_moveMedianLine = false;
+
+ return animation;
+}
+
+ChartAnimation *BoxPlotAnimation::boxChangeAnimation(BoxWhiskers *box)
+{
+ BoxWhiskersAnimation *animation = m_animations.value(box);
+ animation->m_moveMedianLine = true;
+ animation->setEndData(box->m_data);
+
+ return animation;
+}
+
+void BoxPlotAnimation::setAnimationStart(BoxWhiskers *box)
+{
+ BoxWhiskersAnimation *animation = m_animations.value(box);
+ animation->setStartData(box->m_data);
+}
+
+//#include "moc_boxplotanimation_p.cpp"
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/animations/boxplotanimation_p.h b/src/animations/boxplotanimation_p.h
new file mode 100644
index 00000000..52a38f20
--- /dev/null
+++ b/src/animations/boxplotanimation_p.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** 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 BOXPLOTANIMATION_P_H
+#define BOXPLOTANIMATION_P_H
+
+#include "chartanimation_p.h"
+#include "boxwhiskers_p.h"
+#include "boxwhiskersdata_p.h"
+#include "boxwhiskersanimation_p.h"
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+class BoxPlotChartItem;
+
+class BoxPlotAnimation
+{
+public:
+ BoxPlotAnimation(BoxPlotChartItem *item);
+ ~BoxPlotAnimation();
+
+ void addBox(BoxWhiskers *box);
+ ChartAnimation *boxAnimation(BoxWhiskers *box);
+ ChartAnimation *boxChangeAnimation(BoxWhiskers *box);
+
+ void setAnimationStart(BoxWhiskers *box);
+
+protected:
+ BoxPlotChartItem *m_item;
+ QHash<BoxWhiskers *, BoxWhiskersAnimation *> m_animations;
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // BOXPLOTANIMATION_P_H
diff --git a/src/animations/boxwhiskersanimation.cpp b/src/animations/boxwhiskersanimation.cpp
new file mode 100644
index 00000000..a46aa76a
--- /dev/null
+++ b/src/animations/boxwhiskersanimation.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** 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 "boxwhiskersanimation_p.h"
+#include "boxplotanimation_p.h"
+#include "boxplotchartitem_p.h"
+#include "boxwhiskersdata_p.h"
+
+Q_DECLARE_METATYPE(QVector<QRectF>)
+Q_DECLARE_METATYPE(QTCOMMERCIALCHART_NAMESPACE::BoxWhiskersData)
+Q_DECLARE_METATYPE(qreal)
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+BoxWhiskersAnimation::BoxWhiskersAnimation(BoxWhiskers *box)
+ : ChartAnimation(box),
+ m_box(box)
+{
+ setDuration(ChartAnimationDuration);
+ setEasingCurve(QEasingCurve::OutQuart);
+}
+
+BoxWhiskersAnimation::~BoxWhiskersAnimation()
+{
+}
+
+QVariant BoxWhiskersAnimation::interpolated(const QVariant &from, const QVariant &to, qreal progress) const
+{
+ BoxWhiskersData startData = qvariant_cast<BoxWhiskersData>(from);
+ BoxWhiskersData endData = qvariant_cast<BoxWhiskersData>(to);
+ BoxWhiskersData result;
+
+ if (m_moveMedianLine) {
+ result.m_lowerExtreme = startData.m_lowerExtreme + progress * (endData.m_lowerExtreme - startData.m_lowerExtreme);
+ result.m_lowerQuartile = startData.m_lowerQuartile + progress * (endData.m_lowerQuartile - startData.m_lowerQuartile);
+ result.m_median = startData.m_median + progress * (endData.m_median - startData.m_median);
+ result.m_upperQuartile = startData.m_upperQuartile + progress * (endData.m_upperQuartile - startData.m_upperQuartile);
+ result.m_upperExtreme = startData.m_upperExtreme + progress * (endData.m_upperExtreme - startData.m_upperExtreme);
+ } else {
+ result.m_lowerExtreme = endData.m_median + progress * (endData.m_lowerExtreme - endData.m_median);
+ result.m_lowerQuartile = endData.m_median + progress * (endData.m_lowerQuartile - endData.m_median);
+ result.m_median = endData.m_median;
+ result.m_upperQuartile = endData.m_median + progress * (endData.m_upperQuartile - endData.m_median);
+ result.m_upperExtreme = endData.m_median + progress * (endData.m_upperExtreme - endData.m_median);
+ }
+ result.m_index = endData.m_index;
+ result.m_boxItems = endData.m_boxItems;
+
+ result.m_maxX = endData.m_maxX;
+ result.m_minX = endData.m_minX;
+ result.m_maxY = endData.m_maxY;
+ result.m_minY = endData.m_minY;
+ result.m_seriesIndex = endData.m_seriesIndex;
+ result.m_seriesCount = endData.m_seriesCount;
+
+ return qVariantFromValue(result);
+}
+
+void BoxWhiskersAnimation::updateCurrentValue(const QVariant &value)
+{
+ BoxWhiskersData data = qvariant_cast<BoxWhiskersData>(value);
+ m_box->setLayout(data);
+}
+
+void BoxWhiskersAnimation::setup(const BoxWhiskersData &startData, const BoxWhiskersData &endData)
+{
+ setKeyValueAt(0.0, qVariantFromValue(startData));
+ setKeyValueAt(1.0, qVariantFromValue(endData));
+}
+
+void BoxWhiskersAnimation::setEndData(const BoxWhiskersData &endData)
+{
+ if (state() != QAbstractAnimation::Stopped)
+ stop();
+
+ setEndValue(qVariantFromValue(endData));
+}
+
+void BoxWhiskersAnimation::setStartData(const BoxWhiskersData &endData)
+{
+ if (state() != QAbstractAnimation::Stopped)
+ stop();
+
+ setStartValue(qVariantFromValue(endData));
+}
+
+#include "moc_boxwhiskersanimation_p.cpp"
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
diff --git a/src/animations/boxwhiskersanimation_p.h b/src/animations/boxwhiskersanimation_p.h
new file mode 100644
index 00000000..5e3bd905
--- /dev/null
+++ b/src/animations/boxwhiskersanimation_p.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** 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 BOXWHISKERSANIMATION_P_H
+#define BOXWHISKERSANIMATION_P_H
+
+#include "chartanimation_p.h"
+#include "boxwhiskers_p.h"
+#include "boxwhiskersdata_p.h"
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+class BoxPlotChartItem;
+
+class BoxWhiskersAnimation : public ChartAnimation
+{
+ Q_OBJECT
+
+public:
+ BoxWhiskersAnimation(BoxWhiskers *box);
+ ~BoxWhiskersAnimation();
+
+public: // from QVariantAnimation
+ virtual QVariant interpolated(const QVariant &from, const QVariant &to, qreal progress) const;
+ virtual void updateCurrentValue(const QVariant &value);
+
+ void setup(const BoxWhiskersData &startData, const BoxWhiskersData &endData);
+ void setEndData(const BoxWhiskersData &endData);
+ void setStartData(const BoxWhiskersData &endData);
+
+ void moveMedianLine(bool move);
+
+protected:
+ friend class BoxPlotAnimation;
+ BoxPlotChartItem *m_item;
+ BoxWhiskers *m_box;
+ BoxWhiskersData *m_boxData;
+ bool m_moveMedianLine;
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // BOXWHISKERSANIMATION_P_H
diff --git a/src/barchart/qabstractbarseries.cpp b/src/barchart/qabstractbarseries.cpp
index 4108dc46..7e4eeb9b 100644
--- a/src/barchart/qabstractbarseries.cpp
+++ b/src/barchart/qabstractbarseries.cpp
@@ -778,21 +778,22 @@ void QAbstractBarSeriesPrivate::initializeAxes()
if (axis->type() == QAbstractAxis::AxisTypeBarCategory) {
switch (q->type()) {
- case QAbstractSeries::SeriesTypeHorizontalBar:
- case QAbstractSeries::SeriesTypeHorizontalPercentBar:
- case QAbstractSeries::SeriesTypeHorizontalStackedBar:
+ case QAbstractSeries::SeriesTypeHorizontalBar:
+ case QAbstractSeries::SeriesTypeHorizontalPercentBar:
+ case QAbstractSeries::SeriesTypeHorizontalStackedBar:
if (axis->orientation() == Qt::Vertical)
populateCategories(qobject_cast<QBarCategoryAxis *>(axis));
- break;
- case QAbstractSeries::SeriesTypeBar:
- case QAbstractSeries::SeriesTypePercentBar:
- case QAbstractSeries::SeriesTypeStackedBar:
+ break;
+ case QAbstractSeries::SeriesTypeBar:
+ case QAbstractSeries::SeriesTypePercentBar:
+ case QAbstractSeries::SeriesTypeStackedBar:
+ case QAbstractSeries::SeriesTypeBoxPlot:
if (axis->orientation() == Qt::Horizontal)
- populateCategories(qobject_cast<QBarCategoryAxis *>(axis));
- break;
- default:
+ populateCategories(qobject_cast<QBarCategoryAxis *>(axis));
+ break;
+ default:
qWarning() << "Unexpected series type";
- break;
+ break;
}
}
}
@@ -812,6 +813,7 @@ QAbstractAxis::AxisType QAbstractBarSeriesPrivate::defaultAxisType(Qt::Orientati
case QAbstractSeries::SeriesTypeBar:
case QAbstractSeries::SeriesTypePercentBar:
case QAbstractSeries::SeriesTypeStackedBar:
+ case QAbstractSeries::SeriesTypeBoxPlot:
if (orientation == Qt::Horizontal)
return QAbstractAxis::AxisTypeBarCategory;
break;
diff --git a/src/barchart/qabstractbarseries.h b/src/barchart/qabstractbarseries.h
index 2370b269..8588c159 100644
--- a/src/barchart/qabstractbarseries.h
+++ b/src/barchart/qabstractbarseries.h
@@ -72,6 +72,7 @@ protected:
friend class AbstractBarChartItem;
friend class PercentBarChartItem;
friend class StackedBarChartItem;
+ friend class BoxPlotChartItem;
friend class BarChartItem;
friend class HorizontalBarChartItem;
friend class HorizontalStackedBarChartItem;
diff --git a/src/barchart/qbarset.h b/src/barchart/qbarset.h
index 82f6e5ca..cdee47e7 100644
--- a/src/barchart/qbarset.h
+++ b/src/barchart/qbarset.h
@@ -111,6 +111,7 @@ private:
friend class HorizontalBarChartItem;
friend class HorizontalStackedBarChartItem;
friend class HorizontalPercentBarChartItem;
+ friend class BoxPlotChartItem;
};
QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/barchart/qvbarmodelmapper.cpp b/src/barchart/qvbarmodelmapper.cpp
index 3f261f42..bc71fbf7 100644
--- a/src/barchart/qvbarmodelmapper.cpp
+++ b/src/barchart/qvbarmodelmapper.cpp
@@ -58,7 +58,7 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE
/*!
\property QVBarModelMapper::series
- \brief Defines the QPieSeries object that is used by the mapper.
+ \brief Defines the QBarSeries object that is used by the mapper.
All the data in the series is discarded when it is set to the mapper.
When new series is specified the old series is disconnected (it preserves its data)
diff --git a/src/boxplotchart/boxplotchart.pri b/src/boxplotchart/boxplotchart.pri
new file mode 100644
index 00000000..db6e034b
--- /dev/null
+++ b/src/boxplotchart/boxplotchart.pri
@@ -0,0 +1,25 @@
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+
+SOURCES += \
+ $$PWD/boxplotchartitem.cpp \
+ $$PWD/qboxplotseries.cpp \
+ $$PWD/boxwhiskers.cpp \
+ $$PWD/qboxset.cpp \
+ $$PWD/qboxplotmodelmapper.cpp \
+ $$PWD/qvboxplotmodelmapper.cpp
+
+PRIVATE_HEADERS += \
+ $$PWD/boxplotchartitem_p.h \
+ $$PWD/qboxplotseries_p.h \
+ $$PWD/boxwhiskers_p.h \
+ $$PWD/boxwhiskersdata_p.h \
+ $$PWD/qboxset_p.h \
+ $$PWD/qboxplotmodelmapper_p.h
+
+PUBLIC_HEADERS += \
+ $$PWD/qboxplotseries.h \
+ $$PWD/qboxset.h \
+ $$PWD/qboxplotmodelmapper.h \
+ $$PWD/qvboxplotmodelmapper.h
+
diff --git a/src/boxplotchart/boxplotchartitem.cpp b/src/boxplotchart/boxplotchartitem.cpp
new file mode 100644
index 00000000..0ddaa44e
--- /dev/null
+++ b/src/boxplotchart/boxplotchartitem.cpp
@@ -0,0 +1,210 @@
+/****************************************************************************
+**
+** 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 "boxplotchartitem_p.h"
+#include "qboxplotseries_p.h"
+#include "bar_p.h"
+#include "qboxset_p.h"
+#include "qabstractbarseries_p.h"
+#include "qboxset.h"
+#include "boxwhiskers_p.h"
+#include <QPainter>
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+BoxPlotChartItem::BoxPlotChartItem(QBoxPlotSeries *series, QGraphicsItem *item) :
+ ChartItem(series->d_func(), item),
+ m_series(series),
+ m_animation(0),
+ m_animate(0),
+ m_domainMaxY(0.0),
+ m_domainMinY(0.0)
+{
+ connect(series, SIGNAL(boxsetsRemoved(QList<QBoxSet *>)), this, SLOT(handleBoxsetRemove(QList<QBoxSet *>)));
+ connect(series->d_func(), SIGNAL(restructuredBoxes()), this, SLOT(handleDataStructureChanged()));
+ connect(series->d_func(), SIGNAL(updatedLayout()), this, SLOT(handleLayoutChanged()));
+ connect(series->d_func(), SIGNAL(updatedBoxes()), this, SLOT(handleUpdatedBars()));
+ connect(series->d_func(), SIGNAL(updated()), this, SLOT(handleUpdatedBars()));
+ // QBoxPlotSeriesPrivate calls handleDataStructureChanged(), don't do it here
+ setZValue(ChartPresenter::BoxPlotSeriesZValue);
+}
+
+BoxPlotChartItem::~BoxPlotChartItem()
+{
+}
+
+void BoxPlotChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(painter);
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+}
+
+void BoxPlotChartItem::setAnimation(BoxPlotAnimation *animation)
+{
+ m_animation = animation;
+ if (m_animation) {
+ foreach (BoxWhiskers *item, m_boxTable.values())
+ m_animation->addBox(item);
+ handleDomainUpdated();
+ }
+}
+
+void BoxPlotChartItem::handleDataStructureChanged()
+{
+ int setCount = m_series->count();
+
+ for (int s = 0; s < setCount; s++) {
+ QBoxSet *set = m_series->d_func()->boxSetAt(s);
+
+ BoxWhiskers *box = m_boxTable.value(set);
+ if (!box) {
+ // Item is not yet created, make a box and add it to hash table
+ box = new BoxWhiskers(set, domain(), this);
+ m_boxTable.insert(set, box);
+ connect(box, SIGNAL(clicked(QBoxSet *)), m_series, SIGNAL(clicked(QBoxSet *)));
+ connect(box, SIGNAL(hovered(bool, QBoxSet *)), m_series, SIGNAL(hovered(bool, QBoxSet *)));
+ connect(box, SIGNAL(clicked(QBoxSet *)), set, SIGNAL(clicked()));
+ connect(box, SIGNAL(hovered(bool, QBoxSet *)), set, SIGNAL(hovered(bool)));
+
+ // Set the decorative issues for the newly created box
+ box->setBrush(m_series->brush());
+ box->setPen(m_series->pen());
+ }
+ updateBoxGeometry(box, s);
+
+ box->updateGeometry();
+
+ if (m_animation)
+ m_animation->addBox(box);
+ }
+
+ handleDomainUpdated();
+}
+
+void BoxPlotChartItem::handleUpdatedBars()
+{
+ foreach (BoxWhiskers *item, m_boxTable.values()) {
+ item->setBrush(m_series->brush());
+ item->setPen(m_series->pen());
+ }
+ // Override with QBoxSet specific settings
+ foreach (QBoxSet *set, m_boxTable.keys()) {
+ if (set->brush().style() != Qt::NoBrush)
+ m_boxTable.value(set)->setBrush(set->brush());
+ if (set->pen().style() != Qt::NoPen)
+ m_boxTable.value(set)->setPen(set->pen());
+ }
+}
+
+void BoxPlotChartItem::handleBoxsetRemove(QList<QBoxSet*> barSets)
+{
+ foreach (QBoxSet *set, barSets) {
+ BoxWhiskers *boxItem = m_boxTable.value(set);
+ m_boxTable.remove(set);
+ delete boxItem;
+ }
+}
+
+void BoxPlotChartItem::handleDomainUpdated()
+{
+ if ((domain()->size().width() <= 0) || (domain()->size().height() <= 0))
+ return;
+
+ // Set my bounding rect to same as domain size
+ m_boundingRect.setRect(0.0, 0.0, domain()->size().width(), domain()->size().height());
+
+ foreach (BoxWhiskers *item, m_boxTable.values()) {
+ // Update the domain size for each BoxWhisker item
+ item->setDomainSize(domain()->size());
+ if (domain()->minY() != m_domainMinY || domain()->maxY() != m_domainMaxY) {
+ item->updateGeometry();
+ m_domainMinY = domain()->minY();
+ m_domainMaxY = domain()->maxY();
+ }
+
+ // If the animation is set, start the animation for each BoxWhisker item
+ if (m_animation)
+ presenter()->startAnimation(m_animation->boxAnimation(item));
+ }
+}
+
+void BoxPlotChartItem::handleLayoutChanged()
+{
+ foreach (BoxWhiskers *item, m_boxTable.values()) {
+ if (m_animation)
+ m_animation->setAnimationStart(item);
+
+ bool dirty = updateBoxGeometry(item, item->m_data.m_index);
+ if (dirty && m_animation)
+ presenter()->startAnimation(m_animation->boxChangeAnimation(item));
+ else
+ item->updateGeometry();
+ }
+}
+
+QRectF BoxPlotChartItem::boundingRect() const
+{
+ return m_boundingRect;
+}
+
+void BoxPlotChartItem::initializeLayout()
+{
+}
+
+QVector<QRectF> BoxPlotChartItem::calculateLayout()
+{
+ return QVector<QRectF>();
+}
+
+bool BoxPlotChartItem::updateBoxGeometry(BoxWhiskers *box, int index)
+{
+ bool changed = false;
+
+ QBoxSet *set = m_series->d_func()->boxSetAt(index);
+ BoxWhiskersData &data = box->m_data;
+
+ if ((data.m_lowerExtreme != set->at(0)) || (data.m_lowerQuartile != set->at(1)) ||
+ (data.m_median != set->at(2)) || (data.m_upperQuartile != set->at(3)) || (data.m_upperExtreme != set->at(4))) {
+ changed = true;
+ }
+
+ data.m_lowerExtreme = set->at(0);
+ data.m_lowerQuartile = set->at(1);
+ data.m_median = set->at(2);
+ data.m_upperQuartile = set->at(3);
+ data.m_upperExtreme = set->at(4);
+ data.m_index = index;
+ data.m_boxItems = m_series->count();
+
+ data.m_maxX = domain()->maxX();
+ data.m_minX = domain()->minX();
+ data.m_maxY = domain()->maxY();
+ data.m_minY = domain()->minY();
+
+ data.m_seriesIndex = m_seriesIndex;
+ data.m_seriesCount = m_seriesCount;
+
+ return changed;
+}
+
+#include "moc_boxplotchartitem_p.cpp"
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/boxplotchart/boxplotchartitem_p.h b/src/boxplotchart/boxplotchartitem_p.h
new file mode 100644
index 00000000..dafaf365
--- /dev/null
+++ b/src/boxplotchart/boxplotchartitem_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** 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 BOXPLOTCHARTITEM_H
+#define BOXPLOTCHARTITEM_H
+
+#include "boxwhiskers_p.h"
+#include "qboxplotseries.h"
+#include "chartitem_p.h"
+#include "boxplotanimation_p.h"
+#include "qboxset.h"
+#include <QGraphicsItem>
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+class BoxPlotSeriesPrivate;
+
+class BoxPlotChartItem : public ChartItem
+{
+ Q_OBJECT
+public:
+ BoxPlotChartItem(QBoxPlotSeries *series, QGraphicsItem *item = 0);
+ ~BoxPlotChartItem();
+
+ void setAnimation(BoxPlotAnimation *animation);
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+ QRectF boundingRect() const;
+
+public Q_SLOTS:
+ void handleDataStructureChanged();
+ void handleDomainUpdated();
+ void handleLayoutChanged();
+ void handleUpdatedBars();
+ void handleBoxsetRemove(QList<QBoxSet *> barSets);
+
+private:
+ virtual QVector<QRectF> calculateLayout();
+ void initializeLayout();
+ bool updateBoxGeometry(BoxWhiskers *box, int index);
+
+protected:
+ friend class QBoxPlotSeriesPrivate;
+ QBoxPlotSeries *m_series; // Not owned.
+ QList<BoxWhiskers *> m_boxes;
+ QHash<QBoxSet *, BoxWhiskers *> m_boxTable;
+ int m_seriesIndex;
+ int m_seriesCount;
+
+ BoxPlotAnimation *m_animation;
+ bool m_animate;
+ qreal m_domainMaxY;
+ qreal m_domainMinY;
+
+ QRectF m_boundingRect;
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // BOXPLOTCHARTITEM_H
diff --git a/src/boxplotchart/boxwhiskers.cpp b/src/boxplotchart/boxwhiskers.cpp
new file mode 100644
index 00000000..7bc378d3
--- /dev/null
+++ b/src/boxplotchart/boxwhiskers.cpp
@@ -0,0 +1,167 @@
+/****************************************************************************
+ **
+ ** 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 "boxwhiskers_p.h"
+#include <QPainter>
+#include <QWidget>
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+BoxWhiskers::BoxWhiskers(QBoxSet *set, AbstractDomain *domain, QGraphicsObject *parent) :
+ QGraphicsObject(parent),
+ m_boxSet(set),
+ m_domain(domain)
+{
+ setAcceptHoverEvents(true);
+ setAcceptedMouseButtons(Qt::MouseButtonMask);
+}
+
+BoxWhiskers::~BoxWhiskers()
+{
+}
+
+void BoxWhiskers::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_UNUSED(event)
+ emit clicked(m_boxSet);
+}
+
+void BoxWhiskers::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
+{
+ Q_UNUSED(event)
+ emit hovered(true, m_boxSet);
+}
+
+void BoxWhiskers::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
+{
+ Q_UNUSED(event)
+ emit hovered(false, m_boxSet);
+}
+
+void BoxWhiskers::setBrush(const QBrush &brush)
+{
+ m_brush = brush;
+ update();
+}
+
+void BoxWhiskers::setPen(const QPen &pen)
+{
+ m_pen = pen;
+ update();
+}
+
+void BoxWhiskers::setLayout(const BoxWhiskersData &data)
+{
+ m_data = data;
+
+ updateGeometry();
+ update();
+}
+
+
+QSizeF BoxWhiskers::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED(which)
+ Q_UNUSED(constraint)
+
+ return QSizeF();
+}
+
+void BoxWhiskers::setGeometry(const QRectF &rect)
+{
+ Q_UNUSED(rect)
+}
+
+void BoxWhiskers::setDomainSize(const QSizeF &size)
+{
+ m_domainSize = size;
+
+ updateBoundingRect();
+}
+
+QRectF BoxWhiskers::boundingRect() const
+{
+ return m_boundingRect;
+}
+
+void BoxWhiskers::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option)
+ Q_UNUSED(widget)
+
+ painter->setPen(m_pen);
+ painter->setBrush(m_brush);
+ painter->setClipRect(parentItem()->boundingRect());
+ painter->scale(m_domainSize.width() / m_data.m_boxItems, m_domainSize.height() / m_domain->spanY());
+ painter->drawPath(m_boxPath);
+}
+
+void BoxWhiskers::updateGeometry()
+{
+ prepareGeometryChange();
+
+ QPainterPath path;
+
+ qreal columnWidth = 1.0 / m_data.m_seriesCount;
+ qreal left = 0.25 * columnWidth + columnWidth * m_data.m_seriesIndex;
+ qreal right = 0.75 * columnWidth + columnWidth * m_data.m_seriesIndex;
+ qreal middle = 0.5 * columnWidth + columnWidth * m_data.m_seriesIndex;
+ qreal domainMaxY = m_domain->maxY();
+
+ // Upper whisker
+ path.moveTo(left + m_data.m_index, domainMaxY - m_data.m_upperExtreme);
+ path.lineTo(right + m_data.m_index, domainMaxY - m_data.m_upperExtreme);
+ path.moveTo(middle + m_data.m_index, domainMaxY - m_data.m_upperExtreme);
+ path.lineTo(middle + m_data.m_index, domainMaxY - m_data.m_upperQuartile);
+
+ // Middle Box
+ path.addRect(left + m_data.m_index, domainMaxY - m_data.m_upperQuartile,
+ 0.5 * columnWidth, m_data.m_upperQuartile - m_data.m_lowerQuartile);
+
+ // Median/mean line
+ path.moveTo(left + m_data.m_index, domainMaxY - m_data.m_median);
+ path.lineTo(right + m_data.m_index, domainMaxY - m_data.m_median);
+
+ // Lower whisker
+ path.moveTo(left + m_data.m_index, domainMaxY - m_data.m_lowerExtreme);
+ path.lineTo(right + m_data.m_index, domainMaxY - m_data.m_lowerExtreme);
+ path.moveTo(middle + m_data.m_index, domainMaxY - m_data.m_lowerExtreme);
+ path.lineTo(middle + m_data.m_index, domainMaxY - m_data.m_lowerQuartile);
+
+ path.closeSubpath();
+
+ m_boxPath = path;
+
+ updateBoundingRect();
+}
+
+void BoxWhiskers::updateBoundingRect()
+{
+ qreal scaleY = m_domainSize.height() / (m_domain->maxY() - m_domain->minY());
+ qreal scaleX = m_domainSize.width() / m_data.m_boxItems;
+ QRectF br = m_boxPath.boundingRect();
+
+ m_boundingRect = QRectF(br.x() * scaleX, br.y() * scaleY,
+ br.width() * scaleX, br.height() * scaleY);
+}
+
+#include "moc_boxwhiskers_p.cpp"
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/boxplotchart/boxwhiskers_p.h b/src/boxplotchart/boxwhiskers_p.h
new file mode 100644
index 00000000..63cf2259
--- /dev/null
+++ b/src/boxplotchart/boxwhiskers_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** 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 BOXWHISKERS_H
+#define BOXWHISKERS_H
+
+#include "boxwhiskersdata_p.h"
+#include "qchartglobal.h"
+#include "abstractdomain_p.h"
+#include <QBoxSet>
+#include <QGraphicsRectItem>
+#include <QGraphicsLineItem>
+#include <QGraphicsLayoutItem>
+#include <QPainterPath>
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+class QBarSet;
+
+class BoxWhiskers : public QGraphicsObject
+{
+ Q_OBJECT
+
+public:
+ BoxWhiskers(QBoxSet *set, AbstractDomain *domain, QGraphicsObject *parent);
+ ~BoxWhiskers();
+
+ void setBrush(const QBrush &brush);
+ void setPen(const QPen &pen);
+ void setLayout(const BoxWhiskersData &data);
+ void setDomainSize(const QSizeF &size);
+
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
+ void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
+
+ QRectF boundingRect() const;
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ void updateGeometry();
+protected:
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const;
+ void setGeometry(const QRectF &rect);
+
+private:
+ void updateBoundingRect();
+
+Q_SIGNALS:
+ void clicked(QBoxSet *boxset);
+ void hovered(bool status, QBoxSet *boxset);
+
+private:
+ friend class BoxPlotChartItem;
+ friend class BoxPlotAnimation;
+
+ QBoxSet *m_boxSet;
+ AbstractDomain *m_domain;
+ QPainterPath m_boxPath;
+ QRectF m_boundingRect;
+ bool m_hovering;
+ bool m_validData;
+ QBrush m_brush;
+ QPen m_pen;
+ BoxWhiskersData m_data;
+ QSizeF m_domainSize;
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // BOXWHISKERS_H
diff --git a/src/boxplotchart/boxwhiskersdata_p.h b/src/boxplotchart/boxwhiskersdata_p.h
new file mode 100644
index 00000000..557c3cb7
--- /dev/null
+++ b/src/boxplotchart/boxwhiskersdata_p.h
@@ -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$
+**
+****************************************************************************/
+
+// 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 BOXWHISKERSDATA_P_H
+#define BOXWHISKERSDATA_P_H
+
+#include "qchartglobal.h"
+#include <QSizeF>
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+class BoxWhiskersData
+{
+public:
+ BoxWhiskersData() :
+ m_lowerExtreme(0.0),
+ m_lowerQuartile(0.0),
+ m_median(0.0),
+ m_upperQuartile(0.0),
+ m_upperExtreme(0.0),
+ m_index(0),
+ m_boxItems(0),
+ m_maxX(0.0),
+ m_minX(0.0),
+ m_maxY(0.0),
+ m_minY(0.0),
+ m_seriesIndex(0),
+ m_seriesCount(0)
+ {
+ }
+
+ // Box related statistics
+ qreal m_lowerExtreme;
+ qreal m_lowerQuartile;
+ qreal m_median;
+ qreal m_upperQuartile;
+ qreal m_upperExtreme;
+ int m_index;
+ int m_boxItems;
+
+ // Domain boundaries, axis
+ qreal m_maxX;
+ qreal m_minX;
+ qreal m_maxY;
+ qreal m_minY;
+
+ // Serieses related data
+ int m_seriesIndex;
+ int m_seriesCount;
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // BOXWHISKERSDATA_P_H
diff --git a/src/boxplotchart/qboxplotmodelmapper.cpp b/src/boxplotchart/qboxplotmodelmapper.cpp
new file mode 100644
index 00000000..98cf91fd
--- /dev/null
+++ b/src/boxplotchart/qboxplotmodelmapper.cpp
@@ -0,0 +1,532 @@
+/****************************************************************************
+**
+** 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 "qboxplotmodelmapper.h"
+#include "qboxplotmodelmapper_p.h"
+#include "qboxplotseries.h"
+#include "qboxset.h"
+#include "qchart.h"
+#include <QAbstractItemModel>
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+QBoxPlotModelMapper::QBoxPlotModelMapper(QObject *parent) :
+ QObject(parent),
+ d_ptr(new QBoxPlotModelMapperPrivate(this))
+{
+}
+
+QAbstractItemModel *QBoxPlotModelMapper::model() const
+{
+ Q_D(const QBoxPlotModelMapper);
+ return d->m_model;
+}
+
+void QBoxPlotModelMapper::setModel(QAbstractItemModel *model)
+{
+ if (model == 0)
+ return;
+
+ Q_D(QBoxPlotModelMapper);
+ if (d->m_model)
+ disconnect(d->m_model, 0, d, 0);
+
+ d->m_model = model;
+ d->initializeBoxFromModel();
+ // connect signals from the model
+ connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
+ connect(d->m_model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), d, SLOT(modelHeaderDataUpdated(Qt::Orientation,int,int)));
+ connect(d->m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelRowsAdded(QModelIndex,int,int)));
+ connect(d->m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelRowsRemoved(QModelIndex,int,int)));
+ connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelColumnsAdded(QModelIndex,int,int)));
+ connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelColumnsRemoved(QModelIndex,int,int)));
+ connect(d->m_model, SIGNAL(destroyed()), d, SLOT(handleModelDestroyed()));
+}
+
+QBoxPlotSeries *QBoxPlotModelMapper::series() const
+{
+ Q_D(const QBoxPlotModelMapper);
+ return d->m_series;
+}
+
+void QBoxPlotModelMapper::setSeries(QBoxPlotSeries *series)
+{
+ Q_D(QBoxPlotModelMapper);
+ if (d->m_series)
+ disconnect(d->m_series, 0, d, 0);
+
+ if (series == 0)
+ return;
+
+ d->m_series = series;
+ d->initializeBoxFromModel();
+ // connect the signals from the series
+ connect(d->m_series, SIGNAL(boxsetsAdded(QList<QBoxSet *>)), d, SLOT(boxSetsAdded(QList<QBoxSet *>)));
+ connect(d->m_series, SIGNAL(boxsetsRemoved(QList<QBoxSet *>)), d, SLOT(boxSetsRemoved(QList<QBoxSet *>)));
+ connect(d->m_series, SIGNAL(destroyed()), d, SLOT(handleSeriesDestroyed()));
+}
+
+/*!
+ Returns which row/column of the model contains the first values of the QBoxSets in the series.
+ The default value is 0.
+*/
+int QBoxPlotModelMapper::first() const
+{
+ Q_D(const QBoxPlotModelMapper);
+ return d->m_first;
+}
+
+/*!
+ Sets which row/column of the model contains the \a first values of the QBoxSets in the series.
+ The default value is 0.
+*/
+void QBoxPlotModelMapper::setFirst(int first)
+{
+ Q_D(QBoxPlotModelMapper);
+ d->m_first = qMax(first, 0);
+ d->initializeBoxFromModel();
+}
+
+/*!
+ Returns the number of rows/columns of the model that are mapped as the data for QBoxPlotSeries
+ Minimal and default value is: -1 (count limited by the number of rows/columns in the model)
+*/
+int QBoxPlotModelMapper::count() const
+{
+ Q_D(const QBoxPlotModelMapper);
+ return d->m_count;
+}
+
+/*!
+ Sets the \a count of rows/columns of the model that are mapped as the data for QBoxPlotSeries
+ Minimal and default value is: -1 (count limited by the number of rows/columns in the model)
+*/
+void QBoxPlotModelMapper::setCount(int count)
+{
+ Q_D(QBoxPlotModelMapper);
+ d->m_count = qMax(count, -1);
+ d->initializeBoxFromModel();
+}
+
+/*!
+ Returns the orientation that is used when QBoxPlotModelMapper accesses the model.
+ This means whether the consecutive values of the box-and-whiskers set are read from row (Qt::Horizontal)
+ or from columns (Qt::Vertical)
+*/
+Qt::Orientation QBoxPlotModelMapper::orientation() const
+{
+ Q_D(const QBoxPlotModelMapper);
+ return d->m_orientation;
+}
+
+/*!
+ Returns the \a orientation that is used when QBoxPlotModelMapper accesses the model.
+ This mean whether the consecutive values of the box-and-whiskers set are read from row (Qt::Horizontal)
+ or from columns (Qt::Vertical)
+*/
+void QBoxPlotModelMapper::setOrientation(Qt::Orientation orientation)
+{
+ Q_D(QBoxPlotModelMapper);
+ d->m_orientation = orientation;
+ d->initializeBoxFromModel();
+}
+
+/*!
+ Returns which section of the model is used as the data source for the first box set
+*/
+int QBoxPlotModelMapper::firstBoxSetSection() const
+{
+ Q_D(const QBoxPlotModelMapper);
+ return d->m_firstBoxSetSection;
+}
+
+/*!
+ Sets the model section that is used as the data source for the first box set
+ Parameter \a firstBoxSetSection specifies the section of the model.
+*/
+void QBoxPlotModelMapper::setFirstBoxSetSection(int firstBoxSetSection)
+{
+ Q_D(QBoxPlotModelMapper);
+ d->m_firstBoxSetSection = qMax(-1, firstBoxSetSection);
+ d->initializeBoxFromModel();
+}
+
+/*!
+ Returns which section of the model is used as the data source for the last box set
+*/
+int QBoxPlotModelMapper::lastBoxSetSection() const
+{
+ Q_D(const QBoxPlotModelMapper);
+ return d->m_lastBoxSetSection;
+}
+
+/*!
+ Sets the model section that is used as the data source for the last box set
+ Parameter \a lastBoxSetSection specifies the section of the model.
+*/
+void QBoxPlotModelMapper::setLastBoxSetSection(int lastBoxSetSection)
+{
+ Q_D(QBoxPlotModelMapper);
+ d->m_lastBoxSetSection = qMax(-1, lastBoxSetSection);
+ d->initializeBoxFromModel();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QBoxPlotModelMapperPrivate::QBoxPlotModelMapperPrivate(QBoxPlotModelMapper *q) :
+ QObject(q),
+ m_series(0),
+ m_model(0),
+ m_first(0),
+ m_count(-1),
+ m_orientation(Qt::Vertical),
+ m_firstBoxSetSection(-1),
+ m_lastBoxSetSection(-1),
+ m_seriesSignalsBlock(false),
+ m_modelSignalsBlock(false),
+ q_ptr(q)
+{
+}
+
+void QBoxPlotModelMapperPrivate::blockModelSignals(bool block)
+{
+ m_modelSignalsBlock = block;
+}
+
+void QBoxPlotModelMapperPrivate::blockSeriesSignals(bool block)
+{
+ m_seriesSignalsBlock = block;
+}
+
+QBoxSet *QBoxPlotModelMapperPrivate::boxSet(QModelIndex index)
+{
+ if (!index.isValid())
+ return 0;
+
+ if (m_orientation == Qt::Vertical && index.column() >= m_firstBoxSetSection && index.column() <= m_lastBoxSetSection) {
+ if (index.row() >= m_first && (m_count == - 1 || index.row() < m_first + m_count))
+ return m_series->boxSets().at(index.column() - m_firstBoxSetSection);
+ } else if (m_orientation == Qt::Horizontal && index.row() >= m_firstBoxSetSection && index.row() <= m_lastBoxSetSection) {
+ if (index.column() >= m_first && (m_count == - 1 || index.column() < m_first + m_count))
+ return m_series->boxSets().at(index.row() - m_firstBoxSetSection);
+ }
+ return 0; // This part of model has not been mapped to any boxset
+}
+
+QModelIndex QBoxPlotModelMapperPrivate::boxModelIndex(int boxSection, int posInBar)
+{
+ if (m_count != -1 && posInBar >= m_count)
+ return QModelIndex(); // invalid
+
+ if (boxSection < m_firstBoxSetSection || boxSection > m_lastBoxSetSection)
+ return QModelIndex(); // invalid
+
+ if (m_orientation == Qt::Vertical)
+ return m_model->index(posInBar + m_first, boxSection);
+ else
+ return m_model->index(boxSection, posInBar + m_first);
+}
+
+void QBoxPlotModelMapperPrivate::handleSeriesDestroyed()
+{
+ m_series = 0;
+}
+
+void QBoxPlotModelMapperPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
+{
+ Q_UNUSED(topLeft)
+ Q_UNUSED(bottomRight)
+
+ if (m_model == 0 || m_series == 0)
+ return;
+
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ QModelIndex index;
+ for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
+ for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
+ index = topLeft.sibling(row, column);
+ QBoxSet *box = boxSet(index);
+ if (box) {
+ if (m_orientation == Qt::Vertical)
+ box->setValue(row - m_first, m_model->data(index).toReal());
+ else
+ box->setValue(column - m_first, m_model->data(index).toReal());
+ }
+ }
+ }
+ blockSeriesSignals(false);
+}
+
+void QBoxPlotModelMapperPrivate::modelHeaderDataUpdated(Qt::Orientation orientation, int first, int last)
+{
+ Q_UNUSED(orientation);
+ Q_UNUSED(first);
+ Q_UNUSED(last);
+}
+
+void QBoxPlotModelMapperPrivate::modelRowsAdded(QModelIndex parent, int start, int end)
+{
+ Q_UNUSED(parent)
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ if (m_orientation == Qt::Vertical)
+ insertData(start, end);
+ else if (start <= m_firstBoxSetSection || start <= m_lastBoxSetSection) // if the changes affect the map - reinitialize
+ initializeBoxFromModel();
+ blockSeriesSignals(false);
+}
+
+void QBoxPlotModelMapperPrivate::modelRowsRemoved(QModelIndex parent, int start, int end)
+{
+ Q_UNUSED(parent)
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ if (m_orientation == Qt::Vertical)
+ removeData(start, end);
+ else if (start <= m_firstBoxSetSection || start <= m_lastBoxSetSection) // if the changes affect the map - reinitialize
+ initializeBoxFromModel();
+ blockSeriesSignals(false);
+}
+
+void QBoxPlotModelMapperPrivate::modelColumnsAdded(QModelIndex parent, int start, int end)
+{
+ Q_UNUSED(parent)
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ if (m_orientation == Qt::Horizontal)
+ insertData(start, end);
+ else if (start <= m_firstBoxSetSection || start <= m_lastBoxSetSection) // if the changes affect the map - reinitialize
+ initializeBoxFromModel();
+ blockSeriesSignals(false);
+}
+
+void QBoxPlotModelMapperPrivate::modelColumnsRemoved(QModelIndex parent, int start, int end)
+{
+ Q_UNUSED(parent)
+ if (m_modelSignalsBlock)
+ return;
+
+ blockSeriesSignals();
+ if (m_orientation == Qt::Horizontal)
+ removeData(start, end);
+ else if (start <= m_firstBoxSetSection || start <= m_lastBoxSetSection) // if the changes affect the map - reinitialize
+ initializeBoxFromModel();
+ blockSeriesSignals(false);
+}
+
+void QBoxPlotModelMapperPrivate::handleModelDestroyed()
+{
+ m_model = 0;
+}
+
+void QBoxPlotModelMapperPrivate::insertData(int start, int end)
+{
+ Q_UNUSED(end)
+ Q_UNUSED(start)
+ Q_UNUSED(end)
+ // Currently boxplotchart needs to be fully recalculated when change is made.
+ // Re-initialize
+ initializeBoxFromModel();
+}
+
+void QBoxPlotModelMapperPrivate::removeData(int start, int end)
+{
+ Q_UNUSED(end)
+ Q_UNUSED(start)
+ Q_UNUSED(end)
+ // Currently boxplotchart needs to be fully recalculated when change is made.
+ // Re-initialize
+ initializeBoxFromModel();
+}
+
+void QBoxPlotModelMapperPrivate::boxSetsAdded(QList<QBoxSet *> sets)
+{
+ if (m_seriesSignalsBlock)
+ return;
+
+ if (sets.count() == 0)
+ return;
+
+ int firstIndex = m_series->boxSets().indexOf(sets.at(0));
+ if (firstIndex == -1)
+ return;
+
+ int maxCount = 0;
+ for (int i = 0; i < sets.count(); i++) {
+ if (sets.at(i)->count() > m_count)
+ maxCount = sets.at(i)->count();
+ }
+
+ if (m_count != -1 && m_count < maxCount)
+ m_count = maxCount;
+
+ m_lastBoxSetSection += sets.count();
+
+ blockModelSignals();
+ int modelCapacity = m_orientation == Qt::Vertical ? m_model->rowCount() - m_first : m_model->columnCount() - m_first;
+ if (maxCount > modelCapacity) {
+ if (m_orientation == Qt::Vertical)
+ m_model->insertRows(m_model->rowCount(), maxCount - modelCapacity);
+ else
+ m_model->insertColumns(m_model->columnCount(), maxCount - modelCapacity);
+ }
+
+ if (m_orientation == Qt::Vertical)
+ m_model->insertColumns(firstIndex + m_firstBoxSetSection, sets.count());
+ else
+ m_model->insertRows(firstIndex + m_firstBoxSetSection, sets.count());
+
+
+ for (int i = firstIndex + m_firstBoxSetSection; i < firstIndex + m_firstBoxSetSection + sets.count(); i++) {
+ for (int j = 0; j < sets.at(i - firstIndex - m_firstBoxSetSection)->count(); j++)
+ m_model->setData(boxModelIndex(i, j), sets.at(i - firstIndex - m_firstBoxSetSection)->at(j));
+ }
+ blockModelSignals(false);
+ initializeBoxFromModel();
+}
+
+void QBoxPlotModelMapperPrivate::boxSetsRemoved(QList<QBoxSet *> sets)
+{
+ if (m_seriesSignalsBlock)
+ return;
+
+ if (sets.count() == 0)
+ return;
+
+ int firstIndex = m_boxSets.indexOf(sets.at(0));
+ if (firstIndex == -1)
+ return;
+
+ m_lastBoxSetSection -= sets.count();
+
+ for (int i = firstIndex + sets.count() - 1; i >= firstIndex; i--)
+ m_boxSets.removeAt(i);
+
+ blockModelSignals();
+ if (m_orientation == Qt::Vertical)
+ m_model->removeColumns(firstIndex + m_firstBoxSetSection, sets.count());
+ else
+ m_model->removeRows(firstIndex + m_firstBoxSetSection, sets.count());
+ blockModelSignals(false);
+ initializeBoxFromModel();
+}
+
+void QBoxPlotModelMapperPrivate::valuesAdded(int index, int count)
+{
+ if (m_seriesSignalsBlock)
+ return;
+
+ if (m_count != -1)
+ m_count += count;
+
+ int boxSetIndex = m_boxSets.indexOf(qobject_cast<QBoxSet *>(QObject::sender()));
+
+ blockModelSignals();
+ if (m_orientation == Qt::Vertical)
+ m_model->insertRows(index + m_first, count);
+ else
+ m_model->insertColumns(index + m_first, count);
+
+ for (int j = index; j < index + count; j++)
+ m_model->setData(boxModelIndex(boxSetIndex + m_firstBoxSetSection, j), m_boxSets.at(boxSetIndex)->at(j));
+
+ blockModelSignals(false);
+ initializeBoxFromModel();
+}
+
+void QBoxPlotModelMapperPrivate::valuesRemoved(int index, int count)
+{
+ if (m_seriesSignalsBlock)
+ return;
+
+ if (m_count != -1)
+ m_count -= count;
+
+ blockModelSignals();
+ if (m_orientation == Qt::Vertical)
+ m_model->removeRows(index + m_first, count);
+ else
+ m_model->removeColumns(index + m_first, count);
+
+ blockModelSignals(false);
+ initializeBoxFromModel();
+}
+
+void QBoxPlotModelMapperPrivate::boxValueChanged(int index)
+{
+ if (m_seriesSignalsBlock)
+ return;
+
+ int boxSetIndex = m_boxSets.indexOf(qobject_cast<QBoxSet *>(QObject::sender()));
+
+ blockModelSignals();
+ m_model->setData(boxModelIndex(boxSetIndex + m_firstBoxSetSection, index), m_boxSets.at(boxSetIndex)->at(index));
+ blockModelSignals(false);
+ initializeBoxFromModel();
+}
+
+void QBoxPlotModelMapperPrivate::initializeBoxFromModel()
+{
+ if (m_model == 0 || m_series == 0)
+ return;
+
+ blockSeriesSignals();
+ // clear current content
+ m_series->clear();
+ m_boxSets.clear();
+
+ // create the initial box-and-whiskers sets
+ for (int i = m_firstBoxSetSection; i <= m_lastBoxSetSection; i++) {
+ int posInBar = 0;
+ QModelIndex boxIndex = boxModelIndex(i, posInBar);
+ // check if there is such model index
+ if (boxIndex.isValid()) {
+ QBoxSet *boxSet = new QBoxSet();
+ while (boxIndex.isValid()) {
+ boxSet->append(m_model->data(boxIndex, Qt::DisplayRole).toDouble());
+ posInBar++;
+ boxIndex = boxModelIndex(i, posInBar);
+ }
+ connect(boxSet, SIGNAL(valuesAdded(int,int)), this, SLOT(valuesAdded(int,int)));
+ connect(boxSet, SIGNAL(valuesRemoved(int,int)), this, SLOT(valuesRemoved(int,int)));
+ connect(boxSet, SIGNAL(valueChanged(int)), this, SLOT(boxValueChanged(int)));
+ m_series->append(boxSet);
+ m_boxSets.append(boxSet);
+ } else {
+ break;
+ }
+ }
+ blockSeriesSignals(false);
+}
+
+#include "moc_qboxplotmodelmapper.cpp"
+#include "moc_qboxplotmodelmapper_p.cpp"
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
diff --git a/src/boxplotchart/qboxplotmodelmapper.h b/src/boxplotchart/qboxplotmodelmapper.h
new file mode 100644
index 00000000..8db87a65
--- /dev/null
+++ b/src/boxplotchart/qboxplotmodelmapper.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** 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 QBOXPLOTMODELMAPPER_H
+#define QBOXPLOTMODELMAPPER_H
+
+#include "qchartglobal.h"
+#include <QObject>
+
+class QAbstractItemModel;
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+class QBoxPlotModelMapperPrivate;
+class QBoxPlotSeries;
+
+class QTCOMMERCIALCHART_EXPORT QBoxPlotModelMapper : public QObject
+{
+ Q_OBJECT
+
+protected:
+ explicit QBoxPlotModelMapper(QObject *parent = 0);
+
+ QAbstractItemModel *model() const;
+ void setModel(QAbstractItemModel *model);
+
+ QBoxPlotSeries *series() const;
+ void setSeries(QBoxPlotSeries *series);
+
+ int first() const;
+ void setFirst(int first);
+
+ int count() const;
+ void setCount(int count);
+
+ int firstBoxSetSection() const;
+ void setFirstBoxSetSection(int firstBoxSetSection);
+
+ int lastBoxSetSection() const;
+ void setLastBoxSetSection(int lastBoxSetSection);
+
+ Qt::Orientation orientation() const;
+ void setOrientation(Qt::Orientation orientation);
+
+protected:
+ QBoxPlotModelMapperPrivate * const d_ptr;
+ Q_DECLARE_PRIVATE(QBoxPlotModelMapper)
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // QBOXPLOTMODELMAPPER_H
diff --git a/src/boxplotchart/qboxplotmodelmapper_p.h b/src/boxplotchart/qboxplotmodelmapper_p.h
new file mode 100644
index 00000000..bfeeb80e
--- /dev/null
+++ b/src/boxplotchart/qboxplotmodelmapper_p.h
@@ -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$
+**
+****************************************************************************/
+
+// 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 QBOXPLOTMODELMAPPER_P_H
+#define QBOXPLOTMODELMAPPER_P_H
+
+#include <QObject>
+#include "qboxplotmodelmapper.h"
+
+class QModelIndex;
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+class QBoxSet;
+
+class QBoxPlotModelMapperPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QBoxPlotModelMapperPrivate(QBoxPlotModelMapper *q);
+
+public Q_SLOTS:
+ // for the model
+ void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight);
+ void modelHeaderDataUpdated(Qt::Orientation orientation, int first, int last);
+ void modelRowsAdded(QModelIndex parent, int start, int end);
+ void modelRowsRemoved(QModelIndex parent, int start, int end);
+ void modelColumnsAdded(QModelIndex parent, int start, int end);
+ void modelColumnsRemoved(QModelIndex parent, int start, int end);
+ void handleModelDestroyed();
+
+ // for the series
+ void boxSetsAdded(QList<QBoxSet *> sets);
+ void boxSetsRemoved(QList<QBoxSet *> sets);
+ void valuesAdded(int index, int count);
+ void valuesRemoved(int index, int count);
+ void boxValueChanged(int index);
+ void handleSeriesDestroyed();
+
+ void initializeBoxFromModel();
+
+private:
+ QBoxSet *boxSet(QModelIndex index);
+ QModelIndex boxModelIndex(int boxSection, int posInBox);
+ void insertData(int start, int end);
+ void removeData(int start, int end);
+ void blockModelSignals(bool block = true);
+ void blockSeriesSignals(bool block = true);
+
+private:
+ QBoxPlotSeries *m_series;
+ QList<QBoxSet *> m_boxSets;
+ QAbstractItemModel *m_model;
+ int m_first;
+ int m_count;
+ Qt::Orientation m_orientation;
+ int m_firstBoxSetSection;
+ int m_lastBoxSetSection;
+ bool m_seriesSignalsBlock;
+ bool m_modelSignalsBlock;
+
+private:
+ QBoxPlotModelMapper *q_ptr;
+ Q_DECLARE_PUBLIC(QBoxPlotModelMapper)
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // QBOXPLOTMODELMAPPER_P_H
diff --git a/src/boxplotchart/qboxplotseries.cpp b/src/boxplotchart/qboxplotseries.cpp
new file mode 100644
index 00000000..842a9eb1
--- /dev/null
+++ b/src/boxplotchart/qboxplotseries.cpp
@@ -0,0 +1,680 @@
+/****************************************************************************
+**
+** 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 "qboxplotseries.h"
+#include "qboxplotseries_p.h"
+#include "qboxplotlegendmarker.h"
+#include "qbarcategoryaxis.h"
+#include "boxplotchartitem_p.h"
+#include "chartdataset_p.h"
+#include "charttheme_p.h"
+#include "qvalueaxis.h"
+#include "charttheme_p.h"
+#include "boxplotanimation_p.h"
+#include "qchart_p.h"
+#include "qboxset.h"
+#include "qboxset_p.h"
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+/*!
+ \class QBoxPlotSeries
+ \brief Series for creating box-and-whiskers chart
+ \mainclass
+
+ QBoxPlotSeries represents a series of data shown as box-and-whisker bars. The purpose of this class is to act as
+ a container for single box-and-whisker items. Each item is drawn to own slot. If chart includes multiple instances of
+ QBoxPlotSeries then box-and-whiskers items with the same index are drawn to same slot.
+
+ See the \l {Box and Whiskers Example} {box-and-whiskers chart example} to learn how to create a box-and-whiskers chart.
+ \image examples_boxplotchart.png
+
+ \sa QBoxSet
+*/
+
+/*!
+ \qmlclass BoxPlotSeries QBoxPlotSeries
+ \inherits QAbstractSeries
+
+ BoxPlotSeries represents a series of data shown as box-and-whisker bars. The purpose of this class is to act as
+ a container for single box-and-whisker items. Each item is drawn to own slot. If chart includes multiple instances of
+ BoxPlotSeries then box-and-whiskers items with the same index are drawn to same slot.
+
+ The following QML shows how to create a simple box-and-whiskers chart:
+ \code
+ import QtQuick 1.0
+ import QtCommercial.Chart 1.1
+
+ ChartView {
+ title: "Box Plot series"
+ width: 400
+ height: 300
+ theme: ChartView.ChartThemeBrownSand
+ legend.alignment: Qt.AlignBottom
+
+ BoxPlotSeries {
+ id: plotSeries
+ name: "Income"
+ BoxSet { label: "Jan"; values: [3, 4, 5.1, 6.2, 8.5] }
+ BoxSet { label: "Feb"; values: [5, 6, 7.5, 8.6, 11.8] }
+ BoxSet { label: "Mar"; values: [3.2, 5, 5.7, 8, 9.2] }
+ BoxSet { label: "Apr"; values: [3.8, 5, 6.4, 7, 8] }
+ BoxSet { label: "May"; values: [4, 5, 5.2, 6, 7] }
+ }
+ }
+ \endcode
+
+ \beginfloatleft
+ \image examples_qmlboxplot.png
+ \endfloat
+ \clearfloat
+*/
+
+/*!
+ \fn QBoxPlotSeries::boxsetsAdded(QList<QBoxSet *> sets)
+ \brief Signal is emitted when a new \a sets of box-and-whiskers data is added to the series.
+*/
+
+/*!
+ \fn QBoxPlotSeries::boxsetsRemoved(QList<QBoxSet *> sets)
+ \brief Signal is emitted when \a sets of box-and-whiskers data is removed from the series.
+*/
+
+/*!
+ \fn QBoxPlotSeries::clicked(QBoxSet *boxset)
+ \brief Signal is emitted when the user clicks the \a boxset on the chart.
+*/
+
+/*!
+ \fn QBoxPlotSeries::hovered(bool status, QBoxSet *boxset)
+ \brief Signal is emitted when there is change in hover \a status over \a boxset.
+*/
+
+/*!
+ \fn QBoxPlotSeries::countChanged()
+ \brief Signal is emitted when there is change in count of box-and-whiskers items in the series.
+*/
+/*!
+ \fn virtual SeriesType QBoxPlotSeries::type() const
+ \brief Returns type of series.
+ \sa QAbstractSeries, SeriesType
+*/
+/*!
+ \qmlmethod BoxPlotSeries::append(const QString label, QVariantList values)
+ Appends a new box-and-whiskers set with \a label and \a values to the series.
+ */
+/*!
+ \qmlmethod BoxPlotSeries::append(BoxSet *box)
+ Appends the \a box to the series.
+*/
+/*!
+ \qmlmethod BoxPlotSeries::insert(int index, const QString label, QVariantList values)
+ Inserts a new box-and-whiskers set with \a label and \a values at the \a index position.
+*/
+/*!
+ \qmlmethod BoxPlotSeries::remove(QBoxSet *boxset)
+ Removes the \a boxset from the series.
+*/
+/*!
+ \qmlmethod BoxPlotSeries::clear()
+ Removes all boxsets from the series. Deletes removed sets.
+*/
+
+/*!
+ \qmlsignal BoxPlotSeries::onClicked(BoxSet boxset);
+ Signal is emitted when the user clicks the \a boxset on the chart.
+*/
+/*!
+ \qmlsignal BoxPlotSeries::onHovered(bool status, BoxSet boxset);
+ Signal is emitted when there is change in hover \a status over \a boxset.
+*/
+/*!
+ \qmlsignal BoxPlotSeries::onCountChanged();
+ Signal is emitted when there is change in count of box-and-whiskers items in the series.
+*/
+/*!
+ \qmlsignal BoxPlotSeries::onBoxsetsAdded()
+ Signal is emitted when new box-and-whiskers sets are added to the series.
+ */
+/*!
+ \qmlsignal BoxPlotSeries::boxsetsRemoved()
+ Signal is emitted when new box-and-whiskers sets are removed from the series.
+ */
+
+/*!
+ Constructs empty QBoxPlotSeries.
+ QBoxPlotSeries is QObject which is a child of a \a parent.
+*/
+QBoxPlotSeries::QBoxPlotSeries(QObject *parent)
+ : QAbstractSeries(*new QBoxPlotSeriesPrivate(this), parent)
+{
+}
+
+/*!
+ Destructor. Removes series from chart.
+*/
+QBoxPlotSeries::~QBoxPlotSeries()
+{
+ Q_D(QBoxPlotSeries);
+ if (d->m_chart)
+ d->m_chart->removeSeries(this);
+}
+
+/*!
+ Adds a single box and whiskers set to series. Takes ownership of the \a set. If the set is null or is already in series, it won't be appended.
+ Returns true, if appending succeeded.
+*/
+bool QBoxPlotSeries::append(QBoxSet *set)
+{
+ Q_D(QBoxPlotSeries);
+
+ bool success = d->append(set);
+ if (success) {
+ QList<QBoxSet *> sets;
+ sets.append(set);
+ set->setParent(this);
+ emit boxsetsAdded(sets);
+ emit countChanged();
+ }
+ return success;
+}
+
+/*!
+ Removes boxset from the series. Deletes the \a set and returns true if successful.
+*/
+bool QBoxPlotSeries::remove(QBoxSet *set)
+{
+ Q_D(QBoxPlotSeries);
+ bool success = d->remove(set);
+ if (success) {
+ QList<QBoxSet *> sets;
+ sets.append(set);
+ set->setParent(0);
+ emit boxsetsRemoved(sets);
+ emit countChanged();
+ delete set;
+ set = 0;
+ }
+ return success;
+}
+
+/*!
+ Takes a single \a set from the series. Does not delete the boxset object.
+
+ NOTE: The series remains as the boxset's parent object. You must set the
+ parent object to take full ownership.
+
+ Returns true if take was successful.
+*/
+bool QBoxPlotSeries::take(QBoxSet *set)
+{
+ Q_D(QBoxPlotSeries);
+
+ bool success = d->remove(set);
+ if (success) {
+ QList<QBoxSet *> sets;
+ sets.append(set);
+ emit boxsetsRemoved(sets);
+ emit countChanged();
+ }
+ return success;
+}
+
+/*!
+ Adds a list of boxsets to series. Takes ownership of the \a sets.
+ Returns true, if all sets were appended successfully. If any of the sets is null or is already appended to series,
+ nothing is appended and function returns false. If any of the sets is in list more than once, nothing is appended
+ and function returns false.
+*/
+bool QBoxPlotSeries::append(QList<QBoxSet *> sets)
+{
+ Q_D(QBoxPlotSeries);
+ bool success = d->append(sets);
+ if (success) {
+ emit boxsetsAdded(sets);
+ emit countChanged();
+ }
+ return success;
+}
+
+/*!
+ Insert a box-and-whiskers set to the series at \a index postion. Takes ownership of the \a set. If the set is null or
+ is already in series, it won't be appended. Returns true, if inserting succeeded.
+
+*/
+bool QBoxPlotSeries::insert(int index, QBoxSet *set)
+{
+ Q_D(QBoxPlotSeries);
+ bool success = d->insert(index, set);
+ if (success) {
+ QList<QBoxSet *> sets;
+ sets.append(set);
+ emit boxsetsAdded(sets);
+ emit countChanged();
+ }
+ return success;
+}
+
+/*!
+ Removes all boxsets from the series. Deletes removed sets.
+*/
+void QBoxPlotSeries::clear()
+{
+ Q_D(QBoxPlotSeries);
+ QList<QBoxSet *> sets = boxSets();
+ bool success = d->remove(sets);
+ if (success) {
+ emit boxsetsRemoved(sets);
+ emit countChanged();
+ foreach (QBoxSet *set, sets)
+ delete set;
+ }
+}
+
+/*!
+ Returns number of sets in series.
+*/
+int QBoxPlotSeries::count() const
+{
+ Q_D(const QBoxPlotSeries);
+ return d->m_boxSets.count();
+}
+
+/*!
+ Returns a list of sets in series. Keeps ownership of sets.
+ */
+QList<QBoxSet *> QBoxPlotSeries::boxSets() const
+{
+ Q_D(const QBoxPlotSeries);
+ return d->m_boxSets;
+}
+
+/*
+ Returns QAbstractSeries::SeriesTypeBoxPlot.
+*/
+QAbstractSeries::SeriesType QBoxPlotSeries::type() const
+{
+ return QAbstractSeries::SeriesTypeBoxPlot;
+}
+
+/*!
+ Sets brush for the series. Box-and-whiskers items are drawn using \a brush
+*/
+void QBoxPlotSeries::setBrush(const QBrush &brush)
+{
+ Q_D(QBoxPlotSeries);
+
+ if (d->m_brush != brush) {
+ d->m_brush = brush;
+ emit d->updated();
+ }
+}
+
+/*!
+ Returns brush of the series.
+*/
+QBrush QBoxPlotSeries::brush() const
+{
+ Q_D(const QBoxPlotSeries);
+
+ return d->m_brush;
+}
+
+/*!
+ Sets pen for the series. Box-and-whiskers items are drawn using \a pen
+*/
+void QBoxPlotSeries::setPen(const QPen &pen)
+{
+ Q_D(QBoxPlotSeries);
+
+ if (d->m_pen != pen) {
+ d->m_pen = pen;
+ emit d->updated();
+ }
+}
+
+/*!
+ Returns the pen of this series.
+*/
+QPen QBoxPlotSeries::pen() const
+{
+ Q_D(const QBoxPlotSeries);
+
+ return d->m_pen;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QBoxPlotSeriesPrivate::QBoxPlotSeriesPrivate(QBoxPlotSeries *q)
+ : QAbstractSeriesPrivate(q),
+ m_pen(QChartPrivate::defaultPen()),
+ m_brush(QChartPrivate::defaultBrush())
+{
+}
+
+QBoxPlotSeriesPrivate::~QBoxPlotSeriesPrivate()
+{
+ disconnect(this, 0, 0, 0);
+}
+
+void QBoxPlotSeriesPrivate::initializeDomain()
+{
+ qreal minX(domain()->minX());
+ qreal minY(domain()->minY());
+ qreal maxX(domain()->maxX());
+ qreal maxY(domain()->maxY());
+
+ qreal x = m_boxSets.count();
+ minX = qMin(minX, - (qreal)0.5);
+ minY = qMin(minY, min());
+ maxX = qMax(maxX, x - (qreal)0.5);
+ maxY = qMax(maxY, max());
+
+ domain()->setRange(minX, maxX, minY, maxY);
+}
+
+void QBoxPlotSeriesPrivate::initializeAxes()
+{
+ foreach (QAbstractAxis* axis, m_axes) {
+ if (axis->type() == QAbstractAxis::AxisTypeBarCategory) {
+ if (axis->orientation() == Qt::Horizontal)
+ populateCategories(qobject_cast<QBarCategoryAxis *>(axis));
+ }
+ }
+}
+
+QAbstractAxis::AxisType QBoxPlotSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
+{
+ if (orientation == Qt::Horizontal)
+ return QAbstractAxis::AxisTypeBarCategory;
+
+ return QAbstractAxis::AxisTypeValue;
+}
+
+QAbstractAxis* QBoxPlotSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const
+{
+ Q_UNUSED(orientation);
+
+ return 0;
+}
+
+void QBoxPlotSeriesPrivate::populateCategories(QBarCategoryAxis *axis)
+{
+ QStringList categories;
+ if (axis->categories().isEmpty()) {
+ for (int i(1); i < m_boxSets.count() + 1; i++) {
+ QBoxSet *set = m_boxSets.at(i - 1);
+ if (set->label().isEmpty())
+ categories << QString::number(i);
+ else
+ categories << set->label();
+ }
+ axis->append(categories);
+ }
+}
+
+void QBoxPlotSeriesPrivate::initializeGraphics(QGraphicsItem *parent)
+{
+ Q_Q(QBoxPlotSeries);
+
+ BoxPlotChartItem *boxPlot = new BoxPlotChartItem(q, parent);
+ m_item.reset(boxPlot);
+ QAbstractSeriesPrivate::initializeGraphics(parent);
+
+ if (m_chart) {
+ connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), this, SLOT(handleSeriesChange(QAbstractSeries*)) );
+ connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)), this, SLOT(handleSeriesRemove(QAbstractSeries*)) );
+
+ QList<QAbstractSeries *> serieses = m_chart->series();
+
+ // Tries to find this series from the Chart's list of series and deduce the index
+ int index = 0;
+ foreach (QAbstractSeries *s, serieses) {
+ if (s->type() == QAbstractSeries::SeriesTypeBoxPlot) {
+ if (q == static_cast<QBoxPlotSeries *>(s)) {
+ boxPlot->m_seriesIndex = index;
+ m_index = index;
+ }
+ index++;
+ }
+ }
+ boxPlot->m_seriesCount = index;
+ }
+
+ // Make BoxPlotChartItem to instantiate box & whisker items
+ boxPlot->handleDataStructureChanged();
+}
+
+void QBoxPlotSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
+{
+ Q_Q(QBoxPlotSeries);
+
+ const QList<QGradient> gradients = theme->seriesGradients();
+
+ if (forced || QChartPrivate::defaultBrush() == m_brush) {
+ QColor brushColor = ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0.5);
+ q->setBrush(brushColor);
+ }
+
+ if (forced || QChartPrivate::defaultPen() == m_pen) {
+ QPen pen = theme->outlinePen();
+ pen.setCosmetic(true);
+ q->setPen(pen);
+ }
+}
+
+void QBoxPlotSeriesPrivate::initializeAnimations(QChart::AnimationOptions options)
+{
+ BoxPlotChartItem *item = static_cast<BoxPlotChartItem *>(m_item.data());
+ Q_ASSERT(item);
+ if (options.testFlag(QChart::SeriesAnimations))
+ item->setAnimation(new BoxPlotAnimation(item));
+ else
+ item->setAnimation((BoxPlotAnimation *)0);
+ QAbstractSeriesPrivate::initializeAnimations(options);
+}
+
+QList<QLegendMarker*> QBoxPlotSeriesPrivate::createLegendMarkers(QLegend *legend)
+{
+ Q_Q(QBoxPlotSeries);
+ QList<QLegendMarker *> list;
+ return list << new QBoxPlotLegendMarker(q, legend);
+}
+
+void QBoxPlotSeriesPrivate::handleSeriesRemove(QAbstractSeries *series)
+{
+ Q_Q(QBoxPlotSeries);
+
+ QBoxPlotSeries *removedSeries = static_cast<QBoxPlotSeries *>(series);
+ QObject::disconnect(m_chart->d_ptr->m_dataset, 0, removedSeries->d_func(), 0);
+
+ // Test if series removed is me, then don't do anything
+ if (q != removedSeries) {
+ BoxPlotChartItem *item = static_cast<BoxPlotChartItem *>(m_item.data());
+ if (item) {
+ item->m_seriesCount = item->m_seriesCount - 1;
+ if (removedSeries->d_func()->m_index < m_index) {
+ m_index--;
+ item->m_seriesIndex = m_index;
+ }
+
+ item->handleDataStructureChanged();
+ }
+ }
+}
+
+void QBoxPlotSeriesPrivate::handleSeriesChange(QAbstractSeries *series)
+{
+ Q_UNUSED(series);
+
+ Q_Q(QBoxPlotSeries);
+
+ BoxPlotChartItem *boxPlot = static_cast<BoxPlotChartItem *>(m_item.data());
+
+ if (m_chart) {
+ QList<QAbstractSeries *> serieses = m_chart->series();
+
+ // Tries to find this series from the Chart's list of series and deduce the index
+ int index = 0;
+ foreach (QAbstractSeries *s, serieses) {
+ if (s->type() == QAbstractSeries::SeriesTypeBoxPlot) {
+ if (q == static_cast<QBoxPlotSeries *>(s)) {
+ boxPlot->m_seriesIndex = index;
+ m_index = index;
+ }
+ index++;
+ }
+ }
+ boxPlot->m_seriesCount = index;
+ }
+
+ boxPlot->handleDataStructureChanged();
+}
+
+bool QBoxPlotSeriesPrivate::append(QBoxSet *set)
+{
+ if ((m_boxSets.contains(set)) || (set == 0))
+ return false; // Fail if set is already in list or set is null.
+
+ m_boxSets.append(set);
+ QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
+ QObject::connect(set->d_ptr.data(), SIGNAL(updatedBox()), this, SIGNAL(updatedBoxes()));
+ QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBox()), this, SIGNAL(restructuredBoxes()));
+
+ emit restructuredBoxes(); // this notifies boxplotchartitem
+ return true;
+}
+
+bool QBoxPlotSeriesPrivate::remove(QBoxSet *set)
+{
+ if (!m_boxSets.contains(set))
+ return false; // Fail if set is not in list
+
+ m_boxSets.removeOne(set);
+ QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
+ QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedBox()), this, SIGNAL(updatedBoxes()));
+ QObject::disconnect(set->d_ptr.data(), SIGNAL(restructuredBox()), this, SIGNAL(restructuredBoxes()));
+
+ emit restructuredBoxes(); // this notifies boxplotchartitem
+ return true;
+}
+
+bool QBoxPlotSeriesPrivate::append(QList<QBoxSet *> sets)
+{
+ foreach (QBoxSet *set, sets) {
+ if ((set == 0) || (m_boxSets.contains(set)))
+ return false; // Fail if any of the sets is null or is already appended.
+ if (sets.count(set) != 1)
+ return false; // Also fail if same set is more than once in given list.
+ }
+
+ foreach (QBoxSet *set, sets) {
+ m_boxSets.append(set);
+ QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
+ QObject::connect(set->d_ptr.data(), SIGNAL(updatedBox()), this, SIGNAL(updatedBoxes()));
+ QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBox()), this, SIGNAL(restructuredBoxes()));
+ }
+
+ emit restructuredBoxes(); // this notifies boxplotchartitem
+ return true;
+}
+
+bool QBoxPlotSeriesPrivate::remove(QList<QBoxSet *> sets)
+{
+ if (sets.count() == 0)
+ return false;
+
+ foreach (QBoxSet *set, sets) {
+ if ((set == 0) || (!m_boxSets.contains(set)))
+ return false; // Fail if any of the sets is null or is not in series
+ if (sets.count(set) != 1)
+ return false; // Also fail if same set is more than once in given list.
+ }
+
+ foreach (QBoxSet *set, sets) {
+ m_boxSets.removeOne(set);
+ QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
+ QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedBox()), this, SIGNAL(updatedBoxes()));
+ QObject::disconnect(set->d_ptr.data(), SIGNAL(restructuredBox()), this, SIGNAL(restructuredBoxes()));
+ }
+
+ emit restructuredBoxes(); // this notifies boxplotchartitem
+
+ return true;
+}
+
+bool QBoxPlotSeriesPrivate::insert(int index, QBoxSet *set)
+{
+ if ((m_boxSets.contains(set)) || (set == 0))
+ return false; // Fail if set is already in list or set is null.
+
+ m_boxSets.insert(index, set);
+ QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
+ QObject::connect(set->d_ptr.data(), SIGNAL(updatedBox()), this, SIGNAL(updatedBoxes()));
+ QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBox()), this, SIGNAL(restructuredBoxes()));
+
+ emit restructuredBoxes(); // this notifies boxplotchartitem
+ return true;
+}
+
+QBoxSet *QBoxPlotSeriesPrivate::boxSetAt(int index)
+{
+ return m_boxSets.at(index);
+}
+
+qreal QBoxPlotSeriesPrivate::min()
+{
+ if (m_boxSets.count() <= 0)
+ return 0;
+
+ qreal min = m_boxSets.at(0)->at(0);
+
+ foreach (QBoxSet *set, m_boxSets) {
+ for (int i = 0; i < 5; i++) {
+ if (set->at(i) < min)
+ min = set->at(i);
+ }
+ }
+
+ return min;
+}
+
+qreal QBoxPlotSeriesPrivate::max()
+{
+ if (m_boxSets.count() <= 0)
+ return 0;
+
+ qreal max = m_boxSets.at(0)->at(0);
+
+ foreach (QBoxSet *set, m_boxSets) {
+ for (int i = 0; i < 5; i++) {
+ if (set->at(i) > max)
+ max = set->at(i);
+ }
+ }
+
+ return max;
+}
+
+#include "moc_qboxplotseries.cpp"
+#include "moc_qboxplotseries_p.cpp"
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
diff --git a/src/boxplotchart/qboxplotseries.h b/src/boxplotchart/qboxplotseries.h
new file mode 100644
index 00000000..ae4930ef
--- /dev/null
+++ b/src/boxplotchart/qboxplotseries.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** 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 QBOXPLOTSERIES_H
+#define QBOXPLOTSERIES_H
+
+#include <qchartglobal.h>
+#include <qboxset.h>
+#include <qabstractseries.h>
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+class QBoxPlotSeriesPrivate;
+
+class QTCOMMERCIALCHART_EXPORT QBoxPlotSeries : public QAbstractSeries
+{
+ Q_OBJECT
+public:
+ explicit QBoxPlotSeries(QObject *parent = 0);
+ ~QBoxPlotSeries();
+
+ bool append(QBoxSet *box);
+ bool remove(QBoxSet *box);
+ bool take(QBoxSet *box);
+ bool append(QList<QBoxSet *> boxes);
+ bool insert(int index, QBoxSet *box);
+ int count() const;
+ QList<QBoxSet *> boxSets() const;
+ void clear();
+
+ QAbstractSeries::SeriesType type() const;
+
+ void setBrush(const QBrush &brush);
+ QBrush brush() const;
+ void setPen(const QPen &pen);
+ QPen pen() const;
+
+Q_SIGNALS:
+ void clicked(QBoxSet *boxset);
+ void hovered(bool status, QBoxSet *boxset);
+ void countChanged();
+
+ void boxsetsAdded(QList<QBoxSet *> sets);
+ void boxsetsRemoved(QList<QBoxSet *> sets);
+
+private:
+ Q_DECLARE_PRIVATE(QBoxPlotSeries)
+ Q_DISABLE_COPY(QBoxPlotSeries)
+ friend class BoxPlotChartItem;
+ friend class QBoxPlotLegendMarkerPrivate;
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // QBOXPLOTSERIES_H
diff --git a/src/boxplotchart/qboxplotseries_p.h b/src/boxplotchart/qboxplotseries_p.h
new file mode 100644
index 00000000..fdd8963a
--- /dev/null
+++ b/src/boxplotchart/qboxplotseries_p.h
@@ -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$
+**
+****************************************************************************/
+
+// 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 QBOXPLOTSERIES_P_H
+#define QBOXPLOTSERIES_P_H
+
+#include "qboxplotseries.h"
+#include "qabstractbarseries_p.h"
+#include "abstractdomain_p.h"
+#include "qbarset.h"
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+class QBoxPlotSeriesPrivate : public QAbstractSeriesPrivate
+{
+ Q_OBJECT
+
+public:
+ QBoxPlotSeriesPrivate(QBoxPlotSeries *q);
+ ~QBoxPlotSeriesPrivate();
+
+ void initializeGraphics(QGraphicsItem *parent);
+ void initializeDomain();
+ void initializeAxes();
+ void initializeAnimations(QChart::AnimationOptions options);
+ void initializeTheme(int index, ChartTheme *theme, bool forced = false);
+
+ QList<QLegendMarker*> createLegendMarkers(QLegend *legend);
+
+ virtual QAbstractAxis::AxisType defaultAxisType(Qt::Orientation orientation) const;
+ QAbstractAxis *createDefaultAxis(Qt::Orientation orientation) const;
+
+ bool append(QBoxSet *set);
+ bool remove(QBoxSet *set);
+ bool append(QList<QBoxSet *> sets);
+ bool remove(QList<QBoxSet *> sets);
+ bool insert(int index, QBoxSet *set);
+ QBoxSet *boxSetAt(int index);
+
+ qreal max();
+ qreal min();
+
+private:
+ void populateCategories(QBarCategoryAxis *axis);
+
+Q_SIGNALS:
+ void updated();
+ void clicked(int index, QBoxSet *barset);
+ void updatedBoxes();
+ void updatedLayout();
+ void restructuredBoxes();
+
+private slots:
+ void handleSeriesChange(QAbstractSeries *series);
+ void handleSeriesRemove(QAbstractSeries *series);
+
+protected:
+ QList<QBoxSet *> m_boxSets;
+ QPen m_pen;
+ QBrush m_brush;
+ int m_index;
+
+private:
+ Q_DECLARE_PUBLIC(QBoxPlotSeries)
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif
diff --git a/src/boxplotchart/qboxset.cpp b/src/boxplotchart/qboxset.cpp
new file mode 100644
index 00000000..514271e0
--- /dev/null
+++ b/src/boxplotchart/qboxset.cpp
@@ -0,0 +1,400 @@
+/****************************************************************************
+**
+** 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 "qboxset.h"
+#include "qboxset_p.h"
+#include "charthelpers_p.h"
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+/*!
+ \class QBoxSet
+ \brief Building block for box-and-whiskers chart
+
+ QBoxSet represents one box-and-whiskers item. It takes five values to create a graphical representation
+ of range and three medians. There are two ways to give the values. The first one is with constructor
+ or stream operator (<<). The values have to be given in the following order: lower extreme,
+ lower quartile, median, upper quartile and upper extreme. The Second method is to create an empty QBoxSet instance and
+ give the values using setValue method.
+
+ \mainclass
+
+ \sa QBoxPlotSeries
+*/
+/*!
+ \qmlclass BoxSet QBoxSet
+
+ BoxSet represents one box-and-whiskers item. It takes five values to create a graphical representation
+ of range and three medians. There are two ways to give the values. The first one is with constructor
+ or with append method. In these the values have to be given in the following order: lower extreme, lower quartile, median,
+ upper quartile and upper extre. The second method is to create an empty QBoxSet instance and give the values using
+ value specific methods.
+ \sa BoxPlotSeries
+*/
+/*!
+ \enum QBoxSet::ValuePositions
+
+ \value LowerExtreme
+ \value LowerQuartile
+ \value Median
+ \value UpperQuartile
+ \value UpperExtreme
+*/
+
+/*!
+ \qmlproperty string BoxSet::label
+ Defines the label of the boxSet.
+*/
+/*!
+ \qmlproperty int BoxSet::count
+ The count of values on the box-and-whiskers set
+*/
+
+/*!
+ \property QBoxSet::pen
+ \brief Defines the pen used by the box-and-whiskers set.
+*/
+
+/*!
+ \property QBoxSet::brush
+ \brief Defines the brush used by the box-and-whiskers set.
+*/
+
+/*!
+ \qmlmethod void BoxSet::setValue(int index, qreal value)
+ Sets a new \a value on the \a index position.
+*/
+/*!
+ \fn void QBoxSet::clicked()
+ The signal is emitted if the user clicks with a mouse on top of box-and-whisker item.
+*/
+/*!
+ \qmlsignal BoxSet::onClicked()
+ This signal is emitted when the user clicks with a mouse on top of box-and-whisker item.
+*/
+
+/*!
+ \fn void QBoxSet::hovered(bool status)
+
+ The signal is emitted if mouse is hovered on top of box-and-whisker item.
+ Parameter \a status is true, if mouse entered on top of item, false if mouse left from top of item.
+*/
+/*!
+ \qmlsignal BoxSet::onHovered(bool status)
+
+ The signal is emitted if mouse is hovered on top of box-and-whisker item.
+ Parameter \a status is true, if mouse entered on top of item, false if mouse left from top of item.
+*/
+
+/*!
+ \fn void QBoxSet::penChanged()
+ This signal is emitted when the pen of the box-and-whisker item has changed.
+ \sa pen
+*/
+/*!
+ \qmlsignal BoxSet::onPenChanged()
+ This signal is emitted when the pen of the box-and-whisker item has changed.
+*/
+/*!
+ \fn void QBoxSet::brushChanged()
+ This signal is emitted when the brush of the box-and-whisker item has changed.
+ \sa brush
+*/
+/*!
+ \qmlsignal BoxSet::onBrushChanged()
+ This signal is emitted when the brush of the box-and-whisker item has changed.
+*/
+
+/*!
+ \fn void QBoxSet::colorChanged(QColor)
+ This signal is emitted when the fill (brush) color of the box-and-whisker item has changed to \a color.
+*/
+/*!
+ \qmlsignal BoxSet::onColorChanged(QColor color)
+ This signal is emitted when the fill (brush) color of the box-and-whisker item has changed to \a color.
+*/
+
+/*!
+ \fn void QBoxSet::valuesChanged()
+ This signal is emitted when multiple values have been changed on the box-and-whisker item.
+ \sa append()
+*/
+/*!
+ \qmlsignal BoxSet::onChangedValues()
+ This signal is emitted when multiple values have been changed on the box-and-whisker item.
+*/
+
+/*!
+ \fn void QBoxSet::valueChanged(int index)
+ This signal is emitted values the value in the box-and-whisker item has been modified.
+ Parameter \a index indicates the position of the modified value.
+ \sa at()
+*/
+/*!
+ \qmlsignal BoxSet::onChangedValue(int index)
+ This signal is emitted values the value in the box-and-whisker item has been modified.
+ Parameter \a index indicates the position of the modified value.
+*/
+
+/*!
+ \fn void QBoxSet::cleared()
+ This signal is emitted when all the values on the set are cleared to 0.
+*/
+/*!
+ \qmlsignal BoxSet::onCleared()
+ This signal is emitted when all the values on the set are cleared to 0.
+*/
+
+
+/*!
+ Constructs QBoxSet with optional \a label and parent of \a parent
+*/
+QBoxSet::QBoxSet(const QString label, QObject *parent)
+ : QObject(parent),
+ d_ptr(new QBoxSetPrivate(label, this))
+{
+}
+
+/*!
+ Constructs QBoxSet with given ordered values. \a le for lower extreme, \a lq for lower quartile, \a m for median,
+ \a uq for upper quartile and \a ue for upper quartile. \a label and \a parent are optional.
+ */
+QBoxSet::QBoxSet(const qreal le, const qreal lq, const qreal m, const qreal uq, const qreal ue, const QString label, QObject *parent)
+ : QObject(parent),
+ d_ptr(new QBoxSetPrivate(label, this))
+{
+ d_ptr->append(le);
+ d_ptr->append(lq);
+ d_ptr->append(m);
+ d_ptr->append(uq);
+ d_ptr->append(ue);
+}
+
+/*!
+ Destroys the boxset
+*/
+QBoxSet::~QBoxSet()
+{
+}
+
+/*!
+ Appends new value \a value to the end of set.
+*/
+void QBoxSet::append(const qreal value)
+{
+ if (d_ptr->append(value))
+ emit valueChanged(d_ptr->m_appendCount - 1);
+}
+
+/*!
+ Appends a list of reals to set. Works like append with single real value. The \a values in list
+ are appended to end of boxset.
+ \sa append()
+*/
+void QBoxSet::append(const QList<qreal> &values)
+{
+ if (d_ptr->append(values))
+ emit valuesChanged();
+}
+
+/*!
+ Sets new \a label for set.
+*/
+void QBoxSet::setLabel(const QString label)
+{
+ d_ptr->m_label = label;
+}
+
+/*!
+ Returns label of the set.
+*/
+QString QBoxSet::label() const
+{
+ return d_ptr->m_label;
+}
+
+/*!
+ Convenience operator. Same as append, with real \a value.
+ \sa append()
+*/
+QBoxSet &QBoxSet::operator << (const qreal &value)
+{
+ append(value);
+ return *this;
+}
+
+/*!
+ Sets a new \a value on the \a index position. For \a index ValuePositions can be used.
+*/
+void QBoxSet::setValue(const int index, const qreal value)
+{
+ d_ptr->setValue(index, value);
+ emit valueChanged(index);
+}
+
+/*!
+ Sets all values on the set to 0.
+ */
+void QBoxSet::clear()
+{
+ d_ptr->clear();
+ emit cleared();
+}
+
+/*!
+ Returns value of set indexed by \a index. For \a index ValuePositions can be used.
+ If the index is out of bounds 0.0 is returned.
+*/
+qreal QBoxSet::at(const int index) const
+{
+ if (index < 0 || index >= 5)
+ return 0;
+ return d_ptr->m_values[index];
+}
+
+/*!
+ Returns value of set indexed by \a index. For \a index ValuePositions can be used.
+ If the index is out of bounds 0.0 is returned.
+*/
+qreal QBoxSet::operator [](const int index) const
+{
+ return at(index);
+}
+
+/*!
+ Returns count of values appended to the set.
+*/
+int QBoxSet::count() const
+{
+ return d_ptr->m_appendCount;
+}
+
+/*!
+ Sets pen for set. Boxes of this set are drawn using \a pen
+*/
+void QBoxSet::setPen(const QPen &pen)
+{
+ if (d_ptr->m_pen != pen) {
+ d_ptr->m_pen = pen;
+ emit d_ptr->updatedBox();
+ emit penChanged();
+ }
+}
+
+/*!
+ Returns pen of the set.
+*/
+QPen QBoxSet::pen() const
+{
+ return d_ptr->m_pen;
+}
+
+/*!
+ Sets brush for the set. Boxes of this set are drawn using \a brush
+*/
+void QBoxSet::setBrush(const QBrush &brush)
+{
+ if (d_ptr->m_brush != brush) {
+ d_ptr->m_brush = brush;
+ emit d_ptr->updatedBox();
+ emit brushChanged();
+ }
+}
+
+/*!
+ Returns brush of the set.
+*/
+QBrush QBoxSet::brush() const
+{
+ return d_ptr->m_brush;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QBoxSetPrivate::QBoxSetPrivate(const QString label, QBoxSet *parent) : QObject(parent),
+ q_ptr(parent),
+ m_label(label),
+ m_valuesCount(5),
+ m_appendCount(0),
+ m_pen(QPen(Qt::NoPen)),
+ m_brush(QBrush(Qt::NoBrush))
+{
+ m_values = new qreal[m_valuesCount];
+}
+
+QBoxSetPrivate::~QBoxSetPrivate()
+{
+}
+
+bool QBoxSetPrivate::append(qreal value)
+{
+ if (isValidValue(value) && m_appendCount < m_valuesCount) {
+ m_values[m_appendCount++] = value;
+ emit restructuredBox();
+
+ return true;
+ }
+ return false;
+}
+
+bool QBoxSetPrivate::append(QList<qreal> values)
+{
+ bool success = false;
+
+ for (int i = 0; i < values.count(); i++) {
+ if (isValidValue(values.at(i)) && m_appendCount < m_valuesCount) {
+ success = true;
+ m_values[m_appendCount++] = values.at(i);
+ }
+ }
+
+ if (success)
+ emit restructuredBox();
+
+ return success;
+}
+
+void QBoxSetPrivate::clear()
+{
+ m_appendCount = 0;
+ for (int i = 0; i < m_valuesCount; i++)
+ m_values[i] = 0.0;
+ emit restructuredBox();
+}
+
+void QBoxSetPrivate::setValue(const int index, const qreal value)
+{
+ if (index < m_valuesCount) {
+ m_values[index] = value;
+ emit updatedLayout();
+ }
+}
+
+qreal QBoxSetPrivate::value(const int index)
+{
+ if (index < 0 || index >= m_valuesCount)
+ return 0;
+ return m_values[index];
+}
+
+#include "moc_qboxset.cpp"
+#include "moc_qboxset_p.cpp"
+
+QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/boxplotchart/qboxset.h b/src/boxplotchart/qboxset.h
new file mode 100644
index 00000000..a949e18b
--- /dev/null
+++ b/src/boxplotchart/qboxset.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** 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 QBOXSET_H
+#define QBOXSET_H
+
+#include <qchartglobal.h>
+#include <QPen>
+#include <QBrush>
+#include <QFont>
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+class QBoxSetPrivate;
+
+class QTCOMMERCIALCHART_EXPORT QBoxSet : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QPen pen READ pen WRITE setPen NOTIFY penChanged)
+ Q_PROPERTY(QBrush brush READ brush WRITE setBrush NOTIFY brushChanged)
+
+public:
+ enum ValuePositions {
+ LowerExtreme,
+ LowerQuartile,
+ Median,
+ UpperQuartile,
+ UpperExtreme
+ };
+
+public:
+ explicit QBoxSet(const QString label = QString(), QObject *parent = 0);
+ explicit QBoxSet(const qreal le, const qreal lq, const qreal m, const qreal uq, const qreal ue, const QString label = QString(), QObject *parent = 0);
+ virtual ~QBoxSet();
+
+ void append(const qreal value);
+ void append(const QList<qreal> &values);
+
+ void clear();
+
+ void setLabel(const QString label);
+ QString label() const;
+
+ QBoxSet &operator << (const qreal &value);
+
+ void setValue(const int index, const qreal value);
+ qreal at(const int index) const;
+ qreal operator [](const int index) const;
+ int count() const;
+
+ void setPen(const QPen &pen);
+ QPen pen() const;
+
+ void setBrush(const QBrush &brush);
+ QBrush brush() const;
+
+Q_SIGNALS:
+ void clicked();
+ void hovered(bool status);
+ void penChanged();
+ void brushChanged();
+
+ void valuesChanged();
+ void valueChanged(int index);
+ void cleared();
+
+private:
+ QScopedPointer<QBoxSetPrivate> d_ptr;
+ Q_DISABLE_COPY(QBoxSet)
+ friend class BarLegendMarker;
+ friend class BarChartItem;
+ friend class BoxPlotChartItem;
+ friend class QBoxPlotSeriesPrivate;
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // QBOXSET_H
diff --git a/src/boxplotchart/qboxset_p.h b/src/boxplotchart/qboxset_p.h
new file mode 100644
index 00000000..4891dca3
--- /dev/null
+++ b/src/boxplotchart/qboxset_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 QBOXSET_P_H
+#define QBOXSET_P_H
+
+#include "qboxset.h"
+#include <QMap>
+#include <QPen>
+#include <QBrush>
+#include <QFont>
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+class QBoxSetPrivate : public QObject
+{
+ Q_OBJECT
+
+public:
+ QBoxSetPrivate(const QString label, QBoxSet *parent);
+ ~QBoxSetPrivate();
+
+ bool append(qreal value);
+ bool append(QList<qreal> values);
+
+ int remove(const int index, const int count);
+ void clear();
+
+ void setValue(const int index, const qreal value);
+
+ qreal value(const int index);
+
+Q_SIGNALS:
+ void restructuredBox();
+ void updatedBox();
+ void updatedLayout();
+
+private:
+ const QBoxSet *q_ptr;
+ QString m_label;
+ const int m_valuesCount;
+ qreal *m_values;
+ int m_appendCount;
+ QPen m_pen;
+ QBrush m_brush;
+ QBrush m_labelBrush;
+ QFont m_labelFont;
+
+ friend class QBoxSet;
+ friend class QBoxPlotSeriesPrivate;
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // QBOXSET_P_H
diff --git a/src/boxplotchart/qvboxplotmodelmapper.cpp b/src/boxplotchart/qvboxplotmodelmapper.cpp
new file mode 100644
index 00000000..7d75a014
--- /dev/null
+++ b/src/boxplotchart/qvboxplotmodelmapper.cpp
@@ -0,0 +1,253 @@
+/****************************************************************************
+**
+** 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 "qvboxplotmodelmapper.h"
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+/*!
+ \class QVBoxPlotModelMapper
+ \brief Vertical model mapper for bar series
+ \mainclass
+
+ Model mappers allow you to use QAbstractItemModel derived models as a data source for a chart series.
+ Vertical model mapper is used to create a connection between QBoxPlotSeries and QAbstractItemModel derived model object.
+ Model mapper maintains equal size of all the QBoxSets.
+ Note: used model has to support adding/removing rows/columns and modifying the data of the cells.
+*/
+/*!
+ \qmlclass VBoxPlotModelMapper
+ \mainclass
+
+ VBoxPlotModelMapper allows you to use your own QAbstractItemModel derived model with data in columns as a data source
+ for any box-and-whiskers series. It is possible to use both QAbstractItemModel and box-and-whiskers series data API to
+ manipulate data.
+ VBoxPlotModelMapper keeps the series and the model in sync.
+
+ The following QML example would create a box-and-whiskers series with three box sets (assuming the
+ model has at least four columns). Each box set would contain data starting from row 1. The name of a set would be
+ defined by the horizontal header (of the column).
+ \code
+ BarSeries {
+ VBarModelMapper {
+ model: myCustomModel // QAbstractItemModel derived implementation
+ firstBoxSetColumn: 1
+ lastBoxSetColumn: 3
+ firstRow: 1
+ }
+ }
+ \endcode
+*/
+
+/*!
+ \property QVBoxPlotModelMapper::series
+ \brief Defines the QBoxPlotSeries object that is used by the mapper.
+
+ All the data in the series is discarded when it is set to the mapper.
+ When new series is specified the old series is disconnected (it preserves its data)
+*/
+/*!
+ \qmlproperty AbstractBarSeries VBarModelMapper::series
+ Defines the AbstractBarSeries based object that is used by the mapper. All the data in the series is discarded when it is
+ set to the mapper. When new series is specified the old series is disconnected (it preserves its data).
+*/
+
+/*!
+ \property QVBoxPlotModelMapper::model
+ \brief Defines the model that is used by the mapper.
+*/
+/*!
+ \qmlproperty SomeModel VBarModelMapper::model
+ The QAbstractItemModel based model that is used by the mapper. You need to implement the model and expose it to
+ QML as shown in \l {QML Custom Model} demo application. Note: the model has to support adding/removing rows/columns
+ and modifying the data of the cells.
+*/
+
+/*!
+ \property QVBoxPlotModelMapper::firstBoxSetColumn
+ \brief Defines which column of the model is used as the data source for the first box-and-whiskers set.
+
+ Default value is: -1 (invalid mapping)
+*/
+/*!
+ \qmlproperty int VBarModelMapper::firstBoxSetColumn
+ Defines which column of the model is used as the data source for the first box-and-whiskers set. Default value
+ is: -1 (invalid mapping).
+*/
+
+/*!
+ \property QVBoxPlotModelMapper::lastBoxSetColumn
+ \brief Defines which column of the model is used as the data source for the last box-and-whiskers set.
+
+ Default value is: -1 (invalid mapping)
+*/
+/*!
+ \qmlproperty int VBarModelMapper::lastBoxSetColumn
+ Defines which column of the model is used as the data source for the last box-and-whiskers set. Default
+ value is: -1 (invalid mapping).
+*/
+
+/*!
+ \property QVBoxPlotModelMapper::firstRow
+ \brief Defines which row of the model contains the first values of the QBoxSets in the series.
+
+ Minimal and default value is: 0
+*/
+/*!
+ \qmlproperty int VBoxPlotModelMapper::firstRow
+ Defines which row of the model contains the first values of the QBoxSets in the series.
+ The default value is 0.
+*/
+
+/*!
+ \property QVBoxPlotModelMapper::rowCount
+ \brief Defines the number of rows of the model that are mapped as the data for QBoxPlotSeries
+
+ Minimal and default value is: -1 (count limited by the number of rows in the model)
+*/
+/*!
+ \qmlproperty int VBoxModelMapper::rowCount
+ Defines the number of rows of the model that are mapped as the data for QBoxPlotSeries. The default value is
+ -1 (count limited by the number of rows in the model)
+*/
+
+/*!
+ \fn void QVBoxPlotModelMapper::seriesReplaced()
+
+ Emitted when the series to which mapper is connected to has changed.
+*/
+
+/*!
+ \fn void QVBoxPlotModelMapper::modelReplaced()
+
+ Emitted when the model to which mapper is connected to has changed.
+*/
+
+/*!
+ \fn void QVBoxPlotModelMapper::firstBoxSetColumnChanged()
+ Emitted when the firstBoxSetColumn has changed.
+*/
+
+/*!
+ \fn void QVBoxPlotModelMapper::lastBoxSetColumnChanged()
+ Emitted when the lastBoxSetColumn has changed.
+*/
+
+/*!
+ \fn void QVBoxPlotModelMapper::firstRowChanged()
+ Emitted when the firstRow has changed.
+*/
+
+/*!
+ \fn void QVBoxPlotModelMapper::rowCountChanged()
+ Emitted when the rowCount has changed.
+*/
+
+/*!
+ Constructs a mapper object which is a child of \a parent.
+*/
+QVBoxPlotModelMapper::QVBoxPlotModelMapper(QObject *parent) :
+ QBoxPlotModelMapper(parent)
+{
+ QBoxPlotModelMapper::setOrientation(Qt::Vertical);
+}
+
+QAbstractItemModel *QVBoxPlotModelMapper::model() const
+{
+ return QBoxPlotModelMapper::model();
+}
+
+void QVBoxPlotModelMapper::setModel(QAbstractItemModel *model)
+{
+ if (model != QBoxPlotModelMapper::model()) {
+ QBoxPlotModelMapper::setModel(model);
+ emit modelReplaced();
+ }
+}
+
+QBoxPlotSeries *QVBoxPlotModelMapper::series() const
+{
+ return QBoxPlotModelMapper::series();
+}
+
+void QVBoxPlotModelMapper::setSeries(QBoxPlotSeries *series)
+{
+ if (series != QBoxPlotModelMapper::series()) {
+ QBoxPlotModelMapper::setSeries(series);
+ emit seriesReplaced();
+ }
+}
+
+int QVBoxPlotModelMapper::firstBoxSetColumn() const
+{
+ return QBoxPlotModelMapper::firstBoxSetSection();
+}
+
+void QVBoxPlotModelMapper::setFirstBoxSetColumn(int firstBoxSetColumn)
+{
+ if (firstBoxSetColumn != firstBoxSetSection()) {
+ QBoxPlotModelMapper::setFirstBoxSetSection(firstBoxSetColumn);
+ emit firstBoxSetColumnChanged();
+ }
+}
+
+int QVBoxPlotModelMapper::lastBoxSetColumn() const
+{
+ return QBoxPlotModelMapper::lastBoxSetSection();
+}
+
+void QVBoxPlotModelMapper::setLastBoxSetColumn(int lastBoxSetColumn)
+{
+ if (lastBoxSetColumn != lastBoxSetSection()) {
+ QBoxPlotModelMapper::setLastBoxSetSection(lastBoxSetColumn);
+ emit lastBoxSetColumnChanged();
+ }
+}
+
+int QVBoxPlotModelMapper::firstRow() const
+{
+ return QBoxPlotModelMapper::first();
+}
+
+void QVBoxPlotModelMapper::setFirstRow(int firstRow)
+{
+ if (firstRow != first()) {
+ QBoxPlotModelMapper::setFirst(firstRow);
+ emit firstRowChanged();
+ }
+}
+
+int QVBoxPlotModelMapper::rowCount() const
+{
+ return QBoxPlotModelMapper::count();
+}
+
+void QVBoxPlotModelMapper::setRowCount(int rowCount)
+{
+ if (rowCount != count()) {
+ QBoxPlotModelMapper::setCount(rowCount);
+ emit rowCountChanged();
+ }
+}
+
+#include "moc_qvboxplotmodelmapper.cpp"
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
diff --git a/src/boxplotchart/qvboxplotmodelmapper.h b/src/boxplotchart/qvboxplotmodelmapper.h
new file mode 100644
index 00000000..062750cb
--- /dev/null
+++ b/src/boxplotchart/qvboxplotmodelmapper.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$
+**
+****************************************************************************/
+
+#ifndef QVBOXPLOTMODELMAPPER_H
+#define QVBOXPLOTMODELMAPPER_H
+
+#include <QBoxPlotModelMapper>
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+class QTCOMMERCIALCHART_EXPORT QVBoxPlotModelMapper : public QBoxPlotModelMapper
+{
+ Q_OBJECT
+ Q_PROPERTY(QBoxPlotSeries *series READ series WRITE setSeries NOTIFY seriesReplaced)
+ Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelReplaced)
+ Q_PROPERTY(int firstBoxSetColumn READ firstBoxSetColumn WRITE setFirstBoxSetColumn NOTIFY firstBoxSetColumnChanged)
+ Q_PROPERTY(int lastBoxSetColumn READ lastBoxSetColumn WRITE setLastBoxSetColumn NOTIFY lastBoxSetColumnChanged)
+ Q_PROPERTY(int firstRow READ firstRow WRITE setFirstRow NOTIFY firstRowChanged)
+ Q_PROPERTY(int rowCount READ rowCount WRITE setRowCount NOTIFY rowCountChanged)
+
+public:
+ explicit QVBoxPlotModelMapper(QObject *parent = 0);
+
+ QAbstractItemModel *model() const;
+ void setModel(QAbstractItemModel *model);
+
+ QBoxPlotSeries *series() const;
+ void setSeries(QBoxPlotSeries *series);
+
+ int firstBoxSetColumn() const;
+ void setFirstBoxSetColumn(int firstBoxSetColumn);
+
+ int lastBoxSetColumn() const;
+ void setLastBoxSetColumn(int lastBoxSetColumn);
+
+ int firstRow() const;
+ void setFirstRow(int firstRow);
+
+ int rowCount() const;
+ void setRowCount(int rowCount);
+
+Q_SIGNALS:
+ void seriesReplaced();
+ void modelReplaced();
+ void firstBoxSetColumnChanged();
+ void lastBoxSetColumnChanged();
+ void firstRowChanged();
+ void rowCountChanged();
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // QVBOXPLOTMODELMAPPER_H
diff --git a/src/chartpresenter_p.h b/src/chartpresenter_p.h
index ab13f051..dcfcf668 100644
--- a/src/chartpresenter_p.h
+++ b/src/chartpresenter_p.h
@@ -65,6 +65,7 @@ public:
BarSeriesZValue = SeriesZValue,
ScatterSeriesZValue = SeriesZValue,
PieSeriesZValue = SeriesZValue,
+ BoxPlotSeriesZValue = SeriesZValue,
LegendZValue,
TopMostZValue
};
diff --git a/src/legend/legend.pri b/src/legend/legend.pri
index 3649007f..c14cf6b0 100644
--- a/src/legend/legend.pri
+++ b/src/legend/legend.pri
@@ -10,7 +10,8 @@ SOURCES += \
$$PWD/qbarlegendmarker.cpp \
$$PWD/qxylegendmarker.cpp \
$$PWD/qarealegendmarker.cpp \
- $$PWD/legendscroller.cpp
+ $$PWD/legendscroller.cpp \
+ $$PWD/qboxplotlegendmarker.cpp
PRIVATE_HEADERS += \
$$PWD/legendscroller_p.h \
@@ -21,7 +22,8 @@ PRIVATE_HEADERS += \
$$PWD/qpielegendmarker_p.h \
$$PWD/qbarlegendmarker_p.h \
$$PWD/qxylegendmarker_p.h \
- $$PWD/qarealegendmarker_p.h
+ $$PWD/qarealegendmarker_p.h \
+ $$PWD/qboxplotlegendmarker_p.h
PUBLIC_HEADERS += \
@@ -30,4 +32,5 @@ PUBLIC_HEADERS += \
$$PWD/qpielegendmarker.h \
$$PWD/qbarlegendmarker.h \
$$PWD/qxylegendmarker.h \
- $$PWD/qarealegendmarker.h
+ $$PWD/qarealegendmarker.h \
+ $$PWD/qboxplotlegendmarker.h
diff --git a/src/legend/qboxplotlegendmarker.cpp b/src/legend/qboxplotlegendmarker.cpp
new file mode 100644
index 00000000..6b239e6a
--- /dev/null
+++ b/src/legend/qboxplotlegendmarker.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 "qboxplotlegendmarker.h"
+#include "qboxplotlegendmarker_p.h"
+#include "qboxplotseries.h"
+#include "qboxplotseries_p.h"
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+/*!
+ \class QBoxPlotLegendMarker
+ \brief QBoxPlotLegendMarker object
+ \mainclass
+
+ QBoxPlotLegendMarker is related to QBoxPlotSeries classes.
+
+ \sa QLegend QBoxPlotSeries
+*/
+
+/*!
+ \fn virtual LegendMarkerType QBoxPlotLegendMarker::type()
+ Returns QLegendMarker::LegendMarkerTypeBoxPlot
+*/
+
+/*!
+ \internal
+*/
+QBoxPlotLegendMarker::QBoxPlotLegendMarker(QBoxPlotSeries *series, QLegend *legend, QObject *parent) :
+ QLegendMarker(*new QBoxPlotLegendMarkerPrivate(this,series,legend), parent)
+{
+ d_ptr->updated();
+}
+
+/*!
+ Destructor
+*/
+QBoxPlotLegendMarker::~QBoxPlotLegendMarker()
+{
+}
+
+/*!
+ \internal
+*/
+QBoxPlotLegendMarker::QBoxPlotLegendMarker(QBoxPlotLegendMarkerPrivate &d, QObject *parent) :
+ QLegendMarker(d, parent)
+{
+}
+
+/*!
+ Returns the related series
+*/
+QBoxPlotSeries* QBoxPlotLegendMarker::series()
+{
+ Q_D(QBoxPlotLegendMarker);
+ return d->m_series;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QBoxPlotLegendMarkerPrivate::QBoxPlotLegendMarkerPrivate(QBoxPlotLegendMarker *q, QBoxPlotSeries *series, QLegend *legend) :
+ QLegendMarkerPrivate(q,legend),
+ q_ptr(q),
+ m_series(series)
+{
+ QObject::connect(m_series, SIGNAL(nameChanged()), this, SLOT(updated()));
+ QObject::connect(m_series->d_func(), SIGNAL(updated()), this, SLOT(updated()));
+}
+
+QBoxPlotLegendMarkerPrivate::~QBoxPlotLegendMarkerPrivate()
+{
+}
+
+QAbstractSeries* QBoxPlotLegendMarkerPrivate::series()
+{
+ return m_series;
+}
+
+QObject* QBoxPlotLegendMarkerPrivate::relatedObject()
+{
+ return m_series;
+}
+
+void QBoxPlotLegendMarkerPrivate::updated()
+{
+ bool labelChanged = false;
+ bool brushChanged = false;
+
+ if (!m_customLabel && (m_item->label() != m_series->name())) {
+ m_item->setLabel(m_series->name());
+ labelChanged = true;
+ }
+ if (!m_customBrush && (m_item->brush() != m_series->brush())) {
+ m_item->setBrush(m_series->brush());
+ brushChanged = true;
+ }
+ invalidateLegend();
+
+ if (labelChanged)
+ emit q_ptr->labelChanged();
+ if (brushChanged)
+ emit q_ptr->brushChanged();
+}
+
+#include "moc_qboxplotlegendmarker.cpp"
+#include "moc_qboxplotlegendmarker_p.cpp"
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
diff --git a/src/legend/qboxplotlegendmarker.h b/src/legend/qboxplotlegendmarker.h
new file mode 100644
index 00000000..69c16aff
--- /dev/null
+++ b/src/legend/qboxplotlegendmarker.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the 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 QBOXPLOTLEGENDMARKER_H
+#define QBOXPLOTLEGENDMARKER_H
+
+#include <QChartGlobal>
+#include <QLegendMarker>
+#include <QBoxPlotSeries>
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+class QBoxPlotLegendMarkerPrivate;
+
+class QTCOMMERCIALCHART_EXPORT QBoxPlotLegendMarker : public QLegendMarker
+{
+ Q_OBJECT
+
+public:
+ explicit QBoxPlotLegendMarker(QBoxPlotSeries *series, QLegend *legend, QObject *parent = 0);
+ virtual ~QBoxPlotLegendMarker();
+
+ virtual LegendMarkerType type() { return LegendMarkerTypeBoxPlot; }
+
+ // Related series
+ virtual QBoxPlotSeries* series();
+
+protected:
+ QBoxPlotLegendMarker(QBoxPlotLegendMarkerPrivate &d, QObject *parent = 0);
+
+private:
+ Q_DECLARE_PRIVATE(QBoxPlotLegendMarker)
+ Q_DISABLE_COPY(QBoxPlotLegendMarker)
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // QBOXPLOTLEGENDMARKER_H
diff --git a/src/legend/qboxplotlegendmarker_p.h b/src/legend/qboxplotlegendmarker_p.h
new file mode 100644
index 00000000..8e403cbd
--- /dev/null
+++ b/src/legend/qboxplotlegendmarker_p.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the 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 QBOXPLOTLEGENDMARKER_P_H
+#define QBOXPLOTLEGENDMARKER_P_H
+
+#include "qchartglobal.h"
+#include "qlegendmarker_p.h"
+#include "legendmarkeritem_p.h"
+#include <QBoxPlotSeries>
+
+QTCOMMERCIALCHART_BEGIN_NAMESPACE
+
+class QBoxPlotLegendMarker;
+
+class QBoxPlotLegendMarkerPrivate : public QLegendMarkerPrivate
+{
+ Q_OBJECT
+public:
+ explicit QBoxPlotLegendMarkerPrivate(QBoxPlotLegendMarker *q, QBoxPlotSeries *series, QLegend *legend);
+ virtual ~QBoxPlotLegendMarkerPrivate();
+
+ virtual QAbstractSeries *series();
+ virtual QObject *relatedObject();
+
+public Q_SLOTS:
+ virtual void updated();
+
+private:
+ QBoxPlotLegendMarker *q_ptr;
+ QBoxPlotSeries *m_series;
+
+ Q_DECLARE_PUBLIC(QBoxPlotLegendMarker)
+};
+
+QTCOMMERCIALCHART_END_NAMESPACE
+
+#endif // QBOXPLOTLEGENDMARKER_P_H
diff --git a/src/legend/qlegendmarker.cpp b/src/legend/qlegendmarker.cpp
index 24a06356..b285090e 100644
--- a/src/legend/qlegendmarker.cpp
+++ b/src/legend/qlegendmarker.cpp
@@ -53,6 +53,7 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE
\value LegendMarkerTypeBar
\value LegendMarkerTypePie
\value LegendMarkerTypeXY
+ \value LegendMarkerTypeBoxPlot
*/
/*!
diff --git a/src/legend/qlegendmarker.h b/src/legend/qlegendmarker.h
index ced43bda..f4b5de04 100644
--- a/src/legend/qlegendmarker.h
+++ b/src/legend/qlegendmarker.h
@@ -42,7 +42,8 @@ public:
LegendMarkerTypeArea,
LegendMarkerTypeBar,
LegendMarkerTypePie,
- LegendMarkerTypeXY
+ LegendMarkerTypeXY,
+ LegendMarkerTypeBoxPlot
};
Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY labelChanged)
diff --git a/src/qabstractseries.cpp b/src/qabstractseries.cpp
index 74181c33..025e9c7f 100644
--- a/src/qabstractseries.cpp
+++ b/src/qabstractseries.cpp
@@ -62,6 +62,7 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE
\value SeriesTypeHorizontalBar
\value SeriesTypeHorizontalStackedBar
\value SeriesTypeHorizontalPercentBar
+ \value SeriesTypeBoxPlot
*/
/*!
diff --git a/src/qabstractseries.h b/src/qabstractseries.h
index f6c7a240..fc651468 100644
--- a/src/qabstractseries.h
+++ b/src/qabstractseries.h
@@ -52,7 +52,8 @@ public:
SeriesTypeSpline,
SeriesTypeHorizontalBar,
SeriesTypeHorizontalStackedBar,
- SeriesTypeHorizontalPercentBar
+ SeriesTypeHorizontalPercentBar,
+ SeriesTypeBoxPlot
};
protected:
@@ -71,8 +72,8 @@ public:
QChart *chart() const;
- bool attachAxis(QAbstractAxis* axis);
- bool detachAxis(QAbstractAxis* axis);
+ bool attachAxis(QAbstractAxis *axis);
+ bool detachAxis(QAbstractAxis *axis);
QList<QAbstractAxis*> attachedAxes();
void show();
diff --git a/src/qabstractseries_p.h b/src/qabstractseries_p.h
index 37fc2b69..f3ef4437 100644
--- a/src/qabstractseries_p.h
+++ b/src/qabstractseries_p.h
@@ -48,6 +48,7 @@ class QLegendMarker;
class ChartTheme;
class ChartAnimation;
class ChartItem;
+class BoxPlotChartItem;
class QAbstractSeriesPrivate : public QObject
{
@@ -92,6 +93,7 @@ private:
friend class ChartDataSet;
friend class ChartPresenter;
friend class QLegendPrivate;
+ friend class BoxPlotChartItem;
};
QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/qchart.h b/src/qchart.h
index 1c6e8c99..77a287a1 100644
--- a/src/qchart.h
+++ b/src/qchart.h
@@ -34,6 +34,7 @@ class QAbstractSeries;
class QAbstractAxis;
class QLegend;
class QChartPrivate;
+class QBoxPlotSeries;
class QTCOMMERCIALCHART_EXPORT QChart : public QGraphicsWidget
{
@@ -161,6 +162,7 @@ protected:
friend class ChartPresenter;
friend class ChartThemeManager;
friend class QAbstractSeries;
+ friend class QBoxPlotSeriesPrivate;
Q_DISABLE_COPY(QChart)
};
diff --git a/src/src.pro b/src/src.pro
index a60a6cf2..ebe649be 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -76,6 +76,7 @@ include(splinechart/splinechart.pri)
include(themes/themes.pri)
include(xychart/xychart.pri)
include(layout/layout.pri)
+include(boxplotchart/boxplotchart.pri)
HEADERS += $$PUBLIC_HEADERS
HEADERS += $$PRIVATE_HEADERS
diff --git a/src/themes/charttheme_p.h b/src/themes/charttheme_p.h
index 9625ba9a..e5f11040 100644
--- a/src/themes/charttheme_p.h
+++ b/src/themes/charttheme_p.h
@@ -63,6 +63,7 @@ public:
QBrush labelBrush() const { return m_labelBrush; }
QPen axisLinePen() const { return m_axisLinePen; }
QPen backgroundShadesPen() const { return m_backgroundShadesPen; }
+ QPen outlinePen() const { return m_outlinePen; }
QBrush backgroundShadesBrush() const { return m_backgroundShadesBrush; }
BackgroundShadesMode backgroundShades() const { return m_backgroundShades; }
bool isBackgroundDropShadowEnabled() const { return m_backgroundDropShadowEnabled; }
@@ -79,6 +80,7 @@ protected:
QBrush m_labelBrush;
QPen m_axisLinePen;
QPen m_backgroundShadesPen;
+ QPen m_outlinePen;
QBrush m_backgroundShadesBrush;
BackgroundShadesMode m_backgroundShades;
bool m_backgroundDropShadowEnabled;
diff --git a/src/themes/chartthemebluecerulean_p.h b/src/themes/chartthemebluecerulean_p.h
index 3c9096f9..3ebaebaa 100644
--- a/src/themes/chartthemebluecerulean_p.h
+++ b/src/themes/chartthemebluecerulean_p.h
@@ -60,6 +60,8 @@ public:
m_gridLinePen = QPen(QRgb(0x84a2b0));
m_gridLinePen.setWidth(1);
m_backgroundShades = BackgroundShadesNone;
+ m_outlinePen = QPen(QRgb(0xd6d6d6));
+ m_outlinePen.setWidthF(2.0);
}
};
diff --git a/src/themes/chartthemeblueicy_p.h b/src/themes/chartthemeblueicy_p.h
index 86277d05..243bf8f7 100644
--- a/src/themes/chartthemeblueicy_p.h
+++ b/src/themes/chartthemeblueicy_p.h
@@ -62,6 +62,8 @@ public:
m_gridLinePen = QPen(QRgb(0xe2e2e2));
m_gridLinePen.setWidth(1);
m_backgroundShades = BackgroundShadesNone;
+ m_outlinePen = QPen(QColor(Qt::black));
+ m_outlinePen.setWidthF(2.0);
}
};
diff --git a/src/themes/chartthemebluencs_p.h b/src/themes/chartthemebluencs_p.h
index ac5cafb0..753348ba 100644
--- a/src/themes/chartthemebluencs_p.h
+++ b/src/themes/chartthemebluencs_p.h
@@ -61,6 +61,8 @@ public:
m_gridLinePen = QPen(QRgb(0xe2e2e2));
m_gridLinePen.setWidth(1);
m_backgroundShades = BackgroundShadesNone;
+ m_outlinePen = QPen(QColor(Qt::black));
+ m_outlinePen.setWidthF(2.0);
}
};
diff --git a/src/themes/chartthemebrownsand_p.h b/src/themes/chartthemebrownsand_p.h
index ab241694..d05bf0fc 100644
--- a/src/themes/chartthemebrownsand_p.h
+++ b/src/themes/chartthemebrownsand_p.h
@@ -61,6 +61,8 @@ public:
m_gridLinePen = QPen(QRgb(0xd4cec3));
m_gridLinePen.setWidth(1);
m_backgroundShades = BackgroundShadesNone;
+ m_outlinePen = QPen(QColor(Qt::black));
+ m_outlinePen.setWidthF(2.0);
}
};
diff --git a/src/themes/chartthemedark_p.h b/src/themes/chartthemedark_p.h
index 53a30aca..7341ed15 100644
--- a/src/themes/chartthemedark_p.h
+++ b/src/themes/chartthemedark_p.h
@@ -61,6 +61,8 @@ public:
m_gridLinePen = QPen(QRgb(0x86878c));
m_gridLinePen.setWidth(1);
m_backgroundShades = BackgroundShadesNone;
+ m_outlinePen = QPen(QRgb(0xd6d6d6));
+ m_outlinePen.setWidthF(1.0);
}
};
diff --git a/src/themes/chartthemehighcontrast_p.h b/src/themes/chartthemehighcontrast_p.h
index 972f1fb0..dcd39a77 100644
--- a/src/themes/chartthemehighcontrast_p.h
+++ b/src/themes/chartthemehighcontrast_p.h
@@ -63,6 +63,8 @@ public:
m_gridLinePen.setWidth(1);
m_backgroundShadesBrush = QBrush(QRgb(0xffeecd));
m_backgroundShades = BackgroundShadesHorizontal;
+ m_outlinePen = QPen(QColor(Qt::black));
+ m_outlinePen.setWidthF(1.0);
}
};
diff --git a/src/themes/chartthemelight_p.h b/src/themes/chartthemelight_p.h
index 251422e6..5543f719 100644
--- a/src/themes/chartthemelight_p.h
+++ b/src/themes/chartthemelight_p.h
@@ -63,6 +63,8 @@ public:
m_gridLinePen = QPen(QRgb(0xe2e2e2));
m_gridLinePen.setWidth(1);
m_backgroundShades = BackgroundShadesNone;
+ m_outlinePen = QPen(QColor(Qt::black));
+ m_outlinePen.setWidthF(2.0);
}
};
diff --git a/tests/boxplottester/boxplottester.pro b/tests/boxplottester/boxplottester.pro
new file mode 100644
index 00000000..57436c0a
--- /dev/null
+++ b/tests/boxplottester/boxplottester.pro
@@ -0,0 +1,18 @@
+!include( ../tests.pri ) {
+ error( "Couldn't find the test.pri file!" )
+}
+
+TEMPLATE = app
+
+QT += core gui opengl
+contains(QT_MAJOR_VERSION, 5) {
+ QT += widgets
+}
+
+SOURCES += main.cpp \
+ mainwidget.cpp \
+ customtablemodel.cpp
+
+HEADERS += \
+ mainwidget.h \
+ customtablemodel.h
diff --git a/tests/boxplottester/customtablemodel.cpp b/tests/boxplottester/customtablemodel.cpp
new file mode 100644
index 00000000..cc555a38
--- /dev/null
+++ b/tests/boxplottester/customtablemodel.cpp
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** 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 "customtablemodel.h"
+#include <QVector>
+#include <QTime>
+#include <QRect>
+#include <QColor>
+
+const QString categories[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Nov", "Dec"};
+
+CustomTableModel::CustomTableModel(QObject *parent) :
+ QAbstractTableModel(parent)
+{
+ m_columnCount = 6;
+ m_rowCount = 5;
+ QVector<qreal>* dataVec_Jan = new QVector<qreal>(m_rowCount);
+ dataVec_Jan->insert(0, 3.0);
+ dataVec_Jan->insert(1, 4.0);
+ dataVec_Jan->insert(2, 4.4);
+ dataVec_Jan->insert(3, 6.0);
+ dataVec_Jan->insert(4, 7.0);
+ m_data.append(dataVec_Jan);
+
+ QVector<qreal>* dataVec_Feb = new QVector<qreal>(m_rowCount);
+ dataVec_Feb->insert(0, 5.0);
+ dataVec_Feb->insert(1, 6.0);
+ dataVec_Feb->insert(2, 7.5);
+ dataVec_Feb->insert(3, 8.0);
+ dataVec_Feb->insert(4, 12.0);
+ m_data.append(dataVec_Feb);
+
+ QVector<qreal>* dataVec_Mar = new QVector<qreal>(m_rowCount);
+ dataVec_Mar->insert(0, 3.0);
+ dataVec_Mar->insert(1, 4.0);
+ dataVec_Mar->insert(2, 5.7);
+ dataVec_Mar->insert(3, 8.0);
+ dataVec_Mar->insert(4, 9.0);
+ m_data.append(dataVec_Mar);
+
+ QVector<qreal>* dataVec_Apr = new QVector<qreal>(m_rowCount);
+ dataVec_Apr->insert(0, 5.0);
+ dataVec_Apr->insert(1, 6.0);
+ dataVec_Apr->insert(2, 6.8);
+ dataVec_Apr->insert(3, 7.0);
+ dataVec_Apr->insert(4, 8.0);
+ m_data.append(dataVec_Apr);
+
+ QVector<qreal>* dataVec_May = new QVector<qreal>(m_rowCount);
+ dataVec_May->insert(0, 4.0);
+ dataVec_May->insert(1, 5.0);
+ dataVec_May->insert(2, 5.2);
+ dataVec_May->insert(3, 6.0);
+ dataVec_May->insert(4, 7.0);
+ m_data.append(dataVec_May);
+
+ QVector<qreal>* dataVec_Jun = new QVector<qreal>(m_rowCount);
+ dataVec_Jun->insert(0, 4.0);
+ dataVec_Jun->insert(1, 7.0);
+ dataVec_Jun->insert(2, 8.2);
+ dataVec_Jun->insert(3, 9.0);
+ dataVec_Jun->insert(4, 10.0);
+ m_data.append(dataVec_Jun);
+}
+
+int CustomTableModel::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent)
+ return m_rowCount;
+}
+
+int CustomTableModel::columnCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent)
+ return m_data.count();
+}
+
+QVariant CustomTableModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (role != Qt::DisplayRole)
+ return QVariant();
+
+ if (orientation == Qt::Horizontal)
+ return categories[section];
+ else
+ return QString("%1").arg(section + 1);
+}
+
+QVariant CustomTableModel::data(const QModelIndex &index, int role) const
+{
+ if (role == Qt::DisplayRole) {
+ return m_data[index.column()]->at(index.row());
+ } else if (role == Qt::EditRole) {
+ return m_data[index.column()]->at(index.row());
+ } else if (role == Qt::BackgroundRole) {
+ QRect rect;
+ foreach (rect, m_mapping)
+ if (rect.contains(index.column(), index.row()))
+ return QColor(m_mapping.key(rect));
+
+ // cell not mapped return white color
+ return QColor(Qt::white);
+ }
+ return QVariant();
+}
+
+bool CustomTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ if (index.isValid() && role == Qt::EditRole) {
+ m_data[index.column()]->replace(index.row(), value.toDouble());
+ emit dataChanged(index, index);
+ return true;
+ }
+ return false;
+}
+
+Qt::ItemFlags CustomTableModel::flags(const QModelIndex &index) const
+{
+ return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
+}
+
+void CustomTableModel::addMapping(QString color, QRect area)
+{
+ m_mapping.insertMulti(color, area);
+}
diff --git a/tests/boxplottester/customtablemodel.h b/tests/boxplottester/customtablemodel.h
new file mode 100644
index 00000000..fc738602
--- /dev/null
+++ b/tests/boxplottester/customtablemodel.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** 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 CUSTOMTABLEMODEL_H
+#define CUSTOMTABLEMODEL_H
+
+#include <QAbstractTableModel>
+#include <QHash>
+#include <QRect>
+
+class CustomTableModel : public QAbstractTableModel
+{
+ Q_OBJECT
+public:
+ explicit CustomTableModel(QObject *parent = 0);
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+
+ void addMapping(QString color, QRect area);
+ void clearMapping() { m_mapping.clear(); }
+
+private:
+ QList<QVector<qreal> *> m_data;
+ QHash<QString, QRect> m_mapping;
+ int m_columnCount;
+ int m_rowCount;
+};
+
+#endif // CUSTOMTABLEMODEL_H
diff --git a/tests/boxplottester/main.cpp b/tests/boxplottester/main.cpp
new file mode 100644
index 00000000..6d0e7cd3
--- /dev/null
+++ b/tests/boxplottester/main.cpp
@@ -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$
+**
+****************************************************************************/
+
+#include <QtCore/QtGlobal>
+#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
+#include <QApplication>
+#else
+#include <QtWidgets/QApplication>
+#endif
+#include "mainwidget.h"
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+
+ MainWidget w;
+ w.resize(1000,600);
+ w.show();
+
+ return a.exec();
+}
diff --git a/tests/boxplottester/mainwidget.cpp b/tests/boxplottester/mainwidget.cpp
new file mode 100644
index 00000000..17227ae9
--- /dev/null
+++ b/tests/boxplottester/mainwidget.cpp
@@ -0,0 +1,416 @@
+/****************************************************************************
+**
+** 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 "mainwidget.h"
+#include "customtablemodel.h"
+#include <QVBoxPlotModelMapper>
+#include <QTableView>
+#include <QHeaderView>
+#include <QChartView>
+#include <QBoxPlotSeries>
+#include <QBoxSet>
+#include <QLegend>
+#include <QBarCategoryAxis>
+#include <QBrush>
+#include <QColor>
+#include <QPushButton>
+#include <QComboBox>
+#include <QSpinBox>
+#include <QCheckBox>
+#include <QGridLayout>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QSpacerItem>
+#include <QMessageBox>
+#include <cmath>
+#include <QDebug>
+#include <QStandardItemModel>
+#include <QBarCategoryAxis>
+
+
+QTCOMMERCIALCHART_USE_NAMESPACE
+
+QString addCategories[] = {"Jul", "Aug", "Sep", "Nov", "Dec"};
+
+MainWidget::MainWidget(QWidget *parent) :
+ QWidget(parent),
+ m_chart(0),
+ rowPos(0),
+ nSeries(0),
+ nNewBoxes(0)
+{
+ m_chart = new QChart();
+
+ // Grid layout for the controls for configuring the chart widget
+ QGridLayout *grid = new QGridLayout();
+
+ // Create add a series button
+ QPushButton *addSeriesButton = new QPushButton("Add a series");
+ connect(addSeriesButton, SIGNAL(clicked()), this, SLOT(addSeries()));
+ grid->addWidget(addSeriesButton, rowPos++, 1);
+
+ // Create remove a series button
+ QPushButton *removeSeriesButton = new QPushButton("Remove a series");
+ connect(removeSeriesButton, SIGNAL(clicked()), this, SLOT(removeSeries()));
+ grid->addWidget(removeSeriesButton, rowPos++, 1);
+
+ // Create add a single box button
+ QPushButton *addBoxButton = new QPushButton("Add a box");
+ connect(addBoxButton, SIGNAL(clicked()), this, SLOT(addBox()));
+ grid->addWidget(addBoxButton, rowPos++, 1);
+
+ // Create insert a box button
+ QPushButton *insertBoxButton = new QPushButton("Insert a box");
+ connect(insertBoxButton, SIGNAL(clicked()), this, SLOT(insertBox()));
+ grid->addWidget(insertBoxButton, rowPos++, 1);
+
+ // Create add a single box button
+ QPushButton *removeBoxButton = new QPushButton("Remove a box");
+ connect(removeBoxButton, SIGNAL(clicked()), this, SLOT(removeBox()));
+ grid->addWidget(removeBoxButton, rowPos++, 1);
+
+ // Create clear button
+ QPushButton *clearButton = new QPushButton("Clear");
+ connect(clearButton, SIGNAL(clicked()), this, SLOT(clear()));
+ grid->addWidget(clearButton, rowPos++, 1);
+
+ // Create clear button
+ QPushButton *clearBoxButton = new QPushButton("ClearBox");
+ connect(clearBoxButton, SIGNAL(clicked()), this, SLOT(clearBox()));
+ grid->addWidget(clearBoxButton, rowPos++, 1);
+
+
+ // Create set brush button
+ QPushButton *setBrushButton = new QPushButton("Set brush");
+ connect(setBrushButton, SIGNAL(clicked()), this, SLOT(setBrush()));
+ grid->addWidget(setBrushButton, rowPos++, 1);
+
+ initThemeCombo(grid);
+ initCheckboxes(grid);
+
+ m_model = new CustomTableModel;
+ QTableView *tableView = new QTableView;
+ tableView->setModel(m_model);
+ tableView->setMaximumWidth(200);
+ grid->addWidget(tableView, rowPos++, 0, 3, 2, Qt::AlignLeft);
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
+ tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
+ tableView->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
+#else
+ tableView->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
+ tableView->verticalHeader()->setResizeMode(QHeaderView::Stretch);
+#endif
+
+ // add row with empty label to make all the other rows static
+ grid->addWidget(new QLabel(""), grid->rowCount(), 0);
+ grid->setRowStretch(grid->rowCount() - 1, 1);
+
+ // Create chart view with the chart
+ m_chartView = new QChartView(m_chart, this);
+ //m_chartView->setRubberBand(QChartView::HorizonalRubberBand);
+
+ // Another grid layout as a main layout
+ QGridLayout *mainLayout = new QGridLayout();
+ mainLayout->addLayout(grid, 0, 0);
+ mainLayout->addWidget(m_chartView, 0, 1, 3, 1);
+ setLayout(mainLayout);
+
+ legendToggled(false);
+ animationToggled(false);
+}
+
+// Combo box for selecting theme
+void MainWidget::initThemeCombo(QGridLayout *grid)
+{
+ QComboBox *chartTheme = new QComboBox();
+ chartTheme->addItem("Default");
+ chartTheme->addItem("Light");
+ chartTheme->addItem("Blue Cerulean");
+ chartTheme->addItem("Dark");
+ chartTheme->addItem("Brown Sand");
+ chartTheme->addItem("Blue NCS");
+ chartTheme->addItem("High Contrast");
+ chartTheme->addItem("Blue Icy");
+ connect(chartTheme, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(changeChartTheme(int)));
+ grid->addWidget(new QLabel("Chart theme:"), rowPos, 0);
+ grid->addWidget(chartTheme, rowPos++, 1);
+}
+
+// Different check boxes for customizing chart
+void MainWidget::initCheckboxes(QGridLayout *grid)
+{
+ QCheckBox *animationCheckBox = new QCheckBox("Animation");
+ connect(animationCheckBox, SIGNAL(toggled(bool)), this, SLOT(animationToggled(bool)));
+ animationCheckBox->setChecked(false);
+ grid->addWidget(animationCheckBox, rowPos++, 0);
+
+ QCheckBox *legendCheckBox = new QCheckBox("Legend");
+ connect(legendCheckBox, SIGNAL(toggled(bool)), this, SLOT(legendToggled(bool)));
+ legendCheckBox->setChecked(false);
+ grid->addWidget(legendCheckBox, rowPos++, 0);
+
+ QCheckBox *titleCheckBox = new QCheckBox("Title");
+ connect(titleCheckBox, SIGNAL(toggled(bool)), this, SLOT(titleToggled(bool)));
+ titleCheckBox->setChecked(false);
+ grid->addWidget(titleCheckBox, rowPos++, 0);
+
+ QCheckBox *modelMapperCheckBox = new QCheckBox("Use model mapper");
+ connect(modelMapperCheckBox, SIGNAL(toggled(bool)), this, SLOT(modelMapperToggled(bool)));
+ modelMapperCheckBox->setChecked(false);
+ grid->addWidget(modelMapperCheckBox, rowPos++, 0);
+
+}
+
+void MainWidget::addSeries()
+{
+ qDebug() << "BoxPlotTester::MainWidget::addSeries()";
+
+ if (nSeries > 9)
+ return;
+
+ // Initial data
+ //![1]
+ QBoxSet *set0 = new QBoxSet();
+ QBoxSet *set1 = new QBoxSet();
+ QBoxSet *set2 = new QBoxSet();
+ QBoxSet *set3 = new QBoxSet();
+ QBoxSet *set4 = new QBoxSet();
+ QBoxSet *set5 = new QBoxSet();
+
+ // low bot med top upp
+ *set0 << 1 << 2 << 4.4 << 13 << 15;
+ *set1 << 5 << 6 << 7.5 << 8 << 12;
+ *set2 << 3 << 5 << 5.7 << 8 << 9;
+ *set3 << 5 << 6 << 6.8 << 7 << 8;
+ *set4 << 4 << 5 << 5.2 << 6 << 7;
+ *set5 << 4 << 7 << 8.2 << 9 << 10;
+
+ m_series[nSeries] = new QBoxPlotSeries();
+ m_series[nSeries]->append(set0);
+ m_series[nSeries]->append(set1);
+ m_series[nSeries]->append(set2);
+ m_series[nSeries]->append(set3);
+ m_series[nSeries]->append(set4);
+ m_series[nSeries]->append(set5);
+ m_series[nSeries]->setName("Box & Whiskers");
+
+ connect(m_series[nSeries], SIGNAL(clicked(QBoxSet*)), this, SLOT(boxClicked(QBoxSet*)));
+ connect(m_series[nSeries], SIGNAL(hovered(bool, QBoxSet*)), this, SLOT(boxHovered(bool, QBoxSet*)));
+ connect(set1, SIGNAL(clicked()), this, SLOT(singleBoxClicked()));
+ connect(set2, SIGNAL(hovered(bool)), this, SLOT(singleBoxHovered(bool)));
+
+ m_chart->addSeries(m_series[nSeries]);
+
+ if (nSeries == 0) {
+ QStringList categories;
+ categories << "Jan" << "Feb" << "Mar" << "Apr" << "May" << "Jun";
+ m_axis = new QBarCategoryAxis();
+ m_axis->append(categories);
+ m_chart->createDefaultAxes();
+ m_chart->setAxisX(m_axis, m_series[nSeries]);
+ }
+
+ nSeries++;
+}
+
+void MainWidget::removeSeries()
+{
+ qDebug() << "BoxPlotTester::MainWidget::removeSeries()";
+
+ if (nSeries > 0) {
+ nSeries--;
+ m_chart->removeSeries(m_series[nSeries]);
+ delete m_series[nSeries];
+ } else {
+ qDebug() << "Create a series first";
+ }
+}
+
+void MainWidget::addBox()
+{
+ qDebug() << "BoxPlotTester::MainWidget::addBox()";
+
+ if (nSeries > 0) {
+ QBoxSet *newSet = new QBoxSet();
+ newSet->setValue(QBoxSet::LowerExtreme, 5.0);
+ newSet->setValue(QBoxSet::LowerQuartile, 6.0);
+ newSet->setValue(QBoxSet::Median, 6.8);
+ newSet->setValue(QBoxSet::UpperQuartile, 7.0);
+ newSet->setValue(QBoxSet::UpperExtreme, 8.0);
+
+ for (int i = 0; i < nSeries; i++)
+ m_series[i]->append(newSet);
+
+ m_axis->append(addCategories[nNewBoxes]);
+
+ nNewBoxes++;
+ }
+}
+
+void MainWidget::insertBox()
+{
+ qDebug() << "BoxPlotTester::MainWidget::insertBox()";
+
+ if (nSeries > 0) {
+ QBoxSet *newSet = new QBoxSet();
+ *newSet << 2 << 6 << 6.8 << 7 << 10;
+
+ for (int i = 0; i < nSeries; i++)
+ m_series[i]->insert(1, newSet);
+
+ m_axis->append(addCategories[nNewBoxes]);
+
+ nNewBoxes++;
+ }
+}
+
+void MainWidget::removeBox()
+{
+ qDebug() << "BoxPlotTester::MainWidget::removeBox";
+
+ if (nSeries > 0) {
+ for (int i = 0; i < nSeries; i++) {
+ QList<QBoxSet *> sets = m_series[i]->boxSets();
+ m_series[i]->remove(sets.at(m_series[i]->count() - 3));
+ }
+
+ m_axis->remove(m_axis->at(1));
+ } else {
+ qDebug() << "Create a series first";
+ }
+}
+
+void MainWidget::clear()
+{
+ qDebug() << "BoxPlotTester::MainWidget::clear";
+
+ if (nSeries > 0)
+ m_series[0]->clear();
+ else
+ qDebug() << "Create a series first";
+}
+
+void MainWidget::clearBox()
+{
+ qDebug() << "BoxPlotTester::MainWidget::clearBox";
+
+ if (nSeries > 0) {
+ QList<QBoxSet *> sets = m_series[0]->boxSets();
+ sets.at(1)->clear();
+ } else {
+ qDebug() << "Create a series first";
+ }
+}
+
+void MainWidget::setBrush()
+{
+ qDebug() << "BoxPlotTester::MainWidget::setBrush";
+
+ if (nSeries > 0) {
+ QList<QBoxSet *> sets = m_series[0]->boxSets();
+ sets.at(1)->setBrush(QBrush(QColor(Qt::yellow)));
+ } else {
+ qDebug() << "Create a series first";
+ }
+}
+
+void MainWidget::animationToggled(bool enabled)
+{
+ qDebug() << "BoxPlotTester::Animation toggled to " << enabled;
+ if (enabled)
+ m_chart->setAnimationOptions(QChart::SeriesAnimations);
+ else
+ m_chart->setAnimationOptions(QChart::NoAnimation);
+}
+
+void MainWidget::legendToggled(bool enabled)
+{
+ qDebug() << "BoxPlotTester::Legend toggled to " << enabled;
+ m_chart->legend()->setVisible(enabled);
+ if (enabled)
+ m_chart->legend()->setAlignment(Qt::AlignBottom);
+}
+
+void MainWidget::titleToggled(bool enabled)
+{
+ qDebug() << "BoxPlotTester::Title toggled to " << enabled;
+ if (enabled)
+ m_chart->setTitle("Simple boxplotchart example");
+ else
+ m_chart->setTitle("");
+}
+
+void MainWidget::modelMapperToggled(bool enabled)
+{
+ if (enabled) {
+ m_series[nSeries] = new QBoxPlotSeries();
+
+ int first = 0;
+ int count = 5;
+ QVBoxPlotModelMapper *mapper = new QVBoxPlotModelMapper(this);
+ mapper->setFirstBoxSetColumn(0);
+ mapper->setLastBoxSetColumn(5);
+ mapper->setFirstRow(first);
+ mapper->setRowCount(count);
+ mapper->setSeries(m_series[nSeries]);
+ mapper->setModel(m_model);
+ m_chart->addSeries(m_series[nSeries]);
+
+ nSeries++;
+ } else {
+ removeSeries();
+ }
+}
+
+void MainWidget::changeChartTheme(int themeIndex)
+{
+ qDebug() << "BoxPlotTester::changeChartTheme: " << themeIndex;
+ if (themeIndex == 0)
+ m_chart->setTheme(QChart::ChartThemeLight);
+ else
+ m_chart->setTheme((QChart::ChartTheme) (themeIndex - 1));
+}
+
+void MainWidget::boxClicked(QBoxSet *set)
+{
+ qDebug() << "boxClicked, median = " << set->at(QBoxSet::Median);
+}
+
+void MainWidget::boxHovered(bool state, QBoxSet *set)
+{
+ if (state)
+ qDebug() << "box median " << set->at(QBoxSet::Median) << " hover started";
+ else
+ qDebug() << "box median " << set->at(QBoxSet::Median) << " hover ended";
+}
+
+void MainWidget::singleBoxClicked()
+{
+ qDebug() << "singleBoxClicked";
+}
+
+void MainWidget::singleBoxHovered(bool state)
+{
+ if (state)
+ qDebug() << "single box hover started";
+ else
+ qDebug() << "single box hover ended";
+}
diff --git a/tests/boxplottester/mainwidget.h b/tests/boxplottester/mainwidget.h
new file mode 100644
index 00000000..de2cf7cc
--- /dev/null
+++ b/tests/boxplottester/mainwidget.h
@@ -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$
+**
+****************************************************************************/
+
+#ifndef MAINWIDGET_H
+#define MAINWIDGET_H
+
+#include "qchartglobal.h"
+#include "qchart.h"
+#include "qchartview.h"
+#include "customtablemodel.h"
+#include <QWidget>
+#include <QBoxPlotSeries>
+#include <QBarCategoryAxis>
+#include <QBoxSet>
+
+class QGridLayout;
+
+QTCOMMERCIALCHART_USE_NAMESPACE
+
+class MainWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit MainWidget(QWidget *parent = 0);
+
+signals:
+
+private:
+ void initThemeCombo(QGridLayout *grid);
+ void initCheckboxes(QGridLayout *grid);
+
+private slots:
+ void addSeries();
+ void removeSeries();
+ void addBox();
+ void insertBox();
+ void removeBox();
+ void clear();
+ void clearBox();
+ void setBrush();
+ void animationToggled(bool enabled);
+ void legendToggled(bool enabled);
+ void titleToggled(bool enabled);
+ void modelMapperToggled(bool enabled);
+ void changeChartTheme(int themeIndex);
+ void boxClicked(QBoxSet *set);
+ void boxHovered(bool state, QBoxSet *set);
+ void singleBoxClicked();
+ void singleBoxHovered(bool state);
+
+private:
+ QChart *m_chart;
+ QChartView *m_chartView;
+ QGridLayout *m_scatterLayout;
+ QBarCategoryAxis *m_axis;
+ CustomTableModel *m_model;
+ int rowPos;
+ int nSeries;
+ int nNewBoxes;
+ QBoxPlotSeries *m_series[10];
+};
+
+#endif // MAINWIDGET_H
diff --git a/tests/tests.pro b/tests/tests.pro
index 73f45abe..a0a9c1b6 100644
--- a/tests/tests.pro
+++ b/tests/tests.pro
@@ -8,7 +8,8 @@ SUBDIRS += \
qmlchartproperties \
qmlchartaxis \
presenterchart \
- polarcharttest
+ polarcharttest \
+ boxplottester
contains(QT_CONFIG, opengl) {
SUBDIRS += chartwidgettest \