##// END OF EJS Templates
Improves build configuration...
Michal Klocek -
r996:ce5f1c868418
parent child
Show More
@@ -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(common.pri) {
2 error('missing common.pri')
1 !include(config.pri) {
2 error('Missing config.pri')
3 3 }
4 4
5 5 TEMPLATE = subdirs
6 SUBDIRS += src qmlplugin examples demos test
6 SUBDIRS = src qmlplugin examples demos test
7 7
8 integrated_build:{
9 message('Configured for integrated build against local libs...')
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( ../common.pri ) {
2 error( "Couldn't find the common.pri file!" )
1 !include( ../config.pri ) {
2 error( "Couldn't find the config.pri file!" )
3 3 }
4 4
5 !include( ../integrated.pri ) {
6 error( "Couldn't find the integrated.pri file !")
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( ../common.pri ) {
2 error( "Couldn't find the common.pri file!" )
1 !include( ../config.pri ) {
2 error( "Couldn't find the config.pri file!" )
3 3 }
4 4
5 !include( ../integrated.pri ) {
6 error( "Couldn't find the integrated.pri file !")
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( ../common.pri ) {
6 !include( ../config.pri ) {
7 7 error( "Couldn't find the common.pri file!" )
8 8 }
9 !include( ../integrated.pri ) {
10 error( "Couldn't find the integrated.pri file !")
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 qDebug()<<"Unknown axis type";
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, &centerAngle, &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( ../common.pri ):error( Couldn't find the common.pri file! )
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 += $$PWD/qchartversion_p.h
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( ../../common.pri ) {
2 error( "Couldn't find the common.pri file!" )
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( ../common.pri ) {
2 error( "Couldn't find the common.pri file!" )
1 !include( ../config.pri ) {
2 error( "Couldn't find the config.pri file!" )
3 3 }
4 !include( ../integrated.pri ) {
5 error( "Couldn't find the integrated.pri file !")
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