Merge remote-tracking branch 'origin/5.6' into 5.7

Conflicts:
	.qmake.conf
	README
	src/charts/qchartglobal.h
	tests/auto/chartdataset/tst_chartdataset.cpp
	tests/auto/domain/tst_domain.cpp

Change-Id: Ib4e01f2646d87b691c7b2f8bee4ed1f5521e4f6d
This commit is contained in:
Liang Qi 2016-08-23 08:23:42 +02:00
commit d352d707f9
27 changed files with 291 additions and 207 deletions

2
README
View File

@ -1,5 +1,5 @@
--------------- ---------------
Qt Charts 5.7.0 Qt Charts
--------------- ---------------
Qt Charts module provides a set of easy to use chart components. It uses Qt Charts module provides a set of easy to use chart components. It uses

25
dist/changes-2.1.2 vendored Normal file
View File

@ -0,0 +1,25 @@
Qt Charts 2.1.2
Fixed issues
------------
- [QTBUG-54914] Make OpenGL accelerated series obey series visibility
- [QTBUG-54803] Ensure the chart is drawn whenever the render node is recreated
- [QTBUG-55098] Fix partial blurriness of the gl accelerated graph
- [QTBUG-54763] Clarify QML BarSet::values documentation
- [QTBUG-53073] Fix VXYModelMapper documentation
- [QTBUG-52654] Print console warning when invalid row/column used in model mapper
- [QTBUG-52086] Fix BarSet value rounding
- [QTBUG-53949] Fix axis minimum height in case of multiple axes on same orientation
- [QTBUG-54401] Fix issues with reverse axes
- QChart mapping functions returned unreversed values
- Bounding regions of series were incorrect
- Mouse events gave wrong positions
- Chart scrolling and zooming didn't account for reversed axes
- [QTBUG-55278] Disconnect boxplot series from chart's dataset correctly
- [QTBUG-53337] Fix setting axis color properties to black for the first time
- [QTBUG-55348] Disconnect a series from ChartItem when it is removed from a chart
- Fix logarithmic axis for area chart
Fixed examples
--------------
- [QTBUG-54492] Fix resize handling in Callout example

View File

@ -32,15 +32,17 @@
#include <QtGui/QFontMetrics> #include <QtGui/QFontMetrics>
#include <QtWidgets/QGraphicsSceneMouseEvent> #include <QtWidgets/QGraphicsSceneMouseEvent>
#include <QtGui/QMouseEvent> #include <QtGui/QMouseEvent>
#include <QtCharts/QChart>
Callout::Callout(QGraphicsItem * parent): Callout::Callout(QChart *chart):
QGraphicsItem(parent) QGraphicsItem(chart),
m_chart(chart)
{ {
} }
QRectF Callout::boundingRect() const QRectF Callout::boundingRect() const
{ {
QPointF anchor = mapFromParent(m_anchor); QPointF anchor = mapFromParent(m_chart->mapToPosition(m_anchor));
QRectF rect; QRectF rect;
rect.setLeft(qMin(m_rect.left(), anchor.x())); rect.setLeft(qMin(m_rect.left(), anchor.x()));
rect.setRight(qMax(m_rect.right(), anchor.x())); rect.setRight(qMax(m_rect.right(), anchor.x()));
@ -56,7 +58,7 @@ void Callout::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, Q
QPainterPath path; QPainterPath path;
path.addRoundedRect(m_rect, 5, 5); path.addRoundedRect(m_rect, 5, 5);
QPointF anchor = mapFromParent(m_anchor); QPointF anchor = mapFromParent(m_chart->mapToPosition(m_anchor));
if (!m_rect.contains(anchor)) { if (!m_rect.contains(anchor)) {
QPointF point1, point2; QPointF point1, point2;
@ -88,7 +90,7 @@ void Callout::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, Q
point2.setY(y2); point2.setY(y2);
path.moveTo(point1); path.moveTo(point1);
path.lineTo(mapFromParent(m_anchor)); path.lineTo(anchor);
path.lineTo(point2); path.lineTo(point2);
path = path.simplified(); path = path.simplified();
} }
@ -126,3 +128,9 @@ void Callout::setAnchor(QPointF point)
{ {
m_anchor = point; m_anchor = point;
} }
void Callout::updateGeometry()
{
prepareGeometryChange();
setPos(m_chart->mapToPosition(m_anchor) + QPoint(10, -50));
}

View File

@ -30,6 +30,7 @@
#ifndef CALLOUT_H #ifndef CALLOUT_H
#define CALLOUT_H #define CALLOUT_H
#include <QtCharts/QChartGlobal>
#include <QtWidgets/QGraphicsItem> #include <QtWidgets/QGraphicsItem>
#include <QtGui/QFont> #include <QtGui/QFont>
@ -37,13 +38,20 @@ QT_BEGIN_NAMESPACE
class QGraphicsSceneMouseEvent; class QGraphicsSceneMouseEvent;
QT_END_NAMESPACE QT_END_NAMESPACE
QT_CHARTS_BEGIN_NAMESPACE
class QChart;
QT_CHARTS_END_NAMESPACE
QT_CHARTS_USE_NAMESPACE
class Callout : public QGraphicsItem class Callout : public QGraphicsItem
{ {
public: public:
Callout(QGraphicsItem * parent = 0); Callout(QChart *parent);
void setText(const QString &text); void setText(const QString &text);
void setAnchor(QPointF point); void setAnchor(QPointF point);
void updateGeometry();
QRectF boundingRect() const; QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget);
@ -58,6 +66,7 @@ private:
QRectF m_rect; QRectF m_rect;
QPointF m_anchor; QPointF m_anchor;
QFont m_font; QFont m_font;
QChart *m_chart;
}; };
#endif // CALLOUT_H #endif // CALLOUT_H

View File

@ -98,6 +98,8 @@ void View::resizeEvent(QResizeEvent *event)
m_chart->resize(event->size()); m_chart->resize(event->size());
m_coordX->setPos(m_chart->size().width()/2 - 50, m_chart->size().height() - 20); m_coordX->setPos(m_chart->size().width()/2 - 50, m_chart->size().height() - 20);
m_coordY->setPos(m_chart->size().width()/2 + 50, m_chart->size().height() - 20); m_coordY->setPos(m_chart->size().width()/2 + 50, m_chart->size().height() - 20);
foreach (Callout *callout, m_callouts)
callout->updateGeometry();
} }
QGraphicsView::resizeEvent(event); QGraphicsView::resizeEvent(event);
} }
@ -111,6 +113,7 @@ void View::mouseMoveEvent(QMouseEvent *event)
void View::keepCallout() void View::keepCallout()
{ {
m_callouts.append(m_tooltip);
m_tooltip = new Callout(m_chart); m_tooltip = new Callout(m_chart);
} }
@ -121,10 +124,9 @@ void View::tooltip(QPointF point, bool state)
if (state) { if (state) {
m_tooltip->setText(QString("X: %1 \nY: %2 ").arg(point.x()).arg(point.y())); m_tooltip->setText(QString("X: %1 \nY: %2 ").arg(point.x()).arg(point.y()));
QXYSeries *series = qobject_cast<QXYSeries *>(sender()); m_tooltip->setAnchor(point);
m_tooltip->setAnchor(m_chart->mapToPosition(point, series));
m_tooltip->setPos(m_chart->mapToPosition(point, series) + QPoint(10, -50));
m_tooltip->setZValue(11); m_tooltip->setZValue(11);
m_tooltip->updateGeometry();
m_tooltip->show(); m_tooltip->show();
} else { } else {
m_tooltip->hide(); m_tooltip->hide();

View File

@ -66,6 +66,7 @@ private:
QGraphicsSimpleTextItem *m_coordY; QGraphicsSimpleTextItem *m_coordY;
QChart *m_chart; QChart *m_chart;
Callout *m_tooltip; Callout *m_tooltip;
QList<Callout *> m_callouts;
}; };
#endif #endif

View File

@ -33,6 +33,7 @@
#include <QtCharts/QLineSeries> #include <QtCharts/QLineSeries>
#include <private/chartpresenter_p.h> #include <private/chartpresenter_p.h>
#include <private/abstractdomain_p.h> #include <private/abstractdomain_p.h>
#include <private/chartdataset_p.h>
#include <QtGui/QPainter> #include <QtGui/QPainter>
#include <QtWidgets/QGraphicsSceneMouseEvent> #include <QtWidgets/QGraphicsSceneMouseEvent>
#include <QtCore/QDebug> #include <QtCore/QDebug>
@ -171,18 +172,26 @@ void AreaChartItem::handleUpdated()
void AreaChartItem::handleDomainUpdated() void AreaChartItem::handleDomainUpdated()
{ {
if (m_upper) { fixEdgeSeriesDomain(m_upper);
AbstractDomain* d = m_upper->domain(); fixEdgeSeriesDomain(m_lower);
d->setSize(domain()->size());
d->setRange(domain()->minX(),domain()->maxX(),domain()->minY(),domain()->maxY());
m_upper->handleDomainUpdated();
} }
if (m_lower) { void AreaChartItem::fixEdgeSeriesDomain(LineChartItem *edgeSeries)
AbstractDomain* d = m_lower->domain(); {
d->setSize(domain()->size()); if (edgeSeries) {
d->setRange(domain()->minX(),domain()->maxX(),domain()->minY(),domain()->maxY()); AbstractDomain* mainDomain = domain();
m_lower->handleDomainUpdated(); AbstractDomain* edgeDomain = edgeSeries->domain();
if (edgeDomain->type() != mainDomain->type()) {
// Change the domain of edge series to the same type as the area series
edgeDomain = dataSet()->createDomain(mainDomain->type());
edgeSeries->seriesPrivate()->setDomain(edgeDomain);
}
edgeDomain->setSize(mainDomain->size());
edgeDomain->setRange(mainDomain->minX(), mainDomain->maxX(), mainDomain->minY(), mainDomain->maxY());
edgeDomain->setReverseX(mainDomain->isReverseX());
edgeDomain->setReverseY(mainDomain->isReverseY());
edgeSeries->handleDomainUpdated();
} }
} }
@ -199,8 +208,6 @@ void AreaChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt
else else
painter->setClipRect(clipRect); painter->setClipRect(clipRect);
reversePainter(painter, clipRect);
painter->drawPath(m_path); painter->drawPath(m_path);
if (m_pointsVisible) { if (m_pointsVisible) {
painter->setPen(m_pointPen); painter->setPen(m_pointPen);
@ -209,8 +216,6 @@ void AreaChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt
painter->drawPoints(m_lower->geometryPoints()); painter->drawPoints(m_lower->geometryPoints());
} }
reversePainter(painter, clipRect);
// Draw series point label // Draw series point label
if (m_pointLabelsVisible) { if (m_pointLabelsVisible) {
static const QString xPointTag(QLatin1String("@xPoint")); static const QString xPointTag(QLatin1String("@xPoint"));
@ -239,17 +244,9 @@ void AreaChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt
// Position text in relation to the point // Position text in relation to the point
int pointLabelWidth = fm.width(pointLabel); int pointLabelWidth = fm.width(pointLabel);
QPointF position(m_upper->geometryPoints().at(i)); QPointF position(m_upper->geometryPoints().at(i));
if (!seriesPrivate()->reverseXAxis())
position.setX(position.x() - pointLabelWidth / 2); position.setX(position.x() - pointLabelWidth / 2);
else
position.setX(domain()->size().width() - position.x() - pointLabelWidth / 2);
if (!seriesPrivate()->reverseYAxis()) {
position.setY(position.y() - m_series->upperSeries()->pen().width() / 2 position.setY(position.y() - m_series->upperSeries()->pen().width() / 2
- labelOffset); - labelOffset);
} else {
position.setY(domain()->size().height() - position.y()
- m_series->upperSeries()->pen().width() / 2 - labelOffset);
}
painter->drawText(position, pointLabel); painter->drawText(position, pointLabel);
} }
} }
@ -265,17 +262,9 @@ void AreaChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt
// Position text in relation to the point // Position text in relation to the point
int pointLabelWidth = fm.width(pointLabel); int pointLabelWidth = fm.width(pointLabel);
QPointF position(m_lower->geometryPoints().at(i)); QPointF position(m_lower->geometryPoints().at(i));
if (!seriesPrivate()->reverseXAxis())
position.setX(position.x() - pointLabelWidth / 2); position.setX(position.x() - pointLabelWidth / 2);
else
position.setX(domain()->size().width() - position.x() - pointLabelWidth / 2);
if (!seriesPrivate()->reverseYAxis()) {
position.setY(position.y() - m_series->lowerSeries()->pen().width() / 2 position.setY(position.y() - m_series->lowerSeries()->pen().width() / 2
- labelOffset); - labelOffset);
} else {
position.setY(domain()->size().height() - position.y()
- m_series->lowerSeries()->pen().width() / 2 - labelOffset);
}
painter->drawText(position, pointLabel); painter->drawText(position, pointLabel);
} }
} }

View File

@ -87,6 +87,8 @@ public Q_SLOTS:
void handleDomainUpdated(); void handleDomainUpdated();
private: private:
void fixEdgeSeriesDomain(LineChartItem *edgeSeries);
QAreaSeries *m_series; QAreaSeries *m_series;
LineChartItem *m_upper; LineChartItem *m_upper;
LineChartItem *m_lower; LineChartItem *m_lower;

View File

@ -523,7 +523,7 @@ QPen QAbstractAxis::linePen() const
void QAbstractAxis::setLinePenColor(QColor color) void QAbstractAxis::setLinePenColor(QColor color)
{ {
QPen p = linePen(); QPen p = linePen();
if (p.color() != color) { if (p.color() != color || d_ptr->m_axisPen == QChartPrivate::defaultPen()) {
p.setColor(color); p.setColor(color);
setLinePen(p); setLinePen(p);
emit colorChanged(color); emit colorChanged(color);
@ -618,31 +618,31 @@ QPen QAbstractAxis::minorGridLinePen() const
void QAbstractAxis::setGridLineColor(const QColor &color) void QAbstractAxis::setGridLineColor(const QColor &color)
{ {
QPen pen = gridLinePen(); QPen pen = gridLinePen();
if (color != pen.color()) { if (color != pen.color() || d_ptr->m_gridLinePen == QChartPrivate::defaultPen()) {
pen.setColor(color); pen.setColor(color);
d_ptr->m_gridLinePen = pen; setGridLinePen(pen);
emit gridLineColorChanged(color); emit gridLineColorChanged(color);
} }
} }
QColor QAbstractAxis::gridLineColor() QColor QAbstractAxis::gridLineColor()
{ {
return d_ptr->m_gridLinePen.color(); return gridLinePen().color();
} }
void QAbstractAxis::setMinorGridLineColor(const QColor &color) void QAbstractAxis::setMinorGridLineColor(const QColor &color)
{ {
QPen pen = minorGridLinePen(); QPen pen = minorGridLinePen();
if (color != pen.color()) { if (color != pen.color() || d_ptr->m_minorGridLinePen == QChartPrivate::defaultPen()) {
pen.setColor(color); pen.setColor(color);
d_ptr->m_minorGridLinePen = pen; setMinorGridLinePen(pen);
emit minorGridLineColorChanged(color); emit minorGridLineColorChanged(color);
} }
} }
QColor QAbstractAxis::minorGridLineColor() QColor QAbstractAxis::minorGridLineColor()
{ {
return d_ptr->m_minorGridLinePen.color(); return minorGridLinePen().color();
} }
void QAbstractAxis::setLabelsVisible(bool visible) void QAbstractAxis::setLabelsVisible(bool visible)
@ -717,7 +717,7 @@ int QAbstractAxis::labelsAngle() const
void QAbstractAxis::setLabelsColor(QColor color) void QAbstractAxis::setLabelsColor(QColor color)
{ {
QBrush b = labelsBrush(); QBrush b = labelsBrush();
if (b.color() != color) { if (b.color() != color || d_ptr->m_labelsBrush == QChartPrivate::defaultBrush()) {
b.setColor(color); b.setColor(color);
setLabelsBrush(b); setLabelsBrush(b);
emit labelsColorChanged(color); emit labelsColorChanged(color);
@ -860,7 +860,7 @@ QBrush QAbstractAxis::shadesBrush() const
void QAbstractAxis::setShadesColor(QColor color) void QAbstractAxis::setShadesColor(QColor color)
{ {
QBrush b = shadesBrush(); QBrush b = shadesBrush();
if (b.color() != color) { if (b.color() != color || d_ptr->m_shadesBrush == QChartPrivate::defaultBrush()) {
b.setColor(color); b.setColor(color);
setShadesBrush(b); setShadesBrush(b);
emit shadesColorChanged(color); emit shadesColorChanged(color);
@ -874,8 +874,8 @@ QColor QAbstractAxis::shadesColor() const
void QAbstractAxis::setShadesBorderColor(QColor color) void QAbstractAxis::setShadesBorderColor(QColor color)
{ {
QPen p = d_ptr->m_shadesPen; QPen p = shadesPen();
if (p.color() != color) { if (p.color() != color || d_ptr->m_shadesPen == QChartPrivate::defaultPen()) {
p.setColor(color); p.setColor(color);
setShadesPen(p); setShadesPen(p);
emit shadesColorChanged(color); emit shadesColorChanged(color);

View File

@ -535,9 +535,10 @@ void QBoxPlotSeriesPrivate::handleSeriesRemove(QAbstractSeries *series)
QBoxPlotSeries *removedSeries = static_cast<QBoxPlotSeries *>(series); QBoxPlotSeries *removedSeries = static_cast<QBoxPlotSeries *>(series);
if (q == removedSeries && m_animation) { if (q == removedSeries) {
if (m_animation)
m_animation->stopAll(); m_animation->stopAll();
QObject::disconnect(m_chart->d_ptr->m_dataset, 0, removedSeries->d_func(), 0); QObject::disconnect(m_chart->d_ptr->m_dataset, 0, this, 0);
} }
// Test if series removed is me, then don't do anything // Test if series removed is me, then don't do anything

View File

@ -81,6 +81,8 @@ public:
GLXYSeriesDataManager *glXYSeriesDataManager() { return m_glXYSeriesDataManager; } GLXYSeriesDataManager *glXYSeriesDataManager() { return m_glXYSeriesDataManager; }
AbstractDomain* createDomain(AbstractDomain::DomainType type);
Q_SIGNALS: Q_SIGNALS:
void axisAdded(QAbstractAxis* axis); void axisAdded(QAbstractAxis* axis);
void axisRemoved(QAbstractAxis* axis); void axisRemoved(QAbstractAxis* axis);
@ -92,7 +94,6 @@ private:
void createAxes(QAbstractAxis::AxisTypes type, Qt::Orientation orientation); void createAxes(QAbstractAxis::AxisTypes type, Qt::Orientation orientation);
QAbstractAxis *createAxis(QAbstractAxis::AxisType type, Qt::Orientation orientation); QAbstractAxis *createAxis(QAbstractAxis::AxisType type, Qt::Orientation orientation);
AbstractDomain::DomainType selectDomain(QList<QAbstractAxis* > axes); AbstractDomain::DomainType selectDomain(QList<QAbstractAxis* > axes);
AbstractDomain* createDomain(AbstractDomain::DomainType type);
void deleteAllAxes(); void deleteAllAxes();
void deleteAllSeries(); void deleteAllSeries();
void findMinMaxForSeries(QList<QAbstractSeries *> series,Qt::Orientations orientation, qreal &min, qreal &max); void findMinMaxForSeries(QList<QAbstractSeries *> series,Qt::Orientations orientation, qreal &min, qreal &max);

View File

@ -52,19 +52,6 @@ void ChartItem::handleDomainUpdated()
qWarning() << __FUNCTION__<< "Slot not implemented"; qWarning() << __FUNCTION__<< "Slot not implemented";
} }
void ChartItem::reversePainter(QPainter *painter, const QRectF &clipRect)
{
if (m_series->reverseXAxis()) {
painter->translate(clipRect.width(), 0);
painter->scale(-1, 1);
}
if (m_series->reverseYAxis()) {
painter->translate(0, clipRect.height());
painter->scale(1, -1);
}
}
#include "moc_chartitem_p.cpp" #include "moc_chartitem_p.cpp"
QT_CHARTS_END_NAMESPACE QT_CHARTS_END_NAMESPACE

View File

@ -55,7 +55,6 @@ public:
public Q_SLOTS: public Q_SLOTS:
virtual void handleDomainUpdated(); virtual void handleDomainUpdated();
void reversePainter(QPainter *painter, const QRectF &clipRect);
QAbstractSeriesPrivate* seriesPrivate() const {return m_series;} QAbstractSeriesPrivate* seriesPrivate() const {return m_series;}
protected: protected:

View File

@ -147,6 +147,7 @@ void ChartPresenter::handleSeriesRemoved(QAbstractSeries *series)
ChartItem *chart = series->d_ptr->m_item.take(); ChartItem *chart = series->d_ptr->m_item.take();
chart->hide(); chart->hide();
chart->disconnect(); chart->disconnect();
series->disconnect(chart);
chart->deleteLater(); chart->deleteLater();
if (chart->animation()) if (chart->animation())
chart->animation()->stopAndDestroyLater(); chart->animation()->stopAndDestroyLater();

View File

@ -45,7 +45,9 @@ AbstractDomain::AbstractDomain(QObject *parent)
m_zoomResetMinX(0), m_zoomResetMinX(0),
m_zoomResetMaxX(0), m_zoomResetMaxX(0),
m_zoomResetMinY(0), m_zoomResetMinY(0),
m_zoomResetMaxY(0) m_zoomResetMaxY(0),
m_reverseX(false),
m_reverseY(false)
{ {
} }
@ -114,15 +116,6 @@ bool AbstractDomain::isEmpty() const
return qFuzzyCompare(spanX(), 0) || qFuzzyCompare(spanY(), 0) || m_size.isEmpty(); return qFuzzyCompare(spanX(), 0) || qFuzzyCompare(spanY(), 0) || m_size.isEmpty();
} }
QPointF AbstractDomain::calculateDomainPoint(const QPointF &point) const
{
const qreal deltaX = m_size.width() / (m_maxX - m_minX);
const qreal deltaY = m_size.height() / (m_maxY - m_minY);
qreal x = point.x() / deltaX + m_minX;
qreal y = (point.y() - m_size.height()) / (-deltaY) + m_minY;
return QPointF(x, y);
}
// handlers // handlers
void AbstractDomain::handleVerticalAxisRangeChanged(qreal min, qreal max) void AbstractDomain::handleVerticalAxisRangeChanged(qreal min, qreal max)
@ -135,6 +128,18 @@ void AbstractDomain::handleHorizontalAxisRangeChanged(qreal min, qreal max)
setRangeX(min, max); setRangeX(min, max);
} }
void AbstractDomain::handleReverseXChanged(bool reverse)
{
m_reverseX = reverse;
emit updated();
}
void AbstractDomain::handleReverseYChanged(bool reverse)
{
m_reverseY = reverse;
emit updated();
}
void AbstractDomain::blockRangeSignals(bool block) void AbstractDomain::blockRangeSignals(bool block)
{ {
if (m_signalsBlocked!=block) { if (m_signalsBlocked!=block) {
@ -207,11 +212,17 @@ bool AbstractDomain::attachAxis(QAbstractAxis *axis)
if (axis->orientation() == Qt::Vertical) { if (axis->orientation() == Qt::Vertical) {
QObject::connect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleVerticalAxisRangeChanged(qreal,qreal))); QObject::connect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleVerticalAxisRangeChanged(qreal,qreal)));
QObject::connect(this, SIGNAL(rangeVerticalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal))); QObject::connect(this, SIGNAL(rangeVerticalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
QObject::connect(axis, &QAbstractAxis::reverseChanged,
this, &AbstractDomain::handleReverseYChanged);
m_reverseY = axis->isReverse();
} }
if (axis->orientation() == Qt::Horizontal) { if (axis->orientation() == Qt::Horizontal) {
QObject::connect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleHorizontalAxisRangeChanged(qreal,qreal))); QObject::connect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleHorizontalAxisRangeChanged(qreal,qreal)));
QObject::connect(this, SIGNAL(rangeHorizontalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal))); QObject::connect(this, SIGNAL(rangeHorizontalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
QObject::connect(axis, &QAbstractAxis::reverseChanged,
this, &AbstractDomain::handleReverseXChanged);
m_reverseX = axis->isReverse();
} }
return true; return true;
@ -222,11 +233,15 @@ bool AbstractDomain::detachAxis(QAbstractAxis *axis)
if (axis->orientation() == Qt::Vertical) { if (axis->orientation() == Qt::Vertical) {
QObject::disconnect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleVerticalAxisRangeChanged(qreal,qreal))); QObject::disconnect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleVerticalAxisRangeChanged(qreal,qreal)));
QObject::disconnect(this, SIGNAL(rangeVerticalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal))); QObject::disconnect(this, SIGNAL(rangeVerticalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
QObject::disconnect(axis, &QAbstractAxis::reverseChanged,
this, &AbstractDomain::handleReverseYChanged);
} }
if (axis->orientation() == Qt::Horizontal) { if (axis->orientation() == Qt::Horizontal) {
QObject::disconnect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleHorizontalAxisRangeChanged(qreal,qreal))); QObject::disconnect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleHorizontalAxisRangeChanged(qreal,qreal)));
QObject::disconnect(this, SIGNAL(rangeHorizontalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal))); QObject::disconnect(this, SIGNAL(rangeHorizontalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
QObject::disconnect(axis, &QAbstractAxis::reverseChanged,
this, &AbstractDomain::handleReverseXChanged);
} }
return true; return true;
@ -269,6 +284,22 @@ void AbstractDomain::adjustLogDomainRanges(qreal &min, qreal &max)
} }
} }
// This function fixes the zoom rect based on axis reversals
QRectF AbstractDomain::fixZoomRect(const QRectF &rect)
{
QRectF fixRect = rect;
if (m_reverseX || m_reverseY) {
QPointF center = rect.center();
if (m_reverseX)
center.setX(m_size.width() - center.x());
if (m_reverseY)
center.setY(m_size.height() - center.y());
fixRect.moveCenter(QPointF(center.x(), center.y()));
}
return fixRect;
}
#include "moc_abstractdomain_p.cpp" #include "moc_abstractdomain_p.cpp"

View File

@ -111,6 +111,12 @@ public:
static void looseNiceNumbers(qreal &min, qreal &max, int &ticksCount); static void looseNiceNumbers(qreal &min, qreal &max, int &ticksCount);
static qreal niceNumber(qreal x, bool ceiling); static qreal niceNumber(qreal x, bool ceiling);
void setReverseX(bool reverse) { m_reverseX = reverse; }
void setReverseY(bool reverse) { m_reverseY = reverse; }
bool isReverseX() const { return m_reverseX; }
bool isReverseY() const { return m_reverseY; }
Q_SIGNALS: Q_SIGNALS:
void updated(); void updated();
void rangeHorizontalChanged(qreal min, qreal max); void rangeHorizontalChanged(qreal min, qreal max);
@ -119,9 +125,12 @@ Q_SIGNALS:
public Q_SLOTS: public Q_SLOTS:
void handleVerticalAxisRangeChanged(qreal min,qreal max); void handleVerticalAxisRangeChanged(qreal min,qreal max);
void handleHorizontalAxisRangeChanged(qreal min,qreal max); void handleHorizontalAxisRangeChanged(qreal min,qreal max);
void handleReverseXChanged(bool reverse);
void handleReverseYChanged(bool reverse);
protected: protected:
void adjustLogDomainRanges(qreal &min, qreal &max); void adjustLogDomainRanges(qreal &min, qreal &max);
QRectF fixZoomRect(const QRectF &rect);
qreal m_minX; qreal m_minX;
qreal m_maxX; qreal m_maxX;
@ -134,6 +143,8 @@ protected:
qreal m_zoomResetMaxX; qreal m_zoomResetMaxX;
qreal m_zoomResetMinY; qreal m_zoomResetMinY;
qreal m_zoomResetMaxY; qreal m_zoomResetMaxY;
bool m_reverseX;
bool m_reverseY;
}; };
QT_CHARTS_END_NAMESPACE QT_CHARTS_END_NAMESPACE

View File

@ -89,15 +89,16 @@ void LogXLogYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
void LogXLogYDomain::zoomIn(const QRectF &rect) void LogXLogYDomain::zoomIn(const QRectF &rect)
{ {
storeZoomReset(); storeZoomReset();
qreal logLeftX = rect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX; QRectF fixedRect = fixZoomRect(rect);
qreal logRightX = rect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX; qreal logLeftX = fixedRect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
qreal logRightX = fixedRect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
qreal leftX = qPow(m_logBaseX, logLeftX); qreal leftX = qPow(m_logBaseX, logLeftX);
qreal rightX = qPow(m_logBaseX, logRightX); qreal rightX = qPow(m_logBaseX, logRightX);
qreal minX = leftX < rightX ? leftX : rightX; qreal minX = leftX < rightX ? leftX : rightX;
qreal maxX = leftX > rightX ? leftX : rightX; qreal maxX = leftX > rightX ? leftX : rightX;
qreal logLeftY = m_logRightY - rect.bottom() * (m_logRightY - m_logLeftY) / m_size.height(); qreal logLeftY = m_logRightY - fixedRect.bottom() * (m_logRightY - m_logLeftY) / m_size.height();
qreal logRightY = m_logRightY - rect.top() * (m_logRightY - m_logLeftY) / m_size.height(); qreal logRightY = m_logRightY - fixedRect.top() * (m_logRightY - m_logLeftY) / m_size.height();
qreal leftY = qPow(m_logBaseY, logLeftY); qreal leftY = qPow(m_logBaseY, logLeftY);
qreal rightY = qPow(m_logBaseY, logRightY); qreal rightY = qPow(m_logBaseY, logRightY);
qreal minY = leftY < rightY ? leftY : rightY; qreal minY = leftY < rightY ? leftY : rightY;
@ -109,8 +110,9 @@ void LogXLogYDomain::zoomIn(const QRectF &rect)
void LogXLogYDomain::zoomOut(const QRectF &rect) void LogXLogYDomain::zoomOut(const QRectF &rect)
{ {
storeZoomReset(); storeZoomReset();
const qreal factorX = m_size.width() / rect.width(); QRectF fixedRect = fixZoomRect(rect);
const qreal factorY = m_size.height() / rect.height(); const qreal factorX = m_size.width() / fixedRect.width();
const qreal factorY = m_size.height() / fixedRect.height();
qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 - factorX); qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 - factorX);
qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 + factorX); qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 + factorX);
@ -131,6 +133,11 @@ void LogXLogYDomain::zoomOut(const QRectF &rect)
void LogXLogYDomain::move(qreal dx, qreal dy) void LogXLogYDomain::move(qreal dx, qreal dy)
{ {
if (m_reverseX)
dx = -dx;
if (m_reverseY)
dy = -dy;
qreal stepX = dx * qAbs(m_logRightX - m_logLeftX) / m_size.width(); qreal stepX = dx * qAbs(m_logRightX - m_logLeftX) / m_size.width();
qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX); qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX);
qreal rightX = qPow(m_logBaseX, m_logRightX + stepX); qreal rightX = qPow(m_logBaseX, m_logRightX + stepX);
@ -153,23 +160,25 @@ QPointF LogXLogYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) c
qreal x(0); qreal x(0);
qreal y(0); qreal y(0);
if (point.x() > 0 && point.y() > 0) { if (point.x() > 0 && point.y() > 0) {
x = (std::log10(point.x()) / std::log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX; x = ((std::log10(point.x()) / std::log10(m_logBaseX)) - m_logLeftX) * deltaX;
y = (std::log10(point.y()) / std::log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height(); y = ((std::log10(point.y()) / std::log10(m_logBaseY)) - m_logLeftY) * deltaY;
ok = true; ok = true;
} else { } else {
qWarning() << "Logarithms of zero and negative values are undefined."; qWarning() << "Logarithms of zero and negative values are undefined.";
ok = false; ok = false;
if (point.x() > 0) if (point.x() > 0)
x = (std::log10(point.x()) / std::log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX; x = ((std::log10(point.x()) / std::log10(m_logBaseX)) - m_logLeftX) * deltaX;
else else
x = 0; x = 0;
if (point.y() > 0) { if (point.y() > 0)
y = (std::log10(point.y()) / std::log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY y = ((std::log10(point.y()) / std::log10(m_logBaseY)) - m_logLeftY) * deltaY;
+ m_size.height(); else
} else { y = 0;
y = m_size.height();
}
} }
if (m_reverseX)
x = m_size.width() - x;
if (!m_reverseY)
y = m_size.height() - y;
return QPointF(x, y); return QPointF(x, y);
} }
@ -183,8 +192,12 @@ QVector<QPointF> LogXLogYDomain::calculateGeometryPoints(const QVector<QPointF>
for (int i = 0; i < vector.count(); ++i) { for (int i = 0; i < vector.count(); ++i) {
if (vector[i].x() > 0 && vector[i].y() > 0) { if (vector[i].x() > 0 && vector[i].y() > 0) {
qreal x = (std::log10(vector[i].x()) / std::log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX; qreal x = ((std::log10(vector[i].x()) / std::log10(m_logBaseX)) - m_logLeftX) * deltaX;
qreal y = (std::log10(vector[i].y()) / std::log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height(); if (m_reverseX)
x = m_size.width() - x;
qreal y = ((std::log10(vector[i].y()) / std::log10(m_logBaseY)) - m_logLeftY) * deltaY;
if (!m_reverseY)
y = m_size.height() - y;
result[i].setX(x); result[i].setX(x);
result[i].setY(y); result[i].setY(y);
} else { } else {
@ -199,8 +212,10 @@ QPointF LogXLogYDomain::calculateDomainPoint(const QPointF &point) const
{ {
const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX); const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX);
const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY); const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
qreal x = qPow(m_logBaseX, m_logLeftX + point.x() / deltaX); qreal x = m_reverseX ? (m_size.width() - point.x()) : point.x();
qreal y = qPow(m_logBaseY, m_logLeftY + (m_size.height() - point.y()) / deltaY); x = qPow(m_logBaseX, m_logLeftX + x / deltaX);
qreal y = m_reverseY ? point.y() : (m_size.height() - point.y());
y = qPow(m_logBaseY, m_logLeftY + y / deltaY);
return QPointF(x, y); return QPointF(x, y);
} }

View File

@ -81,8 +81,9 @@ void LogXYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
void LogXYDomain::zoomIn(const QRectF &rect) void LogXYDomain::zoomIn(const QRectF &rect)
{ {
storeZoomReset(); storeZoomReset();
qreal logLeftX = rect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX; QRectF fixedRect = fixZoomRect(rect);
qreal logRightX = rect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX; qreal logLeftX = fixedRect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
qreal logRightX = fixedRect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
qreal leftX = qPow(m_logBaseX, logLeftX); qreal leftX = qPow(m_logBaseX, logLeftX);
qreal rightX = qPow(m_logBaseX, logRightX); qreal rightX = qPow(m_logBaseX, logRightX);
qreal minX = leftX < rightX ? leftX : rightX; qreal minX = leftX < rightX ? leftX : rightX;
@ -92,8 +93,8 @@ void LogXYDomain::zoomIn(const QRectF &rect)
qreal minY = m_minY; qreal minY = m_minY;
qreal maxY = m_maxY; qreal maxY = m_maxY;
minY = maxY - dy * rect.bottom(); minY = maxY - dy * fixedRect.bottom();
maxY = maxY - dy * rect.top(); maxY = maxY - dy * fixedRect.top();
setRange(minX, maxX, minY, maxY); setRange(minX, maxX, minY, maxY);
} }
@ -101,7 +102,8 @@ void LogXYDomain::zoomIn(const QRectF &rect)
void LogXYDomain::zoomOut(const QRectF &rect) void LogXYDomain::zoomOut(const QRectF &rect)
{ {
storeZoomReset(); storeZoomReset();
const qreal factorX = m_size.width() / rect.width(); QRectF fixedRect = fixZoomRect(rect);
const qreal factorX = m_size.width() / fixedRect.width();
qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 - factorX); qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 - factorX);
qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 + factorX); qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 + factorX);
@ -110,11 +112,11 @@ void LogXYDomain::zoomOut(const QRectF &rect)
qreal minX = leftX < rightX ? leftX : rightX; qreal minX = leftX < rightX ? leftX : rightX;
qreal maxX = leftX > rightX ? leftX : rightX; qreal maxX = leftX > rightX ? leftX : rightX;
qreal dy = spanY() / rect.height(); qreal dy = spanY() / fixedRect.height();
qreal minY = m_minY; qreal minY = m_minY;
qreal maxY = m_maxY; qreal maxY = m_maxY;
maxY = minY + dy * rect.bottom(); maxY = minY + dy * fixedRect.bottom();
minY = maxY - dy * m_size.height(); minY = maxY - dy * m_size.height();
setRange(minX, maxX, minY, maxY); setRange(minX, maxX, minY, maxY);
@ -122,6 +124,11 @@ void LogXYDomain::zoomOut(const QRectF &rect)
void LogXYDomain::move(qreal dx, qreal dy) void LogXYDomain::move(qreal dx, qreal dy)
{ {
if (m_reverseX)
dx = -dx;
if (m_reverseY)
dy = -dy;
qreal stepX = dx * (m_logRightX - m_logLeftX) / m_size.width(); qreal stepX = dx * (m_logRightX - m_logLeftX) / m_size.width();
qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX); qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX);
qreal rightX = qPow(m_logBaseX, m_logRightX + stepX); qreal rightX = qPow(m_logBaseX, m_logRightX + stepX);
@ -145,9 +152,13 @@ QPointF LogXYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) cons
const qreal deltaY = m_size.height() / (m_maxY - m_minY); const qreal deltaY = m_size.height() / (m_maxY - m_minY);
qreal x(0); qreal x(0);
qreal y = (point.y() - m_minY) * -deltaY + m_size.height(); qreal y = (point.y() - m_minY) * deltaY;
if (!m_reverseY)
y = m_size.height() - y;
if (point.x() > 0) { if (point.x() > 0) {
x = (std::log10(point.x()) / std::log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX; x = ((std::log10(point.x()) / std::log10(m_logBaseX)) - m_logLeftX) * deltaX;
if (m_reverseX)
x = m_size.width() - x;
ok = true; ok = true;
} else { } else {
x = 0; x = 0;
@ -167,8 +178,12 @@ QVector<QPointF> LogXYDomain::calculateGeometryPoints(const QVector<QPointF> &ve
for (int i = 0; i < vector.count(); ++i) { for (int i = 0; i < vector.count(); ++i) {
if (vector[i].x() > 0) { if (vector[i].x() > 0) {
qreal x = (std::log10(vector[i].x()) / std::log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX; qreal x = ((std::log10(vector[i].x()) / std::log10(m_logBaseX)) - m_logLeftX) * deltaX;
qreal y = (vector[i].y() - m_minY) * -deltaY + m_size.height(); if (m_reverseX)
x = m_size.width() - x;
qreal y = (vector[i].y() - m_minY) * deltaY;
if (!m_reverseY)
y = m_size.height() - y;
result[i].setX(x); result[i].setX(x);
result[i].setY(y); result[i].setY(y);
} else { } else {
@ -184,8 +199,11 @@ QPointF LogXYDomain::calculateDomainPoint(const QPointF &point) const
{ {
const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX); const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX);
const qreal deltaY = m_size.height() / (m_maxY - m_minY); const qreal deltaY = m_size.height() / (m_maxY - m_minY);
qreal x = qPow(m_logBaseX, m_logLeftX + point.x() / deltaX); qreal x = m_reverseX ? (m_size.width() - point.x()) : point.x();
qreal y = (point.y() - m_size.height()) / (-deltaY) + m_minY; x = qPow(m_logBaseX, m_logLeftX + x / deltaX);
qreal y = m_reverseY ? point.y() : (m_size.height() - point.y());
y /= deltaY;
y += m_minY;
return QPointF(x, y); return QPointF(x, y);
} }

View File

@ -81,15 +81,16 @@ void XLogYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
void XLogYDomain::zoomIn(const QRectF &rect) void XLogYDomain::zoomIn(const QRectF &rect)
{ {
storeZoomReset(); storeZoomReset();
QRectF fixedRect = fixZoomRect(rect);
qreal dx = spanX() / m_size.width(); qreal dx = spanX() / m_size.width();
qreal maxX = m_maxX; qreal maxX = m_maxX;
qreal minX = m_minX; qreal minX = m_minX;
maxX = minX + dx * rect.right(); maxX = minX + dx * fixedRect.right();
minX = minX + dx * rect.left(); minX = minX + dx * fixedRect.left();
qreal logLeftY = m_logRightY - rect.bottom() * (m_logRightY - m_logLeftY) / m_size.height(); qreal logLeftY = m_logRightY - fixedRect.bottom() * (m_logRightY - m_logLeftY) / m_size.height();
qreal logRightY = m_logRightY - rect.top() * (m_logRightY - m_logLeftY) / m_size.height(); qreal logRightY = m_logRightY - fixedRect.top() * (m_logRightY - m_logLeftY) / m_size.height();
qreal leftY = qPow(m_logBaseY, logLeftY); qreal leftY = qPow(m_logBaseY, logLeftY);
qreal rightY = qPow(m_logBaseY, logRightY); qreal rightY = qPow(m_logBaseY, logRightY);
qreal minY = leftY < rightY ? leftY : rightY; qreal minY = leftY < rightY ? leftY : rightY;
@ -101,14 +102,15 @@ void XLogYDomain::zoomIn(const QRectF &rect)
void XLogYDomain::zoomOut(const QRectF &rect) void XLogYDomain::zoomOut(const QRectF &rect)
{ {
storeZoomReset(); storeZoomReset();
qreal dx = spanX() / rect.width(); QRectF fixedRect = fixZoomRect(rect);
qreal dx = spanX() / fixedRect.width();
qreal maxX = m_maxX; qreal maxX = m_maxX;
qreal minX = m_minX; qreal minX = m_minX;
minX = maxX - dx * rect.right(); minX = maxX - dx * fixedRect.right();
maxX = minX + dx * m_size.width(); maxX = minX + dx * m_size.width();
const qreal factorY = m_size.height() / rect.height(); const qreal factorY = m_size.height() / fixedRect.height();
qreal newLogMinY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 - factorY); qreal newLogMinY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 - factorY);
qreal newLogMaxY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 + factorY); qreal newLogMaxY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 + factorY);
qreal leftY = qPow(m_logBaseY, newLogMinY); qreal leftY = qPow(m_logBaseY, newLogMinY);
@ -121,6 +123,11 @@ void XLogYDomain::zoomOut(const QRectF &rect)
void XLogYDomain::move(qreal dx, qreal dy) void XLogYDomain::move(qreal dx, qreal dy)
{ {
if (m_reverseX)
dx = -dx;
if (m_reverseY)
dy = -dy;
qreal x = spanX() / m_size.width(); qreal x = spanX() / m_size.width();
qreal maxX = m_maxX; qreal maxX = m_maxX;
qreal minX = m_minX; qreal minX = m_minX;
@ -145,9 +152,13 @@ QPointF XLogYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) cons
const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY); const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
qreal x = (point.x() - m_minX) * deltaX; qreal x = (point.x() - m_minX) * deltaX;
if (m_reverseX)
x = m_size.width() - x;
qreal y(0); qreal y(0);
if (point.y() > 0) { if (point.y() > 0) {
y = (std::log10(point.y()) / std::log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height(); y = ((std::log10(point.y()) / std::log10(m_logBaseY)) - m_logLeftY) * deltaY;
if (!m_reverseY)
y = m_size.height() - y;
ok = true; ok = true;
} else { } else {
y = m_size.height(); y = m_size.height();
@ -168,7 +179,11 @@ QVector<QPointF> XLogYDomain::calculateGeometryPoints(const QVector<QPointF> &ve
for (int i = 0; i < vector.count(); ++i) { for (int i = 0; i < vector.count(); ++i) {
if (vector[i].y() > 0) { if (vector[i].y() > 0) {
qreal x = (vector[i].x() - m_minX) * deltaX; qreal x = (vector[i].x() - m_minX) * deltaX;
qreal y = (std::log10(vector[i].y()) / std::log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height(); if (m_reverseX)
x = m_size.width() - x;
qreal y = ((std::log10(vector[i].y()) / std::log10(m_logBaseY)) - m_logLeftY) * deltaY;
if (!m_reverseY)
y = m_size.height() - y;
result[i].setX(x); result[i].setX(x);
result[i].setY(y); result[i].setY(y);
} else { } else {
@ -183,8 +198,11 @@ QPointF XLogYDomain::calculateDomainPoint(const QPointF &point) const
{ {
const qreal deltaX = m_size.width() / (m_maxX - m_minX); const qreal deltaX = m_size.width() / (m_maxX - m_minX);
const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY); const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
qreal x = point.x() / deltaX + m_minX; qreal x = m_reverseX ? (m_size.width() - point.x()) : point.x();
qreal y = qPow(m_logBaseY, m_logLeftY + (m_size.height() - point.y()) / deltaY); x /= deltaX;
x += m_minX;
qreal y = m_reverseY ? point.y() : (m_size.height() - point.y());
y = qPow(m_logBaseY, m_logLeftY + y / deltaY);
return QPointF(x, y); return QPointF(x, y);
} }

View File

@ -71,6 +71,7 @@ void XYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
void XYDomain::zoomIn(const QRectF &rect) void XYDomain::zoomIn(const QRectF &rect)
{ {
storeZoomReset(); storeZoomReset();
QRectF fixedRect = fixZoomRect(rect);
qreal dx = spanX() / m_size.width(); qreal dx = spanX() / m_size.width();
qreal dy = spanY() / m_size.height(); qreal dy = spanY() / m_size.height();
@ -79,10 +80,10 @@ void XYDomain::zoomIn(const QRectF &rect)
qreal minY = m_minY; qreal minY = m_minY;
qreal maxY = m_maxY; qreal maxY = m_maxY;
maxX = minX + dx * rect.right(); maxX = minX + dx * fixedRect.right();
minX = minX + dx * rect.left(); minX = minX + dx * fixedRect.left();
minY = maxY - dy * rect.bottom(); minY = maxY - dy * fixedRect.bottom();
maxY = maxY - dy * rect.top(); maxY = maxY - dy * fixedRect.top();
if ((maxX - minX) == spanX()) { if ((maxX - minX) == spanX()) {
minX = m_minX; minX = m_minX;
@ -99,6 +100,7 @@ void XYDomain::zoomIn(const QRectF &rect)
void XYDomain::zoomOut(const QRectF &rect) void XYDomain::zoomOut(const QRectF &rect)
{ {
storeZoomReset(); storeZoomReset();
QRectF fixedRect = fixZoomRect(rect);
qreal dx = spanX() / rect.width(); qreal dx = spanX() / rect.width();
qreal dy = spanY() / rect.height(); qreal dy = spanY() / rect.height();
@ -107,9 +109,9 @@ void XYDomain::zoomOut(const QRectF &rect)
qreal minY = m_minY; qreal minY = m_minY;
qreal maxY = m_maxY; qreal maxY = m_maxY;
minX = maxX - dx * rect.right(); minX = maxX - dx * fixedRect.right();
maxX = minX + dx * m_size.width(); maxX = minX + dx * m_size.width();
maxY = minY + dy * rect.bottom(); maxY = minY + dy * fixedRect.bottom();
minY = maxY - dy * m_size.height(); minY = maxY - dy * m_size.height();
if ((maxX - minX) == spanX()) { if ((maxX - minX) == spanX()) {
@ -126,6 +128,11 @@ void XYDomain::zoomOut(const QRectF &rect)
void XYDomain::move(qreal dx, qreal dy) void XYDomain::move(qreal dx, qreal dy)
{ {
if (m_reverseX)
dx = -dx;
if (m_reverseY)
dy = -dy;
qreal x = spanX() / m_size.width(); qreal x = spanX() / m_size.width();
qreal y = spanY() / m_size.height(); qreal y = spanY() / m_size.height();
@ -150,7 +157,11 @@ QPointF XYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
const qreal deltaX = m_size.width() / (m_maxX - m_minX); const qreal deltaX = m_size.width() / (m_maxX - m_minX);
const qreal deltaY = m_size.height() / (m_maxY - m_minY); const qreal deltaY = m_size.height() / (m_maxY - m_minY);
qreal x = (point.x() - m_minX) * deltaX; qreal x = (point.x() - m_minX) * deltaX;
qreal y = (point.y() - m_minY) * -deltaY + m_size.height(); if (m_reverseX)
x = m_size.width() - x;
qreal y = (point.y() - m_minY) * deltaY;
if (!m_reverseY)
y = m_size.height() - y;
ok = true; ok = true;
return QPointF(x, y); return QPointF(x, y);
} }
@ -165,7 +176,11 @@ QVector<QPointF> XYDomain::calculateGeometryPoints(const QVector<QPointF> &vecto
for (int i = 0; i < vector.count(); ++i) { for (int i = 0; i < vector.count(); ++i) {
qreal x = (vector[i].x() - m_minX) * deltaX; qreal x = (vector[i].x() - m_minX) * deltaX;
qreal y = (vector[i].y() - m_minY) * -deltaY + m_size.height(); if (m_reverseX)
x = m_size.width() - x;
qreal y = (vector[i].y() - m_minY) * deltaY;
if (!m_reverseY)
y = m_size.height() - y;
result[i].setX(x); result[i].setX(x);
result[i].setY(y); result[i].setY(y);
} }
@ -176,8 +191,12 @@ QPointF XYDomain::calculateDomainPoint(const QPointF &point) const
{ {
const qreal deltaX = m_size.width() / (m_maxX - m_minX); const qreal deltaX = m_size.width() / (m_maxX - m_minX);
const qreal deltaY = m_size.height() / (m_maxY - m_minY); const qreal deltaY = m_size.height() / (m_maxY - m_minY);
qreal x = point.x() / deltaX + m_minX; qreal x = m_reverseX ? (m_size.width() - point.x()) : point.x();
qreal y = (point.y() - m_size.height()) / (-deltaY) + m_minY; x /= deltaX;
x += m_minX;
qreal y = m_reverseY ? point.y() : (m_size.height() - point.y());
y /= deltaY;
y += m_minY;
return QPointF(x, y); return QPointF(x, y);
} }

View File

@ -395,8 +395,6 @@ void LineChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt
painter->setClipRect(clipRect); painter->setClipRect(clipRect);
} }
reversePainter(painter, clipRect);
if (m_pointsVisible) { if (m_pointsVisible) {
painter->setBrush(m_linePen.color()); painter->setBrush(m_linePen.color());
painter->drawPath(m_linePath); painter->drawPath(m_linePath);
@ -412,8 +410,6 @@ void LineChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt
} }
} }
reversePainter(painter, clipRect);
if (m_pointLabelsVisible) { if (m_pointLabelsVisible) {
if (m_pointLabelsClipping) if (m_pointLabelsClipping)
painter->setClipping(true); painter->setClipping(true);

View File

@ -457,40 +457,6 @@ void QAbstractSeriesPrivate::initializeAnimations(QChart::AnimationOptions optio
Q_UNUSED(curve); Q_UNUSED(curve);
} }
bool QAbstractSeriesPrivate::reverseXAxis()
{
bool reverseXAxis = false;
if (m_axes.size() != 0 && !(m_chart->chartType() == QChart::ChartTypePolar)) {
int i = 0;
while (i < m_axes.size()) {
if (m_axes.at(i)->orientation() == Qt::Horizontal && m_axes.at(i)->isReverse()) {
reverseXAxis = true;
break;
}
i++;
}
}
return reverseXAxis;
}
bool QAbstractSeriesPrivate::reverseYAxis()
{
bool reverseYAxis = false;
if (m_axes.size() != 0 && !(m_chart->chartType() == QChart::ChartTypePolar)) {
int i = 0;
while (i < m_axes.size()) {
if (m_axes.at(i)->orientation() == Qt::Vertical && m_axes.at(i)->isReverse()) {
reverseYAxis = true;
break;
}
i++;
}
}
return reverseYAxis;
}
// This function can be used to explicitly block OpenGL use from some otherwise supported series, // This function can be used to explicitly block OpenGL use from some otherwise supported series,
// such as the line series used as edge series of an area series. // such as the line series used as edge series of an area series.
void QAbstractSeriesPrivate::setBlockOpenGL(bool enable) void QAbstractSeriesPrivate::setBlockOpenGL(bool enable)

View File

@ -89,8 +89,6 @@ public:
ChartPresenter *presenter() const; ChartPresenter *presenter() const;
QChart* chart() { return m_chart; } QChart* chart() { return m_chart; }
bool reverseXAxis();
bool reverseYAxis();
void setBlockOpenGL(bool enable); void setBlockOpenGL(bool enable);

View File

@ -194,17 +194,10 @@ void ScatterChartItem::updateGeometry()
// fake anyway. After remove animation stops, geometry is updated to correct one. // fake anyway. After remove animation stops, geometry is updated to correct one.
m_markerMap[item] = m_series->at(qMin(seriesLastIndex, i)); m_markerMap[item] = m_series->at(qMin(seriesLastIndex, i));
QPointF position; QPointF position;
if (seriesPrivate()->reverseXAxis())
position.setX(domain()->size().width() - point.x() - rect.width() / 2);
else
position.setX(point.x() - rect.width() / 2); position.setX(point.x() - rect.width() / 2);
if (seriesPrivate()->reverseYAxis())
position.setY(domain()->size().height() - point.y() - rect.height() / 2);
else
position.setY(point.y() - rect.height() / 2); position.setY(point.y() - rect.height() / 2);
item->setPos(position); item->setPos(position);
if (!m_visible || offGridStatus.at(i)) if (!m_visible || offGridStatus.at(i))
item->setVisible(false); item->setVisible(false);
else else

View File

@ -460,8 +460,6 @@ void SplineChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *o
painter->setClipRect(clipRect); painter->setClipRect(clipRect);
} }
reversePainter(painter, clipRect);
painter->drawPath(m_path); painter->drawPath(m_path);
if (m_pointsVisible) { if (m_pointsVisible) {
@ -472,8 +470,6 @@ void SplineChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *o
painter->drawPoints(geometryPoints()); painter->drawPoints(geometryPoints());
} }
reversePainter(painter, clipRect);
if (m_pointLabelsVisible) { if (m_pointLabelsVisible) {
if (m_pointLabelsClipping) if (m_pointLabelsClipping)
painter->setClipping(true); painter->setClipping(true);

View File

@ -559,12 +559,16 @@ void QXYModelMapperPrivate::initializeXYFromModel()
// determine when we should end looping. // determine when we should end looping.
} }
} else { } else {
// Invalid index right off the bat means series will be left empty, so output a warning // Invalid index right off the bat means series will be left empty, so output a warning,
// unless model is also empty
int count = m_orientation == Qt::Vertical ? m_model->rowCount() : m_model->columnCount();
if (count > 0) {
if (!xIndex.isValid()) if (!xIndex.isValid())
qWarning() << __FUNCTION__ << QStringLiteral("Invalid X coordinate index in model mapper."); qWarning() << __FUNCTION__ << QStringLiteral("Invalid X coordinate index in model mapper.");
else if (!yIndex.isValid()) else if (!yIndex.isValid())
qWarning() << __FUNCTION__ << QStringLiteral("Invalid Y coordinate index in model mapper."); qWarning() << __FUNCTION__ << QStringLiteral("Invalid Y coordinate index in model mapper.");
} }
}
blockSeriesSignals(false); blockSeriesSignals(false);
} }

View File

@ -972,14 +972,8 @@ void QXYSeriesPrivate::drawSeriesPointLabels(QPainter *painter, const QVector<QP
// Position text in relation to the point // Position text in relation to the point
int pointLabelWidth = fm.width(pointLabel); int pointLabelWidth = fm.width(pointLabel);
QPointF position(points.at(i)); QPointF position(points.at(i));
if (!reverseXAxis())
position.setX(position.x() - pointLabelWidth / 2); position.setX(position.x() - pointLabelWidth / 2);
else
position.setX(domain()->size().width() - position.x() - pointLabelWidth / 2);
if (!reverseYAxis())
position.setY(position.y() - labelOffset); position.setY(position.y() - labelOffset);
else
position.setY(domain()->size().height() - position.y() - labelOffset);
painter->drawText(position, pointLabel); painter->drawText(position, pointLabel);
} }