summaryrefslogtreecommitdiffstats
path: root/src/charts/barchart/qabstractbarseries.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/charts/barchart/qabstractbarseries.cpp')
-rw-r--r--src/charts/barchart/qabstractbarseries.cpp1030
1 files changed, 1030 insertions, 0 deletions
diff --git a/src/charts/barchart/qabstractbarseries.cpp b/src/charts/barchart/qabstractbarseries.cpp
new file mode 100644
index 00000000..08345112
--- /dev/null
+++ b/src/charts/barchart/qabstractbarseries.cpp
@@ -0,0 +1,1030 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Enterprise Charts Add-on.
+**
+** $QT_BEGIN_LICENSE$
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qabstractbarseries.h"
+#include "qabstractbarseries_p.h"
+#include "qbarset.h"
+#include "qbarset_p.h"
+#include "abstractdomain_p.h"
+#include "chartdataset_p.h"
+#include "charttheme_p.h"
+#include "qvalueaxis.h"
+#include "qbarcategoryaxis.h"
+#include "qbarlegendmarker.h"
+#include "baranimation_p.h"
+#include "abstractbarchartitem_p.h"
+#include "qchart_p.h"
+
+QT_CHARTS_BEGIN_NAMESPACE
+
+/*!
+ \class QAbstractBarSeries
+ \inmodule Qt Charts
+ \brief Series for creating a bar chart.
+ \mainclass
+
+ QAbstractBarSeries represents a series of data shown as bars. The purpose of this class is to draw bars to
+ the position defined by data. Single bar is defined by QPointF, where x value is the x-coordinate of the bar
+ and y-value is the height of the bar. The category names are ignored with this series and x-axis
+ shows the x-values.
+
+ See the \l {BarChart Example} {bar chart example} to learn how to create a simple bar chart.
+ \image examples_barchart.png
+
+ \sa QBarSet, QStackedBarSeries, QPercentBarSeries
+*/
+/*!
+ \qmltype AbstractBarSeries
+ \instantiates QAbstractBarSeries
+ \inqmlmodule QtCharts
+
+ \inherits AbstractSeries
+
+ \brief Series type for creating a bar chart.
+
+ The following QML shows how to create a simple bar chart:
+ \snippet qmlchart/qml/qmlchart/View6.qml 1
+
+ \beginfloatleft
+ \image examples_qmlchart6.png
+ \endfloat
+ \clearfloat
+*/
+
+/*!
+ \qmlproperty AbstractAxis AbstractBarSeries::axisX
+ The x axis used for the series. If you leave both axisX and axisXTop undefined, a BarCategoriesAxis is created for
+ the series.
+ \sa axisXTop
+*/
+
+/*!
+ \qmlproperty AbstractAxis AbstractBarSeries::axisY
+ The y axis used for the series. If you leave both axisY and axisYRight undefined, a ValueAxis is created for
+ the series.
+ \sa axisYRight
+*/
+
+/*!
+ \qmlproperty AbstractAxis AbstractBarSeries::axisXTop
+ The x axis used for the series, drawn on top of the chart view. Note that you can only provide either axisX or
+ axisXTop, but not both.
+ \sa axisX
+*/
+
+/*!
+ \qmlproperty AbstractAxis AbstractBarSeries::axisYRight
+ The y axis used for the series, drawn to the right on the chart view. Note that you can only provide either axisY
+ or axisYRight, but not both.
+ \sa axisY
+*/
+
+/*!
+ \property QAbstractBarSeries::barWidth
+ The width of the bars of the series. The unit of \a width is the unit of x-axis. The minimum width for bars
+ is zero and negative values are treated as zero. Setting the width to zero means that width of the bar on screen
+ is one pixel no matter what the scale of x-axis is. Bars wider than zero are scaled with x-axis.
+ Note that with QBarSeries this value means the width of one group of bars instead of just one bar.
+ \sa QBarSeries
+*/
+/*!
+ \qmlproperty real AbstractBarSeries::barWidth
+ The width of the bars of the series. The unit of width is the unit of x-axis. The minimum width for bars
+ is zero and negative values are treated as zero. Setting the width to zero means that width of the bar on screen
+ is one pixel no matter what the scale of x-axis is. Bars wider than zero are scaled with x-axis.
+ Note that with QBarSeries this value means the width of one group of bars instead of just one bar.
+*/
+
+/*!
+ \property QAbstractBarSeries::count
+ Holds the number of sets in series.
+*/
+/*!
+ \qmlproperty int AbstractBarSeries::count
+ Holds the number of sets in series.
+*/
+
+/*!
+ \property QAbstractBarSeries::labelsVisible
+ Defines the visibility of the labels in series
+*/
+/*!
+ \qmlproperty bool AbstractBarSeries::labelsVisible
+ Defines the visibility of the labels in series
+*/
+
+/*!
+ \property QAbstractBarSeries::labelsFormat
+ The \a format used for showing labels in series.
+
+ QAbstractBarSeries supports the following format tag:
+ \table
+ \row
+ \li @value \li The value of the bar
+ \endtable
+
+ For example, the following usage of the format tags would produce labels that show the value
+ followed by unit ('u'):
+ \code
+ series->setLabelsFormat("@value u");
+ \endcode
+
+ By default, the labels shows the value of the bar. For percent bar series '%' is added after
+ the value. The labels are shown on the plot area, labels on the edge of the plot area are cut.
+ If the bars are close to each other the labels may overlap.
+
+ \sa QAbstractBarSeries::labelsVisible, QAbstractBarSeries::labelsPosition
+*/
+/*!
+ \qmlproperty string AbstractBarSeries::labelsFormat
+ The format used for showing labels in series.
+
+ \sa QAbstractBarSeries::labelsFormat, labelsVisible, labelsPosition
+*/
+/*!
+ \fn void QAbstractBarSeries::labelsFormatChanged(const QString &format)
+ Signal is emitted when the \a format of data value labels is changed.
+*/
+/*!
+ \qmlsignal XYSeries::onLabelsFormatChanged(string format)
+ Signal is emitted when the \a format of data value labels is changed.
+*/
+
+/*!
+ \enum QAbstractBarSeries::LabelsPosition
+
+ This enum describes the position of the data value labels.
+
+ \value LabelsCenter Label is in the center of the bar.
+ \value LabelsInsideEnd Label is inside the bar at the high end of it.
+ \value LabelsInsideBase Label is inside the bar at the low end of it.
+ \value LabelsOutsideEnd Label is outside the bar at the high end of it.
+ */
+
+/*!
+ \property QAbstractBarSeries::labelsPosition
+ Defines the \a position of value labels.
+
+ \sa QAbstractBarSeries::labelsVisible, QAbstractBarSeries::labelsFormat
+*/
+/*!
+ \qmlproperty string AbstractBarSeries::labelsPosition
+ Defines the \a position of value labels.
+
+ \sa labelsVisible, labelsFormat
+*/
+/*!
+ \fn void QAbstractBarSeries::labelsPositionChanged(QAbstractBarSeries::LabelsPosition position)
+ Signal is emitted when the \a position of value labels is changed.
+*/
+/*!
+ \qmlsignal AbstractBarSeries::onLabelsPositionChanged(LabelsPosition position)
+ Signal is emitted when the \a position of value labels is changed.
+*/
+
+/*!
+ \fn void QAbstractBarSeries::clicked(int index, QBarSet *barset)
+ The signal is emitted if the user clicks with a mouse on top of QBarSet \a barset.
+ Clicked bar inside set is indexed by \a index
+*/
+/*!
+ \qmlsignal AbstractBarSeries::onClicked(int index, BarSet barset)
+ The signal is emitted if the user clicks with a mouse on top of BarSet.
+ Clicked bar inside set is indexed by \a index
+*/
+
+/*!
+ \fn void QAbstractBarSeries::hovered(bool status, QBarSet* barset)
+
+ The signal is emitted if mouse is hovered on top of series.
+ Parameter \a barset is the pointer of barset, where hover happened.
+ Parameter \a status is true, if mouse entered on top of series, false if mouse left from top of series.
+*/
+
+/*!
+ \fn void QAbstractBarSeries::hovered(bool status, int index, QBarSet* barset)
+
+ The signal is emitted if mouse is hovered on top of series.
+ Parameter \a barset is the pointer of barset, where hover happened.
+ Parameter \a status is true, if mouse entered on top of series, false if mouse left from top of series.
+ Hovered bar inside the set is indexed by \a index.
+*/
+/*!
+ \qmlsignal AbstractBarSeries::onHovered(bool status, int index, BarSet barset)
+
+ The signal is emitted if mouse is hovered on top of series.
+ Parameter \a barset is the pointer of barset, where hover happened.
+ Parameter \a status is true, if mouse entered on top of series, false if mouse left from top of series.
+ Hovered bar inside the set is indexed by \a index.
+*/
+
+/*!
+ \fn void QAbstractBarSeries::countChanged()
+ This signal is emitted when barset count has been changed, for example by append or remove.
+*/
+/*!
+ \qmlsignal AbstractBarSeries::onCountChanged()
+ This signal is emitted when barset count has been changed, for example by append or remove.
+*/
+
+/*!
+ \fn void QAbstractBarSeries::labelsVisibleChanged()
+ This signal is emitted when labels visibility have changed.
+ \sa isLabelsVisible(), setLabelsVisible()
+*/
+
+/*!
+ \fn void QAbstractBarSeries::barsetsAdded(QList<QBarSet*> sets)
+ This signal is emitted when \a sets have been added to the series.
+ \sa append(), insert()
+*/
+/*!
+ \qmlsignal AbstractBarSeries::onBarsetsAdded(BarSet barset)
+ Emitted when \a barset has been added to the series.
+*/
+
+/*!
+ \fn void QAbstractBarSeries::barsetsRemoved(QList<QBarSet*> sets)
+ This signal is emitted when \a sets have been removed from the series.
+ \sa remove()
+*/
+/*!
+ \qmlsignal AbstractBarSeries::onBarsetsRemoved(BarSet barset)
+ Emitted when \a barset has been removed from the series.
+*/
+
+/*!
+ \qmlmethod BarSet AbstractBarSeries::at(int index)
+ Returns bar set at \a index. Returns null if the index is not valid.
+*/
+
+/*!
+ \qmlmethod BarSet AbstractBarSeries::append(string label, VariantList values)
+ Adds a new bar set with \a label and \a values to \a index. Values is a list of reals.
+ For example:
+ \code
+ myBarSeries.append("set 1", [0, 0.2, 0.2, 0.5, 0.4, 1.5, 0.9]);
+ \endcode
+*/
+
+/*!
+ \qmlmethod BarSet AbstractBarSeries::insert(int index, string label, VariantList values)
+ Inserts a new bar set with \a label and \a values to \a index. Values can be a list of reals or a list of XYPoints.
+ If index is zero or smaller, the new barset is prepended. If the index is count or bigger, the new barset is
+ appended.
+ \sa AbstractBarSeries::append()
+*/
+
+/*!
+ \qmlmethod bool AbstractBarSeries::remove(BarSet barset)
+ Removes the barset from the series. Returns true if successful, false otherwise.
+*/
+
+/*!
+ \qmlmethod AbstractBarSeries::clear()
+ Removes all barsets from the series.
+*/
+
+/*!
+ Destructs abstractbarseries and owned barsets.
+*/
+QAbstractBarSeries::~QAbstractBarSeries()
+{
+
+}
+
+/*!
+ \internal
+*/
+QAbstractBarSeries::QAbstractBarSeries(QAbstractBarSeriesPrivate &o, QObject *parent)
+ : QAbstractSeries(o, parent)
+{
+ Q_D(QAbstractSeries);
+ QObject::connect(this, SIGNAL(countChanged()), d, SIGNAL(countChanged()));
+}
+
+/*!
+ Sets the width of the bars of the series. The unit of \a width is the unit of x-axis. The minimum width for bars
+ is zero and negative values are treated as zero. Setting the width to zero means that width of the bar on screen
+ is one pixel no matter what the scale of x-axis is. Bars wider than zero are scaled with x-axis.
+ Note that with \link QBarSeries \endlink this value means the width of one group of bars instead of just one bar.
+*/
+void QAbstractBarSeries::setBarWidth(qreal width)
+{
+ Q_D(QAbstractBarSeries);
+ d->setBarWidth(width);
+}
+
+/*!
+ Returns the width of the bars of the series.
+ \sa setBarWidth()
+*/
+qreal QAbstractBarSeries::barWidth() const
+{
+ Q_D(const QAbstractBarSeries);
+ return d->barWidth();
+}
+
+/*!
+ Adds a set of bars to series. Takes ownership of \a set. If the set is null or is already in series, it won't be appended.
+ Returns true, if appending succeeded.
+*/
+bool QAbstractBarSeries::append(QBarSet *set)
+{
+ Q_D(QAbstractBarSeries);
+ bool success = d->append(set);
+ if (success) {
+ QList<QBarSet *> sets;
+ sets.append(set);
+ set->setParent(this);
+ emit barsetsAdded(sets);
+ emit countChanged();
+ }
+ return success;
+}
+
+/*!
+ Removes barset from series. Releases ownership of \a set. Deletes the set, if remove
+ was successful.
+ Returns true, if set was removed.
+*/
+bool QAbstractBarSeries::remove(QBarSet *set)
+{
+ Q_D(QAbstractBarSeries);
+ bool success = d->remove(set);
+ if (success) {
+ QList<QBarSet *> sets;
+ sets.append(set);
+ set->setParent(0);
+ emit barsetsRemoved(sets);
+ emit countChanged();
+ delete set;
+ set = 0;
+ }
+ return success;
+}
+
+/*!
+ Takes a single \a set from the series. Does not delete the barset object.
+
+ NOTE: The series remains as the barset's parent object. You must set the
+ parent object to take full ownership.
+
+ Returns true if take was successful.
+*/
+bool QAbstractBarSeries::take(QBarSet *set)
+{
+ Q_D(QAbstractBarSeries);
+ bool success = d->remove(set);
+ if (success) {
+ QList<QBarSet *> sets;
+ sets.append(set);
+ emit barsetsRemoved(sets);
+ emit countChanged();
+ }
+ return success;
+}
+
+/*!
+ Adds a list of barsets to series. Takes ownership of \a sets.
+ Returns true, if all sets were appended successfully. If any of the sets is null or is already appended to series,
+ nothing is appended and function returns false. If any of the sets is in list more than once, nothing is appended
+ and function returns false.
+*/
+bool QAbstractBarSeries::append(QList<QBarSet *> sets)
+{
+ Q_D(QAbstractBarSeries);
+ bool success = d->append(sets);
+ if (success) {
+ emit barsetsAdded(sets);
+ emit countChanged();
+ }
+ return success;
+}
+
+/*!
+ Insert a set of bars to series at \a index postion. Takes ownership of \a set. If the set is null or is already in series, it won't be appended.
+ Returns true, if inserting succeeded.
+
+*/
+bool QAbstractBarSeries::insert(int index, QBarSet *set)
+{
+ Q_D(QAbstractBarSeries);
+ bool success = d->insert(index, set);
+ if (success) {
+ QList<QBarSet *> sets;
+ sets.append(set);
+ emit barsetsAdded(sets);
+ emit countChanged();
+ }
+ return success;
+}
+
+/*!
+ Removes all barsets from the series. Deletes removed sets.
+*/
+void QAbstractBarSeries::clear()
+{
+ Q_D(QAbstractBarSeries);
+ QList<QBarSet *> sets = barSets();
+ bool success = d->remove(sets);
+ if (success) {
+ emit barsetsRemoved(sets);
+ emit countChanged();
+ foreach (QBarSet *set, sets)
+ delete set;
+ }
+}
+
+/*!
+ Returns number of sets in series.
+*/
+int QAbstractBarSeries::count() const
+{
+ Q_D(const QAbstractBarSeries);
+ return d->m_barSets.count();
+}
+
+/*!
+ Returns a list of sets in series. Keeps ownership of sets.
+ */
+QList<QBarSet *> QAbstractBarSeries::barSets() const
+{
+ Q_D(const QAbstractBarSeries);
+ return d->m_barSets;
+}
+
+/*!
+ Sets the visibility of labels in series to \a visible
+*/
+void QAbstractBarSeries::setLabelsVisible(bool visible)
+{
+ Q_D(QAbstractBarSeries);
+ if (d->m_labelsVisible != visible) {
+ d->setLabelsVisible(visible);
+ emit labelsVisibleChanged();
+ }
+}
+
+/*!
+ Returns the visibility of labels
+*/
+bool QAbstractBarSeries::isLabelsVisible() const
+{
+ Q_D(const QAbstractBarSeries);
+ return d->m_labelsVisible;
+}
+
+void QAbstractBarSeries::setLabelsFormat(const QString &format)
+{
+ Q_D(QAbstractBarSeries);
+ if (d->m_labelsFormat != format) {
+ d->m_labelsFormat = format;
+ emit labelsFormatChanged(format);
+ }
+}
+
+QString QAbstractBarSeries::labelsFormat() const
+{
+ Q_D(const QAbstractBarSeries);
+ return d->m_labelsFormat;
+}
+
+void QAbstractBarSeries::setLabelsPosition(QAbstractBarSeries::LabelsPosition position)
+{
+ Q_D(QAbstractBarSeries);
+ if (d->m_labelsPosition != position) {
+ d->m_labelsPosition = position;
+ emit labelsPositionChanged(position);
+ }
+}
+
+QAbstractBarSeries::LabelsPosition QAbstractBarSeries::labelsPosition() const
+{
+ Q_D(const QAbstractBarSeries);
+ return d->m_labelsPosition;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QAbstractBarSeriesPrivate::QAbstractBarSeriesPrivate(QAbstractBarSeries *q) :
+ QAbstractSeriesPrivate(q),
+ m_barWidth(0.5), // Default value is 50% of category width
+ m_labelsVisible(false),
+ m_visible(true),
+ m_blockBarUpdate(false),
+ m_labelsFormat(),
+ m_labelsPosition(QAbstractBarSeries::LabelsCenter)
+{
+}
+
+int QAbstractBarSeriesPrivate::categoryCount() const
+{
+ // No categories defined. return count of longest set.
+ int count = 0;
+ for (int i = 0; i < m_barSets.count(); i++) {
+ if (m_barSets.at(i)->count() > count)
+ count = m_barSets.at(i)->count();
+ }
+
+ return count;
+}
+
+void QAbstractBarSeriesPrivate::setBarWidth(qreal width)
+{
+ if (width < 0.0)
+ width = 0.0;
+ m_barWidth = width;
+ emit updatedLayout();
+}
+
+qreal QAbstractBarSeriesPrivate::barWidth() const
+{
+ return m_barWidth;
+}
+
+QBarSet *QAbstractBarSeriesPrivate::barsetAt(int index)
+{
+ return m_barSets.at(index);
+}
+
+void QAbstractBarSeriesPrivate::setVisible(bool visible)
+{
+ m_visible = visible;
+ emit visibleChanged();
+}
+
+void QAbstractBarSeriesPrivate::setLabelsVisible(bool visible)
+{
+ m_labelsVisible = visible;
+ emit labelsVisibleChanged(visible);
+}
+
+qreal QAbstractBarSeriesPrivate::min()
+{
+ if (m_barSets.count() <= 0)
+ return 0;
+
+ qreal min = INT_MAX;
+
+ for (int i = 0; i < m_barSets.count(); i++) {
+ int categoryCount = m_barSets.at(i)->count();
+ for (int j = 0; j < categoryCount; j++) {
+ qreal temp = m_barSets.at(i)->at(j);
+ if (temp < min)
+ min = temp;
+ }
+ }
+ return min;
+}
+
+qreal QAbstractBarSeriesPrivate::max()
+{
+ if (m_barSets.count() <= 0)
+ return 0;
+
+ qreal max = INT_MIN;
+
+ for (int i = 0; i < m_barSets.count(); i++) {
+ int categoryCount = m_barSets.at(i)->count();
+ for (int j = 0; j < categoryCount; j++) {
+ qreal temp = m_barSets.at(i)->at(j);
+ if (temp > max)
+ max = temp;
+ }
+ }
+
+ return max;
+}
+
+qreal QAbstractBarSeriesPrivate::valueAt(int set, int category)
+{
+ if ((set < 0) || (set >= m_barSets.count()))
+ return 0; // No set, no value.
+ else if ((category < 0) || (category >= m_barSets.at(set)->count()))
+ return 0; // No category, no value.
+
+ return m_barSets.at(set)->at(category);
+}
+
+qreal QAbstractBarSeriesPrivate::percentageAt(int set, int category)
+{
+ if ((set < 0) || (set >= m_barSets.count()))
+ return 0; // No set, no value.
+ else if ((category < 0) || (category >= m_barSets.at(set)->count()))
+ return 0; // No category, no value.
+
+ qreal value = m_barSets.at(set)->at(category);
+ qreal sum = categorySum(category);
+ if (qFuzzyCompare(sum, 0))
+ return 0;
+
+ return value / sum;
+}
+
+qreal QAbstractBarSeriesPrivate::categorySum(int category)
+{
+ qreal sum(0);
+ int count = m_barSets.count(); // Count sets
+ for (int set = 0; set < count; set++) {
+ if (category < m_barSets.at(set)->count())
+ sum += m_barSets.at(set)->at(category);
+ }
+ return sum;
+}
+
+qreal QAbstractBarSeriesPrivate::absoluteCategorySum(int category)
+{
+ qreal sum(0);
+ int count = m_barSets.count(); // Count sets
+ for (int set = 0; set < count; set++) {
+ if (category < m_barSets.at(set)->count())
+ sum += qAbs(m_barSets.at(set)->at(category));
+ }
+ return sum;
+}
+
+qreal QAbstractBarSeriesPrivate::maxCategorySum()
+{
+ qreal max = INT_MIN;
+ int count = categoryCount();
+ for (int i = 0; i < count; i++) {
+ qreal sum = categorySum(i);
+ if (sum > max)
+ max = sum;
+ }
+ return max;
+}
+
+qreal QAbstractBarSeriesPrivate::minX()
+{
+ if (m_barSets.count() <= 0)
+ return 0;
+
+ qreal min = INT_MAX;
+
+ for (int i = 0; i < m_barSets.count(); i++) {
+ int categoryCount = m_barSets.at(i)->count();
+ for (int j = 0; j < categoryCount; j++) {
+ qreal temp = m_barSets.at(i)->d_ptr.data()->m_values.at(j).x();
+ if (temp < min)
+ min = temp;
+ }
+ }
+ return min;
+}
+
+qreal QAbstractBarSeriesPrivate::maxX()
+{
+ if (m_barSets.count() <= 0)
+ return 0;
+
+ qreal max = INT_MIN;
+
+ for (int i = 0; i < m_barSets.count(); i++) {
+ int categoryCount = m_barSets.at(i)->count();
+ for (int j = 0; j < categoryCount; j++) {
+ qreal temp = m_barSets.at(i)->d_ptr.data()->m_values.at(j).x();
+ if (temp > max)
+ max = temp;
+ }
+ }
+
+ return max;
+}
+
+qreal QAbstractBarSeriesPrivate::categoryTop(int category)
+{
+ // Returns top (sum of all positive values) of category.
+ // Returns 0, if all values are negative
+ qreal top(0);
+ int count = m_barSets.count();
+ for (int set = 0; set < count; set++) {
+ if (category < m_barSets.at(set)->count()) {
+ qreal temp = m_barSets.at(set)->at(category);
+ if (temp > 0) {
+ top += temp;
+ }
+ }
+ }
+ return top;
+}
+
+qreal QAbstractBarSeriesPrivate::categoryBottom(int category)
+{
+ // Returns bottom (sum of all negative values) of category
+ // Returns 0, if all values are positive
+ qreal bottom(0);
+ int count = m_barSets.count();
+ for (int set = 0; set < count; set++) {
+ if (category < m_barSets.at(set)->count()) {
+ qreal temp = m_barSets.at(set)->at(category);
+ if (temp < 0) {
+ bottom += temp;
+ }
+ }
+ }
+ return bottom;
+}
+
+qreal QAbstractBarSeriesPrivate::top()
+{
+ // Returns top of all categories
+ qreal top(0);
+ int count = categoryCount();
+ for (int i = 0; i < count; i++) {
+ qreal temp = categoryTop(i);
+ if (temp > top)
+ top = temp;
+ }
+ return top;
+}
+
+qreal QAbstractBarSeriesPrivate::bottom()
+{
+ // Returns bottom of all categories
+ qreal bottom(0);
+ int count = categoryCount();
+ for (int i = 0; i < count; i++) {
+ qreal temp = categoryBottom(i);
+ if (temp < bottom)
+ bottom = temp;
+ }
+ return bottom;
+}
+
+bool QAbstractBarSeriesPrivate::blockBarUpdate()
+{
+ return m_blockBarUpdate;
+}
+
+void QAbstractBarSeriesPrivate::initializeDomain()
+{
+ qreal minX(domain()->minX());
+ qreal minY(domain()->minY());
+ qreal maxX(domain()->maxX());
+ qreal maxY(domain()->maxY());
+
+ qreal seriesMinX = this->minX();
+ qreal seriesMaxX = this->maxX();
+ qreal y = max();
+ minX = qMin(minX, seriesMinX - (qreal)0.5);
+ minY = qMin(minY, y);
+ maxX = qMax(maxX, seriesMaxX + (qreal)0.5);
+ maxY = qMax(maxY, y);
+
+ domain()->setRange(minX, maxX, minY, maxY);
+}
+
+QList<QLegendMarker*> QAbstractBarSeriesPrivate::createLegendMarkers(QLegend* legend)
+{
+ Q_Q(QAbstractBarSeries);
+ QList<QLegendMarker*> markers;
+
+ foreach(QBarSet* set, q->barSets()) {
+ QBarLegendMarker* marker = new QBarLegendMarker(q,set,legend);
+ markers << marker;
+ }
+ return markers;
+}
+
+
+bool QAbstractBarSeriesPrivate::append(QBarSet *set)
+{
+ if ((m_barSets.contains(set)) || (set == 0))
+ return false; // Fail if set is already in list or set is null.
+
+ m_barSets.append(set);
+ QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
+ QObject::connect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars()));
+ QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars()));
+
+ emit restructuredBars(); // this notifies barchartitem
+ return true;
+}
+
+bool QAbstractBarSeriesPrivate::remove(QBarSet *set)
+{
+ if (!m_barSets.contains(set))
+ return false; // Fail if set is not in list
+
+ m_barSets.removeOne(set);
+ QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
+ QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars()));
+ QObject::disconnect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars()));
+
+ emit restructuredBars(); // this notifies barchartitem
+ return true;
+}
+
+bool QAbstractBarSeriesPrivate::append(QList<QBarSet * > sets)
+{
+ foreach (QBarSet *set, sets) {
+ if ((set == 0) || (m_barSets.contains(set)))
+ return false; // Fail if any of the sets is null or is already appended.
+ if (sets.count(set) != 1)
+ return false; // Also fail if same set is more than once in given list.
+ }
+
+ foreach (QBarSet *set, sets) {
+ m_barSets.append(set);
+ QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
+ QObject::connect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars()));
+ QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars()));
+ }
+
+ emit restructuredBars(); // this notifies barchartitem
+ return true;
+}
+
+bool QAbstractBarSeriesPrivate::remove(QList<QBarSet * > sets)
+{
+ if (sets.count() == 0)
+ return false;
+
+ foreach (QBarSet *set, sets) {
+ if ((set == 0) || (!m_barSets.contains(set)))
+ return false; // Fail if any of the sets is null or is not in series
+ if (sets.count(set) != 1)
+ return false; // Also fail if same set is more than once in given list.
+ }
+
+ foreach (QBarSet *set, sets) {
+ m_barSets.removeOne(set);
+ QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
+ QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars()));
+ QObject::disconnect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars()));
+ }
+
+ emit restructuredBars(); // this notifies barchartitem
+
+ return true;
+}
+
+bool QAbstractBarSeriesPrivate::insert(int index, QBarSet *set)
+{
+ if ((m_barSets.contains(set)) || (set == 0))
+ return false; // Fail if set is already in list or set is null.
+
+ m_barSets.insert(index, set);
+ QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
+ QObject::connect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars()));
+ QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars()));
+
+ emit restructuredBars(); // this notifies barchartitem
+ return true;
+}
+
+void QAbstractBarSeriesPrivate::initializeAxes()
+{
+ Q_Q(QAbstractBarSeries);
+
+ foreach(QAbstractAxis* axis, m_axes) {
+
+ if (axis->type() == QAbstractAxis::AxisTypeBarCategory) {
+ switch (q->type()) {
+ case QAbstractSeries::SeriesTypeHorizontalBar:
+ case QAbstractSeries::SeriesTypeHorizontalPercentBar:
+ case QAbstractSeries::SeriesTypeHorizontalStackedBar:
+ if (axis->orientation() == Qt::Vertical)
+ populateCategories(qobject_cast<QBarCategoryAxis *>(axis));
+ break;
+ case QAbstractSeries::SeriesTypeBar:
+ case QAbstractSeries::SeriesTypePercentBar:
+ case QAbstractSeries::SeriesTypeStackedBar:
+ case QAbstractSeries::SeriesTypeBoxPlot:
+ if (axis->orientation() == Qt::Horizontal)
+ populateCategories(qobject_cast<QBarCategoryAxis *>(axis));
+ break;
+ default:
+ qWarning() << "Unexpected series type";
+ break;
+ }
+ }
+ }
+}
+
+QAbstractAxis::AxisType QAbstractBarSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
+{
+ Q_Q(const QAbstractBarSeries);
+
+ switch (q->type()) {
+ case QAbstractSeries::SeriesTypeHorizontalBar:
+ case QAbstractSeries::SeriesTypeHorizontalPercentBar:
+ case QAbstractSeries::SeriesTypeHorizontalStackedBar:
+ if (orientation == Qt::Vertical)
+ return QAbstractAxis::AxisTypeBarCategory;
+ break;
+ case QAbstractSeries::SeriesTypeBar:
+ case QAbstractSeries::SeriesTypePercentBar:
+ case QAbstractSeries::SeriesTypeStackedBar:
+ case QAbstractSeries::SeriesTypeBoxPlot:
+ if (orientation == Qt::Horizontal)
+ return QAbstractAxis::AxisTypeBarCategory;
+ break;
+ default:
+ qWarning() << "Unexpected series type";
+ break;
+ }
+ return QAbstractAxis::AxisTypeValue;
+
+}
+
+void QAbstractBarSeriesPrivate::populateCategories(QBarCategoryAxis *axis)
+{
+ QStringList categories;
+ if (axis->categories().isEmpty()) {
+ for (int i(1); i < categoryCount() + 1; i++)
+ categories << presenter()->numberToString(i);
+ axis->append(categories);
+ }
+}
+
+QAbstractAxis* QAbstractBarSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const
+{
+ if (defaultAxisType(orientation) == QAbstractAxis::AxisTypeBarCategory)
+ return new QBarCategoryAxis;
+ else
+ return new QValueAxis;
+}
+
+void QAbstractBarSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
+{
+ m_blockBarUpdate = true; // Ensures that the bars are not updated before the theme is ready
+
+ const QList<QGradient> gradients = theme->seriesGradients();
+
+ qreal takeAtPos = 0.5;
+ qreal step = 0.2;
+ if (m_barSets.count() > 1) {
+ step = 1.0 / (qreal) m_barSets.count();
+ if (m_barSets.count() % gradients.count())
+ step *= gradients.count();
+ else
+ step *= (gradients.count() - 1);
+ }
+
+ for (int i(0); i < m_barSets.count(); i++) {
+ int colorIndex = (index + i) % gradients.count();
+ if (i > 0 && i %gradients.count() == 0) {
+ // There is no dedicated base color for each sets, generate more colors
+ takeAtPos += step;
+ if (takeAtPos == 1.0)
+ takeAtPos += step;
+ takeAtPos -= (int) takeAtPos;
+ }
+ if (forced || QChartPrivate::defaultBrush() == m_barSets.at(i)->d_ptr->m_brush)
+ m_barSets.at(i)->setBrush(ChartThemeManager::colorAt(gradients.at(colorIndex), takeAtPos));
+
+ // Pick label color from the opposite end of the gradient.
+ // 0.3 as a boundary seems to work well.
+ if (forced || QChartPrivate::defaultBrush() == m_barSets.at(i)->d_ptr->m_labelBrush) {
+ if (takeAtPos < 0.3)
+ m_barSets.at(i)->setLabelBrush(ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 1));
+ else
+ m_barSets.at(i)->setLabelBrush(ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0));
+ }
+ if (forced || QChartPrivate::defaultPen() == m_barSets.at(i)->d_ptr->m_pen) {
+ QColor c = ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0.0);
+ m_barSets.at(i)->setPen(c);
+ }
+ }
+ m_blockBarUpdate = false;
+ emit updatedBars();
+}
+
+void QAbstractBarSeriesPrivate::initializeAnimations(QChart::AnimationOptions options)
+{
+ AbstractBarChartItem *bar = static_cast<AbstractBarChartItem *>(m_item.data());
+ Q_ASSERT(bar);
+ if (bar->animation())
+ bar->animation()->stopAndDestroyLater();
+
+ if (options.testFlag(QChart::SeriesAnimations))
+ bar->setAnimation(new BarAnimation(bar));
+ else
+ bar->setAnimation(0);
+ QAbstractSeriesPrivate::initializeAnimations(options);
+}
+
+#include "moc_qabstractbarseries.cpp"
+#include "moc_qabstractbarseries_p.cpp"
+
+QT_CHARTS_END_NAMESPACE