diff --git a/charts.pro b/charts.pro index 0f71ff7..a7d70df 100644 --- a/charts.pro +++ b/charts.pro @@ -1,9 +1,9 @@ !include(common.pri) { - error('missing common.pri') + error('missing common.pri') } TEMPLATE = subdirs -SUBDIRS += src example test +SUBDIRS += src example test CONFIG += ordered QMAKE_CXXFLAGS += -g -Wall unix:QMAKE_DISTCLEAN += -r build bin diff --git a/integrated.pri b/integrated.pri index 25d92af..7d6a912 100644 --- a/integrated.pri +++ b/integrated.pri @@ -9,24 +9,24 @@ integrated_build:{ #this is ugly hack to work around missing rpath, it simply copies lib win32:{ copylib.target = $$CHART_BUILD_BIN_DIR/QtCommercialChartd.dll - copylib.commands = $$QMAKE_COPY $$CHART_BUILD_LIB_DIR\QtCommercialChartd.dll $$CHART_BUILD_BIN_DIR + copylib.commands = $$QMAKE_COPY $$CHART_BUILD_LIB_DIR\\QtCommercialChartd.dll $$CHART_BUILD_BIN_DIR copylib.depends = $$CHART_BUILD_LIB_DIR/QtCommercialChartd.dll PRE_TARGETDEPS += $$CHART_BUILD_BIN_DIR/QtCommercialChartd.dll QMAKE_EXTRA_TARGETS +=copylib } } else { - LIBS += -lQtCommercialChart + LIBS += -lQtCommercialChart - #this is ugly hack to work around missing rpath, it simply copies lib - win32:{ - copylib.target = $$CHART_BUILD_BIN_DIR/QtCommercialChart - copylib.commands = $$QMAKE_COPY $$CHART_BUILD_LIB_DIR\QtCommercialChart.dll $$CHART_BUILD_BIN_DIR - copylib.depends = $$CHART_BUILD_LIB_DIR/QtCommercialChart.dll - PRE_TARGETDEPS += $$CHART_BUILD_BIN_DIR/QtCommercialChart - QMAKE_EXTRA_TARGETS +=copylib + #this is ugly hack to work around missing rpath, it simply copies lib + win32: { + copylib.target = $$CHART_BUILD_BIN_DIR/QtCommercialChart + copylib.commands = $$QMAKE_COPY $$CHART_BUILD_LIB_DIR\\QtCommercialChart.dll $$CHART_BUILD_BIN_DIR + copylib.depends = $$CHART_BUILD_LIB_DIR/QtCommercialChart.dll + PRE_TARGETDEPS += $$CHART_BUILD_BIN_DIR/QtCommercialChart + QMAKE_EXTRA_TARGETS +=copylib } } -}else{ +} else { CONFIG+=qtcommercialchart } diff --git a/src/pie/main.cpp b/src/pie/main.cpp deleted file mode 100644 index 9e45e97..0000000 --- a/src/pie/main.cpp +++ /dev/null @@ -1,168 +0,0 @@ -#include -#include -#include - -class Slice : public QGraphicsItem -{ -public: - Slice(const QColor& color, qreal startAngle, qreal span) - :m_color(color), - m_startAngle(startAngle), - m_span(span) - { - setAcceptHoverEvents(true); - } - - ~Slice() - { - - } - - virtual QRectF boundingRect() const - { - return parentItem()->boundingRect(); - } - - QPainterPath shape() const - { - qreal angle = (-m_startAngle) + (90); - qreal span = -m_span; - - QPainterPath path; - path.moveTo(boundingRect().center()); - path.arcTo(boundingRect(), angle, span); - - // TODO: draw the shape so that it might have a hole in the center - // - Sin & Cos will be needed to find inner/outer arc endpoints - - // dx, dy are offsets from the center - //qreal l = boundingRect().height(); - //qreal dx = qSin(angle*(M_PI/180)) * l; - //qreal dy = qCos(angle*(M_PI/180)) * l; - - // TODO: exploded slice? - - return path; - } - - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) - { - // Setup painter - painter->setBrush(m_color); - QPen pen; - //pen.setColor(m_color.darker()); - pen.setColor(Qt::gray); - pen.setWidth(1); - painter->setPen(pen); - - // From Qt docs: - // The startAngle and spanAngle must be specified in 1/16th of a degree, i.e. a full circle equals 5760 (16 * 360). - // Positive values for the angles mean counter-clockwise while negative values mean the clockwise direction. - // Zero degrees is at the 3 o'clock position. - // - // For sake of simplicity convert this so that zero degrees is at 12 o'clock and full circle is 360. - //qreal angle = (-m_startAngle*16) + (90*16); - //qreal span = -m_span*16; - //painter->drawPie(boundingRect(), angle, span); - - painter->drawPath(shape()); - } - - virtual void hoverEnterEvent( QGraphicsSceneHoverEvent * event) - { - QGraphicsItem::hoverEnterEvent(event); - qDebug() << "hover" << m_color << m_startAngle << m_span; - } - -private: - QColor m_color; - qreal m_startAngle; - qreal m_span; -}; - -class PieChart : public QGraphicsItem -{ -public: - PieChart() - { - qsrand(QTime::currentTime().msec()); - } - - ~PieChart() - { - - } - - QColor randomColor() - { - QColor c; - c.setRed(qrand() % 255); - c.setGreen(qrand() % 255); - c.setBlue(qrand() % 255); - return c; - } - - void setData(QList data) - { - qreal fullPie = 360; - - qreal total = 0; - foreach (qreal value, data) - total += value; - - qreal angle = 0; - foreach (qreal value, data) { - qreal span = value / total * fullPie; - Slice *slice = new Slice(randomColor(), angle, span); - slice->setParentItem(this); - m_slices.append(slice); - angle += span; - } - } - - virtual QRectF boundingRect() const - { - return QRectF(-200, -200, 200, 200); - } - - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) - { - //painter->setBrush(Qt::red); - //painter->drawRect(boundingRect()); - } - -private: - QList m_slices; - QSizeF m_size; -}; - - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - - QGraphicsScene scene; - - PieChart *pieChart = new PieChart(); - scene.addItem(pieChart); - - QGraphicsView view(&scene); - view.setRenderHint(QPainter::Antialiasing); - view.resize(400, 300); - view.show(); - - QList data; - data << 1; - data << 2; - data << 3; - data << 20; - data << 2; - data << 3; - data << 10; - data << 2; - data << 1; - data << 5; - pieChart->setData(data); - - return a.exec(); -} diff --git a/src/pie/pie.pro b/src/pie/pie.pro deleted file mode 100644 index 97a82f4..0000000 --- a/src/pie/pie.pro +++ /dev/null @@ -1,15 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2012-01-11T14:41:14 -# -#------------------------------------------------- - -QT += core gui - -TARGET = pie -TEMPLATE = app - - -SOURCES += main.cpp - -HEADERS += diff --git a/src/pieslice.cpp b/src/pieslice.cpp index d2800b3..4ba5669 100644 --- a/src/pieslice.cpp +++ b/src/pieslice.cpp @@ -4,10 +4,11 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE -PieSlice::PieSlice(const QColor& color, qreal startAngle, qreal span) +PieSlice::PieSlice(const QColor& color, qreal startAngle, qreal span, QRectF rect) : m_color(color), m_startAngle(startAngle), - m_span(span) + m_span(span), + m_rect(rect) { setAcceptHoverEvents(true); } @@ -18,7 +19,7 @@ PieSlice::~PieSlice() QRectF PieSlice::boundingRect() const { - return parentItem()->boundingRect(); + return m_rect; } QPainterPath PieSlice::shape() const diff --git a/src/pieslice.h b/src/pieslice.h index 71c4dfd..72f95f1 100644 --- a/src/pieslice.h +++ b/src/pieslice.h @@ -11,7 +11,7 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE class PieSlice : public QGraphicsItem { public: - PieSlice(const QColor& color, qreal startAngle, qreal span); + PieSlice(const QColor& color, qreal startAngle, qreal span, QRectF rect); ~PieSlice(); public: // from QGraphicsItem @@ -20,10 +20,11 @@ public: // from QGraphicsItem void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); void hoverEnterEvent(QGraphicsSceneHoverEvent * event); -private: +public: QColor m_color; qreal m_startAngle; qreal m_span; + QRectF m_rect; }; QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/qpieseries.cpp b/src/qpieseries.cpp index d80cf37..a3c57e7 100644 --- a/src/qpieseries.cpp +++ b/src/qpieseries.cpp @@ -7,7 +7,8 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE QPieSeries::QPieSeries(QList x, QGraphicsObject *parent) : QChartSeries(parent), - m_x(x) + m_x(x), + m_sizeFactor(1.0) { // Create slices qreal fullPie = 360; @@ -17,23 +18,62 @@ QPieSeries::QPieSeries(QList x, QGraphicsObject *parent) : QGraphicsItem *parentItem = qobject_cast(parent); Q_ASSERT(parentItem); + m_chartSize = parentItem->boundingRect(); qreal angle = 0; // TODO: no need to create new slices in case size changed; we should re-use the existing ones foreach (qreal value, m_x) { qreal span = value / total * fullPie; - PieSlice *slice = new PieSlice(randomColor(), angle, span); + PieSlice *slice = new PieSlice(randomColor(), angle, span, parentItem->boundingRect()); slice->setParentItem(parentItem); m_slices.append(slice); angle += span; } + + resizeSlices(m_chartSize); } QPieSeries::~QPieSeries() { + while (m_slices.count()) + delete m_slices.takeLast(); } -void QPieSeries::chartSizeChanged(QRectF /*rect*/) +void QPieSeries::chartSizeChanged(QRectF chartRect) { + // TODO: allow user setting the size? + // TODO: allow user defining the margins? + m_chartSize = chartRect; + resizeSlices(m_chartSize); +} + +void QPieSeries::resizeSlices(QRectF rect) +{ + QRectF tempRect = rect; + if (tempRect.width() < tempRect.height()) { + tempRect.setWidth(tempRect.width() * m_sizeFactor); + tempRect.setHeight(tempRect.width()); + tempRect.moveCenter(rect.center()); + } else { + tempRect.setHeight(tempRect.height() * m_sizeFactor); + tempRect.setWidth(tempRect.height()); + tempRect.moveCenter(rect.center()); + } + + foreach (PieSlice *slice, m_slices) + slice->m_rect = tempRect; +} + +void QPieSeries::setSizeFactor(qreal factor) +{ + if (factor > 0.0) + m_sizeFactor = factor; + 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(); } QColor QPieSeries::randomColor() @@ -45,9 +85,6 @@ QColor QPieSeries::randomColor() return c; } -void QPieSeries::setData(QList data) -{ -} #include "moc_qpieseries.cpp" diff --git a/src/qpieseries.h b/src/qpieseries.h index ee9518f..e58da6f 100644 --- a/src/qpieseries.h +++ b/src/qpieseries.h @@ -13,12 +13,14 @@ class PieSlice; class QTCOMMERCIALCHART_EXPORT QPieSeries : public QChartSeries { Q_OBJECT + public: // TODO: use a generic data class instead of x and y QPieSeries(QList x, QGraphicsObject *parent = 0); ~QPieSeries(); QColor randomColor(); - void setData(QList data); + void setSizeFactor(qreal sizeFactor); + qreal sizeFactor() { return m_sizeFactor; } public: // from QChartSeries QChartSeriesType type() const { return QChartSeries::SeriesTypePie; } @@ -27,12 +29,14 @@ public Q_SLOTS: void chartSizeChanged(QRectF rect); private: + void resizeSlices(QRectF rect); //Q_DECLARE_PRIVATE(QPieSeries) Q_DISABLE_COPY(QPieSeries) // TODO: move the followin to internal impl QList m_x; QList m_slices; - QSizeF m_size; + QRectF m_chartSize; + qreal m_sizeFactor; }; QTCOMMERCIALCHART_END_NAMESPACE diff --git a/test/chartwidgettest/chartwidgettest.pro b/test/chartwidgettest/chartwidgettest.pro index 79471c4..3f2e8ea 100644 --- a/test/chartwidgettest/chartwidgettest.pro +++ b/test/chartwidgettest/chartwidgettest.pro @@ -1,5 +1,9 @@ -include( ../../common.pri ) -include( ../../integrated.pri ) +!include( ../../common.pri ) { + error( "Couldn't find the common.pri file!" ) +} +!include( ../../integrated.pri ) { + error( "Couldn't find the integrated.pri file !") +} TARGET = chartwidgettest TEMPLATE = app @@ -9,19 +13,13 @@ contains(QT_MAJOR_VERSION, 5) { QT += widgets } - OBJECTS_DIR = tmp MOC_DIR = tmp SOURCES += main.cpp \ mainwidget.cpp \ -# qscatterseries.cpp \ -# qseriespointgraphicsitem.cpp \ dataseriedialog.cpp HEADERS += \ mainwidget.h \ -# qscatterseries.h \ -# qseriespointgraphicsitem.h \ dataseriedialog.h - diff --git a/test/chartwidgettest/mainwidget.cpp b/test/chartwidgettest/mainwidget.cpp index f37845f..9430082 100644 --- a/test/chartwidgettest/mainwidget.cpp +++ b/test/chartwidgettest/mainwidget.cpp @@ -1,5 +1,7 @@ #include "mainwidget.h" #include "dataseriedialog.h" +#include "qchartseries.h" +#include "qpieseries.h" #include #include #include @@ -56,7 +58,7 @@ MainWidget::MainWidget(QWidget *parent) : connect(m_yMaxSpin, SIGNAL(valueChanged(int)), this, SLOT(yMaxChanged(int))); QGridLayout *grid = new QGridLayout(); - QHBoxLayout *hbox = new QHBoxLayout(); + QGridLayout *mainLayout = new QGridLayout(); //grid->addWidget(new QLabel("Add series:"), 0, 0); grid->addWidget(addSeriesButton, 0, 1); grid->addWidget(new QLabel("Background:"), 2, 0); @@ -74,23 +76,42 @@ MainWidget::MainWidget(QWidget *parent) : grid->addWidget(new QLabel(""), 8, 0); grid->setRowStretch(8, 1); - hbox->addLayout(grid); + mainLayout->addLayout(grid, 0, 0); + + // Scatter specific settings + m_scatterLayout = new QGridLayout(); + m_scatterLayout->addWidget(new QLabel("scatter"), 0, 0); + m_scatterLayout->setEnabled(false); + + // Pie specific settings + m_pieLayout = new QGridLayout(); + m_pieLayout->addWidget(new QLabel("Pie size factor"), 0, 0); + 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))); + m_pieLayout->setEnabled(false); + m_pieLayout->addWidget(pieSizeSpin, 0, 1); + + mainLayout->addLayout(m_scatterLayout, 1, 0); + mainLayout->addLayout(m_pieLayout, 2, 0); m_chartWidget = new QChartWidget(this); //m_chartWidget->setColor(Qt::red); - hbox->addWidget(m_chartWidget); + mainLayout->addWidget(m_chartWidget, 0, 1, 3, 1); // hbox->setStretch(1, 1); - setLayout(hbox); + setLayout(mainLayout); m_autoScaleCheck->setChecked(true); - chartTypeChanged(4); testDataChanged(0); } void MainWidget::addSeries() { - DataSerieDialog dialog(m_defaultSeries, this); + DataSerieDialog dialog(m_defaultSeriesName, this); connect(&dialog, SIGNAL(accepted(QString, QString)), this, SLOT(addSeries(QString, QString))); dialog.exec(); } @@ -98,9 +119,8 @@ void MainWidget::addSeries() void MainWidget::addSeries(QString series, QString data) { qDebug() << "addSeries: " << series << " data: " << data; - m_defaultSeries = series; - - QXYChartSeries* series0 = QXYChartSeries::create(); + m_defaultSeriesName = series; + QChartSeries *newSeries = QXYChartSeries::create(); // TODO: a dedicated data class for storing x and y values QList x; @@ -112,56 +132,59 @@ void MainWidget::addSeries(QString series, QString data) y.append(i); } for (int i = 0; i < 20; i++) - series0->add(i, i); + ((QXYChartSeries *)newSeries)->add(i, i); } else if (data == "linear, 1M") { for (int i = 0; i < 10000; i++) { x.append(i); y.append(20); } for (int i = 0; i < 1000000; i++) - series0->add(i, 10); + ((QXYChartSeries *)newSeries)->add(i, 10); } else if (data == "SIN") { for (int i = 0; i < 100; i++) { x.append(i); y.append(abs(sin(3.14159265358979 / 50 * i) * 100)); } for (int i = 0; i < 100; i++) - series0->add(i, abs(sin(3.14159265358979 / 50 * i) * 100)); + ((QXYChartSeries *)newSeries)->add(i, abs(sin(3.14159265358979 / 50 * i) * 100)); } else if (data == "SIN + random") { for (qreal i = 0; i < 100; i += 0.1) { x.append(i + (rand() % 5)); y.append(abs(sin(3.14159265358979 / 50 * i) * 100) + (rand() % 5)); } for (qreal i = 0; i < 100; i += 0.1) - series0->add(i + (rand() % 5), abs(sin(3.14159265358979 / 50 * i) * 100) + (rand() % 5)); + ((QXYChartSeries *)newSeries)->add(i + (rand() % 5), abs(sin(3.14159265358979 / 50 * i) * 100) + (rand() % 5)); } else { // TODO: check if data has a valid file name } // TODO: color of the series if (series == "Scatter") { - /*QChartSeries* scatterSeries = */ - m_chartWidget->createSeries(x, y, QChartSeries::SeriesTypeScatter); + newSeries = m_chartWidget->createSeries(x, y, QChartSeries::SeriesTypeScatter); } else if (series == "Pie") { - m_chartWidget->createSeries(x, y, QChartSeries::SeriesTypePie); + newSeries = m_chartWidget->createSeries(x, y, QChartSeries::SeriesTypePie); } else if (series == "Line") { - m_chartWidget->addSeries(series0); + m_chartWidget->addSeries(newSeries); } else { // TODO } + + setCurrentSeries(newSeries); } -void MainWidget::chartTypeChanged(int itemIndex) +void MainWidget::setCurrentSeries(QChartSeries *series) { - // TODO: change chart type - switch (itemIndex) { - case 4: - //m_chartWidget->setType(4); + m_currentSeries = series; + switch (m_currentSeries->type()) { + case QChartSeries::SeriesTypeLine: break; - default: { - //m_chartWidget->setType(0); + case QChartSeries::SeriesTypeScatter: + break; + case QChartSeries::SeriesTypePie: + break; + default: + Q_ASSERT(false); break; - } } } @@ -239,3 +262,10 @@ void MainWidget::yMaxChanged(int value) { qDebug() << "yMaxChanged: " << value; } + +void MainWidget::setPieSizeFactor(double size) +{ + QPieSeries *pie = qobject_cast(m_currentSeries); + Q_ASSERT(pie); + pie->setSizeFactor(qreal(size)); +} diff --git a/test/chartwidgettest/mainwidget.h b/test/chartwidgettest/mainwidget.h index 8503c18..3e5fc39 100644 --- a/test/chartwidgettest/mainwidget.h +++ b/test/chartwidgettest/mainwidget.h @@ -7,6 +7,7 @@ class QSpinBox; class QCheckBox; +class QGridLayout; QTCOMMERCIALCHART_USE_NAMESPACE @@ -19,7 +20,6 @@ public: signals: private slots: - void chartTypeChanged(int itemIndex); void addSeries(); void addSeries(QString series, QString data); void testDataChanged(int itemIndex); @@ -29,6 +29,8 @@ private slots: void xMaxChanged(int value); void yMinChanged(int value); void yMaxChanged(int value); + void setCurrentSeries(QChartSeries *series); + void setPieSizeFactor(double margin); private: QChartWidget *m_chartWidget; @@ -37,7 +39,10 @@ private: QSpinBox *m_xMaxSpin; QSpinBox *m_yMinSpin; QSpinBox *m_yMaxSpin; - QString m_defaultSeries; + QString m_defaultSeriesName; + QChartSeries *m_currentSeries; + QGridLayout *m_scatterLayout; + QGridLayout *m_pieLayout; }; #endif // MAINWIDGET_H