@@ -99,6 +99,25 QT_CHARTS_BEGIN_NAMESPACE | |||
|
99 | 99 | Axis emits signal when the categories of the axis have changed. |
|
100 | 100 | */ |
|
101 | 101 | |
|
102 | /*! | |
|
103 | \enum QCategoryAxis::AxisLabelsPosition | |
|
104 | ||
|
105 | This enum describes the position of the category labels. | |
|
106 | ||
|
107 | \value AxisLabelsPositionCenter Labels are centered to category. | |
|
108 | \value AxisLabelsPositionOnValue Labels are positioned to the high end limit of the category. | |
|
109 | */ | |
|
110 | /*! | |
|
111 | \property QCategoryAxis::labelsPosition | |
|
112 | Defines the position of the category labels. The labels in the beginning and in the end of the | |
|
113 | axes may overlap other axes labels when positioned on value. | |
|
114 | */ | |
|
115 | /*! | |
|
116 | \qmlproperty AxisLabelsPosition CategoryAxis::labelsPosition | |
|
117 | Defines the position of the category labels. The labels in the beginning and in the end of the | |
|
118 | axes may overlap other axes labels when positioned on value. | |
|
119 | */ | |
|
120 | ||
|
102 | 121 | |
|
103 | 122 | /*! |
|
104 | 123 | Constructs an axis object which is a child of \a parent. |
@@ -284,11 +303,27 QAbstractAxis::AxisType QCategoryAxis::type() const | |||
|
284 | 303 | return QAbstractAxis::AxisTypeCategory; |
|
285 | 304 | } |
|
286 | 305 | |
|
306 | void QCategoryAxis::setLabelsPosition(QCategoryAxis::AxisLabelsPosition position) | |
|
307 | { | |
|
308 | Q_D(QCategoryAxis); | |
|
309 | if (d->m_labelsPosition != position) { | |
|
310 | d->m_labelsPosition = position; | |
|
311 | emit labelsPositionChanged(position); | |
|
312 | } | |
|
313 | } | |
|
314 | ||
|
315 | QCategoryAxis::AxisLabelsPosition QCategoryAxis::labelsPosition() const | |
|
316 | { | |
|
317 | Q_D(const QCategoryAxis); | |
|
318 | return d->m_labelsPosition; | |
|
319 | } | |
|
320 | ||
|
287 | 321 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
288 | 322 | |
|
289 | 323 | QCategoryAxisPrivate::QCategoryAxisPrivate(QCategoryAxis *q) |
|
290 | 324 | : QValueAxisPrivate(q), |
|
291 | m_categoryMinimum(0) | |
|
325 | m_categoryMinimum(0), | |
|
326 | m_labelsPosition(QCategoryAxis::AxisLabelsPositionCenter) | |
|
292 | 327 | { |
|
293 | 328 | |
|
294 | 329 | } |
@@ -32,8 +32,16 class QT_CHARTS_EXPORT QCategoryAxis : public QValueAxis | |||
|
32 | 32 | Q_PROPERTY(qreal startValue READ startValue WRITE setStartValue) |
|
33 | 33 | Q_PROPERTY(int count READ count) |
|
34 | 34 | Q_PROPERTY(QStringList categoriesLabels READ categoriesLabels) |
|
35 | Q_PROPERTY(AxisLabelsPosition labelsPosition READ labelsPosition WRITE setLabelsPosition NOTIFY labelsPositionChanged) | |
|
36 | Q_ENUMS(AxisLabelsPosition) | |
|
35 | 37 | |
|
36 | 38 | public: |
|
39 | ||
|
40 | enum AxisLabelsPosition { | |
|
41 | AxisLabelsPositionCenter = 0x0, | |
|
42 | AxisLabelsPositionOnValue = 0x1 | |
|
43 | }; | |
|
44 | ||
|
37 | 45 | explicit QCategoryAxis(QObject *parent = 0); |
|
38 | 46 | ~QCategoryAxis(); |
|
39 | 47 | |
@@ -55,8 +63,12 public: | |||
|
55 | 63 | QStringList categoriesLabels(); |
|
56 | 64 | int count() const; |
|
57 | 65 | |
|
66 | QCategoryAxis::AxisLabelsPosition labelsPosition() const; | |
|
67 | void setLabelsPosition(QCategoryAxis::AxisLabelsPosition position); | |
|
68 | ||
|
58 | 69 | Q_SIGNALS: |
|
59 | 70 | void categoriesChanged(); |
|
71 | void labelsPositionChanged(QCategoryAxis::AxisLabelsPosition position); | |
|
60 | 72 | |
|
61 | 73 | private: |
|
62 | 74 | Q_DECLARE_PRIVATE(QCategoryAxis) |
@@ -50,6 +50,7 private: | |||
|
50 | 50 | QMap<QString , Range> m_categoriesMap; |
|
51 | 51 | QStringList m_categories; |
|
52 | 52 | qreal m_categoryMinimum; |
|
53 | QCategoryAxis::AxisLabelsPosition m_labelsPosition; | |
|
53 | 54 | |
|
54 | 55 | private: |
|
55 | 56 | Q_DECLARE_PUBLIC(QCategoryAxis) |
@@ -19,6 +19,7 | |||
|
19 | 19 | #include <private/horizontalaxis_p.h> |
|
20 | 20 | #include <private/qabstractaxis_p.h> |
|
21 | 21 | #include <private/chartpresenter_p.h> |
|
22 | #include <QtCharts/QCategoryAxis> | |
|
22 | 23 | #include <QtCore/QtMath> |
|
23 | 24 | #include <QtCore/QDebug> |
|
24 | 25 | |
@@ -142,6 +143,7 void HorizontalAxis::updateGeometry() | |||
|
142 | 143 | qreal leftBound = qMax(layout[i], gridRect.left()); |
|
143 | 144 | qreal rightBound = qMin(layout[i + 1], gridRect.right()); |
|
144 | 145 | const qreal delta = rightBound - leftBound; |
|
146 | if (axis()->type() != QAbstractAxis::AxisTypeCategory) { | |
|
145 | 147 | // Hide label in case visible part of the category at the grid edge is too narrow |
|
146 | 148 | if (delta < boundingRect.width() |
|
147 | 149 | && (leftBound == gridRect.left() || rightBound == gridRect.right())) { |
@@ -149,6 +151,21 void HorizontalAxis::updateGeometry() | |||
|
149 | 151 | } else { |
|
150 | 152 | labelItem->setPos(leftBound + (delta / 2.0) - center.x(), labelItem->pos().y()); |
|
151 | 153 | } |
|
154 | } else { | |
|
155 | QCategoryAxis *categoryAxis = static_cast<QCategoryAxis *>(axis()); | |
|
156 | if (categoryAxis->labelsPosition() == QCategoryAxis::AxisLabelsPositionCenter) { | |
|
157 | if (delta < boundingRect.width() | |
|
158 | && (leftBound == gridRect.left() || rightBound == gridRect.right())) { | |
|
159 | forceHide = true; | |
|
160 | } else { | |
|
161 | labelItem->setPos(leftBound + (delta / 2.0) - center.x(), | |
|
162 | labelItem->pos().y()); | |
|
163 | } | |
|
164 | } else if (categoryAxis->labelsPosition() | |
|
165 | == QCategoryAxis::AxisLabelsPositionOnValue) { | |
|
166 | labelItem->setPos(rightBound - center.x(), labelItem->pos().y()); | |
|
167 | } | |
|
168 | } | |
|
152 | 169 | } |
|
153 | 170 | |
|
154 | 171 | //label overlap detection - compensate one pixel for rounding errors |
@@ -19,6 +19,7 | |||
|
19 | 19 | #include <private/verticalaxis_p.h> |
|
20 | 20 | #include <QtCharts/QAbstractAxis> |
|
21 | 21 | #include <private/chartpresenter_p.h> |
|
22 | #include <QtCharts/QCategoryAxis> | |
|
22 | 23 | #include <QtCore/QDebug> |
|
23 | 24 | |
|
24 | 25 | QT_CHARTS_BEGIN_NAMESPACE |
@@ -140,23 +141,43 void VerticalAxis::updateGeometry() | |||
|
140 | 141 | |
|
141 | 142 | //label in between |
|
142 | 143 | bool forceHide = false; |
|
144 | bool labelOnValue = false; | |
|
143 | 145 | if (intervalAxis() && (i + 1) != layout.size()) { |
|
144 | 146 | qreal lowerBound = qMin(layout[i], gridRect.bottom()); |
|
145 | 147 | qreal upperBound = qMax(layout[i + 1], gridRect.top()); |
|
146 | 148 | const qreal delta = lowerBound - upperBound; |
|
149 | if (axis()->type() != QAbstractAxis::AxisTypeCategory) { | |
|
147 | 150 | // Hide label in case visible part of the category at the grid edge is too narrow |
|
148 | 151 | if (delta < boundingRect.height() |
|
149 | 152 | && (lowerBound == gridRect.bottom() || upperBound == gridRect.top())) { |
|
150 | 153 | forceHide = true; |
|
151 | 154 | } else { |
|
152 |
labelItem->setPos(labelItem->pos().x() |
|
|
155 | labelItem->setPos(labelItem->pos().x(), | |
|
156 | lowerBound - (delta / 2.0) - center.y()); | |
|
157 | } | |
|
158 | } else { | |
|
159 | QCategoryAxis *categoryAxis = static_cast<QCategoryAxis *>(axis()); | |
|
160 | if (categoryAxis->labelsPosition() == QCategoryAxis::AxisLabelsPositionCenter) { | |
|
161 | if (delta < boundingRect.height() | |
|
162 | && (lowerBound == gridRect.bottom() || upperBound == gridRect.top())) { | |
|
163 | forceHide = true; | |
|
164 | } else { | |
|
165 | labelItem->setPos(labelItem->pos().x(), | |
|
166 | lowerBound - (delta / 2.0) - center.y()); | |
|
167 | } | |
|
168 | } else if (categoryAxis->labelsPosition() | |
|
169 | == QCategoryAxis::AxisLabelsPositionOnValue) { | |
|
170 | labelOnValue = true; | |
|
171 | labelItem->setPos(labelItem->pos().x(), upperBound - center.y()); | |
|
172 | } | |
|
153 | 173 | } |
|
154 | 174 | } |
|
155 | 175 | |
|
156 | 176 | //label overlap detection - compensate one pixel for rounding errors |
|
157 | 177 | if (labelItem->pos().y() + boundingRect.height() > height || forceHide || |
|
158 |
(labelItem->pos().y() + (heightDiff / 2.0) - 1.0) > axisRect.bottom() |
|
|
159 | labelItem->pos().y() + (heightDiff / 2.0) < (axisRect.top() - 1.0)) { | |
|
178 | ((labelItem->pos().y() + (heightDiff / 2.0) - 1.0) > axisRect.bottom() | |
|
179 | && !labelOnValue) || | |
|
180 | (labelItem->pos().y() + (heightDiff / 2.0) < (axisRect.top() - 1.0) && !labelOnValue)) { | |
|
160 | 181 | labelItem->setVisible(false); |
|
161 | 182 | } |
|
162 | 183 | else { |
@@ -300,7 +300,11 public: | |||
|
300 | 300 | QLatin1String("Trying to create uncreatable: DeclarativeAxes.")); |
|
301 | 301 | qmlRegisterUncreatableType<DeclarativeMargins>(uri, 2, 0, "Margins", |
|
302 | 302 | QLatin1String("Trying to create uncreatable: Margins.")); |
|
303 | ||
|
304 | // QtCharts 2.1 | |
|
305 | qmlRegisterType<DeclarativeCategoryAxis, 1>(uri, 2, 1, "CategoryAxis"); | |
|
303 | 306 | } |
|
307 | ||
|
304 | 308 | }; |
|
305 | 309 | |
|
306 | 310 | QT_CHARTS_END_NAMESPACE |
@@ -93,6 +93,20 void DeclarativeCategoryAxis::appendAxisChildren(QQmlListProperty<QObject> *list | |||
|
93 | 93 | Q_UNUSED(element) |
|
94 | 94 | } |
|
95 | 95 | |
|
96 | DeclarativeCategoryAxis::AxisLabelsPosition DeclarativeCategoryAxis::labelsPosition() const | |
|
97 | { | |
|
98 | return (DeclarativeCategoryAxis::AxisLabelsPosition) QCategoryAxis::labelsPosition(); | |
|
99 | } | |
|
100 | ||
|
101 | void DeclarativeCategoryAxis::setLabelsPosition(AxisLabelsPosition position) | |
|
102 | { | |
|
103 | QCategoryAxis::AxisLabelsPosition labelsPosition = (QCategoryAxis::AxisLabelsPosition) position; | |
|
104 | if (labelsPosition != m_labelsPosition) { | |
|
105 | QCategoryAxis::setLabelsPosition(labelsPosition); | |
|
106 | emit labelsPositionChanged(position); | |
|
107 | } | |
|
108 | } | |
|
109 | ||
|
96 | 110 | #include "moc_declarativecategoryaxis.cpp" |
|
97 | 111 | |
|
98 | 112 | QT_CHARTS_END_NAMESPACE |
@@ -50,15 +50,31 class DeclarativeCategoryAxis : public QCategoryAxis, public QQmlParserStatus | |||
|
50 | 50 | Q_INTERFACES(QQmlParserStatus) |
|
51 | 51 | Q_PROPERTY(QQmlListProperty<QObject> axisChildren READ axisChildren) |
|
52 | 52 | Q_CLASSINFO("DefaultProperty", "axisChildren") |
|
53 | Q_PROPERTY(AxisLabelsPosition labelsPosition READ labelsPosition WRITE setLabelsPosition NOTIFY labelsPositionChanged REVISION 1) | |
|
54 | Q_ENUMS(AxisLabelsPosition) | |
|
53 | 55 | |
|
54 | 56 | public: |
|
57 | // duplicating enums from QChart to make the QML api namings 1-to-1 with the C++ api | |
|
58 | enum AxisLabelsPosition { | |
|
59 | AxisLabelsPositionCenter = 0x0, | |
|
60 | AxisLabelsPositionOnValue = 0x1 | |
|
61 | }; | |
|
62 | ||
|
55 | 63 | explicit DeclarativeCategoryAxis(QObject *parent = 0); |
|
56 | 64 | QQmlListProperty<QObject> axisChildren(); |
|
57 | 65 | |
|
66 | ||
|
58 | 67 | public: // from QDeclarativeParserStatus |
|
59 | 68 | void classBegin(); |
|
60 | 69 | void componentComplete(); |
|
61 | 70 | |
|
71 | public: | |
|
72 | AxisLabelsPosition labelsPosition() const; | |
|
73 | void setLabelsPosition(AxisLabelsPosition position); | |
|
74 | ||
|
75 | Q_SIGNALS: | |
|
76 | Q_REVISION(1) void labelsPositionChanged(AxisLabelsPosition position); | |
|
77 | ||
|
62 | 78 | public Q_SLOTS: |
|
63 | 79 | Q_INVOKABLE void append(const QString &label, qreal categoryEndValue); |
|
64 | 80 | Q_INVOKABLE void remove(const QString &label); |
@@ -67,6 +83,9 public Q_SLOTS: | |||
|
67 | 83 | |
|
68 | 84 | private: |
|
69 | 85 | static bool endValueLessThan(const QPair<QString, qreal> &value1, const QPair<QString, qreal> &value2); |
|
86 | ||
|
87 | private: | |
|
88 | AxisLabelsPosition m_labelsPosition; | |
|
70 | 89 | }; |
|
71 | 90 | |
|
72 | 91 | QT_CHARTS_END_NAMESPACE |
@@ -430,9 +430,26 Module { | |||
|
430 | 430 | name: "QtCharts::DeclarativeCategoryAxis" |
|
431 | 431 | defaultProperty: "axisChildren" |
|
432 | 432 | prototype: "QtCharts::QCategoryAxis" |
|
433 | exports: ["QtCharts/CategoryAxis 1.1", "QtCharts/CategoryAxis 2.0"] | |
|
434 | exportMetaObjectRevisions: [0, 0] | |
|
433 | exports: [ | |
|
434 | "QtCharts/CategoryAxis 1.1", | |
|
435 | "QtCharts/CategoryAxis 2.0", | |
|
436 | "QtCharts/CategoryAxis 2.1" | |
|
437 | ] | |
|
438 | exportMetaObjectRevisions: [0, 0, 1] | |
|
439 | Enum { | |
|
440 | name: "AxisLabelsPosition" | |
|
441 | values: { | |
|
442 | "AxisLabelsPositionCenter": 0, | |
|
443 | "AxisLabelsPositionOnValue": 1 | |
|
444 | } | |
|
445 | } | |
|
435 | 446 | Property { name: "axisChildren"; type: "QObject"; isList: true; isReadonly: true } |
|
447 | Property { name: "labelsPosition"; revision: 1; type: "AxisLabelsPosition" } | |
|
448 | Signal { | |
|
449 | name: "labelsPositionChanged" | |
|
450 | revision: 1 | |
|
451 | Parameter { name: "position"; type: "AxisLabelsPosition" } | |
|
452 | } | |
|
436 | 453 | Method { |
|
437 | 454 | name: "append" |
|
438 | 455 | Parameter { name: "label"; type: "string" } |
@@ -1911,10 +1928,22 Module { | |||
|
1911 | 1928 | Component { |
|
1912 | 1929 | name: "QtCharts::QCategoryAxis" |
|
1913 | 1930 | prototype: "QtCharts::QValueAxis" |
|
1931 | Enum { | |
|
1932 | name: "AxisLabelsPosition" | |
|
1933 | values: { | |
|
1934 | "AxisLabelsPositionCenter": 0, | |
|
1935 | "AxisLabelsPositionOnValue": 1 | |
|
1936 | } | |
|
1937 | } | |
|
1914 | 1938 | Property { name: "startValue"; type: "double" } |
|
1915 | 1939 | Property { name: "count"; type: "int"; isReadonly: true } |
|
1916 | 1940 | Property { name: "categoriesLabels"; type: "QStringList"; isReadonly: true } |
|
1941 | Property { name: "labelsPosition"; type: "AxisLabelsPosition" } | |
|
1917 | 1942 | Signal { name: "categoriesChanged" } |
|
1943 | Signal { | |
|
1944 | name: "labelsPositionChanged" | |
|
1945 | Parameter { name: "position"; type: "QCategoryAxis::AxisLabelsPosition" } | |
|
1946 | } | |
|
1918 | 1947 | } |
|
1919 | 1948 | Component { |
|
1920 | 1949 | name: "QtCharts::QDateTimeAxis" |
@@ -52,6 +52,7 private slots: | |||
|
52 | 52 | void range(); |
|
53 | 53 | void range_animation_data(); |
|
54 | 54 | void range_animation(); |
|
55 | void labels_position(); | |
|
55 | 56 | |
|
56 | 57 | void interval_data(); |
|
57 | 58 | void interval(); |
@@ -63,6 +64,7 private: | |||
|
63 | 64 | |
|
64 | 65 | void tst_QCategoryAxis::initTestCase() |
|
65 | 66 | { |
|
67 | qRegisterMetaType<QCategoryAxis::AxisLabelsPosition>("QCategoryAxis::AxisLabelsPosition"); | |
|
66 | 68 | } |
|
67 | 69 | |
|
68 | 70 | void tst_QCategoryAxis::cleanupTestCase() |
@@ -100,6 +102,7 void tst_QCategoryAxis::qcategoryaxis() | |||
|
100 | 102 | QVERIFY(qFuzzyCompare(m_categoryaxis->max(), 0)); |
|
101 | 103 | QVERIFY(qFuzzyCompare(m_categoryaxis->min(), 0)); |
|
102 | 104 | QCOMPARE(m_categoryaxis->type(), QAbstractAxis::AxisTypeCategory); |
|
105 | QCOMPARE(m_categoryaxis->labelsPosition(), QCategoryAxis::AxisLabelsPositionCenter); | |
|
103 | 106 | |
|
104 | 107 | m_chart->setAxisX(m_categoryaxis, m_series); |
|
105 | 108 | m_view->show(); |
@@ -301,6 +304,15 void tst_QCategoryAxis::interval() | |||
|
301 | 304 | QCOMPARE(m_categoryaxis->endValue("replaced"), (qreal)75); |
|
302 | 305 | } |
|
303 | 306 | |
|
307 | void tst_QCategoryAxis::labels_position() | |
|
308 | { | |
|
309 | QSignalSpy spy(m_categoryaxis, | |
|
310 | SIGNAL(labelsPositionChanged(QCategoryAxis::AxisLabelsPosition))); | |
|
311 | m_categoryaxis->setLabelsPosition(QCategoryAxis::AxisLabelsPositionOnValue); | |
|
312 | QCOMPARE(m_categoryaxis->labelsPosition(), QCategoryAxis::AxisLabelsPositionOnValue); | |
|
313 | QCOMPARE(spy.count(), 1); | |
|
314 | } | |
|
315 | ||
|
304 | 316 | QTEST_MAIN(tst_QCategoryAxis) |
|
305 | 317 | #include "tst_qcategoryaxis.moc" |
|
306 | 318 |
@@ -18,7 +18,7 | |||
|
18 | 18 | |
|
19 | 19 | import QtQuick 2.0 |
|
20 | 20 | import QtTest 1.0 |
|
21 |
import QtCharts 2. |
|
|
21 | import QtCharts 2.1 | |
|
22 | 22 | |
|
23 | 23 | Rectangle { |
|
24 | 24 | width: 400 |
@@ -43,6 +43,16 Rectangle { | |||
|
43 | 43 | compare(lineSeries1.axisY.categoriesLabels[1], "label1", "AxisY categories labels"); |
|
44 | 44 | compare(lineSeries1.axisY.categoriesLabels[2], "label2", "AxisY categories labels"); |
|
45 | 45 | } |
|
46 | ||
|
47 | function test_properties() { | |
|
48 | compare(lineSeries1.axisY.labelsPosition, CategoryAxis.AxisLabelsPositionCenter); | |
|
49 | } | |
|
50 | ||
|
51 | function test_signals() { | |
|
52 | axisLabelsPositionSpy.clear(); | |
|
53 | lineSeries1.axisY.labelsPosition = CategoryAxis.AxisLabelsPositionOnValue; | |
|
54 | compare(axisLabelsPositionSpy.count, 1, "onLabelsPositionChanged") | |
|
55 | } | |
|
46 | 56 | } |
|
47 | 57 | |
|
48 | 58 | ChartView { |
@@ -73,6 +83,11 Rectangle { | |||
|
73 | 83 | label: "label2" |
|
74 | 84 | endValue: 10 |
|
75 | 85 | } |
|
86 | SignalSpy { | |
|
87 | id: axisLabelsPositionSpy | |
|
88 | target: axisY | |
|
89 | signalName: "labelsPositionChanged" | |
|
90 | } | |
|
76 | 91 | } |
|
77 | 92 | XYPoint { x: -1; y: -1 } |
|
78 | 93 | XYPoint { x: 0; y: 0 } |
@@ -38,6 +38,7 private: | |||
|
38 | 38 | QString imports_1_3(); |
|
39 | 39 | QString imports_1_4(); |
|
40 | 40 | QString imports_2_0(); |
|
41 | QString imports_2_1(); | |
|
41 | 42 | |
|
42 | 43 | }; |
|
43 | 44 | |
@@ -78,6 +79,12 QString tst_qml::imports_2_0() | |||
|
78 | 79 | "import QtCharts 2.0 \n"; |
|
79 | 80 | } |
|
80 | 81 | |
|
82 | QString tst_qml::imports_2_1() | |
|
83 | { | |
|
84 | return "import QtQuick 2.1 \n" | |
|
85 | "import QtCharts 2.1 \n"; | |
|
86 | } | |
|
87 | ||
|
81 | 88 | void tst_qml::initTestCase() |
|
82 | 89 | { |
|
83 | 90 | } |
@@ -168,6 +175,8 void tst_qml::checkPlugin_data() | |||
|
168 | 175 | QTest::newRow("LogValueAxis_2_0") << imports_2_0() + "LogValueAxis{}"; |
|
169 | 176 | QTest::newRow("BoxPlotSeries_2_0") << imports_2_0() + "BoxPlotSeries{}"; |
|
170 | 177 | QTest::newRow("BoxSet_2_0") << imports_2_0() + "BoxSet{}"; |
|
178 | ||
|
179 | QTest::newRow("CategoryAxis") << imports_2_1() + "CategoryAxis{}"; | |
|
171 | 180 | } |
|
172 | 181 | |
|
173 | 182 | void tst_qml::checkPlugin() |
General Comments 0
You need to be logged in to leave comments.
Login now