diff --git a/example/stackedbarchartdrilldown/main.cpp b/example/stackedbarchartdrilldown/main.cpp index 9a87499..3735a4c 100644 --- a/example/stackedbarchartdrilldown/main.cpp +++ b/example/stackedbarchartdrilldown/main.cpp @@ -15,37 +15,28 @@ class DrilldownBarSeries : public QStackedBarSeries { Q_OBJECT public: - DrilldownBarSeries(QStringList categories, QObject* parent = 0) : QStackedBarSeries(categories,parent) {} + DrilldownBarSeries(QStringList categories, QObject *parent = 0) : QStackedBarSeries(categories,parent) {} - -public Q_SLOTS: - void handleRightClick(QBarSet *barset, QString category) + void addDrilldownSeries(QString category, DrilldownBarSeries* drilldownSeries) { - qDebug() << "DrilldownBarSeries::handleRightClick" << barset->name() << category; -// mChart->changeSeries(this); + mDrilldownSeries[category] = drilldownSeries; } -}; -//! [1] - -//! [2] -class DrilldownBarSet : public QBarSet -{ - Q_OBJECT -public: - DrilldownBarSet(QString name, DrilldownBarSeries* drilldownSeries) : QBarSet(name) , mSeries(drilldownSeries) {} - DrilldownBarSeries* drilldownSeries(QString category) - { - return mSeries; - } + { +// qDebug() << "DrilldownBarSeries::drilldownSeries" << category << mDrilldownSeries[category]; + return mDrilldownSeries[category]; + } + +public Q_SLOTS: private: - DrilldownBarSeries* mSeries; + + QMap mDrilldownSeries; }; -//! [2] +//! [1] -//! [3] +//! [2] class DrilldownChart : public QChartView { Q_OBJECT @@ -66,14 +57,14 @@ public Q_SLOTS: { qDebug() << "DrilldownChart::handleRightClick" << barset->name() << category; // TODO: continue from here - DrilldownBarSet* drilldownBarSet = static_cast(barset); - changeSeries(drilldownBarSet->drilldownSeries(category)); + DrilldownBarSeries* series = static_cast (sender()); + changeSeries(series->drilldownSeries(category)); } private: QSeries* m_currentSeries; }; -//! [3] +//! [2] int main(int argc, char *argv[]) { @@ -83,7 +74,7 @@ int main(int argc, char *argv[]) DrilldownChart* drilldownChart = new DrilldownChart(&window); drilldownChart->setChartTheme(QChart::ChartThemeIcy); - //! [4] + //! [3] // Define categories QStringList months; months << "Jun" << "Jul" << "Aug" << "Sep"; @@ -91,61 +82,62 @@ int main(int argc, char *argv[]) weeks << "week 1" << "week 2" << "week 3" << "week 4"; QStringList plants; plants << "Habanero" << "Lemon Drop" << "Starfish" << "Aji Amarillo"; + //! [3] + //! [4] + // Create drilldown structure + DrilldownBarSeries* seasonSeries = new DrilldownBarSeries(months, drilldownChart); + seasonSeries->setTitle("Crop by month - Season"); - DrilldownBarSeries* monthlySeries = new DrilldownBarSeries(months, drilldownChart); - monthlySeries->setTitle("Crop by month - Season"); + // Each month in season series has drilldown series for weekly data + foreach (QString month, months) { - foreach (QString plant, plants) { + // Create drilldown series for every week DrilldownBarSeries* weeklySeries = new DrilldownBarSeries(weeks, drilldownChart); - DrilldownBarSet* monthlyCrop = new DrilldownBarSet(plant,weeklySeries); - weeklySeries->setTitle("Crop by week - Month"); - - foreach(QString month, months) { - DrilldownBarSet* weeklyCrop = new DrilldownBarSet(plant,monthlySeries); - - foreach (QString week, weeks ) { - *weeklyCrop << (qrand() % 20); - } + seasonSeries->addDrilldownSeries(month, weeklySeries); - weeklySeries->addBarSet(weeklyCrop); - weeklySeries->setToolTipEnabled(true); - *monthlyCrop << weeklyCrop->total(); - - QObject::connect(weeklyCrop,SIGNAL(clicked(QString)),weeklyCrop,SIGNAL(toggleFloatingValues())); - QObject::connect(weeklySeries,SIGNAL(rightClicked(QBarSet*,QString)),drilldownChart,SLOT(handleRightClick(QBarSet*,QString))); + // Drilling down from weekly data brings us back to season data. + foreach (QString week, weeks) { + weeklySeries->addDrilldownSeries(week, seasonSeries); + weeklySeries->setTitle(QString("Crop by week - " + month)); } - QObject::connect(monthlyCrop,SIGNAL(clicked(QString)),monthlyCrop,SIGNAL(toggleFloatingValues())); - monthlySeries->addBarSet(monthlyCrop); + // Use right click signal to implement drilldown + QObject::connect(weeklySeries,SIGNAL(rightClicked(QBarSet*,QString)),drilldownChart,SLOT(handleRightClick(QBarSet*,QString))); } + //! [4] -/* + //! [5] + // Fill monthly and weekly series with data foreach (QString plant, plants) { - DrilldownBarSeries* weeklySeries = new DrilldownBarSeries(weeks, drilldownChart); - DrilldownBarSet* monthlyCrop = new DrilldownBarSet(plant,weeklySeries); - weeklySeries->setTitle("Crop by week - Month"); - foreach(QString month, months) { - DrilldownBarSet* weeklyCrop = new DrilldownBarSet(plant,monthlySeries); + QBarSet* monthlyCrop = new QBarSet(plant); + foreach (QString month, months) { + QBarSet* weeklyCrop = new QBarSet(plant); foreach (QString week, weeks ) { *weeklyCrop << (qrand() % 20); } - weeklySeries->addBarSet(weeklyCrop); - weeklySeries->setToolTipEnabled(true); + // Get the drilldown series from upper level series and add crop to it. + seasonSeries->drilldownSeries(month)->addBarSet(weeklyCrop); + seasonSeries->drilldownSeries(month)->setToolTipEnabled(true); *monthlyCrop << weeklyCrop->total(); + QObject::connect(weeklyCrop,SIGNAL(clicked(QString)),weeklyCrop,SIGNAL(toggleFloatingValues())); - QObject::connect(weeklySeries,SIGNAL(rightClicked(QBarSet*,QString)),drilldownChart,SLOT(handleRightClick(QBarSet*,QString))); } + seasonSeries->addBarSet(monthlyCrop); QObject::connect(monthlyCrop,SIGNAL(clicked(QString)),monthlyCrop,SIGNAL(toggleFloatingValues())); - monthlySeries->addBarSet(monthlyCrop); } -*/ - QObject::connect(monthlySeries,SIGNAL(rightClicked(QBarSet*,QString)),drilldownChart,SLOT(handleRightClick(QBarSet*,QString))); + //! [5] + + seasonSeries->setToolTipEnabled(true); + + // Enable drilldown from season series using right click. + QObject::connect(seasonSeries,SIGNAL(rightClicked(QBarSet*,QString)),drilldownChart,SLOT(handleRightClick(QBarSet*,QString))); - monthlySeries->setToolTipEnabled(true); - drilldownChart->changeSeries(monthlySeries); - drilldownChart->setChartTitle(monthlySeries->title()); + // Show season series in initial view + drilldownChart->changeSeries(seasonSeries); + drilldownChart->setChartTitle(seasonSeries->title()); + // Disable axis, since they don't really apply to bar chart drilldownChart->axisX()->setAxisVisible(false); drilldownChart->axisX()->setGridVisible(false); drilldownChart->axisX()->setLabelsVisible(false); diff --git a/src/barchart/stackedbarpresenter.cpp b/src/barchart/stackedbarpresenter.cpp index b126233..6588a15 100644 --- a/src/barchart/stackedbarpresenter.cpp +++ b/src/barchart/stackedbarpresenter.cpp @@ -15,7 +15,6 @@ StackedBarPresenter::StackedBarPresenter(QBarSeries *series, QGraphicsItem *pare StackedBarPresenter::~StackedBarPresenter() { - qDebug() << "StackedBarPresenter deleted"; } diff --git a/src/chartdataset.cpp b/src/chartdataset.cpp index 0155cf7..e5d33c6 100644 --- a/src/chartdataset.cpp +++ b/src/chartdataset.cpp @@ -213,12 +213,20 @@ void ChartDataSet::calculateDomain(QSeries* series,Domain* domain) const case QSeries::SeriesTypeScatter: { QScatterSeries *scatterSeries = qobject_cast(series); Q_ASSERT(scatterSeries); + qreal minX(domain->minX()); + qreal minY(domain->minY()); + qreal maxX(domain->maxX()); + qreal maxY(domain->maxY()); foreach (QPointF point, scatterSeries->data()) { - domain->setMinX(qMin(domain->minX(), point.x())); - domain->setMinY(qMax(domain->maxX(), point.x())); - domain->setMaxX(qMin(domain->minY(), point.y())); - domain->setMaxY(qMax(domain->maxY(), point.y())); + minX = qMin(minX, point.x()); + minY = qMin(minY, point.y()); + maxX = qMax(maxX, point.x()); + maxY = qMax(maxY, point.y()); } + domain->setMinX(minX); + domain->setMinY(minY); + domain->setMaxX(maxX); + domain->setMaxY(maxY); break; } diff --git a/src/chartpresenter.cpp b/src/chartpresenter.cpp index b8e4fa8..ed4b803 100644 --- a/src/chartpresenter.cpp +++ b/src/chartpresenter.cpp @@ -219,9 +219,13 @@ void ChartPresenter::handleSeriesAdded(QSeries* series,Domain* domain) scatterSeries, SIGNAL(clicked(QPointF))); QObject::connect(this, SIGNAL(geometryChanged(const QRectF&)), scatterPresenter, SLOT(handleGeometryChanged(const QRectF&))); + QObject::connect(domain, SIGNAL(domainChanged(qreal,qreal,qreal,qreal)), + scatterPresenter, SLOT(handleDomainChanged(qreal,qreal,qreal,qreal))); m_chartTheme->decorate(scatterPresenter, scatterSeries, m_chartItems.count()); m_chartItems.insert(scatterSeries, scatterPresenter); - if(m_rect.isValid()) scatterPresenter->handleGeometryChanged(m_rect); + if (m_rect.isValid()) + scatterPresenter->handleGeometryChanged(m_rect); + scatterPresenter->handleDomainChanged(domain->minX(), domain->maxX(), domain->minY(), domain->maxY()); break; } case QSeries::SeriesTypePie: { diff --git a/src/qchartaxiscategories.h b/src/qchartaxiscategories.h index ae878ea..16261c6 100644 --- a/src/qchartaxiscategories.h +++ b/src/qchartaxiscategories.h @@ -4,7 +4,7 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE -class QChartAxisCategories : public QObject +class QTCOMMERCIALCHART_EXPORT QChartAxisCategories : public QObject { Q_OBJECT private: diff --git a/src/scatterseries/scatterpresenter.cpp b/src/scatterseries/scatterpresenter.cpp index f190417..369f52e 100644 --- a/src/scatterseries/scatterpresenter.cpp +++ b/src/scatterseries/scatterpresenter.cpp @@ -18,10 +18,10 @@ ScatterPresenter::ScatterPresenter(QScatterSeries *series, QGraphicsObject *pare m_minY(0), m_maxY(0), m_series(series), - m_boundingRect() + m_clippingRect() { if (parent) - m_boundingRect = parent->boundingRect(); + m_clippingRect = parent->boundingRect(); if (series) { connect(series, SIGNAL(changed()), this, SLOT(handleModelChanged())); @@ -38,16 +38,16 @@ ScatterPresenter::ScatterPresenter(QScatterSeries *series, QGraphicsObject *pare void ScatterPresenter::handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY) { - m_minX=minX; - m_maxX=maxX; - m_minY=minY; - m_maxY=maxY; + m_minX = minX; + m_maxX = maxX; + m_minY = minY; + m_maxY = maxY; changeGeometry(); } void ScatterPresenter::handleGeometryChanged(const QRectF& rect) { - m_boundingRect = rect.translated(-rect.topLeft()); + m_clippingRect = rect.translated(-rect.topLeft()); changeGeometry(); setPos(rect.topLeft()); } @@ -61,7 +61,7 @@ void ScatterPresenter::handleModelChanged() void ScatterPresenter::paint(QPainter *painter, const QStyleOptionGraphicsItem */*option*/, QWidget */*widget*/) { painter->save(); - painter->setClipRect(m_boundingRect); + painter->setClipRect(m_clippingRect); // TODO: how to draw a drop shadow? // Now using a custom implementation for drop shadow instead of QGraphicsDropShadowEffect. @@ -104,17 +104,17 @@ void ScatterPresenter::mousePressEvent(QGraphicsSceneMouseEvent *event) void ScatterPresenter::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { QPointF clickedPoint( - m_minX + (event->lastPos().x() / m_boundingRect.width()) * (m_maxX-m_minX), - m_maxY - (event->lastPos().y() / m_boundingRect.height()) * (m_maxY-m_minY)); + m_minX + (event->lastPos().x() / m_clippingRect.width()) * (m_maxX-m_minX), + m_maxY - (event->lastPos().y() / m_clippingRect.height()) * (m_maxY-m_minY)); emit clicked(clickedPoint); } void ScatterPresenter::changeGeometry() { - if (m_boundingRect.isValid()) { + if (m_clippingRect.isValid()) { prepareGeometryChange(); - qreal scalex = m_boundingRect.width() / (m_maxX-m_minX); - qreal scaley = m_boundingRect.height() / (m_maxY-m_minY); + qreal scalex = m_clippingRect.width() / (m_maxX - m_minX); + qreal scaley = m_clippingRect.height() / (m_maxY - m_minY); int shape = m_series->shape(); m_path = QPainterPath(); @@ -124,7 +124,7 @@ void ScatterPresenter::changeGeometry() foreach (QPointF point, m_series->data()) { // Convert relative coordinates to absolute pixel coordinates that can be used for drawing qreal x = point.x() * scalex - m_minX * scalex - size / 2; - qreal y = m_boundingRect.height() - point.y() * scaley + m_minY * scaley - size / 2; + qreal y = m_clippingRect.height() - point.y() * scaley + m_minY * scaley - size / 2; if (x < scene()->width() && y < scene()->height()) { switch (shape) { diff --git a/src/scatterseries/scatterpresenter_p.h b/src/scatterseries/scatterpresenter_p.h index ebd4bfa..1e500ff 100644 --- a/src/scatterseries/scatterpresenter_p.h +++ b/src/scatterseries/scatterpresenter_p.h @@ -39,7 +39,7 @@ public: qreal m_minY; qreal m_maxY; QScatterSeries *m_series; - QRectF m_boundingRect; + QRectF m_clippingRect; QPen m_markerPen; QBrush m_markerBrush; QPainterPath m_path; diff --git a/test/chartwidgettest/mainwidget.cpp b/test/chartwidgettest/mainwidget.cpp index 0e573e9..b4ccb1d 100644 --- a/test/chartwidgettest/mainwidget.cpp +++ b/test/chartwidgettest/mainwidget.cpp @@ -49,15 +49,6 @@ MainWidget::MainWidget(QWidget *parent) : QGridLayout *mainLayout = new QGridLayout(); mainLayout->addLayout(grid, 0, 0); - // Init series type specific controls - initPieControls(); - mainLayout->addLayout(m_pieLayout, 2, 0); - // Scatter series specific settings -// m_scatterLayout = new QGridLayout(); -// m_scatterLayout->addWidget(new QLabel("scatter"), 0, 0); -// m_scatterLayout->setEnabled(false); -// mainLayout->addLayout(m_scatterLayout, 1, 0); - // Add layouts and the chart widget to the main layout mainLayout->addWidget(m_chartView, 0, 1, 3, 1); setLayout(mainLayout); @@ -153,33 +144,6 @@ void MainWidget::antiAliasToggled(bool enabled) m_chartView->setRenderHint(QPainter::Antialiasing, enabled); } -void MainWidget::initPieControls() -{ - // Pie series specific settings - // Pie size factory - QDoubleSpinBox *pieSizeSpin = new QDoubleSpinBox(); - pieSizeSpin->setMinimum(LONG_MIN); - pieSizeSpin->setMaximum(LONG_MAX); - pieSizeSpin->setValue(1.0); - pieSizeSpin->setSingleStep(0.1); - connect(pieSizeSpin, SIGNAL(valueChanged(double)), this, SLOT(setPieSizeFactor(double))); - // Pie position - QComboBox *piePosCombo = new QComboBox(this); - piePosCombo->addItem("Maximized"); - piePosCombo->addItem("Top left"); - piePosCombo->addItem("Top right"); - piePosCombo->addItem("Bottom left"); - piePosCombo->addItem("Bottom right"); - connect(piePosCombo, SIGNAL(currentIndexChanged(int)), - this, SLOT(setPiePosition(int))); - m_pieLayout = new QGridLayout(); - m_pieLayout->setEnabled(false); - m_pieLayout->addWidget(new QLabel("Pie size factor"), 0, 0); - m_pieLayout->addWidget(pieSizeSpin, 0, 1); - m_pieLayout->addWidget(new QLabel("Pie position"), 1, 0); - m_pieLayout->addWidget(piePosCombo, 1, 1); -} - void MainWidget::addSeries() { if (!m_addSerieDialog) { @@ -376,17 +340,3 @@ void MainWidget::changeChartTheme(int themeIndex) s.setWidth(s.width()+1); resize(s); } - -void MainWidget::setPieSizeFactor(double size) -{ - QPieSeries *pie = qobject_cast(m_currentSeries); - if (pie) - pie->setSizeFactor(qreal(size)); -} - -void MainWidget::setPiePosition(int position) -{ - QPieSeries *pie = qobject_cast(m_currentSeries); - if (pie) - pie->setPosition((QPieSeries::PiePosition) position); -} diff --git a/test/chartwidgettest/mainwidget.h b/test/chartwidgettest/mainwidget.h index 2bcbddc..567e27c 100644 --- a/test/chartwidgettest/mainwidget.h +++ b/test/chartwidgettest/mainwidget.h @@ -27,7 +27,6 @@ private: void initScaleControls(QGridLayout *grid); void initThemeCombo(QGridLayout *grid); void initCheckboxes(QGridLayout *grid); - void initPieControls(); private slots: void addSeries(); @@ -41,8 +40,6 @@ private slots: void antiAliasToggled(bool enabled); void setCurrentSeries(QSeries *series); void changeChartTheme(int themeIndex); - void setPieSizeFactor(double margin); - void setPiePosition(int position); QList generateTestData(int columnCount, int rowCount, QString dataCharacteristics); QStringList generateLabels(int count); @@ -57,7 +54,6 @@ private: QString m_defaultSeriesName; QSeries *m_currentSeries; QGridLayout *m_scatterLayout; - QGridLayout *m_pieLayout; }; #endif // MAINWIDGET_H