@@ -1,75 +1,75 | |||
|
1 | integrated_build:{ | |
|
1 | local_build:{ | |
|
2 | 2 | INCLUDEPATH += $$CHART_BUILD_PUBLIC_HEADER_DIR |
|
3 | 3 | |
|
4 | 4 | !win32: { |
|
5 | 5 | LIBS += -L $$CHART_BUILD_LIB_DIR -Wl,-rpath,$$CHART_BUILD_LIB_DIR |
|
6 | 6 | }else{ |
|
7 | 7 | win32-msvc*: { |
|
8 | 8 | # hack fix for error: |
|
9 | 9 | # "LINK : fatal error LNK1146: no argument specified with option '/LIBPATH:'" |
|
10 | 10 | QMAKE_LIBDIR += $$CHART_BUILD_LIB_DIR |
|
11 | 11 | }else{ |
|
12 | 12 | LIBS += -L $$CHART_BUILD_LIB_DIR |
|
13 | 13 | } |
|
14 | 14 | } |
|
15 | 15 | |
|
16 | 16 | CONFIG(debug, debug|release) { |
|
17 | 17 | LIBS += -lQtCommercialChartd |
|
18 | 18 | #this is ugly hack to work around missing rpath, it simply copies lib |
|
19 | 19 | win32:{ |
|
20 | 20 | copylib.target = $$CHART_BUILD_BIN_DIR/QtCommercialChartd.dll |
|
21 | 21 | copylib.commands = $$QMAKE_COPY $$CHART_BUILD_LIB_DIR\\QtCommercialChartd.dll $$CHART_BUILD_BIN_DIR |
|
22 | 22 | copylib.depends = $$CHART_BUILD_LIB_DIR/QtCommercialChartd.dll |
|
23 | 23 | PRE_TARGETDEPS += $$CHART_BUILD_BIN_DIR/QtCommercialChartd.dll |
|
24 | 24 | QMAKE_EXTRA_TARGETS +=copylib |
|
25 | 25 | } |
|
26 | 26 | } else { |
|
27 | 27 | LIBS += -lQtCommercialChart |
|
28 | 28 | |
|
29 | 29 | #this is ugly hack to work around missing rpath, it simply copies lib |
|
30 | 30 | win32: { |
|
31 | 31 | copylib.target = $$CHART_BUILD_BIN_DIR/QtCommercialChart |
|
32 | 32 | copylib.commands = $$QMAKE_COPY $$CHART_BUILD_LIB_DIR\\QtCommercialChart.dll $$CHART_BUILD_BIN_DIR |
|
33 | 33 | copylib.depends = $$CHART_BUILD_LIB_DIR/QtCommercialChart.dll |
|
34 | 34 | PRE_TARGETDEPS += $$CHART_BUILD_BIN_DIR/QtCommercialChart |
|
35 | 35 | QMAKE_EXTRA_TARGETS +=copylib |
|
36 | 36 | } |
|
37 | 37 | } |
|
38 | 38 | |
|
39 | 39 | mac: { |
|
40 | 40 | # This is a hack to make binaries to use the internal version of the QtCommercial Charts library on OSX |
|
41 | 41 | CHARTS_LIB_NAME = libQtCommercialChart.1.dylib |
|
42 | 42 | CONFIG(debug, debug|release) { |
|
43 | 43 | CHARTS_LIB_NAME = libQtCommercialChartd.1.dylib |
|
44 | 44 | } |
|
45 | 45 | BIN_TARGET_PATH = "" |
|
46 | 46 | exists ($$CHART_BUILD_BIN_DIR"/"$$TARGET".app/Contents/MacOS/"$$TARGET) { |
|
47 | 47 | BIN_TARGET_PATH = $$CHART_BUILD_BIN_DIR"/"$$TARGET".app/Contents/MacOS/"$$TARGET |
|
48 | 48 | } |
|
49 | 49 | exists ($$CHART_BUILD_BIN_DIR"/test/"$$TARGET".app/Contents/MacOS/"$$TARGET) { |
|
50 | 50 | # Executable in test folder |
|
51 | 51 | BIN_TARGET_PATH = $$CHART_BUILD_BIN_DIR"/test/"$$TARGET".app/Contents/MacOS/"$$TARGET |
|
52 | 52 | } |
|
53 | 53 | exists ($$CHART_BUILD_BIN_DIR"/test/tst_"$$TARGET".app/Contents/MacOS/tst_"$$TARGET) { |
|
54 | 54 | # Executable in test folder with custom target "tst_NNN" |
|
55 | 55 | BIN_TARGET_PATH = $$CHART_BUILD_BIN_DIR"/test/tst_"$$TARGET".app/Contents/MacOS/tst_"$$TARGET |
|
56 | 56 | } |
|
57 | 57 | exists($$CHART_BUILD_PLUGIN_DIR"/lib"$$TARGET".dylib") { |
|
58 | 58 | # Plugin |
|
59 | 59 | BIN_TARGET_PATH = $$CHART_BUILD_PLUGIN_DIR"/lib"$$TARGET".dylib" |
|
60 | 60 | } |
|
61 | 61 | !isEmpty (BIN_TARGET_PATH) { |
|
62 | 62 | QMAKE_POST_LINK += install_name_tool -change $$CHARTS_LIB_NAME $$CHART_BUILD_LIB_DIR"/"$$CHARTS_LIB_NAME $$BIN_TARGET_PATH |
|
63 | 63 | # message($$QMAKE_POST_LINK) |
|
64 | 64 | } |
|
65 | 65 | |
|
66 | 66 | # Hack to make qml plugins available as internal build versions |
|
67 | 67 | exists($$CHART_BUILD_PLUGIN_DIR"/lib"$$TARGET".dylib") { |
|
68 | 68 | QMAKE_POST_LINK += " & $$QMAKE_COPY qmldir $$CHART_BUILD_PLUGIN_DIR" |
|
69 | 69 | message($$QMAKE_POST_LINK) |
|
70 | 70 | } |
|
71 | 71 | } |
|
72 | 72 | |
|
73 | 73 | } else { |
|
74 | 74 | CONFIG += qtcommercialchart |
|
75 | 75 | } |
@@ -1,33 +1,38 | |||
|
1 |
!include(co |
|
|
2 |
error(' |
|
|
1 | !include(config.pri) { | |
|
2 | error('Missing config.pri') | |
|
3 | 3 | } |
|
4 | 4 | |
|
5 | 5 | TEMPLATE = subdirs |
|
6 |
SUBDIRS |
|
|
6 | SUBDIRS = src qmlplugin examples demos test | |
|
7 | 7 | |
|
8 | integrated_build:{ | |
|
9 |
message('Configured for |
|
|
8 | local_build:{ | |
|
9 | message('Configured for local build against local libs...') | |
|
10 | message('You can run "make" to build qchart library, examples and demos...') | |
|
10 | 11 | } else { |
|
11 | 12 | message('Running build aginst system libs...') |
|
12 | message('Please build example test and qmlplugin after installing library.') | |
|
13 | message('Bulding only charts library...') | |
|
14 | message('You can run "make install" to build and install charts.') | |
|
15 | message('Afterwards you can run "cd examples; qmake ; make " to build examples.') | |
|
16 | message('Run qmake CONFIG+=local_build' to build everything at once.) | |
|
17 | SUBDIRS = src | |
|
13 | 18 | } |
|
14 | 19 | |
|
15 | 20 | CONFIG += ordered |
|
16 | 21 | QMAKE_CXXFLAGS += -g -Wall |
|
17 | 22 | unix:QMAKE_DISTCLEAN += -r build bin include lib doc/html |
|
18 | 23 | win32:QMAKE_DISTCLEAN += /Q /s build bin include lib doc\\html |
|
19 | 24 | |
|
20 | 25 | # install feature file |
|
21 | 26 | feature.path = $$[QT_INSTALL_DATA]/mkspecs/features |
|
22 | 27 | feature.files = $$PWD/features/qtcommercialchart.prf |
|
23 | 28 | INSTALLS += feature |
|
24 | 29 | |
|
25 | 30 | docs.target = docs |
|
26 | 31 | win32:{ |
|
27 | 32 | docs.commands = qdoc3 $$CHART_BUILD_DOC_DIR\\qcharts.qdocconf |
|
28 | 33 | }else{ |
|
29 | 34 | docs.commands = qdoc3 $$CHART_BUILD_DOC_DIR/qcharts.qdocconf |
|
30 | 35 | } |
|
31 | 36 | docs.depends = FORCE |
|
32 | 37 | QMAKE_EXTRA_TARGETS += docs |
|
33 | 38 |
@@ -1,44 +1,47 | |||
|
1 | CONFIG+=integrated_build #remove if you want to build against installed libs | |
|
2 | 1 | |
|
2 | #check if shadow build | |
|
3 | 3 | !contains($${PWD}, $${OUT_PWD}){ |
|
4 | search = "$$PWD:::" | |
|
4 | search = "$$PWD:::" | |
|
5 | 5 | temp = $$split(search,"/") |
|
6 | 6 | temp = $$last(temp) |
|
7 | 7 | path = $$replace(search,$$temp,'') |
|
8 | 8 | temp = $$split(OUT_PWD,$$path) |
|
9 | 9 | temp = $$split(temp,'/') |
|
10 | 10 | temp = $$first(temp) |
|
11 | 11 | path = "$${path}$${temp}" |
|
12 |
SHADOW=$$path |
|
|
12 | SHADOW=$$path | |
|
13 | CONFIG-=developer_build | |
|
13 | 14 | }else{ |
|
14 | 15 | SHADOW=$$PWD |
|
15 | 16 | } |
|
16 | 17 | |
|
17 | 18 | CHART_BUILD_PUBLIC_HEADER_DIR = $$SHADOW/include |
|
18 | 19 | CHART_BUILD_PRIVATE_HEADER_DIR = $$CHART_BUILD_PUBLIC_HEADER_DIR/private |
|
19 | 20 | CHART_BUILD_LIB_DIR = $$SHADOW/lib |
|
20 | 21 | CHART_BUILD_DIR = $$SHADOW/build |
|
21 | 22 | CHART_BUILD_BIN_DIR = $$SHADOW/bin |
|
22 | 23 | CHART_BUILD_PLUGIN_DIR = $$CHART_BUILD_LIB_DIR/QtCommercial/Chart |
|
23 | 24 | CHART_BUILD_DOC_DIR = $$SHADOW/doc |
|
24 | 25 | |
|
25 | 26 | |
|
26 | 27 | # hack to fix windows builds |
|
27 | 28 | win32:{ |
|
28 | 29 | CHART_BUILD_PUBLIC_HEADER_DIR = $$replace(CHART_BUILD_PUBLIC_HEADER_DIR, "/","\\") |
|
29 | 30 | CHART_BUILD_PRIVATE_HEADER_DIR = $$replace(CHART_BUILD_PRIVATE_HEADER_DIR, "/","\\") |
|
30 | 31 | CHART_BUILD_LIB_DIR = $$replace(CHART_BUILD_LIB_DIR, "/","\\") |
|
31 | 32 | CHART_BUILD_BUILD_DIR = $$replace(CHART_BUILD_BUILD_DIR, "/","\\") |
|
32 | 33 | CHART_BUILD_BIN_DIR = $$replace(CHART_BUILD_BIN_DIR, "/","\\") |
|
33 | 34 | CHART_BUILD_PLUGIN_DIR = $$replace(CHART_BUILD_PLUGIN_DIR, "/","\\") |
|
34 | 35 | CHART_BUILD_DOC_DIR = $$replace(CHART_BUILD_DOC_DIR, "/","\\") |
|
35 | 36 | } |
|
36 | 37 | |
|
37 | 38 | mac: { |
|
38 | 39 | # TODO: The following qmake flags are a work-around to make QtCommercial Charts compile on |
|
39 | 40 | # QtCommercial 4.8. On the other hand Charts builds successfully with Qt open source 4.8 |
|
40 | 41 | # without these definitions, so this is probably a configuration issue on QtCommercial 4.8; |
|
41 | 42 | # it should probably define the minimum OSX version to be 10.5... |
|
42 | 43 | QMAKE_CXXFLAGS *= -mmacosx-version-min=10.5 |
|
43 | 44 | QMAKE_LFLAGS *= -mmacosx-version-min=10.5 |
|
44 | 45 | } |
|
46 | ||
|
47 | developer_build: DEFINES+=DEVELOPER_BUILD No newline at end of file |
@@ -1,16 +1,16 | |||
|
1 |
!include( ../co |
|
|
2 |
error( "Couldn't find the co |
|
|
1 | !include( ../config.pri ) { | |
|
2 | error( "Couldn't find the config.pri file!" ) | |
|
3 | 3 | } |
|
4 | 4 | |
|
5 |
!include( ../ |
|
|
6 |
error( "Couldn't find the |
|
|
5 | !include( ../build.pri ) { | |
|
6 | error( "Couldn't find the build.pri file !") | |
|
7 | 7 | } |
|
8 | 8 | |
|
9 | 9 | DESTDIR = $$CHART_BUILD_BIN_DIR |
|
10 | 10 | OBJECTS_DIR = $$CHART_BUILD_DIR/bin/$$TARGET |
|
11 | 11 | MOC_DIR = $$CHART_BUILD_DIR/bin/$$TARGET |
|
12 | 12 | UI_DIR = $$CHART_BUILD_DIR/bin/$$TARGET |
|
13 | 13 | RCC_DIR = $$CHART_BUILD_DIR/bin/$$TARGET |
|
14 | 14 | |
|
15 | 15 | TEMPLATE = app |
|
16 | 16 | QT += core gui No newline at end of file |
@@ -1,16 +1,16 | |||
|
1 |
!include( ../co |
|
|
2 |
error( "Couldn't find the co |
|
|
1 | !include( ../config.pri ) { | |
|
2 | error( "Couldn't find the config.pri file!" ) | |
|
3 | 3 | } |
|
4 | 4 | |
|
5 |
!include( ../ |
|
|
6 |
error( "Couldn't find the |
|
|
5 | !include( ../build.pri ) { | |
|
6 | error( "Couldn't find the build.pri file !") | |
|
7 | 7 | } |
|
8 | 8 | |
|
9 | 9 | DESTDIR = $$CHART_BUILD_BIN_DIR |
|
10 | 10 | OBJECTS_DIR = $$CHART_BUILD_DIR/bin/$$TARGET |
|
11 | 11 | MOC_DIR = $$CHART_BUILD_DIR/bin/$$TARGET |
|
12 | 12 | UI_DIR = $$CHART_BUILD_DIR/bin/$$TARGET |
|
13 | 13 | RCC_DIR = $$CHART_BUILD_DIR/bin/$$TARGET |
|
14 | 14 | |
|
15 | 15 | TEMPLATE = app |
|
16 | 16 | QT += core gui No newline at end of file |
@@ -1,42 +1,43 | |||
|
1 | 1 | /**************************************************************************** |
|
2 | 2 | ** |
|
3 | 3 | ** Copyright (C) 2012 Digia Plc |
|
4 | 4 | ** All rights reserved. |
|
5 | 5 | ** For any questions to Digia, please use contact form at http://qt.digia.com |
|
6 | 6 | ** |
|
7 | 7 | ** This file is part of the Qt Commercial Charts Add-on. |
|
8 | 8 | ** |
|
9 | 9 | ** $QT_BEGIN_LICENSE$ |
|
10 | 10 | ** Licensees holding valid Qt Commercial licenses may use this file in |
|
11 | 11 | ** accordance with the Qt Commercial License Agreement provided with the |
|
12 | 12 | ** Software or, alternatively, in accordance with the terms contained in |
|
13 | 13 | ** a written agreement between you and Digia. |
|
14 | 14 | ** |
|
15 | 15 | ** If you have questions regarding the use of this file, please use |
|
16 | 16 | ** contact form at http://qt.digia.com |
|
17 | 17 | ** $QT_END_LICENSE$ |
|
18 | 18 | ** |
|
19 | 19 | ****************************************************************************/ |
|
20 | 20 | |
|
21 | 21 | #ifndef DECLARATIVE_XY_POINT_H |
|
22 | 22 | #define DECLARATIVE_XY_POINT_H |
|
23 | 23 | |
|
24 | 24 | #include "qchartglobal.h" |
|
25 | 25 | #include <QObject> |
|
26 | 26 | #include <QPointF> |
|
27 | #include <QTextStream> | |
|
27 | 28 | |
|
28 | 29 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
29 | 30 | |
|
30 | 31 | class DeclarativeXyPoint : public QObject, public QPointF |
|
31 | 32 | { |
|
32 | 33 | Q_OBJECT |
|
33 | 34 | Q_PROPERTY(qreal x READ x WRITE setX /*NOTIFY dataXChanged*/) |
|
34 | 35 | Q_PROPERTY(qreal y READ y WRITE setY /*NOTIFY dataYChanged*/) |
|
35 | 36 | |
|
36 | 37 | public: |
|
37 | 38 | explicit DeclarativeXyPoint(QObject *parent = 0); |
|
38 | 39 | }; |
|
39 | 40 | |
|
40 | 41 | QTCOMMERCIALCHART_END_NAMESPACE |
|
41 | 42 | |
|
42 | 43 | #endif // DECLARATIVE_XY_POINT_H |
@@ -1,51 +1,51 | |||
|
1 | 1 | TEMPLATE = lib |
|
2 | 2 | TARGET = qtcommercialchartqml |
|
3 | 3 | CONFIG += qt plugin |
|
4 | 4 | QT += declarative |
|
5 | 5 | |
|
6 |
!include( ../co |
|
|
6 | !include( ../config.pri ) { | |
|
7 | 7 | error( "Couldn't find the common.pri file!" ) |
|
8 | 8 | } |
|
9 |
!include( ../ |
|
|
10 |
error( "Couldn't find the |
|
|
9 | !include( ../build.pri ) { | |
|
10 | error( "Couldn't find the build.pri file !") | |
|
11 | 11 | } |
|
12 | 12 | |
|
13 | 13 | DESTDIR = $$CHART_BUILD_PLUGIN_DIR |
|
14 | 14 | contains(QT_MAJOR_VERSION, 5) { |
|
15 | 15 | # TODO: QtQuick2 not supported by the implementation currently |
|
16 | 16 | DEFINES += QTQUICK2 |
|
17 | 17 | } |
|
18 | 18 | |
|
19 | 19 | OBJECTS_DIR = $$CHART_BUILD_DIR/plugin |
|
20 | 20 | MOC_DIR = $$CHART_BUILD_DIR/plugin |
|
21 | 21 | UI_DIR = $$CHART_BUILD_DIR/plugin |
|
22 | 22 | RCC_DIR = $$CHART_BUILD_DIR/plugin |
|
23 | 23 | |
|
24 | 24 | SOURCES += \ |
|
25 | 25 | plugin.cpp \ |
|
26 | 26 | declarativechart.cpp \ |
|
27 | 27 | declarativexyseries.cpp \ |
|
28 | 28 | declarativexypoint.cpp \ |
|
29 | 29 | declarativelineseries.cpp \ |
|
30 | 30 | declarativesplineseries.cpp \ |
|
31 | 31 | declarativeareaseries.cpp \ |
|
32 | 32 | declarativescatterseries.cpp \ |
|
33 | 33 | declarativepieseries.cpp \ |
|
34 | 34 | declarativebarseries.cpp |
|
35 | 35 | HEADERS += \ |
|
36 | 36 | declarativechart.h \ |
|
37 | 37 | declarativexyseries.h \ |
|
38 | 38 | declarativexypoint.h \ |
|
39 | 39 | declarativelineseries.h \ |
|
40 | 40 | declarativesplineseries.h \ |
|
41 | 41 | declarativeareaseries.h \ |
|
42 | 42 | declarativescatterseries.h \ |
|
43 | 43 | declarativepieseries.h \ |
|
44 | 44 | declarativebarseries.h |
|
45 | 45 | |
|
46 | 46 | TARGETPATH = QtCommercial/Chart |
|
47 | 47 | target.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH |
|
48 | 48 | qmldir.files += $$PWD/qmldir |
|
49 | 49 | qmldir.path += $$[QT_INSTALL_IMPORTS]/$$TARGETPATH |
|
50 | 50 | |
|
51 | 51 | INSTALLS += target qmldir |
@@ -1,149 +1,150 | |||
|
1 | 1 | /**************************************************************************** |
|
2 | 2 | ** |
|
3 | 3 | ** Copyright (C) 2012 Digia Plc |
|
4 | 4 | ** All rights reserved. |
|
5 | 5 | ** For any questions to Digia, please use contact form at http://qt.digia.com |
|
6 | 6 | ** |
|
7 | 7 | ** This file is part of the Qt Commercial Charts Add-on. |
|
8 | 8 | ** |
|
9 | 9 | ** $QT_BEGIN_LICENSE$ |
|
10 | 10 | ** Licensees holding valid Qt Commercial licenses may use this file in |
|
11 | 11 | ** accordance with the Qt Commercial License Agreement provided with the |
|
12 | 12 | ** Software or, alternatively, in accordance with the terms contained in |
|
13 | 13 | ** a written agreement between you and Digia. |
|
14 | 14 | ** |
|
15 | 15 | ** If you have questions regarding the use of this file, please use |
|
16 | 16 | ** contact form at http://qt.digia.com |
|
17 | 17 | ** $QT_END_LICENSE$ |
|
18 | 18 | ** |
|
19 | 19 | ****************************************************************************/ |
|
20 | 20 | |
|
21 | 21 | #include "splineanimation_p.h" |
|
22 | 22 | #include "splinechartitem_p.h" |
|
23 | #include <QDebug> | |
|
23 | 24 | |
|
24 | 25 | Q_DECLARE_METATYPE(QVector<QPointF>) |
|
25 | 26 | Q_DECLARE_METATYPE(SplineVector) |
|
26 | 27 | |
|
27 | 28 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
28 | 29 | |
|
29 | 30 | SplineAnimation::SplineAnimation(SplineChartItem* item):ChartAnimation(item), |
|
30 | 31 | m_item(item), |
|
31 | 32 | m_dirty(true) |
|
32 | 33 | { |
|
33 | 34 | } |
|
34 | 35 | |
|
35 | 36 | SplineAnimation::~SplineAnimation() |
|
36 | 37 | { |
|
37 | 38 | } |
|
38 | 39 | |
|
39 | 40 | void SplineAnimation::setValues(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, QVector<QPointF> &oldControlPoints, QVector<QPointF> &newControlPoints, int index) |
|
40 | 41 | { |
|
41 | 42 | int x = oldPoints.count(); |
|
42 | 43 | int y = newPoints.count(); |
|
43 | 44 | |
|
44 | 45 | Q_ASSERT(newPoints.count() * 2 - 2 == newControlPoints.count()); |
|
45 | 46 | |
|
46 | 47 | if (x != y && abs(x - y) != 1) { |
|
47 | 48 | m_oldSpline.first = newPoints; |
|
48 | 49 | m_oldSpline.second = newControlPoints; |
|
49 | 50 | oldPoints.resize(newPoints.size()); |
|
50 | 51 | oldControlPoints.resize(newControlPoints.size()); |
|
51 | 52 | SplineVector oldPair; |
|
52 | 53 | oldPair.first = oldPoints; |
|
53 | 54 | oldPair.second = oldControlPoints; |
|
54 | 55 | SplineVector newPair; |
|
55 | 56 | newPair.first = newPoints; |
|
56 | 57 | newPair.second = newControlPoints; |
|
57 | 58 | setKeyValueAt(0.0, qVariantFromValue(oldPair)); |
|
58 | 59 | setKeyValueAt(1.0, qVariantFromValue(newPair)); |
|
59 | 60 | m_dirty = false; |
|
60 | 61 | } |
|
61 | 62 | else { |
|
62 | 63 | if(m_dirty) { |
|
63 | 64 | m_oldSpline.first = oldPoints; |
|
64 | 65 | m_oldSpline.second = oldControlPoints; |
|
65 | 66 | m_dirty = false; |
|
66 | 67 | } |
|
67 | 68 | oldPoints = newPoints; |
|
68 | 69 | oldControlPoints = newControlPoints; |
|
69 | 70 | if (y < x) { |
|
70 | 71 | m_oldSpline.first.remove(index); //remove |
|
71 | 72 | m_oldSpline.second.remove(index * 2); |
|
72 | 73 | m_oldSpline.second.remove(index * 2); |
|
73 | 74 | } |
|
74 | 75 | if (y > x) { |
|
75 | 76 | m_oldSpline.first.insert(index, x > 0 ? m_oldSpline.first[index-1] : newPoints[index]); //add |
|
76 | 77 | m_oldSpline.second.insert((index - 1) * 2, x > 1 ? m_oldSpline.second[(index-2)*2] : newControlPoints[(index - 1) * 2]); //add |
|
77 | 78 | m_oldSpline.second.insert((index - 1) * 2 + 1, x > 1 ? m_oldSpline.second[(index - 2) * 2 + 1] : newControlPoints[(index - 1) * 2 + 1]); //add |
|
78 | 79 | } |
|
79 | 80 | SplineVector newPair; |
|
80 | 81 | newPair.first=newPoints; |
|
81 | 82 | newPair.second=newControlPoints; |
|
82 | 83 | setKeyValueAt(0.0, qVariantFromValue(m_oldSpline)); |
|
83 | 84 | setKeyValueAt(1.0, qVariantFromValue(newPair)); |
|
84 | 85 | |
|
85 | 86 | } |
|
86 | 87 | } |
|
87 | 88 | |
|
88 | 89 | QVariant SplineAnimation::interpolated(const QVariant &start, const QVariant &end, qreal progress ) const |
|
89 | 90 | { |
|
90 | 91 | |
|
91 | 92 | SplineVector startPair = qVariantValue< SplineVector >(start); |
|
92 | 93 | SplineVector endPair = qVariantValue< SplineVector >(end); |
|
93 | 94 | SplineVector result; |
|
94 | 95 | |
|
95 | 96 | |
|
96 | 97 | switch (m_type) { |
|
97 | 98 | |
|
98 | 99 | case MoveDownAnimation: { |
|
99 | 100 | if (startPair.first.count() != endPair.first.count()) |
|
100 | 101 | break; |
|
101 | 102 | Q_ASSERT(startPair.first.count() * 2 - 2 == startPair.second.count()); |
|
102 | 103 | Q_ASSERT(endPair.first.count() * 2 - 2 == endPair.second.count()); |
|
103 | 104 | for(int i = 0; i < endPair.first.count(); i++) { |
|
104 | 105 | qreal x = startPair.first[i].x() + ((endPair.first[i].x() - startPair.first[i].x()) * progress); |
|
105 | 106 | qreal y = startPair.first[i].y() + ((endPair.first[i].y() - startPair.first[i].y()) * progress); |
|
106 | 107 | result.first << QPointF(x,y); |
|
107 | 108 | if (i + 1 >= endPair.first.count()) |
|
108 | 109 | continue; |
|
109 | 110 | x = startPair.second[i * 2].x() + ((endPair.second[i * 2].x() - startPair.second[i * 2].x()) * progress); |
|
110 | 111 | y = startPair.second[i * 2].y() + ((endPair.second[i * 2].y() - startPair.second[i * 2].y()) * progress); |
|
111 | 112 | result.second << QPoint(x,y); |
|
112 | 113 | x = startPair.second[i * 2 + 1].x() + ((endPair.second[i * 2 + 1].x() - startPair.second[i * 2 + 1].x()) * progress); |
|
113 | 114 | y = startPair.second[i * 2 + 1].y() + ((endPair.second[i * 2 + 1].y() - startPair.second[i * 2 + 1].y()) * progress); |
|
114 | 115 | result.second << QPoint(x,y); |
|
115 | 116 | } |
|
116 | 117 | |
|
117 | 118 | } |
|
118 | 119 | break; |
|
119 | 120 | case LineDrawAnimation:{ |
|
120 | 121 | Q_ASSERT(endPair.first.count() * 2 - 2 == endPair.second.count()); |
|
121 | 122 | int count = endPair.first.count()* qBound(qreal(0), progress, qreal(1)); |
|
122 | 123 | for(int i = 0; i < count; i++) { |
|
123 | 124 | result.first << endPair.first[i]; |
|
124 | 125 | if(i + 1 == count) |
|
125 | 126 | break; |
|
126 | 127 | result.second << endPair.second[2 * i]; |
|
127 | 128 | result.second << endPair.second[2 * i + 1]; |
|
128 | 129 | } |
|
129 | 130 | } |
|
130 | 131 | break; |
|
131 | 132 | default: |
|
132 | 133 | qWarning() << "Unknow type of animation"; |
|
133 | 134 | break; |
|
134 | 135 | } |
|
135 | 136 | |
|
136 | 137 | return qVariantFromValue(result); |
|
137 | 138 | } |
|
138 | 139 | |
|
139 | 140 | void SplineAnimation::updateCurrentValue (const QVariant &value ) |
|
140 | 141 | { |
|
141 | 142 | if (state() != QAbstractAnimation::Stopped) { //workaround |
|
142 | 143 | m_dirty = true; |
|
143 | 144 | QPair<QVector<QPointF >, QVector<QPointF > > pair = qVariantValue< QPair< QVector<QPointF>, QVector<QPointF> > >(value); |
|
144 | 145 | m_item->setLayout(pair.first, pair.second); |
|
145 | 146 | } |
|
146 | 147 | } |
|
147 | 148 | |
|
148 | 149 | |
|
149 | 150 | QTCOMMERCIALCHART_END_NAMESPACE |
@@ -1,109 +1,110 | |||
|
1 | 1 | /**************************************************************************** |
|
2 | 2 | ** |
|
3 | 3 | ** Copyright (C) 2012 Digia Plc |
|
4 | 4 | ** All rights reserved. |
|
5 | 5 | ** For any questions to Digia, please use contact form at http://qt.digia.com |
|
6 | 6 | ** |
|
7 | 7 | ** This file is part of the Qt Commercial Charts Add-on. |
|
8 | 8 | ** |
|
9 | 9 | ** $QT_BEGIN_LICENSE$ |
|
10 | 10 | ** Licensees holding valid Qt Commercial licenses may use this file in |
|
11 | 11 | ** accordance with the Qt Commercial License Agreement provided with the |
|
12 | 12 | ** Software or, alternatively, in accordance with the terms contained in |
|
13 | 13 | ** a written agreement between you and Digia. |
|
14 | 14 | ** |
|
15 | 15 | ** If you have questions regarding the use of this file, please use |
|
16 | 16 | ** contact form at http://qt.digia.com |
|
17 | 17 | ** $QT_END_LICENSE$ |
|
18 | 18 | ** |
|
19 | 19 | ****************************************************************************/ |
|
20 | 20 | |
|
21 | 21 | #include "xyanimation_p.h" |
|
22 | 22 | #include "xychartitem_p.h" |
|
23 | #include <QDebug> | |
|
23 | 24 | |
|
24 | 25 | Q_DECLARE_METATYPE(QVector<QPointF>) |
|
25 | 26 | |
|
26 | 27 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
27 | 28 | |
|
28 | 29 | XYAnimation::XYAnimation(XYChartItem *item):ChartAnimation(item), |
|
29 | 30 | m_item(item), |
|
30 | 31 | m_dirty(false) |
|
31 | 32 | { |
|
32 | 33 | } |
|
33 | 34 | |
|
34 | 35 | XYAnimation::~XYAnimation() |
|
35 | 36 | { |
|
36 | 37 | } |
|
37 | 38 | |
|
38 | 39 | void XYAnimation::setValues(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, int index) |
|
39 | 40 | { |
|
40 | 41 | int x = oldPoints.count(); |
|
41 | 42 | int y = newPoints.count(); |
|
42 | 43 | |
|
43 | 44 | if (x != y && abs(x - y) != 1) { |
|
44 | 45 | m_oldPoints = newPoints; |
|
45 | 46 | oldPoints.resize(newPoints.size()); |
|
46 | 47 | setKeyValueAt(0.0, qVariantFromValue(oldPoints)); |
|
47 | 48 | setKeyValueAt(1.0, qVariantFromValue(newPoints)); |
|
48 | 49 | m_dirty = false; |
|
49 | 50 | } |
|
50 | 51 | else { |
|
51 | 52 | if (m_dirty) { |
|
52 | 53 | m_oldPoints = oldPoints; |
|
53 | 54 | m_dirty = false; |
|
54 | 55 | } |
|
55 | 56 | oldPoints = newPoints; |
|
56 | 57 | if (y < x) |
|
57 | 58 | m_oldPoints.remove(index); //remove |
|
58 | 59 | if (y > x) |
|
59 | 60 | m_oldPoints.insert(index, x > 0 ? m_oldPoints[index-1] : newPoints[index]); //add |
|
60 | 61 | setKeyValueAt(0.0, qVariantFromValue(m_oldPoints)); |
|
61 | 62 | setKeyValueAt(1.0, qVariantFromValue(newPoints)); |
|
62 | 63 | Q_ASSERT(m_oldPoints.count() == newPoints.count()); |
|
63 | 64 | } |
|
64 | 65 | } |
|
65 | 66 | |
|
66 | 67 | QVariant XYAnimation::interpolated(const QVariant &start, const QVariant &end, qreal progress ) const |
|
67 | 68 | { |
|
68 | 69 | QVector<QPointF> startVector = qVariantValue<QVector<QPointF> >(start); |
|
69 | 70 | QVector<QPointF> endVector = qVariantValue<QVector<QPointF> >(end); |
|
70 | 71 | QVector<QPointF> result; |
|
71 | 72 | |
|
72 | 73 | switch (m_type) { |
|
73 | 74 | |
|
74 | 75 | case MoveDownAnimation: { |
|
75 | 76 | |
|
76 | 77 | if (startVector.count() != endVector.count()) |
|
77 | 78 | break; |
|
78 | 79 | |
|
79 | 80 | for(int i = 0; i < startVector.count(); i++) { |
|
80 | 81 | qreal x = startVector[i].x() + ((endVector[i].x() - startVector[i].x()) * progress); |
|
81 | 82 | qreal y = startVector[i].y() + ((endVector[i].y() - startVector[i].y()) * progress); |
|
82 | 83 | result << QPointF(x, y); |
|
83 | 84 | } |
|
84 | 85 | |
|
85 | 86 | } |
|
86 | 87 | break; |
|
87 | 88 | case LineDrawAnimation: { |
|
88 | 89 | for(int i = 0; i < endVector.count() * qBound(qreal(0), progress, qreal(1)); i++) |
|
89 | 90 | result << endVector[i]; |
|
90 | 91 | } |
|
91 | 92 | break; |
|
92 | 93 | default: |
|
93 | 94 | qWarning() << "Unknown type of animation"; |
|
94 | 95 | break; |
|
95 | 96 | } |
|
96 | 97 | |
|
97 | 98 | return qVariantFromValue(result); |
|
98 | 99 | } |
|
99 | 100 | |
|
100 | 101 | void XYAnimation::updateCurrentValue (const QVariant &value) |
|
101 | 102 | { |
|
102 | 103 | if(state()!=QAbstractAnimation::Stopped){ //workaround |
|
103 | 104 | m_dirty = true; |
|
104 | 105 | QVector<QPointF> vector = qVariantValue<QVector<QPointF> >(value); |
|
105 | 106 | m_item->setLayout(vector); |
|
106 | 107 | } |
|
107 | 108 | } |
|
108 | 109 | |
|
109 | 110 | QTCOMMERCIALCHART_END_NAMESPACE |
@@ -1,465 +1,466 | |||
|
1 | 1 | /**************************************************************************** |
|
2 | 2 | ** |
|
3 | 3 | ** Copyright (C) 2012 Digia Plc |
|
4 | 4 | ** All rights reserved. |
|
5 | 5 | ** For any questions to Digia, please use contact form at http://qt.digia.com |
|
6 | 6 | ** |
|
7 | 7 | ** This file is part of the Qt Commercial Charts Add-on. |
|
8 | 8 | ** |
|
9 | 9 | ** $QT_BEGIN_LICENSE$ |
|
10 | 10 | ** Licensees holding valid Qt Commercial licenses may use this file in |
|
11 | 11 | ** accordance with the Qt Commercial License Agreement provided with the |
|
12 | 12 | ** Software or, alternatively, in accordance with the terms contained in |
|
13 | 13 | ** a written agreement between you and Digia. |
|
14 | 14 | ** |
|
15 | 15 | ** If you have questions regarding the use of this file, please use |
|
16 | 16 | ** contact form at http://qt.digia.com |
|
17 | 17 | ** $QT_END_LICENSE$ |
|
18 | 18 | ** |
|
19 | 19 | ****************************************************************************/ |
|
20 | 20 | |
|
21 | 21 | #include "axis_p.h" |
|
22 | 22 | #include "qchartaxis.h" |
|
23 | 23 | #include "qchartaxis_p.h" |
|
24 | 24 | #include "qchartaxiscategories_p.h" |
|
25 | 25 | #include "chartpresenter_p.h" |
|
26 | 26 | #include "chartanimator_p.h" |
|
27 | 27 | #include <QPainter> |
|
28 | #include <QDebug> | |
|
28 | 29 | #include <cmath> |
|
29 | 30 | |
|
30 | 31 | static int label_padding = 5; |
|
31 | 32 | |
|
32 | 33 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
33 | 34 | |
|
34 | 35 | Axis::Axis(QChartAxis *axis,ChartPresenter *presenter,AxisType type) : Chart(presenter), |
|
35 | 36 | m_chartAxis(axis), |
|
36 | 37 | m_type(type), |
|
37 | 38 | m_labelsAngle(0), |
|
38 | 39 | m_grid(new QGraphicsItemGroup(presenter->rootItem())), |
|
39 | 40 | m_shades(new QGraphicsItemGroup(presenter->rootItem())), |
|
40 | 41 | m_labels(new QGraphicsItemGroup(presenter->rootItem())), |
|
41 | 42 | m_axis(new QGraphicsItemGroup(presenter->rootItem())), |
|
42 | 43 | m_min(0), |
|
43 | 44 | m_max(0), |
|
44 | 45 | m_ticksCount(0) |
|
45 | 46 | { |
|
46 | 47 | //initial initialization |
|
47 | 48 | m_axis->setZValue(ChartPresenter::AxisZValue); |
|
48 | 49 | m_axis->setHandlesChildEvents(false); |
|
49 | 50 | |
|
50 | 51 | m_shades->setZValue(ChartPresenter::ShadesZValue); |
|
51 | 52 | m_grid->setZValue(ChartPresenter::GridZValue); |
|
52 | 53 | |
|
53 | 54 | QObject::connect(m_chartAxis->d_ptr.data(),SIGNAL(updated()),this,SLOT(handleAxisUpdated())); |
|
54 | 55 | QObject::connect(m_chartAxis->categories()->d_ptr.data(),SIGNAL(updated()),this,SLOT(handleAxisCategoriesUpdated())); |
|
55 | 56 | |
|
56 | 57 | handleAxisUpdated(); |
|
57 | 58 | } |
|
58 | 59 | |
|
59 | 60 | Axis::~Axis() |
|
60 | 61 | { |
|
61 | 62 | } |
|
62 | 63 | |
|
63 | 64 | void Axis::createItems(int count) |
|
64 | 65 | { |
|
65 | 66 | |
|
66 | 67 | if (m_axis->children().size() == 0) |
|
67 | 68 | m_axis->addToGroup(new AxisItem(this)); |
|
68 | 69 | for (int i = 0; i < count; ++i) { |
|
69 | 70 | m_grid->addToGroup(new QGraphicsLineItem()); |
|
70 | 71 | m_labels->addToGroup(new QGraphicsSimpleTextItem()); |
|
71 | 72 | m_axis->addToGroup(new QGraphicsLineItem()); |
|
72 | 73 | if ((m_grid->childItems().size())%2 && m_grid->childItems().size()>2) m_shades->addToGroup(new QGraphicsRectItem()); |
|
73 | 74 | } |
|
74 | 75 | } |
|
75 | 76 | |
|
76 | 77 | void Axis::deleteItems(int count) |
|
77 | 78 | { |
|
78 | 79 | QList<QGraphicsItem *> lines = m_grid->childItems(); |
|
79 | 80 | QList<QGraphicsItem *> labels = m_labels->childItems(); |
|
80 | 81 | QList<QGraphicsItem *> shades = m_shades->childItems(); |
|
81 | 82 | QList<QGraphicsItem *> axis = m_axis->childItems(); |
|
82 | 83 | |
|
83 | 84 | for (int i = 0; i < count; ++i) { |
|
84 | 85 | if (lines.size()%2 && lines.size() > 1) delete(shades.takeLast()); |
|
85 | 86 | delete(lines.takeLast()); |
|
86 | 87 | delete(labels.takeLast()); |
|
87 | 88 | delete(axis.takeLast()); |
|
88 | 89 | } |
|
89 | 90 | } |
|
90 | 91 | |
|
91 | 92 | void Axis::updateLayout(QVector<qreal> &layout) |
|
92 | 93 | { |
|
93 | 94 | if (animator()) { |
|
94 | 95 | animator()->updateLayout(this,layout); |
|
95 | 96 | } else { |
|
96 | 97 | setLayout(layout); |
|
97 | 98 | } |
|
98 | 99 | } |
|
99 | 100 | |
|
100 | 101 | bool Axis::createLabels(QStringList &labels,qreal min, qreal max,int ticks) const |
|
101 | 102 | { |
|
102 | 103 | Q_ASSERT(max>=min); |
|
103 | 104 | Q_ASSERT(ticks>1); |
|
104 | 105 | |
|
105 | 106 | QChartAxisCategories* categories = m_chartAxis->categories(); |
|
106 | 107 | |
|
107 | 108 | bool category = categories->count()>0; |
|
108 | 109 | |
|
109 | 110 | if (!category) { |
|
110 | 111 | int n = qMax(int(-floor(log10((max-min)/(ticks-1)))),0); |
|
111 | 112 | n++; |
|
112 | 113 | for (int i=0; i< ticks; i++) { |
|
113 | 114 | qreal value = min + (i * (max - min)/ (ticks-1)); |
|
114 | 115 | labels << QString::number(value,'f',n); |
|
115 | 116 | } |
|
116 | 117 | } else { |
|
117 | 118 | QList<qreal> values = categories->values(); |
|
118 | 119 | for (int i=0; i< ticks; i++) { |
|
119 | 120 | qreal value = (min + (i * (max - min)/ (ticks-1))); |
|
120 | 121 | int j=0; |
|
121 | 122 | for (; j<values.count(); j++) { |
|
122 | 123 | if (values.at(j) > value) break; |
|
123 | 124 | } |
|
124 | 125 | if (j!=0) value=values.at(j-1); |
|
125 | 126 | |
|
126 | 127 | QString label = categories->label(value); |
|
127 | 128 | labels << label; |
|
128 | 129 | } |
|
129 | 130 | } |
|
130 | 131 | |
|
131 | 132 | return category; |
|
132 | 133 | } |
|
133 | 134 | |
|
134 | 135 | void Axis::setAxisOpacity(qreal opacity) |
|
135 | 136 | { |
|
136 | 137 | m_axis->setOpacity(opacity); |
|
137 | 138 | } |
|
138 | 139 | |
|
139 | 140 | qreal Axis::axisOpacity() const |
|
140 | 141 | { |
|
141 | 142 | return m_axis->opacity(); |
|
142 | 143 | } |
|
143 | 144 | |
|
144 | 145 | void Axis::setGridOpacity(qreal opacity) |
|
145 | 146 | { |
|
146 | 147 | m_grid->setOpacity(opacity); |
|
147 | 148 | } |
|
148 | 149 | |
|
149 | 150 | qreal Axis::gridOpacity() const |
|
150 | 151 | { |
|
151 | 152 | return m_grid->opacity(); |
|
152 | 153 | } |
|
153 | 154 | |
|
154 | 155 | void Axis::setLabelsOpacity(qreal opacity) |
|
155 | 156 | { |
|
156 | 157 | m_labels->setOpacity(opacity); |
|
157 | 158 | } |
|
158 | 159 | |
|
159 | 160 | qreal Axis::labelsOpacity() const |
|
160 | 161 | { |
|
161 | 162 | return m_labels->opacity(); |
|
162 | 163 | } |
|
163 | 164 | |
|
164 | 165 | void Axis::setShadesOpacity(qreal opacity) |
|
165 | 166 | { |
|
166 | 167 | m_shades->setOpacity(opacity); |
|
167 | 168 | } |
|
168 | 169 | |
|
169 | 170 | qreal Axis::shadesOpacity() const |
|
170 | 171 | { |
|
171 | 172 | return m_shades->opacity(); |
|
172 | 173 | } |
|
173 | 174 | |
|
174 | 175 | void Axis::setLabelsAngle(int angle) |
|
175 | 176 | { |
|
176 | 177 | foreach(QGraphicsItem* item , m_labels->childItems()) { |
|
177 | 178 | item->setRotation(angle); |
|
178 | 179 | } |
|
179 | 180 | |
|
180 | 181 | m_labelsAngle=angle; |
|
181 | 182 | } |
|
182 | 183 | |
|
183 | 184 | void Axis::setLabelsPen(const QPen &pen) |
|
184 | 185 | { |
|
185 | 186 | foreach(QGraphicsItem* item , m_labels->childItems()) { |
|
186 | 187 | static_cast<QGraphicsSimpleTextItem*>(item)->setPen(pen); |
|
187 | 188 | } |
|
188 | 189 | } |
|
189 | 190 | |
|
190 | 191 | void Axis::setLabelsBrush(const QBrush &brush) |
|
191 | 192 | { |
|
192 | 193 | foreach(QGraphicsItem* item , m_labels->childItems()) { |
|
193 | 194 | static_cast<QGraphicsSimpleTextItem*>(item)->setBrush(brush); |
|
194 | 195 | } |
|
195 | 196 | } |
|
196 | 197 | |
|
197 | 198 | void Axis::setLabelsFont(const QFont &font) |
|
198 | 199 | { |
|
199 | 200 | foreach(QGraphicsItem* item , m_labels->childItems()) { |
|
200 | 201 | static_cast<QGraphicsSimpleTextItem*>(item)->setFont(font); |
|
201 | 202 | } |
|
202 | 203 | } |
|
203 | 204 | |
|
204 | 205 | void Axis::setShadesBrush(const QBrush &brush) |
|
205 | 206 | { |
|
206 | 207 | foreach(QGraphicsItem* item , m_shades->childItems()) { |
|
207 | 208 | static_cast<QGraphicsRectItem*>(item)->setBrush(brush); |
|
208 | 209 | } |
|
209 | 210 | } |
|
210 | 211 | |
|
211 | 212 | void Axis::setShadesPen(const QPen &pen) |
|
212 | 213 | { |
|
213 | 214 | foreach(QGraphicsItem* item , m_shades->childItems()) { |
|
214 | 215 | static_cast<QGraphicsRectItem*>(item)->setPen(pen); |
|
215 | 216 | } |
|
216 | 217 | } |
|
217 | 218 | |
|
218 | 219 | void Axis::setAxisPen(const QPen &pen) |
|
219 | 220 | { |
|
220 | 221 | foreach(QGraphicsItem* item , m_axis->childItems()) { |
|
221 | 222 | static_cast<QGraphicsLineItem*>(item)->setPen(pen); |
|
222 | 223 | } |
|
223 | 224 | } |
|
224 | 225 | |
|
225 | 226 | void Axis::setGridPen(const QPen &pen) |
|
226 | 227 | { |
|
227 | 228 | foreach(QGraphicsItem* item , m_grid->childItems()) { |
|
228 | 229 | static_cast<QGraphicsLineItem*>(item)->setPen(pen); |
|
229 | 230 | } |
|
230 | 231 | } |
|
231 | 232 | |
|
232 | 233 | QVector<qreal> Axis::calculateLayout() const |
|
233 | 234 | { |
|
234 | 235 | Q_ASSERT(m_ticksCount>=2); |
|
235 | 236 | |
|
236 | 237 | QVector<qreal> points; |
|
237 | 238 | points.resize(m_ticksCount); |
|
238 | 239 | |
|
239 | 240 | switch (m_type) |
|
240 | 241 | { |
|
241 | 242 | case X_AXIS: |
|
242 | 243 | { |
|
243 | 244 | const qreal deltaX = m_rect.width()/(m_ticksCount-1); |
|
244 | 245 | for (int i = 0; i < m_ticksCount; ++i) { |
|
245 | 246 | int x = i * deltaX + m_rect.left(); |
|
246 | 247 | points[i] = x; |
|
247 | 248 | } |
|
248 | 249 | } |
|
249 | 250 | break; |
|
250 | 251 | case Y_AXIS: |
|
251 | 252 | { |
|
252 | 253 | const qreal deltaY = m_rect.height()/(m_ticksCount-1); |
|
253 | 254 | for (int i = 0; i < m_ticksCount; ++i) { |
|
254 | 255 | int y = i * -deltaY + m_rect.bottom(); |
|
255 | 256 | points[i] = y; |
|
256 | 257 | } |
|
257 | 258 | } |
|
258 | 259 | break; |
|
259 | 260 | } |
|
260 | 261 | return points; |
|
261 | 262 | } |
|
262 | 263 | |
|
263 | 264 | void Axis::setLayout(QVector<qreal> &layout) |
|
264 | 265 | { |
|
265 | 266 | int diff = m_layoutVector.size() - layout.size(); |
|
266 | 267 | |
|
267 | 268 | if (diff>0) { |
|
268 | 269 | deleteItems(diff); |
|
269 | 270 | } else if (diff<0) { |
|
270 | 271 | createItems(-diff); |
|
271 | 272 | } |
|
272 | 273 | |
|
273 | 274 | if( diff!=0) handleAxisUpdated(); |
|
274 | 275 | |
|
275 | 276 | QStringList ticksList; |
|
276 | 277 | |
|
277 | 278 | bool categories = createLabels(ticksList,m_min,m_max,layout.size()); |
|
278 | 279 | |
|
279 | 280 | QList<QGraphicsItem *> lines = m_grid->childItems(); |
|
280 | 281 | QList<QGraphicsItem *> labels = m_labels->childItems(); |
|
281 | 282 | QList<QGraphicsItem *> shades = m_shades->childItems(); |
|
282 | 283 | QList<QGraphicsItem *> axis = m_axis->childItems(); |
|
283 | 284 | |
|
284 | 285 | Q_ASSERT(labels.size() == ticksList.size()); |
|
285 | 286 | Q_ASSERT(layout.size() == ticksList.size()); |
|
286 | 287 | |
|
287 | 288 | qreal minWidth = 0; |
|
288 | 289 | qreal minHeight = 0; |
|
289 | 290 | |
|
290 | 291 | switch (m_type) |
|
291 | 292 | { |
|
292 | 293 | case X_AXIS: |
|
293 | 294 | { |
|
294 | 295 | QGraphicsLineItem *lineItem = static_cast<QGraphicsLineItem*>(axis.at(0)); |
|
295 | 296 | lineItem->setLine(m_rect.left(), m_rect.bottom(), m_rect.right(), m_rect.bottom()); |
|
296 | 297 | |
|
297 | 298 | for (int i = 0; i < layout.size(); ++i) { |
|
298 | 299 | QGraphicsLineItem *lineItem = static_cast<QGraphicsLineItem*>(lines.at(i)); |
|
299 | 300 | lineItem->setLine(layout[i], m_rect.top(), layout[i], m_rect.bottom()); |
|
300 | 301 | QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem*>(labels.at(i)); |
|
301 | 302 | if (!categories || i<1) { |
|
302 | 303 | labelItem->setText(ticksList.at(i)); |
|
303 | 304 | const QRectF& rect = labelItem->boundingRect(); |
|
304 | 305 | minWidth+=rect.width(); |
|
305 | 306 | minHeight=qMax(rect.height(),minHeight); |
|
306 | 307 | QPointF center = rect.center(); |
|
307 | 308 | labelItem->setTransformOriginPoint(center.x(), center.y()); |
|
308 | 309 | labelItem->setPos(layout[i] - center.x(), m_rect.bottom() + label_padding); |
|
309 | 310 | } else { |
|
310 | 311 | labelItem->setText(ticksList.at(i)); |
|
311 | 312 | const QRectF& rect = labelItem->boundingRect(); |
|
312 | 313 | minWidth+=rect.width(); |
|
313 | 314 | minHeight=qMax(rect.height()+label_padding,minHeight); |
|
314 | 315 | QPointF center = rect.center(); |
|
315 | 316 | labelItem->setTransformOriginPoint(center.x(), center.y()); |
|
316 | 317 | labelItem->setPos(layout[i] - (layout[i] - layout[i-1])/2 - center.x(), m_rect.bottom() + label_padding); |
|
317 | 318 | } |
|
318 | 319 | |
|
319 | 320 | if ((i+1)%2 && i>1) { |
|
320 | 321 | QGraphicsRectItem *rectItem = static_cast<QGraphicsRectItem*>(shades.at(i/2-1)); |
|
321 | 322 | rectItem->setRect(layout[i-1],m_rect.top(),layout[i]-layout[i-1],m_rect.height()); |
|
322 | 323 | } |
|
323 | 324 | lineItem = static_cast<QGraphicsLineItem*>(axis.at(i+1)); |
|
324 | 325 | lineItem->setLine(layout[i],m_rect.bottom(),layout[i],m_rect.bottom()+5); |
|
325 | 326 | } |
|
326 | 327 | |
|
327 | 328 | } |
|
328 | 329 | break; |
|
329 | 330 | |
|
330 | 331 | case Y_AXIS: |
|
331 | 332 | { |
|
332 | 333 | QGraphicsLineItem *lineItem = static_cast<QGraphicsLineItem*>(axis.at(0)); |
|
333 | 334 | lineItem->setLine(m_rect.left() , m_rect.top(), m_rect.left(), m_rect.bottom()); |
|
334 | 335 | |
|
335 | 336 | for (int i = 0; i < layout.size(); ++i) { |
|
336 | 337 | QGraphicsLineItem *lineItem = static_cast<QGraphicsLineItem*>(lines.at(i)); |
|
337 | 338 | lineItem->setLine(m_rect.left() , layout[i], m_rect.right(), layout[i]); |
|
338 | 339 | QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem*>(labels.at(i)); |
|
339 | 340 | |
|
340 | 341 | if (!categories || i<1) { |
|
341 | 342 | labelItem->setText(ticksList.at(i)); |
|
342 | 343 | const QRectF& rect = labelItem->boundingRect(); |
|
343 | 344 | minWidth=qMax(rect.width()+label_padding,minWidth); |
|
344 | 345 | minHeight+=rect.height(); |
|
345 | 346 | QPointF center = rect.center(); |
|
346 | 347 | labelItem->setTransformOriginPoint(center.x(), center.y()); |
|
347 | 348 | labelItem->setPos(m_rect.left() - rect.width() - label_padding , layout[i]-center.y()); |
|
348 | 349 | } else { |
|
349 | 350 | labelItem->setText(ticksList.at(i)); |
|
350 | 351 | const QRectF& rect = labelItem->boundingRect(); |
|
351 | 352 | minWidth=qMax(rect.width(),minWidth); |
|
352 | 353 | minHeight+=rect.height(); |
|
353 | 354 | QPointF center = rect.center(); |
|
354 | 355 | labelItem->setTransformOriginPoint(center.x(), center.y()); |
|
355 | 356 | labelItem->setPos(m_rect.left() - rect.width() - label_padding , layout[i] - (layout[i] - layout[i-1])/2 -center.y()); |
|
356 | 357 | } |
|
357 | 358 | |
|
358 | 359 | if ((i+1)%2 && i>1) { |
|
359 | 360 | QGraphicsRectItem *rectItem = static_cast<QGraphicsRectItem*>(shades.at(i/2-1)); |
|
360 | 361 | rectItem->setRect(m_rect.left(),layout[i],m_rect.width(),layout[i-1]-layout[i]); |
|
361 | 362 | } |
|
362 | 363 | lineItem = static_cast<QGraphicsLineItem*>(axis.at(i+1)); |
|
363 | 364 | lineItem->setLine(m_rect.left()-5,layout[i],m_rect.left(),layout[i]); |
|
364 | 365 | } |
|
365 | 366 | } |
|
366 | 367 | break; |
|
367 | 368 | default: |
|
368 |
|
|
|
369 | qWarning()<<"Unknown axis type"; | |
|
369 | 370 | break; |
|
370 | 371 | } |
|
371 | 372 | |
|
372 | 373 | m_layoutVector=layout; |
|
373 | 374 | |
|
374 | 375 | presenter()->setMinimumMarginWidth(this,minWidth); |
|
375 | 376 | presenter()->setMinimumMarginHeight(this,minHeight); |
|
376 | 377 | |
|
377 | 378 | } |
|
378 | 379 | |
|
379 | 380 | bool Axis::isEmpty() |
|
380 | 381 | { |
|
381 | 382 | return m_rect.isEmpty() || qFuzzyIsNull(m_min - m_max) || m_ticksCount==0; |
|
382 | 383 | } |
|
383 | 384 | |
|
384 | 385 | //handlers |
|
385 | 386 | |
|
386 | 387 | void Axis::handleAxisCategoriesUpdated() |
|
387 | 388 | { |
|
388 | 389 | if (isEmpty()) return; |
|
389 | 390 | updateLayout(m_layoutVector); |
|
390 | 391 | } |
|
391 | 392 | |
|
392 | 393 | void Axis::handleAxisUpdated() |
|
393 | 394 | { |
|
394 | 395 | |
|
395 | 396 | if (isEmpty()) return; |
|
396 | 397 | |
|
397 | 398 | if (m_chartAxis->isAxisVisible()) { |
|
398 | 399 | setAxisOpacity(100); |
|
399 | 400 | } else { |
|
400 | 401 | setAxisOpacity(0); |
|
401 | 402 | } |
|
402 | 403 | |
|
403 | 404 | if (m_chartAxis->isGridLineVisible()) { |
|
404 | 405 | setGridOpacity(100); |
|
405 | 406 | } else { |
|
406 | 407 | setGridOpacity(0); |
|
407 | 408 | } |
|
408 | 409 | |
|
409 | 410 | if (m_chartAxis->labelsVisible()) { |
|
410 | 411 | setLabelsOpacity(100); |
|
411 | 412 | } else { |
|
412 | 413 | setLabelsOpacity(0); |
|
413 | 414 | } |
|
414 | 415 | |
|
415 | 416 | if (m_chartAxis->shadesVisible()) { |
|
416 | 417 | setShadesOpacity(m_chartAxis->shadesOpacity()); |
|
417 | 418 | } else { |
|
418 | 419 | setShadesOpacity(0); |
|
419 | 420 | } |
|
420 | 421 | |
|
421 | 422 | setLabelsAngle(m_chartAxis->labelsAngle()); |
|
422 | 423 | setAxisPen(m_chartAxis->axisPen()); |
|
423 | 424 | setLabelsPen(m_chartAxis->labelsPen()); |
|
424 | 425 | setLabelsBrush(m_chartAxis->labelsBrush()); |
|
425 | 426 | setLabelsFont(m_chartAxis->labelsFont()); |
|
426 | 427 | setGridPen(m_chartAxis->gridLinePen()); |
|
427 | 428 | setShadesPen(m_chartAxis->shadesPen()); |
|
428 | 429 | setShadesBrush(m_chartAxis->shadesBrush()); |
|
429 | 430 | |
|
430 | 431 | } |
|
431 | 432 | |
|
432 | 433 | void Axis::handleRangeChanged(qreal min, qreal max,int tickCount) |
|
433 | 434 | { |
|
434 | 435 | if (qFuzzyIsNull(min - max) || tickCount < 2) |
|
435 | 436 | return; |
|
436 | 437 | |
|
437 | 438 | m_min = min; |
|
438 | 439 | m_max = max; |
|
439 | 440 | m_ticksCount= tickCount; |
|
440 | 441 | |
|
441 | 442 | if (isEmpty()) return; |
|
442 | 443 | QVector<qreal> layout = calculateLayout(); |
|
443 | 444 | updateLayout(layout); |
|
444 | 445 | |
|
445 | 446 | } |
|
446 | 447 | |
|
447 | 448 | void Axis::handleGeometryChanged(const QRectF &rect) |
|
448 | 449 | { |
|
449 | 450 | if(m_rect != rect) |
|
450 | 451 | { |
|
451 | 452 | m_rect = rect; |
|
452 | 453 | if (isEmpty()) return; |
|
453 | 454 | QVector<qreal> layout = calculateLayout(); |
|
454 | 455 | updateLayout(layout); |
|
455 | 456 | } |
|
456 | 457 | } |
|
457 | 458 | |
|
458 | 459 | void Axis::axisSelected() |
|
459 | 460 | { |
|
460 | 461 | qDebug()<<"TODO: axis clicked"; |
|
461 | 462 | } |
|
462 | 463 | |
|
463 | 464 | #include "moc_axis_p.cpp" |
|
464 | 465 | |
|
465 | 466 | QTCOMMERCIALCHART_END_NAMESPACE |
@@ -1,56 +1,57 | |||
|
1 | 1 | /**************************************************************************** |
|
2 | 2 | ** |
|
3 | 3 | ** Copyright (C) 2012 Digia Plc |
|
4 | 4 | ** All rights reserved. |
|
5 | 5 | ** For any questions to Digia, please use contact form at http://qt.digia.com |
|
6 | 6 | ** |
|
7 | 7 | ** This file is part of the Qt Commercial Charts Add-on. |
|
8 | 8 | ** |
|
9 | 9 | ** $QT_BEGIN_LICENSE$ |
|
10 | 10 | ** Licensees holding valid Qt Commercial licenses may use this file in |
|
11 | 11 | ** accordance with the Qt Commercial License Agreement provided with the |
|
12 | 12 | ** Software or, alternatively, in accordance with the terms contained in |
|
13 | 13 | ** a written agreement between you and Digia. |
|
14 | 14 | ** |
|
15 | 15 | ** If you have questions regarding the use of this file, please use |
|
16 | 16 | ** contact form at http://qt.digia.com |
|
17 | 17 | ** $QT_END_LICENSE$ |
|
18 | 18 | ** |
|
19 | 19 | ****************************************************************************/ |
|
20 | 20 | |
|
21 | 21 | // W A R N I N G |
|
22 | 22 | // ------------- |
|
23 | 23 | // |
|
24 | 24 | // This file is not part of the QtCommercial Chart API. It exists purely as an |
|
25 | 25 | // implementation detail. This header file may change from version to |
|
26 | 26 | // version without notice, or even be removed. |
|
27 | 27 | // |
|
28 | 28 | // We mean it. |
|
29 | 29 | |
|
30 | 30 | #ifndef QCHARTAXISCATEGORIES_P_H |
|
31 | 31 | #define QCHARTAXISCATEGORIES_P_H |
|
32 | 32 | |
|
33 | 33 | #include "qchartaxiscategories.h" |
|
34 | #include <QMap> | |
|
34 | 35 | |
|
35 | 36 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
36 | 37 | |
|
37 | 38 | class QChartAxisCategoriesPrivate : public QObject |
|
38 | 39 | { |
|
39 | 40 | Q_OBJECT |
|
40 | 41 | public: |
|
41 | 42 | QChartAxisCategoriesPrivate(QChartAxisCategories *q); |
|
42 | 43 | ~QChartAxisCategoriesPrivate(); |
|
43 | 44 | |
|
44 | 45 | Q_SIGNALS: |
|
45 | 46 | void updated(); |
|
46 | 47 | |
|
47 | 48 | private: |
|
48 | 49 | QChartAxisCategories *q_ptr; |
|
49 | 50 | QMap<qreal,QString> m_map; |
|
50 | 51 | friend class QChartAxisCategories; |
|
51 | 52 | |
|
52 | 53 | }; |
|
53 | 54 | |
|
54 | 55 | QTCOMMERCIALCHART_END_NAMESPACE |
|
55 | 56 | |
|
56 | 57 | #endif |
@@ -1,39 +1,40 | |||
|
1 | 1 | #ifndef QBARSET_P_H |
|
2 | 2 | #define QBARSET_P_H |
|
3 | 3 | |
|
4 | 4 | #include "qbarset.h" |
|
5 | #include <QMap> | |
|
5 | 6 | |
|
6 | 7 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
7 | 8 | |
|
8 | 9 | class QBarSetPrivate : public QObject |
|
9 | 10 | { |
|
10 | 11 | Q_OBJECT |
|
11 | 12 | |
|
12 | 13 | public: |
|
13 | 14 | QBarSetPrivate(const QString name, QBarSet *parent); |
|
14 | 15 | ~QBarSetPrivate(); |
|
15 | 16 | |
|
16 | 17 | Q_SIGNALS: |
|
17 | 18 | void clicked(QString category, Qt::MouseButtons button); |
|
18 | 19 | void structureChanged(); |
|
19 | 20 | void valueChanged(); |
|
20 | 21 | void labelsVisibleChanged(bool visible); |
|
21 | 22 | |
|
22 | 23 | public: |
|
23 | 24 | QBarSet * const q_ptr; |
|
24 | 25 | QString m_name; |
|
25 | 26 | QList<qreal> m_values; // TODO: replace with map (category, value) |
|
26 | 27 | QMap<QString, qreal> m_mappedValues; |
|
27 | 28 | QPen m_pen; |
|
28 | 29 | QBrush m_brush; |
|
29 | 30 | QPen m_labelPen; |
|
30 | 31 | QBrush m_labelBrush; |
|
31 | 32 | QFont m_labelFont; |
|
32 | 33 | bool m_labelsVisible; |
|
33 | 34 | |
|
34 | 35 | friend class QBarSet; |
|
35 | 36 | }; |
|
36 | 37 | |
|
37 | 38 | QTCOMMERCIALCHART_END_NAMESPACE |
|
38 | 39 | |
|
39 | 40 | #endif // QBARSETPRIVATE_P_H |
@@ -1,81 +1,82 | |||
|
1 | 1 | /**************************************************************************** |
|
2 | 2 | ** |
|
3 | 3 | ** Copyright (C) 2012 Digia Plc |
|
4 | 4 | ** All rights reserved. |
|
5 | 5 | ** For any questions to Digia, please use contact form at http://qt.digia.com |
|
6 | 6 | ** |
|
7 | 7 | ** This file is part of the Qt Commercial Charts Add-on. |
|
8 | 8 | ** |
|
9 | 9 | ** $QT_BEGIN_LICENSE$ |
|
10 | 10 | ** Licensees holding valid Qt Commercial licenses may use this file in |
|
11 | 11 | ** accordance with the Qt Commercial License Agreement provided with the |
|
12 | 12 | ** Software or, alternatively, in accordance with the terms contained in |
|
13 | 13 | ** a written agreement between you and Digia. |
|
14 | 14 | ** |
|
15 | 15 | ** If you have questions regarding the use of this file, please use |
|
16 | 16 | ** contact form at http://qt.digia.com |
|
17 | 17 | ** $QT_END_LICENSE$ |
|
18 | 18 | ** |
|
19 | 19 | ****************************************************************************/ |
|
20 | 20 | |
|
21 | 21 | #include "chart_p.h" |
|
22 | 22 | #include "chartpresenter_p.h" |
|
23 | #include <QDebug> | |
|
23 | 24 | |
|
24 | 25 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
25 | 26 | |
|
26 | 27 | |
|
27 | 28 | Chart::Chart(ChartPresenter *presenter):QObject(presenter), |
|
28 | 29 | m_animator(0), |
|
29 | 30 | m_presenter(presenter) |
|
30 | 31 | { |
|
31 | 32 | } |
|
32 | 33 | |
|
33 | 34 | void Chart::setAnimator(ChartAnimator* animator) |
|
34 | 35 | { |
|
35 | 36 | m_animator=animator; |
|
36 | 37 | } |
|
37 | 38 | |
|
38 | 39 | ChartAnimator* Chart::animator() const |
|
39 | 40 | { |
|
40 | 41 | return m_animator; |
|
41 | 42 | } |
|
42 | 43 | |
|
43 | 44 | ChartPresenter* Chart::presenter() const |
|
44 | 45 | { |
|
45 | 46 | return m_presenter; |
|
46 | 47 | } |
|
47 | 48 | |
|
48 | 49 | void Chart::handleGeometryChanged(const QRectF& rect) |
|
49 | 50 | { |
|
50 | 51 | Q_UNUSED(rect); |
|
51 | 52 | qWarning()<<"Slot not implemented"; |
|
52 | 53 | } |
|
53 | 54 | |
|
54 | 55 | void Chart::handleDomainChanged(qreal minX,qreal maxX,qreal minY,qreal maxY) |
|
55 | 56 | { |
|
56 | 57 | Q_UNUSED(minX); |
|
57 | 58 | Q_UNUSED(maxX); |
|
58 | 59 | Q_UNUSED(minY); |
|
59 | 60 | Q_UNUSED(maxY); |
|
60 | 61 | qWarning()<<"Slot not implemented"; |
|
61 | 62 | } |
|
62 | 63 | |
|
63 | 64 | void Chart::rangeXChanged(qreal min, qreal max, int tickXCount) |
|
64 | 65 | { |
|
65 | 66 | Q_UNUSED(min); |
|
66 | 67 | Q_UNUSED(max); |
|
67 | 68 | Q_UNUSED(tickXCount); |
|
68 | 69 | qWarning()<<"Slot not implemented"; |
|
69 | 70 | } |
|
70 | 71 | |
|
71 | 72 | void Chart::rangeYChanged(qreal min, qreal max, int tickYCount) |
|
72 | 73 | { |
|
73 | 74 | Q_UNUSED(min); |
|
74 | 75 | Q_UNUSED(max); |
|
75 | 76 | Q_UNUSED(tickYCount); |
|
76 | 77 | qWarning()<<"Slot not implemented"; |
|
77 | 78 | } |
|
78 | 79 | |
|
79 | 80 | #include "moc_chart_p.cpp" |
|
80 | 81 | |
|
81 | 82 | QTCOMMERCIALCHART_END_NAMESPACE |
@@ -1,55 +1,56 | |||
|
1 | 1 | /**************************************************************************** |
|
2 | 2 | ** |
|
3 | 3 | ** Copyright (C) 2012 Digia Plc |
|
4 | 4 | ** All rights reserved. |
|
5 | 5 | ** For any questions to Digia, please use contact form at http://qt.digia.com |
|
6 | 6 | ** |
|
7 | 7 | ** This file is part of the Qt Commercial Charts Add-on. |
|
8 | 8 | ** |
|
9 | 9 | ** $QT_BEGIN_LICENSE$ |
|
10 | 10 | ** Licensees holding valid Qt Commercial licenses may use this file in |
|
11 | 11 | ** accordance with the Qt Commercial License Agreement provided with the |
|
12 | 12 | ** Software or, alternatively, in accordance with the terms contained in |
|
13 | 13 | ** a written agreement between you and Digia. |
|
14 | 14 | ** |
|
15 | 15 | ** If you have questions regarding the use of this file, please use |
|
16 | 16 | ** contact form at http://qt.digia.com |
|
17 | 17 | ** $QT_END_LICENSE$ |
|
18 | 18 | ** |
|
19 | 19 | ****************************************************************************/ |
|
20 | 20 | |
|
21 | 21 | #ifndef CHART_H |
|
22 | 22 | #define CHART_H |
|
23 | 23 | |
|
24 | 24 | #include "qchartglobal.h" |
|
25 | #include <QObject> | |
|
25 | 26 | #include <QRect> |
|
26 | 27 | |
|
27 | 28 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
28 | 29 | |
|
29 | 30 | class ChartAnimator; |
|
30 | 31 | class ChartPresenter; |
|
31 | 32 | |
|
32 | 33 | class Chart: public QObject |
|
33 | 34 | { |
|
34 | 35 | Q_OBJECT |
|
35 | 36 | public: |
|
36 | 37 | explicit Chart(ChartPresenter *presenter); |
|
37 | 38 | |
|
38 | 39 | public Q_SLOTS: |
|
39 | 40 | virtual void handleGeometryChanged(const QRectF& rect); |
|
40 | 41 | virtual void handleDomainChanged(qreal minX,qreal maxX,qreal minY,qreal maxY); |
|
41 | 42 | virtual void rangeXChanged(qreal min, qreal max, int tickXCount); |
|
42 | 43 | virtual void rangeYChanged(qreal min, qreal max, int tickYCount); |
|
43 | 44 | |
|
44 | 45 | void setAnimator(ChartAnimator* animator); |
|
45 | 46 | ChartAnimator* animator() const; |
|
46 | 47 | ChartPresenter* presenter() const; |
|
47 | 48 | |
|
48 | 49 | private: |
|
49 | 50 | ChartAnimator* m_animator; |
|
50 | 51 | ChartPresenter* m_presenter; |
|
51 | 52 | }; |
|
52 | 53 | |
|
53 | 54 | QTCOMMERCIALCHART_END_NAMESPACE |
|
54 | 55 | |
|
55 | 56 | #endif |
@@ -1,73 +1,77 | |||
|
1 | 1 | /**************************************************************************** |
|
2 | 2 | ** |
|
3 | 3 | ** Copyright (C) 2012 Digia Plc |
|
4 | 4 | ** All rights reserved. |
|
5 | 5 | ** For any questions to Digia, please use contact form at http://qt.digia.com |
|
6 | 6 | ** |
|
7 | 7 | ** This file is part of the Qt Commercial Charts Add-on. |
|
8 | 8 | ** |
|
9 | 9 | ** $QT_BEGIN_LICENSE$ |
|
10 | 10 | ** Licensees holding valid Qt Commercial licenses may use this file in |
|
11 | 11 | ** accordance with the Qt Commercial License Agreement provided with the |
|
12 | 12 | ** Software or, alternatively, in accordance with the terms contained in |
|
13 | 13 | ** a written agreement between you and Digia. |
|
14 | 14 | ** |
|
15 | 15 | ** If you have questions regarding the use of this file, please use |
|
16 | 16 | ** contact form at http://qt.digia.com |
|
17 | 17 | ** $QT_END_LICENSE$ |
|
18 | 18 | ** |
|
19 | 19 | ****************************************************************************/ |
|
20 | 20 | |
|
21 | 21 | #ifndef CHARTCONFIG_H |
|
22 | 22 | #define CHARTCONFIG_H |
|
23 | 23 | |
|
24 | 24 | #include "qchartglobal.h" |
|
25 | ||
|
25 | 26 | #ifdef Q_CC_MSVC |
|
26 | 27 | // There is a problem with jom.exe currently. It does not seem to understand QMAKE_EXTRA_TARGETS properly. |
|
27 | 28 | // This is the case at least with shadow builds. |
|
28 | 29 | // http://qt-project.org/wiki/jom |
|
29 | const char *buildTime = __DATE__; | |
|
30 | #undef DEVELOPER_BUILD | |
|
31 | #endif | |
|
32 | ||
|
33 | #ifndef DEVELOPER_BUILD | |
|
34 | const char *buildTime = __TIME__" "__DATE__; | |
|
30 | 35 | const char *gitHead = "unknown"; |
|
31 | 36 | #else |
|
32 | 37 | #include "qchartversion_p.h" |
|
33 | 38 | #endif |
|
34 | 39 | |
|
35 | ||
|
36 | 40 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
37 | 41 | |
|
38 | 42 | class ChartConfig { |
|
39 | 43 | |
|
40 | 44 | private: |
|
41 | 45 | ChartConfig(){ |
|
42 | #ifndef QT_NO_DEBUG | |
|
46 | #if defined(DEVELOPMENT_BUILD) && !defined(QT_NO_DEBUG) | |
|
43 | 47 | qDebug()<<"buildTime" << buildTime; |
|
44 | 48 | qDebug()<<"gitHead" << gitHead; |
|
45 | 49 | #endif |
|
46 | 50 | m_instance = this; |
|
47 | 51 | } |
|
48 | 52 | public: |
|
49 | 53 | static ChartConfig* instance(){ |
|
50 | 54 | if(!m_instance){ |
|
51 | 55 | m_instance= new ChartConfig(); |
|
52 | 56 | } |
|
53 | 57 | return m_instance; |
|
54 | 58 | } |
|
55 | 59 | |
|
56 | 60 | QString compilationTime(){ |
|
57 | 61 | return buildTime; |
|
58 | 62 | } |
|
59 | 63 | |
|
60 | 64 | QString compilationHead(){ |
|
61 | 65 | return gitHead; |
|
62 | 66 | } |
|
63 | 67 | |
|
64 | 68 | private: |
|
65 | 69 | static ChartConfig* m_instance; |
|
66 | 70 | }; |
|
67 | 71 | |
|
68 | 72 | |
|
69 | 73 | ChartConfig* ChartConfig::m_instance=0; |
|
70 | 74 | |
|
71 | 75 | QTCOMMERCIALCHART_END_NAMESPACE |
|
72 | 76 | |
|
73 | 77 | #endif |
@@ -1,91 +1,92 | |||
|
1 | 1 | /**************************************************************************** |
|
2 | 2 | ** |
|
3 | 3 | ** Copyright (C) 2012 Digia Plc |
|
4 | 4 | ** All rights reserved. |
|
5 | 5 | ** For any questions to Digia, please use contact form at http://qt.digia.com |
|
6 | 6 | ** |
|
7 | 7 | ** This file is part of the Qt Commercial Charts Add-on. |
|
8 | 8 | ** |
|
9 | 9 | ** $QT_BEGIN_LICENSE$ |
|
10 | 10 | ** Licensees holding valid Qt Commercial licenses may use this file in |
|
11 | 11 | ** accordance with the Qt Commercial License Agreement provided with the |
|
12 | 12 | ** Software or, alternatively, in accordance with the terms contained in |
|
13 | 13 | ** a written agreement between you and Digia. |
|
14 | 14 | ** |
|
15 | 15 | ** If you have questions regarding the use of this file, please use |
|
16 | 16 | ** contact form at http://qt.digia.com |
|
17 | 17 | ** $QT_END_LICENSE$ |
|
18 | 18 | ** |
|
19 | 19 | ****************************************************************************/ |
|
20 | 20 | |
|
21 | 21 | #ifndef DOMAIN_H |
|
22 | 22 | #define DOMAIN_H |
|
23 | 23 | #include "qchartglobal.h" |
|
24 | 24 | #include <QRectF> |
|
25 | 25 | #include <QSizeF> |
|
26 | #include <QDebug> | |
|
26 | 27 | |
|
27 | 28 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
28 | 29 | |
|
29 | 30 | class Domain: public QObject { |
|
30 | 31 | Q_OBJECT |
|
31 | 32 | public: |
|
32 | 33 | explicit Domain(QObject* object=0); |
|
33 | 34 | virtual ~Domain(); |
|
34 | 35 | |
|
35 | 36 | void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY); |
|
36 | 37 | void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY, int tickXCount, int tickYCount); |
|
37 | 38 | void setRangeX(qreal min, qreal max); |
|
38 | 39 | void setRangeX(qreal min, qreal max, int tickCount); |
|
39 | 40 | void setRangeY(qreal min, qreal max); |
|
40 | 41 | void setRangeY(qreal min, qreal max, int tickCount); |
|
41 | 42 | void setMinX(qreal min); |
|
42 | 43 | void setMaxX(qreal max); |
|
43 | 44 | void setMinY(qreal min); |
|
44 | 45 | void setMaxY(qreal max); |
|
45 | 46 | |
|
46 | 47 | qreal minX() const { return m_minX; } |
|
47 | 48 | qreal maxX() const { return m_maxX; } |
|
48 | 49 | qreal minY() const { return m_minY; } |
|
49 | 50 | qreal maxY() const { return m_maxY; } |
|
50 | 51 | |
|
51 | 52 | qreal spanX() const; |
|
52 | 53 | qreal spanY() const; |
|
53 | 54 | bool isEmpty() const; |
|
54 | 55 | |
|
55 | 56 | int tickXCount() const {return m_tickXCount;} |
|
56 | 57 | int tickYCount() const {return m_tickYCount;} |
|
57 | 58 | |
|
58 | 59 | friend bool operator== (const Domain &domain1, const Domain &domain2); |
|
59 | 60 | friend bool operator!= (const Domain &domain1, const Domain &domain2); |
|
60 | 61 | friend QDebug operator<<(QDebug dbg, const Domain &domain); |
|
61 | 62 | |
|
62 | 63 | void zoomIn(const QRectF& rect, const QSizeF& size); |
|
63 | 64 | void zoomOut(const QRectF& rect, const QSizeF& size); |
|
64 | 65 | void move(int dx,int dy,const QSizeF& size); |
|
65 | 66 | |
|
66 | 67 | Q_SIGNALS: |
|
67 | 68 | void domainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY); |
|
68 | 69 | void rangeXChanged(qreal min, qreal max, int tickXCount); |
|
69 | 70 | void rangeYChanged(qreal min, qreal max, int tickYCount); |
|
70 | 71 | |
|
71 | 72 | public Q_SLOTS: |
|
72 | 73 | void handleAxisXChanged(qreal min,qreal max,int tickXCount = 5,bool niceNumbers = false); |
|
73 | 74 | void handleAxisYChanged(qreal min,qreal max,int tickYCount = 5,bool niceNumbers = false); |
|
74 | 75 | |
|
75 | 76 | private: |
|
76 | 77 | void looseNiceNumbers(qreal &min, qreal &max, int &ticksCount); |
|
77 | 78 | qreal niceNumber(qreal x,bool celing); |
|
78 | 79 | |
|
79 | 80 | private: |
|
80 | 81 | qreal m_minX; |
|
81 | 82 | qreal m_maxX; |
|
82 | 83 | qreal m_minY; |
|
83 | 84 | qreal m_maxY; |
|
84 | 85 | int m_tickXCount; |
|
85 | 86 | int m_tickYCount; |
|
86 | 87 | bool m_niceNumbers; |
|
87 | 88 | }; |
|
88 | 89 | |
|
89 | 90 | QTCOMMERCIALCHART_END_NAMESPACE |
|
90 | 91 | |
|
91 | 92 | #endif |
@@ -1,211 +1,210 | |||
|
1 | 1 | /**************************************************************************** |
|
2 | 2 | ** |
|
3 | 3 | ** Copyright (C) 2012 Digia Plc |
|
4 | 4 | ** All rights reserved. |
|
5 | 5 | ** For any questions to Digia, please use contact form at http://qt.digia.com |
|
6 | 6 | ** |
|
7 | 7 | ** This file is part of the Qt Commercial Charts Add-on. |
|
8 | 8 | ** |
|
9 | 9 | ** $QT_BEGIN_LICENSE$ |
|
10 | 10 | ** Licensees holding valid Qt Commercial licenses may use this file in |
|
11 | 11 | ** accordance with the Qt Commercial License Agreement provided with the |
|
12 | 12 | ** Software or, alternatively, in accordance with the terms contained in |
|
13 | 13 | ** a written agreement between you and Digia. |
|
14 | 14 | ** |
|
15 | 15 | ** If you have questions regarding the use of this file, please use |
|
16 | 16 | ** contact form at http://qt.digia.com |
|
17 | 17 | ** $QT_END_LICENSE$ |
|
18 | 18 | ** |
|
19 | 19 | ****************************************************************************/ |
|
20 | 20 | |
|
21 | 21 | #include "piechartitem_p.h" |
|
22 | 22 | #include "piesliceitem_p.h" |
|
23 | 23 | #include "qpieslice.h" |
|
24 | 24 | #include "qpieseries.h" |
|
25 | 25 | #include "chartpresenter_p.h" |
|
26 | 26 | #include "chartdataset_p.h" |
|
27 | 27 | #include "chartanimator_p.h" |
|
28 | #include <QDebug> | |
|
29 | 28 | #include <QPainter> |
|
30 | 29 | #include <QTimer> |
|
31 | 30 | |
|
32 | 31 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
33 | 32 | |
|
34 | 33 | PieChartItem::PieChartItem(QPieSeries *series, ChartPresenter* presenter) |
|
35 | 34 | :ChartItem(presenter), |
|
36 | 35 | m_series(series) |
|
37 | 36 | { |
|
38 | 37 | Q_ASSERT(series); |
|
39 | 38 | connect(series, SIGNAL(added(QList<QPieSlice*>)), this, SLOT(handleSlicesAdded(QList<QPieSlice*>))); |
|
40 | 39 | connect(series, SIGNAL(removed(QList<QPieSlice*>)), this, SLOT(handleSlicesRemoved(QList<QPieSlice*>))); |
|
41 | 40 | connect(series, SIGNAL(piePositionChanged()), this, SLOT(handlePieLayoutChanged())); |
|
42 | 41 | connect(series, SIGNAL(pieSizeChanged()), this, SLOT(handlePieLayoutChanged())); |
|
43 | 42 | |
|
44 | 43 | QTimer::singleShot(0, this, SLOT(initialize())); // TODO: get rid of this |
|
45 | 44 | |
|
46 | 45 | // Note: the following does not affect as long as the item does not have anything to paint |
|
47 | 46 | setZValue(ChartPresenter::PieSeriesZValue); |
|
48 | 47 | } |
|
49 | 48 | |
|
50 | 49 | PieChartItem::~PieChartItem() |
|
51 | 50 | { |
|
52 | 51 | // slices deleted automatically through QGraphicsItem |
|
53 | 52 | } |
|
54 | 53 | |
|
55 | 54 | void PieChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) |
|
56 | 55 | { |
|
57 | 56 | Q_UNUSED(painter) |
|
58 | 57 | // TODO: paint shadows for all components |
|
59 | 58 | // - get paths from items & merge & offset and draw with shadow color? |
|
60 | 59 | //painter->setBrush(QBrush(Qt::red)); |
|
61 | 60 | //painter->drawRect(m_debugRect); |
|
62 | 61 | } |
|
63 | 62 | |
|
64 | 63 | void PieChartItem::initialize() |
|
65 | 64 | { |
|
66 | 65 | handleSlicesAdded(m_series->slices()); |
|
67 | 66 | } |
|
68 | 67 | |
|
69 | 68 | void PieChartItem::handleSlicesAdded(QList<QPieSlice*> slices) |
|
70 | 69 | { |
|
71 | 70 | bool isEmpty = m_slices.isEmpty(); |
|
72 | 71 | |
|
73 | 72 | presenter()->chartTheme()->decorate(m_series, presenter()->dataSet()->seriesIndex(m_series)); |
|
74 | 73 | |
|
75 | 74 | foreach (QPieSlice *s, slices) { |
|
76 | 75 | PieSliceItem* item = new PieSliceItem(this); |
|
77 | 76 | m_slices.insert(s, item); |
|
78 | 77 | connect(s, SIGNAL(changed()), this, SLOT(handleSliceChanged())); |
|
79 | 78 | connect(item, SIGNAL(clicked(Qt::MouseButtons)), s, SIGNAL(clicked(Qt::MouseButtons))); |
|
80 | 79 | connect(item, SIGNAL(hoverEnter()), s, SIGNAL(hoverEnter())); |
|
81 | 80 | connect(item, SIGNAL(hoverLeave()), s, SIGNAL(hoverLeave())); |
|
82 | 81 | |
|
83 | 82 | PieSliceData data = sliceData(s); |
|
84 | 83 | |
|
85 | 84 | if (animator()) |
|
86 | 85 | animator()->addAnimation(this, s, data, isEmpty); |
|
87 | 86 | else |
|
88 | 87 | setLayout(s, data); |
|
89 | 88 | } |
|
90 | 89 | } |
|
91 | 90 | |
|
92 | 91 | void PieChartItem::handleSlicesRemoved(QList<QPieSlice*> slices) |
|
93 | 92 | { |
|
94 | 93 | presenter()->chartTheme()->decorate(m_series, presenter()->dataSet()->seriesIndex(m_series)); |
|
95 | 94 | |
|
96 | 95 | foreach (QPieSlice *s, slices) { |
|
97 | 96 | if (animator()) |
|
98 | 97 | animator()->removeAnimation(this, s); |
|
99 | 98 | else |
|
100 | 99 | destroySlice(s); |
|
101 | 100 | } |
|
102 | 101 | } |
|
103 | 102 | |
|
104 | 103 | void PieChartItem::handlePieLayoutChanged() |
|
105 | 104 | { |
|
106 | 105 | PieLayout layout = calculateLayout(); |
|
107 | 106 | applyLayout(layout); |
|
108 | 107 | update(); |
|
109 | 108 | } |
|
110 | 109 | |
|
111 | 110 | void PieChartItem::handleSliceChanged() |
|
112 | 111 | { |
|
113 | 112 | QPieSlice* slice = qobject_cast<QPieSlice *>(sender()); |
|
114 | 113 | Q_ASSERT(m_slices.contains(slice)); |
|
115 | 114 | PieSliceData data = sliceData(slice); |
|
116 | 115 | updateLayout(slice, data); |
|
117 | 116 | update(); |
|
118 | 117 | } |
|
119 | 118 | |
|
120 | 119 | void PieChartItem::handleDomainChanged(qreal, qreal, qreal, qreal) |
|
121 | 120 | { |
|
122 | 121 | // TODO |
|
123 | 122 | } |
|
124 | 123 | |
|
125 | 124 | void PieChartItem::handleGeometryChanged(const QRectF& rect) |
|
126 | 125 | { |
|
127 | 126 | prepareGeometryChange(); |
|
128 | 127 | m_rect = rect; |
|
129 | 128 | handlePieLayoutChanged(); |
|
130 | 129 | } |
|
131 | 130 | |
|
132 | 131 | void PieChartItem::calculatePieLayout() |
|
133 | 132 | { |
|
134 | 133 | // find pie center coordinates |
|
135 | 134 | m_pieCenter.setX(m_rect.left() + (m_rect.width() * m_series->horizontalPosition())); |
|
136 | 135 | m_pieCenter.setY(m_rect.top() + (m_rect.height() * m_series->verticalPosition())); |
|
137 | 136 | |
|
138 | 137 | // find maximum radius for pie |
|
139 | 138 | m_pieRadius = m_rect.height() / 2; |
|
140 | 139 | if (m_rect.width() < m_rect.height()) |
|
141 | 140 | m_pieRadius = m_rect.width() / 2; |
|
142 | 141 | |
|
143 | 142 | // apply size factor |
|
144 | 143 | m_pieRadius *= m_series->pieSize(); |
|
145 | 144 | } |
|
146 | 145 | |
|
147 | 146 | PieSliceData PieChartItem::sliceData(QPieSlice *slice) |
|
148 | 147 | { |
|
149 | 148 | // TODO: This function is kid of useless now. Refactor. |
|
150 | 149 | PieSliceData sliceData = PieSliceData::data(slice); |
|
151 | 150 | sliceData.m_center = PieSliceItem::sliceCenter(m_pieCenter, m_pieRadius, slice); |
|
152 | 151 | sliceData.m_radius = m_pieRadius; |
|
153 | 152 | return sliceData; |
|
154 | 153 | } |
|
155 | 154 | |
|
156 | 155 | PieLayout PieChartItem::calculateLayout() |
|
157 | 156 | { |
|
158 | 157 | calculatePieLayout(); |
|
159 | 158 | PieLayout layout; |
|
160 | 159 | foreach (QPieSlice* s, m_series->slices()) { |
|
161 | 160 | if (m_slices.contains(s)) // calculate layout only for those slices that are already visible |
|
162 | 161 | layout.insert(s, sliceData(s)); |
|
163 | 162 | } |
|
164 | 163 | return layout; |
|
165 | 164 | } |
|
166 | 165 | |
|
167 | 166 | void PieChartItem::applyLayout(const PieLayout &layout) |
|
168 | 167 | { |
|
169 | 168 | if (animator()) |
|
170 | 169 | animator()->updateLayout(this, layout); |
|
171 | 170 | else |
|
172 | 171 | setLayout(layout); |
|
173 | 172 | } |
|
174 | 173 | |
|
175 | 174 | void PieChartItem::updateLayout(QPieSlice *slice, const PieSliceData &sliceData) |
|
176 | 175 | { |
|
177 | 176 | if (animator()) |
|
178 | 177 | animator()->updateLayout(this, slice, sliceData); |
|
179 | 178 | else |
|
180 | 179 | setLayout(slice, sliceData); |
|
181 | 180 | } |
|
182 | 181 | |
|
183 | 182 | void PieChartItem::setLayout(const PieLayout &layout) |
|
184 | 183 | { |
|
185 | 184 | foreach (QPieSlice *slice, layout.keys()) { |
|
186 | 185 | PieSliceItem *item = m_slices.value(slice); |
|
187 | 186 | Q_ASSERT(item); |
|
188 | 187 | item->setSliceData(layout.value(slice)); |
|
189 | 188 | item->updateGeometry(); |
|
190 | 189 | item->update(); |
|
191 | 190 | } |
|
192 | 191 | } |
|
193 | 192 | |
|
194 | 193 | void PieChartItem::setLayout(QPieSlice *slice, const PieSliceData &sliceData) |
|
195 | 194 | { |
|
196 | 195 | // find slice |
|
197 | 196 | PieSliceItem *item = m_slices.value(slice); |
|
198 | 197 | Q_ASSERT(item); |
|
199 | 198 | item->setSliceData(sliceData); |
|
200 | 199 | item->updateGeometry(); |
|
201 | 200 | item->update(); |
|
202 | 201 | } |
|
203 | 202 | |
|
204 | 203 | void PieChartItem::destroySlice(QPieSlice *slice) |
|
205 | 204 | { |
|
206 | 205 | delete m_slices.take(slice); |
|
207 | 206 | } |
|
208 | 207 | |
|
209 | 208 | #include "moc_piechartitem_p.cpp" |
|
210 | 209 | |
|
211 | 210 | QTCOMMERCIALCHART_END_NAMESPACE |
@@ -1,142 +1,141 | |||
|
1 | 1 | /**************************************************************************** |
|
2 | 2 | ** |
|
3 | 3 | ** Copyright (C) 2012 Digia Plc |
|
4 | 4 | ** All rights reserved. |
|
5 | 5 | ** For any questions to Digia, please use contact form at http://qt.digia.com |
|
6 | 6 | ** |
|
7 | 7 | ** This file is part of the Qt Commercial Charts Add-on. |
|
8 | 8 | ** |
|
9 | 9 | ** $QT_BEGIN_LICENSE$ |
|
10 | 10 | ** Licensees holding valid Qt Commercial licenses may use this file in |
|
11 | 11 | ** accordance with the Qt Commercial License Agreement provided with the |
|
12 | 12 | ** Software or, alternatively, in accordance with the terms contained in |
|
13 | 13 | ** a written agreement between you and Digia. |
|
14 | 14 | ** |
|
15 | 15 | ** If you have questions regarding the use of this file, please use |
|
16 | 16 | ** contact form at http://qt.digia.com |
|
17 | 17 | ** $QT_END_LICENSE$ |
|
18 | 18 | ** |
|
19 | 19 | ****************************************************************************/ |
|
20 | 20 | |
|
21 | 21 | #ifndef PIESLICEDATA_P_H |
|
22 | 22 | #define PIESLICEDATA_P_H |
|
23 | 23 | |
|
24 | 24 | #include "qchartglobal.h" |
|
25 | 25 | #include "qpieslice.h" |
|
26 | 26 | #include <QPen> |
|
27 | 27 | #include <QBrush> |
|
28 | #include <QDebug> | |
|
29 | 28 | |
|
30 | 29 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
31 | 30 | |
|
32 | 31 | template <class T> |
|
33 | 32 | class Themed : public T |
|
34 | 33 | { |
|
35 | 34 | public: |
|
36 | 35 | Themed():m_isThemed(true) {} |
|
37 | 36 | |
|
38 | 37 | inline T &operator=(const T &other) { return T::operator =(other); } |
|
39 | 38 | |
|
40 | 39 | inline bool operator!=(const T &other) const { return T::operator !=(other); } |
|
41 | 40 | inline bool operator!=(const Themed &other) const |
|
42 | 41 | { |
|
43 | 42 | if (T::operator !=(other)) |
|
44 | 43 | return true; |
|
45 | 44 | |
|
46 | 45 | if (m_isThemed != other.m_isThemed) |
|
47 | 46 | return true; |
|
48 | 47 | |
|
49 | 48 | return false; |
|
50 | 49 | } |
|
51 | 50 | |
|
52 | 51 | inline void setThemed(bool state) { m_isThemed = state; } |
|
53 | 52 | inline bool isThemed() const { return m_isThemed; } |
|
54 | 53 | |
|
55 | 54 | private: |
|
56 | 55 | bool m_isThemed; |
|
57 | 56 | }; |
|
58 | 57 | |
|
59 | 58 | class PieSliceData |
|
60 | 59 | { |
|
61 | 60 | public: |
|
62 | 61 | PieSliceData() |
|
63 | 62 | { |
|
64 | 63 | m_value = 0; |
|
65 | 64 | |
|
66 | 65 | m_isExploded = false; |
|
67 | 66 | m_explodeDistanceFactor = 0.15; |
|
68 | 67 | |
|
69 | 68 | m_isLabelVisible = false; |
|
70 | 69 | m_labelArmLengthFactor = 0.15; |
|
71 | 70 | |
|
72 | 71 | m_percentage = 0; |
|
73 | 72 | m_radius = 0; |
|
74 | 73 | m_startAngle = 0; |
|
75 | 74 | m_angleSpan = 0; |
|
76 | 75 | } |
|
77 | 76 | |
|
78 | 77 | bool operator!=(const PieSliceData &other) const |
|
79 | 78 | { |
|
80 | 79 | if (!qFuzzyIsNull(m_value - other.m_value)) |
|
81 | 80 | return true; |
|
82 | 81 | |
|
83 | 82 | if (m_slicePen != other.m_slicePen || |
|
84 | 83 | m_sliceBrush != other.m_sliceBrush) |
|
85 | 84 | return true; |
|
86 | 85 | |
|
87 | 86 | if (m_isExploded != other.m_isExploded || |
|
88 | 87 | !qFuzzyIsNull(m_explodeDistanceFactor - other.m_explodeDistanceFactor)) |
|
89 | 88 | return true; |
|
90 | 89 | |
|
91 | 90 | if (m_isLabelVisible != other.m_isLabelVisible || |
|
92 | 91 | m_labelText != other.m_labelText || |
|
93 | 92 | m_labelFont != other.m_labelFont || |
|
94 | 93 | !qFuzzyIsNull(m_labelArmLengthFactor - other.m_labelArmLengthFactor) || |
|
95 | 94 | m_labelPen != other.m_labelPen) |
|
96 | 95 | return true; |
|
97 | 96 | |
|
98 | 97 | if (!qFuzzyIsNull(m_percentage - other.m_percentage) || |
|
99 | 98 | m_center != other.m_center || |
|
100 | 99 | !qFuzzyIsNull(m_radius - other.m_radius) || |
|
101 | 100 | !qFuzzyIsNull(m_startAngle - other.m_startAngle) || |
|
102 | 101 | !qFuzzyIsNull(m_angleSpan - other.m_angleSpan)) |
|
103 | 102 | return true; |
|
104 | 103 | |
|
105 | 104 | return false; |
|
106 | 105 | } |
|
107 | 106 | |
|
108 | 107 | void emitChangedSignal(QPieSlice *s) |
|
109 | 108 | { |
|
110 | 109 | emit s->changed(); |
|
111 | 110 | } |
|
112 | 111 | |
|
113 | 112 | static PieSliceData &data(QPieSlice *slice) |
|
114 | 113 | { |
|
115 | 114 | Q_ASSERT(slice); |
|
116 | 115 | return *slice->d; |
|
117 | 116 | } |
|
118 | 117 | |
|
119 | 118 | qreal m_value; |
|
120 | 119 | |
|
121 | 120 | Themed<QPen> m_slicePen; |
|
122 | 121 | Themed<QBrush> m_sliceBrush; |
|
123 | 122 | |
|
124 | 123 | bool m_isExploded; |
|
125 | 124 | qreal m_explodeDistanceFactor; |
|
126 | 125 | |
|
127 | 126 | bool m_isLabelVisible; |
|
128 | 127 | QString m_labelText; |
|
129 | 128 | Themed<QFont> m_labelFont; |
|
130 | 129 | qreal m_labelArmLengthFactor; |
|
131 | 130 | Themed<QPen> m_labelPen; |
|
132 | 131 | |
|
133 | 132 | qreal m_percentage; |
|
134 | 133 | QPointF m_center; |
|
135 | 134 | qreal m_radius; |
|
136 | 135 | qreal m_startAngle; |
|
137 | 136 | qreal m_angleSpan; |
|
138 | 137 | }; |
|
139 | 138 | |
|
140 | 139 | QTCOMMERCIALCHART_END_NAMESPACE |
|
141 | 140 | |
|
142 | 141 | #endif // PIESLICEDATA_P_H |
@@ -1,213 +1,212 | |||
|
1 | 1 | /**************************************************************************** |
|
2 | 2 | ** |
|
3 | 3 | ** Copyright (C) 2012 Digia Plc |
|
4 | 4 | ** All rights reserved. |
|
5 | 5 | ** For any questions to Digia, please use contact form at http://qt.digia.com |
|
6 | 6 | ** |
|
7 | 7 | ** This file is part of the Qt Commercial Charts Add-on. |
|
8 | 8 | ** |
|
9 | 9 | ** $QT_BEGIN_LICENSE$ |
|
10 | 10 | ** Licensees holding valid Qt Commercial licenses may use this file in |
|
11 | 11 | ** accordance with the Qt Commercial License Agreement provided with the |
|
12 | 12 | ** Software or, alternatively, in accordance with the terms contained in |
|
13 | 13 | ** a written agreement between you and Digia. |
|
14 | 14 | ** |
|
15 | 15 | ** If you have questions regarding the use of this file, please use |
|
16 | 16 | ** contact form at http://qt.digia.com |
|
17 | 17 | ** $QT_END_LICENSE$ |
|
18 | 18 | ** |
|
19 | 19 | ****************************************************************************/ |
|
20 | 20 | |
|
21 | 21 | #include "piesliceitem_p.h" |
|
22 | 22 | #include "piechartitem_p.h" |
|
23 | 23 | #include "qpieseries.h" |
|
24 | 24 | #include "qpieslice.h" |
|
25 | 25 | #include "chartpresenter_p.h" |
|
26 | 26 | #include <QPainter> |
|
27 | #include <QDebug> | |
|
28 | 27 | #include <qmath.h> |
|
29 | 28 | #include <QGraphicsSceneEvent> |
|
30 | 29 | #include <QTime> |
|
31 | 30 | |
|
32 | 31 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
33 | 32 | |
|
34 | 33 | #define PI 3.14159265 // TODO: is this defined in some header? |
|
35 | 34 | |
|
36 | 35 | QPointF offset(qreal angle, qreal length) |
|
37 | 36 | { |
|
38 | 37 | qreal dx = qSin(angle*(PI/180)) * length; |
|
39 | 38 | qreal dy = qCos(angle*(PI/180)) * length; |
|
40 | 39 | return QPointF(dx, -dy); |
|
41 | 40 | } |
|
42 | 41 | |
|
43 | 42 | PieSliceItem::PieSliceItem(QGraphicsItem* parent) |
|
44 | 43 | :QGraphicsObject(parent) |
|
45 | 44 | { |
|
46 | 45 | setAcceptHoverEvents(true); |
|
47 | 46 | setAcceptedMouseButtons(Qt::MouseButtonMask); |
|
48 | 47 | setZValue(ChartPresenter::PieSeriesZValue); |
|
49 | 48 | } |
|
50 | 49 | |
|
51 | 50 | PieSliceItem::~PieSliceItem() |
|
52 | 51 | { |
|
53 | 52 | |
|
54 | 53 | } |
|
55 | 54 | |
|
56 | 55 | QRectF PieSliceItem::boundingRect() const |
|
57 | 56 | { |
|
58 | 57 | return m_boundingRect; |
|
59 | 58 | } |
|
60 | 59 | |
|
61 | 60 | QPainterPath PieSliceItem::shape() const |
|
62 | 61 | { |
|
63 | 62 | // Don't include the label and label arm. |
|
64 | 63 | // This is used to detect a mouse clicks. We do not want clicks from label. |
|
65 | 64 | return m_slicePath; |
|
66 | 65 | } |
|
67 | 66 | |
|
68 | 67 | void PieSliceItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/) |
|
69 | 68 | { |
|
70 | 69 | painter->save(); |
|
71 | 70 | painter->setClipRect(parentItem()->boundingRect()); |
|
72 | 71 | painter->setPen(m_data.m_slicePen); |
|
73 | 72 | painter->setBrush(m_data.m_sliceBrush); |
|
74 | 73 | painter->drawPath(m_slicePath); |
|
75 | 74 | painter->restore(); |
|
76 | 75 | |
|
77 | 76 | if (m_data.m_isLabelVisible) { |
|
78 | 77 | painter->setClipRect(parentItem()->boundingRect()); |
|
79 | 78 | painter->setPen(m_data.m_labelPen); |
|
80 | 79 | painter->drawPath(m_labelArmPath); |
|
81 | 80 | // the pen color will affect the font color as well |
|
82 | 81 | painter->setFont(m_data.m_labelFont); |
|
83 | 82 | painter->drawText(m_labelTextRect.bottomLeft(), m_data.m_labelText); |
|
84 | 83 | } |
|
85 | 84 | } |
|
86 | 85 | |
|
87 | 86 | void PieSliceItem::hoverEnterEvent(QGraphicsSceneHoverEvent* /*event*/) |
|
88 | 87 | { |
|
89 | 88 | emit hoverEnter(); // TODO: refactor emit hover(somebooleanvalue) |
|
90 | 89 | } |
|
91 | 90 | |
|
92 | 91 | void PieSliceItem::hoverLeaveEvent(QGraphicsSceneHoverEvent* /*event*/) |
|
93 | 92 | { |
|
94 | 93 | emit hoverLeave(); // TODO: refactor emit hover(somebooleanvalue) |
|
95 | 94 | } |
|
96 | 95 | |
|
97 | 96 | void PieSliceItem::mousePressEvent(QGraphicsSceneMouseEvent *event) |
|
98 | 97 | { |
|
99 | 98 | emit clicked(event->buttons()); |
|
100 | 99 | } |
|
101 | 100 | |
|
102 | 101 | void PieSliceItem::setSliceData(PieSliceData sliceData) |
|
103 | 102 | { |
|
104 | 103 | m_data = sliceData; |
|
105 | 104 | } |
|
106 | 105 | |
|
107 | 106 | void PieSliceItem::updateGeometry() |
|
108 | 107 | { |
|
109 | 108 | if (m_data.m_radius <= 0) |
|
110 | 109 | return; |
|
111 | 110 | |
|
112 | 111 | prepareGeometryChange(); |
|
113 | 112 | |
|
114 | 113 | // update slice path |
|
115 | 114 | qreal centerAngle; |
|
116 | 115 | QPointF armStart; |
|
117 | 116 | m_slicePath = slicePath(m_data.m_center, m_data.m_radius, m_data.m_startAngle, m_data.m_angleSpan, ¢erAngle, &armStart); |
|
118 | 117 | |
|
119 | 118 | // update text rect |
|
120 | 119 | m_labelTextRect = labelTextRect(m_data.m_labelFont, m_data.m_labelText); |
|
121 | 120 | |
|
122 | 121 | // update label arm path |
|
123 | 122 | QPointF labelTextStart; |
|
124 | 123 | m_labelArmPath = labelArmPath(armStart, centerAngle, m_data.m_radius * m_data.m_labelArmLengthFactor, m_labelTextRect.width(), &labelTextStart); |
|
125 | 124 | |
|
126 | 125 | // update text position |
|
127 | 126 | m_labelTextRect.moveBottomLeft(labelTextStart); |
|
128 | 127 | |
|
129 | 128 | // update bounding rect |
|
130 | 129 | if (m_data.m_isLabelVisible) |
|
131 | 130 | m_boundingRect = m_slicePath.boundingRect().united(m_labelArmPath.boundingRect()).united(m_labelTextRect); |
|
132 | 131 | else |
|
133 | 132 | m_boundingRect = m_slicePath.boundingRect(); |
|
134 | 133 | } |
|
135 | 134 | |
|
136 | 135 | QPointF PieSliceItem::sliceCenter(QPointF point, qreal radius, QPieSlice *slice) |
|
137 | 136 | { |
|
138 | 137 | if (slice->isExploded()) { |
|
139 | 138 | qreal centerAngle = slice->startAngle() + ((slice->endAngle() - slice->startAngle())/2); |
|
140 | 139 | qreal len = radius * slice->explodeDistanceFactor(); |
|
141 | 140 | qreal dx = qSin(centerAngle*(PI/180)) * len; |
|
142 | 141 | qreal dy = -qCos(centerAngle*(PI/180)) * len; |
|
143 | 142 | point += QPointF(dx, dy); |
|
144 | 143 | } |
|
145 | 144 | return point; |
|
146 | 145 | } |
|
147 | 146 | |
|
148 | 147 | QPainterPath PieSliceItem::slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, qreal *centerAngle, QPointF* armStart) |
|
149 | 148 | { |
|
150 | 149 | // calculate center angle |
|
151 | 150 | *centerAngle = startAngle + (angleSpan/2); |
|
152 | 151 | |
|
153 | 152 | // calculate slice rectangle |
|
154 | 153 | QRectF rect(center.x()-radius, center.y()-radius, radius*2, radius*2); |
|
155 | 154 | |
|
156 | 155 | // slice path |
|
157 | 156 | // TODO: draw the shape so that it might have a hole in the center |
|
158 | 157 | QPainterPath path; |
|
159 | 158 | path.moveTo(rect.center()); |
|
160 | 159 | path.arcTo(rect, -startAngle + 90, -angleSpan); |
|
161 | 160 | path.closeSubpath(); |
|
162 | 161 | |
|
163 | 162 | // calculate label arm start point |
|
164 | 163 | *armStart = center; |
|
165 | 164 | *armStart += offset(*centerAngle, radius + PIESLICE_LABEL_GAP); |
|
166 | 165 | |
|
167 | 166 | return path; |
|
168 | 167 | } |
|
169 | 168 | |
|
170 | 169 | QPainterPath PieSliceItem::labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF *textStart) |
|
171 | 170 | { |
|
172 | 171 | // prevent label arm pointing straight down because it will look bad |
|
173 | 172 | if (angle < 180 && angle > 170) |
|
174 | 173 | angle = 170; |
|
175 | 174 | if (angle > 180 && angle < 190) |
|
176 | 175 | angle = 190; |
|
177 | 176 | |
|
178 | 177 | // line from slice to label |
|
179 | 178 | qreal dx = qSin(angle*(PI/180)) * length; |
|
180 | 179 | qreal dy = -qCos(angle*(PI/180)) * length; |
|
181 | 180 | QPointF parm1 = start + QPointF(dx, dy); |
|
182 | 181 | |
|
183 | 182 | // line to underline the label |
|
184 | 183 | QPointF parm2 = parm1; |
|
185 | 184 | if (angle < 180) { // arm swings the other way on the left side |
|
186 | 185 | parm2 += QPointF(textWidth, 0); |
|
187 | 186 | *textStart = parm1; |
|
188 | 187 | } |
|
189 | 188 | else { |
|
190 | 189 | parm2 += QPointF(-textWidth,0); |
|
191 | 190 | *textStart = parm2; |
|
192 | 191 | } |
|
193 | 192 | |
|
194 | 193 | // elevate the text position a bit so that it does not hit the line |
|
195 | 194 | *textStart += QPointF(0, -3); |
|
196 | 195 | |
|
197 | 196 | QPainterPath path; |
|
198 | 197 | path.moveTo(start); |
|
199 | 198 | path.lineTo(parm1); |
|
200 | 199 | path.lineTo(parm2); |
|
201 | 200 | |
|
202 | 201 | return path; |
|
203 | 202 | } |
|
204 | 203 | |
|
205 | 204 | QRectF PieSliceItem::labelTextRect(QFont font, QString text) |
|
206 | 205 | { |
|
207 | 206 | QFontMetricsF fm(font); |
|
208 | 207 | return fm.boundingRect(text); |
|
209 | 208 | } |
|
210 | 209 | |
|
211 | 210 | #include "moc_piesliceitem_p.cpp" |
|
212 | 211 | |
|
213 | 212 | QTCOMMERCIALCHART_END_NAMESPACE |
@@ -1,741 +1,740 | |||
|
1 | 1 | /**************************************************************************** |
|
2 | 2 | ** |
|
3 | 3 | ** Copyright (C) 2012 Digia Plc |
|
4 | 4 | ** All rights reserved. |
|
5 | 5 | ** For any questions to Digia, please use contact form at http://qt.digia.com |
|
6 | 6 | ** |
|
7 | 7 | ** This file is part of the Qt Commercial Charts Add-on. |
|
8 | 8 | ** |
|
9 | 9 | ** $QT_BEGIN_LICENSE$ |
|
10 | 10 | ** Licensees holding valid Qt Commercial licenses may use this file in |
|
11 | 11 | ** accordance with the Qt Commercial License Agreement provided with the |
|
12 | 12 | ** Software or, alternatively, in accordance with the terms contained in |
|
13 | 13 | ** a written agreement between you and Digia. |
|
14 | 14 | ** |
|
15 | 15 | ** If you have questions regarding the use of this file, please use |
|
16 | 16 | ** contact form at http://qt.digia.com |
|
17 | 17 | ** $QT_END_LICENSE$ |
|
18 | 18 | ** |
|
19 | 19 | ****************************************************************************/ |
|
20 | 20 | |
|
21 | 21 | #include "qpieseries.h" |
|
22 | 22 | #include "qpieseries_p.h" |
|
23 | 23 | #include "qpieslice.h" |
|
24 | 24 | #include "pieslicedata_p.h" |
|
25 | 25 | #include "chartdataset_p.h" |
|
26 | 26 | #include "charttheme_p.h" |
|
27 | 27 | #include "chartanimator_p.h" |
|
28 | 28 | #include "legendmarker_p.h" |
|
29 | 29 | #include <QAbstractItemModel> |
|
30 | #include <QDebug> | |
|
31 | 30 | |
|
32 | 31 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
33 | 32 | |
|
34 | 33 | /*! |
|
35 | 34 | \class QPieSeries |
|
36 | 35 | \brief Pie series API for QtCommercial Charts |
|
37 | 36 | |
|
38 | 37 | The pie series defines a pie chart which consists of pie slices which are defined as QPieSlice objects. |
|
39 | 38 | The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices. |
|
40 | 39 | The actual slice size is determined by that relative value. |
|
41 | 40 | |
|
42 | 41 | Pie size and position on the chart is controlled by using relative values which range from 0.0 to 1.0 |
|
43 | 42 | These relate to the actual chart rectangle. |
|
44 | 43 | |
|
45 | 44 | By default the pie is defined as a full pie but it can also be a partial pie. |
|
46 | 45 | This can be done by setting a starting angle and angle span to the series. |
|
47 | 46 | Full pie is 360 degrees where 0 is at 12 a'clock. |
|
48 | 47 | |
|
49 | 48 | See the \l {PieChart Example} {pie chart example} to learn how to create a simple pie chart. |
|
50 | 49 | \image examples_piechart.png |
|
51 | 50 | */ |
|
52 | 51 | |
|
53 | 52 | /*! |
|
54 | 53 | \property QPieSeries::horizontalPosition |
|
55 | 54 | \brief Defines the horizontal position of the pie. |
|
56 | 55 | |
|
57 | 56 | The value is a relative value to the chart rectangle where: |
|
58 | 57 | |
|
59 | 58 | \list |
|
60 | 59 | \o 0.0 is the absolute left. |
|
61 | 60 | \o 1.0 is the absolute right. |
|
62 | 61 | \endlist |
|
63 | 62 | |
|
64 | 63 | Default value is 0.5 (center). |
|
65 | 64 | */ |
|
66 | 65 | |
|
67 | 66 | /*! |
|
68 | 67 | \property QPieSeries::verticalPosition |
|
69 | 68 | \brief Defines the vertical position of the pie. |
|
70 | 69 | |
|
71 | 70 | The value is a relative value to the chart rectangle where: |
|
72 | 71 | |
|
73 | 72 | \list |
|
74 | 73 | \o 0.0 is the absolute top. |
|
75 | 74 | \o 1.0 is the absolute bottom. |
|
76 | 75 | \endlist |
|
77 | 76 | |
|
78 | 77 | Default value is 0.5 (center). |
|
79 | 78 | */ |
|
80 | 79 | |
|
81 | 80 | /*! |
|
82 | 81 | \property QPieSeries::size |
|
83 | 82 | \brief Defines the pie size. |
|
84 | 83 | |
|
85 | 84 | The value is a relative value to the chart rectangle where: |
|
86 | 85 | |
|
87 | 86 | \list |
|
88 | 87 | \o 0.0 is the minimum size (pie not drawn). |
|
89 | 88 | \o 1.0 is the maximum size that can fit the chart. |
|
90 | 89 | \endlist |
|
91 | 90 | |
|
92 | 91 | Default value is 0.7. |
|
93 | 92 | */ |
|
94 | 93 | |
|
95 | 94 | /*! |
|
96 | 95 | \property QPieSeries::startAngle |
|
97 | 96 | \brief Defines the starting angle of the pie. |
|
98 | 97 | |
|
99 | 98 | Full pie is 360 degrees where 0 degrees is at 12 a'clock. |
|
100 | 99 | |
|
101 | 100 | Default is value is 0. |
|
102 | 101 | */ |
|
103 | 102 | |
|
104 | 103 | /*! |
|
105 | 104 | \property QPieSeries::endAngle |
|
106 | 105 | \brief Defines the ending angle of the pie. |
|
107 | 106 | |
|
108 | 107 | Full pie is 360 degrees where 0 degrees is at 12 a'clock. |
|
109 | 108 | |
|
110 | 109 | Default is value is 360. |
|
111 | 110 | */ |
|
112 | 111 | |
|
113 | 112 | |
|
114 | 113 | /*! |
|
115 | 114 | Constructs a series object which is a child of \a parent. |
|
116 | 115 | */ |
|
117 | 116 | QPieSeries::QPieSeries(QObject *parent) : |
|
118 | 117 | QAbstractSeries(*new QPieSeriesPrivate(this),parent) |
|
119 | 118 | { |
|
120 | 119 | |
|
121 | 120 | } |
|
122 | 121 | |
|
123 | 122 | /*! |
|
124 | 123 | Destroys the series and its slices. |
|
125 | 124 | */ |
|
126 | 125 | QPieSeries::~QPieSeries() |
|
127 | 126 | { |
|
128 | 127 | // NOTE: d_prt destroyed by QObject |
|
129 | 128 | } |
|
130 | 129 | |
|
131 | 130 | /*! |
|
132 | 131 | Returns QChartSeries::SeriesTypePie. |
|
133 | 132 | */ |
|
134 | 133 | QAbstractSeries::QSeriesType QPieSeries::type() const |
|
135 | 134 | { |
|
136 | 135 | return QAbstractSeries::SeriesTypePie; |
|
137 | 136 | } |
|
138 | 137 | |
|
139 | 138 | /*! |
|
140 | 139 | Sets an array of \a slices to the series replacing the existing slices. |
|
141 | 140 | Slice ownership is passed to the series. |
|
142 | 141 | */ |
|
143 | 142 | void QPieSeries::replace(QList<QPieSlice*> slices) |
|
144 | 143 | { |
|
145 | 144 | clear(); |
|
146 | 145 | append(slices); |
|
147 | 146 | } |
|
148 | 147 | |
|
149 | 148 | /*! |
|
150 | 149 | Appends an array of \a slices to the series. |
|
151 | 150 | Slice ownership is passed to the series. |
|
152 | 151 | */ |
|
153 | 152 | void QPieSeries::append(QList<QPieSlice*> slices) |
|
154 | 153 | { |
|
155 | 154 | Q_D(QPieSeries); |
|
156 | 155 | |
|
157 | 156 | foreach (QPieSlice* s, slices) { |
|
158 | 157 | s->setParent(this); |
|
159 | 158 | d->m_slices << s; |
|
160 | 159 | } |
|
161 | 160 | |
|
162 | 161 | d->updateDerivativeData(); |
|
163 | 162 | |
|
164 | 163 | foreach (QPieSlice* s, slices) { |
|
165 | 164 | connect(s, SIGNAL(changed()), d, SLOT(sliceChanged())); |
|
166 | 165 | connect(s, SIGNAL(clicked(Qt::MouseButtons)), d, SLOT(sliceClicked(Qt::MouseButtons))); |
|
167 | 166 | connect(s, SIGNAL(hoverEnter()), d, SLOT(sliceHoverEnter())); |
|
168 | 167 | connect(s, SIGNAL(hoverLeave()), d, SLOT(sliceHoverLeave())); |
|
169 | 168 | } |
|
170 | 169 | |
|
171 | 170 | emit added(slices); |
|
172 | 171 | } |
|
173 | 172 | |
|
174 | 173 | /*! |
|
175 | 174 | Appends a single \a slice to the series. |
|
176 | 175 | Slice ownership is passed to the series. |
|
177 | 176 | */ |
|
178 | 177 | void QPieSeries::append(QPieSlice* slice) |
|
179 | 178 | { |
|
180 | 179 | append(QList<QPieSlice*>() << slice); |
|
181 | 180 | } |
|
182 | 181 | |
|
183 | 182 | /*! |
|
184 | 183 | Appends a single \a slice to the series and returns a reference to the series. |
|
185 | 184 | Slice ownership is passed to the series. |
|
186 | 185 | */ |
|
187 | 186 | QPieSeries& QPieSeries::operator << (QPieSlice* slice) |
|
188 | 187 | { |
|
189 | 188 | append(slice); |
|
190 | 189 | return *this; |
|
191 | 190 | } |
|
192 | 191 | |
|
193 | 192 | |
|
194 | 193 | /*! |
|
195 | 194 | Appends a single slice to the series with give \a value and \a name. |
|
196 | 195 | Slice ownership is passed to the series. |
|
197 | 196 | */ |
|
198 | 197 | QPieSlice* QPieSeries::append(qreal value, QString name) |
|
199 | 198 | { |
|
200 | 199 | QPieSlice* slice = new QPieSlice(value, name); |
|
201 | 200 | append(slice); |
|
202 | 201 | return slice; |
|
203 | 202 | } |
|
204 | 203 | |
|
205 | 204 | /*! |
|
206 | 205 | Inserts a single \a slice to the series before the slice at \a index position. |
|
207 | 206 | Slice ownership is passed to the series. |
|
208 | 207 | */ |
|
209 | 208 | void QPieSeries::insert(int index, QPieSlice* slice) |
|
210 | 209 | { |
|
211 | 210 | Q_D(QPieSeries); |
|
212 | 211 | Q_ASSERT(index <= d->m_slices.count()); |
|
213 | 212 | slice->setParent(this); |
|
214 | 213 | d->m_slices.insert(index, slice); |
|
215 | 214 | |
|
216 | 215 | d->updateDerivativeData(); |
|
217 | 216 | |
|
218 | 217 | connect(slice, SIGNAL(changed()), d, SLOT(sliceChanged())); |
|
219 | 218 | connect(slice, SIGNAL(clicked(Qt::MouseButtons)), d, SLOT(sliceClicked(Qt::MouseButtons))); |
|
220 | 219 | connect(slice, SIGNAL(hoverEnter()), d, SLOT(sliceHoverEnter())); |
|
221 | 220 | connect(slice, SIGNAL(hoverLeave()), d, SLOT(sliceHoverLeave())); |
|
222 | 221 | |
|
223 | 222 | emit added(QList<QPieSlice*>() << slice); |
|
224 | 223 | } |
|
225 | 224 | |
|
226 | 225 | /*! |
|
227 | 226 | Removes a single \a slice from the series and deletes the slice. |
|
228 | 227 | |
|
229 | 228 | Do not reference the pointer after this call. |
|
230 | 229 | */ |
|
231 | 230 | void QPieSeries::remove(QPieSlice* slice) |
|
232 | 231 | { |
|
233 | 232 | Q_D(QPieSeries); |
|
234 | 233 | if (!d->m_slices.removeOne(slice)) { |
|
235 | 234 | Q_ASSERT(0); // TODO: how should this be reported? |
|
236 | 235 | return; |
|
237 | 236 | } |
|
238 | 237 | |
|
239 | 238 | d->updateDerivativeData(); |
|
240 | 239 | |
|
241 | 240 | emit removed(QList<QPieSlice*>() << slice); |
|
242 | 241 | |
|
243 | 242 | delete slice; |
|
244 | 243 | slice = 0; |
|
245 | 244 | } |
|
246 | 245 | |
|
247 | 246 | /*! |
|
248 | 247 | Clears all slices from the series. |
|
249 | 248 | */ |
|
250 | 249 | void QPieSeries::clear() |
|
251 | 250 | { |
|
252 | 251 | Q_D(QPieSeries); |
|
253 | 252 | if (d->m_slices.count() == 0) |
|
254 | 253 | return; |
|
255 | 254 | |
|
256 | 255 | QList<QPieSlice*> slices = d->m_slices; |
|
257 | 256 | foreach (QPieSlice* s, d->m_slices) { |
|
258 | 257 | d->m_slices.removeOne(s); |
|
259 | 258 | delete s; |
|
260 | 259 | } |
|
261 | 260 | |
|
262 | 261 | d->updateDerivativeData(); |
|
263 | 262 | |
|
264 | 263 | emit removed(slices); |
|
265 | 264 | } |
|
266 | 265 | |
|
267 | 266 | /*! |
|
268 | 267 | returns the number of the slices in this series. |
|
269 | 268 | */ |
|
270 | 269 | int QPieSeries::count() const |
|
271 | 270 | { |
|
272 | 271 | Q_D(const QPieSeries); |
|
273 | 272 | return d->m_slices.count(); |
|
274 | 273 | } |
|
275 | 274 | |
|
276 | 275 | /*! |
|
277 | 276 | Returns true is the series is empty. |
|
278 | 277 | */ |
|
279 | 278 | bool QPieSeries::isEmpty() const |
|
280 | 279 | { |
|
281 | 280 | Q_D(const QPieSeries); |
|
282 | 281 | return d->m_slices.isEmpty(); |
|
283 | 282 | } |
|
284 | 283 | |
|
285 | 284 | /*! |
|
286 | 285 | Returns a list of slices that belong to this series. |
|
287 | 286 | */ |
|
288 | 287 | QList<QPieSlice*> QPieSeries::slices() const |
|
289 | 288 | { |
|
290 | 289 | Q_D(const QPieSeries); |
|
291 | 290 | return d->m_slices; |
|
292 | 291 | } |
|
293 | 292 | |
|
294 | 293 | void QPieSeries::setHorizontalPosition(qreal relativePosition) |
|
295 | 294 | { |
|
296 | 295 | Q_D(QPieSeries); |
|
297 | 296 | if (d->setRealValue(d->m_pieRelativeHorPos, relativePosition, 1.0)) |
|
298 | 297 | emit piePositionChanged(); |
|
299 | 298 | } |
|
300 | 299 | |
|
301 | 300 | void QPieSeries::setVerticalPosition(qreal relativePosition) |
|
302 | 301 | { |
|
303 | 302 | Q_D(QPieSeries); |
|
304 | 303 | if (d->setRealValue(d->m_pieRelativeVerPos, relativePosition, 1.0)) |
|
305 | 304 | emit piePositionChanged(); |
|
306 | 305 | } |
|
307 | 306 | |
|
308 | 307 | qreal QPieSeries::horizontalPosition() const |
|
309 | 308 | { |
|
310 | 309 | Q_D(const QPieSeries); |
|
311 | 310 | return d->m_pieRelativeHorPos; |
|
312 | 311 | } |
|
313 | 312 | |
|
314 | 313 | qreal QPieSeries::verticalPosition() const |
|
315 | 314 | { |
|
316 | 315 | Q_D(const QPieSeries); |
|
317 | 316 | return d->m_pieRelativeVerPos; |
|
318 | 317 | } |
|
319 | 318 | |
|
320 | 319 | void QPieSeries::setPieSize(qreal relativeSize) |
|
321 | 320 | { |
|
322 | 321 | Q_D(QPieSeries); |
|
323 | 322 | if (d->setRealValue(d->m_pieRelativeSize, relativeSize, 1.0)) |
|
324 | 323 | emit pieSizeChanged(); |
|
325 | 324 | } |
|
326 | 325 | |
|
327 | 326 | qreal QPieSeries::pieSize() const |
|
328 | 327 | { |
|
329 | 328 | Q_D(const QPieSeries); |
|
330 | 329 | return d->m_pieRelativeSize; |
|
331 | 330 | } |
|
332 | 331 | |
|
333 | 332 | |
|
334 | 333 | void QPieSeries::setPieStartAngle(qreal angle) |
|
335 | 334 | { |
|
336 | 335 | Q_D(QPieSeries); |
|
337 | 336 | if (d->setRealValue(d->m_pieStartAngle, angle, d->m_pieEndAngle)) |
|
338 | 337 | d->updateDerivativeData(); |
|
339 | 338 | } |
|
340 | 339 | |
|
341 | 340 | qreal QPieSeries::pieStartAngle() const |
|
342 | 341 | { |
|
343 | 342 | Q_D(const QPieSeries); |
|
344 | 343 | return d->m_pieStartAngle; |
|
345 | 344 | } |
|
346 | 345 | |
|
347 | 346 | /*! |
|
348 | 347 | Sets the end angle of the pie. |
|
349 | 348 | |
|
350 | 349 | Full pie is 360 degrees where 0 degrees is at 12 a'clock. |
|
351 | 350 | |
|
352 | 351 | \a angle must be greater than start angle. |
|
353 | 352 | |
|
354 | 353 | \sa pieEndAngle(), pieStartAngle(), setPieStartAngle() |
|
355 | 354 | */ |
|
356 | 355 | void QPieSeries::setPieEndAngle(qreal angle) |
|
357 | 356 | { |
|
358 | 357 | Q_D(QPieSeries); |
|
359 | 358 | |
|
360 | 359 | if (d->setRealValue(d->m_pieEndAngle, angle, 360.0, d->m_pieStartAngle)) |
|
361 | 360 | d->updateDerivativeData(); |
|
362 | 361 | } |
|
363 | 362 | |
|
364 | 363 | /*! |
|
365 | 364 | Returns the end angle of the pie. |
|
366 | 365 | |
|
367 | 366 | Full pie is 360 degrees where 0 degrees is at 12 a'clock. |
|
368 | 367 | |
|
369 | 368 | \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle() |
|
370 | 369 | */ |
|
371 | 370 | qreal QPieSeries::pieEndAngle() const |
|
372 | 371 | { |
|
373 | 372 | Q_D(const QPieSeries); |
|
374 | 373 | return d->m_pieEndAngle; |
|
375 | 374 | } |
|
376 | 375 | |
|
377 | 376 | /*! |
|
378 | 377 | Sets the all the slice labels \a visible or invisible. |
|
379 | 378 | |
|
380 | 379 | \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible() |
|
381 | 380 | */ |
|
382 | 381 | void QPieSeries::setLabelsVisible(bool visible) |
|
383 | 382 | { |
|
384 | 383 | Q_D(QPieSeries); |
|
385 | 384 | foreach (QPieSlice* s, d->m_slices) |
|
386 | 385 | s->setLabelVisible(visible); |
|
387 | 386 | } |
|
388 | 387 | |
|
389 | 388 | /*! |
|
390 | 389 | Returns the sum of all slice values in this series. |
|
391 | 390 | |
|
392 | 391 | \sa QPieSlice::value(), QPieSlice::setValue(), QPieSlice::percentage() |
|
393 | 392 | */ |
|
394 | 393 | qreal QPieSeries::sum() const |
|
395 | 394 | { |
|
396 | 395 | Q_D(const QPieSeries); |
|
397 | 396 | return d->m_sum; |
|
398 | 397 | } |
|
399 | 398 | |
|
400 | 399 | /*! |
|
401 | 400 | \fn void QPieSeries::clicked(QPieSlice* slice, Qt::MouseButtons buttons) |
|
402 | 401 | |
|
403 | 402 | This signal is emitted when a \a slice has been clicked with mouse \a buttons. |
|
404 | 403 | |
|
405 | 404 | \sa QPieSlice::clicked() |
|
406 | 405 | */ |
|
407 | 406 | |
|
408 | 407 | /*! |
|
409 | 408 | \fn void QPieSeries::hoverEnter(QPieSlice* slice) |
|
410 | 409 | |
|
411 | 410 | This signal is emitted when user has hovered over a \a slice. |
|
412 | 411 | |
|
413 | 412 | \sa QPieSlice::hoverEnter() |
|
414 | 413 | */ |
|
415 | 414 | |
|
416 | 415 | /*! |
|
417 | 416 | \fn void QPieSeries::hoverLeave(QPieSlice* slice) |
|
418 | 417 | |
|
419 | 418 | This signal is emitted when user has hovered away from a \a slice. |
|
420 | 419 | |
|
421 | 420 | \sa QPieSlice::hoverLeave() |
|
422 | 421 | */ |
|
423 | 422 | |
|
424 | 423 | /*! |
|
425 | 424 | \fn void QPieSeries::added(QList<QPieSlice*> slices) |
|
426 | 425 | |
|
427 | 426 | This signal is emitted when \a slices has been added to the series. |
|
428 | 427 | |
|
429 | 428 | \sa append(), insert() |
|
430 | 429 | */ |
|
431 | 430 | |
|
432 | 431 | /*! |
|
433 | 432 | \fn void QPieSeries::removed(QList<QPieSlice*> slices) |
|
434 | 433 | |
|
435 | 434 | This signal is emitted when \a slices has been removed from the series. |
|
436 | 435 | |
|
437 | 436 | \sa remove(), clear() |
|
438 | 437 | */ |
|
439 | 438 | |
|
440 | 439 | /*! |
|
441 | 440 | \fn void QPieSeries::piePositionChanged() |
|
442 | 441 | |
|
443 | 442 | This signal is emitted when pie position has changed. |
|
444 | 443 | |
|
445 | 444 | \sa verticalPosition(), setVerticalPosition(), horizontalPosition(), setHorizontalPosition() |
|
446 | 445 | */ |
|
447 | 446 | |
|
448 | 447 | /*! |
|
449 | 448 | \fn void QPieSeries::pieSizeChanged() |
|
450 | 449 | |
|
451 | 450 | This signal is emitted when pie size has changed. |
|
452 | 451 | |
|
453 | 452 | \sa pieSize(), setPieSize() |
|
454 | 453 | */ |
|
455 | 454 | |
|
456 | 455 | /*! |
|
457 | 456 | \fn bool QPieSeries::setModel(QAbstractItemModel *model) |
|
458 | 457 | Sets the \a model to be used as a data source |
|
459 | 458 | */ |
|
460 | 459 | bool QPieSeries::setModel(QAbstractItemModel* model) |
|
461 | 460 | { |
|
462 | 461 | Q_D(QPieSeries); |
|
463 | 462 | // disconnect signals from old model |
|
464 | 463 | if(d->m_model) |
|
465 | 464 | { |
|
466 | 465 | disconnect(d->m_model, 0, this, 0); |
|
467 | 466 | d->m_mapValues = -1; |
|
468 | 467 | d->m_mapLabels = -1; |
|
469 | 468 | d->m_mapOrientation = Qt::Vertical; |
|
470 | 469 | } |
|
471 | 470 | |
|
472 | 471 | // set new model |
|
473 | 472 | if(model) |
|
474 | 473 | { |
|
475 | 474 | d->m_model = model; |
|
476 | 475 | return true; |
|
477 | 476 | } |
|
478 | 477 | else |
|
479 | 478 | { |
|
480 | 479 | d->m_model = 0; |
|
481 | 480 | return false; |
|
482 | 481 | } |
|
483 | 482 | } |
|
484 | 483 | |
|
485 | 484 | /*! |
|
486 | 485 | \fn bool QPieSeries::setModelMapping(int modelValuesLine, int modelLabelsLine, Qt::Orientation orientation) |
|
487 | 486 | Sets column/row specified by \a modelValuesLine to be used as a list of pie slice values for the pie. |
|
488 | 487 | Parameter \a modelValuesLine indicates the column/row where the values for the pie slices are located in the model. |
|
489 | 488 | Parameter \a modelLabelsLine indicates the column/row where the labels for the pie slices are located in the model. |
|
490 | 489 | The \a orientation parameter specifies whether the data is in columns or in rows. |
|
491 | 490 | */ |
|
492 | 491 | void QPieSeries::setModelMapping(int modelValuesLine, int modelLabelsLine, Qt::Orientation orientation) |
|
493 | 492 | { |
|
494 | 493 | Q_D(QPieSeries); |
|
495 | 494 | |
|
496 | 495 | if (d->m_model == 0) |
|
497 | 496 | return; |
|
498 | 497 | |
|
499 | 498 | d->m_mapValues = modelValuesLine; |
|
500 | 499 | d->m_mapLabels = modelLabelsLine; |
|
501 | 500 | d->m_mapOrientation = orientation; |
|
502 | 501 | |
|
503 | 502 | // connect the signals |
|
504 | 503 | if (d->m_mapOrientation == Qt::Vertical) { |
|
505 | 504 | connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex))); |
|
506 | 505 | connect(d->m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelDataAdded(QModelIndex,int,int))); |
|
507 | 506 | connect(d->m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelDataRemoved(QModelIndex,int,int))); |
|
508 | 507 | } else { |
|
509 | 508 | connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex))); |
|
510 | 509 | connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelDataAdded(QModelIndex,int,int))); |
|
511 | 510 | connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelDataRemoved(QModelIndex,int,int))); |
|
512 | 511 | } |
|
513 | 512 | |
|
514 | 513 | // create the initial slices set |
|
515 | 514 | if (d->m_mapOrientation == Qt::Vertical) { |
|
516 | 515 | for (int i = 0; i < d->m_model->rowCount(); i++) |
|
517 | 516 | append(d->m_model->data(d->m_model->index(i, d->m_mapValues), Qt::DisplayRole).toDouble(), d->m_model->data(d->m_model->index(i, d->m_mapLabels), Qt::DisplayRole).toString()); |
|
518 | 517 | } else { |
|
519 | 518 | for (int i = 0; i < d->m_model->columnCount(); i++) |
|
520 | 519 | append(d->m_model->data(d->m_model->index(d->m_mapValues, i), Qt::DisplayRole).toDouble(), d->m_model->data(d->m_model->index(d->m_mapLabels, i), Qt::DisplayRole).toString()); |
|
521 | 520 | } |
|
522 | 521 | } |
|
523 | 522 | |
|
524 | 523 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
525 | 524 | |
|
526 | 525 | |
|
527 | 526 | QPieSeriesPrivate::QPieSeriesPrivate(QPieSeries *parent) : |
|
528 | 527 | QAbstractSeriesPrivate(parent), |
|
529 | 528 | m_pieRelativeHorPos(0.5), |
|
530 | 529 | m_pieRelativeVerPos(0.5), |
|
531 | 530 | m_pieRelativeSize(0.7), |
|
532 | 531 | m_pieStartAngle(0), |
|
533 | 532 | m_pieEndAngle(360), |
|
534 | 533 | m_sum(0), |
|
535 | 534 | m_mapValues(0), |
|
536 | 535 | m_mapLabels(0), |
|
537 | 536 | m_mapOrientation(Qt::Horizontal) |
|
538 | 537 | { |
|
539 | 538 | |
|
540 | 539 | } |
|
541 | 540 | |
|
542 | 541 | QPieSeriesPrivate::~QPieSeriesPrivate() |
|
543 | 542 | { |
|
544 | 543 | |
|
545 | 544 | } |
|
546 | 545 | |
|
547 | 546 | void QPieSeriesPrivate::updateDerivativeData() |
|
548 | 547 | { |
|
549 | 548 | m_sum = 0; |
|
550 | 549 | |
|
551 | 550 | // nothing to do? |
|
552 | 551 | if (m_slices.count() == 0) |
|
553 | 552 | return; |
|
554 | 553 | |
|
555 | 554 | // calculate sum of all slices |
|
556 | 555 | foreach (QPieSlice* s, m_slices) |
|
557 | 556 | m_sum += s->value(); |
|
558 | 557 | |
|
559 | 558 | // nothing to show.. |
|
560 | 559 | if (qFuzzyIsNull(m_sum)) |
|
561 | 560 | return; |
|
562 | 561 | |
|
563 | 562 | // update slice attributes |
|
564 | 563 | qreal sliceAngle = m_pieStartAngle; |
|
565 | 564 | qreal pieSpan = m_pieEndAngle - m_pieStartAngle; |
|
566 | 565 | QVector<QPieSlice*> changed; |
|
567 | 566 | foreach (QPieSlice* s, m_slices) { |
|
568 | 567 | |
|
569 | 568 | PieSliceData data = PieSliceData::data(s); |
|
570 | 569 | data.m_percentage = s->value() / m_sum; |
|
571 | 570 | data.m_angleSpan = pieSpan * data.m_percentage; |
|
572 | 571 | data.m_startAngle = sliceAngle; |
|
573 | 572 | sliceAngle += data.m_angleSpan; |
|
574 | 573 | |
|
575 | 574 | if (PieSliceData::data(s) != data) { |
|
576 | 575 | PieSliceData::data(s) = data; |
|
577 | 576 | changed << s; |
|
578 | 577 | } |
|
579 | 578 | } |
|
580 | 579 | |
|
581 | 580 | // emit signals |
|
582 | 581 | foreach (QPieSlice* s, changed) |
|
583 | 582 | PieSliceData::data(s).emitChangedSignal(s); |
|
584 | 583 | } |
|
585 | 584 | |
|
586 | 585 | void QPieSeriesPrivate::sliceChanged() |
|
587 | 586 | { |
|
588 | 587 | Q_ASSERT(m_slices.contains(qobject_cast<QPieSlice *>(sender()))); |
|
589 | 588 | updateDerivativeData(); |
|
590 | 589 | } |
|
591 | 590 | |
|
592 | 591 | void QPieSeriesPrivate::sliceClicked(Qt::MouseButtons buttons) |
|
593 | 592 | { |
|
594 | 593 | QPieSlice* slice = qobject_cast<QPieSlice *>(sender()); |
|
595 | 594 | Q_ASSERT(m_slices.contains(slice)); |
|
596 | 595 | Q_Q(QPieSeries); |
|
597 | 596 | emit q->clicked(slice, buttons); |
|
598 | 597 | } |
|
599 | 598 | |
|
600 | 599 | void QPieSeriesPrivate::sliceHoverEnter() |
|
601 | 600 | { |
|
602 | 601 | QPieSlice* slice = qobject_cast<QPieSlice *>(sender()); |
|
603 | 602 | Q_ASSERT(m_slices.contains(slice)); |
|
604 | 603 | Q_Q(QPieSeries); |
|
605 | 604 | emit q->hoverEnter(slice); |
|
606 | 605 | } |
|
607 | 606 | |
|
608 | 607 | void QPieSeriesPrivate::sliceHoverLeave() |
|
609 | 608 | { |
|
610 | 609 | QPieSlice* slice = qobject_cast<QPieSlice *>(sender()); |
|
611 | 610 | Q_ASSERT(m_slices.contains(slice)); |
|
612 | 611 | Q_Q(QPieSeries); |
|
613 | 612 | emit q->hoverLeave(slice); |
|
614 | 613 | } |
|
615 | 614 | |
|
616 | 615 | void QPieSeriesPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight) |
|
617 | 616 | { |
|
618 | 617 | Q_UNUSED(bottomRight) |
|
619 | 618 | |
|
620 | 619 | if (m_mapOrientation == Qt::Vertical) |
|
621 | 620 | { |
|
622 | 621 | if (topLeft.column() == m_mapValues) |
|
623 | 622 | if (m_mapValues == m_mapLabels) |
|
624 | 623 | { |
|
625 | 624 | m_slices.at(topLeft.row())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble()); |
|
626 | 625 | m_slices.at(topLeft.row())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString()); |
|
627 | 626 | } |
|
628 | 627 | else |
|
629 | 628 | { |
|
630 | 629 | m_slices.at(topLeft.row())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble()); |
|
631 | 630 | } |
|
632 | 631 | else if (topLeft.column() == m_mapLabels) |
|
633 | 632 | m_slices.at(topLeft.row())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString()); |
|
634 | 633 | } |
|
635 | 634 | else |
|
636 | 635 | { |
|
637 | 636 | if (topLeft.row() == m_mapValues) |
|
638 | 637 | if (m_mapValues == m_mapLabels) |
|
639 | 638 | { |
|
640 | 639 | m_slices.at(topLeft.column())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble()); |
|
641 | 640 | m_slices.at(topLeft.column())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString()); |
|
642 | 641 | } |
|
643 | 642 | else |
|
644 | 643 | { |
|
645 | 644 | m_slices.at(topLeft.column())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble()); |
|
646 | 645 | } |
|
647 | 646 | else if (topLeft.row() == m_mapLabels) |
|
648 | 647 | m_slices.at(topLeft.column())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString()); |
|
649 | 648 | } |
|
650 | 649 | } |
|
651 | 650 | |
|
652 | 651 | void QPieSeriesPrivate::modelDataAdded(QModelIndex parent, int start, int end) |
|
653 | 652 | { |
|
654 | 653 | Q_UNUSED(parent) |
|
655 | 654 | Q_UNUSED(end) |
|
656 | 655 | Q_Q(QPieSeries); |
|
657 | 656 | |
|
658 | 657 | QPieSlice* newSlice = new QPieSlice; |
|
659 | 658 | newSlice->setLabelVisible(true); |
|
660 | 659 | if (m_mapOrientation == Qt::Vertical) |
|
661 | 660 | { |
|
662 | 661 | newSlice->setValue(m_model->data(m_model->index(start, m_mapValues), Qt::DisplayRole).toDouble()); |
|
663 | 662 | newSlice->setLabel(m_model->data(m_model->index(start, m_mapLabels), Qt::DisplayRole).toString()); |
|
664 | 663 | } |
|
665 | 664 | else |
|
666 | 665 | { |
|
667 | 666 | newSlice->setValue(m_model->data(m_model->index(m_mapValues, start), Qt::DisplayRole).toDouble()); |
|
668 | 667 | newSlice->setLabel(m_model->data(m_model->index(m_mapLabels, start), Qt::DisplayRole).toString()); |
|
669 | 668 | } |
|
670 | 669 | |
|
671 | 670 | q->insert(start, newSlice); |
|
672 | 671 | } |
|
673 | 672 | |
|
674 | 673 | void QPieSeriesPrivate::modelDataRemoved(QModelIndex parent, int start, int end) |
|
675 | 674 | { |
|
676 | 675 | Q_UNUSED(parent) |
|
677 | 676 | Q_UNUSED(end) |
|
678 | 677 | Q_Q(QPieSeries); |
|
679 | 678 | q->remove(m_slices.at(start)); |
|
680 | 679 | } |
|
681 | 680 | |
|
682 | 681 | bool QPieSeriesPrivate::setRealValue(qreal &value, qreal newValue, qreal max, qreal min) |
|
683 | 682 | { |
|
684 | 683 | // Remove rounding errors |
|
685 | 684 | qreal roundedValue = newValue; |
|
686 | 685 | if (qFuzzyIsNull(min) && qFuzzyIsNull(newValue)) |
|
687 | 686 | roundedValue = 0.0; |
|
688 | 687 | else if (qFuzzyCompare(newValue, max)) |
|
689 | 688 | roundedValue = max; |
|
690 | 689 | else if (qFuzzyCompare(newValue, min)) |
|
691 | 690 | roundedValue = min; |
|
692 | 691 | |
|
693 | 692 | // Check if the position is valid after removing the rounding errors |
|
694 | 693 | if (roundedValue < min || roundedValue > max) { |
|
695 | 694 | qWarning("QPieSeries: Illegal value"); |
|
696 | 695 | return false; |
|
697 | 696 | } |
|
698 | 697 | |
|
699 | 698 | if (!qFuzzyIsNull(value - roundedValue)) { |
|
700 | 699 | value = roundedValue; |
|
701 | 700 | return true; |
|
702 | 701 | } |
|
703 | 702 | |
|
704 | 703 | // The change was so small it is considered a rounding error |
|
705 | 704 | return false; |
|
706 | 705 | } |
|
707 | 706 | |
|
708 | 707 | void QPieSeriesPrivate::scaleDomain(Domain& domain) |
|
709 | 708 | { |
|
710 | 709 | Q_UNUSED(domain); |
|
711 | 710 | #ifndef QT_NO_DEBUG |
|
712 | 711 | qWarning() << __FILE__<<__FUNCTION__<<"not implemented"; |
|
713 | 712 | #endif |
|
714 | 713 | } |
|
715 | 714 | |
|
716 | 715 | Chart* QPieSeriesPrivate::createGraphics(ChartPresenter* presenter) |
|
717 | 716 | { |
|
718 | 717 | Q_Q(QPieSeries); |
|
719 | 718 | PieChartItem* pie = new PieChartItem(q,presenter); |
|
720 | 719 | if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) { |
|
721 | 720 | presenter->animator()->addAnimation(pie); |
|
722 | 721 | } |
|
723 | 722 | presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q)); |
|
724 | 723 | return pie; |
|
725 | 724 | } |
|
726 | 725 | |
|
727 | 726 | QList<LegendMarker*> QPieSeriesPrivate::createLegendMarker(QLegend* legend) |
|
728 | 727 | { |
|
729 | 728 | Q_Q(QPieSeries); |
|
730 | 729 | QList<LegendMarker*> markers; |
|
731 | 730 | foreach(QPieSlice* slice, q->slices()) { |
|
732 | 731 | PieLegendMarker* marker = new PieLegendMarker(q,slice,legend); |
|
733 | 732 | markers << marker; |
|
734 | 733 | } |
|
735 | 734 | return markers; |
|
736 | 735 | } |
|
737 | 736 | |
|
738 | 737 | #include "moc_qpieseries.cpp" |
|
739 | 738 | #include "moc_qpieseries_p.cpp" |
|
740 | 739 | |
|
741 | 740 | QTCOMMERCIALCHART_END_NAMESPACE |
@@ -1,63 +1,64 | |||
|
1 | 1 | /**************************************************************************** |
|
2 | 2 | ** |
|
3 | 3 | ** Copyright (C) 2012 Digia Plc |
|
4 | 4 | ** All rights reserved. |
|
5 | 5 | ** For any questions to Digia, please use contact form at http://qt.digia.com |
|
6 | 6 | ** |
|
7 | 7 | ** This file is part of the Qt Commercial Charts Add-on. |
|
8 | 8 | ** |
|
9 | 9 | ** $QT_BEGIN_LICENSE$ |
|
10 | 10 | ** Licensees holding valid Qt Commercial licenses may use this file in |
|
11 | 11 | ** accordance with the Qt Commercial License Agreement provided with the |
|
12 | 12 | ** Software or, alternatively, in accordance with the terms contained in |
|
13 | 13 | ** a written agreement between you and Digia. |
|
14 | 14 | ** |
|
15 | 15 | ** If you have questions regarding the use of this file, please use |
|
16 | 16 | ** contact form at http://qt.digia.com |
|
17 | 17 | ** $QT_END_LICENSE$ |
|
18 | 18 | ** |
|
19 | 19 | ****************************************************************************/ |
|
20 | 20 | |
|
21 | 21 | #ifndef CHARTGLOBAL_H |
|
22 | 22 | #define CHARTGLOBAL_H |
|
23 | 23 | |
|
24 | 24 | #define QTCOMMERCIALCHART_VERSION_STR "1.0" |
|
25 | 25 | #define QTCOMMERCIALCHART_VERSION 0x01 |
|
26 | 26 | |
|
27 | 27 | #if defined(QTCOMMERCIALCHART_LIBRARY) |
|
28 | 28 | # define QTCOMMERCIALCHART_EXPORT Q_DECL_EXPORT |
|
29 | 29 | #else |
|
30 | 30 | # define QTCOMMERCIALCHART_EXPORT Q_DECL_IMPORT |
|
31 | 31 | #endif |
|
32 | 32 | |
|
33 | 33 | #define QTCOMMERCIALCHART_NAMESPACE QtCommercialChart |
|
34 | 34 | |
|
35 | 35 | #ifdef QTCOMMERCIALCHART_NAMESPACE |
|
36 | 36 | # define QTCOMMERCIALCHART_BEGIN_NAMESPACE namespace QTCOMMERCIALCHART_NAMESPACE { |
|
37 | 37 | # define QTCOMMERCIALCHART_END_NAMESPACE } |
|
38 | 38 | # define QTCOMMERCIALCHART_USE_NAMESPACE using namespace QTCOMMERCIALCHART_NAMESPACE; |
|
39 | 39 | #else |
|
40 | 40 | # define QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
41 | 41 | # define QTCOMMERCIALCHART_END_NAMESPACE |
|
42 | 42 | # define QTCOMMERCIALCHART_USE_NAMESPACE |
|
43 | 43 | #endif |
|
44 | 44 | |
|
45 | #define CHART_DEBUG chartDebug(3,__LINE__,__FILE__,__FUNCTION__); | |
|
45 | #if defined(DEVELOPER_BUILD) && !defined(QT_NO_DEBUG) | |
|
46 | #define CHART_DEBUG chartDebug(3,__LINE__,__FILE__,__FUNCTION__) | |
|
47 | ||
|
46 | 48 | |
|
47 | 49 | #include <stdarg.h> |
|
48 | 50 | #include <QDebug> |
|
49 | 51 | |
|
50 | /* | |
|
51 | static QDebug chartDebug(int numargs,...) | |
|
52 | static inline QDebug chartDebug(int numargs,...) | |
|
52 | 53 | { |
|
53 | 54 | va_list valist; |
|
54 | 55 | va_start(valist,numargs); |
|
55 | 56 | //for( int i = 0 ; i < numargs; i++ ) |
|
56 | 57 | int line=va_arg(valist,int); |
|
57 | 58 | char* file=va_arg(valist,char*); |
|
58 | 59 | char* function=va_arg(valist,char*); |
|
59 | 60 | va_end(valist); |
|
60 | 61 | return qDebug()<<QString().append(function).append("(").append(file).append(":%1)").arg(line); |
|
61 | 62 | } |
|
62 | */ | |
|
63 | #endif | |
|
63 | 64 | #endif |
@@ -1,190 +1,191 | |||
|
1 | 1 | /**************************************************************************** |
|
2 | 2 | ** |
|
3 | 3 | ** Copyright (C) 2012 Digia Plc |
|
4 | 4 | ** All rights reserved. |
|
5 | 5 | ** For any questions to Digia, please use contact form at http://qt.digia.com |
|
6 | 6 | ** |
|
7 | 7 | ** This file is part of the Qt Commercial Charts Add-on. |
|
8 | 8 | ** |
|
9 | 9 | ** $QT_BEGIN_LICENSE$ |
|
10 | 10 | ** Licensees holding valid Qt Commercial licenses may use this file in |
|
11 | 11 | ** accordance with the Qt Commercial License Agreement provided with the |
|
12 | 12 | ** Software or, alternatively, in accordance with the terms contained in |
|
13 | 13 | ** a written agreement between you and Digia. |
|
14 | 14 | ** |
|
15 | 15 | ** If you have questions regarding the use of this file, please use |
|
16 | 16 | ** contact form at http://qt.digia.com |
|
17 | 17 | ** $QT_END_LICENSE$ |
|
18 | 18 | ** |
|
19 | 19 | ****************************************************************************/ |
|
20 | 20 | |
|
21 | 21 | #include "scatterchartitem_p.h" |
|
22 | 22 | #include "qscatterseries.h" |
|
23 | 23 | #include "qscatterseries_p.h" |
|
24 | 24 | #include "chartpresenter_p.h" |
|
25 | 25 | #include <QPainter> |
|
26 | 26 | #include <QGraphicsScene> |
|
27 | #include <QDebug> | |
|
27 | 28 | |
|
28 | 29 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
29 | 30 | |
|
30 | 31 | ScatterChartItem::ScatterChartItem(QScatterSeries *series, ChartPresenter *presenter) : |
|
31 | 32 | XYChartItem(series,presenter), |
|
32 | 33 | m_series(series), |
|
33 | 34 | m_items(this), |
|
34 | 35 | m_shape(QScatterSeries::MarkerShapeRectangle), |
|
35 | 36 | m_size(15) |
|
36 | 37 | |
|
37 | 38 | { |
|
38 | 39 | QObject::connect(m_series->d_func(),SIGNAL(updated()), this, SLOT(handleUpdated())); |
|
39 | 40 | |
|
40 | 41 | setZValue(ChartPresenter::ScatterSeriesZValue); |
|
41 | 42 | setFlags(QGraphicsItem::ItemClipsChildrenToShape); |
|
42 | 43 | |
|
43 | 44 | handleUpdated(); |
|
44 | 45 | |
|
45 | 46 | m_items.setHandlesChildEvents(false); |
|
46 | 47 | |
|
47 | 48 | // TODO: how to draw a drop shadow? |
|
48 | 49 | // QGraphicsDropShadowEffect *dropShadow = new QGraphicsDropShadowEffect(); |
|
49 | 50 | // dropShadow->setOffset(2.0); |
|
50 | 51 | // dropShadow->setBlurRadius(2.0); |
|
51 | 52 | // setGraphicsEffect(dropShadow); |
|
52 | 53 | } |
|
53 | 54 | |
|
54 | 55 | |
|
55 | 56 | QRectF ScatterChartItem::boundingRect() const |
|
56 | 57 | { |
|
57 | 58 | return m_rect; |
|
58 | 59 | } |
|
59 | 60 | |
|
60 | 61 | void ScatterChartItem::createPoints(int count) |
|
61 | 62 | { |
|
62 | 63 | for (int i = 0; i < count; ++i) { |
|
63 | 64 | |
|
64 | 65 | QGraphicsItem *item = 0; |
|
65 | 66 | |
|
66 | 67 | switch (m_shape) { |
|
67 | 68 | case QScatterSeries::MarkerShapeCircle:{ |
|
68 | 69 | QGraphicsEllipseItem* i = new QGraphicsEllipseItem(0,0,m_size,m_size); |
|
69 | 70 | const QRectF& rect = i->boundingRect(); |
|
70 | 71 | i->setPos(-rect.width()/2,-rect.height()/2); |
|
71 | 72 | item = new Marker(i,this); |
|
72 | 73 | break; |
|
73 | 74 | } |
|
74 | 75 | case QScatterSeries::MarkerShapeRectangle:{ |
|
75 | 76 | QGraphicsRectItem* i = new QGraphicsRectItem(0,0,m_size,m_size); |
|
76 | 77 | i->setPos(-m_size/2,-m_size/2); |
|
77 | 78 | item = new Marker(i,this); |
|
78 | 79 | break; |
|
79 | 80 | } |
|
80 | 81 | default: |
|
81 | 82 | qWarning()<<"Unsupported marker type"; |
|
82 | 83 | break; |
|
83 | 84 | |
|
84 | 85 | } |
|
85 | 86 | m_items.addToGroup(item); |
|
86 | 87 | } |
|
87 | 88 | } |
|
88 | 89 | |
|
89 | 90 | void ScatterChartItem::deletePoints(int count) |
|
90 | 91 | { |
|
91 | 92 | QList<QGraphicsItem *> items = m_items.childItems(); |
|
92 | 93 | |
|
93 | 94 | for (int i = 0; i < count; ++i) { |
|
94 | 95 | delete(items.takeLast()); |
|
95 | 96 | } |
|
96 | 97 | } |
|
97 | 98 | |
|
98 | 99 | void ScatterChartItem::markerSelected(Marker *marker) |
|
99 | 100 | { |
|
100 | 101 | emit XYChartItem::clicked(QPointF(m_series->x(marker->index()), m_series->y(marker->index()))); |
|
101 | 102 | } |
|
102 | 103 | |
|
103 | 104 | void ScatterChartItem::setLayout(QVector<QPointF>& points) |
|
104 | 105 | { |
|
105 | 106 | if(points.size()==0) |
|
106 | 107 | { |
|
107 | 108 | XYChartItem::setLayout(points); |
|
108 | 109 | return; |
|
109 | 110 | } |
|
110 | 111 | |
|
111 | 112 | int diff = m_items.childItems().size() - points.size(); |
|
112 | 113 | |
|
113 | 114 | if(diff>0) { |
|
114 | 115 | deletePoints(diff); |
|
115 | 116 | } |
|
116 | 117 | else if(diff<0) { |
|
117 | 118 | createPoints(-diff); |
|
118 | 119 | } |
|
119 | 120 | |
|
120 | 121 | if(diff!=0) handleUpdated(); |
|
121 | 122 | |
|
122 | 123 | QList<QGraphicsItem*> items = m_items.childItems(); |
|
123 | 124 | |
|
124 | 125 | for (int i = 0; i < points.size(); i++) { |
|
125 | 126 | Marker* item = static_cast<Marker*>(items.at(i)); |
|
126 | 127 | const QPointF& point = points.at(i); |
|
127 | 128 | const QRectF& rect = item->boundingRect(); |
|
128 | 129 | item->setIndex(i); |
|
129 | 130 | item->setPos(point.x()-rect.width()/2,point.y()-rect.height()/2); |
|
130 | 131 | if(!clipRect().contains(point)) { |
|
131 | 132 | item->setVisible(false); |
|
132 | 133 | } |
|
133 | 134 | else { |
|
134 | 135 | item->setVisible(true); |
|
135 | 136 | } |
|
136 | 137 | } |
|
137 | 138 | |
|
138 | 139 | prepareGeometryChange(); |
|
139 | 140 | m_rect = clipRect(); |
|
140 | 141 | XYChartItem::setLayout(points); |
|
141 | 142 | } |
|
142 | 143 | |
|
143 | 144 | |
|
144 | 145 | void ScatterChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) |
|
145 | 146 | { |
|
146 | 147 | Q_UNUSED(painter) |
|
147 | 148 | Q_UNUSED(option) |
|
148 | 149 | Q_UNUSED(widget) |
|
149 | 150 | } |
|
150 | 151 | |
|
151 | 152 | void ScatterChartItem::setPen(const QPen& pen) |
|
152 | 153 | { |
|
153 | 154 | foreach(QGraphicsItem* item , m_items.childItems()) { |
|
154 | 155 | static_cast<Marker*>(item)->setPen(pen); |
|
155 | 156 | } |
|
156 | 157 | } |
|
157 | 158 | |
|
158 | 159 | void ScatterChartItem::setBrush(const QBrush& brush) |
|
159 | 160 | { |
|
160 | 161 | foreach(QGraphicsItem* item , m_items.childItems()) { |
|
161 | 162 | static_cast<Marker*>(item)->setBrush(brush); |
|
162 | 163 | } |
|
163 | 164 | } |
|
164 | 165 | |
|
165 | 166 | void ScatterChartItem::handleUpdated() |
|
166 | 167 | { |
|
167 | 168 | |
|
168 | 169 | int count = m_items.childItems().count(); |
|
169 | 170 | |
|
170 | 171 | if(count==0) return; |
|
171 | 172 | |
|
172 | 173 | bool recreate = m_size != m_series->size() || m_shape != m_series->shape(); |
|
173 | 174 | |
|
174 | 175 | //TODO: only rewrite on size change |
|
175 | 176 | |
|
176 | 177 | m_size = m_series->size(); |
|
177 | 178 | m_shape = m_series->shape(); |
|
178 | 179 | |
|
179 | 180 | if(recreate){ |
|
180 | 181 | deletePoints(count); |
|
181 | 182 | createPoints(count); |
|
182 | 183 | } |
|
183 | 184 | |
|
184 | 185 | setPen(m_series->pen()); |
|
185 | 186 | setBrush(m_series->brush()); |
|
186 | 187 | } |
|
187 | 188 | |
|
188 | 189 | #include "moc_scatterchartitem_p.cpp" |
|
189 | 190 | |
|
190 | 191 | QTCOMMERCIALCHART_END_NAMESPACE |
@@ -1,250 +1,251 | |||
|
1 | 1 | /**************************************************************************** |
|
2 | 2 | ** |
|
3 | 3 | ** Copyright (C) 2012 Digia Plc |
|
4 | 4 | ** All rights reserved. |
|
5 | 5 | ** For any questions to Digia, please use contact form at http://qt.digia.com |
|
6 | 6 | ** |
|
7 | 7 | ** This file is part of the Qt Commercial Charts Add-on. |
|
8 | 8 | ** |
|
9 | 9 | ** $QT_BEGIN_LICENSE$ |
|
10 | 10 | ** Licensees holding valid Qt Commercial licenses may use this file in |
|
11 | 11 | ** accordance with the Qt Commercial License Agreement provided with the |
|
12 | 12 | ** Software or, alternatively, in accordance with the terms contained in |
|
13 | 13 | ** a written agreement between you and Digia. |
|
14 | 14 | ** |
|
15 | 15 | ** If you have questions regarding the use of this file, please use |
|
16 | 16 | ** contact form at http://qt.digia.com |
|
17 | 17 | ** $QT_END_LICENSE$ |
|
18 | 18 | ** |
|
19 | 19 | ****************************************************************************/ |
|
20 | 20 | |
|
21 | 21 | #include "scroller_p.h" |
|
22 | 22 | #include "qlegend.h" |
|
23 | 23 | #include <QGraphicsSceneMouseEvent> |
|
24 | #include <QDebug> | |
|
24 | 25 | |
|
25 | 26 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
26 | 27 | |
|
27 | 28 | Scroller::Scroller(): |
|
28 | 29 | m_ticker(this), |
|
29 | 30 | m_state(Idle), |
|
30 | 31 | m_moveThreshold(10), |
|
31 | 32 | m_timeTreshold(50) |
|
32 | 33 | { |
|
33 | 34 | |
|
34 | 35 | } |
|
35 | 36 | |
|
36 | 37 | Scroller::~Scroller() |
|
37 | 38 | { |
|
38 | 39 | } |
|
39 | 40 | |
|
40 | 41 | void Scroller::mousePressEvent(QGraphicsSceneMouseEvent* event) |
|
41 | 42 | { |
|
42 | 43 | if (event->button() == Qt::LeftButton) { |
|
43 | 44 | |
|
44 | 45 | switch (m_state) { |
|
45 | 46 | case Idle: |
|
46 | 47 | { |
|
47 | 48 | m_state = Pressed; |
|
48 | 49 | m_offset = offset(); |
|
49 | 50 | m_press = event->pos(); |
|
50 | 51 | m_timeStamp = QTime::currentTime(); |
|
51 | 52 | event->accept(); |
|
52 | 53 | break; |
|
53 | 54 | } |
|
54 | 55 | case Scroll: |
|
55 | 56 | { |
|
56 | 57 | m_state = Stop; |
|
57 | 58 | m_speed = QPoint(0, 0); |
|
58 | 59 | m_offset = offset(); |
|
59 | 60 | m_press = event->pos(); |
|
60 | 61 | event->accept(); |
|
61 | 62 | break; |
|
62 | 63 | } |
|
63 | 64 | case Pressed: |
|
64 | 65 | case Move: |
|
65 | 66 | case Stop: |
|
66 | 67 | qWarning() << __FUNCTION__<<"Scroller unexpected state" << m_state; |
|
67 | 68 | event->ignore(); |
|
68 | 69 | break; |
|
69 | 70 | } |
|
70 | 71 | } |
|
71 | 72 | } |
|
72 | 73 | |
|
73 | 74 | void Scroller::mouseMoveEvent(QGraphicsSceneMouseEvent* event) |
|
74 | 75 | { |
|
75 | 76 | QPointF delta = event->pos() - m_press; |
|
76 | 77 | |
|
77 | 78 | switch (m_state) { |
|
78 | 79 | case Pressed: |
|
79 | 80 | case Stop: |
|
80 | 81 | { |
|
81 | 82 | if (qAbs(delta.x()) > m_moveThreshold || qAbs(delta.y()) > m_moveThreshold) { |
|
82 | 83 | m_state = Move; |
|
83 | 84 | m_timeStamp = QTime::currentTime(); |
|
84 | 85 | m_distance = QPointF(0, 0); |
|
85 | 86 | m_press = event->pos(); |
|
86 | 87 | event->accept(); |
|
87 | 88 | break; |
|
88 | 89 | } |
|
89 | 90 | else { |
|
90 | 91 | event->ignore(); |
|
91 | 92 | break; |
|
92 | 93 | } |
|
93 | 94 | } |
|
94 | 95 | case Move: |
|
95 | 96 | { |
|
96 | 97 | setOffset(m_offset - delta); |
|
97 | 98 | calculateSpeed(event->pos()); |
|
98 | 99 | event->accept(); |
|
99 | 100 | break; |
|
100 | 101 | } |
|
101 | 102 | case Idle: |
|
102 | 103 | case Scroll: |
|
103 | 104 | qWarning() << __FUNCTION__<<"Scroller unexpected state" << m_state; |
|
104 | 105 | event->ignore(); |
|
105 | 106 | break; |
|
106 | 107 | } |
|
107 | 108 | |
|
108 | 109 | } |
|
109 | 110 | |
|
110 | 111 | void Scroller::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) |
|
111 | 112 | { |
|
112 | 113 | if (event->button() == Qt::LeftButton) { |
|
113 | 114 | |
|
114 | 115 | switch (m_state) { |
|
115 | 116 | |
|
116 | 117 | case Scroll: |
|
117 | 118 | m_state = Stop; |
|
118 | 119 | m_speed = QPointF(0, 0); |
|
119 | 120 | m_offset = offset(); |
|
120 | 121 | event->accept(); |
|
121 | 122 | break; |
|
122 | 123 | case Pressed: |
|
123 | 124 | { |
|
124 | 125 | m_state = Idle; |
|
125 | 126 | //if (m_timeStamp.elapsed() < m_clickedPressDelay) { |
|
126 | 127 | |
|
127 | 128 | //emit clicked(m_offset.toPoint()); |
|
128 | 129 | //} |
|
129 | 130 | event->accept(); |
|
130 | 131 | break; |
|
131 | 132 | } |
|
132 | 133 | case Move: |
|
133 | 134 | { |
|
134 | 135 | calculateSpeed(event->pos()); |
|
135 | 136 | m_offset = offset(); |
|
136 | 137 | m_press = event->pos(); |
|
137 | 138 | if (m_speed == QPointF(0, 0)) { |
|
138 | 139 | m_state = Idle; |
|
139 | 140 | } |
|
140 | 141 | else { |
|
141 | 142 | m_speed /= 4; |
|
142 | 143 | m_state = Scroll; |
|
143 | 144 | m_ticker.start(20); |
|
144 | 145 | } |
|
145 | 146 | event->accept(); |
|
146 | 147 | break; |
|
147 | 148 | } |
|
148 | 149 | |
|
149 | 150 | case Stop: |
|
150 | 151 | case Idle: |
|
151 | 152 | qWarning() << __FUNCTION__<<"Scroller unexpected state" << m_state; |
|
152 | 153 | event->ignore(); |
|
153 | 154 | break; |
|
154 | 155 | |
|
155 | 156 | } |
|
156 | 157 | } |
|
157 | 158 | } |
|
158 | 159 | |
|
159 | 160 | void Scroller::scrollTick() |
|
160 | 161 | { |
|
161 | 162 | switch (m_state) { |
|
162 | 163 | case Scroll: |
|
163 | 164 | { |
|
164 | 165 | lowerSpeed(m_speed); |
|
165 | 166 | setOffset(m_offset - m_speed); |
|
166 | 167 | m_offset = offset(); |
|
167 | 168 | if (m_speed == QPointF(0, 0)) { |
|
168 | 169 | m_state = Idle; |
|
169 | 170 | m_ticker.stop(); |
|
170 | 171 | } |
|
171 | 172 | break; |
|
172 | 173 | } |
|
173 | 174 | case Stop: |
|
174 | 175 | m_ticker.stop(); |
|
175 | 176 | break; |
|
176 | 177 | case Idle: |
|
177 | 178 | case Move: |
|
178 | 179 | case Pressed: |
|
179 | 180 | qWarning() << __FUNCTION__<<"Scroller unexpected state" << m_state; |
|
180 | 181 | m_ticker.stop(); |
|
181 | 182 | break; |
|
182 | 183 | |
|
183 | 184 | } |
|
184 | 185 | } |
|
185 | 186 | |
|
186 | 187 | void Scroller::lowerSpeed(QPointF& speed, qreal maxSpeed) |
|
187 | 188 | { |
|
188 | 189 | qreal x = qBound(-maxSpeed, speed.x(), maxSpeed); |
|
189 | 190 | qreal y = qBound(-maxSpeed, speed.y(), maxSpeed); |
|
190 | 191 | |
|
191 | 192 | x = (x == 0) ? x : |
|
192 | 193 | (x > 0) ? qMax(qreal(0), x - m_fraction.x()) : qMin(qreal(0), x + m_fraction.x()); |
|
193 | 194 | y = (y == 0) ? y : |
|
194 | 195 | (y > 0) ? qMax(qreal(0), y - m_fraction.y()) : qMin(qreal(0), y + m_fraction.y()); |
|
195 | 196 | speed.setX(x); |
|
196 | 197 | speed.setY(y); |
|
197 | 198 | } |
|
198 | 199 | |
|
199 | 200 | void Scroller::calculateSpeed(const QPointF& position) |
|
200 | 201 | { |
|
201 | 202 | if (m_timeStamp.elapsed() > m_timeTreshold) { |
|
202 | 203 | |
|
203 | 204 | QPointF distance = position - m_press; |
|
204 | 205 | |
|
205 | 206 | m_timeStamp = QTime::currentTime(); |
|
206 | 207 | m_speed = distance - m_distance; |
|
207 | 208 | m_distance = distance; |
|
208 | 209 | |
|
209 | 210 | qreal fraction = qMax(qAbs(m_speed.x()), qAbs(m_speed.y())); |
|
210 | 211 | |
|
211 | 212 | if (fraction != 0) { |
|
212 | 213 | m_fraction.setX(qAbs(m_speed.x() / fraction)); |
|
213 | 214 | m_fraction.setY(qAbs(m_speed.y() / fraction)); |
|
214 | 215 | } |
|
215 | 216 | else { |
|
216 | 217 | m_fraction.setX(1); |
|
217 | 218 | m_fraction.setY(1); |
|
218 | 219 | } |
|
219 | 220 | } |
|
220 | 221 | } |
|
221 | 222 | |
|
222 | 223 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
223 | 224 | |
|
224 | 225 | ScrollTicker::ScrollTicker(Scroller *scroller,QObject* parent):QObject(parent), |
|
225 | 226 | m_scroller(scroller) |
|
226 | 227 | { |
|
227 | 228 | |
|
228 | 229 | } |
|
229 | 230 | |
|
230 | 231 | void ScrollTicker::start(int interval) |
|
231 | 232 | { |
|
232 | 233 | if (!m_timer.isActive()){ |
|
233 | 234 | m_timer.start(interval, this); |
|
234 | 235 | } |
|
235 | 236 | } |
|
236 | 237 | |
|
237 | 238 | void ScrollTicker::stop() |
|
238 | 239 | { |
|
239 | 240 | m_timer.stop(); |
|
240 | 241 | } |
|
241 | 242 | |
|
242 | 243 | void ScrollTicker::timerEvent(QTimerEvent *event) |
|
243 | 244 | { |
|
244 | 245 | Q_UNUSED(event); |
|
245 | 246 | m_scroller->scrollTick(); |
|
246 | 247 | } |
|
247 | 248 | |
|
248 | 249 | #include "moc_scroller_p.cpp" |
|
249 | 250 | |
|
250 | 251 | QTCOMMERCIALCHART_END_NAMESPACE |
@@ -1,167 +1,169 | |||
|
1 |
!include( ../co |
|
|
1 | !include( ../config.pri ):error( Couldn't find the config.pri file! ) | |
|
2 | 2 | TARGET = QtCommercialChart |
|
3 | 3 | DESTDIR = $$CHART_BUILD_LIB_DIR |
|
4 | 4 | TEMPLATE = lib |
|
5 | 5 | QT += core \ |
|
6 | 6 | gui |
|
7 | 7 | win32-msvc*: LIBS += User32.lib |
|
8 | 8 | CONFIG += debug_and_release |
|
9 | 9 | CONFIG(debug, debug|release):TARGET = QtCommercialChartd |
|
10 | 10 | SOURCES += \ |
|
11 | 11 | $$PWD/chartdataset.cpp \ |
|
12 | 12 | $$PWD/chartpresenter.cpp \ |
|
13 | 13 | $$PWD/charttheme.cpp \ |
|
14 | 14 | $$PWD/domain.cpp \ |
|
15 | 15 | $$PWD/qchart.cpp \ |
|
16 | 16 | $$PWD/qchartview.cpp \ |
|
17 | 17 | $$PWD/qabstractseries.cpp \ |
|
18 | 18 | $$PWD/chartbackground.cpp \ |
|
19 | 19 | $$PWD/chart.cpp \ |
|
20 | 20 | $$PWD/scroller.cpp |
|
21 | 21 | PRIVATE_HEADERS += \ |
|
22 | 22 | $$PWD/chartdataset_p.h \ |
|
23 | 23 | $$PWD/chartitem_p.h \ |
|
24 | 24 | $$PWD/chartpresenter_p.h \ |
|
25 | 25 | $$PWD/charttheme_p.h \ |
|
26 | 26 | $$PWD/domain_p.h \ |
|
27 | 27 | $$PWD/chartbackground_p.h \ |
|
28 | 28 | $$PWD/chart_p.h \ |
|
29 | 29 | $$PWD/chartconfig_p.h \ |
|
30 | 30 | $$PWD/qchart_p.h \ |
|
31 | 31 | $$PWD/qchartview_p.h \ |
|
32 | 32 | $$PWD/scroller_p.h \ |
|
33 | 33 | $$PWD/qabstractseries_p.h |
|
34 | 34 | PUBLIC_HEADERS += \ |
|
35 | 35 | $$PWD/qchart.h \ |
|
36 | 36 | $$PWD/qchartglobal.h \ |
|
37 | 37 | $$PWD/qabstractseries.h \ |
|
38 | 38 | $$PWD/qchartview.h |
|
39 | 39 | |
|
40 | 40 | include(animations/animations.pri) |
|
41 | 41 | include(areachart/areachart.pri) |
|
42 | 42 | include(axis/axis.pri) |
|
43 | 43 | include(barchart/barchart.pri) |
|
44 | 44 | include(legend/legend.pri) |
|
45 | 45 | include(linechart/linechart.pri) |
|
46 | 46 | include(piechart/piechart.pri) |
|
47 | 47 | include(scatterseries/scatter.pri) |
|
48 | 48 | include(splinechart/splinechart.pri) |
|
49 | 49 | include(themes/themes.pri) |
|
50 | 50 | include(xychart/xychart.pri) |
|
51 | 51 | |
|
52 | 52 | HEADERS += $$PUBLIC_HEADERS |
|
53 | 53 | HEADERS += $$PRIVATE_HEADERS |
|
54 | 54 | HEADERS += $$THEMES |
|
55 | 55 | INCLUDEPATH += ../include . |
|
56 | 56 | |
|
57 | 57 | OBJECTS_DIR = $$CHART_BUILD_DIR/lib |
|
58 | 58 | MOC_DIR = $$CHART_BUILD_DIR/lib |
|
59 | 59 | UI_DIR = $$CHART_BUILD_DIR/lib |
|
60 | 60 | RCC_DIR = $$CHART_BUILD_DIR/lib |
|
61 | 61 | DEFINES += QTCOMMERCIALCHART_LIBRARY |
|
62 | 62 | |
|
63 | 63 | #qt public headers |
|
64 | 64 | #this is very primitive and lame parser , TODO: make perl script insted |
|
65 | 65 | !exists($$CHART_BUILD_PUBLIC_HEADER_DIR/QChartGlobal) |
|
66 | 66 | { |
|
67 | 67 | system($$QMAKE_MKDIR $$CHART_BUILD_PUBLIC_HEADER_DIR) |
|
68 | 68 | win32:{ |
|
69 | 69 | command = "echo $${LITERAL_HASH}include \"qchartglobal.h\" > $$CHART_BUILD_PUBLIC_HEADER_DIR/QChartGlobal" |
|
70 | 70 | }else{ |
|
71 | 71 | command = "echo \"$${LITERAL_HASH}include \\\"qchartglobal.h\\\"\" > $$CHART_BUILD_PUBLIC_HEADER_DIR/QChartGlobal" |
|
72 | 72 | } |
|
73 | PUBLIC_QT_HEADERS += $$CHART_BUILD_PUBLIC_HEADER_DIR/QChartGlobal | |
|
73 | 74 | system($$command) |
|
74 | 75 | } |
|
75 | 76 | |
|
76 | 77 | for(file, PUBLIC_HEADERS) { |
|
77 | 78 | name = $$split(file,'/') |
|
78 | 79 | name = $$last(name) |
|
79 | 80 | class = "$$cat($$file)" |
|
80 | 81 | class = $$find(class,class) |
|
81 | 82 | !isEmpty(class){ |
|
82 | 83 | class = $$split(class,QTCOMMERCIALCHART_EXPORT) |
|
83 | 84 | class = $$member(class,1) |
|
84 | 85 | class = $$split(class,' ') |
|
85 | 86 | class = $$replace(class,' ','') |
|
86 | 87 | class = $$member(class,0) |
|
87 | 88 | win32:{ |
|
88 | 89 | command = "echo $${LITERAL_HASH}include \"$$name\" > $$CHART_BUILD_PUBLIC_HEADER_DIR/$$class" |
|
89 | 90 | }else{ |
|
90 | 91 | command = "echo \"$${LITERAL_HASH}include \\\"$$name\\\"\" > $$CHART_BUILD_PUBLIC_HEADER_DIR/$$class" |
|
91 | 92 | } |
|
92 | 93 | PUBLIC_QT_HEADERS += $$CHART_BUILD_PUBLIC_HEADER_DIR/$$class |
|
93 | 94 | system($$command) |
|
94 | 95 | } |
|
95 | 96 | } |
|
96 | 97 | |
|
97 | 98 | public_headers.path = $$[QT_INSTALL_HEADERS]/QtCommercialChart |
|
98 | 99 | public_headers.files = $$PUBLIC_HEADERS $$PUBLIC_QT_HEADERS |
|
99 | 100 | |
|
100 | 101 | target.path = $$[QT_INSTALL_LIBS] |
|
101 | 102 | INSTALLS += target public_headers |
|
102 | 103 | |
|
103 | 104 | install_build_public_headers.name = build_public_headers |
|
104 | 105 | install_build_public_headers.output = $$CHART_BUILD_PUBLIC_HEADER_DIR/${QMAKE_FILE_BASE}.h |
|
105 | 106 | install_build_public_headers.input = PUBLIC_HEADERS |
|
106 | 107 | install_build_public_headers.commands = $$QMAKE_COPY \ |
|
107 | 108 | ${QMAKE_FILE_NAME} \ |
|
108 | 109 | $$CHART_BUILD_PUBLIC_HEADER_DIR |
|
109 | 110 | install_build_public_headers.CONFIG += target_predeps \ |
|
110 | 111 | no_link |
|
111 | 112 | |
|
112 | 113 | install_build_private_headers.name = buld_private_headers |
|
113 | 114 | install_build_private_headers.output = $$CHART_BUILD_PRIVATE_HEADER_DIR/${QMAKE_FILE_BASE}.h |
|
114 | 115 | install_build_private_headers.input = PRIVATE_HEADERS |
|
115 | 116 | install_build_private_headers.commands = $$QMAKE_COPY \ |
|
116 | 117 | ${QMAKE_FILE_NAME} \ |
|
117 | 118 | $$CHART_BUILD_PRIVATE_HEADER_DIR |
|
118 | 119 | install_build_private_headers.CONFIG += target_predeps \ |
|
119 | 120 | no_link |
|
120 | 121 | |
|
121 | 122 | QMAKE_EXTRA_COMPILERS += install_build_public_headers \ |
|
122 | 123 | install_build_private_headers \ |
|
123 | 124 | |
|
125 | # There is a problem with jom.exe currently. It does not seem to understand QMAKE_EXTRA_TARGETS properly. | |
|
126 | # This is the case at least with shadow builds. | |
|
127 | # http://qt-project.org/wiki/jom | |
|
124 | 128 | |
|
125 |
!win32-msvc*: |
|
|
126 | ||
|
127 | # There is a problem with jom.exe currently. It does not seem to understand QMAKE_EXTRA_TARGETS properly. | |
|
128 | # This is the case at least with shadow builds. | |
|
129 | # http://qt-project.org/wiki/jom | |
|
130 | ||
|
129 | developer_build:!win32-msvc*:{ | |
|
131 | 130 | chartversion.target = $$PWD/qchartversion_p.h |
|
132 | 131 | |
|
133 | 132 | unix:{ |
|
134 | 133 | chartversion.commands = @echo \ |
|
135 | "const char *buildTime = \\\"`date +'%y%m%d%H%M'`\\\" \\; \ | |
|
136 | const char *gitHead = \\\"`git rev-parse HEAD`\\\" \\; " \ | |
|
134 | \" $${LITERAL_HASH}ifndef QCHARTVERSION_P_H\\n\ | |
|
135 | $${LITERAL_HASH}define QCHARTVERSION_P_H\\n\ | |
|
136 | const char *buildTime = \\\"`date +'%y%m%d%H%M'`\\\" ; \\n\ | |
|
137 | const char *gitHead = \\\"`git rev-parse HEAD`\\\" ; \\n \ | |
|
138 | $${LITERAL_HASH}endif \" \ | |
|
137 | 139 | > \ |
|
138 | 140 | $$chartversion.target; |
|
139 | 141 | }else{ |
|
140 | 142 | chartversion.commands = @echo \ |
|
141 | 143 | "const char *buildTime = \"%date%_%time%\" ; \ |
|
142 | 144 | const char *gitHead = \"unknown\" ; " \ |
|
143 | 145 | > \ |
|
144 | 146 | $$chartversion.target |
|
145 | 147 | } |
|
146 | 148 | |
|
147 | 149 | chartversion.depends = $$HEADERS \ |
|
148 | 150 | $$SOURCES |
|
149 | 151 | |
|
150 |
PRE_TARGETDEPS += $$ |
|
|
152 | PRE_TARGETDEPS += $$chartversion.target | |
|
151 | 153 | QMAKE_CLEAN += $$PWD/qchartversion_p.h |
|
152 | 154 | QMAKE_EXTRA_TARGETS += chartversion |
|
153 | 155 | } |
|
154 | 156 | |
|
155 | 157 | unix:QMAKE_DISTCLEAN += -r \ |
|
156 | 158 | $$CHART_BUILD_HEADER_DIR \ |
|
157 | 159 | $$CHART_BUILD_LIB_DIR |
|
158 | 160 | win32:QMAKE_DISTCLEAN += /Q \ |
|
159 | 161 | $$CHART_BUILD_HEADER_DIR \ |
|
160 | 162 | $$CHART_BUILD_LIB_DIR |
|
161 | 163 | |
|
162 | 164 | # treat warnings as errors |
|
163 | 165 | win32-msvc*: { |
|
164 | 166 | QMAKE_CXXFLAGS += /WX |
|
165 | 167 | } else { |
|
166 | 168 | QMAKE_CXXFLAGS += -Werror |
|
167 | 169 | } |
@@ -1,17 +1,6 | |||
|
1 |
!include( ../ |
|
|
2 |
error( "Couldn't find the |
|
|
3 | } | |
|
4 | !include( ../../integrated.pri ) { | |
|
5 | error( "Couldn't find the integrated.pri file !") | |
|
1 | !include( ../test.pri ) { | |
|
2 | error( "Couldn't find the test.pri file!" ) | |
|
6 | 3 | } |
|
7 | 4 | |
|
8 | TEMPLATE = app | |
|
9 | 5 | CONFIG += qtestlib |
|
10 | ||
|
11 | DESTDIR = $$CHART_BUILD_BIN_DIR/test | |
|
12 | OBJECTS_DIR = $$CHART_BUILD_DIR/test/$$TARGET | |
|
13 | MOC_DIR = $$CHART_BUILD_DIR/test/$$TARGET | |
|
14 | UI_DIR = $$CHART_BUILD_DIR/test/$$TARGET | |
|
15 | RCC_DIR = $$CHART_BUILD_DIR/test/$$TARGET | |
|
16 | ||
|
17 | 6 | !contains(TARGET, ^tst_.*):TARGET = $$join(TARGET,,"tst_") |
@@ -1,243 +1,244 | |||
|
1 | 1 | /**************************************************************************** |
|
2 | 2 | ** |
|
3 | 3 | ** Copyright (C) 2012 Digia Plc |
|
4 | 4 | ** All rights reserved. |
|
5 | 5 | ** For any questions to Digia, please use contact form at http://qt.digia.com |
|
6 | 6 | ** |
|
7 | 7 | ** This file is part of the Qt Commercial Charts Add-on. |
|
8 | 8 | ** |
|
9 | 9 | ** $QT_BEGIN_LICENSE$ |
|
10 | 10 | ** Licensees holding valid Qt Commercial licenses may use this file in |
|
11 | 11 | ** accordance with the Qt Commercial License Agreement provided with the |
|
12 | 12 | ** Software or, alternatively, in accordance with the terms contained in |
|
13 | 13 | ** a written agreement between you and Digia. |
|
14 | 14 | ** |
|
15 | 15 | ** If you have questions regarding the use of this file, please use |
|
16 | 16 | ** contact form at http://qt.digia.com |
|
17 | 17 | ** $QT_END_LICENSE$ |
|
18 | 18 | ** |
|
19 | 19 | ****************************************************************************/ |
|
20 | 20 | |
|
21 | 21 | #include "widget.h" |
|
22 | 22 | |
|
23 | 23 | #include <QChart> |
|
24 | 24 | #include <QScatterSeries> |
|
25 | 25 | #include <QChartAxis> |
|
26 | 26 | #include <QBarSet> |
|
27 | 27 | #include <QBarSeries> |
|
28 | 28 | #include <QLegend> |
|
29 | 29 | |
|
30 | 30 | #include <QGridLayout> |
|
31 | 31 | #include <QPushButton> |
|
32 | 32 | #include <QLabel> |
|
33 | 33 | #include <QListWidget> |
|
34 | 34 | #include <QPrinter> |
|
35 | 35 | #include <QPrintDialog> |
|
36 | 36 | #include <QRadioButton> |
|
37 | 37 | #include <QStringList> |
|
38 | 38 | #include <QSqlQuery> |
|
39 | #include <QDebug> | |
|
39 | 40 | |
|
40 | 41 | QTCOMMERCIALCHART_USE_NAMESPACE |
|
41 | 42 | |
|
42 | 43 | Widget::Widget(QWidget *parent) |
|
43 | 44 | : QWidget(parent) |
|
44 | 45 | { |
|
45 | 46 | setGeometry(100, 100, 1000, 600); |
|
46 | 47 | |
|
47 | 48 | // right panel layout |
|
48 | 49 | barChartRadioButton = new QRadioButton(tr("Bar chart")); |
|
49 | 50 | barChartRadioButton->setChecked(true); |
|
50 | 51 | scatterChartRadioButton = new QRadioButton(tr("Scatter chart")); |
|
51 | 52 | scatterChartRadioButton->setChecked(false); |
|
52 | 53 | countrieslist = new QListWidget; |
|
53 | 54 | countrieslist->setSelectionMode(QAbstractItemView::MultiSelection); |
|
54 | 55 | |
|
55 | 56 | //list of years widget |
|
56 | 57 | yearslist = new QListWidget; |
|
57 | 58 | yearslist->setSelectionMode(QAbstractItemView::ExtendedSelection); |
|
58 | 59 | for (int i = 1990; i < 2011; i++) |
|
59 | 60 | yearslist->addItem(QString("%1").arg(i)); |
|
60 | 61 | |
|
61 | 62 | QPushButton* refreshButton = new QPushButton(tr("Refresh")); |
|
62 | 63 | connect(refreshButton, SIGNAL(clicked()), this, SLOT(refreshChart())); |
|
63 | 64 | |
|
64 | 65 | QPushButton* printButton = new QPushButton(tr("Print to pdf")); |
|
65 | 66 | connect(printButton, SIGNAL(clicked()), this, SLOT(printChart())); |
|
66 | 67 | |
|
67 | 68 | QVBoxLayout* rightPanelLayout = new QVBoxLayout; |
|
68 | 69 | rightPanelLayout->addWidget(barChartRadioButton); |
|
69 | 70 | rightPanelLayout->addWidget(scatterChartRadioButton); |
|
70 | 71 | rightPanelLayout->addWidget(countrieslist); |
|
71 | 72 | rightPanelLayout->addWidget(yearslist); |
|
72 | 73 | rightPanelLayout->addWidget(refreshButton); |
|
73 | 74 | rightPanelLayout->addWidget(printButton); |
|
74 | 75 | rightPanelLayout->setStretch(0, 1); |
|
75 | 76 | rightPanelLayout->setStretch(1, 0); |
|
76 | 77 | |
|
77 | 78 | QChart *chart = new QChart(); |
|
78 | 79 | chart->setTitle("GDP by country"); |
|
79 | 80 | chart->legend()->setVisible(true); |
|
80 | 81 | |
|
81 | 82 | // main layout |
|
82 | 83 | chartView = new QChartView(chart); |
|
83 | 84 | QGridLayout* mainLayout = new QGridLayout; |
|
84 | 85 | mainLayout->addWidget(chartView, 0, 0); |
|
85 | 86 | mainLayout->addLayout(rightPanelLayout, 0, 1); |
|
86 | 87 | mainLayout->setColumnStretch(0,1); |
|
87 | 88 | setLayout(mainLayout); |
|
88 | 89 | |
|
89 | 90 | // connect to the database |
|
90 | 91 | db = QSqlDatabase::addDatabase("QSQLITE"); |
|
91 | 92 | db.setDatabaseName("gdpData"); |
|
92 | 93 | if(!db.open()) |
|
93 | 94 | { |
|
94 | 95 | qDebug() << "could not open database. SQLite db file missing (?)"; |
|
95 | 96 | return; |
|
96 | 97 | } |
|
97 | 98 | |
|
98 | 99 | // get the list of all countires and regions. |
|
99 | 100 | QSqlQuery query; |
|
100 | 101 | query.exec("SELECT DISTINCT country FROM gdp2"); |
|
101 | 102 | |
|
102 | 103 | // add the countries to the country filter |
|
103 | 104 | while (query.next()) { |
|
104 | 105 | countrieslist->addItem(query.value(0).toString()); |
|
105 | 106 | } |
|
106 | 107 | } |
|
107 | 108 | |
|
108 | 109 | Widget::~Widget() |
|
109 | 110 | { |
|
110 | 111 | // |
|
111 | 112 | db.close(); |
|
112 | 113 | } |
|
113 | 114 | |
|
114 | 115 | /*! |
|
115 | 116 | refreshes the chart |
|
116 | 117 | */ |
|
117 | 118 | void Widget::refreshChart() |
|
118 | 119 | { |
|
119 | 120 | chartView->chart()->removeAllSeries(); |
|
120 | 121 | |
|
121 | 122 | // selected countries items list is not sorted. copy the values to QStringlist and sort them. |
|
122 | 123 | QStringList selectedCountriesStrings; |
|
123 | 124 | QList<QListWidgetItem*> selectedCountriesItems = countrieslist->selectedItems(); |
|
124 | 125 | for (int i = 0; i < selectedCountriesItems.size(); i++) |
|
125 | 126 | selectedCountriesStrings.append(selectedCountriesItems[i]->text()); |
|
126 | 127 | selectedCountriesStrings.sort(); |
|
127 | 128 | |
|
128 | 129 | QSqlQuery query; |
|
129 | 130 | // selected years items list is not sorted. copy the values to QList<int> and sort them. |
|
130 | 131 | QList<int> selectedYearsInts; |
|
131 | 132 | QList<QListWidgetItem*> selectedYearsItems = yearslist->selectedItems(); |
|
132 | 133 | for (int i = 0; i < selectedYearsItems.size(); i++) |
|
133 | 134 | selectedYearsInts.append(selectedYearsItems[i]->text().toInt()); |
|
134 | 135 | qSort(selectedYearsInts.begin(), selectedYearsInts.end()); |
|
135 | 136 | |
|
136 | 137 | if (barChartRadioButton->isChecked()) |
|
137 | 138 | { |
|
138 | 139 | // use the sorted selected coutries list to initialize BarCategory |
|
139 | 140 | QStringList category; |
|
140 | 141 | for (int i = 0; i < selectedCountriesStrings.size(); i++) |
|
141 | 142 | category << selectedCountriesStrings[i]; |
|
142 | 143 | QBarSeries* series0 = new QBarSeries(category); |
|
143 | 144 | series0 = new QBarSeries(category); |
|
144 | 145 | |
|
145 | 146 | // prepare the selected counries SQL query |
|
146 | 147 | QString countriesQuery = "country IN ("; |
|
147 | 148 | for (int i = 0; i < selectedCountriesStrings.size(); i++) |
|
148 | 149 | { |
|
149 | 150 | countriesQuery.append("'" + selectedCountriesStrings[i] + "'"); |
|
150 | 151 | if ( i < selectedCountriesStrings.size() - 1) |
|
151 | 152 | countriesQuery.append(","); |
|
152 | 153 | else |
|
153 | 154 | countriesQuery.append(")"); |
|
154 | 155 | } |
|
155 | 156 | |
|
156 | 157 | // perform a query for each selected year |
|
157 | 158 | for (int i = 0; i < selectedYearsInts.size(); i++) |
|
158 | 159 | { |
|
159 | 160 | query.exec("SELECT country,gdpvalue FROM gdp2 where year=" + QString("%1").arg(selectedYearsInts[i]) + " AND " + countriesQuery); |
|
160 | 161 | QBarSet* barSet = new QBarSet(QString::number(selectedYearsInts[i])); |
|
161 | 162 | |
|
162 | 163 | // while (query.next()) { |
|
163 | 164 | // qDebug() << query.value(0).toString() << " : " << query.value(1).toString(); |
|
164 | 165 | // } |
|
165 | 166 | query.first(); |
|
166 | 167 | |
|
167 | 168 | // the data for some of the coutries for some years might be missing. |
|
168 | 169 | // QBarChart needs bars to have same size |
|
169 | 170 | for (int k = 0; k < selectedCountriesStrings.size(); k++) |
|
170 | 171 | { |
|
171 | 172 | if (selectedCountriesStrings[k] == query.value(0).toString()) |
|
172 | 173 | { |
|
173 | 174 | *barSet << query.value(1).toReal(); |
|
174 | 175 | qDebug() << query.value(0).toString() << query.value(1).toReal() << " : " << QString("%1").arg(selectedYearsInts[i]); |
|
175 | 176 | query.next(); |
|
176 | 177 | } |
|
177 | 178 | else |
|
178 | 179 | { |
|
179 | 180 | // data missing, put 0 |
|
180 | 181 | *barSet << 0.0f; |
|
181 | 182 | qDebug() << "Putting 0 for the missing data" << " : " << QString("%1").arg(selectedYearsInts[i]); |
|
182 | 183 | } |
|
183 | 184 | } |
|
184 | 185 | series0->appendBarSet(barSet); |
|
185 | 186 | } |
|
186 | 187 | // add the serie to the chart |
|
187 | 188 | chartView->chart()->addSeries(series0); |
|
188 | 189 | } |
|
189 | 190 | else if (scatterChartRadioButton->isChecked()) |
|
190 | 191 | { |
|
191 | 192 | QString yearsQuery = "year IN ("; |
|
192 | 193 | for (int i = 0; i < selectedYearsInts.size(); i++) |
|
193 | 194 | { |
|
194 | 195 | yearsQuery.append("'" + QString("%1").arg(selectedYearsInts[i]) + "'"); |
|
195 | 196 | if ( i < selectedYearsInts.size() - 1) |
|
196 | 197 | yearsQuery.append(","); |
|
197 | 198 | else |
|
198 | 199 | yearsQuery.append(")"); |
|
199 | 200 | } |
|
200 | 201 | |
|
201 | 202 | // perform a query for each selected country |
|
202 | 203 | for (int i = 0; i < selectedCountriesStrings.size(); i++) |
|
203 | 204 | { |
|
204 | 205 | query.exec("SELECT year,gdpvalue FROM gdp2 where country='" + selectedCountriesStrings[i] + "' AND " + yearsQuery); |
|
205 | 206 | query.first(); |
|
206 | 207 | |
|
207 | 208 | QScatterSeries* series = new QScatterSeries; |
|
208 | 209 | series->setName(selectedCountriesStrings[i]); |
|
209 | 210 | // the data for some of the coutries for some years might be missing. |
|
210 | 211 | for (int k = 0; k < selectedYearsInts.size(); k++) |
|
211 | 212 | { |
|
212 | 213 | if (selectedYearsInts[k] == query.value(0).toInt()) |
|
213 | 214 | { |
|
214 | 215 | *series << QPointF(query.value(0).toInt() , query.value(1).toReal()); |
|
215 | 216 | qDebug() << query.value(0).toString() << query.value(1).toReal() << " : " << QString("%1").arg(selectedYearsInts[k]); |
|
216 | 217 | query.next(); |
|
217 | 218 | } |
|
218 | 219 | else |
|
219 | 220 | { |
|
220 | 221 | // data missing, put 0 |
|
221 | 222 | *series << QPointF(selectedYearsInts[k] , 0.0f); |
|
222 | 223 | qDebug() << "Putting 0 for the missing data" << " : " << QString("%1").arg(selectedYearsInts[i]) << " " << query.value(0).toInt(); |
|
223 | 224 | } |
|
224 | 225 | } |
|
225 | 226 | // chartArea->axisX()->setRange(selectedYearsInts[selectedYearsInts.size() - 1] + 1, selectedYearsInts[0] - 1); |
|
226 | 227 | chartView->chart()->addSeries(series); |
|
227 | 228 | } |
|
228 | 229 | chartView->chart()->axisX()->setRange(selectedYearsInts[selectedYearsInts.size() - 1] - 1, selectedYearsInts[0] + 1); |
|
229 | 230 | } |
|
230 | 231 | } |
|
231 | 232 | |
|
232 | 233 | void Widget::printChart() |
|
233 | 234 | { |
|
234 | 235 | QPrinter printer; |
|
235 | 236 | // QPrinter printer(QPrinter::HighResolution); |
|
236 | 237 | printer.setOutputFormat(QPrinter::PdfFormat); |
|
237 | 238 | printer.setOrientation(QPrinter::Landscape); |
|
238 | 239 | printer.setOutputFileName("print.pdf"); |
|
239 | 240 | |
|
240 | 241 | QPainter painter; |
|
241 | 242 | painter.begin(&printer); |
|
242 | 243 | chartView->render(&painter); |
|
243 | 244 | } |
@@ -1,14 +1,14 | |||
|
1 |
!include( ../co |
|
|
2 |
error( "Couldn't find the co |
|
|
1 | !include( ../config.pri ) { | |
|
2 | error( "Couldn't find the config.pri file!" ) | |
|
3 | 3 | } |
|
4 |
!include( ../ |
|
|
5 |
error( "Couldn't find the |
|
|
4 | !include( ../build.pri ) { | |
|
5 | error( "Couldn't find the build.pri file !") | |
|
6 | 6 | } |
|
7 | 7 | |
|
8 | 8 | TEMPLATE = app |
|
9 | 9 | |
|
10 | 10 | DESTDIR = $$CHART_BUILD_BIN_DIR/test |
|
11 | 11 | OBJECTS_DIR = $$CHART_BUILD_DIR/test/$$TARGET |
|
12 | 12 | MOC_DIR = $$CHART_BUILD_DIR/test/$$TARGET |
|
13 | 13 | UI_DIR = $$CHART_BUILD_DIR/test/$$TARGET |
|
14 | 14 | RCC_DIR = $$CHART_BUILD_DIR/test/$$TARGET |
General Comments 0
You need to be logged in to leave comments.
Login now