diff --git a/src/pieslice.cpp b/src/pieslice.cpp index 4ba5669..850bc84 100644 --- a/src/pieslice.cpp +++ b/src/pieslice.cpp @@ -48,6 +48,7 @@ void PieSlice::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, { // Setup painter painter->setBrush(m_color); + painter->setRenderHint(QPainter::Antialiasing); QPen pen; //pen.setColor(m_color.darker()); pen.setColor(Qt::gray); diff --git a/src/qchart.cpp b/src/qchart.cpp index 63f69ab..c9d00b4 100644 --- a/src/qchart.cpp +++ b/src/qchart.cpp @@ -213,6 +213,9 @@ void QChart::setTheme(QChart::ChartThemeId theme) m_themeColors.append(QColor(160, 160, 113)); m_themeColors.append(QColor(210, 210, 52)); m_themeColors.append(QColor(136, 114, 58)); + + m_backgroundGradient.setColorAt(0.0, QColor(QRgb(0xff9d844d))); + m_backgroundGradient.setColorAt(1.0, QColor(QRgb(0xffafafaf))); break; case QChart::ChartThemeIcy: m_themeColors.append(QColor(0, 3, 165)); @@ -221,6 +224,9 @@ void QChart::setTheme(QChart::ChartThemeId theme) m_themeColors.append(QColor(48, 97, 87)); m_themeColors.append(QColor(19, 71, 90)); m_themeColors.append(QColor(110, 70, 228)); + + m_backgroundGradient.setColorAt(0.0, QColor(QRgb(0xffe4ffff))); + m_backgroundGradient.setColorAt(1.0, QColor(QRgb(0xffafafaf))); break; case QChart::ChartThemeGrayscale: m_themeColors.append(QColor(0, 0, 0)); @@ -228,12 +234,28 @@ void QChart::setTheme(QChart::ChartThemeId theme) m_themeColors.append(QColor(100, 100, 100)); m_themeColors.append(QColor(140, 140, 140)); m_themeColors.append(QColor(180, 180, 180)); + + m_backgroundGradient.setColorAt(0.0, QColor(QRgb(0xffffffff))); + m_backgroundGradient.setColorAt(1.0, QColor(QRgb(0xffafafaf))); + break; + case QChart::ChartThemeUnnamed1: + m_themeColors.append(QColor(QRgb(0xff3fa9f5))); + m_themeColors.append(QColor(QRgb(0xff7AC943))); + m_themeColors.append(QColor(QRgb(0xffFF931E))); + m_themeColors.append(QColor(QRgb(0xffFF1D25))); + m_themeColors.append(QColor(QRgb(0xffFF7BAC))); + + m_backgroundGradient.setColorAt(0.0, QColor(QRgb(0xfff3dc9e))); + m_backgroundGradient.setColorAt(1.0, QColor(QRgb(0xffafafaf))); break; default: Q_ASSERT(false); break; } + m_background->setBrush(m_backgroundGradient); + m_background->setPen(Qt::NoPen); + foreach(QChartSeries* series, m_chartSeries) { // TODO: other series interested on themes? if (series->type() == QChartSeries::SeriesTypeLine) { diff --git a/src/qchart.h b/src/qchart.h index b2d05d6..6a5da93 100644 --- a/src/qchart.h +++ b/src/qchart.h @@ -30,7 +30,8 @@ public: enum ChartThemeId { ChartThemeVanilla = 0, ChartThemeIcy, - ChartThemeGrayscale + ChartThemeGrayscale, + ChartThemeUnnamed1 }; public: diff --git a/src/qchartwidget.cpp b/src/qchartwidget.cpp index e46f462..dc87270 100644 --- a/src/qchartwidget.cpp +++ b/src/qchartwidget.cpp @@ -7,7 +7,8 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE QChartWidget::QChartWidget(QWidget *parent) : -QGraphicsView(parent) + QGraphicsView(parent), + m_rubberBand(QRubberBand::Rectangle, this) { setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); m_scene = new QGraphicsScene(); @@ -17,6 +18,7 @@ QGraphicsView(parent) m_chart = new QChart(); m_scene->addItem(m_chart); + m_rubberBand.setEnabled(true); // TODO: should zoom be enabled by default? show(); } @@ -37,6 +39,41 @@ QSize QChartWidget::sizeHint() const return QSize(100, 100); } +void QChartWidget::mousePressEvent(QMouseEvent *event) +{ + if(m_rubberBand.isEnabled() && event->button() == Qt::LeftButton) { + int margin = m_chart->margin(); + QRect rect(margin, margin, width() - 2 * margin, height() - 2 * margin); + m_origin = event->pos(); + + if (rect.contains(m_origin)) { + m_rubberBand.setGeometry(QRect(m_origin, QSize())); + m_rubberBand.show(); + event->accept(); + } + } +} + +void QChartWidget::mouseMoveEvent(QMouseEvent *event) +{ + if(m_rubberBand.isVisible()) + m_rubberBand.setGeometry(QRect(m_origin, event->pos()).normalized()); +} + +void QChartWidget::mouseReleaseEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton && m_rubberBand.isVisible()) { + m_rubberBand.hide(); + QRect rect = m_rubberBand.geometry(); + m_chart->zoomInToRect(rect); + event->accept(); + } + + if(event->button()==Qt::RightButton) { + m_chart->zoomOut(); + } +} + void QChartWidget::addSeries(QChartSeries* series) { m_chart->addSeries(series); @@ -52,6 +89,11 @@ void QChartWidget::setTheme(QChart::ChartThemeId theme) m_chart->setTheme(theme); } +void QChartWidget::setZoomEnabled(bool enabled) +{ + m_rubberBand.setEnabled(enabled); +} + #include "moc_qchartwidget.cpp" QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/qchartwidget.h b/src/qchartwidget.h index 6cc4321..d0cbf0d 100644 --- a/src/qchartwidget.h +++ b/src/qchartwidget.h @@ -4,8 +4,10 @@ #include "qchartglobal.h" #include "qchart.h" #include +#include class QGraphicsScene; +class QRubberBand; QTCOMMERCIALCHART_BEGIN_NAMESPACE @@ -19,12 +21,9 @@ public: explicit QChartWidget(QWidget *parent = 0); ~QChartWidget(); - //implement from QWidget - void resizeEvent(QResizeEvent *event); - QSize sizeHint() const; - // TODO: addSeries and createSeries are optional solutions // TODO: currently createSeries assumes x, y value pairs. This isn't case with all charts. So is there another createSeries for other types (for example one list of ints)? +public Q_SLOTS: void addSeries(QChartSeries* series); QChartSeries* createSeries(QChartSeries::QChartSeriesType type); @@ -34,11 +33,22 @@ public: */ void setTheme(QChart::ChartThemeId theme); + void setZoomEnabled(bool enabled); + +private: // From QWidget TODO: should these be protected instead? Is QChartWidget meant to be extened by the user? + void resizeEvent(QResizeEvent *event); + QSize sizeHint() const; + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + private: Q_DISABLE_COPY(QChartWidget) + // TODO: move the following to pimpl QGraphicsScene *m_scene; QChart* m_chart; - + QRubberBand m_rubberBand; + QPoint m_origin; }; QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/qpieseries.cpp b/src/qpieseries.cpp index 064aa92..2a2b8e8 100644 --- a/src/qpieseries.cpp +++ b/src/qpieseries.cpp @@ -7,7 +7,8 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE QPieSeries::QPieSeries(QGraphicsObject *parent) : QChartSeries(parent), - m_sizeFactor(1.0) + m_sizeFactor(1.0), + m_position(PiePositionMaximized) { } @@ -84,6 +85,35 @@ void QPieSeries::resizeSlices(QRectF rect) tempRect.moveCenter(rect.center()); } + switch (m_position) { + case PiePositionTopLeft: { + tempRect.setHeight(tempRect.height() / 2); + tempRect.setWidth(tempRect.height()); + tempRect.moveCenter(QPointF(rect.center().x() / 2, rect.center().y() / 2)); + break; + } + case PiePositionTopRight: { + tempRect.setHeight(tempRect.height() / 2); + tempRect.setWidth(tempRect.height()); + tempRect.moveCenter(QPointF((rect.center().x() / 2) * 3, rect.center().y() / 2)); + break; + } + case PiePositionBottomLeft: { + tempRect.setHeight(tempRect.height() / 2); + tempRect.setWidth(tempRect.height()); + tempRect.moveCenter(QPointF(rect.center().x() / 2, (rect.center().y() / 2) * 3)); + break; + } + case PiePositionBottomRight: { + tempRect.setHeight(tempRect.height() / 2); + tempRect.setWidth(tempRect.height()); + tempRect.moveCenter(QPointF((rect.center().x() / 2) * 3, (rect.center().y() / 2) * 3)); + break; + } + default: + break; + } + foreach (PieSlice *slice, m_slices) slice->m_rect = tempRect; } @@ -101,6 +131,18 @@ void QPieSeries::setSizeFactor(qreal factor) parentItem->update(); } +void QPieSeries::setPosition(PiePosition position) +{ + m_position = position; + resizeSlices(m_chartSize); + + // Initiate update via the parent graphics item + // TODO: potential issue: what if this function is called from the parent context? + QGraphicsItem *parentItem = qobject_cast(parent()); + Q_ASSERT(parentItem); + parentItem->update(); +} + #include "moc_qpieseries.cpp" QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/qpieseries.h b/src/qpieseries.h index d2ee898..5dda1de 100644 --- a/src/qpieseries.h +++ b/src/qpieseries.h @@ -15,11 +15,18 @@ class QTCOMMERCIALCHART_EXPORT QPieSeries : public QChartSeries Q_OBJECT public: + enum PiePosition { + PiePositionMaximized = 0, + PiePositionTopLeft, + PiePositionTopRight, + PiePositionBottomLeft, + PiePositionBottomRight + }; + +public: // TODO: use a generic data class instead of x and y QPieSeries(QGraphicsObject *parent = 0); ~QPieSeries(); - void setSizeFactor(qreal sizeFactor); - qreal sizeFactor() { return m_sizeFactor; } public: // from QChartSeries QChartSeriesType type() const { return QChartSeries::SeriesTypePie; } @@ -29,6 +36,9 @@ public: void setSliceColor(int index, QColor color); QColor sliceColor(int index); int sliceCount(); + void setSizeFactor(qreal sizeFactor); + qreal sizeFactor() { return m_sizeFactor; } + void setPosition(PiePosition position); public Q_SLOTS: void chartSizeChanged(QRectF rect); @@ -43,6 +53,7 @@ private: QList m_slices; QRectF m_chartSize; qreal m_sizeFactor; + PiePosition m_position; }; QTCOMMERCIALCHART_END_NAMESPACE diff --git a/test/chartwidgettest/mainwidget.cpp b/test/chartwidgettest/mainwidget.cpp index 41575e3..cdee412 100644 --- a/test/chartwidgettest/mainwidget.cpp +++ b/test/chartwidgettest/mainwidget.cpp @@ -21,14 +21,16 @@ QTCOMMERCIALCHART_USE_NAMESPACE MainWidget::MainWidget(QWidget *parent) : QWidget(parent) { + m_chartWidget = new QChartWidget(this); + QPushButton *addSeriesButton = new QPushButton("Add series"); connect(addSeriesButton, SIGNAL(clicked()), this, SLOT(addSeries())); // Chart background QComboBox *backgroundCombo = new QComboBox(this); - backgroundCombo->addItem("None"); - backgroundCombo->addItem("TODO Grid"); - backgroundCombo->addItem("TODO Image"); + backgroundCombo->addItem("Color"); + backgroundCombo->addItem("Gradient"); + backgroundCombo->addItem("Image"); connect(backgroundCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(backgroundChanged(int))); @@ -62,13 +64,16 @@ MainWidget::MainWidget(QWidget *parent) : chartTheme->addItem("Vanilla"); chartTheme->addItem("Icy"); chartTheme->addItem("Grayscale"); - chartTheme->addItem("Tobedefined"); + chartTheme->addItem("Unnamed1"); connect(chartTheme, SIGNAL(currentIndexChanged(int)), this, SLOT(changeChartTheme(int))); + QCheckBox *zoomCheckBox = new QCheckBox("Zoom enabled"); + connect(zoomCheckBox, SIGNAL(toggled(bool)), m_chartWidget, SLOT(setZoomEnabled(bool))); + zoomCheckBox->setChecked(true); + QGridLayout *grid = new QGridLayout(); QGridLayout *mainLayout = new QGridLayout(); - //grid->addWidget(new QLabel("Add series:"), 0, 0); grid->addWidget(addSeriesButton, 0, 1); grid->addWidget(new QLabel("Background:"), 2, 0); grid->addWidget(backgroundCombo, 2, 1); @@ -83,9 +88,10 @@ MainWidget::MainWidget(QWidget *parent) : grid->addWidget(m_yMaxSpin, 7, 1); grid->addWidget(new QLabel("Chart theme:"), 8, 0); grid->addWidget(chartTheme, 8, 1); + grid->addWidget(zoomCheckBox, 9, 0); // add row with empty label to make all the other rows static - grid->addWidget(new QLabel(""), 9, 0); - grid->setRowStretch(9, 1); + grid->addWidget(new QLabel(""), 10, 0); + grid->setRowStretch(10, 1); mainLayout->addLayout(grid, 0, 0); @@ -95,21 +101,32 @@ MainWidget::MainWidget(QWidget *parent) : m_scatterLayout->setEnabled(false); // Pie specific settings - m_pieLayout = new QGridLayout(); - m_pieLayout->addWidget(new QLabel("Pie size factor"), 0, 0); + // 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); mainLayout->addLayout(m_scatterLayout, 1, 0); mainLayout->addLayout(m_pieLayout, 2, 0); - m_chartWidget = new QChartWidget(this); //m_chartWidget->setColor(Qt::red); mainLayout->addWidget(m_chartWidget, 0, 1, 3, 1); // hbox->setStretch(1, 1); @@ -312,3 +329,10 @@ void MainWidget::setPieSizeFactor(double size) 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 21cf670..f5226e0 100644 --- a/test/chartwidgettest/mainwidget.h +++ b/test/chartwidgettest/mainwidget.h @@ -32,6 +32,7 @@ private slots: void setCurrentSeries(QChartSeries *series); void changeChartTheme(int themeIndex); void setPieSizeFactor(double margin); + void setPiePosition(int position); private: QChartWidget *m_chartWidget;