##// END OF EJS Templates
Fix QNX build issue...
Titta Heikkala -
r2775:143be951b1fe
parent child
Show More
@@ -1,138 +1,138
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2014 Digia Plc
3 ** Copyright (C) 2014 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.io
5 ** For any questions to Digia, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and Digia.
12 ** agreement between you and Digia.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <private/chartbarcategoryaxisx_p.h>
19 #include <private/chartbarcategoryaxisx_p.h>
20 #include <private/chartpresenter_p.h>
20 #include <private/chartpresenter_p.h>
21 #include <private/qbarcategoryaxis_p.h>
21 #include <private/qbarcategoryaxis_p.h>
22 #include <private/abstractchartlayout_p.h>
22 #include <private/abstractchartlayout_p.h>
23 #include <QtCore/QDebug>
23 #include <QtCore/QDebug>
24 #include <QtCore/QtMath>
24 #include <QtCore/QtMath>
25
25
26 QT_CHARTS_BEGIN_NAMESPACE
26 QT_CHARTS_BEGIN_NAMESPACE
27
27
28 ChartBarCategoryAxisX::ChartBarCategoryAxisX(QBarCategoryAxis *axis, QGraphicsItem* item)
28 ChartBarCategoryAxisX::ChartBarCategoryAxisX(QBarCategoryAxis *axis, QGraphicsItem* item)
29 : HorizontalAxis(axis, item, true),
29 : HorizontalAxis(axis, item, true),
30 m_categoriesAxis(axis)
30 m_categoriesAxis(axis)
31 {
31 {
32 QObject::connect(m_categoriesAxis,SIGNAL(categoriesChanged()),this, SLOT(handleCategoriesChanged()));
32 QObject::connect(m_categoriesAxis,SIGNAL(categoriesChanged()),this, SLOT(handleCategoriesChanged()));
33 handleCategoriesChanged();
33 handleCategoriesChanged();
34 }
34 }
35
35
36 ChartBarCategoryAxisX::~ChartBarCategoryAxisX()
36 ChartBarCategoryAxisX::~ChartBarCategoryAxisX()
37 {
37 {
38 }
38 }
39
39
40 QVector<qreal> ChartBarCategoryAxisX::calculateLayout() const
40 QVector<qreal> ChartBarCategoryAxisX::calculateLayout() const
41 {
41 {
42 QVector<qreal> points;
42 QVector<qreal> points;
43 const QRectF& gridRect = gridGeometry();
43 const QRectF& gridRect = gridGeometry();
44 qreal range = max() - min();
44 qreal range = max() - min();
45 const qreal delta = gridRect.width() / range;
45 const qreal delta = gridRect.width() / range;
46
46
47 if (delta < 2)
47 if (delta < 2)
48 return points;
48 return points;
49
49
50 qreal adjustedMin = min() + 0.5;
50 qreal adjustedMin = min() + 0.5;
51 qreal offset = (ceil(adjustedMin) - adjustedMin) * delta;
51 qreal offset = (qCeil(adjustedMin) - adjustedMin) * delta;
52
52
53 int count = qFloor(range);
53 int count = qFloor(range);
54 if (count < 1)
54 if (count < 1)
55 return points;
55 return points;
56
56
57 points.resize(count + 2);
57 points.resize(count + 2);
58
58
59 for (int i = 0; i < count + 2; ++i)
59 for (int i = 0; i < count + 2; ++i)
60 points[i] = offset + (qreal(i) * delta) + gridRect.left();
60 points[i] = offset + (qreal(i) * delta) + gridRect.left();
61
61
62 return points;
62 return points;
63 }
63 }
64
64
65 QStringList ChartBarCategoryAxisX::createCategoryLabels(const QVector<qreal>& layout) const
65 QStringList ChartBarCategoryAxisX::createCategoryLabels(const QVector<qreal>& layout) const
66 {
66 {
67 QStringList result ;
67 QStringList result ;
68 const QRectF &gridRect = gridGeometry();
68 const QRectF &gridRect = gridGeometry();
69 qreal d = (max() - min()) / gridRect.width();
69 qreal d = (max() - min()) / gridRect.width();
70
70
71 for (int i = 0; i < layout.count() - 1; ++i) {
71 for (int i = 0; i < layout.count() - 1; ++i) {
72 qreal x = qFloor((((layout[i] + layout[i + 1]) / 2 - gridRect.left()) * d + min() + 0.5));
72 qreal x = qFloor((((layout[i] + layout[i + 1]) / 2 - gridRect.left()) * d + min() + 0.5));
73 if (x < max() && (x >= 0) && x < m_categoriesAxis->categories().count()) {
73 if (x < max() && (x >= 0) && x < m_categoriesAxis->categories().count()) {
74 result << m_categoriesAxis->categories().at(x);
74 result << m_categoriesAxis->categories().at(x);
75 } else {
75 } else {
76 // No label for x coordinate
76 // No label for x coordinate
77 result << QString();
77 result << QString();
78 }
78 }
79 }
79 }
80 result << QString();
80 result << QString();
81 return result;
81 return result;
82 }
82 }
83
83
84
84
85 void ChartBarCategoryAxisX::updateGeometry()
85 void ChartBarCategoryAxisX::updateGeometry()
86 {
86 {
87 const QVector<qreal>& layout = ChartAxisElement::layout();
87 const QVector<qreal>& layout = ChartAxisElement::layout();
88 if (layout.isEmpty())
88 if (layout.isEmpty())
89 return;
89 return;
90 setLabels(createCategoryLabels(layout));
90 setLabels(createCategoryLabels(layout));
91 HorizontalAxis::updateGeometry();
91 HorizontalAxis::updateGeometry();
92 }
92 }
93
93
94 void ChartBarCategoryAxisX::handleCategoriesChanged()
94 void ChartBarCategoryAxisX::handleCategoriesChanged()
95 {
95 {
96 QGraphicsLayoutItem::updateGeometry();
96 QGraphicsLayoutItem::updateGeometry();
97 if(presenter()) presenter()->layout()->invalidate();
97 if(presenter()) presenter()->layout()->invalidate();
98 }
98 }
99
99
100 QSizeF ChartBarCategoryAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
100 QSizeF ChartBarCategoryAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
101 {
101 {
102 Q_UNUSED(constraint)
102 Q_UNUSED(constraint)
103
103
104 QSizeF sh;
104 QSizeF sh;
105 QSizeF base = HorizontalAxis::sizeHint(which, constraint);
105 QSizeF base = HorizontalAxis::sizeHint(which, constraint);
106 QStringList ticksList = m_categoriesAxis->categories();
106 QStringList ticksList = m_categoriesAxis->categories();
107
107
108 qreal width = 0; // Width is irrelevant for X axes with interval labels
108 qreal width = 0; // Width is irrelevant for X axes with interval labels
109 qreal height = 0;
109 qreal height = 0;
110
110
111 switch (which) {
111 switch (which) {
112 case Qt::MinimumSize: {
112 case Qt::MinimumSize: {
113 QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(),
113 QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(),
114 QStringLiteral("..."),
114 QStringLiteral("..."),
115 axis()->labelsAngle());
115 axis()->labelsAngle());
116 height = boundingRect.height() + labelPadding() + base.height() + 1.0;
116 height = boundingRect.height() + labelPadding() + base.height() + 1.0;
117 sh = QSizeF(width, height);
117 sh = QSizeF(width, height);
118 break;
118 break;
119 }
119 }
120 case Qt::PreferredSize:{
120 case Qt::PreferredSize:{
121 qreal labelHeight = 0.0;
121 qreal labelHeight = 0.0;
122 foreach (const QString& s, ticksList) {
122 foreach (const QString& s, ticksList) {
123 QRectF rect = ChartPresenter::textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
123 QRectF rect = ChartPresenter::textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
124 labelHeight = qMax(rect.height(), labelHeight);
124 labelHeight = qMax(rect.height(), labelHeight);
125 }
125 }
126 height = labelHeight + labelPadding() + base.height() + 1.0;
126 height = labelHeight + labelPadding() + base.height() + 1.0;
127 sh = QSizeF(width, height);
127 sh = QSizeF(width, height);
128 break;
128 break;
129 }
129 }
130 default:
130 default:
131 break;
131 break;
132 }
132 }
133 return sh;
133 return sh;
134 }
134 }
135
135
136 #include "moc_chartbarcategoryaxisx_p.cpp"
136 #include "moc_chartbarcategoryaxisx_p.cpp"
137
137
138 QT_CHARTS_END_NAMESPACE
138 QT_CHARTS_END_NAMESPACE
@@ -1,140 +1,140
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2014 Digia Plc
3 ** Copyright (C) 2014 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.io
5 ** For any questions to Digia, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and Digia.
12 ** agreement between you and Digia.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <private/chartbarcategoryaxisy_p.h>
19 #include <private/chartbarcategoryaxisy_p.h>
20 #include <private/chartpresenter_p.h>
20 #include <private/chartpresenter_p.h>
21 #include <private/qbarcategoryaxis_p.h>
21 #include <private/qbarcategoryaxis_p.h>
22 #include <private/abstractchartlayout_p.h>
22 #include <private/abstractchartlayout_p.h>
23 #include <QtCore/QtMath>
23 #include <QtCore/QtMath>
24 #include <QtCore/QDebug>
24 #include <QtCore/QDebug>
25
25
26 QT_CHARTS_BEGIN_NAMESPACE
26 QT_CHARTS_BEGIN_NAMESPACE
27
27
28 ChartBarCategoryAxisY::ChartBarCategoryAxisY(QBarCategoryAxis *axis, QGraphicsItem* item)
28 ChartBarCategoryAxisY::ChartBarCategoryAxisY(QBarCategoryAxis *axis, QGraphicsItem* item)
29 : VerticalAxis(axis, item, true),
29 : VerticalAxis(axis, item, true),
30 m_categoriesAxis(axis)
30 m_categoriesAxis(axis)
31 {
31 {
32 QObject::connect( m_categoriesAxis,SIGNAL(categoriesChanged()),this, SLOT(handleCategoriesChanged()));
32 QObject::connect( m_categoriesAxis,SIGNAL(categoriesChanged()),this, SLOT(handleCategoriesChanged()));
33 handleCategoriesChanged();
33 handleCategoriesChanged();
34 }
34 }
35
35
36 ChartBarCategoryAxisY::~ChartBarCategoryAxisY()
36 ChartBarCategoryAxisY::~ChartBarCategoryAxisY()
37 {
37 {
38 }
38 }
39
39
40 QVector<qreal> ChartBarCategoryAxisY::calculateLayout() const
40 QVector<qreal> ChartBarCategoryAxisY::calculateLayout() const
41 {
41 {
42 QVector<qreal> points;
42 QVector<qreal> points;
43 const QRectF& gridRect = gridGeometry();
43 const QRectF& gridRect = gridGeometry();
44 qreal range = max() - min();
44 qreal range = max() - min();
45 const qreal delta = gridRect.height() / range;
45 const qreal delta = gridRect.height() / range;
46
46
47 if (delta < 2)
47 if (delta < 2)
48 return points;
48 return points;
49
49
50 qreal adjustedMin = min() + 0.5;
50 qreal adjustedMin = min() + 0.5;
51 qreal offset = (ceil(adjustedMin) - adjustedMin) * delta;
51 qreal offset = (qCeil(adjustedMin) - adjustedMin) * delta;
52
52
53 int count = qFloor(range);
53 int count = qFloor(range);
54 if (count < 1)
54 if (count < 1)
55 return points;
55 return points;
56
56
57 points.resize(count + 2);
57 points.resize(count + 2);
58
58
59 for (int i = 0; i < count + 2; ++i)
59 for (int i = 0; i < count + 2; ++i)
60 points[i] = gridRect.bottom() - (qreal(i) * delta) - offset;
60 points[i] = gridRect.bottom() - (qreal(i) * delta) - offset;
61
61
62 return points;
62 return points;
63 }
63 }
64
64
65 QStringList ChartBarCategoryAxisY::createCategoryLabels(const QVector<qreal>& layout) const
65 QStringList ChartBarCategoryAxisY::createCategoryLabels(const QVector<qreal>& layout) const
66 {
66 {
67 QStringList result;
67 QStringList result;
68 const QRectF &gridRect = gridGeometry();
68 const QRectF &gridRect = gridGeometry();
69 qreal d = (max() - min()) / gridRect.height();
69 qreal d = (max() - min()) / gridRect.height();
70
70
71 for (int i = 0; i < layout.count() - 1; ++i) {
71 for (int i = 0; i < layout.count() - 1; ++i) {
72 qreal x = qFloor(((gridRect.height() - (layout[i + 1] + layout[i]) / 2 + gridRect.top()) * d + min() + 0.5));
72 qreal x = qFloor(((gridRect.height() - (layout[i + 1] + layout[i]) / 2 + gridRect.top()) * d + min() + 0.5));
73 if ((x < m_categoriesAxis->categories().count()) && (x >= 0)) {
73 if ((x < m_categoriesAxis->categories().count()) && (x >= 0)) {
74 result << m_categoriesAxis->categories().at(x);
74 result << m_categoriesAxis->categories().at(x);
75 } else {
75 } else {
76 // No label for x coordinate
76 // No label for x coordinate
77 result << QString();
77 result << QString();
78 }
78 }
79 }
79 }
80 result << QString();
80 result << QString();
81 return result;
81 return result;
82 }
82 }
83
83
84 void ChartBarCategoryAxisY::updateGeometry()
84 void ChartBarCategoryAxisY::updateGeometry()
85 {
85 {
86 const QVector<qreal>& layout = ChartAxisElement::layout();
86 const QVector<qreal>& layout = ChartAxisElement::layout();
87 if (layout.isEmpty())
87 if (layout.isEmpty())
88 return;
88 return;
89 setLabels(createCategoryLabels(layout));
89 setLabels(createCategoryLabels(layout));
90 VerticalAxis::updateGeometry();
90 VerticalAxis::updateGeometry();
91 }
91 }
92
92
93 void ChartBarCategoryAxisY::handleCategoriesChanged()
93 void ChartBarCategoryAxisY::handleCategoriesChanged()
94 {
94 {
95 QGraphicsLayoutItem::updateGeometry();
95 QGraphicsLayoutItem::updateGeometry();
96 if(presenter()) presenter()->layout()->invalidate();
96 if(presenter()) presenter()->layout()->invalidate();
97 }
97 }
98
98
99 QSizeF ChartBarCategoryAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
99 QSizeF ChartBarCategoryAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
100 {
100 {
101 Q_UNUSED(constraint)
101 Q_UNUSED(constraint)
102
102
103 QSizeF sh;
103 QSizeF sh;
104 QSizeF base = VerticalAxis::sizeHint(which, constraint);
104 QSizeF base = VerticalAxis::sizeHint(which, constraint);
105 QStringList ticksList = m_categoriesAxis->categories();
105 QStringList ticksList = m_categoriesAxis->categories();
106 qreal width = 0;
106 qreal width = 0;
107 qreal height = 0; // Height is irrelevant for Y axes with interval labels
107 qreal height = 0; // Height is irrelevant for Y axes with interval labels
108
108
109 switch (which) {
109 switch (which) {
110 case Qt::MinimumSize: {
110 case Qt::MinimumSize: {
111 QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(),
111 QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(),
112 QStringLiteral("..."),
112 QStringLiteral("..."),
113 axis()->labelsAngle());
113 axis()->labelsAngle());
114 width = boundingRect.width() + labelPadding() + base.width() + 1.0;
114 width = boundingRect.width() + labelPadding() + base.width() + 1.0;
115 if (base.width() > 0.0)
115 if (base.width() > 0.0)
116 width += labelPadding();
116 width += labelPadding();
117 sh = QSizeF(width, height);
117 sh = QSizeF(width, height);
118 break;
118 break;
119 }
119 }
120 case Qt::PreferredSize:{
120 case Qt::PreferredSize:{
121 qreal labelWidth = 0.0;
121 qreal labelWidth = 0.0;
122 foreach (const QString& s, ticksList) {
122 foreach (const QString& s, ticksList) {
123 QRectF rect = ChartPresenter::textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
123 QRectF rect = ChartPresenter::textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
124 labelWidth = qMax(rect.width(), labelWidth);
124 labelWidth = qMax(rect.width(), labelWidth);
125 }
125 }
126 width = labelWidth + labelPadding() + base.width() + 1.0;
126 width = labelWidth + labelPadding() + base.width() + 1.0;
127 if (base.width() > 0.0)
127 if (base.width() > 0.0)
128 width += labelPadding();
128 width += labelPadding();
129 sh = QSizeF(width, height);
129 sh = QSizeF(width, height);
130 break;
130 break;
131 }
131 }
132 default:
132 default:
133 break;
133 break;
134 }
134 }
135 return sh;
135 return sh;
136 }
136 }
137
137
138 #include "moc_chartbarcategoryaxisy_p.cpp"
138 #include "moc_chartbarcategoryaxisy_p.cpp"
139
139
140 QT_CHARTS_END_NAMESPACE
140 QT_CHARTS_END_NAMESPACE
@@ -1,390 +1,391
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2014 Digia Plc
3 ** Copyright (C) 2014 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.io
5 ** For any questions to Digia, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and Digia.
12 ** agreement between you and Digia.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <private/chartaxiselement_p.h>
19 #include <private/chartaxiselement_p.h>
20 #include <private/qabstractaxis_p.h>
20 #include <private/qabstractaxis_p.h>
21 #include <private/chartpresenter_p.h>
21 #include <private/chartpresenter_p.h>
22 #include <private/abstractchartlayout_p.h>
22 #include <private/abstractchartlayout_p.h>
23 #include <QtCore/QtMath>
23 #include <QtCore/QtMath>
24 #include <QtCore/QDateTime>
24 #include <QtCore/QDateTime>
25 #include <QtGui/QTextDocument>
25 #include <QtGui/QTextDocument>
26 #include <cmath>
26
27
27 QT_CHARTS_BEGIN_NAMESPACE
28 QT_CHARTS_BEGIN_NAMESPACE
28
29
29 static const char *labelFormatMatchString = "%[\\-\\+#\\s\\d\\.\\'lhjztL]*([dicuoxfegXFEG])";
30 static const char *labelFormatMatchString = "%[\\-\\+#\\s\\d\\.\\'lhjztL]*([dicuoxfegXFEG])";
30 static const char *labelFormatMatchLocalizedString = "^([^%]*)%\\.(\\d+)([defgiEG])(.*)$";
31 static const char *labelFormatMatchLocalizedString = "^([^%]*)%\\.(\\d+)([defgiEG])(.*)$";
31 static QRegExp *labelFormatMatcher = 0;
32 static QRegExp *labelFormatMatcher = 0;
32 static QRegExp *labelFormatMatcherLocalized = 0;
33 static QRegExp *labelFormatMatcherLocalized = 0;
33 class StaticLabelFormatMatcherDeleter
34 class StaticLabelFormatMatcherDeleter
34 {
35 {
35 public:
36 public:
36 StaticLabelFormatMatcherDeleter() {}
37 StaticLabelFormatMatcherDeleter() {}
37 ~StaticLabelFormatMatcherDeleter() {
38 ~StaticLabelFormatMatcherDeleter() {
38 delete labelFormatMatcher;
39 delete labelFormatMatcher;
39 delete labelFormatMatcherLocalized;
40 delete labelFormatMatcherLocalized;
40 }
41 }
41 };
42 };
42 static StaticLabelFormatMatcherDeleter staticLabelFormatMatcherDeleter;
43 static StaticLabelFormatMatcherDeleter staticLabelFormatMatcherDeleter;
43
44
44 ChartAxisElement::ChartAxisElement(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
45 ChartAxisElement::ChartAxisElement(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
45 : ChartElement(item),
46 : ChartElement(item),
46 m_axis(axis),
47 m_axis(axis),
47 m_animation(0),
48 m_animation(0),
48 m_grid(new QGraphicsItemGroup(item)),
49 m_grid(new QGraphicsItemGroup(item)),
49 m_arrow(new QGraphicsItemGroup(item)),
50 m_arrow(new QGraphicsItemGroup(item)),
50 m_shades(new QGraphicsItemGroup(item)),
51 m_shades(new QGraphicsItemGroup(item)),
51 m_labels(new QGraphicsItemGroup(item)),
52 m_labels(new QGraphicsItemGroup(item)),
52 m_title(new QGraphicsTextItem(item)),
53 m_title(new QGraphicsTextItem(item)),
53 m_intervalAxis(intervalAxis)
54 m_intervalAxis(intervalAxis)
54
55
55 {
56 {
56 //initial initialization
57 //initial initialization
57 m_arrow->setHandlesChildEvents(false);
58 m_arrow->setHandlesChildEvents(false);
58 m_arrow->setZValue(ChartPresenter::AxisZValue);
59 m_arrow->setZValue(ChartPresenter::AxisZValue);
59 m_labels->setZValue(ChartPresenter::AxisZValue);
60 m_labels->setZValue(ChartPresenter::AxisZValue);
60 m_shades->setZValue(ChartPresenter::ShadesZValue);
61 m_shades->setZValue(ChartPresenter::ShadesZValue);
61 m_grid->setZValue(ChartPresenter::GridZValue);
62 m_grid->setZValue(ChartPresenter::GridZValue);
62 m_title->setZValue(ChartPresenter::GridZValue);
63 m_title->setZValue(ChartPresenter::GridZValue);
63 m_title->document()->setDocumentMargin(ChartPresenter::textMargin());
64 m_title->document()->setDocumentMargin(ChartPresenter::textMargin());
64 handleVisibleChanged(axis->isVisible());
65 handleVisibleChanged(axis->isVisible());
65 connectSlots();
66 connectSlots();
66
67
67 setFlag(QGraphicsItem::ItemHasNoContents, true);
68 setFlag(QGraphicsItem::ItemHasNoContents, true);
68 }
69 }
69
70
70 ChartAxisElement::~ChartAxisElement()
71 ChartAxisElement::~ChartAxisElement()
71 {
72 {
72 }
73 }
73
74
74 void ChartAxisElement::connectSlots()
75 void ChartAxisElement::connectSlots()
75 {
76 {
76 QObject::connect(axis(), SIGNAL(visibleChanged(bool)), this, SLOT(handleVisibleChanged(bool)));
77 QObject::connect(axis(), SIGNAL(visibleChanged(bool)), this, SLOT(handleVisibleChanged(bool)));
77 QObject::connect(axis(), SIGNAL(lineVisibleChanged(bool)), this, SLOT(handleArrowVisibleChanged(bool)));
78 QObject::connect(axis(), SIGNAL(lineVisibleChanged(bool)), this, SLOT(handleArrowVisibleChanged(bool)));
78 QObject::connect(axis(), SIGNAL(gridVisibleChanged(bool)), this, SLOT(handleGridVisibleChanged(bool)));
79 QObject::connect(axis(), SIGNAL(gridVisibleChanged(bool)), this, SLOT(handleGridVisibleChanged(bool)));
79 QObject::connect(axis(), SIGNAL(labelsVisibleChanged(bool)), this, SLOT(handleLabelsVisibleChanged(bool)));
80 QObject::connect(axis(), SIGNAL(labelsVisibleChanged(bool)), this, SLOT(handleLabelsVisibleChanged(bool)));
80 QObject::connect(axis(), SIGNAL(shadesVisibleChanged(bool)), this, SLOT(handleShadesVisibleChanged(bool)));
81 QObject::connect(axis(), SIGNAL(shadesVisibleChanged(bool)), this, SLOT(handleShadesVisibleChanged(bool)));
81 QObject::connect(axis(), SIGNAL(labelsAngleChanged(int)), this, SLOT(handleLabelsAngleChanged(int)));
82 QObject::connect(axis(), SIGNAL(labelsAngleChanged(int)), this, SLOT(handleLabelsAngleChanged(int)));
82 QObject::connect(axis(), SIGNAL(linePenChanged(const QPen&)), this, SLOT(handleArrowPenChanged(const QPen&)));
83 QObject::connect(axis(), SIGNAL(linePenChanged(const QPen&)), this, SLOT(handleArrowPenChanged(const QPen&)));
83 QObject::connect(axis(), SIGNAL(labelsBrushChanged(const QBrush&)), this, SLOT(handleLabelsBrushChanged(const QBrush&)));
84 QObject::connect(axis(), SIGNAL(labelsBrushChanged(const QBrush&)), this, SLOT(handleLabelsBrushChanged(const QBrush&)));
84 QObject::connect(axis(), SIGNAL(labelsFontChanged(const QFont&)), this, SLOT(handleLabelsFontChanged(const QFont&)));
85 QObject::connect(axis(), SIGNAL(labelsFontChanged(const QFont&)), this, SLOT(handleLabelsFontChanged(const QFont&)));
85 QObject::connect(axis(), SIGNAL(gridLinePenChanged(const QPen&)), this, SLOT(handleGridPenChanged(const QPen&)));
86 QObject::connect(axis(), SIGNAL(gridLinePenChanged(const QPen&)), this, SLOT(handleGridPenChanged(const QPen&)));
86 QObject::connect(axis(), SIGNAL(shadesPenChanged(const QPen&)), this, SLOT(handleShadesPenChanged(const QPen&)));
87 QObject::connect(axis(), SIGNAL(shadesPenChanged(const QPen&)), this, SLOT(handleShadesPenChanged(const QPen&)));
87 QObject::connect(axis(), SIGNAL(shadesBrushChanged(const QBrush&)), this, SLOT(handleShadesBrushChanged(const QBrush&)));
88 QObject::connect(axis(), SIGNAL(shadesBrushChanged(const QBrush&)), this, SLOT(handleShadesBrushChanged(const QBrush&)));
88 QObject::connect(axis(), SIGNAL(titleTextChanged(const QString&)), this, SLOT(handleTitleTextChanged(const QString&)));
89 QObject::connect(axis(), SIGNAL(titleTextChanged(const QString&)), this, SLOT(handleTitleTextChanged(const QString&)));
89 QObject::connect(axis(), SIGNAL(titleFontChanged(const QFont&)), this, SLOT(handleTitleFontChanged(const QFont&)));
90 QObject::connect(axis(), SIGNAL(titleFontChanged(const QFont&)), this, SLOT(handleTitleFontChanged(const QFont&)));
90 QObject::connect(axis(), SIGNAL(titleBrushChanged(const QBrush&)), this, SLOT(handleTitleBrushChanged(const QBrush&)));
91 QObject::connect(axis(), SIGNAL(titleBrushChanged(const QBrush&)), this, SLOT(handleTitleBrushChanged(const QBrush&)));
91 QObject::connect(axis(), SIGNAL(titleVisibleChanged(bool)), this, SLOT(handleTitleVisibleChanged(bool)));
92 QObject::connect(axis(), SIGNAL(titleVisibleChanged(bool)), this, SLOT(handleTitleVisibleChanged(bool)));
92 QObject::connect(axis()->d_ptr.data(), SIGNAL(rangeChanged(qreal, qreal)), this, SLOT(handleRangeChanged(qreal, qreal)));
93 QObject::connect(axis()->d_ptr.data(), SIGNAL(rangeChanged(qreal, qreal)), this, SLOT(handleRangeChanged(qreal, qreal)));
93 }
94 }
94
95
95 void ChartAxisElement::handleArrowVisibleChanged(bool visible)
96 void ChartAxisElement::handleArrowVisibleChanged(bool visible)
96 {
97 {
97 m_arrow->setVisible(visible);
98 m_arrow->setVisible(visible);
98 }
99 }
99
100
100 void ChartAxisElement::handleGridVisibleChanged(bool visible)
101 void ChartAxisElement::handleGridVisibleChanged(bool visible)
101 {
102 {
102 m_grid->setVisible(visible);
103 m_grid->setVisible(visible);
103 }
104 }
104
105
105 void ChartAxisElement::handleLabelsVisibleChanged(bool visible)
106 void ChartAxisElement::handleLabelsVisibleChanged(bool visible)
106 {
107 {
107 QGraphicsLayoutItem::updateGeometry();
108 QGraphicsLayoutItem::updateGeometry();
108 presenter()->layout()->invalidate();
109 presenter()->layout()->invalidate();
109 m_labels->setVisible(visible);
110 m_labels->setVisible(visible);
110 }
111 }
111
112
112 void ChartAxisElement::handleShadesVisibleChanged(bool visible)
113 void ChartAxisElement::handleShadesVisibleChanged(bool visible)
113 {
114 {
114 m_shades->setVisible(visible);
115 m_shades->setVisible(visible);
115 }
116 }
116
117
117 void ChartAxisElement::handleTitleVisibleChanged(bool visible)
118 void ChartAxisElement::handleTitleVisibleChanged(bool visible)
118 {
119 {
119 QGraphicsLayoutItem::updateGeometry();
120 QGraphicsLayoutItem::updateGeometry();
120 presenter()->layout()->invalidate();
121 presenter()->layout()->invalidate();
121 m_title->setVisible(visible);
122 m_title->setVisible(visible);
122 }
123 }
123
124
124 void ChartAxisElement::handleLabelsAngleChanged(int angle)
125 void ChartAxisElement::handleLabelsAngleChanged(int angle)
125 {
126 {
126 foreach (QGraphicsItem *item, m_labels->childItems())
127 foreach (QGraphicsItem *item, m_labels->childItems())
127 item->setRotation(angle);
128 item->setRotation(angle);
128
129
129 QGraphicsLayoutItem::updateGeometry();
130 QGraphicsLayoutItem::updateGeometry();
130 presenter()->layout()->invalidate();
131 presenter()->layout()->invalidate();
131 }
132 }
132
133
133 void ChartAxisElement::handleLabelsBrushChanged(const QBrush &brush)
134 void ChartAxisElement::handleLabelsBrushChanged(const QBrush &brush)
134 {
135 {
135 foreach (QGraphicsItem *item, m_labels->childItems())
136 foreach (QGraphicsItem *item, m_labels->childItems())
136 static_cast<QGraphicsTextItem *>(item)->setDefaultTextColor(brush.color());
137 static_cast<QGraphicsTextItem *>(item)->setDefaultTextColor(brush.color());
137 }
138 }
138
139
139 void ChartAxisElement::handleLabelsFontChanged(const QFont &font)
140 void ChartAxisElement::handleLabelsFontChanged(const QFont &font)
140 {
141 {
141 foreach (QGraphicsItem *item, m_labels->childItems())
142 foreach (QGraphicsItem *item, m_labels->childItems())
142 static_cast<QGraphicsTextItem *>(item)->setFont(font);
143 static_cast<QGraphicsTextItem *>(item)->setFont(font);
143 QGraphicsLayoutItem::updateGeometry();
144 QGraphicsLayoutItem::updateGeometry();
144 presenter()->layout()->invalidate();
145 presenter()->layout()->invalidate();
145 }
146 }
146
147
147 void ChartAxisElement::handleTitleTextChanged(const QString &title)
148 void ChartAxisElement::handleTitleTextChanged(const QString &title)
148 {
149 {
149 QGraphicsLayoutItem::updateGeometry();
150 QGraphicsLayoutItem::updateGeometry();
150 presenter()->layout()->invalidate();
151 presenter()->layout()->invalidate();
151 if (title.isEmpty() || !m_title->isVisible())
152 if (title.isEmpty() || !m_title->isVisible())
152 m_title->setHtml(title);
153 m_title->setHtml(title);
153 }
154 }
154
155
155 void ChartAxisElement::handleTitleBrushChanged(const QBrush &brush)
156 void ChartAxisElement::handleTitleBrushChanged(const QBrush &brush)
156 {
157 {
157 m_title->setDefaultTextColor(brush.color());
158 m_title->setDefaultTextColor(brush.color());
158 }
159 }
159
160
160 void ChartAxisElement::handleTitleFontChanged(const QFont &font)
161 void ChartAxisElement::handleTitleFontChanged(const QFont &font)
161 {
162 {
162 if (m_title->font() != font) {
163 if (m_title->font() != font) {
163 m_title->setFont(font);
164 m_title->setFont(font);
164 QGraphicsLayoutItem::updateGeometry();
165 QGraphicsLayoutItem::updateGeometry();
165 presenter()->layout()->invalidate();
166 presenter()->layout()->invalidate();
166 }
167 }
167 }
168 }
168
169
169 void ChartAxisElement::handleVisibleChanged(bool visible)
170 void ChartAxisElement::handleVisibleChanged(bool visible)
170 {
171 {
171 setVisible(visible);
172 setVisible(visible);
172 if (!visible) {
173 if (!visible) {
173 m_grid->setVisible(visible);
174 m_grid->setVisible(visible);
174 m_arrow->setVisible(visible);
175 m_arrow->setVisible(visible);
175 m_shades->setVisible(visible);
176 m_shades->setVisible(visible);
176 m_labels->setVisible(visible);
177 m_labels->setVisible(visible);
177 m_title->setVisible(visible);
178 m_title->setVisible(visible);
178 } else {
179 } else {
179 m_grid->setVisible(axis()->isGridLineVisible());
180 m_grid->setVisible(axis()->isGridLineVisible());
180 m_arrow->setVisible(axis()->isLineVisible());
181 m_arrow->setVisible(axis()->isLineVisible());
181 m_shades->setVisible(axis()->shadesVisible());
182 m_shades->setVisible(axis()->shadesVisible());
182 m_labels->setVisible(axis()->labelsVisible());
183 m_labels->setVisible(axis()->labelsVisible());
183 m_title->setVisible(axis()->isTitleVisible());
184 m_title->setVisible(axis()->isTitleVisible());
184 }
185 }
185
186
186 if (presenter()) presenter()->layout()->invalidate();
187 if (presenter()) presenter()->layout()->invalidate();
187 }
188 }
188
189
189 void ChartAxisElement::handleRangeChanged(qreal min, qreal max)
190 void ChartAxisElement::handleRangeChanged(qreal min, qreal max)
190 {
191 {
191 Q_UNUSED(min);
192 Q_UNUSED(min);
192 Q_UNUSED(max);
193 Q_UNUSED(max);
193
194
194 if (!isEmpty()) {
195 if (!isEmpty()) {
195 QVector<qreal> layout = calculateLayout();
196 QVector<qreal> layout = calculateLayout();
196 updateLayout(layout);
197 updateLayout(layout);
197 QSizeF before = effectiveSizeHint(Qt::PreferredSize);
198 QSizeF before = effectiveSizeHint(Qt::PreferredSize);
198 QSizeF after = sizeHint(Qt::PreferredSize);
199 QSizeF after = sizeHint(Qt::PreferredSize);
199
200
200 if (before != after) {
201 if (before != after) {
201 QGraphicsLayoutItem::updateGeometry();
202 QGraphicsLayoutItem::updateGeometry();
202 // We don't want to call invalidate on layout, since it will change minimum size of
203 // We don't want to call invalidate on layout, since it will change minimum size of
203 // component, which we would like to avoid since it causes nasty flips when scrolling
204 // component, which we would like to avoid since it causes nasty flips when scrolling
204 // or zooming, instead recalculate layout and use plotArea for extra space.
205 // or zooming, instead recalculate layout and use plotArea for extra space.
205 presenter()->layout()->setGeometry(presenter()->layout()->geometry());
206 presenter()->layout()->setGeometry(presenter()->layout()->geometry());
206 }
207 }
207 }
208 }
208 }
209 }
209
210
210 bool ChartAxisElement::isEmpty()
211 bool ChartAxisElement::isEmpty()
211 {
212 {
212 return axisGeometry().isEmpty()
213 return axisGeometry().isEmpty()
213 || gridGeometry().isEmpty()
214 || gridGeometry().isEmpty()
214 || qFuzzyCompare(min(), max());
215 || qFuzzyCompare(min(), max());
215 }
216 }
216
217
217 qreal ChartAxisElement::min() const
218 qreal ChartAxisElement::min() const
218 {
219 {
219 return m_axis->d_ptr->min();
220 return m_axis->d_ptr->min();
220 }
221 }
221
222
222 qreal ChartAxisElement::max() const
223 qreal ChartAxisElement::max() const
223 {
224 {
224 return m_axis->d_ptr->max();
225 return m_axis->d_ptr->max();
225 }
226 }
226
227
227 QString ChartAxisElement::formatLabel(const QString &formatSpec, const QByteArray &array,
228 QString ChartAxisElement::formatLabel(const QString &formatSpec, const QByteArray &array,
228 qreal value, int precision, const QString &preStr,
229 qreal value, int precision, const QString &preStr,
229 const QString &postStr) const
230 const QString &postStr) const
230 {
231 {
231 QString retVal;
232 QString retVal;
232 if (!formatSpec.isEmpty()) {
233 if (!formatSpec.isEmpty()) {
233 if (formatSpec.at(0) == QLatin1Char('d')
234 if (formatSpec.at(0) == QLatin1Char('d')
234 || formatSpec.at(0) == QLatin1Char('i')
235 || formatSpec.at(0) == QLatin1Char('i')
235 || formatSpec.at(0) == QLatin1Char('c')) {
236 || formatSpec.at(0) == QLatin1Char('c')) {
236 if (presenter()->localizeNumbers())
237 if (presenter()->localizeNumbers())
237 retVal = preStr + presenter()->locale().toString(qint64(value)) + postStr;
238 retVal = preStr + presenter()->locale().toString(qint64(value)) + postStr;
238 else
239 else
239 retVal = QString().sprintf(array, qint64(value));
240 retVal = QString().sprintf(array, qint64(value));
240 } else if (formatSpec.at(0) == QLatin1Char('u')
241 } else if (formatSpec.at(0) == QLatin1Char('u')
241 || formatSpec.at(0) == QLatin1Char('o')
242 || formatSpec.at(0) == QLatin1Char('o')
242 || formatSpec.at(0) == QLatin1Char('x')
243 || formatSpec.at(0) == QLatin1Char('x')
243 || formatSpec.at(0) == QLatin1Char('X')) {
244 || formatSpec.at(0) == QLatin1Char('X')) {
244 // These formats are not supported by localized numbers
245 // These formats are not supported by localized numbers
245 retVal = QString().sprintf(array, quint64(value));
246 retVal = QString().sprintf(array, quint64(value));
246 } else if (formatSpec.at(0) == QLatin1Char('f')
247 } else if (formatSpec.at(0) == QLatin1Char('f')
247 || formatSpec.at(0) == QLatin1Char('F')
248 || formatSpec.at(0) == QLatin1Char('F')
248 || formatSpec.at(0) == QLatin1Char('e')
249 || formatSpec.at(0) == QLatin1Char('e')
249 || formatSpec.at(0) == QLatin1Char('E')
250 || formatSpec.at(0) == QLatin1Char('E')
250 || formatSpec.at(0) == QLatin1Char('g')
251 || formatSpec.at(0) == QLatin1Char('g')
251 || formatSpec.at(0) == QLatin1Char('G')) {
252 || formatSpec.at(0) == QLatin1Char('G')) {
252 if (presenter()->localizeNumbers()) {
253 if (presenter()->localizeNumbers()) {
253 retVal = preStr
254 retVal = preStr
254 + presenter()->locale().toString(value, formatSpec.at(0).toLatin1(),
255 + presenter()->locale().toString(value, formatSpec.at(0).toLatin1(),
255 precision)
256 precision)
256 + postStr;
257 + postStr;
257 } else {
258 } else {
258 retVal = QString().sprintf(array, value);
259 retVal = QString().sprintf(array, value);
259 }
260 }
260 }
261 }
261 }
262 }
262 return retVal;
263 return retVal;
263 }
264 }
264
265
265 QStringList ChartAxisElement::createValueLabels(qreal min, qreal max, int ticks,
266 QStringList ChartAxisElement::createValueLabels(qreal min, qreal max, int ticks,
266 const QString &format) const
267 const QString &format) const
267 {
268 {
268 QStringList labels;
269 QStringList labels;
269
270
270 if (max <= min || ticks < 1)
271 if (max <= min || ticks < 1)
271 return labels;
272 return labels;
272
273
273 if (format.isNull()) {
274 if (format.isNull()) {
274 int n = qMax(int(-qFloor(log10((max - min) / (ticks - 1)))), 0) + 1;
275 int n = qMax(int(-qFloor(std::log10((max - min) / (ticks - 1)))), 0) + 1;
275 for (int i = 0; i < ticks; i++) {
276 for (int i = 0; i < ticks; i++) {
276 qreal value = min + (i * (max - min) / (ticks - 1));
277 qreal value = min + (i * (max - min) / (ticks - 1));
277 labels << presenter()->numberToString(value, 'f', n);
278 labels << presenter()->numberToString(value, 'f', n);
278 }
279 }
279 } else {
280 } else {
280 QByteArray array = format.toLatin1();
281 QByteArray array = format.toLatin1();
281 QString formatSpec;
282 QString formatSpec;
282 QString preStr;
283 QString preStr;
283 QString postStr;
284 QString postStr;
284 int precision = 6; // Six is the default precision in Qt API
285 int precision = 6; // Six is the default precision in Qt API
285 if (presenter()->localizeNumbers()) {
286 if (presenter()->localizeNumbers()) {
286 if (!labelFormatMatcherLocalized)
287 if (!labelFormatMatcherLocalized)
287 labelFormatMatcherLocalized
288 labelFormatMatcherLocalized
288 = new QRegExp(QString::fromLatin1(labelFormatMatchLocalizedString));
289 = new QRegExp(QString::fromLatin1(labelFormatMatchLocalizedString));
289 if (labelFormatMatcherLocalized->indexIn(format, 0) != -1) {
290 if (labelFormatMatcherLocalized->indexIn(format, 0) != -1) {
290 preStr = labelFormatMatcherLocalized->cap(1);
291 preStr = labelFormatMatcherLocalized->cap(1);
291 if (!labelFormatMatcherLocalized->cap(2).isEmpty())
292 if (!labelFormatMatcherLocalized->cap(2).isEmpty())
292 precision = labelFormatMatcherLocalized->cap(2).toInt();
293 precision = labelFormatMatcherLocalized->cap(2).toInt();
293 formatSpec = labelFormatMatcherLocalized->cap(3);
294 formatSpec = labelFormatMatcherLocalized->cap(3);
294 postStr = labelFormatMatcherLocalized->cap(4);
295 postStr = labelFormatMatcherLocalized->cap(4);
295 }
296 }
296 } else {
297 } else {
297 if (!labelFormatMatcher)
298 if (!labelFormatMatcher)
298 labelFormatMatcher = new QRegExp(QString::fromLatin1(labelFormatMatchString));
299 labelFormatMatcher = new QRegExp(QString::fromLatin1(labelFormatMatchString));
299 if (labelFormatMatcher->indexIn(format, 0) != -1)
300 if (labelFormatMatcher->indexIn(format, 0) != -1)
300 formatSpec = labelFormatMatcher->cap(1);
301 formatSpec = labelFormatMatcher->cap(1);
301 }
302 }
302 for (int i = 0; i < ticks; i++) {
303 for (int i = 0; i < ticks; i++) {
303 qreal value = min + (i * (max - min) / (ticks - 1));
304 qreal value = min + (i * (max - min) / (ticks - 1));
304 labels << formatLabel(formatSpec, array, value, precision, preStr, postStr);
305 labels << formatLabel(formatSpec, array, value, precision, preStr, postStr);
305 }
306 }
306 }
307 }
307
308
308 return labels;
309 return labels;
309 }
310 }
310
311
311 QStringList ChartAxisElement::createLogValueLabels(qreal min, qreal max, qreal base, int ticks,
312 QStringList ChartAxisElement::createLogValueLabels(qreal min, qreal max, qreal base, int ticks,
312 const QString &format) const
313 const QString &format) const
313 {
314 {
314 QStringList labels;
315 QStringList labels;
315
316
316 if (max <= min || ticks < 1)
317 if (max <= min || ticks < 1)
317 return labels;
318 return labels;
318
319
319 int firstTick;
320 int firstTick;
320 if (base > 1)
321 if (base > 1)
321 firstTick = ceil(log10(min) / log10(base));
322 firstTick = qCeil(std::log10(min) / std::log10(base));
322 else
323 else
323 firstTick = ceil(log10(max) / log10(base));
324 firstTick = qCeil(std::log10(max) / std::log10(base));
324
325
325 if (format.isNull()) {
326 if (format.isNull()) {
326 int n = 0;
327 int n = 0;
327 if (ticks > 1)
328 if (ticks > 1)
328 n = qMax(int(-qFloor(log10((max - min) / (ticks - 1)))), 0);
329 n = qMax(int(-qFloor(std::log10((max - min) / (ticks - 1)))), 0);
329 n++;
330 n++;
330 for (int i = firstTick; i < ticks + firstTick; i++) {
331 for (int i = firstTick; i < ticks + firstTick; i++) {
331 qreal value = qPow(base, i);
332 qreal value = qPow(base, i);
332 labels << presenter()->numberToString(value, 'f', n);
333 labels << presenter()->numberToString(value, 'f', n);
333 }
334 }
334 } else {
335 } else {
335 QByteArray array = format.toLatin1();
336 QByteArray array = format.toLatin1();
336 QString formatSpec;
337 QString formatSpec;
337 QString preStr;
338 QString preStr;
338 QString postStr;
339 QString postStr;
339 int precision = 6; // Six is the default precision in Qt API
340 int precision = 6; // Six is the default precision in Qt API
340 if (presenter()->localizeNumbers()) {
341 if (presenter()->localizeNumbers()) {
341 if (!labelFormatMatcherLocalized)
342 if (!labelFormatMatcherLocalized)
342 labelFormatMatcherLocalized =
343 labelFormatMatcherLocalized =
343 new QRegExp(QString::fromLatin1(labelFormatMatchLocalizedString));
344 new QRegExp(QString::fromLatin1(labelFormatMatchLocalizedString));
344 if (labelFormatMatcherLocalized->indexIn(format, 0) != -1) {
345 if (labelFormatMatcherLocalized->indexIn(format, 0) != -1) {
345 preStr = labelFormatMatcherLocalized->cap(1);
346 preStr = labelFormatMatcherLocalized->cap(1);
346 if (!labelFormatMatcherLocalized->cap(2).isEmpty())
347 if (!labelFormatMatcherLocalized->cap(2).isEmpty())
347 precision = labelFormatMatcherLocalized->cap(2).toInt();
348 precision = labelFormatMatcherLocalized->cap(2).toInt();
348 formatSpec = labelFormatMatcherLocalized->cap(3);
349 formatSpec = labelFormatMatcherLocalized->cap(3);
349 postStr = labelFormatMatcherLocalized->cap(4);
350 postStr = labelFormatMatcherLocalized->cap(4);
350 }
351 }
351 } else {
352 } else {
352 if (!labelFormatMatcher)
353 if (!labelFormatMatcher)
353 labelFormatMatcher = new QRegExp(QString::fromLatin1(labelFormatMatchString));
354 labelFormatMatcher = new QRegExp(QString::fromLatin1(labelFormatMatchString));
354 if (labelFormatMatcher->indexIn(format, 0) != -1)
355 if (labelFormatMatcher->indexIn(format, 0) != -1)
355 formatSpec = labelFormatMatcher->cap(1);
356 formatSpec = labelFormatMatcher->cap(1);
356 }
357 }
357 for (int i = firstTick; i < ticks + firstTick; i++) {
358 for (int i = firstTick; i < ticks + firstTick; i++) {
358 qreal value = qPow(base, i);
359 qreal value = qPow(base, i);
359 labels << formatLabel(formatSpec, array, value, precision, preStr, postStr);
360 labels << formatLabel(formatSpec, array, value, precision, preStr, postStr);
360 }
361 }
361 }
362 }
362
363
363 return labels;
364 return labels;
364 }
365 }
365
366
366 QStringList ChartAxisElement::createDateTimeLabels(qreal min, qreal max,int ticks,
367 QStringList ChartAxisElement::createDateTimeLabels(qreal min, qreal max,int ticks,
367 const QString &format) const
368 const QString &format) const
368 {
369 {
369 QStringList labels;
370 QStringList labels;
370
371
371 if (max <= min || ticks < 1)
372 if (max <= min || ticks < 1)
372 return labels;
373 return labels;
373
374
374 int n = qMax(int(-floor(log10((max - min) / (ticks - 1)))), 0);
375 int n = qMax(int(-qFloor(std::log10((max - min) / (ticks - 1)))), 0);
375 n++;
376 n++;
376 for (int i = 0; i < ticks; i++) {
377 for (int i = 0; i < ticks; i++) {
377 qreal value = min + (i * (max - min) / (ticks - 1));
378 qreal value = min + (i * (max - min) / (ticks - 1));
378 labels << presenter()->locale().toString(QDateTime::fromMSecsSinceEpoch(value), format);
379 labels << presenter()->locale().toString(QDateTime::fromMSecsSinceEpoch(value), format);
379 }
380 }
380 return labels;
381 return labels;
381 }
382 }
382
383
383 void ChartAxisElement::axisSelected()
384 void ChartAxisElement::axisSelected()
384 {
385 {
385 emit clicked();
386 emit clicked();
386 }
387 }
387
388
388 #include "moc_chartaxiselement_p.cpp"
389 #include "moc_chartaxiselement_p.cpp"
389
390
390 QT_CHARTS_END_NAMESPACE
391 QT_CHARTS_END_NAMESPACE
@@ -1,135 +1,136
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2014 Digia Plc
3 ** Copyright (C) 2014 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.io
5 ** For any questions to Digia, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and Digia.
12 ** agreement between you and Digia.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <private/chartlogvalueaxisx_p.h>
19 #include <private/chartlogvalueaxisx_p.h>
20 #include <private/chartpresenter_p.h>
20 #include <private/chartpresenter_p.h>
21 #include <QtCharts/QLogValueAxis>
21 #include <QtCharts/QLogValueAxis>
22 #include <private/abstractchartlayout_p.h>
22 #include <private/abstractchartlayout_p.h>
23 #include <QtWidgets/QGraphicsLayout>
23 #include <QtWidgets/QGraphicsLayout>
24 #include <QtCore/QtMath>
24 #include <QtCore/QtMath>
25 #include <QtCore/QDebug>
25 #include <QtCore/QDebug>
26 #include <cmath>
26
27
27 QT_CHARTS_BEGIN_NAMESPACE
28 QT_CHARTS_BEGIN_NAMESPACE
28
29
29 ChartLogValueAxisX::ChartLogValueAxisX(QLogValueAxis *axis, QGraphicsItem *item)
30 ChartLogValueAxisX::ChartLogValueAxisX(QLogValueAxis *axis, QGraphicsItem *item)
30 : HorizontalAxis(axis, item),
31 : HorizontalAxis(axis, item),
31 m_axis(axis)
32 m_axis(axis)
32 {
33 {
33 QObject::connect(m_axis, SIGNAL(baseChanged(qreal)), this, SLOT(handleBaseChanged(qreal)));
34 QObject::connect(m_axis, SIGNAL(baseChanged(qreal)), this, SLOT(handleBaseChanged(qreal)));
34 QObject::connect(m_axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
35 QObject::connect(m_axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
35 }
36 }
36
37
37 ChartLogValueAxisX::~ChartLogValueAxisX()
38 ChartLogValueAxisX::~ChartLogValueAxisX()
38 {
39 {
39 }
40 }
40
41
41 QVector<qreal> ChartLogValueAxisX::calculateLayout() const
42 QVector<qreal> ChartLogValueAxisX::calculateLayout() const
42 {
43 {
43 QVector<qreal> points;
44 QVector<qreal> points;
44
45
45 qreal logMax = log10(m_axis->max()) / log10(m_axis->base());
46 qreal logMax = std::log10(m_axis->max()) / std::log10(m_axis->base());
46 qreal logMin = log10(m_axis->min()) / log10(m_axis->base());
47 qreal logMin = std::log10(m_axis->min()) / std::log10(m_axis->base());
47 qreal leftEdge = logMin < logMax ? logMin : logMax;
48 qreal leftEdge = logMin < logMax ? logMin : logMax;
48 qreal ceilEdge = ceil(leftEdge);
49 qreal ceilEdge = qCeil(leftEdge);
49 int tickCount = qAbs(ceil(logMax) - ceil(logMin));
50 int tickCount = qAbs(qCeil(logMax) - qCeil(logMin));
50
51
51 points.resize(tickCount);
52 points.resize(tickCount);
52 const QRectF &gridRect = gridGeometry();
53 const QRectF &gridRect = gridGeometry();
53 const qreal deltaX = gridRect.width() / qAbs(logMax - logMin);
54 const qreal deltaX = gridRect.width() / qAbs(logMax - logMin);
54 for (int i = 0; i < tickCount; ++i)
55 for (int i = 0; i < tickCount; ++i)
55 points[i] = (ceilEdge + qreal(i)) * deltaX - leftEdge * deltaX + gridRect.left();
56 points[i] = (ceilEdge + qreal(i)) * deltaX - leftEdge * deltaX + gridRect.left();
56
57
57 return points;
58 return points;
58 }
59 }
59
60
60 void ChartLogValueAxisX::updateGeometry()
61 void ChartLogValueAxisX::updateGeometry()
61 {
62 {
62 const QVector<qreal>& layout = ChartAxisElement::layout();
63 const QVector<qreal>& layout = ChartAxisElement::layout();
63 setLabels(createLogValueLabels(m_axis->min(), m_axis->max(), m_axis->base(), layout.size(), m_axis->labelFormat()));
64 setLabels(createLogValueLabels(m_axis->min(), m_axis->max(), m_axis->base(), layout.size(), m_axis->labelFormat()));
64 HorizontalAxis::updateGeometry();
65 HorizontalAxis::updateGeometry();
65 }
66 }
66
67
67 void ChartLogValueAxisX::handleBaseChanged(qreal base)
68 void ChartLogValueAxisX::handleBaseChanged(qreal base)
68 {
69 {
69 Q_UNUSED(base);
70 Q_UNUSED(base);
70 QGraphicsLayoutItem::updateGeometry();
71 QGraphicsLayoutItem::updateGeometry();
71 if(presenter()) presenter()->layout()->invalidate();
72 if(presenter()) presenter()->layout()->invalidate();
72 }
73 }
73
74
74 void ChartLogValueAxisX::handleLabelFormatChanged(const QString &format)
75 void ChartLogValueAxisX::handleLabelFormatChanged(const QString &format)
75 {
76 {
76 Q_UNUSED(format);
77 Q_UNUSED(format);
77 QGraphicsLayoutItem::updateGeometry();
78 QGraphicsLayoutItem::updateGeometry();
78 if(presenter()) presenter()->layout()->invalidate();
79 if(presenter()) presenter()->layout()->invalidate();
79 }
80 }
80
81
81 QSizeF ChartLogValueAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
82 QSizeF ChartLogValueAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
82 {
83 {
83 Q_UNUSED(constraint)
84 Q_UNUSED(constraint)
84
85
85 QSizeF sh;
86 QSizeF sh;
86
87
87 QSizeF base = HorizontalAxis::sizeHint(which, constraint);
88 QSizeF base = HorizontalAxis::sizeHint(which, constraint);
88 QStringList ticksList;
89 QStringList ticksList;
89 qreal logMax = log10(m_axis->max()) / log10(m_axis->base());
90 qreal logMax = std::log10(m_axis->max()) / std::log10(m_axis->base());
90 qreal logMin = log10(m_axis->min()) / log10(m_axis->base());
91 qreal logMin = std::log10(m_axis->min()) / std::log10(m_axis->base());
91 int tickCount = qAbs(ceil(logMax) - ceil(logMin));
92 int tickCount = qAbs(qCeil(logMax) - qCeil(logMin));
92 if (m_axis->max() > m_axis->min() && tickCount > 0)
93 if (m_axis->max() > m_axis->min() && tickCount > 0)
93 ticksList = createLogValueLabels(m_axis->min(), m_axis->max(), m_axis->base(), tickCount, m_axis->labelFormat());
94 ticksList = createLogValueLabels(m_axis->min(), m_axis->max(), m_axis->base(), tickCount, m_axis->labelFormat());
94 else
95 else
95 ticksList.append(QStringLiteral(" "));
96 ticksList.append(QStringLiteral(" "));
96 // Width of horizontal axis sizeHint indicates the maximum distance labels can extend past
97 // Width of horizontal axis sizeHint indicates the maximum distance labels can extend past
97 // first and last ticks. Base width is irrelevant.
98 // first and last ticks. Base width is irrelevant.
98 qreal width = 0;
99 qreal width = 0;
99 qreal height = 0;
100 qreal height = 0;
100
101
101 switch (which) {
102 switch (which) {
102 case Qt::MinimumSize:{
103 case Qt::MinimumSize:{
103 QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(),
104 QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(),
104 QStringLiteral("..."),
105 QStringLiteral("..."),
105 axis()->labelsAngle());
106 axis()->labelsAngle());
106 width = boundingRect.width() / 2.0;
107 width = boundingRect.width() / 2.0;
107 height = boundingRect.height() + labelPadding() + base.height() + 1.0;
108 height = boundingRect.height() + labelPadding() + base.height() + 1.0;
108 sh = QSizeF(width, height);
109 sh = QSizeF(width, height);
109 break;
110 break;
110 }
111 }
111 case Qt::PreferredSize: {
112 case Qt::PreferredSize: {
112 qreal labelHeight = 0.0;
113 qreal labelHeight = 0.0;
113 qreal firstWidth = -1.0;
114 qreal firstWidth = -1.0;
114 foreach (const QString& s, ticksList) {
115 foreach (const QString& s, ticksList) {
115 QRectF rect = ChartPresenter::textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
116 QRectF rect = ChartPresenter::textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
116 labelHeight = qMax(rect.height(), labelHeight);
117 labelHeight = qMax(rect.height(), labelHeight);
117 width = rect.width();
118 width = rect.width();
118 if (firstWidth < 0.0)
119 if (firstWidth < 0.0)
119 firstWidth = width;
120 firstWidth = width;
120 }
121 }
121 height = labelHeight + labelPadding() + base.height() + 1.0;
122 height = labelHeight + labelPadding() + base.height() + 1.0;
122 width = qMax(width, firstWidth) / 2.0;
123 width = qMax(width, firstWidth) / 2.0;
123 sh = QSizeF(width, height);
124 sh = QSizeF(width, height);
124 break;
125 break;
125 }
126 }
126 default:
127 default:
127 break;
128 break;
128 }
129 }
129
130
130 return sh;
131 return sh;
131 }
132 }
132
133
133 #include "moc_chartlogvalueaxisx_p.cpp"
134 #include "moc_chartlogvalueaxisx_p.cpp"
134
135
135 QT_CHARTS_END_NAMESPACE
136 QT_CHARTS_END_NAMESPACE
@@ -1,135 +1,136
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2014 Digia Plc
3 ** Copyright (C) 2014 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.io
5 ** For any questions to Digia, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and Digia.
12 ** agreement between you and Digia.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <private/chartlogvalueaxisy_p.h>
19 #include <private/chartlogvalueaxisy_p.h>
20 #include <private/chartpresenter_p.h>
20 #include <private/chartpresenter_p.h>
21 #include <QtCharts/QLogValueAxis>
21 #include <QtCharts/QLogValueAxis>
22 #include <private/abstractchartlayout_p.h>
22 #include <private/abstractchartlayout_p.h>
23 #include <QtWidgets/QGraphicsLayout>
23 #include <QtWidgets/QGraphicsLayout>
24 #include <QtCore/QtMath>
24 #include <QtCore/QtMath>
25 #include <QtCore/QDebug>
25 #include <QtCore/QDebug>
26 #include <cmath>
26
27
27 QT_CHARTS_BEGIN_NAMESPACE
28 QT_CHARTS_BEGIN_NAMESPACE
28
29
29 ChartLogValueAxisY::ChartLogValueAxisY(QLogValueAxis *axis, QGraphicsItem *item)
30 ChartLogValueAxisY::ChartLogValueAxisY(QLogValueAxis *axis, QGraphicsItem *item)
30 : VerticalAxis(axis, item),
31 : VerticalAxis(axis, item),
31 m_axis(axis)
32 m_axis(axis)
32 {
33 {
33 QObject::connect(m_axis, SIGNAL(baseChanged(qreal)), this, SLOT(handleBaseChanged(qreal)));
34 QObject::connect(m_axis, SIGNAL(baseChanged(qreal)), this, SLOT(handleBaseChanged(qreal)));
34 QObject::connect(m_axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
35 QObject::connect(m_axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
35 }
36 }
36
37
37 ChartLogValueAxisY::~ChartLogValueAxisY()
38 ChartLogValueAxisY::~ChartLogValueAxisY()
38 {
39 {
39 }
40 }
40
41
41 QVector<qreal> ChartLogValueAxisY::calculateLayout() const
42 QVector<qreal> ChartLogValueAxisY::calculateLayout() const
42 {
43 {
43 QVector<qreal> points;
44 QVector<qreal> points;
44 qreal logMax = log10(m_axis->max()) / log10(m_axis->base());
45 qreal logMax = std::log10(m_axis->max()) / std::log10(m_axis->base());
45 qreal logMin = log10(m_axis->min()) / log10(m_axis->base());
46 qreal logMin = std::log10(m_axis->min()) / std::log10(m_axis->base());
46 qreal leftEdge = logMin < logMax ? logMin : logMax;
47 qreal leftEdge = logMin < logMax ? logMin : logMax;
47 qreal ceilEdge = ceil(leftEdge);
48 qreal ceilEdge = qCeil(leftEdge);
48 int tickCount = qAbs(ceil(logMax) - ceil(logMin));
49 int tickCount = qAbs(qCeil(logMax) - qCeil(logMin));
49
50
50 points.resize(tickCount);
51 points.resize(tickCount);
51 const QRectF &gridRect = gridGeometry();
52 const QRectF &gridRect = gridGeometry();
52 const qreal deltaY = gridRect.height() / qAbs(logMax - logMin);
53 const qreal deltaY = gridRect.height() / qAbs(logMax - logMin);
53 for (int i = 0; i < tickCount; ++i)
54 for (int i = 0; i < tickCount; ++i)
54 points[i] = (ceilEdge + qreal(i)) * -deltaY - leftEdge * -deltaY + gridRect.bottom();
55 points[i] = (ceilEdge + qreal(i)) * -deltaY - leftEdge * -deltaY + gridRect.bottom();
55
56
56 return points;
57 return points;
57 }
58 }
58
59
59
60
60 void ChartLogValueAxisY::updateGeometry()
61 void ChartLogValueAxisY::updateGeometry()
61 {
62 {
62 const QVector<qreal> &layout = ChartAxisElement::layout();
63 const QVector<qreal> &layout = ChartAxisElement::layout();
63 setLabels(createLogValueLabels(m_axis->min(), m_axis->max(), m_axis->base(), layout.size(), m_axis->labelFormat()));
64 setLabels(createLogValueLabels(m_axis->min(), m_axis->max(), m_axis->base(), layout.size(), m_axis->labelFormat()));
64 VerticalAxis::updateGeometry();
65 VerticalAxis::updateGeometry();
65 }
66 }
66
67
67 void ChartLogValueAxisY::handleBaseChanged(qreal base)
68 void ChartLogValueAxisY::handleBaseChanged(qreal base)
68 {
69 {
69 Q_UNUSED(base);
70 Q_UNUSED(base);
70 QGraphicsLayoutItem::updateGeometry();
71 QGraphicsLayoutItem::updateGeometry();
71 if(presenter()) presenter()->layout()->invalidate();
72 if(presenter()) presenter()->layout()->invalidate();
72 }
73 }
73
74
74 void ChartLogValueAxisY::handleLabelFormatChanged(const QString &format)
75 void ChartLogValueAxisY::handleLabelFormatChanged(const QString &format)
75 {
76 {
76 Q_UNUSED(format);
77 Q_UNUSED(format);
77 QGraphicsLayoutItem::updateGeometry();
78 QGraphicsLayoutItem::updateGeometry();
78 if(presenter()) presenter()->layout()->invalidate();
79 if(presenter()) presenter()->layout()->invalidate();
79 }
80 }
80
81
81 QSizeF ChartLogValueAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
82 QSizeF ChartLogValueAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
82 {
83 {
83 Q_UNUSED(constraint)
84 Q_UNUSED(constraint)
84
85
85 QSizeF sh;
86 QSizeF sh;
86
87
87 QSizeF base = VerticalAxis::sizeHint(which, constraint);
88 QSizeF base = VerticalAxis::sizeHint(which, constraint);
88 QStringList ticksList;
89 QStringList ticksList;
89 qreal logMax = log10(m_axis->max()) / log10(m_axis->base());
90 qreal logMax = std::log10(m_axis->max()) / std::log10(m_axis->base());
90 qreal logMin = log10(m_axis->min()) / log10(m_axis->base());
91 qreal logMin = std::log10(m_axis->min()) / std::log10(m_axis->base());
91 int tickCount = qAbs(ceil(logMax) - ceil(logMin));
92 int tickCount = qAbs(qCeil(logMax) - qCeil(logMin));
92 if (m_axis->max() > m_axis->min() && tickCount > 0)
93 if (m_axis->max() > m_axis->min() && tickCount > 0)
93 ticksList = createLogValueLabels(m_axis->min(), m_axis->max(), m_axis->base(), tickCount, m_axis->labelFormat());
94 ticksList = createLogValueLabels(m_axis->min(), m_axis->max(), m_axis->base(), tickCount, m_axis->labelFormat());
94 else
95 else
95 ticksList.append(QStringLiteral(" "));
96 ticksList.append(QStringLiteral(" "));
96 qreal width = 0;
97 qreal width = 0;
97 // Height of vertical axis sizeHint indicates the maximum distance labels can extend past
98 // Height of vertical axis sizeHint indicates the maximum distance labels can extend past
98 // first and last ticks. Base height is irrelevant.
99 // first and last ticks. Base height is irrelevant.
99 qreal height = 0;
100 qreal height = 0;
100
101
101 switch (which) {
102 switch (which) {
102 case Qt::MinimumSize: {
103 case Qt::MinimumSize: {
103 QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(),
104 QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(),
104 QStringLiteral("..."),
105 QStringLiteral("..."),
105 axis()->labelsAngle());
106 axis()->labelsAngle());
106 width = boundingRect.width() + labelPadding() + base.width() + 1.0;
107 width = boundingRect.width() + labelPadding() + base.width() + 1.0;
107 height = boundingRect.height() / 2.0;
108 height = boundingRect.height() / 2.0;
108 sh = QSizeF(width, height);
109 sh = QSizeF(width, height);
109 break;
110 break;
110 }
111 }
111 case Qt::PreferredSize: {
112 case Qt::PreferredSize: {
112 qreal labelWidth = 0.0;
113 qreal labelWidth = 0.0;
113 qreal firstHeight = -1.0;
114 qreal firstHeight = -1.0;
114 foreach (const QString& s, ticksList) {
115 foreach (const QString& s, ticksList) {
115 QRectF rect = ChartPresenter::textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
116 QRectF rect = ChartPresenter::textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
116 labelWidth = qMax(rect.width(), labelWidth);
117 labelWidth = qMax(rect.width(), labelWidth);
117 height = rect.height();
118 height = rect.height();
118 if (firstHeight < 0.0)
119 if (firstHeight < 0.0)
119 firstHeight = height;
120 firstHeight = height;
120 }
121 }
121 width = labelWidth + labelPadding() + base.width() + 2.0; //two pixels of tolerance
122 width = labelWidth + labelPadding() + base.width() + 2.0; //two pixels of tolerance
122 height = qMax(height, firstHeight) / 2.0;
123 height = qMax(height, firstHeight) / 2.0;
123 sh = QSizeF(width, height);
124 sh = QSizeF(width, height);
124 break;
125 break;
125 }
126 }
126 default:
127 default:
127 break;
128 break;
128 }
129 }
129
130
130 return sh;
131 return sh;
131 }
132 }
132
133
133 #include "moc_chartlogvalueaxisy_p.cpp"
134 #include "moc_chartlogvalueaxisy_p.cpp"
134
135
135 QT_CHARTS_END_NAMESPACE
136 QT_CHARTS_END_NAMESPACE
@@ -1,88 +1,89
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2014 Digia Plc
3 ** Copyright (C) 2014 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.io
5 ** For any questions to Digia, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and Digia.
12 ** agreement between you and Digia.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <private/polarchartlogvalueaxisangular_p.h>
19 #include <private/polarchartlogvalueaxisangular_p.h>
20 #include <private/abstractchartlayout_p.h>
20 #include <private/abstractchartlayout_p.h>
21 #include <private/chartpresenter_p.h>
21 #include <private/chartpresenter_p.h>
22 #include <QtCharts/QLogValueAxis>
22 #include <QtCharts/QLogValueAxis>
23 #include <QtCore/QtMath>
23 #include <QtCore/QtMath>
24 #include <QtCore/QDebug>
24 #include <QtCore/QDebug>
25 #include <cmath>
25
26
26 QT_CHARTS_BEGIN_NAMESPACE
27 QT_CHARTS_BEGIN_NAMESPACE
27
28
28 PolarChartLogValueAxisAngular::PolarChartLogValueAxisAngular(QLogValueAxis *axis, QGraphicsItem *item)
29 PolarChartLogValueAxisAngular::PolarChartLogValueAxisAngular(QLogValueAxis *axis, QGraphicsItem *item)
29 : PolarChartAxisAngular(axis, item)
30 : PolarChartAxisAngular(axis, item)
30 {
31 {
31 QObject::connect(axis, SIGNAL(baseChanged(qreal)), this, SLOT(handleBaseChanged(qreal)));
32 QObject::connect(axis, SIGNAL(baseChanged(qreal)), this, SLOT(handleBaseChanged(qreal)));
32 QObject::connect(axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
33 QObject::connect(axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
33 }
34 }
34
35
35 PolarChartLogValueAxisAngular::~PolarChartLogValueAxisAngular()
36 PolarChartLogValueAxisAngular::~PolarChartLogValueAxisAngular()
36 {
37 {
37 }
38 }
38
39
39 QVector<qreal> PolarChartLogValueAxisAngular::calculateLayout() const
40 QVector<qreal> PolarChartLogValueAxisAngular::calculateLayout() const
40 {
41 {
41 QLogValueAxis *logValueAxis = static_cast<QLogValueAxis *>(axis());
42 QLogValueAxis *logValueAxis = static_cast<QLogValueAxis *>(axis());
42 const qreal logMax = log10(logValueAxis->max()) / log10(logValueAxis->base());
43 const qreal logMax = std::log10(logValueAxis->max()) / std::log10(logValueAxis->base());
43 const qreal logMin = log10(logValueAxis->min()) / log10(logValueAxis->base());
44 const qreal logMin = std::log10(logValueAxis->min()) / std::log10(logValueAxis->base());
44 const qreal startEdge = logMin < logMax ? logMin : logMax;
45 const qreal startEdge = logMin < logMax ? logMin : logMax;
45 const qreal delta = 360.0 / qAbs(logMax - logMin);
46 const qreal delta = 360.0 / qAbs(logMax - logMin);
46 const qreal initialSpan = (ceil(startEdge) - startEdge) * delta;
47 const qreal initialSpan = (qCeil(startEdge) - startEdge) * delta;
47 int tickCount = qAbs(ceil(logMax) - ceil(logMin));
48 int tickCount = qAbs(qCeil(logMax) - qCeil(logMin));
48
49
49 QVector<qreal> points;
50 QVector<qreal> points;
50 points.resize(tickCount);
51 points.resize(tickCount);
51
52
52 for (int i = 0; i < tickCount; ++i) {
53 for (int i = 0; i < tickCount; ++i) {
53 qreal angularCoordinate = initialSpan + (delta * qreal(i));
54 qreal angularCoordinate = initialSpan + (delta * qreal(i));
54 points[i] = angularCoordinate;
55 points[i] = angularCoordinate;
55 }
56 }
56
57
57 return points;
58 return points;
58 }
59 }
59
60
60 void PolarChartLogValueAxisAngular::createAxisLabels(const QVector<qreal> &layout)
61 void PolarChartLogValueAxisAngular::createAxisLabels(const QVector<qreal> &layout)
61 {
62 {
62 QLogValueAxis *logValueAxis = static_cast<QLogValueAxis *>(axis());
63 QLogValueAxis *logValueAxis = static_cast<QLogValueAxis *>(axis());
63 setLabels(createLogValueLabels(logValueAxis->min(),
64 setLabels(createLogValueLabels(logValueAxis->min(),
64 logValueAxis->max(),
65 logValueAxis->max(),
65 logValueAxis->base(),
66 logValueAxis->base(),
66 layout.size(),
67 layout.size(),
67 logValueAxis->labelFormat()));
68 logValueAxis->labelFormat()));
68 }
69 }
69
70
70 void PolarChartLogValueAxisAngular::handleBaseChanged(qreal base)
71 void PolarChartLogValueAxisAngular::handleBaseChanged(qreal base)
71 {
72 {
72 Q_UNUSED(base);
73 Q_UNUSED(base);
73 QGraphicsLayoutItem::updateGeometry();
74 QGraphicsLayoutItem::updateGeometry();
74 if (presenter())
75 if (presenter())
75 presenter()->layout()->invalidate();
76 presenter()->layout()->invalidate();
76 }
77 }
77
78
78 void PolarChartLogValueAxisAngular::handleLabelFormatChanged(const QString &format)
79 void PolarChartLogValueAxisAngular::handleLabelFormatChanged(const QString &format)
79 {
80 {
80 Q_UNUSED(format);
81 Q_UNUSED(format);
81 QGraphicsLayoutItem::updateGeometry();
82 QGraphicsLayoutItem::updateGeometry();
82 if (presenter())
83 if (presenter())
83 presenter()->layout()->invalidate();
84 presenter()->layout()->invalidate();
84 }
85 }
85
86
86 #include "moc_polarchartlogvalueaxisangular_p.cpp"
87 #include "moc_polarchartlogvalueaxisangular_p.cpp"
87
88
88 QT_CHARTS_END_NAMESPACE
89 QT_CHARTS_END_NAMESPACE
@@ -1,93 +1,94
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2014 Digia Plc
3 ** Copyright (C) 2014 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.io
5 ** For any questions to Digia, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and Digia.
12 ** agreement between you and Digia.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <private/polarchartlogvalueaxisradial_p.h>
19 #include <private/polarchartlogvalueaxisradial_p.h>
20 #include <private/abstractchartlayout_p.h>
20 #include <private/abstractchartlayout_p.h>
21 #include <private/chartpresenter_p.h>
21 #include <private/chartpresenter_p.h>
22 #include <QtCharts/QLogValueAxis>
22 #include <QtCharts/QLogValueAxis>
23 #include <QtCore/QtMath>
23 #include <QtCore/QtMath>
24 #include <QtCore/QDebug>
24 #include <QtCore/QDebug>
25 #include <cmath>
25
26
26 QT_CHARTS_BEGIN_NAMESPACE
27 QT_CHARTS_BEGIN_NAMESPACE
27
28
28 PolarChartLogValueAxisRadial::PolarChartLogValueAxisRadial(QLogValueAxis *axis, QGraphicsItem *item)
29 PolarChartLogValueAxisRadial::PolarChartLogValueAxisRadial(QLogValueAxis *axis, QGraphicsItem *item)
29 : PolarChartAxisRadial(axis, item)
30 : PolarChartAxisRadial(axis, item)
30 {
31 {
31 QObject::connect(axis, SIGNAL(baseChanged(qreal)), this, SLOT(handleBaseChanged(qreal)));
32 QObject::connect(axis, SIGNAL(baseChanged(qreal)), this, SLOT(handleBaseChanged(qreal)));
32 QObject::connect(axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
33 QObject::connect(axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
33 }
34 }
34
35
35 PolarChartLogValueAxisRadial::~PolarChartLogValueAxisRadial()
36 PolarChartLogValueAxisRadial::~PolarChartLogValueAxisRadial()
36 {
37 {
37 }
38 }
38
39
39 QVector<qreal> PolarChartLogValueAxisRadial::calculateLayout() const
40 QVector<qreal> PolarChartLogValueAxisRadial::calculateLayout() const
40 {
41 {
41 QLogValueAxis *logValueAxis = static_cast<QLogValueAxis *>(axis());
42 QLogValueAxis *logValueAxis = static_cast<QLogValueAxis *>(axis());
42 const qreal logMax = log10(logValueAxis->max()) / log10(logValueAxis->base());
43 const qreal logMax = std::log10(logValueAxis->max()) / std::log10(logValueAxis->base());
43 const qreal logMin = log10(logValueAxis->min()) / log10(logValueAxis->base());
44 const qreal logMin = std::log10(logValueAxis->min()) / std::log10(logValueAxis->base());
44 const qreal innerEdge = logMin < logMax ? logMin : logMax;
45 const qreal innerEdge = logMin < logMax ? logMin : logMax;
45 const qreal outerEdge = logMin > logMax ? logMin : logMax;
46 const qreal outerEdge = logMin > logMax ? logMin : logMax;
46 const qreal delta = (axisGeometry().width() / 2.0) / qAbs(logMax - logMin);
47 const qreal delta = (axisGeometry().width() / 2.0) / qAbs(logMax - logMin);
47 const qreal initialSpan = (ceil(innerEdge) - innerEdge) * delta;
48 const qreal initialSpan = (qCeil(innerEdge) - innerEdge) * delta;
48 int tickCount = qAbs(ceil(logMax) - ceil(logMin));
49 int tickCount = qAbs(qCeil(logMax) - qCeil(logMin));
49
50
50 // Extra tick if outer edge is exactly at the tick
51 // Extra tick if outer edge is exactly at the tick
51 if (outerEdge == ceil(outerEdge))
52 if (outerEdge == qCeil(outerEdge))
52 tickCount++;
53 tickCount++;
53
54
54 QVector<qreal> points;
55 QVector<qreal> points;
55 points.resize(tickCount);
56 points.resize(tickCount);
56
57
57 for (int i = 0; i < tickCount; ++i) {
58 for (int i = 0; i < tickCount; ++i) {
58 qreal radialCoordinate = initialSpan + (delta * qreal(i));
59 qreal radialCoordinate = initialSpan + (delta * qreal(i));
59 points[i] = radialCoordinate;
60 points[i] = radialCoordinate;
60 }
61 }
61
62
62 return points;
63 return points;
63 }
64 }
64
65
65 void PolarChartLogValueAxisRadial::createAxisLabels(const QVector<qreal> &layout)
66 void PolarChartLogValueAxisRadial::createAxisLabels(const QVector<qreal> &layout)
66 {
67 {
67 QLogValueAxis *logValueAxis = static_cast<QLogValueAxis *>(axis());
68 QLogValueAxis *logValueAxis = static_cast<QLogValueAxis *>(axis());
68 setLabels(createLogValueLabels(logValueAxis->min(),
69 setLabels(createLogValueLabels(logValueAxis->min(),
69 logValueAxis->max(),
70 logValueAxis->max(),
70 logValueAxis->base(),
71 logValueAxis->base(),
71 layout.size(),
72 layout.size(),
72 logValueAxis->labelFormat()));
73 logValueAxis->labelFormat()));
73 }
74 }
74
75
75 void PolarChartLogValueAxisRadial::handleBaseChanged(qreal base)
76 void PolarChartLogValueAxisRadial::handleBaseChanged(qreal base)
76 {
77 {
77 Q_UNUSED(base);
78 Q_UNUSED(base);
78 QGraphicsLayoutItem::updateGeometry();
79 QGraphicsLayoutItem::updateGeometry();
79 if (presenter())
80 if (presenter())
80 presenter()->layout()->invalidate();
81 presenter()->layout()->invalidate();
81 }
82 }
82
83
83 void PolarChartLogValueAxisRadial::handleLabelFormatChanged(const QString &format)
84 void PolarChartLogValueAxisRadial::handleLabelFormatChanged(const QString &format)
84 {
85 {
85 Q_UNUSED(format);
86 Q_UNUSED(format);
86 QGraphicsLayoutItem::updateGeometry();
87 QGraphicsLayoutItem::updateGeometry();
87 if (presenter())
88 if (presenter())
88 presenter()->layout()->invalidate();
89 presenter()->layout()->invalidate();
89 }
90 }
90
91
91 #include "moc_polarchartlogvalueaxisradial_p.cpp"
92 #include "moc_polarchartlogvalueaxisradial_p.cpp"
92
93
93 QT_CHARTS_END_NAMESPACE
94 QT_CHARTS_END_NAMESPACE
@@ -1,263 +1,264
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2014 Digia Plc
3 ** Copyright (C) 2014 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.io
5 ** For any questions to Digia, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and Digia.
12 ** agreement between you and Digia.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <private/abstractdomain_p.h>
19 #include <private/abstractdomain_p.h>
20 #include <private/qabstractaxis_p.h>
20 #include <private/qabstractaxis_p.h>
21 #include <QtCore/QtMath>
21 #include <QtCore/QtMath>
22 #include <cmath>
22
23
23 QT_CHARTS_BEGIN_NAMESPACE
24 QT_CHARTS_BEGIN_NAMESPACE
24
25
25 AbstractDomain::AbstractDomain(QObject *parent)
26 AbstractDomain::AbstractDomain(QObject *parent)
26 : QObject(parent),
27 : QObject(parent),
27 m_minX(0),
28 m_minX(0),
28 m_maxX(0),
29 m_maxX(0),
29 m_minY(0),
30 m_minY(0),
30 m_maxY(0),
31 m_maxY(0),
31 m_signalsBlocked(false),
32 m_signalsBlocked(false),
32 m_zoomed(false),
33 m_zoomed(false),
33 m_zoomResetMinX(0),
34 m_zoomResetMinX(0),
34 m_zoomResetMaxX(0),
35 m_zoomResetMaxX(0),
35 m_zoomResetMinY(0),
36 m_zoomResetMinY(0),
36 m_zoomResetMaxY(0)
37 m_zoomResetMaxY(0)
37
38
38 {
39 {
39 }
40 }
40
41
41 AbstractDomain::~AbstractDomain()
42 AbstractDomain::~AbstractDomain()
42 {
43 {
43 }
44 }
44
45
45 void AbstractDomain::setSize(const QSizeF &size)
46 void AbstractDomain::setSize(const QSizeF &size)
46 {
47 {
47 if (m_size != size) {
48 if (m_size != size) {
48 m_size=size;
49 m_size=size;
49 emit updated();
50 emit updated();
50 }
51 }
51 }
52 }
52
53
53 QSizeF AbstractDomain::size() const
54 QSizeF AbstractDomain::size() const
54 {
55 {
55 return m_size;
56 return m_size;
56 }
57 }
57
58
58 void AbstractDomain::setRangeX(qreal min, qreal max)
59 void AbstractDomain::setRangeX(qreal min, qreal max)
59 {
60 {
60 setRange(min, max, m_minY, m_maxY);
61 setRange(min, max, m_minY, m_maxY);
61 }
62 }
62
63
63 void AbstractDomain::setRangeY(qreal min, qreal max)
64 void AbstractDomain::setRangeY(qreal min, qreal max)
64 {
65 {
65 setRange(m_minX, m_maxX, min, max);
66 setRange(m_minX, m_maxX, min, max);
66 }
67 }
67
68
68 void AbstractDomain::setMinX(qreal min)
69 void AbstractDomain::setMinX(qreal min)
69 {
70 {
70 setRange(min, m_maxX, m_minY, m_maxY);
71 setRange(min, m_maxX, m_minY, m_maxY);
71 }
72 }
72
73
73 void AbstractDomain::setMaxX(qreal max)
74 void AbstractDomain::setMaxX(qreal max)
74 {
75 {
75 setRange(m_minX, max, m_minY, m_maxY);
76 setRange(m_minX, max, m_minY, m_maxY);
76 }
77 }
77
78
78 void AbstractDomain::setMinY(qreal min)
79 void AbstractDomain::setMinY(qreal min)
79 {
80 {
80 setRange(m_minX, m_maxX, min, m_maxY);
81 setRange(m_minX, m_maxX, min, m_maxY);
81 }
82 }
82
83
83 void AbstractDomain::setMaxY(qreal max)
84 void AbstractDomain::setMaxY(qreal max)
84 {
85 {
85 setRange(m_minX, m_maxX, m_minY, max);
86 setRange(m_minX, m_maxX, m_minY, max);
86 }
87 }
87
88
88 qreal AbstractDomain::spanX() const
89 qreal AbstractDomain::spanX() const
89 {
90 {
90 Q_ASSERT(m_maxX >= m_minX);
91 Q_ASSERT(m_maxX >= m_minX);
91 return m_maxX - m_minX;
92 return m_maxX - m_minX;
92 }
93 }
93
94
94 qreal AbstractDomain::spanY() const
95 qreal AbstractDomain::spanY() const
95 {
96 {
96 Q_ASSERT(m_maxY >= m_minY);
97 Q_ASSERT(m_maxY >= m_minY);
97 return m_maxY - m_minY;
98 return m_maxY - m_minY;
98 }
99 }
99
100
100 bool AbstractDomain::isEmpty() const
101 bool AbstractDomain::isEmpty() const
101 {
102 {
102 return qFuzzyCompare(spanX(), 0) || qFuzzyCompare(spanY(), 0) || m_size.isEmpty();
103 return qFuzzyCompare(spanX(), 0) || qFuzzyCompare(spanY(), 0) || m_size.isEmpty();
103 }
104 }
104
105
105 QPointF AbstractDomain::calculateDomainPoint(const QPointF &point) const
106 QPointF AbstractDomain::calculateDomainPoint(const QPointF &point) const
106 {
107 {
107 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
108 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
108 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
109 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
109 qreal x = point.x() / deltaX + m_minX;
110 qreal x = point.x() / deltaX + m_minX;
110 qreal y = (point.y() - m_size.height()) / (-deltaY) + m_minY;
111 qreal y = (point.y() - m_size.height()) / (-deltaY) + m_minY;
111 return QPointF(x, y);
112 return QPointF(x, y);
112 }
113 }
113
114
114 // handlers
115 // handlers
115
116
116 void AbstractDomain::handleVerticalAxisRangeChanged(qreal min, qreal max)
117 void AbstractDomain::handleVerticalAxisRangeChanged(qreal min, qreal max)
117 {
118 {
118 setRangeY(min, max);
119 setRangeY(min, max);
119 }
120 }
120
121
121 void AbstractDomain::handleHorizontalAxisRangeChanged(qreal min, qreal max)
122 void AbstractDomain::handleHorizontalAxisRangeChanged(qreal min, qreal max)
122 {
123 {
123 setRangeX(min, max);
124 setRangeX(min, max);
124 }
125 }
125
126
126 void AbstractDomain::blockRangeSignals(bool block)
127 void AbstractDomain::blockRangeSignals(bool block)
127 {
128 {
128 if (m_signalsBlocked!=block) {
129 if (m_signalsBlocked!=block) {
129 m_signalsBlocked=block;
130 m_signalsBlocked=block;
130 if (!block) {
131 if (!block) {
131 emit rangeHorizontalChanged(m_minX,m_maxX);
132 emit rangeHorizontalChanged(m_minX,m_maxX);
132 emit rangeVerticalChanged(m_minY,m_maxY);
133 emit rangeVerticalChanged(m_minY,m_maxY);
133 }
134 }
134 }
135 }
135 }
136 }
136
137
137 void AbstractDomain::zoomReset()
138 void AbstractDomain::zoomReset()
138 {
139 {
139 if (m_zoomed) {
140 if (m_zoomed) {
140 setRange(m_zoomResetMinX,
141 setRange(m_zoomResetMinX,
141 m_zoomResetMaxX,
142 m_zoomResetMaxX,
142 m_zoomResetMinY,
143 m_zoomResetMinY,
143 m_zoomResetMaxY);
144 m_zoomResetMaxY);
144 m_zoomed = false;
145 m_zoomed = false;
145 }
146 }
146 }
147 }
147
148
148 void AbstractDomain::storeZoomReset()
149 void AbstractDomain::storeZoomReset()
149 {
150 {
150 if (!m_zoomed) {
151 if (!m_zoomed) {
151 m_zoomed = true;
152 m_zoomed = true;
152 m_zoomResetMinX = m_minX;
153 m_zoomResetMinX = m_minX;
153 m_zoomResetMaxX = m_maxX;
154 m_zoomResetMaxX = m_maxX;
154 m_zoomResetMinY = m_minY;
155 m_zoomResetMinY = m_minY;
155 m_zoomResetMaxY = m_maxY;
156 m_zoomResetMaxY = m_maxY;
156 }
157 }
157 }
158 }
158
159
159 //algorithm defined by Paul S.Heckbert GraphicalGems I
160 //algorithm defined by Paul S.Heckbert GraphicalGems I
160
161
161 void AbstractDomain::looseNiceNumbers(qreal &min, qreal &max, int &ticksCount)
162 void AbstractDomain::looseNiceNumbers(qreal &min, qreal &max, int &ticksCount)
162 {
163 {
163 qreal range = niceNumber(max - min, true); //range with ceiling
164 qreal range = niceNumber(max - min, true); //range with ceiling
164 qreal step = niceNumber(range / (ticksCount - 1), false);
165 qreal step = niceNumber(range / (ticksCount - 1), false);
165 min = qFloor(min / step);
166 min = qFloor(min / step);
166 max = qCeil(max / step);
167 max = qCeil(max / step);
167 ticksCount = int(max - min) + 1;
168 ticksCount = int(max - min) + 1;
168 min *= step;
169 min *= step;
169 max *= step;
170 max *= step;
170 }
171 }
171
172
172 //nice numbers can be expressed as form of 1*10^n, 2* 10^n or 5*10^n
173 //nice numbers can be expressed as form of 1*10^n, 2* 10^n or 5*10^n
173
174
174 qreal AbstractDomain::niceNumber(qreal x, bool ceiling)
175 qreal AbstractDomain::niceNumber(qreal x, bool ceiling)
175 {
176 {
176 qreal z = qPow(10, qFloor(log10(x))); //find corresponding number of the form of 10^n than is smaller than x
177 qreal z = qPow(10, qFloor(std::log10(x))); //find corresponding number of the form of 10^n than is smaller than x
177 qreal q = x / z; //q<10 && q>=1;
178 qreal q = x / z; //q<10 && q>=1;
178
179
179 if (ceiling) {
180 if (ceiling) {
180 if (q <= 1.0) q = 1;
181 if (q <= 1.0) q = 1;
181 else if (q <= 2.0) q = 2;
182 else if (q <= 2.0) q = 2;
182 else if (q <= 5.0) q = 5;
183 else if (q <= 5.0) q = 5;
183 else q = 10;
184 else q = 10;
184 } else {
185 } else {
185 if (q < 1.5) q = 1;
186 if (q < 1.5) q = 1;
186 else if (q < 3.0) q = 2;
187 else if (q < 3.0) q = 2;
187 else if (q < 7.0) q = 5;
188 else if (q < 7.0) q = 5;
188 else q = 10;
189 else q = 10;
189 }
190 }
190 return q * z;
191 return q * z;
191 }
192 }
192
193
193 bool AbstractDomain::attachAxis(QAbstractAxis *axis)
194 bool AbstractDomain::attachAxis(QAbstractAxis *axis)
194 {
195 {
195 if (axis->orientation() == Qt::Vertical) {
196 if (axis->orientation() == Qt::Vertical) {
196 QObject::connect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleVerticalAxisRangeChanged(qreal,qreal)));
197 QObject::connect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleVerticalAxisRangeChanged(qreal,qreal)));
197 QObject::connect(this, SIGNAL(rangeVerticalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
198 QObject::connect(this, SIGNAL(rangeVerticalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
198 }
199 }
199
200
200 if (axis->orientation() == Qt::Horizontal) {
201 if (axis->orientation() == Qt::Horizontal) {
201 QObject::connect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleHorizontalAxisRangeChanged(qreal,qreal)));
202 QObject::connect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleHorizontalAxisRangeChanged(qreal,qreal)));
202 QObject::connect(this, SIGNAL(rangeHorizontalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
203 QObject::connect(this, SIGNAL(rangeHorizontalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
203 }
204 }
204
205
205 return true;
206 return true;
206 }
207 }
207
208
208 bool AbstractDomain::detachAxis(QAbstractAxis *axis)
209 bool AbstractDomain::detachAxis(QAbstractAxis *axis)
209 {
210 {
210 if (axis->orientation() == Qt::Vertical) {
211 if (axis->orientation() == Qt::Vertical) {
211 QObject::disconnect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleVerticalAxisRangeChanged(qreal,qreal)));
212 QObject::disconnect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleVerticalAxisRangeChanged(qreal,qreal)));
212 QObject::disconnect(this, SIGNAL(rangeVerticalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
213 QObject::disconnect(this, SIGNAL(rangeVerticalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
213 }
214 }
214
215
215 if (axis->orientation() == Qt::Horizontal) {
216 if (axis->orientation() == Qt::Horizontal) {
216 QObject::disconnect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleHorizontalAxisRangeChanged(qreal,qreal)));
217 QObject::disconnect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleHorizontalAxisRangeChanged(qreal,qreal)));
217 QObject::disconnect(this, SIGNAL(rangeHorizontalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
218 QObject::disconnect(this, SIGNAL(rangeHorizontalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
218 }
219 }
219
220
220 return true;
221 return true;
221 }
222 }
222
223
223 // operators
224 // operators
224
225
225 bool QT_CHARTS_AUTOTEST_EXPORT operator== (const AbstractDomain &domain1, const AbstractDomain &domain2)
226 bool QT_CHARTS_AUTOTEST_EXPORT operator== (const AbstractDomain &domain1, const AbstractDomain &domain2)
226 {
227 {
227 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
228 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
228 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
229 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
229 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
230 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
230 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
231 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
231 }
232 }
232
233
233
234
234 bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const AbstractDomain &domain1, const AbstractDomain &domain2)
235 bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const AbstractDomain &domain1, const AbstractDomain &domain2)
235 {
236 {
236 return !(domain1 == domain2);
237 return !(domain1 == domain2);
237 }
238 }
238
239
239
240
240 QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const AbstractDomain &domain)
241 QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const AbstractDomain &domain)
241 {
242 {
242 #ifdef QT_NO_TEXTSTREAM
243 #ifdef QT_NO_TEXTSTREAM
243 Q_UNUSED(domain)
244 Q_UNUSED(domain)
244 #else
245 #else
245 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
246 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
246 #endif
247 #endif
247 return dbg.maybeSpace();
248 return dbg.maybeSpace();
248 }
249 }
249
250
250 // This function adjusts min/max ranges to failsafe values if negative/zero values are attempted.
251 // This function adjusts min/max ranges to failsafe values if negative/zero values are attempted.
251 void AbstractDomain::adjustLogDomainRanges(qreal &min, qreal &max)
252 void AbstractDomain::adjustLogDomainRanges(qreal &min, qreal &max)
252 {
253 {
253 if (min <= 0) {
254 if (min <= 0) {
254 min = 1.0;
255 min = 1.0;
255 if (max <= min)
256 if (max <= min)
256 max = min + 1.0;
257 max = min + 1.0;
257 }
258 }
258 }
259 }
259
260
260
261
261 #include "moc_abstractdomain_p.cpp"
262 #include "moc_abstractdomain_p.cpp"
262
263
263 QT_CHARTS_END_NAMESPACE
264 QT_CHARTS_END_NAMESPACE
@@ -1,276 +1,277
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2014 Digia Plc
3 ** Copyright (C) 2014 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.io
5 ** For any questions to Digia, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and Digia.
12 ** agreement between you and Digia.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <private/logxlogydomain_p.h>
19 #include <private/logxlogydomain_p.h>
20 #include <private/qabstractaxis_p.h>
20 #include <private/qabstractaxis_p.h>
21 #include <QtCharts/QLogValueAxis>
21 #include <QtCharts/QLogValueAxis>
22 #include <QtCore/QtMath>
22 #include <QtCore/QtMath>
23 #include <cmath>
23
24
24 QT_CHARTS_BEGIN_NAMESPACE
25 QT_CHARTS_BEGIN_NAMESPACE
25
26
26 LogXLogYDomain::LogXLogYDomain(QObject *parent)
27 LogXLogYDomain::LogXLogYDomain(QObject *parent)
27 : AbstractDomain(parent),
28 : AbstractDomain(parent),
28 m_logLeftX(0),
29 m_logLeftX(0),
29 m_logRightX(1),
30 m_logRightX(1),
30 m_logBaseX(10),
31 m_logBaseX(10),
31 m_logLeftY(0),
32 m_logLeftY(0),
32 m_logRightY(1),
33 m_logRightY(1),
33 m_logBaseY(10)
34 m_logBaseY(10)
34 {
35 {
35 }
36 }
36
37
37 LogXLogYDomain::~LogXLogYDomain()
38 LogXLogYDomain::~LogXLogYDomain()
38 {
39 {
39 }
40 }
40
41
41 void LogXLogYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
42 void LogXLogYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
42 {
43 {
43 bool axisXChanged = false;
44 bool axisXChanged = false;
44 bool axisYChanged = false;
45 bool axisYChanged = false;
45
46
46 adjustLogDomainRanges(minX, maxX);
47 adjustLogDomainRanges(minX, maxX);
47 adjustLogDomainRanges(minY, maxY);
48 adjustLogDomainRanges(minY, maxY);
48
49
49 if (!qFuzzyIsNull(m_minX - minX) || !qFuzzyIsNull(m_maxX - maxX)) {
50 if (!qFuzzyIsNull(m_minX - minX) || !qFuzzyIsNull(m_maxX - maxX)) {
50 m_minX = minX;
51 m_minX = minX;
51 m_maxX = maxX;
52 m_maxX = maxX;
52 axisXChanged = true;
53 axisXChanged = true;
53 qreal logMinX = log10(m_minX) / log10(m_logBaseX);
54 qreal logMinX = std::log10(m_minX) / std::log10(m_logBaseX);
54 qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
55 qreal logMaxX = std::log10(m_maxX) / std::log10(m_logBaseX);
55 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
56 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
56 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
57 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
57 if(!m_signalsBlocked)
58 if(!m_signalsBlocked)
58 emit rangeHorizontalChanged(m_minX, m_maxX);
59 emit rangeHorizontalChanged(m_minX, m_maxX);
59 }
60 }
60
61
61 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
62 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
62 m_minY = minY;
63 m_minY = minY;
63 m_maxY = maxY;
64 m_maxY = maxY;
64 axisYChanged = true;
65 axisYChanged = true;
65 qreal logMinY = log10(m_minY) / log10(m_logBaseY);
66 qreal logMinY = std::log10(m_minY) / std::log10(m_logBaseY);
66 qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
67 qreal logMaxY = std::log10(m_maxY) / std::log10(m_logBaseY);
67 m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
68 m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
68 m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
69 m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
69 if (!m_signalsBlocked)
70 if (!m_signalsBlocked)
70 emit rangeVerticalChanged(m_minY, m_maxY);
71 emit rangeVerticalChanged(m_minY, m_maxY);
71 }
72 }
72
73
73 if (axisXChanged || axisYChanged)
74 if (axisXChanged || axisYChanged)
74 emit updated();
75 emit updated();
75 }
76 }
76
77
77 void LogXLogYDomain::zoomIn(const QRectF &rect)
78 void LogXLogYDomain::zoomIn(const QRectF &rect)
78 {
79 {
79 storeZoomReset();
80 storeZoomReset();
80 qreal logLeftX = rect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
81 qreal logLeftX = rect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
81 qreal logRightX = rect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
82 qreal logRightX = rect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
82 qreal leftX = qPow(m_logBaseX, logLeftX);
83 qreal leftX = qPow(m_logBaseX, logLeftX);
83 qreal rightX = qPow(m_logBaseX, logRightX);
84 qreal rightX = qPow(m_logBaseX, logRightX);
84 qreal minX = leftX < rightX ? leftX : rightX;
85 qreal minX = leftX < rightX ? leftX : rightX;
85 qreal maxX = leftX > rightX ? leftX : rightX;
86 qreal maxX = leftX > rightX ? leftX : rightX;
86
87
87 qreal logLeftY = m_logRightY - rect.bottom() * (m_logRightY - m_logLeftY) / m_size.height();
88 qreal logLeftY = m_logRightY - rect.bottom() * (m_logRightY - m_logLeftY) / m_size.height();
88 qreal logRightY = m_logRightY - rect.top() * (m_logRightY - m_logLeftY) / m_size.height();
89 qreal logRightY = m_logRightY - rect.top() * (m_logRightY - m_logLeftY) / m_size.height();
89 qreal leftY = qPow(m_logBaseY, logLeftY);
90 qreal leftY = qPow(m_logBaseY, logLeftY);
90 qreal rightY = qPow(m_logBaseY, logRightY);
91 qreal rightY = qPow(m_logBaseY, logRightY);
91 qreal minY = leftY < rightY ? leftY : rightY;
92 qreal minY = leftY < rightY ? leftY : rightY;
92 qreal maxY = leftY > rightY ? leftY : rightY;
93 qreal maxY = leftY > rightY ? leftY : rightY;
93
94
94 setRange(minX, maxX, minY, maxY);
95 setRange(minX, maxX, minY, maxY);
95 }
96 }
96
97
97 void LogXLogYDomain::zoomOut(const QRectF &rect)
98 void LogXLogYDomain::zoomOut(const QRectF &rect)
98 {
99 {
99 storeZoomReset();
100 storeZoomReset();
100 const qreal factorX = m_size.width() / rect.width();
101 const qreal factorX = m_size.width() / rect.width();
101 const qreal factorY = m_size.height() / rect.height();
102 const qreal factorY = m_size.height() / rect.height();
102
103
103 qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 - factorX);
104 qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 - factorX);
104 qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 + factorX);
105 qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 + factorX);
105 qreal leftX = qPow(m_logBaseX, logLeftX);
106 qreal leftX = qPow(m_logBaseX, logLeftX);
106 qreal rightX = qPow(m_logBaseX, logRIghtX);
107 qreal rightX = qPow(m_logBaseX, logRIghtX);
107 qreal minX = leftX < rightX ? leftX : rightX;
108 qreal minX = leftX < rightX ? leftX : rightX;
108 qreal maxX = leftX > rightX ? leftX : rightX;
109 qreal maxX = leftX > rightX ? leftX : rightX;
109
110
110 qreal newLogMinY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 - factorY);
111 qreal newLogMinY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 - factorY);
111 qreal newLogMaxY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 + factorY);
112 qreal newLogMaxY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 + factorY);
112 qreal leftY = qPow(m_logBaseY, newLogMinY);
113 qreal leftY = qPow(m_logBaseY, newLogMinY);
113 qreal rightY = qPow(m_logBaseY, newLogMaxY);
114 qreal rightY = qPow(m_logBaseY, newLogMaxY);
114 qreal minY = leftY < rightY ? leftY : rightY;
115 qreal minY = leftY < rightY ? leftY : rightY;
115 qreal maxY = leftY > rightY ? leftY : rightY;
116 qreal maxY = leftY > rightY ? leftY : rightY;
116
117
117 setRange(minX, maxX, minY, maxY);
118 setRange(minX, maxX, minY, maxY);
118 }
119 }
119
120
120 void LogXLogYDomain::move(qreal dx, qreal dy)
121 void LogXLogYDomain::move(qreal dx, qreal dy)
121 {
122 {
122 qreal stepX = dx * qAbs(m_logRightX - m_logLeftX) / m_size.width();
123 qreal stepX = dx * qAbs(m_logRightX - m_logLeftX) / m_size.width();
123 qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX);
124 qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX);
124 qreal rightX = qPow(m_logBaseX, m_logRightX + stepX);
125 qreal rightX = qPow(m_logBaseX, m_logRightX + stepX);
125 qreal minX = leftX < rightX ? leftX : rightX;
126 qreal minX = leftX < rightX ? leftX : rightX;
126 qreal maxX = leftX > rightX ? leftX : rightX;
127 qreal maxX = leftX > rightX ? leftX : rightX;
127
128
128 qreal stepY = dy * (m_logRightY - m_logLeftY) / m_size.height();
129 qreal stepY = dy * (m_logRightY - m_logLeftY) / m_size.height();
129 qreal leftY = qPow(m_logBaseY, m_logLeftY + stepY);
130 qreal leftY = qPow(m_logBaseY, m_logLeftY + stepY);
130 qreal rightY = qPow(m_logBaseY, m_logRightY + stepY);
131 qreal rightY = qPow(m_logBaseY, m_logRightY + stepY);
131 qreal minY = leftY < rightY ? leftY : rightY;
132 qreal minY = leftY < rightY ? leftY : rightY;
132 qreal maxY = leftY > rightY ? leftY : rightY;
133 qreal maxY = leftY > rightY ? leftY : rightY;
133
134
134 setRange(minX, maxX, minY, maxY);
135 setRange(minX, maxX, minY, maxY);
135 }
136 }
136
137
137 QPointF LogXLogYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
138 QPointF LogXLogYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
138 {
139 {
139 const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX);
140 const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX);
140 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
141 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
141 qreal x(0);
142 qreal x(0);
142 qreal y(0);
143 qreal y(0);
143 if (point.x() > 0 && point.y() > 0) {
144 if (point.x() > 0 && point.y() > 0) {
144 x = (log10(point.x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
145 x = (std::log10(point.x()) / std::log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
145 y = (log10(point.y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
146 y = (std::log10(point.y()) / std::log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
146 ok = true;
147 ok = true;
147 } else {
148 } else {
148 qWarning() << "Logarithms of zero and negative values are undefined.";
149 qWarning() << "Logarithms of zero and negative values are undefined.";
149 ok = false;
150 ok = false;
150 if (point.x() > 0)
151 if (point.x() > 0)
151 x = (log10(point.x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
152 x = (std::log10(point.x()) / std::log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
152 else
153 else
153 x = 0;
154 x = 0;
154 if (point.y() > 0) {
155 if (point.y() > 0) {
155 y = (log10(point.y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY
156 y = (std::log10(point.y()) / std::log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY
156 + m_size.height();
157 + m_size.height();
157 } else {
158 } else {
158 y = m_size.height();
159 y = m_size.height();
159 }
160 }
160 }
161 }
161 return QPointF(x, y);
162 return QPointF(x, y);
162 }
163 }
163
164
164 QVector<QPointF> LogXLogYDomain::calculateGeometryPoints(const QList<QPointF> &vector) const
165 QVector<QPointF> LogXLogYDomain::calculateGeometryPoints(const QList<QPointF> &vector) const
165 {
166 {
166 const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX);
167 const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX);
167 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
168 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
168
169
169 QVector<QPointF> result;
170 QVector<QPointF> result;
170 result.resize(vector.count());
171 result.resize(vector.count());
171
172
172 for (int i = 0; i < vector.count(); ++i) {
173 for (int i = 0; i < vector.count(); ++i) {
173 if (vector[i].x() > 0 && vector[i].y() > 0) {
174 if (vector[i].x() > 0 && vector[i].y() > 0) {
174 qreal x = (log10(vector[i].x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
175 qreal x = (std::log10(vector[i].x()) / std::log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
175 qreal y = (log10(vector[i].y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
176 qreal y = (std::log10(vector[i].y()) / std::log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
176 result[i].setX(x);
177 result[i].setX(x);
177 result[i].setY(y);
178 result[i].setY(y);
178 } else {
179 } else {
179 qWarning() << "Logarithms of zero and negative values are undefined.";
180 qWarning() << "Logarithms of zero and negative values are undefined.";
180 return QVector<QPointF>();
181 return QVector<QPointF>();
181 }
182 }
182 }
183 }
183 return result;
184 return result;
184 }
185 }
185
186
186 QPointF LogXLogYDomain::calculateDomainPoint(const QPointF &point) const
187 QPointF LogXLogYDomain::calculateDomainPoint(const QPointF &point) const
187 {
188 {
188 const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX);
189 const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX);
189 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
190 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
190 qreal x = qPow(m_logBaseX, m_logLeftX + point.x() / deltaX);
191 qreal x = qPow(m_logBaseX, m_logLeftX + point.x() / deltaX);
191 qreal y = qPow(m_logBaseY, m_logLeftY + (m_size.height() - point.y()) / deltaY);
192 qreal y = qPow(m_logBaseY, m_logLeftY + (m_size.height() - point.y()) / deltaY);
192 return QPointF(x, y);
193 return QPointF(x, y);
193 }
194 }
194
195
195 bool LogXLogYDomain::attachAxis(QAbstractAxis *axis)
196 bool LogXLogYDomain::attachAxis(QAbstractAxis *axis)
196 {
197 {
197 AbstractDomain::attachAxis(axis);
198 AbstractDomain::attachAxis(axis);
198 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
199 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
199
200
200 if (logAxis && logAxis->orientation() == Qt::Vertical) {
201 if (logAxis && logAxis->orientation() == Qt::Vertical) {
201 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
202 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
202 handleVerticalAxisBaseChanged(logAxis->base());
203 handleVerticalAxisBaseChanged(logAxis->base());
203 }
204 }
204
205
205 if (logAxis && logAxis->orientation() == Qt::Horizontal) {
206 if (logAxis && logAxis->orientation() == Qt::Horizontal) {
206 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
207 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
207 handleHorizontalAxisBaseChanged(logAxis->base());
208 handleHorizontalAxisBaseChanged(logAxis->base());
208 }
209 }
209
210
210 return true;
211 return true;
211 }
212 }
212
213
213 bool LogXLogYDomain::detachAxis(QAbstractAxis *axis)
214 bool LogXLogYDomain::detachAxis(QAbstractAxis *axis)
214 {
215 {
215 AbstractDomain::detachAxis(axis);
216 AbstractDomain::detachAxis(axis);
216 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
217 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
217
218
218 if (logAxis && logAxis->orientation() == Qt::Vertical)
219 if (logAxis && logAxis->orientation() == Qt::Vertical)
219 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
220 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
220
221
221 if (logAxis && logAxis->orientation() == Qt::Horizontal)
222 if (logAxis && logAxis->orientation() == Qt::Horizontal)
222 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
223 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
223
224
224 return true;
225 return true;
225 }
226 }
226
227
227 void LogXLogYDomain::handleVerticalAxisBaseChanged(qreal baseY)
228 void LogXLogYDomain::handleVerticalAxisBaseChanged(qreal baseY)
228 {
229 {
229 m_logBaseY = baseY;
230 m_logBaseY = baseY;
230 qreal logMinY = log10(m_minY) / log10(m_logBaseY);
231 qreal logMinY = std::log10(m_minY) / std::log10(m_logBaseY);
231 qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
232 qreal logMaxY = std::log10(m_maxY) / std::log10(m_logBaseY);
232 m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
233 m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
233 m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
234 m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
234 emit updated();
235 emit updated();
235 }
236 }
236
237
237 void LogXLogYDomain::handleHorizontalAxisBaseChanged(qreal baseX)
238 void LogXLogYDomain::handleHorizontalAxisBaseChanged(qreal baseX)
238 {
239 {
239 m_logBaseX = baseX;
240 m_logBaseX = baseX;
240 qreal logMinX = log10(m_minX) / log10(m_logBaseX);
241 qreal logMinX = std::log10(m_minX) / std::log10(m_logBaseX);
241 qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
242 qreal logMaxX = std::log10(m_maxX) / std::log10(m_logBaseX);
242 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
243 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
243 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
244 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
244 emit updated();
245 emit updated();
245 }
246 }
246
247
247 // operators
248 // operators
248
249
249 bool QT_CHARTS_AUTOTEST_EXPORT operator== (const LogXLogYDomain &domain1, const LogXLogYDomain &domain2)
250 bool QT_CHARTS_AUTOTEST_EXPORT operator== (const LogXLogYDomain &domain1, const LogXLogYDomain &domain2)
250 {
251 {
251 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
252 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
252 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
253 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
253 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
254 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
254 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
255 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
255 }
256 }
256
257
257
258
258 bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const LogXLogYDomain &domain1, const LogXLogYDomain &domain2)
259 bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const LogXLogYDomain &domain1, const LogXLogYDomain &domain2)
259 {
260 {
260 return !(domain1 == domain2);
261 return !(domain1 == domain2);
261 }
262 }
262
263
263
264
264 QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXLogYDomain &domain)
265 QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXLogYDomain &domain)
265 {
266 {
266 #ifdef QT_NO_TEXTSTREAM
267 #ifdef QT_NO_TEXTSTREAM
267 Q_UNUSED(domain)
268 Q_UNUSED(domain)
268 #else
269 #else
269 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
270 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
270 #endif
271 #endif
271 return dbg.maybeSpace();
272 return dbg.maybeSpace();
272 }
273 }
273
274
274 #include "moc_logxlogydomain_p.cpp"
275 #include "moc_logxlogydomain_p.cpp"
275
276
276 QT_CHARTS_END_NAMESPACE
277 QT_CHARTS_END_NAMESPACE
@@ -1,271 +1,272
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2014 Digia Plc
3 ** Copyright (C) 2014 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.io
5 ** For any questions to Digia, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and Digia.
12 ** agreement between you and Digia.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <private/logxlogypolardomain_p.h>
19 #include <private/logxlogypolardomain_p.h>
20 #include <private/qabstractaxis_p.h>
20 #include <private/qabstractaxis_p.h>
21 #include <QtCharts/QLogValueAxis>
21 #include <QtCharts/QLogValueAxis>
22 #include <QtCore/QtMath>
22 #include <QtCore/QtMath>
23 #include <cmath>
23
24
24 QT_CHARTS_BEGIN_NAMESPACE
25 QT_CHARTS_BEGIN_NAMESPACE
25
26
26 LogXLogYPolarDomain::LogXLogYPolarDomain(QObject *parent)
27 LogXLogYPolarDomain::LogXLogYPolarDomain(QObject *parent)
27 : PolarDomain(parent),
28 : PolarDomain(parent),
28 m_logLeftX(0),
29 m_logLeftX(0),
29 m_logRightX(1),
30 m_logRightX(1),
30 m_logBaseX(10),
31 m_logBaseX(10),
31 m_logInnerY(0),
32 m_logInnerY(0),
32 m_logOuterY(1),
33 m_logOuterY(1),
33 m_logBaseY(10)
34 m_logBaseY(10)
34 {
35 {
35 }
36 }
36
37
37 LogXLogYPolarDomain::~LogXLogYPolarDomain()
38 LogXLogYPolarDomain::~LogXLogYPolarDomain()
38 {
39 {
39 }
40 }
40
41
41 void LogXLogYPolarDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
42 void LogXLogYPolarDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
42 {
43 {
43 bool axisXChanged = false;
44 bool axisXChanged = false;
44 bool axisYChanged = false;
45 bool axisYChanged = false;
45
46
46 adjustLogDomainRanges(minX, maxX);
47 adjustLogDomainRanges(minX, maxX);
47 adjustLogDomainRanges(minY, maxY);
48 adjustLogDomainRanges(minY, maxY);
48
49
49 if (!qFuzzyCompare(m_minX, minX) || !qFuzzyCompare(m_maxX, maxX)) {
50 if (!qFuzzyCompare(m_minX, minX) || !qFuzzyCompare(m_maxX, maxX)) {
50 m_minX = minX;
51 m_minX = minX;
51 m_maxX = maxX;
52 m_maxX = maxX;
52 axisXChanged = true;
53 axisXChanged = true;
53 qreal logMinX = log10(m_minX) / log10(m_logBaseX);
54 qreal logMinX = std::log10(m_minX) / std::log10(m_logBaseX);
54 qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
55 qreal logMaxX = std::log10(m_maxX) / std::log10(m_logBaseX);
55 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
56 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
56 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
57 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
57 if (!m_signalsBlocked)
58 if (!m_signalsBlocked)
58 emit rangeHorizontalChanged(m_minX, m_maxX);
59 emit rangeHorizontalChanged(m_minX, m_maxX);
59 }
60 }
60
61
61 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
62 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
62 m_minY = minY;
63 m_minY = minY;
63 m_maxY = maxY;
64 m_maxY = maxY;
64 axisYChanged = true;
65 axisYChanged = true;
65 qreal logMinY = log10(m_minY) / log10(m_logBaseY);
66 qreal logMinY = std::log10(m_minY) / std::log10(m_logBaseY);
66 qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
67 qreal logMaxY = std::log10(m_maxY) / std::log10(m_logBaseY);
67 m_logInnerY = logMinY < logMaxY ? logMinY : logMaxY;
68 m_logInnerY = logMinY < logMaxY ? logMinY : logMaxY;
68 m_logOuterY = logMinY > logMaxY ? logMinY : logMaxY;
69 m_logOuterY = logMinY > logMaxY ? logMinY : logMaxY;
69 if (!m_signalsBlocked)
70 if (!m_signalsBlocked)
70 emit rangeVerticalChanged(m_minY, m_maxY);
71 emit rangeVerticalChanged(m_minY, m_maxY);
71 }
72 }
72
73
73 if (axisXChanged || axisYChanged)
74 if (axisXChanged || axisYChanged)
74 emit updated();
75 emit updated();
75 }
76 }
76
77
77 void LogXLogYPolarDomain::zoomIn(const QRectF &rect)
78 void LogXLogYPolarDomain::zoomIn(const QRectF &rect)
78 {
79 {
79 storeZoomReset();
80 storeZoomReset();
80 qreal logLeftX = rect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
81 qreal logLeftX = rect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
81 qreal logRightX = rect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
82 qreal logRightX = rect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
82 qreal leftX = qPow(m_logBaseX, logLeftX);
83 qreal leftX = qPow(m_logBaseX, logLeftX);
83 qreal rightX = qPow(m_logBaseX, logRightX);
84 qreal rightX = qPow(m_logBaseX, logRightX);
84 qreal minX = leftX < rightX ? leftX : rightX;
85 qreal minX = leftX < rightX ? leftX : rightX;
85 qreal maxX = leftX > rightX ? leftX : rightX;
86 qreal maxX = leftX > rightX ? leftX : rightX;
86
87
87 qreal logLeftY = m_logOuterY - rect.bottom() * (m_logOuterY - m_logInnerY) / m_size.height();
88 qreal logLeftY = m_logOuterY - rect.bottom() * (m_logOuterY - m_logInnerY) / m_size.height();
88 qreal logRightY = m_logOuterY - rect.top() * (m_logOuterY - m_logInnerY) / m_size.height();
89 qreal logRightY = m_logOuterY - rect.top() * (m_logOuterY - m_logInnerY) / m_size.height();
89 qreal leftY = qPow(m_logBaseY, logLeftY);
90 qreal leftY = qPow(m_logBaseY, logLeftY);
90 qreal rightY = qPow(m_logBaseY, logRightY);
91 qreal rightY = qPow(m_logBaseY, logRightY);
91 qreal minY = leftY < rightY ? leftY : rightY;
92 qreal minY = leftY < rightY ? leftY : rightY;
92 qreal maxY = leftY > rightY ? leftY : rightY;
93 qreal maxY = leftY > rightY ? leftY : rightY;
93
94
94 setRange(minX, maxX, minY, maxY);
95 setRange(minX, maxX, minY, maxY);
95 }
96 }
96
97
97 void LogXLogYPolarDomain::zoomOut(const QRectF &rect)
98 void LogXLogYPolarDomain::zoomOut(const QRectF &rect)
98 {
99 {
99 storeZoomReset();
100 storeZoomReset();
100 const qreal factorX = m_size.width() / rect.width();
101 const qreal factorX = m_size.width() / rect.width();
101
102
102 qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2.0 * (1.0 - factorX);
103 qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2.0 * (1.0 - factorX);
103 qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2.0 * (1.0 + factorX);
104 qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2.0 * (1.0 + factorX);
104 qreal leftX = qPow(m_logBaseX, logLeftX);
105 qreal leftX = qPow(m_logBaseX, logLeftX);
105 qreal rightX = qPow(m_logBaseX, logRIghtX);
106 qreal rightX = qPow(m_logBaseX, logRIghtX);
106 qreal minX = leftX < rightX ? leftX : rightX;
107 qreal minX = leftX < rightX ? leftX : rightX;
107 qreal maxX = leftX > rightX ? leftX : rightX;
108 qreal maxX = leftX > rightX ? leftX : rightX;
108
109
109 const qreal factorY = m_size.height() / rect.height();
110 const qreal factorY = m_size.height() / rect.height();
110 qreal newLogMinY = m_logInnerY + (m_logOuterY - m_logInnerY) / 2.0 * (1.0 - factorY);
111 qreal newLogMinY = m_logInnerY + (m_logOuterY - m_logInnerY) / 2.0 * (1.0 - factorY);
111 qreal newLogMaxY = m_logInnerY + (m_logOuterY - m_logInnerY) / 2.0 * (1.0 + factorY);
112 qreal newLogMaxY = m_logInnerY + (m_logOuterY - m_logInnerY) / 2.0 * (1.0 + factorY);
112 qreal leftY = qPow(m_logBaseY, newLogMinY);
113 qreal leftY = qPow(m_logBaseY, newLogMinY);
113 qreal rightY = qPow(m_logBaseY, newLogMaxY);
114 qreal rightY = qPow(m_logBaseY, newLogMaxY);
114 qreal minY = leftY < rightY ? leftY : rightY;
115 qreal minY = leftY < rightY ? leftY : rightY;
115 qreal maxY = leftY > rightY ? leftY : rightY;
116 qreal maxY = leftY > rightY ? leftY : rightY;
116
117
117 setRange(minX, maxX, minY, maxY);
118 setRange(minX, maxX, minY, maxY);
118 }
119 }
119
120
120 void LogXLogYPolarDomain::move(qreal dx, qreal dy)
121 void LogXLogYPolarDomain::move(qreal dx, qreal dy)
121 {
122 {
122 qreal stepX = dx * (m_logRightX - m_logLeftX) / m_size.width();
123 qreal stepX = dx * (m_logRightX - m_logLeftX) / m_size.width();
123 qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX);
124 qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX);
124 qreal rightX = qPow(m_logBaseX, m_logRightX + stepX);
125 qreal rightX = qPow(m_logBaseX, m_logRightX + stepX);
125 qreal minX = leftX < rightX ? leftX : rightX;
126 qreal minX = leftX < rightX ? leftX : rightX;
126 qreal maxX = leftX > rightX ? leftX : rightX;
127 qreal maxX = leftX > rightX ? leftX : rightX;
127
128
128 qreal stepY = dy * (m_logOuterY - m_logInnerY) / m_radius;
129 qreal stepY = dy * (m_logOuterY - m_logInnerY) / m_radius;
129 qreal leftY = qPow(m_logBaseY, m_logInnerY + stepY);
130 qreal leftY = qPow(m_logBaseY, m_logInnerY + stepY);
130 qreal rightY = qPow(m_logBaseY, m_logOuterY + stepY);
131 qreal rightY = qPow(m_logBaseY, m_logOuterY + stepY);
131 qreal minY = leftY < rightY ? leftY : rightY;
132 qreal minY = leftY < rightY ? leftY : rightY;
132 qreal maxY = leftY > rightY ? leftY : rightY;
133 qreal maxY = leftY > rightY ? leftY : rightY;
133
134
134 setRange(minX, maxX, minY, maxY);
135 setRange(minX, maxX, minY, maxY);
135 }
136 }
136
137
137 qreal LogXLogYPolarDomain::toAngularCoordinate(qreal value, bool &ok) const
138 qreal LogXLogYPolarDomain::toAngularCoordinate(qreal value, bool &ok) const
138 {
139 {
139 qreal retVal;
140 qreal retVal;
140 if (value <= 0) {
141 if (value <= 0) {
141 ok = false;
142 ok = false;
142 retVal = 0.0;
143 retVal = 0.0;
143 } else {
144 } else {
144 ok = true;
145 ok = true;
145 const qreal tickSpan = 360.0 / qAbs(m_logRightX - m_logLeftX);
146 const qreal tickSpan = 360.0 / qAbs(m_logRightX - m_logLeftX);
146 const qreal logValue = log10(value) / log10(m_logBaseX);
147 const qreal logValue = std::log10(value) / std::log10(m_logBaseX);
147 const qreal valueDelta = logValue - m_logLeftX;
148 const qreal valueDelta = logValue - m_logLeftX;
148
149
149 retVal = valueDelta * tickSpan;
150 retVal = valueDelta * tickSpan;
150 }
151 }
151 return retVal;
152 return retVal;
152 }
153 }
153
154
154 qreal LogXLogYPolarDomain::toRadialCoordinate(qreal value, bool &ok) const
155 qreal LogXLogYPolarDomain::toRadialCoordinate(qreal value, bool &ok) const
155 {
156 {
156 qreal retVal;
157 qreal retVal;
157 if (value <= 0) {
158 if (value <= 0) {
158 ok = false;
159 ok = false;
159 retVal = 0.0;
160 retVal = 0.0;
160 } else {
161 } else {
161 ok = true;
162 ok = true;
162 const qreal tickSpan = m_radius / qAbs(m_logOuterY - m_logInnerY);
163 const qreal tickSpan = m_radius / qAbs(m_logOuterY - m_logInnerY);
163 const qreal logValue = log10(value) / log10(m_logBaseY);
164 const qreal logValue = std::log10(value) / std::log10(m_logBaseY);
164 const qreal valueDelta = logValue - m_logInnerY;
165 const qreal valueDelta = logValue - m_logInnerY;
165
166
166 retVal = valueDelta * tickSpan;
167 retVal = valueDelta * tickSpan;
167
168
168 if (retVal < 0.0)
169 if (retVal < 0.0)
169 retVal = 0.0;
170 retVal = 0.0;
170 }
171 }
171 return retVal;
172 return retVal;
172 }
173 }
173
174
174 QPointF LogXLogYPolarDomain::calculateDomainPoint(const QPointF &point) const
175 QPointF LogXLogYPolarDomain::calculateDomainPoint(const QPointF &point) const
175 {
176 {
176 if (point == m_center)
177 if (point == m_center)
177 return QPointF(0.0, m_minY);
178 return QPointF(0.0, m_minY);
178
179
179 QLineF line(m_center, point);
180 QLineF line(m_center, point);
180 qreal a = 90.0 - line.angle();
181 qreal a = 90.0 - line.angle();
181 if (a < 0.0)
182 if (a < 0.0)
182 a += 360.0;
183 a += 360.0;
183
184
184 const qreal deltaX = 360.0 / qAbs(m_logRightX - m_logLeftX);
185 const qreal deltaX = 360.0 / qAbs(m_logRightX - m_logLeftX);
185 a = qPow(m_logBaseX, m_logLeftX + (a / deltaX));
186 a = qPow(m_logBaseX, m_logLeftX + (a / deltaX));
186
187
187 const qreal deltaY = m_radius / qAbs(m_logOuterY - m_logInnerY);
188 const qreal deltaY = m_radius / qAbs(m_logOuterY - m_logInnerY);
188 qreal r = qPow(m_logBaseY, m_logInnerY + (line.length() / deltaY));
189 qreal r = qPow(m_logBaseY, m_logInnerY + (line.length() / deltaY));
189
190
190 return QPointF(a, r);
191 return QPointF(a, r);
191 }
192 }
192
193
193 bool LogXLogYPolarDomain::attachAxis(QAbstractAxis *axis)
194 bool LogXLogYPolarDomain::attachAxis(QAbstractAxis *axis)
194 {
195 {
195 AbstractDomain::attachAxis(axis);
196 AbstractDomain::attachAxis(axis);
196 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
197 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
197
198
198 if (logAxis && logAxis->orientation() == Qt::Horizontal) {
199 if (logAxis && logAxis->orientation() == Qt::Horizontal) {
199 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
200 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
200 handleHorizontalAxisBaseChanged(logAxis->base());
201 handleHorizontalAxisBaseChanged(logAxis->base());
201 } else if (logAxis && logAxis->orientation() == Qt::Vertical){
202 } else if (logAxis && logAxis->orientation() == Qt::Vertical){
202 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
203 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
203 handleVerticalAxisBaseChanged(logAxis->base());
204 handleVerticalAxisBaseChanged(logAxis->base());
204 }
205 }
205
206
206 return true;
207 return true;
207 }
208 }
208
209
209 bool LogXLogYPolarDomain::detachAxis(QAbstractAxis *axis)
210 bool LogXLogYPolarDomain::detachAxis(QAbstractAxis *axis)
210 {
211 {
211 AbstractDomain::detachAxis(axis);
212 AbstractDomain::detachAxis(axis);
212 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
213 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
213
214
214 if (logAxis && logAxis->orientation() == Qt::Horizontal)
215 if (logAxis && logAxis->orientation() == Qt::Horizontal)
215 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
216 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
216 else if (logAxis && logAxis->orientation() == Qt::Vertical)
217 else if (logAxis && logAxis->orientation() == Qt::Vertical)
217 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
218 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
218
219
219 return true;
220 return true;
220 }
221 }
221
222
222 void LogXLogYPolarDomain::handleHorizontalAxisBaseChanged(qreal baseX)
223 void LogXLogYPolarDomain::handleHorizontalAxisBaseChanged(qreal baseX)
223 {
224 {
224 m_logBaseX = baseX;
225 m_logBaseX = baseX;
225 qreal logMinX = log10(m_minX) / log10(m_logBaseX);
226 qreal logMinX = std::log10(m_minX) / std::log10(m_logBaseX);
226 qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
227 qreal logMaxX = std::log10(m_maxX) / std::log10(m_logBaseX);
227 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
228 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
228 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
229 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
229 emit updated();
230 emit updated();
230 }
231 }
231
232
232 void LogXLogYPolarDomain::handleVerticalAxisBaseChanged(qreal baseY)
233 void LogXLogYPolarDomain::handleVerticalAxisBaseChanged(qreal baseY)
233 {
234 {
234 m_logBaseY = baseY;
235 m_logBaseY = baseY;
235 qreal logMinY = log10(m_minY) / log10(m_logBaseY);
236 qreal logMinY = std::log10(m_minY) / std::log10(m_logBaseY);
236 qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
237 qreal logMaxY = std::log10(m_maxY) / std::log10(m_logBaseY);
237 m_logInnerY = logMinY < logMaxY ? logMinY : logMaxY;
238 m_logInnerY = logMinY < logMaxY ? logMinY : logMaxY;
238 m_logOuterY = logMinY > logMaxY ? logMinY : logMaxY;
239 m_logOuterY = logMinY > logMaxY ? logMinY : logMaxY;
239 emit updated();
240 emit updated();
240 }
241 }
241
242
242 // operators
243 // operators
243
244
244 bool QT_CHARTS_AUTOTEST_EXPORT operator== (const LogXLogYPolarDomain &domain1, const LogXLogYPolarDomain &domain2)
245 bool QT_CHARTS_AUTOTEST_EXPORT operator== (const LogXLogYPolarDomain &domain1, const LogXLogYPolarDomain &domain2)
245 {
246 {
246 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
247 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
247 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
248 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
248 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
249 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
249 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
250 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
250 }
251 }
251
252
252
253
253 bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const LogXLogYPolarDomain &domain1, const LogXLogYPolarDomain &domain2)
254 bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const LogXLogYPolarDomain &domain1, const LogXLogYPolarDomain &domain2)
254 {
255 {
255 return !(domain1 == domain2);
256 return !(domain1 == domain2);
256 }
257 }
257
258
258
259
259 QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXLogYPolarDomain &domain)
260 QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXLogYPolarDomain &domain)
260 {
261 {
261 #ifdef QT_NO_TEXTSTREAM
262 #ifdef QT_NO_TEXTSTREAM
262 Q_UNUSED(domain)
263 Q_UNUSED(domain)
263 #else
264 #else
264 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
265 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
265 #endif
266 #endif
266 return dbg.maybeSpace();
267 return dbg.maybeSpace();
267 }
268 }
268
269
269 #include "moc_logxlogypolardomain_p.cpp"
270 #include "moc_logxlogypolardomain_p.cpp"
270
271
271 QT_CHARTS_END_NAMESPACE
272 QT_CHARTS_END_NAMESPACE
@@ -1,243 +1,244
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2014 Digia Plc
3 ** Copyright (C) 2014 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.io
5 ** For any questions to Digia, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and Digia.
12 ** agreement between you and Digia.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <private/logxydomain_p.h>
19 #include <private/logxydomain_p.h>
20 #include <private/qabstractaxis_p.h>
20 #include <private/qabstractaxis_p.h>
21 #include <QtCharts/QLogValueAxis>
21 #include <QtCharts/QLogValueAxis>
22 #include <QtCore/QtMath>
22 #include <QtCore/QtMath>
23 #include <cmath>
23
24
24 QT_CHARTS_BEGIN_NAMESPACE
25 QT_CHARTS_BEGIN_NAMESPACE
25
26
26 LogXYDomain::LogXYDomain(QObject *parent)
27 LogXYDomain::LogXYDomain(QObject *parent)
27 : AbstractDomain(parent),
28 : AbstractDomain(parent),
28 m_logLeftX(0),
29 m_logLeftX(0),
29 m_logRightX(1),
30 m_logRightX(1),
30 m_logBaseX(10)
31 m_logBaseX(10)
31 {
32 {
32 }
33 }
33
34
34 LogXYDomain::~LogXYDomain()
35 LogXYDomain::~LogXYDomain()
35 {
36 {
36 }
37 }
37
38
38 void LogXYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
39 void LogXYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
39 {
40 {
40 bool axisXChanged = false;
41 bool axisXChanged = false;
41 bool axisYChanged = false;
42 bool axisYChanged = false;
42
43
43 adjustLogDomainRanges(minX, maxX);
44 adjustLogDomainRanges(minX, maxX);
44
45
45 if (!qFuzzyCompare(m_minX, minX) || !qFuzzyCompare(m_maxX, maxX)) {
46 if (!qFuzzyCompare(m_minX, minX) || !qFuzzyCompare(m_maxX, maxX)) {
46 m_minX = minX;
47 m_minX = minX;
47 m_maxX = maxX;
48 m_maxX = maxX;
48 axisXChanged = true;
49 axisXChanged = true;
49 qreal logMinX = log10(m_minX) / log10(m_logBaseX);
50 qreal logMinX = std::log10(m_minX) / std::log10(m_logBaseX);
50 qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
51 qreal logMaxX = std::log10(m_maxX) / std::log10(m_logBaseX);
51 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
52 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
52 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
53 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
53 if(!m_signalsBlocked)
54 if(!m_signalsBlocked)
54 emit rangeHorizontalChanged(m_minX, m_maxX);
55 emit rangeHorizontalChanged(m_minX, m_maxX);
55 }
56 }
56
57
57 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
58 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
58 m_minY = minY;
59 m_minY = minY;
59 m_maxY = maxY;
60 m_maxY = maxY;
60 axisYChanged = true;
61 axisYChanged = true;
61 if (!m_signalsBlocked)
62 if (!m_signalsBlocked)
62 emit rangeVerticalChanged(m_minY, m_maxY);
63 emit rangeVerticalChanged(m_minY, m_maxY);
63 }
64 }
64
65
65 if (axisXChanged || axisYChanged)
66 if (axisXChanged || axisYChanged)
66 emit updated();
67 emit updated();
67 }
68 }
68
69
69 void LogXYDomain::zoomIn(const QRectF &rect)
70 void LogXYDomain::zoomIn(const QRectF &rect)
70 {
71 {
71 storeZoomReset();
72 storeZoomReset();
72 qreal logLeftX = rect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
73 qreal logLeftX = rect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
73 qreal logRightX = rect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
74 qreal logRightX = rect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
74 qreal leftX = qPow(m_logBaseX, logLeftX);
75 qreal leftX = qPow(m_logBaseX, logLeftX);
75 qreal rightX = qPow(m_logBaseX, logRightX);
76 qreal rightX = qPow(m_logBaseX, logRightX);
76 qreal minX = leftX < rightX ? leftX : rightX;
77 qreal minX = leftX < rightX ? leftX : rightX;
77 qreal maxX = leftX > rightX ? leftX : rightX;
78 qreal maxX = leftX > rightX ? leftX : rightX;
78
79
79 qreal dy = spanY() / m_size.height();
80 qreal dy = spanY() / m_size.height();
80 qreal minY = m_minY;
81 qreal minY = m_minY;
81 qreal maxY = m_maxY;
82 qreal maxY = m_maxY;
82
83
83 minY = maxY - dy * rect.bottom();
84 minY = maxY - dy * rect.bottom();
84 maxY = maxY - dy * rect.top();
85 maxY = maxY - dy * rect.top();
85
86
86 setRange(minX, maxX, minY, maxY);
87 setRange(minX, maxX, minY, maxY);
87 }
88 }
88
89
89 void LogXYDomain::zoomOut(const QRectF &rect)
90 void LogXYDomain::zoomOut(const QRectF &rect)
90 {
91 {
91 storeZoomReset();
92 storeZoomReset();
92 const qreal factorX = m_size.width() / rect.width();
93 const qreal factorX = m_size.width() / rect.width();
93
94
94 qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 - factorX);
95 qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 - factorX);
95 qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 + factorX);
96 qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 + factorX);
96 qreal leftX = qPow(m_logBaseX, logLeftX);
97 qreal leftX = qPow(m_logBaseX, logLeftX);
97 qreal rightX = qPow(m_logBaseX, logRIghtX);
98 qreal rightX = qPow(m_logBaseX, logRIghtX);
98 qreal minX = leftX < rightX ? leftX : rightX;
99 qreal minX = leftX < rightX ? leftX : rightX;
99 qreal maxX = leftX > rightX ? leftX : rightX;
100 qreal maxX = leftX > rightX ? leftX : rightX;
100
101
101 qreal dy = spanY() / rect.height();
102 qreal dy = spanY() / rect.height();
102 qreal minY = m_minY;
103 qreal minY = m_minY;
103 qreal maxY = m_maxY;
104 qreal maxY = m_maxY;
104
105
105 maxY = minY + dy * rect.bottom();
106 maxY = minY + dy * rect.bottom();
106 minY = maxY - dy * m_size.height();
107 minY = maxY - dy * m_size.height();
107
108
108 setRange(minX, maxX, minY, maxY);
109 setRange(minX, maxX, minY, maxY);
109 }
110 }
110
111
111 void LogXYDomain::move(qreal dx, qreal dy)
112 void LogXYDomain::move(qreal dx, qreal dy)
112 {
113 {
113 qreal stepX = dx * (m_logRightX - m_logLeftX) / m_size.width();
114 qreal stepX = dx * (m_logRightX - m_logLeftX) / m_size.width();
114 qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX);
115 qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX);
115 qreal rightX = qPow(m_logBaseX, m_logRightX + stepX);
116 qreal rightX = qPow(m_logBaseX, m_logRightX + stepX);
116 qreal minX = leftX < rightX ? leftX : rightX;
117 qreal minX = leftX < rightX ? leftX : rightX;
117 qreal maxX = leftX > rightX ? leftX : rightX;
118 qreal maxX = leftX > rightX ? leftX : rightX;
118
119
119 qreal y = spanY() / m_size.height();
120 qreal y = spanY() / m_size.height();
120 qreal minY = m_minY;
121 qreal minY = m_minY;
121 qreal maxY = m_maxY;
122 qreal maxY = m_maxY;
122
123
123 if (dy != 0) {
124 if (dy != 0) {
124 minY = minY + y * dy;
125 minY = minY + y * dy;
125 maxY = maxY + y * dy;
126 maxY = maxY + y * dy;
126 }
127 }
127 setRange(minX, maxX, minY, maxY);
128 setRange(minX, maxX, minY, maxY);
128 }
129 }
129
130
130 QPointF LogXYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
131 QPointF LogXYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
131 {
132 {
132 const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX);
133 const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX);
133 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
134 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
134
135
135 qreal x(0);
136 qreal x(0);
136 qreal y = (point.y() - m_minY) * -deltaY + m_size.height();
137 qreal y = (point.y() - m_minY) * -deltaY + m_size.height();
137 if (point.x() > 0) {
138 if (point.x() > 0) {
138 x = (log10(point.x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
139 x = (std::log10(point.x()) / std::log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
139 ok = true;
140 ok = true;
140 } else {
141 } else {
141 x = 0;
142 x = 0;
142 qWarning() << "Logarithms of zero and negative values are undefined.";
143 qWarning() << "Logarithms of zero and negative values are undefined.";
143 ok = false;
144 ok = false;
144 }
145 }
145 return QPointF(x, y);
146 return QPointF(x, y);
146 }
147 }
147
148
148 QVector<QPointF> LogXYDomain::calculateGeometryPoints(const QList<QPointF> &vector) const
149 QVector<QPointF> LogXYDomain::calculateGeometryPoints(const QList<QPointF> &vector) const
149 {
150 {
150 const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX);
151 const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX);
151 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
152 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
152
153
153 QVector<QPointF> result;
154 QVector<QPointF> result;
154 result.resize(vector.count());
155 result.resize(vector.count());
155
156
156 for (int i = 0; i < vector.count(); ++i) {
157 for (int i = 0; i < vector.count(); ++i) {
157 if (vector[i].x() > 0) {
158 if (vector[i].x() > 0) {
158 qreal x = (log10(vector[i].x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
159 qreal x = (std::log10(vector[i].x()) / std::log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
159 qreal y = (vector[i].y() - m_minY) * -deltaY + m_size.height();
160 qreal y = (vector[i].y() - m_minY) * -deltaY + m_size.height();
160 result[i].setX(x);
161 result[i].setX(x);
161 result[i].setY(y);
162 result[i].setY(y);
162 } else {
163 } else {
163 qWarning() << "Logarithms of zero and negative values are undefined.";
164 qWarning() << "Logarithms of zero and negative values are undefined.";
164 return QVector<QPointF>();
165 return QVector<QPointF>();
165 }
166 }
166
167
167 }
168 }
168 return result;
169 return result;
169 }
170 }
170
171
171 QPointF LogXYDomain::calculateDomainPoint(const QPointF &point) const
172 QPointF LogXYDomain::calculateDomainPoint(const QPointF &point) const
172 {
173 {
173 const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX);
174 const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX);
174 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
175 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
175 qreal x = qPow(m_logBaseX, m_logLeftX + point.x() / deltaX);
176 qreal x = qPow(m_logBaseX, m_logLeftX + point.x() / deltaX);
176 qreal y = (point.y() - m_size.height()) / (-deltaY) + m_minY;
177 qreal y = (point.y() - m_size.height()) / (-deltaY) + m_minY;
177 return QPointF(x, y);
178 return QPointF(x, y);
178 }
179 }
179
180
180 bool LogXYDomain::attachAxis(QAbstractAxis *axis)
181 bool LogXYDomain::attachAxis(QAbstractAxis *axis)
181 {
182 {
182 AbstractDomain::attachAxis(axis);
183 AbstractDomain::attachAxis(axis);
183 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
184 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
184
185
185 if (logAxis && logAxis->orientation() == Qt::Horizontal) {
186 if (logAxis && logAxis->orientation() == Qt::Horizontal) {
186 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
187 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
187 handleHorizontalAxisBaseChanged(logAxis->base());
188 handleHorizontalAxisBaseChanged(logAxis->base());
188 }
189 }
189
190
190 return true;
191 return true;
191 }
192 }
192
193
193 bool LogXYDomain::detachAxis(QAbstractAxis *axis)
194 bool LogXYDomain::detachAxis(QAbstractAxis *axis)
194 {
195 {
195 AbstractDomain::detachAxis(axis);
196 AbstractDomain::detachAxis(axis);
196 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
197 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
197
198
198 if (logAxis && logAxis->orientation() == Qt::Horizontal)
199 if (logAxis && logAxis->orientation() == Qt::Horizontal)
199 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
200 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
200
201
201 return true;
202 return true;
202 }
203 }
203
204
204 void LogXYDomain::handleHorizontalAxisBaseChanged(qreal baseX)
205 void LogXYDomain::handleHorizontalAxisBaseChanged(qreal baseX)
205 {
206 {
206 m_logBaseX = baseX;
207 m_logBaseX = baseX;
207 qreal logMinX = log10(m_minX) / log10(m_logBaseX);
208 qreal logMinX = std::log10(m_minX) / std::log10(m_logBaseX);
208 qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
209 qreal logMaxX = std::log10(m_maxX) / std::log10(m_logBaseX);
209 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
210 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
210 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
211 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
211 emit updated();
212 emit updated();
212 }
213 }
213
214
214 // operators
215 // operators
215
216
216 bool QT_CHARTS_AUTOTEST_EXPORT operator== (const LogXYDomain &domain1, const LogXYDomain &domain2)
217 bool QT_CHARTS_AUTOTEST_EXPORT operator== (const LogXYDomain &domain1, const LogXYDomain &domain2)
217 {
218 {
218 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
219 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
219 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
220 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
220 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
221 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
221 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
222 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
222 }
223 }
223
224
224
225
225 bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const LogXYDomain &domain1, const LogXYDomain &domain2)
226 bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const LogXYDomain &domain1, const LogXYDomain &domain2)
226 {
227 {
227 return !(domain1 == domain2);
228 return !(domain1 == domain2);
228 }
229 }
229
230
230
231
231 QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXYDomain &domain)
232 QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXYDomain &domain)
232 {
233 {
233 #ifdef QT_NO_TEXTSTREAM
234 #ifdef QT_NO_TEXTSTREAM
234 Q_UNUSED(domain)
235 Q_UNUSED(domain)
235 #else
236 #else
236 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
237 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
237 #endif
238 #endif
238 return dbg.maybeSpace();
239 return dbg.maybeSpace();
239 }
240 }
240
241
241 #include "moc_logxydomain_p.cpp"
242 #include "moc_logxydomain_p.cpp"
242
243
243 QT_CHARTS_END_NAMESPACE
244 QT_CHARTS_END_NAMESPACE
@@ -1,240 +1,241
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2014 Digia Plc
3 ** Copyright (C) 2014 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.io
5 ** For any questions to Digia, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and Digia.
12 ** agreement between you and Digia.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <private/logxypolardomain_p.h>
19 #include <private/logxypolardomain_p.h>
20 #include <private/qabstractaxis_p.h>
20 #include <private/qabstractaxis_p.h>
21 #include <QtCharts/QLogValueAxis>
21 #include <QtCharts/QLogValueAxis>
22 #include <QtCore/QtMath>
22 #include <QtCore/QtMath>
23 #include <cmath>
23
24
24 QT_CHARTS_BEGIN_NAMESPACE
25 QT_CHARTS_BEGIN_NAMESPACE
25
26
26 LogXYPolarDomain::LogXYPolarDomain(QObject *parent)
27 LogXYPolarDomain::LogXYPolarDomain(QObject *parent)
27 : PolarDomain(parent),
28 : PolarDomain(parent),
28 m_logLeftX(0),
29 m_logLeftX(0),
29 m_logRightX(1),
30 m_logRightX(1),
30 m_logBaseX(10)
31 m_logBaseX(10)
31 {
32 {
32 }
33 }
33
34
34 LogXYPolarDomain::~LogXYPolarDomain()
35 LogXYPolarDomain::~LogXYPolarDomain()
35 {
36 {
36 }
37 }
37
38
38 void LogXYPolarDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
39 void LogXYPolarDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
39 {
40 {
40 bool axisXChanged = false;
41 bool axisXChanged = false;
41 bool axisYChanged = false;
42 bool axisYChanged = false;
42
43
43 adjustLogDomainRanges(minX, maxX);
44 adjustLogDomainRanges(minX, maxX);
44
45
45 if (!qFuzzyCompare(m_minX, minX) || !qFuzzyCompare(m_maxX, maxX)) {
46 if (!qFuzzyCompare(m_minX, minX) || !qFuzzyCompare(m_maxX, maxX)) {
46 m_minX = minX;
47 m_minX = minX;
47 m_maxX = maxX;
48 m_maxX = maxX;
48 axisXChanged = true;
49 axisXChanged = true;
49 qreal logMinX = log10(m_minX) / log10(m_logBaseX);
50 qreal logMinX = std::log10(m_minX) / std::log10(m_logBaseX);
50 qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
51 qreal logMaxX = std::log10(m_maxX) / std::log10(m_logBaseX);
51 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
52 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
52 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
53 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
53 if (!m_signalsBlocked)
54 if (!m_signalsBlocked)
54 emit rangeHorizontalChanged(m_minX, m_maxX);
55 emit rangeHorizontalChanged(m_minX, m_maxX);
55 }
56 }
56
57
57 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
58 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
58 m_minY = minY;
59 m_minY = minY;
59 m_maxY = maxY;
60 m_maxY = maxY;
60 axisYChanged = true;
61 axisYChanged = true;
61 if (!m_signalsBlocked)
62 if (!m_signalsBlocked)
62 emit rangeVerticalChanged(m_minY, m_maxY);
63 emit rangeVerticalChanged(m_minY, m_maxY);
63 }
64 }
64
65
65 if (axisXChanged || axisYChanged)
66 if (axisXChanged || axisYChanged)
66 emit updated();
67 emit updated();
67 }
68 }
68
69
69 void LogXYPolarDomain::zoomIn(const QRectF &rect)
70 void LogXYPolarDomain::zoomIn(const QRectF &rect)
70 {
71 {
71 storeZoomReset();
72 storeZoomReset();
72 qreal logLeftX = rect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
73 qreal logLeftX = rect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
73 qreal logRightX = rect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
74 qreal logRightX = rect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
74 qreal leftX = qPow(m_logBaseX, logLeftX);
75 qreal leftX = qPow(m_logBaseX, logLeftX);
75 qreal rightX = qPow(m_logBaseX, logRightX);
76 qreal rightX = qPow(m_logBaseX, logRightX);
76 qreal minX = leftX < rightX ? leftX : rightX;
77 qreal minX = leftX < rightX ? leftX : rightX;
77 qreal maxX = leftX > rightX ? leftX : rightX;
78 qreal maxX = leftX > rightX ? leftX : rightX;
78
79
79 qreal dy = spanY() / m_size.height();
80 qreal dy = spanY() / m_size.height();
80 qreal minY = m_minY;
81 qreal minY = m_minY;
81 qreal maxY = m_maxY;
82 qreal maxY = m_maxY;
82
83
83 minY = maxY - dy * rect.bottom();
84 minY = maxY - dy * rect.bottom();
84 maxY = maxY - dy * rect.top();
85 maxY = maxY - dy * rect.top();
85
86
86 setRange(minX, maxX, minY, maxY);
87 setRange(minX, maxX, minY, maxY);
87 }
88 }
88
89
89 void LogXYPolarDomain::zoomOut(const QRectF &rect)
90 void LogXYPolarDomain::zoomOut(const QRectF &rect)
90 {
91 {
91 storeZoomReset();
92 storeZoomReset();
92 const qreal factorX = m_size.width() / rect.width();
93 const qreal factorX = m_size.width() / rect.width();
93
94
94 qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2.0 * (1.0 - factorX);
95 qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2.0 * (1.0 - factorX);
95 qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2.0 * (1.0 + factorX);
96 qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2.0 * (1.0 + factorX);
96 qreal leftX = qPow(m_logBaseX, logLeftX);
97 qreal leftX = qPow(m_logBaseX, logLeftX);
97 qreal rightX = qPow(m_logBaseX, logRIghtX);
98 qreal rightX = qPow(m_logBaseX, logRIghtX);
98 qreal minX = leftX < rightX ? leftX : rightX;
99 qreal minX = leftX < rightX ? leftX : rightX;
99 qreal maxX = leftX > rightX ? leftX : rightX;
100 qreal maxX = leftX > rightX ? leftX : rightX;
100
101
101 qreal dy = spanY() / rect.height();
102 qreal dy = spanY() / rect.height();
102 qreal minY = m_minY;
103 qreal minY = m_minY;
103 qreal maxY = m_maxY;
104 qreal maxY = m_maxY;
104
105
105 maxY = minY + dy * rect.bottom();
106 maxY = minY + dy * rect.bottom();
106 minY = maxY - dy * m_size.height();
107 minY = maxY - dy * m_size.height();
107
108
108 setRange(minX, maxX, minY, maxY);
109 setRange(minX, maxX, minY, maxY);
109 }
110 }
110
111
111 void LogXYPolarDomain::move(qreal dx, qreal dy)
112 void LogXYPolarDomain::move(qreal dx, qreal dy)
112 {
113 {
113 qreal stepX = dx * (m_logRightX - m_logLeftX) / m_size.width();
114 qreal stepX = dx * (m_logRightX - m_logLeftX) / m_size.width();
114 qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX);
115 qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX);
115 qreal rightX = qPow(m_logBaseX, m_logRightX + stepX);
116 qreal rightX = qPow(m_logBaseX, m_logRightX + stepX);
116 qreal minX = leftX < rightX ? leftX : rightX;
117 qreal minX = leftX < rightX ? leftX : rightX;
117 qreal maxX = leftX > rightX ? leftX : rightX;
118 qreal maxX = leftX > rightX ? leftX : rightX;
118
119
119 qreal y = spanY() / m_radius;
120 qreal y = spanY() / m_radius;
120 qreal minY = m_minY;
121 qreal minY = m_minY;
121 qreal maxY = m_maxY;
122 qreal maxY = m_maxY;
122
123
123 if (dy != 0) {
124 if (dy != 0) {
124 minY = minY + y * dy;
125 minY = minY + y * dy;
125 maxY = maxY + y * dy;
126 maxY = maxY + y * dy;
126 }
127 }
127 setRange(minX, maxX, minY, maxY);
128 setRange(minX, maxX, minY, maxY);
128 }
129 }
129
130
130 qreal LogXYPolarDomain::toAngularCoordinate(qreal value, bool &ok) const
131 qreal LogXYPolarDomain::toAngularCoordinate(qreal value, bool &ok) const
131 {
132 {
132 qreal retVal;
133 qreal retVal;
133 if (value <= 0) {
134 if (value <= 0) {
134 ok = false;
135 ok = false;
135 retVal = 0.0;
136 retVal = 0.0;
136 } else {
137 } else {
137 ok = true;
138 ok = true;
138 const qreal tickSpan = 360.0 / qAbs(m_logRightX - m_logLeftX);
139 const qreal tickSpan = 360.0 / qAbs(m_logRightX - m_logLeftX);
139 const qreal logValue = log10(value) / log10(m_logBaseX);
140 const qreal logValue = std::log10(value) / std::log10(m_logBaseX);
140 const qreal valueDelta = logValue - m_logLeftX;
141 const qreal valueDelta = logValue - m_logLeftX;
141
142
142 retVal = valueDelta * tickSpan;
143 retVal = valueDelta * tickSpan;
143 }
144 }
144 return retVal;
145 return retVal;
145 }
146 }
146
147
147 qreal LogXYPolarDomain::toRadialCoordinate(qreal value, bool &ok) const
148 qreal LogXYPolarDomain::toRadialCoordinate(qreal value, bool &ok) const
148 {
149 {
149 ok = true;
150 ok = true;
150 if (value < m_minY)
151 if (value < m_minY)
151 value = m_minY;
152 value = m_minY;
152
153
153 // Dont limit the max. The drawing should clip the stuff that goes out of the grid
154 // Dont limit the max. The drawing should clip the stuff that goes out of the grid
154 qreal f = (value - m_minY) / (m_maxY - m_minY);
155 qreal f = (value - m_minY) / (m_maxY - m_minY);
155
156
156 return f * m_radius;
157 return f * m_radius;
157 }
158 }
158
159
159 QPointF LogXYPolarDomain::calculateDomainPoint(const QPointF &point) const
160 QPointF LogXYPolarDomain::calculateDomainPoint(const QPointF &point) const
160 {
161 {
161 if (point == m_center)
162 if (point == m_center)
162 return QPointF(0.0, m_minY);
163 return QPointF(0.0, m_minY);
163
164
164 QLineF line(m_center, point);
165 QLineF line(m_center, point);
165 qreal a = 90.0 - line.angle();
166 qreal a = 90.0 - line.angle();
166 if (a < 0.0)
167 if (a < 0.0)
167 a += 360.0;
168 a += 360.0;
168
169
169 const qreal deltaX = 360.0 / qAbs(m_logRightX - m_logLeftX);
170 const qreal deltaX = 360.0 / qAbs(m_logRightX - m_logLeftX);
170 a = qPow(m_logBaseX, m_logLeftX + (a / deltaX));
171 a = qPow(m_logBaseX, m_logLeftX + (a / deltaX));
171
172
172 qreal r = m_minY + ((m_maxY - m_minY) * (line.length() / m_radius));
173 qreal r = m_minY + ((m_maxY - m_minY) * (line.length() / m_radius));
173
174
174 return QPointF(a, r);
175 return QPointF(a, r);
175 }
176 }
176
177
177 bool LogXYPolarDomain::attachAxis(QAbstractAxis *axis)
178 bool LogXYPolarDomain::attachAxis(QAbstractAxis *axis)
178 {
179 {
179 AbstractDomain::attachAxis(axis);
180 AbstractDomain::attachAxis(axis);
180 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
181 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
181
182
182 if (logAxis && logAxis->orientation() == Qt::Horizontal) {
183 if (logAxis && logAxis->orientation() == Qt::Horizontal) {
183 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
184 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
184 handleHorizontalAxisBaseChanged(logAxis->base());
185 handleHorizontalAxisBaseChanged(logAxis->base());
185 }
186 }
186
187
187 return true;
188 return true;
188 }
189 }
189
190
190 bool LogXYPolarDomain::detachAxis(QAbstractAxis *axis)
191 bool LogXYPolarDomain::detachAxis(QAbstractAxis *axis)
191 {
192 {
192 AbstractDomain::detachAxis(axis);
193 AbstractDomain::detachAxis(axis);
193 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
194 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
194
195
195 if (logAxis && logAxis->orientation() == Qt::Horizontal)
196 if (logAxis && logAxis->orientation() == Qt::Horizontal)
196 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
197 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
197
198
198 return true;
199 return true;
199 }
200 }
200
201
201 void LogXYPolarDomain::handleHorizontalAxisBaseChanged(qreal baseX)
202 void LogXYPolarDomain::handleHorizontalAxisBaseChanged(qreal baseX)
202 {
203 {
203 m_logBaseX = baseX;
204 m_logBaseX = baseX;
204 qreal logMinX = log10(m_minX) / log10(m_logBaseX);
205 qreal logMinX = std::log10(m_minX) / std::log10(m_logBaseX);
205 qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
206 qreal logMaxX = std::log10(m_maxX) / std::log10(m_logBaseX);
206 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
207 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
207 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
208 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
208 emit updated();
209 emit updated();
209 }
210 }
210
211
211 // operators
212 // operators
212
213
213 bool QT_CHARTS_AUTOTEST_EXPORT operator== (const LogXYPolarDomain &domain1, const LogXYPolarDomain &domain2)
214 bool QT_CHARTS_AUTOTEST_EXPORT operator== (const LogXYPolarDomain &domain1, const LogXYPolarDomain &domain2)
214 {
215 {
215 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
216 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
216 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
217 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
217 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
218 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
218 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
219 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
219 }
220 }
220
221
221
222
222 bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const LogXYPolarDomain &domain1, const LogXYPolarDomain &domain2)
223 bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const LogXYPolarDomain &domain1, const LogXYPolarDomain &domain2)
223 {
224 {
224 return !(domain1 == domain2);
225 return !(domain1 == domain2);
225 }
226 }
226
227
227
228
228 QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXYPolarDomain &domain)
229 QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXYPolarDomain &domain)
229 {
230 {
230 #ifdef QT_NO_TEXTSTREAM
231 #ifdef QT_NO_TEXTSTREAM
231 Q_UNUSED(domain)
232 Q_UNUSED(domain)
232 #else
233 #else
233 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
234 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
234 #endif
235 #endif
235 return dbg.maybeSpace();
236 return dbg.maybeSpace();
236 }
237 }
237
238
238 #include "moc_logxypolardomain_p.cpp"
239 #include "moc_logxypolardomain_p.cpp"
239
240
240 QT_CHARTS_END_NAMESPACE
241 QT_CHARTS_END_NAMESPACE
@@ -1,239 +1,240
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2014 Digia Plc
3 ** Copyright (C) 2014 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.io
5 ** For any questions to Digia, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and Digia.
12 ** agreement between you and Digia.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <private/xlogydomain_p.h>
19 #include <private/xlogydomain_p.h>
20 #include <private/qabstractaxis_p.h>
20 #include <private/qabstractaxis_p.h>
21 #include <QtCharts/QLogValueAxis>
21 #include <QtCharts/QLogValueAxis>
22 #include <QtCore/QtMath>
22 #include <QtCore/QtMath>
23 #include <cmath>
23
24
24 QT_CHARTS_BEGIN_NAMESPACE
25 QT_CHARTS_BEGIN_NAMESPACE
25
26
26 XLogYDomain::XLogYDomain(QObject *parent)
27 XLogYDomain::XLogYDomain(QObject *parent)
27 : AbstractDomain(parent),
28 : AbstractDomain(parent),
28 m_logLeftY(0),
29 m_logLeftY(0),
29 m_logRightY(1),
30 m_logRightY(1),
30 m_logBaseY(10)
31 m_logBaseY(10)
31 {
32 {
32 }
33 }
33
34
34 XLogYDomain::~XLogYDomain()
35 XLogYDomain::~XLogYDomain()
35 {
36 {
36 }
37 }
37
38
38 void XLogYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
39 void XLogYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
39 {
40 {
40 bool axisXChanged = false;
41 bool axisXChanged = false;
41 bool axisYChanged = false;
42 bool axisYChanged = false;
42
43
43 adjustLogDomainRanges(minY, maxY);
44 adjustLogDomainRanges(minY, maxY);
44
45
45 if (!qFuzzyIsNull(m_minX - minX) || !qFuzzyIsNull(m_maxX - maxX)) {
46 if (!qFuzzyIsNull(m_minX - minX) || !qFuzzyIsNull(m_maxX - maxX)) {
46 m_minX = minX;
47 m_minX = minX;
47 m_maxX = maxX;
48 m_maxX = maxX;
48 axisXChanged = true;
49 axisXChanged = true;
49 if(!m_signalsBlocked)
50 if(!m_signalsBlocked)
50 emit rangeHorizontalChanged(m_minX, m_maxX);
51 emit rangeHorizontalChanged(m_minX, m_maxX);
51 }
52 }
52
53
53 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
54 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
54 m_minY = minY;
55 m_minY = minY;
55 m_maxY = maxY;
56 m_maxY = maxY;
56 axisYChanged = true;
57 axisYChanged = true;
57 qreal logMinY = log10(m_minY) / log10(m_logBaseY);
58 qreal logMinY = std::log10(m_minY) / std::log10(m_logBaseY);
58 qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
59 qreal logMaxY = std::log10(m_maxY) / std::log10(m_logBaseY);
59 m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
60 m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
60 m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
61 m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
61 if (!m_signalsBlocked)
62 if (!m_signalsBlocked)
62 emit rangeVerticalChanged(m_minY, m_maxY);
63 emit rangeVerticalChanged(m_minY, m_maxY);
63 }
64 }
64
65
65 if (axisXChanged || axisYChanged)
66 if (axisXChanged || axisYChanged)
66 emit updated();
67 emit updated();
67 }
68 }
68
69
69 void XLogYDomain::zoomIn(const QRectF &rect)
70 void XLogYDomain::zoomIn(const QRectF &rect)
70 {
71 {
71 storeZoomReset();
72 storeZoomReset();
72 qreal dx = spanX() / m_size.width();
73 qreal dx = spanX() / m_size.width();
73 qreal maxX = m_maxX;
74 qreal maxX = m_maxX;
74 qreal minX = m_minX;
75 qreal minX = m_minX;
75
76
76 maxX = minX + dx * rect.right();
77 maxX = minX + dx * rect.right();
77 minX = minX + dx * rect.left();
78 minX = minX + dx * rect.left();
78
79
79 qreal logLeftY = m_logRightY - rect.bottom() * (m_logRightY - m_logLeftY) / m_size.height();
80 qreal logLeftY = m_logRightY - rect.bottom() * (m_logRightY - m_logLeftY) / m_size.height();
80 qreal logRightY = m_logRightY - rect.top() * (m_logRightY - m_logLeftY) / m_size.height();
81 qreal logRightY = m_logRightY - rect.top() * (m_logRightY - m_logLeftY) / m_size.height();
81 qreal leftY = qPow(m_logBaseY, logLeftY);
82 qreal leftY = qPow(m_logBaseY, logLeftY);
82 qreal rightY = qPow(m_logBaseY, logRightY);
83 qreal rightY = qPow(m_logBaseY, logRightY);
83 qreal minY = leftY < rightY ? leftY : rightY;
84 qreal minY = leftY < rightY ? leftY : rightY;
84 qreal maxY = leftY > rightY ? leftY : rightY;
85 qreal maxY = leftY > rightY ? leftY : rightY;
85
86
86 setRange(minX, maxX, minY, maxY);
87 setRange(minX, maxX, minY, maxY);
87 }
88 }
88
89
89 void XLogYDomain::zoomOut(const QRectF &rect)
90 void XLogYDomain::zoomOut(const QRectF &rect)
90 {
91 {
91 storeZoomReset();
92 storeZoomReset();
92 qreal dx = spanX() / rect.width();
93 qreal dx = spanX() / rect.width();
93 qreal maxX = m_maxX;
94 qreal maxX = m_maxX;
94 qreal minX = m_minX;
95 qreal minX = m_minX;
95
96
96 minX = maxX - dx * rect.right();
97 minX = maxX - dx * rect.right();
97 maxX = minX + dx * m_size.width();
98 maxX = minX + dx * m_size.width();
98
99
99 const qreal factorY = m_size.height() / rect.height();
100 const qreal factorY = m_size.height() / rect.height();
100 qreal newLogMinY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 - factorY);
101 qreal newLogMinY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 - factorY);
101 qreal newLogMaxY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 + factorY);
102 qreal newLogMaxY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 + factorY);
102 qreal leftY = qPow(m_logBaseY, newLogMinY);
103 qreal leftY = qPow(m_logBaseY, newLogMinY);
103 qreal rightY = qPow(m_logBaseY, newLogMaxY);
104 qreal rightY = qPow(m_logBaseY, newLogMaxY);
104 qreal minY = leftY < rightY ? leftY : rightY;
105 qreal minY = leftY < rightY ? leftY : rightY;
105 qreal maxY = leftY > rightY ? leftY : rightY;
106 qreal maxY = leftY > rightY ? leftY : rightY;
106
107
107 setRange(minX, maxX, minY, maxY);
108 setRange(minX, maxX, minY, maxY);
108 }
109 }
109
110
110 void XLogYDomain::move(qreal dx, qreal dy)
111 void XLogYDomain::move(qreal dx, qreal dy)
111 {
112 {
112 qreal x = spanX() / m_size.width();
113 qreal x = spanX() / m_size.width();
113 qreal maxX = m_maxX;
114 qreal maxX = m_maxX;
114 qreal minX = m_minX;
115 qreal minX = m_minX;
115
116
116 if (dx != 0) {
117 if (dx != 0) {
117 minX = minX + x * dx;
118 minX = minX + x * dx;
118 maxX = maxX + x * dx;
119 maxX = maxX + x * dx;
119 }
120 }
120
121
121 qreal stepY = dy * (m_logRightY - m_logLeftY) / m_size.height();
122 qreal stepY = dy * (m_logRightY - m_logLeftY) / m_size.height();
122 qreal leftY = qPow(m_logBaseY, m_logLeftY + stepY);
123 qreal leftY = qPow(m_logBaseY, m_logLeftY + stepY);
123 qreal rightY = qPow(m_logBaseY, m_logRightY + stepY);
124 qreal rightY = qPow(m_logBaseY, m_logRightY + stepY);
124 qreal minY = leftY < rightY ? leftY : rightY;
125 qreal minY = leftY < rightY ? leftY : rightY;
125 qreal maxY = leftY > rightY ? leftY : rightY;
126 qreal maxY = leftY > rightY ? leftY : rightY;
126
127
127 setRange(minX, maxX, minY, maxY);
128 setRange(minX, maxX, minY, maxY);
128 }
129 }
129
130
130 QPointF XLogYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
131 QPointF XLogYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
131 {
132 {
132 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
133 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
133 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
134 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
134
135
135 qreal x = (point.x() - m_minX) * deltaX;
136 qreal x = (point.x() - m_minX) * deltaX;
136 qreal y(0);
137 qreal y(0);
137 if (point.y() > 0) {
138 if (point.y() > 0) {
138 y = (log10(point.y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
139 y = (std::log10(point.y()) / std::log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
139 ok = true;
140 ok = true;
140 } else {
141 } else {
141 y = m_size.height();
142 y = m_size.height();
142 qWarning() << "Logarithms of zero and negative values are undefined.";
143 qWarning() << "Logarithms of zero and negative values are undefined.";
143 ok = false;
144 ok = false;
144 }
145 }
145 return QPointF(x, y);
146 return QPointF(x, y);
146 }
147 }
147
148
148 QVector<QPointF> XLogYDomain::calculateGeometryPoints(const QList<QPointF> &vector) const
149 QVector<QPointF> XLogYDomain::calculateGeometryPoints(const QList<QPointF> &vector) const
149 {
150 {
150 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
151 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
151 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
152 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
152
153
153 QVector<QPointF> result;
154 QVector<QPointF> result;
154 result.resize(vector.count());
155 result.resize(vector.count());
155
156
156 for (int i = 0; i < vector.count(); ++i) {
157 for (int i = 0; i < vector.count(); ++i) {
157 if (vector[i].y() > 0) {
158 if (vector[i].y() > 0) {
158 qreal x = (vector[i].x() - m_minX) * deltaX;
159 qreal x = (vector[i].x() - m_minX) * deltaX;
159 qreal y = (log10(vector[i].y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
160 qreal y = (std::log10(vector[i].y()) / std::log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
160 result[i].setX(x);
161 result[i].setX(x);
161 result[i].setY(y);
162 result[i].setY(y);
162 } else {
163 } else {
163 qWarning() << "Logarithms of zero and negative values are undefined.";
164 qWarning() << "Logarithms of zero and negative values are undefined.";
164 return QVector<QPointF>();
165 return QVector<QPointF>();
165 }
166 }
166 }
167 }
167 return result;
168 return result;
168 }
169 }
169
170
170 QPointF XLogYDomain::calculateDomainPoint(const QPointF &point) const
171 QPointF XLogYDomain::calculateDomainPoint(const QPointF &point) const
171 {
172 {
172 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
173 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
173 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
174 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
174 qreal x = point.x() / deltaX + m_minX;
175 qreal x = point.x() / deltaX + m_minX;
175 qreal y = qPow(m_logBaseY, m_logLeftY + (m_size.height() - point.y()) / deltaY);
176 qreal y = qPow(m_logBaseY, m_logLeftY + (m_size.height() - point.y()) / deltaY);
176 return QPointF(x, y);
177 return QPointF(x, y);
177 }
178 }
178
179
179 bool XLogYDomain::attachAxis(QAbstractAxis *axis)
180 bool XLogYDomain::attachAxis(QAbstractAxis *axis)
180 {
181 {
181 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
182 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
182
183
183 if (logAxis && logAxis->orientation() == Qt::Vertical) {
184 if (logAxis && logAxis->orientation() == Qt::Vertical) {
184 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
185 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
185 handleVerticalAxisBaseChanged(logAxis->base());
186 handleVerticalAxisBaseChanged(logAxis->base());
186 }
187 }
187 return AbstractDomain::attachAxis(axis);
188 return AbstractDomain::attachAxis(axis);
188 }
189 }
189
190
190 bool XLogYDomain::detachAxis(QAbstractAxis *axis)
191 bool XLogYDomain::detachAxis(QAbstractAxis *axis)
191 {
192 {
192 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
193 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
193
194
194 if (logAxis && logAxis->orientation() == Qt::Vertical)
195 if (logAxis && logAxis->orientation() == Qt::Vertical)
195 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
196 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
196
197
197 return AbstractDomain::detachAxis(axis);
198 return AbstractDomain::detachAxis(axis);
198 }
199 }
199
200
200 void XLogYDomain::handleVerticalAxisBaseChanged(qreal baseY)
201 void XLogYDomain::handleVerticalAxisBaseChanged(qreal baseY)
201 {
202 {
202 m_logBaseY = baseY;
203 m_logBaseY = baseY;
203 qreal logMinY = log10(m_minY) / log10(m_logBaseY);
204 qreal logMinY = std::log10(m_minY) / std::log10(m_logBaseY);
204 qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
205 qreal logMaxY = std::log10(m_maxY) / std::log10(m_logBaseY);
205 m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
206 m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
206 m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
207 m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
207 emit updated();
208 emit updated();
208 }
209 }
209
210
210 // operators
211 // operators
211
212
212 bool QT_CHARTS_AUTOTEST_EXPORT operator== (const XLogYDomain &domain1, const XLogYDomain &domain2)
213 bool QT_CHARTS_AUTOTEST_EXPORT operator== (const XLogYDomain &domain1, const XLogYDomain &domain2)
213 {
214 {
214 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
215 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
215 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
216 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
216 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
217 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
217 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
218 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
218 }
219 }
219
220
220
221
221 bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const XLogYDomain &domain1, const XLogYDomain &domain2)
222 bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const XLogYDomain &domain1, const XLogYDomain &domain2)
222 {
223 {
223 return !(domain1 == domain2);
224 return !(domain1 == domain2);
224 }
225 }
225
226
226
227
227 QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const XLogYDomain &domain)
228 QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const XLogYDomain &domain)
228 {
229 {
229 #ifdef QT_NO_TEXTSTREAM
230 #ifdef QT_NO_TEXTSTREAM
230 Q_UNUSED(domain)
231 Q_UNUSED(domain)
231 #else
232 #else
232 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
233 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
233 #endif
234 #endif
234 return dbg.maybeSpace();
235 return dbg.maybeSpace();
235 }
236 }
236
237
237 #include "moc_xlogydomain_p.cpp"
238 #include "moc_xlogydomain_p.cpp"
238
239
239 QT_CHARTS_END_NAMESPACE
240 QT_CHARTS_END_NAMESPACE
@@ -1,235 +1,236
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2014 Digia Plc
3 ** Copyright (C) 2014 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.io
5 ** For any questions to Digia, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and Digia.
12 ** agreement between you and Digia.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <private/xlogypolardomain_p.h>
19 #include <private/xlogypolardomain_p.h>
20 #include <private/qabstractaxis_p.h>
20 #include <private/qabstractaxis_p.h>
21 #include <QtCharts/QLogValueAxis>
21 #include <QtCharts/QLogValueAxis>
22 #include <QtCore/QtMath>
22 #include <QtCore/QtMath>
23 #include <cmath>
23
24
24 QT_CHARTS_BEGIN_NAMESPACE
25 QT_CHARTS_BEGIN_NAMESPACE
25
26
26 XLogYPolarDomain::XLogYPolarDomain(QObject *parent)
27 XLogYPolarDomain::XLogYPolarDomain(QObject *parent)
27 : PolarDomain(parent),
28 : PolarDomain(parent),
28 m_logInnerY(0),
29 m_logInnerY(0),
29 m_logOuterY(1),
30 m_logOuterY(1),
30 m_logBaseY(10)
31 m_logBaseY(10)
31 {
32 {
32 }
33 }
33
34
34 XLogYPolarDomain::~XLogYPolarDomain()
35 XLogYPolarDomain::~XLogYPolarDomain()
35 {
36 {
36 }
37 }
37
38
38 void XLogYPolarDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
39 void XLogYPolarDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
39 {
40 {
40 bool axisXChanged = false;
41 bool axisXChanged = false;
41 bool axisYChanged = false;
42 bool axisYChanged = false;
42
43
43 adjustLogDomainRanges(minY, maxY);
44 adjustLogDomainRanges(minY, maxY);
44
45
45 if (!qFuzzyIsNull(m_minX - minX) || !qFuzzyIsNull(m_maxX - maxX)) {
46 if (!qFuzzyIsNull(m_minX - minX) || !qFuzzyIsNull(m_maxX - maxX)) {
46 m_minX = minX;
47 m_minX = minX;
47 m_maxX = maxX;
48 m_maxX = maxX;
48 axisXChanged = true;
49 axisXChanged = true;
49 if (!m_signalsBlocked)
50 if (!m_signalsBlocked)
50 emit rangeHorizontalChanged(m_minX, m_maxX);
51 emit rangeHorizontalChanged(m_minX, m_maxX);
51 }
52 }
52
53
53 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
54 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
54 m_minY = minY;
55 m_minY = minY;
55 m_maxY = maxY;
56 m_maxY = maxY;
56 axisYChanged = true;
57 axisYChanged = true;
57 qreal logMinY = log10(m_minY) / log10(m_logBaseY);
58 qreal logMinY = std::log10(m_minY) / std::log10(m_logBaseY);
58 qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
59 qreal logMaxY = std::log10(m_maxY) / std::log10(m_logBaseY);
59 m_logInnerY = logMinY < logMaxY ? logMinY : logMaxY;
60 m_logInnerY = logMinY < logMaxY ? logMinY : logMaxY;
60 m_logOuterY = logMinY > logMaxY ? logMinY : logMaxY;
61 m_logOuterY = logMinY > logMaxY ? logMinY : logMaxY;
61 if (!m_signalsBlocked)
62 if (!m_signalsBlocked)
62 emit rangeVerticalChanged(m_minY, m_maxY);
63 emit rangeVerticalChanged(m_minY, m_maxY);
63 }
64 }
64
65
65 if (axisXChanged || axisYChanged)
66 if (axisXChanged || axisYChanged)
66 emit updated();
67 emit updated();
67 }
68 }
68
69
69 void XLogYPolarDomain::zoomIn(const QRectF &rect)
70 void XLogYPolarDomain::zoomIn(const QRectF &rect)
70 {
71 {
71 storeZoomReset();
72 storeZoomReset();
72 qreal dx = spanX() / m_size.width();
73 qreal dx = spanX() / m_size.width();
73 qreal maxX = m_maxX;
74 qreal maxX = m_maxX;
74 qreal minX = m_minX;
75 qreal minX = m_minX;
75
76
76 maxX = minX + dx * rect.right();
77 maxX = minX + dx * rect.right();
77 minX = minX + dx * rect.left();
78 minX = minX + dx * rect.left();
78
79
79 qreal logLeftY = m_logOuterY - rect.bottom() * (m_logOuterY - m_logInnerY) / m_size.height();
80 qreal logLeftY = m_logOuterY - rect.bottom() * (m_logOuterY - m_logInnerY) / m_size.height();
80 qreal logRightY = m_logOuterY - rect.top() * (m_logOuterY - m_logInnerY) / m_size.height();
81 qreal logRightY = m_logOuterY - rect.top() * (m_logOuterY - m_logInnerY) / m_size.height();
81 qreal leftY = qPow(m_logBaseY, logLeftY);
82 qreal leftY = qPow(m_logBaseY, logLeftY);
82 qreal rightY = qPow(m_logBaseY, logRightY);
83 qreal rightY = qPow(m_logBaseY, logRightY);
83 qreal minY = leftY < rightY ? leftY : rightY;
84 qreal minY = leftY < rightY ? leftY : rightY;
84 qreal maxY = leftY > rightY ? leftY : rightY;
85 qreal maxY = leftY > rightY ? leftY : rightY;
85
86
86 setRange(minX, maxX, minY, maxY);
87 setRange(minX, maxX, minY, maxY);
87 }
88 }
88
89
89 void XLogYPolarDomain::zoomOut(const QRectF &rect)
90 void XLogYPolarDomain::zoomOut(const QRectF &rect)
90 {
91 {
91 storeZoomReset();
92 storeZoomReset();
92 qreal dx = spanX() / rect.width();
93 qreal dx = spanX() / rect.width();
93 qreal maxX = m_maxX;
94 qreal maxX = m_maxX;
94 qreal minX = m_minX;
95 qreal minX = m_minX;
95
96
96 minX = maxX - dx * rect.right();
97 minX = maxX - dx * rect.right();
97 maxX = minX + dx * m_size.width();
98 maxX = minX + dx * m_size.width();
98
99
99 const qreal factorY = m_size.height() / rect.height();
100 const qreal factorY = m_size.height() / rect.height();
100 qreal newLogMinY = m_logInnerY + (m_logOuterY - m_logInnerY) / 2.0 * (1.0 - factorY);
101 qreal newLogMinY = m_logInnerY + (m_logOuterY - m_logInnerY) / 2.0 * (1.0 - factorY);
101 qreal newLogMaxY = m_logInnerY + (m_logOuterY - m_logInnerY) / 2.0 * (1.0 + factorY);
102 qreal newLogMaxY = m_logInnerY + (m_logOuterY - m_logInnerY) / 2.0 * (1.0 + factorY);
102 qreal leftY = qPow(m_logBaseY, newLogMinY);
103 qreal leftY = qPow(m_logBaseY, newLogMinY);
103 qreal rightY = qPow(m_logBaseY, newLogMaxY);
104 qreal rightY = qPow(m_logBaseY, newLogMaxY);
104 qreal minY = leftY < rightY ? leftY : rightY;
105 qreal minY = leftY < rightY ? leftY : rightY;
105 qreal maxY = leftY > rightY ? leftY : rightY;
106 qreal maxY = leftY > rightY ? leftY : rightY;
106
107
107 setRange(minX, maxX, minY, maxY);
108 setRange(minX, maxX, minY, maxY);
108 }
109 }
109
110
110 void XLogYPolarDomain::move(qreal dx, qreal dy)
111 void XLogYPolarDomain::move(qreal dx, qreal dy)
111 {
112 {
112 qreal x = spanX() / 360.0;
113 qreal x = spanX() / 360.0;
113
114
114 qreal maxX = m_maxX;
115 qreal maxX = m_maxX;
115 qreal minX = m_minX;
116 qreal minX = m_minX;
116
117
117 if (dx != 0) {
118 if (dx != 0) {
118 minX = minX + x * dx;
119 minX = minX + x * dx;
119 maxX = maxX + x * dx;
120 maxX = maxX + x * dx;
120 }
121 }
121
122
122 qreal stepY = dy * (m_logOuterY - m_logInnerY) / m_radius;
123 qreal stepY = dy * (m_logOuterY - m_logInnerY) / m_radius;
123 qreal leftY = qPow(m_logBaseY, m_logInnerY + stepY);
124 qreal leftY = qPow(m_logBaseY, m_logInnerY + stepY);
124 qreal rightY = qPow(m_logBaseY, m_logOuterY + stepY);
125 qreal rightY = qPow(m_logBaseY, m_logOuterY + stepY);
125 qreal minY = leftY < rightY ? leftY : rightY;
126 qreal minY = leftY < rightY ? leftY : rightY;
126 qreal maxY = leftY > rightY ? leftY : rightY;
127 qreal maxY = leftY > rightY ? leftY : rightY;
127
128
128 setRange(minX, maxX, minY, maxY);
129 setRange(minX, maxX, minY, maxY);
129 }
130 }
130
131
131 qreal XLogYPolarDomain::toAngularCoordinate(qreal value, bool &ok) const
132 qreal XLogYPolarDomain::toAngularCoordinate(qreal value, bool &ok) const
132 {
133 {
133 ok = true;
134 ok = true;
134 qreal f = (value - m_minX) / (m_maxX - m_minX);
135 qreal f = (value - m_minX) / (m_maxX - m_minX);
135 return f * 360.0;
136 return f * 360.0;
136 }
137 }
137
138
138 qreal XLogYPolarDomain::toRadialCoordinate(qreal value, bool &ok) const
139 qreal XLogYPolarDomain::toRadialCoordinate(qreal value, bool &ok) const
139 {
140 {
140 qreal retVal;
141 qreal retVal;
141 if (value <= 0) {
142 if (value <= 0) {
142 ok = false;
143 ok = false;
143 retVal = 0.0;
144 retVal = 0.0;
144 } else {
145 } else {
145 ok = true;
146 ok = true;
146 const qreal tickSpan = m_radius / qAbs(m_logOuterY - m_logInnerY);
147 const qreal tickSpan = m_radius / qAbs(m_logOuterY - m_logInnerY);
147 const qreal logValue = log10(value) / log10(m_logBaseY);
148 const qreal logValue = std::log10(value) / std::log10(m_logBaseY);
148 const qreal valueDelta = logValue - m_logInnerY;
149 const qreal valueDelta = logValue - m_logInnerY;
149
150
150 retVal = valueDelta * tickSpan;
151 retVal = valueDelta * tickSpan;
151
152
152 if (retVal < 0.0)
153 if (retVal < 0.0)
153 retVal = 0.0;
154 retVal = 0.0;
154 }
155 }
155 return retVal;
156 return retVal;
156 }
157 }
157
158
158 QPointF XLogYPolarDomain::calculateDomainPoint(const QPointF &point) const
159 QPointF XLogYPolarDomain::calculateDomainPoint(const QPointF &point) const
159 {
160 {
160 if (point == m_center)
161 if (point == m_center)
161 return QPointF(0.0, m_minY);
162 return QPointF(0.0, m_minY);
162
163
163 QLineF line(m_center, point);
164 QLineF line(m_center, point);
164 qreal a = 90.0 - line.angle();
165 qreal a = 90.0 - line.angle();
165 if (a < 0.0)
166 if (a < 0.0)
166 a += 360.0;
167 a += 360.0;
167 a = ((a / 360.0) * (m_maxX - m_minX)) + m_minX;
168 a = ((a / 360.0) * (m_maxX - m_minX)) + m_minX;
168
169
169 const qreal deltaY = m_radius / qAbs(m_logOuterY - m_logInnerY);
170 const qreal deltaY = m_radius / qAbs(m_logOuterY - m_logInnerY);
170 qreal r = qPow(m_logBaseY, m_logInnerY + (line.length() / deltaY));
171 qreal r = qPow(m_logBaseY, m_logInnerY + (line.length() / deltaY));
171
172
172 return QPointF(a, r);
173 return QPointF(a, r);
173 }
174 }
174
175
175 bool XLogYPolarDomain::attachAxis(QAbstractAxis *axis)
176 bool XLogYPolarDomain::attachAxis(QAbstractAxis *axis)
176 {
177 {
177 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
178 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
178
179
179 if (logAxis && logAxis->orientation() == Qt::Vertical) {
180 if (logAxis && logAxis->orientation() == Qt::Vertical) {
180 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
181 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
181 handleVerticalAxisBaseChanged(logAxis->base());
182 handleVerticalAxisBaseChanged(logAxis->base());
182 }
183 }
183 return AbstractDomain::attachAxis(axis);
184 return AbstractDomain::attachAxis(axis);
184 }
185 }
185
186
186 bool XLogYPolarDomain::detachAxis(QAbstractAxis *axis)
187 bool XLogYPolarDomain::detachAxis(QAbstractAxis *axis)
187 {
188 {
188 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
189 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
189
190
190 if (logAxis && logAxis->orientation() == Qt::Vertical)
191 if (logAxis && logAxis->orientation() == Qt::Vertical)
191 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
192 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
192
193
193 return AbstractDomain::detachAxis(axis);
194 return AbstractDomain::detachAxis(axis);
194 }
195 }
195
196
196 void XLogYPolarDomain::handleVerticalAxisBaseChanged(qreal baseY)
197 void XLogYPolarDomain::handleVerticalAxisBaseChanged(qreal baseY)
197 {
198 {
198 m_logBaseY = baseY;
199 m_logBaseY = baseY;
199 qreal logMinY = log10(m_minY) / log10(m_logBaseY);
200 qreal logMinY = std::log10(m_minY) / std::log10(m_logBaseY);
200 qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
201 qreal logMaxY = std::log10(m_maxY) / std::log10(m_logBaseY);
201 m_logInnerY = logMinY < logMaxY ? logMinY : logMaxY;
202 m_logInnerY = logMinY < logMaxY ? logMinY : logMaxY;
202 m_logOuterY = logMinY > logMaxY ? logMinY : logMaxY;
203 m_logOuterY = logMinY > logMaxY ? logMinY : logMaxY;
203 emit updated();
204 emit updated();
204 }
205 }
205
206
206 // operators
207 // operators
207
208
208 bool QT_CHARTS_AUTOTEST_EXPORT operator== (const XLogYPolarDomain &domain1, const XLogYPolarDomain &domain2)
209 bool QT_CHARTS_AUTOTEST_EXPORT operator== (const XLogYPolarDomain &domain1, const XLogYPolarDomain &domain2)
209 {
210 {
210 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
211 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
211 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
212 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
212 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
213 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
213 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
214 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
214 }
215 }
215
216
216
217
217 bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const XLogYPolarDomain &domain1, const XLogYPolarDomain &domain2)
218 bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const XLogYPolarDomain &domain1, const XLogYPolarDomain &domain2)
218 {
219 {
219 return !(domain1 == domain2);
220 return !(domain1 == domain2);
220 }
221 }
221
222
222
223
223 QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const XLogYPolarDomain &domain)
224 QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const XLogYPolarDomain &domain)
224 {
225 {
225 #ifdef QT_NO_TEXTSTREAM
226 #ifdef QT_NO_TEXTSTREAM
226 Q_UNUSED(domain)
227 Q_UNUSED(domain)
227 #else
228 #else
228 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
229 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
229 #endif
230 #endif
230 return dbg.maybeSpace();
231 return dbg.maybeSpace();
231 }
232 }
232
233
233 #include "moc_xlogypolardomain_p.cpp"
234 #include "moc_xlogypolardomain_p.cpp"
234
235
235 QT_CHARTS_END_NAMESPACE
236 QT_CHARTS_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now