From 05d1d227ed47ef4e4b3ccdf1c4fd65cc00dc3b1f 2012-02-22 08:31:15 From: Marek Rosa Date: 2012-02-22 08:31:15 Subject: [PATCH] Merge branch 'master' of https://git.it.local/repos/QtCommercialDevel-13049/charts --- diff --git a/common.pri b/common.pri index a37e6ba..97d8da7 100644 --- a/common.pri +++ b/common.pri @@ -5,6 +5,7 @@ CHART_BUILD_PRIVATE_HEADER_DIR = $$CHART_BUILD_PUBLIC_HEADER_DIR/private CHART_BUILD_LIB_DIR = $$PWD/lib CHART_BUILD_DIR = $$PWD/build CHART_BUILD_BIN_DIR = $$PWD/bin +CHART_BUILD_PLUGIN_DIR = $$CHART_BUILD_LIB_DIR/QtCommercial/Chart # hack to fix windows builds win32:{ @@ -13,6 +14,7 @@ win32:{ CHART_BUILD_LIB_DIR = $$replace(CHART_BUILD_LIB_DIR, "/","\\") CHART_BUILD_BUILD_DIR = $$replace(CHART_BUILD_BUILD_DIR, "/","\\") CHART_BUILD_BIN_DIR = $$replace(CHART_BUILD_BIN_DIR, "/","\\") + CHART_BUILD_PLUGIN_DIR = $$replace(CHART_BUILD_PLUGIN_DIR, "/","\\") } mac: { diff --git a/doc/images/scatter_example1.jpg b/doc/images/scatter_example1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3e95f07c821e092a4a6bac0715971dbc602898c1 GIT binary patch literal 11172 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 literal 0 Hc$@^lOiET&UP@Y7ModgWM?qOlT~kX_QeM|USHnP6LsJ7}2qQZ?I~NC+Fc+7w zhLo6;2Fc+60R}-126YBCW=16jCP7AKLB{__7^D~&n3$LukO9!Oj7;o6Ib8t;CPrpv zCKeWUs1zemDT^Shq9L1*uw!7MsM5lVDn^No8xMX2DwkwrU}gk)91fU)CNVGpr4$8$ zwlJ~+Al_yW!n=?|HY`RPy^*X~(3WII=$8I3~+zW6G|dJv*1iZQ4F7V6BvKkDU3Z71yJB zFYcPq+3_}sjo~)i%#xeFS9|g`SSA?%dOOQncm`u=O~>KMb68jHbKl7AvU$!OjSLm$ zy_G?l+XLJE-nq`b;T>s6n0Y+q`jxp$9cIT?tL?Te iKC;bp@uL0D18#hkT-3G9^}DtJKU=y^lOiET&UP@Y7ModgWM?qOlT~kX_QeM|USHnP6LsJ7}2qQZ?I~NC+Fc+7w zhLo6;2Fc+60R}-125kmiW=16jCP7AKLB{__7^D~&n3zGXg#$)51{PL!W}uv@00R>v zGczMIJ1YYrmlY&{X_rQoOkcuem%{-J9X=vQxkR{lb6}XA#u>=vsZq8THlG^ zqEn_S>|_zV$8REQ*OnD@Js|#G^s6N8?6xkuqtO|mHq#R4Ierk~F+MfHQRULyjmMVW zcx=Ita>+gL)wD@jPAQc-toJvKgq*EYw?__hL1~o zi$XjWhN%eslo39_{zyZjD(M&N6}HC;Z-ujjr5QYxWge}Ht$cd_`RVtw)-Q}btopPk zazFK~4%eFL~Yagbmt4xtJ;SMYnTl7&`FvFaou5aZ{GzwV)0$=a>MB31 ko*TuVpHg@r((-T6hL^t@ogIJO;=lWDR{mM$pyvNK0sEceasU7T literal 0 Hc$@\n" +sources.fileextensions = *.cpp *.qdoc *.mm *.qml +headers.fileextensions = *.h *.ch *.h++ *.hh *.hpp *.hxx +examples.fileextensions = *.cpp *.h *.js *.xq *.svg *.xml *.ui *.qhp *.qhcp *.qml +examples.imageextensions = *.png *.jpeg *.jpg *.gif *.mng +imagedirs = ./images +outputdir = ./html + +Cpp.ignoretokens = QTCOMMERCIALCHART_EXPORT \ + QTCOMMERCIALCHART_END_NAMESPACE \ + QTCOMMERCIALCHART_BEGIN_NAMESPACE +Cpp.ignoredirectives = Q_DECLARE_HANDLE \ + Q_DECLARE_INTERFACE \ + Q_DECLARE_METATYPE \ + Q_DECLARE_OPERATORS_FOR_FLAGS \ + Q_DECLARE_PRIVATE \ + Q_DECLARE_PUBLIC \ + Q_DECLARE_SHARED \ + Q_DECLARE_TR_FUNCTIONS \ + Q_DECLARE_TYPEINFO \ + Q_DISABLE_COPY \ + QT_FORWARD_DECLARE_CLASS \ + Q_DUMMY_COMPARISON_OPERATOR \ + Q_ENUMS \ + Q_FLAGS \ + Q_INTERFACES \ + __attribute__ \ No newline at end of file diff --git a/doc/style/offline.css b/doc/style/offline.css new file mode 100644 index 0000000..3689ee8 --- /dev/null +++ b/doc/style/offline.css @@ -0,0 +1,673 @@ +@media screen +{ + +/* basic elements */ + html + { + color: #000000; + background: #FFFFFF; + } + table + { + border-collapse: collapse; + border-spacing: 0; + } + fieldset, img + { + border: 0; + max-width:100%; + } + address, caption, cite, code, dfn, em, strong, th, var, optgroup + { + font-style: inherit; + font-weight: inherit; + } + del, ins + { + text-decoration: none; + } + li + { + list-style: none; + } + ol li + { + list-style: decimal; + } + caption, th + { + text-align: left; + } + h1, h2, h3, h4, h5, h6 + { + font-size: 100%; + } + q:before, q:after + { + content: ''; + } + abbr, acronym + { + border: 0; + font-variant: normal; + } + sup, sub + { + vertical-align: baseline; + } + tt, .qmlreadonly span, .qmldefault span + { + word-spacing:0.5em; + } + legend + { + color: #000000; + } + strong + { + font-weight: bold; + } + em + { + font-style: italic; + } + + body + { + margin-left: 0.5em; + margin-right: 0.5em; + } + a + { + color: #00732F; + text-decoration: none; + } + hr + { + background-color: #E6E6E6; + border: 1px solid #E6E6E6; + height: 1px; + width: 100%; + text-align: left; + margin: 1.5em 0 1.5em 0; + } + + pre + { + border: 1px solid #DDDDDD; + -moz-border-radius: 0.7em 0.7em 0.7em 0.7em; + -webkit-border-radius: 0.7em 0.7em 0.7em 0.7em; + border-radius: 0.7em 0.7em 0.7em 0.7em; + margin: 0 1.5em 1em 1em; + padding: 1em 1em 1em 1em; + overflow-x: auto; + } + table, pre + { + -moz-border-radius: 0.7em 0.7em 0.7em 0.7em; + -webkit-border-radius: 0.7em 0.7em 0.7em 0.7em; + border-radius: 0.7em 0.7em 0.7em 0.7em; + background-color: #F6F6F6; + border: 1px solid #E6E6E6; + border-collapse: separate; + margin-bottom: 2.5em; + } + pre { + font-size: 90%; + display: block; + overflow:hidden; + } + thead + { + margin-top: 0.5em; + font-weight: bold + } + th + { + padding: 0.5em 1.5em 0.5em 1.5em; + background-color: #E1E1E1; + border-left: 1px solid #E6E6E6; + } + td + { + padding: 0.25em 1.5em 0.25em 2em; + } + + td.rightAlign + { + padding: 0.25em 0.5em 0.25em 1em; + } + table tr.odd + { + border-left: 1px solid #E6E6E6; + background-color: #F6F6F6; + color: #66666E; + } + table tr.even + { + border-left: 1px solid #E6E6E6; + background-color: #ffffff; + color: #66666E; + } + + div.float-left + { + float: left; margin-right: 2em + } + div.float-right + { + float: right; margin-left: 2em + } + + span.comment + { + color: #008B00; + font-style: italic + } + span.string, span.char + { + color: #000084; + } + span.number + { + color: #a46200; + } + span.operator + { + color: #202020; + } + span.keyword + { + color: #840000; + } + span.name + { + color: black + } + span.type + { + font-weight: bold + } + span.type a:visited + { + color: #0F5300; + } + span.preprocessor + { + color: #404040 + } +/* end basic elements */ + +/* font style elements */ + .heading + { + font-weight: bold; + font-size: 125%; + } + .subtitle + { + font-size: 110% + } + .small-subtitle + { + font-size: 100% + } + .red + { + color:red; + } +/* end font style elements */ + +/* global settings*/ + .header, .footer + { + display: block; + clear: both; + overflow: hidden; + } +/* end global settings*/ + +/* header elements */ + .header .qtref + { + color: #00732F; + font-weight: bold; + font-size: 130%; + } + + .header .content + { + margin-bottom: 0.5em + } + + .naviNextPrevious + { + display: none + } + .header .breadcrumb + { + font-size: 90%; + padding: 0.5em 0 0.5em 1em; + margin: 0; + background-color: #fafafa; + height: 1.35em; + border-bottom: 1px solid #d1d1d1; + } + + .header .breadcrumb ul + { + margin: 0; + padding: 0; + } + + .header .content + { + word-wrap: break-word; + } + + .header .breadcrumb ul li + { + float: left; + background: url(../images/breadcrumb.png) no-repeat 0 3px; + padding-left: 1.5em; + margin-left: 1.5em; + } + + .header .breadcrumb ul li.last + { + font-weight: normal; + } + + .header .breadcrumb ul li a + { + color: #00732F; + } + + .header .breadcrumb ul li.first + { + background-image: none; + padding-left: 0; + margin-left: 0; + } + + .header .content ol li { + background: none; + margin-bottom: 1.0em; + margin-left: 1.2em; + padding-left: 0 + } + + .header .content li + { + background: url(../images/bullet_sq.png) no-repeat 0 5px; + margin-bottom: 1em; + padding-left: 1.2em; + } + +/* end header elements */ + +/* content elements */ + .content h1 + { + font-weight: bold; + font-size: 150% + } + + .content h2 + { + font-weight: bold; + font-size: 135%; + width: 100%; + } + .content h3 + { + font-weight: bold; + font-size: 120%; + width: 100%; + } + .content table p + { + margin: 0 + } + .content ul + { + padding-left: 2.5em; + } + .content li + { + padding-top: 0.25em; + padding-bottom: 0.25em; + } + .content ul img { + vertical-align: middle; + } + + .content a:visited + { + color: #4c0033; + text-decoration: none; + } + + .content a:visited:hover + { + color: #4c0033; + text-decoration: underline; + } + + a:hover + { + color: #4c0033; + text-decoration: underline; + } + descr p a + { + text-decoration: underline; + } + + .descr p a:visited + { + text-decoration: underline; + } + + .alphaChar{ + width:95%; + background-color:#F6F6F6; + border:1px solid #E6E6E6; + -moz-border-radius: 7px 7px 7px 7px; + border-radius: 7px 7px 7px 7px; + -webkit-border-radius: 7px 7px 7px 7px; + font-size:12pt; + padding-left:10px; + margin-top:10px; + margin-bottom:10px; + } + .flowList{ + /*vertical-align:top;*/ + /*margin:20px auto;*/ + + column-count:3; + -webkit-column-count:3; + -moz-column-count:3; +/* + column-width:100%; + -webkit-column-width:200px; + -col-column-width:200px; +*/ + column-gap:41px; + -webkit-column-gap:41px; + -moz-column-gap:41px; + + column-rule: 1px dashed #ccc; + -webkit-column-rule: 1px dashed #ccc; + -moz-column-rule: 1px dashed #ccc; + } + + .flowList dl{ + } + .flowList dd{ + /*display:inline-block;*/ + margin-left:10px; + min-width:250px; + line-height: 1.5; + min-width:100%; + min-height:15px; + } + + .flowList dd a{ + } + + .content .flowList p{ + padding:0px; + } + + .content .alignedsummary + { + margin: 15px; + } + + + .qmltype + { + text-align: center; + font-size: 120%; + } + .qmlreadonly + { + padding-left: 5px; + float: right; + color: #254117; + } + + .qmldefault + { + padding-left: 5px; + float: right; + color: red; + } + + .qmldoc + { + } + + .generic .alphaChar{ + margin-top:5px; + } + + .generic .odd .alphaChar{ + background-color: #F6F6F6; + } + + .generic .even .alphaChar{ + background-color: #FFFFFF; + } + + .memItemRight{ + padding: 0.25em 1.5em 0.25em 0; + } + .highlightedCode + { + margin: 1.0em; + } + .annotated td { + padding: 0.25em 0.5em 0.25em 0.5em; + } + + .header .content .toc ul + { + padding-left: 0px; + } + + .content .toc h3 { + border-bottom: 0px; + margin-top: 0px; + } + + .content .toc h3 a:hover { + color: #00732F; + text-decoration: none; + } + + .content .toc .level2 + { + margin-left: 1.5em; + } + + .content .toc .level3 + { + margin-left: 3.0em; + } + + .content ul li + { + background: url(../images/bullet_sq.png) no-repeat 0 0.7em; + padding-left: 1em + } + + .content .toc li + { + background: url(../images/bullet_dn.png) no-repeat 0 5px; + padding-left: 1em + } + + .relpage + { + -moz-border-radius: 7px 7px 7px 7px; + -webkit-border-radius: 7px 7px 7px 7px; + border-radius: 7px 7px 7px 7px; + border: 1px solid #DDDDDD; + padding: 25px 25px; + clear: both; + } + .relpage ul + { + float: none; + padding: 1.5em; + } + + h3.fn, span.fn + { + -moz-border-radius:7px 7px 7px 7px; + -webkit-border-radius:7px 7px 7px 7px; + border-radius:7px 7px 7px 7px; + background-color: #F6F6F6; + border-width: 1px; + border-style: solid; + border-color: #E6E6E6; + font-weight: bold; + word-spacing:3px; + padding:3px 5px; + } + + .functionIndex { + font-size:12pt; + word-spacing:10px; + margin-bottom:10px; + background-color: #F6F6F6; + border-width: 1px; + border-style: solid; + border-color: #E6E6E6; + -moz-border-radius: 7px 7px 7px 7px; + -webkit-border-radius: 7px 7px 7px 7px; + border-radius: 7px 7px 7px 7px; + width:100%; + } + + .centerAlign + { + text-align:center; + } + + .rightAlign + { + text-align:right; + } + + .leftAlign + { + text-align:left; + } + + .topAlign{ + vertical-align:top + } + + .functionIndex a{ + display:inline-block; + } + +/* end content elements */ +/* footer elements */ + + .footer + { + color: #393735; + font-size: 0.75em; + text-align: center; + padding-top: 1.5em; + padding-bottom: 1em; + background-color: #E6E7E8; + margin: 0; + } + .footer p + { + margin: 0.25em + } + .small + { + font-size: 0.5em; + } +/* end footer elements */ + + .item { + float: left; + position: relative; + width: 100%; + overflow: hidden; + } + + + .item .primary { + margin-right: 220px; + position: relative; + } + + .item hr { + margin-left: -220px; + } + + .item .secondary { + float: right; + width: 200px; + position: relative; + } + + .item .cols { + clear: both; + display: block; + } + + .item .cols .col { + float: left; + margin-left: 1.5%; + } + + .item .cols .col.first { + margin-left: 0; + } + + .item .cols.two .col { + width: 45%; + } + + .item .box { + margin: 0 0 10px 0; + } + + .item .box h3 { + margin: 0 0 10px 0; + } + + .cols.unclear { + clear:none; + } +} + +/* end of screen media */ + +/* start of print media */ + +@media print +{ + input, textarea, .header, .footer, .toolbar, .feedback, .wrapper .hd, .wrapper .bd .sidebar, .wrapper .ft, #feedbackBox, #blurpage, .toc, .breadcrumb, .toolbar, .floatingResult + { + display: none; + background: none; + } + .content + { + background: none; + display: block; + width: 100%; margin: 0; float: none; + } +} +/* end of print media */ diff --git a/example/gdpbarchart/widget.cpp b/example/gdpbarchart/widget.cpp index 549a9d4..8514984 100644 --- a/example/gdpbarchart/widget.cpp +++ b/example/gdpbarchart/widget.cpp @@ -1,6 +1,7 @@ /*! \class Widget \brief Ui for the application. + \internal */ #include "widget.h" diff --git a/example/presenterchart/chartview.cpp b/example/presenterchart/chartview.cpp index f1fa540..877ea3f 100644 --- a/example/presenterchart/chartview.cpp +++ b/example/presenterchart/chartview.cpp @@ -43,7 +43,9 @@ m_index(0) ChartView::~ChartView() { - + if(m_series.size()==0) return; + removeSeries(m_series.at(m_index)); + qDeleteAll(m_series); } void ChartView::handleTimeout() diff --git a/example/scatter/main.cpp b/example/scatter/main.cpp index ac6a1d4..0a5c1b7 100644 --- a/example/scatter/main.cpp +++ b/example/scatter/main.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -12,7 +11,7 @@ int main(int argc, char *argv[]) QApplication a(argc, argv); // Create chart widget - QChartView *chartWidget = new QChartView(); + QChartView *chartView = new QChartView(); // Add scatter series with simple test data QScatterSeries *scatter = new QScatterSeries(); @@ -23,34 +22,27 @@ int main(int argc, char *argv[]) << QPointF(2.0, 4.5) << QPointF(2.0, 5.5) << QPointF(2.5, 5.0); - chartWidget->addSeries(scatter); + // Chart takes ownership + chartView->addSeries(scatter); // Add another scatter series // - more data with random component QScatterSeries *scatter2 = new QScatterSeries(); - for (qreal i(0.0); i < 20; i += 0.05) { + for (qreal i(0.0); i < 20; i += 0.15) { (*scatter2) << QPointF(i + (qreal)(rand() % 100) / 100.0, i + (qreal)(rand() % 100) / 100.0); } - chartWidget->addSeries(scatter2); - // Custom pen and brush (not those defined by the chart theme) - // - uses opaque color - QColor color("#2685BF"); - color.setAlpha(80); - QBrush brush(Qt::SolidPattern); - brush.setColor(color); + QBrush brush(QColor(255, 0, 0, 100), Qt::SolidPattern); scatter2->setMarkerBrush(brush); - QPen pen; - pen.setColor(color); - pen.setWidth(2); + QPen pen(QColor(0, 255, 0, 80), 3); scatter2->setMarkerPen(pen); - // use a rectangle as the marker shape scatter2->setMarkerShape(QScatterSeries::MarkerShapeRectangle); + chartView->addSeries(scatter2); // Use the chart widget as the central widget QMainWindow w; w.resize(640, 480); - w.setCentralWidget(chartWidget); + w.setCentralWidget(chartView); w.show(); return a.exec(); diff --git a/qcharts.qdocconf b/qcharts.qdocconf deleted file mode 100644 index f8566b1..0000000 --- a/qcharts.qdocconf +++ /dev/null @@ -1,18 +0,0 @@ -#include(compat.qdocconf) - -project = QCharts -description = Library for creating charts - -sourcedirs = ./src \ - ./example -headerdirs = ./src \ - ./example -exampledirs = ./src \ - ./example - -sources.fileextensions = "*.cpp *.qdoc *.mm *.qml" -headers.fileextensions = "*.h *.ch *.h++ *.hh *.hpp *.hxx" -examples.fileextensions = "*.cpp *.h *.js *.xq *.svg *.xml *.ui *.qhp *.qhcp *.qml" -examples.imageextensions = "*.png *.jpeg *.jpg *.gif *.mng" - -outputdir = ./doc/html diff --git a/qmlplugin/qmlplugin.pro b/qmlplugin/qmlplugin.pro index 3416541..0c4eb90 100644 --- a/qmlplugin/qmlplugin.pro +++ b/qmlplugin/qmlplugin.pro @@ -7,7 +7,7 @@ TEMPLATE = lib TARGET = qtcommercialchartqml - +DESTDIR = $$CHART_BUILD_PLUGIN_DIR CONFIG += qt plugin QT += declarative @@ -16,10 +16,10 @@ contains(QT_MAJOR_VERSION, 5) { DEFINES += QTQUICK2 } -OBJECTS_DIR = $$CHART_BUILD_DIR/lib -MOC_DIR = $$CHART_BUILD_DIR/lib -UI_DIR = $$CHART_BUILD_DIR/lib -RCC_DIR = $$CHART_BUILD_DIR/lib +OBJECTS_DIR = $$CHART_BUILD_DIR/plugin +MOC_DIR = $$CHART_BUILD_DIR/plugin +UI_DIR = $$CHART_BUILD_DIR/plugin +RCC_DIR = $$CHART_BUILD_DIR/plugin SOURCES += \ plugin.cpp \ @@ -37,6 +37,8 @@ HEADERS += \ declarativepieseries.h \ declarativelineseries.h +QMAKE_POST_LINK = $$QMAKE_COPY qmldir $$CHART_BUILD_PLUGIN_DIR + TARGETPATH = QtCommercial/Chart target.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH qmldir.files += $$PWD/qmldir diff --git a/src/axisitem.cpp b/src/axisitem.cpp index 0686f32..ceaa778 100644 --- a/src/axisitem.cpp +++ b/src/axisitem.cpp @@ -1,5 +1,6 @@ #include "axisitem_p.h" #include "qchartaxis.h" +#include "chartpresenter_p.h" #include #include @@ -14,11 +15,12 @@ m_labelsAngle(0), m_shadesEnabled(true), m_grid(parent), m_shades(parent), -m_labels(parent) +m_labels(parent), +m_origin(0,0) { //initial initialization - m_shades.setZValue(0); - m_grid.setZValue(2); + m_shades.setZValue(ChartPresenter::ShadesZValue); + m_grid.setZValue(ChartPresenter::GridZValue); } AxisItem::~AxisItem() @@ -172,6 +174,7 @@ void AxisItem::handleLabelsChanged(QChartAxis* axis,const QStringList& labels) clear(); m_thicksList=labels; createItems(m_thicksList.size()); + updateItem(m_thicksList.size()); items = m_labels.childItems(); handleAxisUpdate(axis); } @@ -208,7 +211,6 @@ void AxisItem::setGridOpacity(qreal opacity) m_grid.setOpacity(opacity); } - qreal AxisItem::gridOpacity() const { return m_grid.opacity(); diff --git a/src/axisitem_p.h b/src/axisitem_p.h index 3c4bba1..cd28482 100644 --- a/src/axisitem_p.h +++ b/src/axisitem_p.h @@ -50,9 +50,9 @@ public: void setLabelsFont(const QFont& font); public slots: - void handleAxisUpdate(QChartAxis* axis); - void handleLabelsChanged(QChartAxis* axis,const QStringList& labels); - void handleGeometryChanged(const QRectF& size); + void handleAxisUpdate(QChartAxis* axis); //look and feel + void handleLabelsChanged(QChartAxis* axis,const QStringList& labels); //labels from dataset + void handleGeometryChanged(const QRectF& size); // geometry from presenter protected: void updateItem(int count); private: @@ -68,6 +68,7 @@ private: QGraphicsItemGroup m_labels; QGraphicsLineItem m_axis; QStringList m_thicksList; + QPointF m_origin; }; diff --git a/src/barchart/bar.cpp b/src/barchart/bar.cpp index da6ce29..615314b 100644 --- a/src/barchart/bar.cpp +++ b/src/barchart/bar.cpp @@ -5,8 +5,9 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE Bar::Bar(QGraphicsItem *parent) - : ChartItem(parent) + : QGraphicsObject(parent) { + setAcceptedMouseButtons(Qt::LeftButton); } void Bar::setSize(const QSizeF& size) @@ -18,7 +19,6 @@ void Bar::setSize(const QSizeF& size) void Bar::resize( qreal w, qreal h ) { -// qDebug() << "bar::resize" << w << h; mWidth = w; mHeight = h; } @@ -30,7 +30,6 @@ void Bar::setColor( QColor col ) void Bar::setPos(qreal x, qreal y) { - // qDebug() << "Bar::setpos" << x << y; mXpos = x; mYpos = y; } @@ -50,10 +49,7 @@ void Bar::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidg if (0 == mHeight) { return; } - // TODO: accept brush instead of color painter->setBrush(mBrush); -// QBrush brush(mColor); -// painter->setBrush(brush); // This compensates for rounding errors. drawRect takes ints and cumulative error of pos + size may be over 1. int x0 = mXpos; @@ -71,6 +67,11 @@ QRectF Bar::boundingRect() const return r; } -//#include "moc_bar_p.cpp" +void Bar::mousePressEvent(QGraphicsSceneMouseEvent* /*event*/) +{ + emit clicked(); +} + +#include "moc_bar_p.cpp" QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/barchart/bar_p.h b/src/barchart/bar_p.h index 013c01d..6b2c13a 100644 --- a/src/barchart/bar_p.h +++ b/src/barchart/bar_p.h @@ -1,17 +1,17 @@ #ifndef BAR_H #define BAR_H -#include "chartitem_p.h" #include "qchartglobal.h" -#include +#include #include #include QTCOMMERCIALCHART_BEGIN_NAMESPACE // Single bar item of chart -class Bar : public ChartItem +class Bar : public QGraphicsObject { + Q_OBJECT public: Bar(QGraphicsItem *parent=0); @@ -30,6 +30,10 @@ public: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); QRectF boundingRect() const; + void mousePressEvent(QGraphicsSceneMouseEvent *event); + +Q_SIGNALS: + void clicked(); private: diff --git a/src/barchart/barchart.pri b/src/barchart/barchart.pri index 6b9594d..35668e6 100644 --- a/src/barchart/barchart.pri +++ b/src/barchart/barchart.pri @@ -14,7 +14,8 @@ SOURCES += \ $$PWD/qpercentbarchartseries.cpp \ $$PWD/qstackedbarchartseries.cpp \ $$PWD/separator.cpp \ - $$PWD/stackedbarpresenter.cpp + $$PWD/stackedbarpresenter.cpp \ + $$PWD/barvalue.cpp PRIVATE_HEADERS += \ $$PWD/bar_p.h \ @@ -24,12 +25,14 @@ PRIVATE_HEADERS += \ $$PWD/barpresenterbase.h \ $$PWD/percentbarpresenter.h \ $$PWD/separator_p.h \ - $$PWD/stackedbarpresenter.h - + $$PWD/stackedbarpresenter.h \ + $$PWD/barvalue_p.h + PUBLIC_HEADERS += \ $$PWD/qbarcategory.h \ $$PWD/qbarchartseries.h \ $$PWD/qbarset.h \ $$PWD/qpercentbarchartseries.h \ $$PWD/qstackedbarchartseries.h - \ No newline at end of file + + diff --git a/src/barchart/barchartmodel.cpp b/src/barchart/barchartmodel.cpp index 97a661e..55826af 100644 --- a/src/barchart/barchartmodel.cpp +++ b/src/barchart/barchartmodel.cpp @@ -134,14 +134,34 @@ qreal BarChartModel::valueAt(int set, int category) return mDataModel.at(set)->valueAt(category); } -qreal BarChartModel::categorySum(int column) +qreal BarChartModel::percentageAt(int set, int category) +{ + if ((set < 0) || (set >= mDataModel.count())) { + // No set, no value. + return 0; + } else if ((category < 0) || (category >= mDataModel.at(set)->count())) { + // No category, no value. + return 0; + } + + qreal value = mDataModel.at(set)->valueAt(category); + qreal total = categorySum(category); + if (0 == total) { + return 100.0; + } + + return value / total; +} + + +qreal BarChartModel::categorySum(int category) { qreal sum(0); - int count = mDataModel.count(); // Count rows + int count = mDataModel.count(); // Count sets - for (int row = 0; row < count; row++) { - if (column < mDataModel.at(row)->count()) { - sum += mDataModel.at(row)->valueAt(column); + for (int set = 0; set < count; set++) { + if (category < mDataModel.at(set)->count()) { + sum += mDataModel.at(set)->valueAt(category); } } return sum; diff --git a/src/barchart/barchartmodel_p.h b/src/barchart/barchartmodel_p.h index f19ad08..26f3009 100644 --- a/src/barchart/barchartmodel_p.h +++ b/src/barchart/barchartmodel_p.h @@ -33,8 +33,9 @@ public: qreal max(); // Maximum value of all sets qreal min(); // Minimum value of all sets qreal valueAt(int set, int category); + qreal percentageAt(int set, int category); - qreal categorySum(int column); + qreal categorySum(int category); qreal maxCategorySum(); // returns maximum sum of sets in all categories. QString label(int category); diff --git a/src/barchart/barpresenter.cpp b/src/barchart/barpresenter.cpp index f23f4fb..3323d2a 100644 --- a/src/barchart/barpresenter.cpp +++ b/src/barchart/barpresenter.cpp @@ -1,6 +1,7 @@ #include "barpresenter.h" #include "bar_p.h" #include "barlabel_p.h" +#include "barvalue_p.h" #include "qbarset.h" #include @@ -9,12 +10,11 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE BarPresenter::BarPresenter(BarChartModel& model, QGraphicsItem *parent) : BarPresenterBase(model,parent) { - mBarDefaultWidth = 5; + mBarDefaultWidth = 15; } void BarPresenter::layoutChanged() { -// qDebug() << "BarGroup::layoutChanged"; // Scale bars to new layout // Layout for bars: if (mModel.countSets() <= 0) { @@ -23,32 +23,32 @@ void BarPresenter::layoutChanged() } if (childItems().count() == 0) { - qDebug() << "WARNING: BarGroup::layoutChanged called before graphics items are created!"; + qDebug() << "WARNING: BarPresenter::layoutChanged called before graphics items are created!"; return; } // TODO: better way to auto-layout? // Use reals for accurancy (we might get some compiler warnings... :) - int itemCount = mModel.countCategories(); + int categoryCount = mModel.countCategories(); int setCount = mModel.countSets(); qreal tW = mWidth; qreal tH = mHeight; qreal tM = mModel.max(); qreal scale = (tH/tM); - qreal tC = itemCount+1; + qreal tC = categoryCount+1; qreal xStepPerSet = (tW/tC); // Scaling. int itemIndex(0); - int labelIndex = itemCount * setCount; + int labelIndex(0); - for (int item=0; item < itemCount; item++) { - qreal xPos = xStepPerSet * item + ((tW + mBarDefaultWidth*setCount)/(itemCount*2)); + for (int category=0; category < categoryCount; category++) { + qreal xPos = xStepPerSet * category + ((tW + mBarDefaultWidth*setCount)/(categoryCount*2)); qreal yPos = mHeight; for (int set = 0; set < setCount; set++) { - qreal barHeight = mModel.valueAt(set, item) * scale; - Bar* bar = reinterpret_cast (childItems().at(itemIndex)); + qreal barHeight = mModel.valueAt(set, category) * scale; + Bar* bar = mBars.at(itemIndex); // TODO: width settable per bar? bar->resize(mBarDefaultWidth, barHeight); @@ -59,12 +59,33 @@ void BarPresenter::layoutChanged() } // TODO: Layout for labels, remove magic number - xPos = xStepPerSet * item + ((tW + mBarDefaultWidth*setCount)/(itemCount*2)); - BarLabel* label = reinterpret_cast (childItems().at(labelIndex)); + xPos = xStepPerSet * category + ((tW + mBarDefaultWidth*setCount)/(categoryCount*2)); + BarLabel* label = mLabels.at(labelIndex); label->setPos(xPos, mHeight + 20); labelIndex++; } + // Position floating values + itemIndex = 0; + for (int category=0; category < mModel.countCategories(); category++) { + qreal xPos = xStepPerSet * category + ((tW + mBarDefaultWidth*setCount)/(categoryCount*2)); + qreal yPos = mHeight; + for (int set=0; set < mModel.countSets(); set++) { + qreal barHeight = mModel.valueAt(set,category) * scale; + BarValue* value = mFloatingValues.at(itemIndex); + + // TODO: remove hard coding, apply layout + value->resize(100,50); + value->setPos(xPos + mBarDefaultWidth/2, yPos-barHeight/2); + value->setPen(QPen(QColor(255,255,255,255))); + + QString vString(QString::number(mModel.valueAt(set,category))); + value->setValueString(vString); + + itemIndex++; + xPos += mBarDefaultWidth; + } + } mLayoutDirty = true; } diff --git a/src/barchart/barpresenter.h b/src/barchart/barpresenter.h index 036f6ef..197c0ab 100644 --- a/src/barchart/barpresenter.h +++ b/src/barchart/barpresenter.h @@ -7,8 +7,7 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE -// Base class for bar groups - +// Presenter for parallel bars. Grouping of bars is done on category basis. class BarPresenter : public BarPresenterBase { public: diff --git a/src/barchart/barpresenterbase.cpp b/src/barchart/barpresenterbase.cpp index 6d8c36f..4eba484 100644 --- a/src/barchart/barpresenterbase.cpp +++ b/src/barchart/barpresenterbase.cpp @@ -1,5 +1,6 @@ #include "barpresenterbase.h" #include "bar_p.h" +#include "barvalue_p.h" #include "barlabel_p.h" #include "separator_p.h" #include "qbarset.h" @@ -12,7 +13,7 @@ BarPresenterBase::BarPresenterBase(BarChartModel& model, QGraphicsItem *parent) ,mBarDefaultWidth(20) // TODO: remove hard coding, when we have layout code ready ,mLayoutSet(false) ,mLayoutDirty(true) - ,mSeparatorsVisible(true) + ,mSeparatorsVisible(false) ,mModel(model) { dataChanged(); @@ -25,9 +26,8 @@ void BarPresenterBase::setSeparatorsVisible(bool visible) void BarPresenterBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { -// qDebug() << "BarGroupBase::paint" << childItems().count(); if (!mLayoutSet) { - qDebug() << "BarGroupBase::paint called without layout set. Aborting."; + qDebug() << "BarPresenterBase::paint called without layout set. Aborting."; return; } // if (mLayoutDirty) { @@ -51,51 +51,83 @@ void BarPresenterBase::setBarWidth( int w ) void BarPresenterBase::dataChanged() { // TODO: performance optimizations. Do we really need to delete and create items every time data is changed or can we reuse them? - + qDebug() << "datachanged"; // Delete old bars foreach (QGraphicsItem* item, childItems()) { delete item; } + mBars.clear(); + mLabels.clear(); + mSeparators.clear(); + mFloatingValues.clear(); + // Create new graphic items for bars for (int s=0; sset(mModel.label(i)); childItems().append(label); + mLabels.append(label); } + // Create separators count = mModel.countCategories() - 1; // There is one less separator than columns for (int i=0; isetColor(QColor(255,0,0,255)); // TODO: color for separations from theme childItems().append(sep); + mSeparators.append(sep); + } + + // Create floating values + for (int s=0; sbelongsToSet(set)) { + mFloatingValues.at(i)->setVisible(set->isFloatingValuesVisible()); + } + } +} + //handlers void BarPresenterBase::handleModelChanged(int index) { -// qDebug() << "BarGroupBase::handleModelChanged" << index; +// qDebug() << "BarPresenterBase::handleModelChanged" << index; dataChanged(); } void BarPresenterBase::handleDomainChanged(const Domain& domain) { -// qDebug() << "BarGroupBase::handleDomainChanged"; +// qDebug() << "BarPresenterBase::handleDomainChanged"; // TODO: Figure out the use case for this. // Affects the size of visible item, so layout is changed. // layoutChanged(); diff --git a/src/barchart/barpresenterbase.h b/src/barchart/barpresenterbase.h index bb8dc8f..ecbe5fa 100644 --- a/src/barchart/barpresenterbase.h +++ b/src/barchart/barpresenterbase.h @@ -9,7 +9,12 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE -// Base Class for bar groups. Common implemantation of different groups. Not to be instantiated. +class Bar; +class BarLabel; +class Separator; +class BarValue; + +// Common implemantation of different presenters. Not to be instantiated. class BarPresenterBase : public QObject, public ChartItem { Q_OBJECT @@ -36,6 +41,9 @@ public: virtual void dataChanged(); // data of series has changed -> need to recalculate bar sizes virtual void layoutChanged() = 0; // layout has changed -> need to recalculate bar sizes +public Q_SLOTS: + void setFloatingValues(QBarSet *set); + protected slots: void handleModelChanged(int index); void handleDomainChanged(const Domain& domain); @@ -51,10 +59,15 @@ protected: bool mLayoutSet; // True, if component has been laid out. bool mLayoutDirty; - QList mColors; // List of colors for series for now bool mSeparatorsVisible; BarChartModel& mModel; + // Not owned. + QList mBars; + QList mLabels; + QList mSeparators; + QList mFloatingValues; + QPen mPen; }; diff --git a/src/barchart/barvalue.cpp b/src/barchart/barvalue.cpp new file mode 100644 index 0000000..cfa2063 --- /dev/null +++ b/src/barchart/barvalue.cpp @@ -0,0 +1,64 @@ +#include "barvalue_p.h" +#include +#include + +QTCOMMERCIALCHART_BEGIN_NAMESPACE + +BarValue::BarValue(QBarSet &set, QGraphicsItem *parent) + : QGraphicsItem(parent) + ,mBarSet(set) +{ +// setVisible(false); +} + +void BarValue::setValueString(QString str) +{ + mValueString = str; +} + +QString BarValue::valueString() +{ + return mValueString; +} + +void BarValue::setPen(const QPen& pen) +{ + mPen = pen; +} + +const QPen& BarValue::pen() +{ + return mPen; +} + +void BarValue::resize(qreal w, qreal h) +{ + mWidth = w; + mHeight = h; +} + +void BarValue::setPos(qreal x, qreal y) +{ + mXpos = x; + mYpos = y; +} + +bool BarValue::belongsToSet(QBarSet *set) +{ + return (&mBarSet == set); +} + +void BarValue::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + painter->setPen(mPen); + painter->drawText(boundingRect(),mValueString); +} + +QRectF BarValue::boundingRect() const +{ + QRectF r(mXpos, mYpos, mXpos + mWidth, mYpos + mHeight); + return r; +} + + +QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/barchart/barvalue_p.h b/src/barchart/barvalue_p.h new file mode 100644 index 0000000..eaba88b --- /dev/null +++ b/src/barchart/barvalue_p.h @@ -0,0 +1,49 @@ +#ifndef BARVALUE_P_H +#define BARVALUE_P_H + +#include "qchartglobal.h" +#include +#include + +QTCOMMERCIALCHART_BEGIN_NAMESPACE + +class QBarSet; + +// Visual class for floating bar values +// TODO: fonts, colors etc. +// By default these are not visible. +class BarValue : public QGraphicsItem // TODO: public QGraphicsObject for signals? +{ +public: + BarValue(QBarSet &set, QGraphicsItem *parent = 0); + + void setValueString(QString str); + QString valueString(); + + void setPen(const QPen& pen); + const QPen& pen(); + + void resize(qreal w, qreal h); + void setPos(qreal x, qreal y); + + bool belongsToSet(QBarSet *set); + + // From QGraphicsItem + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + QRectF boundingRect() const; + +private: + + QBarSet& mBarSet; + QPen mPen; + QString mValueString; + + qreal mXpos; + qreal mYpos; + qreal mWidth; + qreal mHeight; +}; + +QTCOMMERCIALCHART_END_NAMESPACE + +#endif // BARVALUE_P_H diff --git a/src/barchart/percentbarpresenter.cpp b/src/barchart/percentbarpresenter.cpp index 20431d4..dd90d73 100644 --- a/src/barchart/percentbarpresenter.cpp +++ b/src/barchart/percentbarpresenter.cpp @@ -1,6 +1,7 @@ #include "percentbarpresenter.h" #include "bar_p.h" #include "barlabel_p.h" +#include "barvalue_p.h" #include "separator_p.h" #include "qbarset.h" #include @@ -15,7 +16,6 @@ PercentBarPresenter::PercentBarPresenter(BarChartModel& model, QGraphicsItem *pa void PercentBarPresenter::layoutChanged() { -// qDebug() << "PercentBarGroup::layoutChanged"; // Scale bars to new layout // Layout for bars: if (mModel.countSets() <= 0) { @@ -25,7 +25,7 @@ void PercentBarPresenter::layoutChanged() } if (childItems().count() == 0) { - qDebug() << "WARNING: PercentBarGroup::layoutChanged called before graphics items are created!"; + qDebug() << "WARNING: PercentBarPresenter::layoutChanged called before graphics items are created!"; return; } @@ -33,20 +33,20 @@ void PercentBarPresenter::layoutChanged() // Use reals for accurancy (we might get some compiler warnings... :) int count = mModel.countCategories(); int itemIndex(0); + int labelIndex(0); qreal tW = mWidth; qreal tC = count+1; qreal xStep = (tW/tC); qreal xPos = ((tW/tC) - mBarDefaultWidth / 2); - int labelIndex = mModel.countCategories() * mModel.countSets(); + qreal h = mHeight; for (int category = 0; category < mModel.countCategories(); category++) { qreal colSum = mModel.categorySum(category); - qreal h = mHeight; qreal scale = (h / colSum); qreal yPos = h; for (int set=0; set < mModel.countSets(); set++) { qreal barHeight = mModel.valueAt(set, category) * scale; - Bar* bar = reinterpret_cast (childItems().at(itemIndex)); + Bar* bar = mBars.at(itemIndex); // TODO: width settable per bar? bar->resize(mBarDefaultWidth, barHeight); @@ -57,21 +57,44 @@ void PercentBarPresenter::layoutChanged() } // TODO: Layout for labels, remove magic number - BarLabel* label = reinterpret_cast (childItems().at(labelIndex)); + BarLabel* label = mLabels.at(labelIndex); label->setPos(xPos, mHeight + 20); labelIndex++; xPos += xStep; } // Position separators - int separatorIndex = labelIndex; // Separators are after labels in childItems(). TODO: better way to store these? - xPos = xStep + xStep/2; // Initial position is between first and second group. ie one and half steps from left. + xPos = xStep + xStep/2; for (int s=0; s < mModel.countCategories() - 1; s++) { - Separator* sep = reinterpret_cast (childItems().at(separatorIndex)); + Separator* sep = mSeparators.at(s); sep->setPos(xPos,0); sep->setSize(QSizeF(1,mHeight)); xPos += xStep; - separatorIndex++; + } + + // Position floating values + itemIndex = 0; + xPos = ((tW/tC) - mBarDefaultWidth / 2); + for (int category=0; category < mModel.countCategories(); category++) { + qreal yPos = h; + qreal colSum = mModel.categorySum(category); + qreal scale = (h / colSum); + for (int set=0; set < mModel.countSets(); set++) { + qreal barHeight = mModel.valueAt(set,category) * scale; + BarValue* value = mFloatingValues.at(itemIndex); + + // TODO: remove hard coding, apply layout + value->setPos(xPos + mBarDefaultWidth/2, yPos-barHeight/2); + value->setPen(QPen(QColor(255,255,255,255))); + + QString vString(QString::number(mModel.percentageAt(set,category) * 100)); + vString.append("%"); + value->setValueString(vString); + + itemIndex++; + yPos -= barHeight; + } + xPos += xStep; } mLayoutDirty = true; diff --git a/src/barchart/qbarset.cpp b/src/barchart/qbarset.cpp index eb6533f..fc0107a 100644 --- a/src/barchart/qbarset.cpp +++ b/src/barchart/qbarset.cpp @@ -5,6 +5,7 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE QBarSet::QBarSet() { + mFloatingValuesVisible = false; } void QBarSet::setName(QString name) @@ -57,11 +58,29 @@ const QBrush& QBarSet::brush() const return mBrush; } +bool QBarSet::isFloatingValuesVisible() +{ + return mFloatingValuesVisible; +} + void QBarSet::barClicked() { + qDebug() << "QBarset::barClicked"; // Some bar of this set has been clicked // TODO: What happens then? - qDebug() << "bar Clicked"; + emit clicked(); // Notify that set has been clicked +} + +void QBarSet::toggleFloatingValuesVisible() +{ + qDebug() << "QBarset::toggleFloatingValuesVisible"; + // TODO: toggle vs explicit set? + if (mFloatingValuesVisible) { + mFloatingValuesVisible=false; + } else { + mFloatingValuesVisible=true; + } + emit setFloatingValuesVisible(this); } diff --git a/src/barchart/qbarset.h b/src/barchart/qbarset.h index a071a74..9a7e82a 100644 --- a/src/barchart/qbarset.h +++ b/src/barchart/qbarset.h @@ -27,7 +27,11 @@ public: void setBrush(const QBrush& brush); const QBrush& brush() const; -// void clicked(); + bool isFloatingValuesVisible(); + +Q_SIGNALS: + void clicked(); + void setFloatingValuesVisible(QBarSet* set); /* void hoverEnter(); void hoverLeave(); @@ -35,6 +39,7 @@ public: public Q_SLOTS: void barClicked(); + void toggleFloatingValuesVisible(); private: @@ -43,6 +48,7 @@ private: QPen mPen; QBrush mBrush; + bool mFloatingValuesVisible; }; QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/barchart/stackedbarpresenter.cpp b/src/barchart/stackedbarpresenter.cpp index 74fdcdc..67c0c7b 100644 --- a/src/barchart/stackedbarpresenter.cpp +++ b/src/barchart/stackedbarpresenter.cpp @@ -1,6 +1,7 @@ #include "stackedbarpresenter.h" #include "bar_p.h" #include "barlabel_p.h" +#include "barvalue_p.h" #include "separator_p.h" #include "qbarset.h" #include @@ -14,7 +15,6 @@ StackedBarPresenter::StackedBarPresenter(BarChartModel& model, QGraphicsItem *pa void StackedBarPresenter::layoutChanged() { -// qDebug() << "StackedBarGroup::layoutChanged"; // Scale bars to new layout // Layout for bars: if (mModel.countSets() <= 0) { @@ -30,7 +30,7 @@ void StackedBarPresenter::layoutChanged() } if (childItems().count() == 0) { - qDebug() << "WARNING: StackedBarGroup::layoutChanged called before graphics items are created!"; + qDebug() << "WARNING: StackedBarPresenter::layoutChanged called before graphics items are created!"; return; } @@ -42,17 +42,17 @@ void StackedBarPresenter::layoutChanged() qreal scale = (h / maxSum); int itemIndex(0); + int labelIndex(0); qreal tW = mWidth; qreal tC = mModel.countCategories() + 1; qreal xStep = (tW/tC); qreal xPos = ((tW/tC) - mBarDefaultWidth / 2); - int labelIndex = mModel.countSets() * mModel.countCategories(); for (int category = 0; category < mModel.countCategories(); category++) { qreal yPos = h; for (int set=0; set < mModel.countSets(); set++) { qreal barHeight = mModel.valueAt(set, category) * scale; - Bar* bar = reinterpret_cast (childItems().at(itemIndex)); + Bar* bar = mBars.at(itemIndex); bar->resize(mBarDefaultWidth, barHeight); bar->setBrush(mModel.setAt(set).brush()); @@ -62,21 +62,42 @@ void StackedBarPresenter::layoutChanged() } // TODO: Layout for labels, remove magic number - BarLabel* label = reinterpret_cast (childItems().at(labelIndex)); + BarLabel* label = mLabels.at(labelIndex); label->setPos(xPos, mHeight + 20); labelIndex++; xPos += xStep; } // Position separators - int separatorIndex = labelIndex; // Separators are after labels in childItems(). TODO: better way to store these? - xPos = xStep + xStep/2; // Initial position is between first and second group. ie one and half steps from left. + xPos = xStep + xStep/2; for (int s=0; s < mModel.countCategories() - 1; s++) { - Separator* sep = reinterpret_cast (childItems().at(separatorIndex)); + Separator* sep = mSeparators.at(s); sep->setPos(xPos,0); sep->setSize(QSizeF(1,mHeight)); xPos += xStep; - separatorIndex++; + } + + // Position floating values + itemIndex = 0; + xPos = ((tW/tC) - mBarDefaultWidth / 2); + for (int category=0; category < mModel.countCategories(); category++) { + qreal yPos = h; + for (int set=0; set < mModel.countSets(); set++) { + qreal barHeight = mModel.valueAt(set,category) * scale; + BarValue* value = mFloatingValues.at(itemIndex); + + // TODO: remove hard coding, apply layout + value->resize(100,50); + value->setPos(xPos + mBarDefaultWidth/2, yPos-barHeight/2); + value->setPen(QPen(QColor(255,255,255,255))); + + QString vString(QString::number(mModel.valueAt(set,category))); + value->setValueString(vString); + + itemIndex++; + yPos -= barHeight; + } + xPos += xStep; } mLayoutDirty = true; diff --git a/src/barchart/stackedbarpresenter.h b/src/barchart/stackedbarpresenter.h index fc79acc..1db1be0 100644 --- a/src/barchart/stackedbarpresenter.h +++ b/src/barchart/stackedbarpresenter.h @@ -1,5 +1,5 @@ -#ifndef STACKEDBARGROUP_H -#define STACKEDBARGROUP_H +#ifndef STACKEDBARPRESENTER_H +#define STACKEDBARPRESENTER_H #include "barpresenterbase.h" #include "qstackedbarchartseries.h" @@ -13,7 +13,7 @@ public: StackedBarPresenter(BarChartModel& model, QGraphicsItem *parent = 0); private: - // From BarGroupBase + // From BarPresenterBase void layoutChanged(); // layout has changed -> need to recalculate bar sizes private: @@ -23,4 +23,4 @@ private: QTCOMMERCIALCHART_END_NAMESPACE -#endif // STACKEDBARGROUP_H +#endif // STACKEDBARPRESENTER_H diff --git a/src/chartdataset.cpp b/src/chartdataset.cpp index 6d78be0..1fbdd18 100644 --- a/src/chartdataset.cpp +++ b/src/chartdataset.cpp @@ -168,16 +168,36 @@ void ChartDataSet::removeSeries(QChartSeries* series) emit seriesRemoved(series); m_seriesMap.remove(axis,series); //remove axis if no longer there - if(!m_seriesMap.contains(axis) && axis != m_axisY){ + if(!m_seriesMap.contains(axis)){ emit axisRemoved(axis); m_domainMap.remove(axis); + if(axis != m_axisY) delete axis; } + series->setParent(0); break; } } } +void ChartDataSet::removeAllSeries() +{ + QList keys = m_seriesMap.uniqueKeys(); + foreach(QChartAxis* axis , keys) { + QList seriesList = m_seriesMap.values(axis); + for(int i =0 ; i < seriesList.size();i++ ) + { + emit seriesRemoved(seriesList.at(i)); + delete(seriesList.at(i)); + } + m_seriesMap.remove(axis); + m_domainMap.remove(axis); + emit axisRemoved(axis); + if(axis != m_axisY) delete axis; + } + m_domainIndex=0; +} + bool ChartDataSet::nextDomain() { int limit = (m_domainMap.values().size()/m_domainMap.uniqueKeys().size())-1; @@ -207,10 +227,13 @@ bool ChartDataSet::previousDomain() void ChartDataSet::setDomain(int index) { QList domainList = m_domainMap.uniqueKeys(); + + Domain domain; + foreach (QChartAxis* axis , domainList) { int i = m_domainMap.count(axis) - index -1; Q_ASSERT(i>=0); - Domain domain = m_domainMap.values(axis).at(i); + domain = m_domainMap.values(axis).at(i); QStringList labels = createLabels(axis,domain.m_minY,domain.m_maxY); QList seriesList = m_seriesMap.values(axis); foreach(QChartSeries* series, seriesList) { @@ -219,7 +242,6 @@ void ChartDataSet::setDomain(int index) emit axisLabelsChanged(axis,labels); } - Domain domain = m_domainMap.value(axisY()); QStringList labels = createLabels(axisX(),domain.m_minX,domain.m_maxX); emit axisLabelsChanged(axisX(),labels); } @@ -254,8 +276,10 @@ void ChartDataSet::addDomain(const QRectF& rect, const QRectF& viewport) QList domainList = m_domainMap.uniqueKeys(); + Domain domain; + foreach (QChartAxis* axis , domainList){ - Domain domain(m_domainMap.value(axis).subDomain(rect,viewport.width(),viewport.height())); + domain = m_domainMap.value(axis).subDomain(rect,viewport.width(),viewport.height()); QStringList labels = createLabels(axis,domain.m_minY,domain.m_maxY); QList seriesList = m_seriesMap.values(axis); foreach(QChartSeries* series, seriesList){ @@ -265,7 +289,6 @@ void ChartDataSet::addDomain(const QRectF& rect, const QRectF& viewport) m_domainMap.insert(axis,domain); } - Domain domain = m_domainMap.value(axisY()); QStringList labels = createLabels(axisX(),domain.m_minX,domain.m_maxX); emit axisLabelsChanged(axisX(),labels); diff --git a/src/chartdataset_p.h b/src/chartdataset_p.h index c350b04..b5851c3 100644 --- a/src/chartdataset_p.h +++ b/src/chartdataset_p.h @@ -18,6 +18,7 @@ public: void addSeries(QChartSeries* series,QChartAxis *axisY = 0); void removeSeries(QChartSeries* series); + void removeAllSeries(); void addDomain(const QRectF& rect, const QRectF& viewport); bool nextDomain(); bool previousDomain(); diff --git a/src/chartpresenter.cpp b/src/chartpresenter.cpp index 60c844b..e767dc6 100644 --- a/src/chartpresenter.cpp +++ b/src/chartpresenter.cpp @@ -84,6 +84,9 @@ void ChartPresenter::handleAxisAdded(QChartAxis* axis) } QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&))); QObject::connect(axis,SIGNAL(update(QChartAxis*)),item,SLOT(handleAxisUpdate(QChartAxis*))); + + item->handleAxisUpdate(axis); + item->handleGeometryChanged(m_rect); m_chartTheme->decorate(axis,item); m_axisItems.insert(axis,item); } diff --git a/src/chartpresenter_p.h b/src/chartpresenter_p.h index 8088d6e..6ec594a 100644 --- a/src/chartpresenter_p.h +++ b/src/chartpresenter_p.h @@ -20,6 +20,8 @@ class ChartPresenter: public QObject { Q_OBJECT public: + enum ZValues { BackgroundZValue = -1 , ShadesZValue, GridZValue, AxisZValue , LineChartZValue }; + ChartPresenter(QChart* chart,ChartDataSet *dataset); virtual ~ChartPresenter(); diff --git a/src/linechart/linechartitem.cpp b/src/linechart/linechartitem.cpp index 804dc5a..25d9e2c 100644 --- a/src/linechart/linechartitem.cpp +++ b/src/linechart/linechartitem.cpp @@ -15,7 +15,7 @@ m_dirtyData(false), m_dirtyGeometry(false), m_dirtyDomain(false) { - + setZValue(ChartPresenter::LineChartZValue); } QRectF LineChartItem::boundingRect() const diff --git a/src/qchart.cpp b/src/qchart.cpp index 3617c83..f6c8b9a 100644 --- a/src/qchart.cpp +++ b/src/qchart.cpp @@ -6,21 +6,44 @@ #include #include +/*! + \class QChart + \brief QtCommercial chart API. + + QChart is a QGraphicsWidget that you can show in a QGraphicsScene. It manages the graphical + representation of different types of QChartSeries and other chart related objects like + QChartAxis and QChartLegend. If you simply want to show a chart in a layout, you can use the + convenience class QChartView instead of QChart. +*/ + QTCOMMERCIALCHART_BEGIN_NAMESPACE +/*! + Constructs a chart object which is a child of parent. +*/ QChart::QChart(QGraphicsItem *parent, Qt::WindowFlags wFlags) : QGraphicsWidget(parent,wFlags), -m_backgroundItem(0), -m_titleItem(0), -m_dataset(new ChartDataSet(this)), -m_presenter(new ChartPresenter(this,m_dataset)) + m_backgroundItem(0), + m_titleItem(0), + m_dataset(new ChartDataSet(this)), + m_presenter(new ChartPresenter(this,m_dataset)) { } -QChart::~QChart() {} +/*! + Destroys the object and it's children, like QChartSeries and QChartAxis object added to it. +*/ +QChart::~QChart() +{ +} -void QChart::addSeries(QChartSeries* series,QChartAxis* axisY) +/*! + Adds the series and optional y axis onto the chart and takes the ownership of the objects. + If auto scaling is enabled, re-scales the axes the series is bound to (both the x axis and + the y axis). +*/ +void QChart::addSeries(QChartSeries* series, QChartAxis* axisY) { - m_dataset->addSeries(series,axisY); + m_dataset->addSeries(series, axisY); } void QChart::removeSeries(QChartSeries* series) @@ -28,6 +51,11 @@ void QChart::removeSeries(QChartSeries* series) m_dataset->removeSeries(series); } +void QChart::removeAllSeries() +{ + m_dataset->removeAllSeries(); +} + void QChart::setChartBackgroundBrush(const QBrush& brush) { createChartBackgroundItem(); @@ -58,13 +86,16 @@ void QChart::createChartBackgroundItem() { if(!m_backgroundItem) { m_backgroundItem = new QGraphicsRectItem(this); - m_backgroundItem->setZValue(-1); + m_backgroundItem->setZValue(ChartPresenter::BackgroundZValue); } } void QChart::createChartTitleItem() { - if(!m_titleItem) m_titleItem = new QGraphicsTextItem(this); + if(!m_titleItem) { + m_titleItem = new QGraphicsTextItem(this); + m_titleItem->setZValue(ChartPresenter::BackgroundZValue); + } } int QChart::margin() const diff --git a/src/qchart.h b/src/qchart.h index f0d98a1..0fa31ca 100644 --- a/src/qchart.h +++ b/src/qchart.h @@ -1,5 +1,5 @@ -#ifndef CHART_H -#define CHART_H +#ifndef QCHART_H +#define QCHART_H #include #include @@ -21,9 +21,6 @@ class ChartItem; class ChartDataSet; class ChartPresenter; -/*! - * TODO: define the responsibilities - */ class QTCOMMERCIALCHART_EXPORT QChart : public QGraphicsWidget { Q_OBJECT @@ -34,7 +31,7 @@ public: ChartThemeVanilla, ChartThemeIcy, ChartThemeGrayscale, - ChartThemeScientific, + ChartThemeScientific //ChartThemeUnnamed1 }; @@ -42,8 +39,9 @@ public: QChart(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0); ~QChart(); - void addSeries(QChartSeries* series,QChartAxis *axisY=0); - void removeSeries(QChartSeries* series); + void addSeries(QChartSeries* series, QChartAxis* axisY = 0); + void removeSeries(QChartSeries* series); //returns ownership , deletes axis if no series attached + void removeAllSeries(); // deletes series and axis void setMargin(int margin); int margin() const; diff --git a/src/qchartview.cpp b/src/qchartview.cpp index d9e54f5..bd8652f 100644 --- a/src/qchartview.cpp +++ b/src/qchartview.cpp @@ -51,6 +51,11 @@ void QChartView::removeSeries(QChartSeries* series) m_chart->removeSeries(series); } +void QChartView::removeAllSeries() +{ + m_chart->removeAllSeries(); +} + void QChartView::zoomIn() { m_chart->zoomIn(); diff --git a/src/qchartview.h b/src/qchartview.h index b7acb5b..a52c959 100644 --- a/src/qchartview.h +++ b/src/qchartview.h @@ -24,8 +24,9 @@ public: //implement from QWidget void resizeEvent(QResizeEvent *event); - void addSeries(QChartSeries* series,QChartAxis* axisY=0);// takes ownership - void removeSeries(QChartSeries* series); + void addSeries(QChartSeries* series,QChartAxis* axisY=0);// takes series ownership , takes axis ownership + void removeSeries(QChartSeries* series); //returns ownership , deletes axis if no series attached + void removeAllSeries(); // deletes series and axis int margin() const; void setChartTitle(const QString& title); diff --git a/src/scatterseries/qscatterseries.cpp b/src/scatterseries/qscatterseries.cpp index d9811d2..da8c86d 100644 --- a/src/scatterseries/qscatterseries.cpp +++ b/src/scatterseries/qscatterseries.cpp @@ -15,23 +15,86 @@ QScatterSeriesPrivate::QScatterSeriesPrivate() : m_markerBrush.setColor(QColor::Invalid); } +/*! + \enum QScatterSeries::MarkerShape + + This enum describes the shape used when rendering marker items. + + \value MarkerShapeDefault + \value MarkerShapePoint + \value MarkerShapeX + \value MarkerShapeRectangle + \value MarkerShapeTiltedRectangle + \value MarkerShapeTriangle + \value MarkerShapeCircle +*/ + +/*! + \class QScatterSeries + \brief QtCommercial Chart series API for showing scatter series. + + Example on how to create a chart with scatter series: + \code + #include + #include + #include + ... + QTCOMMERCIALCHART_USE_NAMESPACE + + // Create chart widget + QChartView *chartView = new QChartView(); + QScatterSeries *scatter = new QScatterSeries(); + *scatter << QPointF(0.5, 5.0) << QPointF(1.0, 4.5) << QPointF(1.0, 5.5) << QPointF(1.5, 5.0); + chartView->addSeries(scatter); + // Then add the QChartView into a layout... + \endcode + + The example code would result the following: + + \image scatter_example1.jpg +*/ + +/*! + Constructs a series object which is a child of \a parent. +*/ QScatterSeries::QScatterSeries(QObject *parent) : QChartSeries(parent), d(new QScatterSeriesPrivate()) { } +/*! + Destroys the object. Note that adding series to QChart transfers the ownership to the chart. +*/ QScatterSeries::~QScatterSeries() { delete d; } +/*! + Add single data point to the series. + For example: + \code + mySeries.addData(QPointF(0.5, 5.0)); + \endcode +*/ void QScatterSeries::addData(QPointF value) { d->m_data.append(value); emit changed(); } +/*! + Stream operator for adding a data point to the series. + \sa addData(), QScatterSeries::addData(QPointF value) + + For example: + \code + mySeries << QPointF(0.5, 5.0) + << QPointF(1.0, 4.5); + \endcode + +*/ QScatterSeries& QScatterSeries::operator << (const QPointF &value) { d->m_data.append(value); @@ -39,42 +102,101 @@ QScatterSeries& QScatterSeries::operator << (const QPointF &value) return *this; } +/*! + Replaces the data of the series with the given list of data points. +*/ void QScatterSeries::setData(QList data) { d->m_data = data; emit changed(); } +/*! + Returns the current list of data points of the series. +*/ QList QScatterSeries::data() { return d->m_data; } +/*! + Overrides the default pen used for drawing a marker item with a user defined pen. The default + pen is defined by chart theme setting. + + For example: + \code + QPen pen(QColor(0, 255, 0, 80), 3); + myScatter->setMarkerPen(pen); + \endcode + + Would present your scatter markers with an opaque, uglyish green outlines: + \image scatter_example_pen.jpg + + \sa setMarkerBrush() + \sa QChart::setTheme() +*/ void QScatterSeries::setMarkerPen(QPen pen) { d->m_markerPen = pen; } +/*! + Returns the pen used for drawing markers. +*/ QPen QScatterSeries::markerPen() { return d->m_markerPen; } +/*! + Overrides the default brush of the marker items with a user defined brush. The default + brush is defined by chart theme setting. + + For example: + \code + QBrush brush(QColor(255, 0, 0, 100), Qt::SolidPattern); + myRandomScatter->setMarkerBrush(brush); + \endcode + + Would fill your scatter markers with an opaque red color: + \image scatter_example_brush.jpg + + \sa setMarkerPen() + \sa QChart::setTheme() +*/ void QScatterSeries::setMarkerBrush(QBrush brush) { d->m_markerBrush = brush; } +/*! + Returns the brush used for drawing markers. +*/ QBrush QScatterSeries::markerBrush() { return d->m_markerBrush; } +/*! + Overrides the default shape of the marker items with a user defined shape. The default + shape is defined by chart theme setting. + + For example: + \code + myScatter->setMarkerShape(QScatterSeries::MarkerShapeRectangle); + \endcode + + Would make your scatter marker items rectangle: + \image scatter_example_shape.jpg +*/ void QScatterSeries::setMarkerShape(MarkerShape shape) { d->m_markerShape = shape; } +/*! + Returns the shape used for drawing markers. +*/ QScatterSeries::MarkerShape QScatterSeries::markerShape() { return (QScatterSeries::MarkerShape) d->m_markerShape; diff --git a/src/scatterseries/scatterpresenter.cpp b/src/scatterseries/scatterpresenter.cpp index 0e25348..d886f03 100644 --- a/src/scatterseries/scatterpresenter.cpp +++ b/src/scatterseries/scatterpresenter.cpp @@ -45,13 +45,15 @@ void ScatterPresenter::paint(QPainter *painter, const QStyleOptionGraphicsItem * { // TODO: Optimization: avoid setting on every paint method call? // The custom settings in series override those defined by the theme - if (m_series->markerPen().color().isValid()) { + if (m_series->markerPen().color().isValid()) painter->setPen(m_series->markerPen()); - painter->setBrush(m_series->markerBrush()); - } else { + else painter->setPen(m_markerPen); + + if (m_series->markerBrush().color().isValid()) + painter->setBrush(m_series->markerBrush()); + else painter->setBrush(m_markerBrush); - } int shape = m_series->markerShape(); diff --git a/test/auto/chartdataset/tst_chartdataset.cpp b/test/auto/chartdataset/tst_chartdataset.cpp index 9c691b9..9d6e5e6 100644 --- a/test/auto/chartdataset/tst_chartdataset.cpp +++ b/test/auto/chartdataset/tst_chartdataset.cpp @@ -39,6 +39,8 @@ private slots: void nextpreviousDomain(); void removeSeries_data(); void removeSeries(); + void removeAllSeries_data(); + void removeAllSeries(); }; void tst_ChartDataSet::initTestCase() @@ -189,8 +191,6 @@ void tst_ChartDataSet::addSeries() else axisYCount++; - - QCOMPARE(spy0.count(), axisYCount); QCOMPARE(spy1.count(), seriesCount*2); QCOMPARE(spy2.count(), 0); @@ -513,6 +513,10 @@ void tst_ChartDataSet::removeSeries() dataSet.removeSeries(seriesList.at(i)); } + //default axis + if (axisYCount == 0) + axisYCount++; + QCOMPARE(spy0.count(), 0); QCOMPARE(spy1.count(), 0); QCOMPARE(spy2.count(), axisYCount); @@ -521,8 +525,75 @@ void tst_ChartDataSet::removeSeries() QCOMPARE(spy5.count(), seriesCount); QCOMPARE(dataSet.domainIndex(), 0); + + qDeleteAll(seriesList); } +void tst_ChartDataSet::removeAllSeries_data() +{ + QTest::addColumn("seriesCount"); + QTest::addColumn("axisYCount"); + QTest::newRow("2 series, default axis") << 2 << 0; + QTest::newRow("2 series, 2 new axis") << 2 << 2; + QTest::newRow("2 series, 1 new axis") << 2 << 2; + QTest::newRow("3 series, 3 new axis") << 3 << 3; + QTest::newRow("3 series, 2 new axis") << 3 << 2; + QTest::newRow("3 series, 1 new axis") << 3 << 1; +} + +void tst_ChartDataSet::removeAllSeries() +{ + QFETCH(int, seriesCount); + QFETCH(int, axisYCount); + + ChartDataSet dataSet; + + QList axisList; + + for (int i = 0; i < axisYCount; i++) { + QChartAxis* axis = new QChartAxis(); + axisList << axis; + } + + QList::iterator iterator = axisList.begin(); + + for (int i = 0; i < seriesCount; i++) { + QChartAxis* axisY = 0; + QLineChartSeries* series = new QLineChartSeries(); + if (iterator != axisList.end()) { + axisY = *iterator; + iterator++; + } else if (axisList.count() > 0) { + iterator--; + axisY = *iterator; + iterator++; + } + dataSet.addSeries(series, axisY); + } + + QSignalSpy spy0(&dataSet, SIGNAL(axisAdded(QChartAxis*))); + QSignalSpy spy1(&dataSet, SIGNAL(axisLabelsChanged(QChartAxis*, QStringList const&))); + QSignalSpy spy2(&dataSet, SIGNAL(axisRemoved(QChartAxis*))); + QSignalSpy spy3(&dataSet, SIGNAL(seriesAdded(QChartSeries*))); + QSignalSpy spy4(&dataSet, SIGNAL(seriesDomainChanged(QChartSeries*, Domain const&))); + QSignalSpy spy5(&dataSet, SIGNAL(seriesRemoved(QChartSeries*))); + + dataSet.removeAllSeries(); + //default axis + if (axisYCount == 0) + axisYCount++; + + QCOMPARE(spy0.count(), 0); + QCOMPARE(spy1.count(), 0); + QCOMPARE(spy2.count(), axisYCount); + QCOMPARE(spy3.count(), 0); + QCOMPARE(spy4.count(), 0); + QCOMPARE(spy5.count(), seriesCount); + + QCOMPARE(dataSet.domainIndex(), 0); +} + + QTEST_MAIN(tst_ChartDataSet) #include "tst_chartdataset.moc" diff --git a/test/qmlchart/main.cpp b/test/qmlchart/main.cpp index ac70a83..15a8fb8 100644 --- a/test/qmlchart/main.cpp +++ b/test/qmlchart/main.cpp @@ -8,7 +8,7 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) QScopedPointer viewer(QmlApplicationViewer::create()); viewer->setOrientation(QmlApplicationViewer::ScreenOrientationAuto); - viewer->setMainQmlFile(QLatin1String("qml/qmlchart/main.qml")); + viewer->setSource(QUrl("qrc:/qml/qmlchart/loader.qml")); viewer->showExpanded(); return app->exec(); diff --git a/test/qmlchart/qml/qmlchart/loader.qml b/test/qmlchart/qml/qmlchart/loader.qml new file mode 100644 index 0000000..d6b44b7 --- /dev/null +++ b/test/qmlchart/qml/qmlchart/loader.qml @@ -0,0 +1,17 @@ +import QtQuick 1.0 + +Item { + id: container + width: 400 + height: 500 + Component.onCompleted: { + var co = Qt.createComponent("main.qml") + if (co.status == Component.Ready) { + var o = co.createObject(container) + } else { + console.log(co.errorString()) + console.log("QtCommercial.Chart 1.1 not available") + console.log("Please use correct QML_IMPORT_PATH export") + } + } +} \ No newline at end of file diff --git a/test/qmlchart/qml/qmlchart/main.qml b/test/qmlchart/qml/qmlchart/main.qml index 7988a5c..4cecfa2 100644 --- a/test/qmlchart/qml/qmlchart/main.qml +++ b/test/qmlchart/qml/qmlchart/main.qml @@ -2,8 +2,8 @@ import QtQuick 1.0 import QtCommercial.Chart 1.0 Rectangle { - width: 360 - height: 360 + width: parent.width + height: parent.height // Another option for QML data api: // ListModel { diff --git a/test/qmlchart/qmlchart.pro b/test/qmlchart/qmlchart.pro index 3927027..ed8d5f0 100644 --- a/test/qmlchart/qmlchart.pro +++ b/test/qmlchart/qmlchart.pro @@ -1,18 +1,21 @@ !include( ../../common.pri ) { error( "Couldn't find the common.pri file!" ) } -!include( ../../integrated.pri ) { - error( "Couldn't find the integrated.pri file !") -} -integrated_build: { - # cannot use integrated build for now; we would need the qml files copied to - # charts/bin folder also to make this work. And even in that case I'm not sure if - # the chart qml plugin can be found or if it needs to be installed to the qt's plugin - # folder always. - warning("TODO: Charts qml test app does not work with integrated builds") +DESTDIR = $$CHART_BUILD_BIN_DIR + +OBJECTS_DIR = $$CHART_BUILD_DIR/bin/$$TARGET +MOC_DIR = $$CHART_BUILD_DIR/bin/$$TARGET +UI_DIR = $$CHART_BUILD_DIR/bin/$$TARGET +RCC_DIR = $$CHART_BUILD_DIR/bin/$$TARGET + +integrated_build:{ + message(Please export QML_IMPORT_PATH=$$CHART_BUILD_LIB_DIR) } +RESOURCES += \ + resources.qrc + # Add more folders to ship with the application, here folder_01.source = qml/qmlchart folder_01.target = qml diff --git a/test/qmlchart/resources.qrc b/test/qmlchart/resources.qrc new file mode 100644 index 0000000..a9c2b4a --- /dev/null +++ b/test/qmlchart/resources.qrc @@ -0,0 +1,6 @@ + + + qml/qmlchart/loader.qml + qml/qmlchart/main.qml + +