diff --git a/example/piechartcustomization/main.cpp b/example/piechartcustomization/main.cpp index ad4a782..58021c7 100644 --- a/example/piechartcustomization/main.cpp +++ b/example/piechartcustomization/main.cpp @@ -14,8 +14,6 @@ QTCOMMERCIALCHART_USE_NAMESPACE -Q_DECLARE_METATYPE(QPieSeries::PiePosition) - class CustomSlice : public QPieSlice { Q_OBJECT @@ -52,11 +50,13 @@ class MainWidget : public QWidget public: explicit MainWidget(QWidget* parent = 0) - :QWidget(parent) + :QWidget(parent), + m_slice(0) { m_chartView = new QChartView(); m_chartView->setChartTitle("Piechart customization"); - //m_chartView->setRenderHint(QPainter::Antialiasing); + m_chartView->setRenderHint(QPainter::Antialiasing); + m_chartView->setChartTheme(QChart::ChartThemeIcy); m_series = new QPieSeries(); *m_series << new CustomSlice(10.0, "Slice 1"); @@ -66,27 +66,23 @@ public: *m_series << new CustomSlice(50.0, "Slice 5"); m_chartView->addSeries(m_series); - m_vPosition = new QComboBox(); - m_vPosition->addItem("Top", QPieSeries::PiePositionTop); - m_vPosition->addItem("Bottom", QPieSeries::PiePositionBottom); - m_vPosition->addItem("Center", QPieSeries::PiePositionVCenter); - - m_hPosition = new QComboBox(); - m_hPosition->addItem("Left", QPieSeries::PiePositionLeft); - m_hPosition->addItem("Right", QPieSeries::PiePositionRight); - m_hPosition->addItem("Center", QPieSeries::PiePositionHCenter); + m_hPosition = new QDoubleSpinBox(); + m_hPosition->setMinimum(0.0); + m_hPosition->setMaximum(1.0); + m_hPosition->setSingleStep(0.1); + m_hPosition->setValue(m_series->horizontalPositionFactor()); - m_sizePolicy = new QComboBox(); - m_sizePolicy->addItem("Maximized", QPieSeries::PieSizePolicyMaximized); - m_sizePolicy->addItem("Space for labels", QPieSeries::PieSizePolicyReserveSpaceForLabels); - m_sizePolicy->addItem("Space for exploding", QPieSeries::PieSizePolicyReserveSpaceForExploding); - m_sizePolicy->addItem("Space for all", QPieSeries::PieSizePolicyReserveSpaceForAll); + m_vPosition = new QDoubleSpinBox(); + m_vPosition->setMinimum(0.0); + m_vPosition->setMaximum(1.0); + m_vPosition->setSingleStep(0.1); + m_vPosition->setValue(m_series->verticalPositionFactor()); m_sizeFactor = new QDoubleSpinBox(); m_sizeFactor->setMinimum(0.0); m_sizeFactor->setMaximum(1.0); - m_sizeFactor->setValue(m_series->sizeFactor()); m_sizeFactor->setSingleStep(0.1); + m_sizeFactor->setValue(m_series->sizeFactor()); m_startAngle = new QDoubleSpinBox(); m_startAngle->setMinimum(0.0); @@ -101,9 +97,8 @@ public: m_endAngle->setSingleStep(1); QFormLayout* seriesSettingsLayout = new QFormLayout(); - seriesSettingsLayout->addRow("Vertical position", m_vPosition); seriesSettingsLayout->addRow("Horizontal position", m_hPosition); - seriesSettingsLayout->addRow("Size policy", m_sizePolicy); + seriesSettingsLayout->addRow("Vertical position", m_vPosition); seriesSettingsLayout->addRow("Size factor", m_sizeFactor); seriesSettingsLayout->addRow("Start angle", m_startAngle); seriesSettingsLayout->addRow("End angle", m_endAngle); @@ -114,13 +109,20 @@ public: m_sliceValue = new QDoubleSpinBox(); m_sliceValue->setMaximum(1000); m_sliceLabelVisible = new QCheckBox(); + m_sliceLabelArmFactor = new QDoubleSpinBox(); + m_sliceLabelArmFactor->setSingleStep(0.01); m_sliceExploded = new QCheckBox(); + m_sliceExplodedFactor = new QDoubleSpinBox(); + m_sliceExplodedFactor->setSingleStep(0.01); QFormLayout* sliceSettingsLayout = new QFormLayout(); sliceSettingsLayout->addRow("Selected", m_sliceName); sliceSettingsLayout->addRow("Value", m_sliceValue); sliceSettingsLayout->addRow("Label visible", m_sliceLabelVisible); + sliceSettingsLayout->addRow("Label arm length", m_sliceLabelArmFactor); sliceSettingsLayout->addRow("Exploded", m_sliceExploded); + sliceSettingsLayout->addRow("Explode distance", m_sliceExplodedFactor); + QGroupBox* sliceSettings = new QGroupBox("Slice"); sliceSettings->setLayout(sliceSettingsLayout); @@ -130,16 +132,17 @@ public: baseLayout->addWidget(m_chartView, 0, 1, 2, 1); setLayout(baseLayout); - connect(m_vPosition, SIGNAL(currentIndexChanged(int)), this, SLOT(updateSerieSettings())); - connect(m_hPosition, SIGNAL(currentIndexChanged(int)), this, SLOT(updateSerieSettings())); - connect(m_sizePolicy, SIGNAL(currentIndexChanged(int)), this, SLOT(updateSerieSettings())); + connect(m_vPosition, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings())); + connect(m_hPosition, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings())); connect(m_sizeFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings())); connect(m_startAngle, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings())); connect(m_endAngle, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings())); connect(m_sliceValue, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings())); connect(m_sliceLabelVisible, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings())); + connect(m_sliceLabelArmFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings())); connect(m_sliceExploded, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings())); + connect(m_sliceExplodedFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings())); connect(m_series, SIGNAL(clicked(QPieSlice*)), this, SLOT(handleSliceClicked(QPieSlice*))); @@ -150,12 +153,7 @@ public Q_SLOTS: void updateSerieSettings() { - QPieSeries::PiePosition vPos(m_vPosition->itemData(m_vPosition->currentIndex()).toInt()); - QPieSeries::PiePosition hPos(m_hPosition->itemData(m_hPosition->currentIndex()).toInt()); - m_series->setPosition(vPos | hPos); - - QPieSeries::PieSizePolicy policy(m_sizePolicy->itemData(m_sizePolicy->currentIndex()).toInt()); - m_series->setSizePolicy(policy); + m_series->setPositionFactors(m_vPosition->value(), m_hPosition->value()); m_series->setSizeFactor(m_sizeFactor->value()); @@ -165,9 +163,14 @@ public Q_SLOTS: void updateSliceSettings() { + if (!m_slice) + return; + m_slice->setValue(m_sliceValue->value()); m_slice->setLabelVisible(m_sliceLabelVisible->isChecked()); + m_slice->setLabelArmLengthFactor(m_sliceLabelArmFactor->value()); m_slice->setExploded(m_sliceExploded->isChecked()); + m_slice->setExplodeDistanceFactor(m_sliceExplodedFactor->value()); } void handleSliceClicked(QPieSlice* slice) @@ -183,9 +186,17 @@ public Q_SLOTS: m_sliceLabelVisible->setChecked(slice->isLabelVisible()); m_sliceLabelVisible->blockSignals(false); + m_sliceLabelArmFactor->blockSignals(true); + m_sliceLabelArmFactor->setValue(slice->labelArmLengthFactor()); + m_sliceLabelArmFactor->blockSignals(false); + m_sliceExploded->blockSignals(true); m_sliceExploded->setChecked(slice->isExploded()); m_sliceExploded->blockSignals(false); + + m_sliceExplodedFactor->blockSignals(true); + m_sliceExplodedFactor->setValue(slice->explodeDistanceFactor()); + m_sliceExplodedFactor->blockSignals(false); } private: @@ -193,9 +204,8 @@ private: QPieSeries* m_series; QPieSlice* m_slice; - QComboBox* m_vPosition; - QComboBox* m_hPosition; - QComboBox* m_sizePolicy; + QDoubleSpinBox* m_hPosition; + QDoubleSpinBox* m_vPosition; QDoubleSpinBox* m_sizeFactor; QDoubleSpinBox* m_startAngle; QDoubleSpinBox* m_endAngle; @@ -203,7 +213,9 @@ private: QLabel* m_sliceName; QDoubleSpinBox* m_sliceValue; QCheckBox* m_sliceLabelVisible; + QDoubleSpinBox* m_sliceLabelArmFactor; QCheckBox* m_sliceExploded; + QDoubleSpinBox* m_sliceExplodedFactor; }; int main(int argc, char *argv[]) diff --git a/src/piechart/piepresenter.cpp b/src/piechart/piepresenter.cpp index fe2bb36..8d3224d 100644 --- a/src/piechart/piepresenter.cpp +++ b/src/piechart/piepresenter.cpp @@ -16,7 +16,6 @@ PiePresenter::PiePresenter(QGraphicsItem *parent, QPieSeries *series) connect(series, SIGNAL(changed(const QPieSeries::ChangeSet&)), this, SLOT(handleSeriesChanged(const QPieSeries::ChangeSet&))); connect(series, SIGNAL(sizeFactorChanged()), this, SLOT(updateGeometry())); connect(series, SIGNAL(positionChanged()), this, SLOT(updateGeometry())); - connect(series, SIGNAL(sizePolicyChanged()), this, SLOT(updateGeometry())); if (m_series->count()) { QPieSeries::ChangeSet changeSet; @@ -75,113 +74,26 @@ void PiePresenter::updateGeometry() if (!m_rect.isValid() || m_rect.isEmpty()) return; - // calculate maximum rectangle for pie - QRectF pieRect = m_rect; - if (pieRect.width() < pieRect.height()) { - pieRect.setHeight(pieRect.width()); - } else { - pieRect.setWidth(pieRect.height()); - } - - // position the pie rectangle - QPointF center = m_rect.center(); // default position is center - qreal dx = pieRect.width() / 2; - qreal dy = pieRect.height() / 2; - if (m_series->position() & QPieSeries::PiePositionLeft) - center.setX(m_rect.left() + dx); - if (m_series->position() & QPieSeries::PiePositionRight) - center.setX(m_rect.right() - dx); - if (m_series->position() & QPieSeries::PiePositionHCenter) - center.setX(m_rect.center().x()); - if (m_series->position() & QPieSeries::PiePositionTop) - center.setY(m_rect.top() + dy); - if (m_series->position() & QPieSeries::PiePositionBottom) - center.setY(m_rect.bottom() - dy); - if (m_series->position() & QPieSeries::PiePositionVCenter) - center.setY(m_rect.center().y()); - pieRect.moveCenter(center); - - // calculate how much space we need around the pie rectangle (labels & exploding) - qreal delta = 0; - qreal pieRadius = pieRect.height() / 2; - foreach (QPieSlice* s, m_series->m_slices) { - - bool exploded = s->isExploded(); - if (m_series->sizePolicy() & QPieSeries::PieSizePolicyReserveSpaceForExploding) - exploded = true; - - bool labelVisible = s->isLabelVisible(); - if (m_series->sizePolicy() & QPieSeries::PieSizePolicyReserveSpaceForLabels) - labelVisible = true; - - qreal centerAngle; - QPointF armStart; - QRectF sliceRect = PieSlice::slicePath(center, pieRadius, s->m_startAngle, s->m_angleSpan, exploded, s->explodeDistance(), ¢erAngle, &armStart).boundingRect(); - - if (labelVisible) { - QRectF textRect = PieSlice::labelTextRect(s->labelFont(), s->label()); - QPointF textStart; - QRectF armRect = PieSlice::labelArmPath(armStart, centerAngle, s->labelArmLength(), textRect.width(), &textStart).boundingRect(); - textRect.moveBottomLeft(textStart); - sliceRect = sliceRect.united(armRect); - sliceRect = sliceRect.united(textRect); - } + // find pie center coordinates + QPointF center; + center.setX(m_rect.left() + (m_rect.width() * m_series->m_hPositionFactor)); + center.setY(m_rect.top() + (m_rect.height() * m_series->m_vPositionFactor)); + // find maximum radius for pie + qreal radius = m_rect.height() / 2; + if (m_rect.width() < m_rect.height()) + radius = m_rect.width() / 2; - qreal dt = m_rect.top() - sliceRect.top(); - if (dt > delta) - delta = dt; - qreal dl = m_rect.left() - sliceRect.left(); - if (dl > delta) - delta = dl; - qreal dr = sliceRect.right() - m_rect.right(); - if (dr > delta) - delta = dr; - qreal db = sliceRect.bottom() - m_rect.bottom(); - if (db > delta) - delta = db; - - /* - if (s->label() == "Slice 5") { - m_debugRect = sliceRect; - qDebug() << "dt:" << dt << ", dl:" << dl << ", dr:" << dr << ", db:" << db << ", delta:" << delta; - } - */ - } - - // shrink the pie rectangle so that everything outside it fits the base rectangle - pieRect.adjust(delta, delta, -delta, -delta); - - /* - // apply size factor (range 0.0 ... 1.0) - pieRect.setWidth(pieRect.width() * m_series->sizeFactor()); - pieRect.setHeight(pieRect.height() * m_series->sizeFactor()); - - // position the pie rectangle (again) - center = m_rect.center(); // default position is center - dx = pieRect.width() / 2; - dy = pieRect.height() / 2; - if (m_series->position() & QPieSeries::PiePositionLeft) - center.setX(m_rect.left() + dx); - if (m_series->position() & QPieSeries::PiePositionRight) - center.setX(m_rect.right() - dx); - if (m_series->position() & QPieSeries::PiePositionHCenter) - center.setX(m_rect.center().x()); - if (m_series->position() & QPieSeries::PiePositionTop) - center.setY(m_rect.top() + dy); - if (m_series->position() & QPieSeries::PiePositionBottom) - center.setY(m_rect.bottom() - dy); - if (m_series->position() & QPieSeries::PiePositionVCenter) - center.setY(m_rect.center().y()); - pieRect.moveCenter(center); - */ + // apply size factor + radius *= m_series->m_pieSizeFactor; // update slices - if (m_pieRect != pieRect) { - m_pieRect = pieRect; - //qDebug() << "PiePresenter::updateGeometry()" << m_rect << m_pieRect; + if (m_pieCenter != center || m_pieRadius != radius) { + m_pieCenter = center; + m_pieRadius = radius; + //qDebug() << "PiePresenter::updateGeometry()" << m_rect << m_pieCenter << m_pieRadius; foreach (PieSlice* s, m_slices.values()) { - s->setPieRect(m_pieRect); + s->setPieCenterAndRadius(center, radius); s->updateGeometry(); s->update(); } @@ -201,7 +113,7 @@ void PiePresenter::addSlice(QPieSlice* sliceData) // create slice PieSlice *slice = new PieSlice(this); - slice->setPieRect(m_pieRect); + slice->setPieCenterAndRadius(m_pieCenter, m_pieRadius); slice->updateData(sliceData); slice->updateGeometry(); slice->update(); diff --git a/src/piechart/piepresenter_p.h b/src/piechart/piepresenter_p.h index f238cfe..5671e3a 100644 --- a/src/piechart/piepresenter_p.h +++ b/src/piechart/piepresenter_p.h @@ -9,8 +9,6 @@ class QGraphicsItem; QTCOMMERCIALCHART_BEGIN_NAMESPACE class PieSlice; -#define PI 3.14159265 // TODO: is this defined in some header? - class PiePresenter : public QObject, public ChartItem { Q_OBJECT @@ -24,9 +22,6 @@ public: // from QGraphicsItem QRectF boundingRect() const { return m_rect; } void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); -public: - QRectF pieRect() const { return m_pieRect; } - public Q_SLOTS: void handleSeriesChanged(const QPieSeries::ChangeSet& changeSet); void handleDomainChanged(const Domain& domain); @@ -43,7 +38,8 @@ private: QHash m_slices; QPieSeries *m_series; QRectF m_rect; - QRectF m_pieRect; + QPointF m_pieCenter; + qreal m_pieRadius; QRectF m_debugRect; }; diff --git a/src/piechart/pieslice.cpp b/src/piechart/pieslice.cpp index 71feff9..a275d4a 100644 --- a/src/piechart/pieslice.cpp +++ b/src/piechart/pieslice.cpp @@ -10,6 +10,8 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE +#define PI 3.14159265 // TODO: is this defined in some header? + QPointF offset(qreal angle, qreal length) { qreal dx = qSin(angle*(PI/180)) * length; @@ -19,11 +21,13 @@ QPointF offset(qreal angle, qreal length) PieSlice::PieSlice(QGraphicsItem* parent) :QGraphicsObject(parent), + m_pieRadius(0), m_startAngle(0), m_angleSpan(0), m_isExploded(false), - m_explodeDistance(0), - m_labelVisible(false) + m_explodeDistanceFactor(0), + m_labelVisible(false), + m_labelArmLengthFactor(0) { setAcceptHoverEvents(true); setAcceptedMouseButtons(Qt::LeftButton); @@ -41,11 +45,15 @@ QRectF PieSlice::boundingRect() const QPainterPath PieSlice::shape() const { + // Don't include the label and label arm. + // This is used to detect a mouse clicks. We do not want clicks from label. return m_slicePath; } void PieSlice::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/) { + painter->setClipRect(parentItem()->boundingRect()); + painter->save(); painter->setPen(m_pen); painter->setBrush(m_brush); @@ -78,36 +86,35 @@ void PieSlice::mousePressEvent(QGraphicsSceneMouseEvent* /*event*/) emit clicked(); } -void PieSlice::setPieRect(QRectF rect) +void PieSlice::setPieCenterAndRadius(QPointF center, qreal radius) { - m_pieRect = rect; + m_pieCenter = center; + m_pieRadius = radius; } void PieSlice::updateGeometry() { - if (!m_pieRect.isValid() || m_pieRect.isEmpty()) + if (m_pieRadius <= 0) return; prepareGeometryChange(); // update slice path - QPointF center = m_pieRect.center(); - qreal radius = m_pieRect.height() / 2; qreal centerAngle; QPointF armStart; - m_slicePath = slicePath(center, radius, m_startAngle, m_angleSpan, m_isExploded, m_explodeDistance, ¢erAngle, &armStart); + m_slicePath = slicePath(m_pieCenter, m_pieRadius, m_startAngle, m_angleSpan, m_isExploded, m_pieRadius * m_explodeDistanceFactor, ¢erAngle, &armStart); // update text rect m_labelTextRect = labelTextRect(m_labelFont, m_labelText); // update label arm path QPointF labelTextStart; - m_labelArmPath = labelArmPath(armStart, centerAngle, m_labelArmLength, m_labelTextRect.width(), &labelTextStart); + m_labelArmPath = labelArmPath(armStart, centerAngle, m_pieRadius * m_labelArmLengthFactor, m_labelTextRect.width(), &labelTextStart); // update text position m_labelTextRect.moveBottomLeft(labelTextStart); - //qDebug() << "PieSlice::updateGeometry" << m_slicelabel->text() << boundingRect() << m_angle << m_span; + //qDebug() << "PieSlice::updateGeometry" << m_labelText << boundingRect() << m_startAngle << m_startAngle + m_angleSpan; } void PieSlice::updateData(const QPieSlice* sliceData) @@ -117,14 +124,14 @@ void PieSlice::updateData(const QPieSlice* sliceData) m_startAngle = sliceData->startAngle(); m_angleSpan = sliceData->m_angleSpan; m_isExploded = sliceData->isExploded(); - m_explodeDistance = sliceData->explodeDistance(); + m_explodeDistanceFactor = sliceData->explodeDistanceFactor(); m_pen = sliceData->pen(); m_brush = sliceData->brush(); m_labelVisible = sliceData->isLabelVisible(); m_labelText = sliceData->label(); m_labelFont = sliceData->labelFont(); - m_labelArmLength = sliceData->labelArmLength(); + m_labelArmLengthFactor = sliceData->labelArmLengthFactor(); m_labelArmPen = sliceData->labelPen(); updateGeometry(); diff --git a/src/piechart/pieslice_p.h b/src/piechart/pieslice_p.h index 378f052..3d6c324 100644 --- a/src/piechart/pieslice_p.h +++ b/src/piechart/pieslice_p.h @@ -38,7 +38,7 @@ Q_SIGNALS: void hoverLeave(); public Q_SLOTS: - void setPieRect(QRectF rect); + void setPieCenterAndRadius(QPointF center, qreal radius); void updateGeometry(); void updateData(const QPieSlice *sliceData); @@ -48,19 +48,20 @@ public: static QRectF labelTextRect(QFont font, QString text); private: - QRectF m_pieRect; + QPointF m_pieCenter; + qreal m_pieRadius; QPainterPath m_slicePath; qreal m_startAngle; qreal m_angleSpan; bool m_isExploded; - qreal m_explodeDistance; + qreal m_explodeDistanceFactor; bool m_labelVisible; QPen m_pen; QBrush m_brush; QPainterPath m_labelArmPath; - qreal m_labelArmLength; + qreal m_labelArmLengthFactor; QPen m_labelArmPen; QRectF m_labelTextRect; diff --git a/src/piechart/qpieseries.cpp b/src/piechart/qpieseries.cpp index 5de0795..0f98d0c 100644 --- a/src/piechart/qpieseries.cpp +++ b/src/piechart/qpieseries.cpp @@ -89,18 +89,6 @@ bool QPieSeries::ChangeSet::isEmpty() const } /*! - \enum QPieSeries::PiePosition - - This enum describes pie position within its bounding rectangle - - \value PiePositionMaximized - \value PiePositionTopLeft - \value PiePositionTopRight - \value PiePositionBottomLeft - \value PiePositionBottomRight -*/ - -/*! \class QPieSeries \brief Pie series API for QtCommercial Charts @@ -117,11 +105,12 @@ bool QPieSeries::ChangeSet::isEmpty() const */ QPieSeries::QPieSeries(QObject *parent) : QSeries(parent), - m_sizeFactor(1.0), - m_position(PiePositionCenter), - m_sizePolicy(PieSizePolicyMaximized), + m_hPositionFactor(0.5), + m_vPositionFactor(0.5), + m_pieSizeFactor(0.7), m_pieStartAngle(0), - m_pieEndAngle(360) + m_pieEndAngle(360), + m_total(0) { } @@ -265,76 +254,109 @@ QList QPieSeries::slices() const } /*! - Sets the size \a factor of the pie. 1.0 is the default value. - Note that the pie will not grow beyond its absolute maximum size. - In practice its use is to make the pie appear smaller. - \sa sizeFactor() + Sets the center position of the pie by \a horizontalFactor and \a verticalFactor. + + The factors are relative to the chart rectangle where: + + \a horizontalFactor 0.0 means the absolute left. + \a horizontalFactor 1.0 means the absolute right. + \a verticalFactor 0.0 means the absolute top. + \a verticalFactor 1.0 means the absolute bottom. + + By default \a horizontalFactor and \a verticalFactor are 0.5 which puts the pie in the middle of the chart rectangle. + + \sa horizontalPositionFactor(), verticalPositionFactor(), setSizeFactor() */ -void QPieSeries::setSizeFactor(qreal factor) +void QPieSeries::setPositionFactors(qreal horizontalFactor, qreal verticalFactor) { - if (factor < 0.0) + if (horizontalFactor < 0.0 || horizontalFactor > 1.0 || verticalFactor < 0.0 || verticalFactor > 1.0) return; - if (m_sizeFactor != factor) { - m_sizeFactor = factor; - emit sizeFactorChanged(); + if (m_hPositionFactor != horizontalFactor || m_vPositionFactor != verticalFactor) { + m_hPositionFactor = horizontalFactor; + m_vPositionFactor = verticalFactor; + emit positionChanged(); } } /*! - Gets the size factor of the pie. - \sa setSizeFactor() -*/ -qreal QPieSeries::sizeFactor() const -{ - return m_sizeFactor; -} + Gets the horizontal position factor of the pie. -/*! - Sets the \a position of the pie within its bounding rectangle. - \sa PiePosition, position() + The factors are relative to the chart rectangle where: + + Horizontal factor 0.0 means the absolute left. + Horizontal factor 1.0 means the absolute right. + + By default horizontal factor is 0.5 which puts the pie in the horizontal middle of the chart rectangle. + + \sa setPositionFactors(), verticalPositionFactor(), setSizeFactor() */ -void QPieSeries::setPosition(PiePosition position) +qreal QPieSeries::horizontalPositionFactor() const { - // TODO: sanity check - if (m_position != position) { - m_position = position; - emit positionChanged(); - } + return m_hPositionFactor; } /*! - Gets the position of the pie within its bounding rectangle. - \sa PiePosition, setPosition() + Gets the vertical position factor of the pie. + + The factors are relative to the chart rectangle where: + + Vertical factor 0.0 means the absolute top. + Vertical factor 1.0 means the absolute bottom. + + By default vertical factor is 0.5 which puts the pie in the vertical middle of the chart rectangle. + + \sa setPositionFactors(), horizontalPositionFactor(), setSizeFactor() */ -QPieSeries::PiePosition QPieSeries::position() const +qreal QPieSeries::verticalPositionFactor() const { - return m_position; + return m_vPositionFactor; } /*! - Sets the \a sizePolicy of the pie. - \sa PieSizePolicy, sizePolicy() + Sets the size \a sizeFactor of the pie. + + The size factor is defined so that the 1.0 is the maximum that can fit the given chart rectangle. + + Default value is 0.7. + + \sa sizeFactor(), setPositionFactors(), verticalPositionFactor(), horizontalPositionFactor() */ -void QPieSeries::setSizePolicy(PieSizePolicy sizePolicy) +void QPieSeries::setSizeFactor(qreal sizeFactor) { - // TODO: sanity check - if (m_sizePolicy != sizePolicy) { - m_sizePolicy = sizePolicy; - emit sizePolicyChanged(); + if (sizeFactor < 0.0) + return; + + if (m_pieSizeFactor != sizeFactor) { + m_pieSizeFactor = sizeFactor; + emit sizeFactorChanged(); } } /*! - Gets the size policy of the pie. - \sa PieSizePolicy, setSizePolicy() + Gets the size factor of the pie. + + The size factor is defined so that the 1.0 is the maximum that can fit the given chart rectangle. + + Default value is 0.7. + + \sa setSizeFactor(), setPositionFactors(), verticalPositionFactor(), horizontalPositionFactor() */ -QPieSeries::PieSizePolicy QPieSeries::sizePolicy() const +qreal QPieSeries::sizeFactor() const { - return m_sizePolicy; + return m_pieSizeFactor; } +/*! + Sets the end angle of the pie. + + Full pie is 360 degrees where 0 degrees is at 12 a'clock. + + \a startAngle must be less than end angle. Default value is 0. + + \sa startAngle(), endAngle(), setEndAngle() +*/ void QPieSeries::setStartAngle(qreal startAngle) { if (startAngle >= 0 && startAngle <= 360 && startAngle != m_pieStartAngle && startAngle <= m_pieEndAngle) { @@ -343,11 +365,27 @@ void QPieSeries::setStartAngle(qreal startAngle) } } +/*! + Gets the start angle of the pie. + + Full pie is 360 degrees where 0 degrees is at 12 a'clock. Default value is 360. + + \sa setStartAngle(), endAngle(), setEndAngle() +*/ qreal QPieSeries::startAngle() const { return m_pieStartAngle; } +/*! + Sets the end angle of the pie. + + Full pie is 360 degrees where 0 degrees is at 12 a'clock. + + \a endAngle must be greater than start angle. + + \sa endAngle(), startAngle(), setStartAngle() +*/ void QPieSeries::setEndAngle(qreal endAngle) { if (endAngle >= 0 && endAngle <= 360 && endAngle != m_pieEndAngle && endAngle >= m_pieStartAngle) { @@ -356,6 +394,13 @@ void QPieSeries::setEndAngle(qreal endAngle) } } +/*! + Returns the end angle of the pie. + + Full pie is 360 degrees where 0 degrees is at 12 a'clock. + + \sa setEndAngle(), startAngle(), setStartAngle() +*/ qreal QPieSeries::endAngle() const { return m_pieEndAngle; @@ -428,7 +473,7 @@ qreal QPieSeries::total() const This signal is emitted when position of the pie has been changed. - \sa position(), setPosition() + \sa horizontalPositionFactor(), verticalPositionFactor(), setPositionFactors() */ void QPieSeries::sliceChanged() diff --git a/src/piechart/qpieseries.h b/src/piechart/qpieseries.h index bc0f410..97d6b86 100644 --- a/src/piechart/qpieseries.h +++ b/src/piechart/qpieseries.h @@ -21,27 +21,6 @@ class QTCOMMERCIALCHART_EXPORT QPieSeries : public QSeries public: - enum PiePositionFlag { - PiePositionLeft = 0x1, - PiePositionRight = 0x2, - PiePositionHCenter = 0x4, - PiePositionTop = 0x10, - PiePositionBottom = 0x20, - PiePositionVCenter = 0x40, - PiePositionCenter = PiePositionHCenter | PiePositionVCenter - }; - - Q_DECLARE_FLAGS(PiePosition, PiePositionFlag) - - enum PieSizePolicyFlag { - PieSizePolicyMaximized = 0, - PieSizePolicyReserveSpaceForLabels = 0x1, - PieSizePolicyReserveSpaceForExploding = 0x2, - PieSizePolicyReserveSpaceForAll = PieSizePolicyReserveSpaceForLabels | PieSizePolicyReserveSpaceForExploding - }; - - Q_DECLARE_FLAGS(PieSizePolicy, PieSizePolicyFlag) - class ChangeSet { public: @@ -88,10 +67,9 @@ public: qreal total() const; // pie customization - void setPosition(PiePosition position); - PiePosition position() const; - void setSizePolicy(PieSizePolicy policy); - PieSizePolicy sizePolicy() const; + void setPositionFactors(qreal horizontalFactor, qreal verticalFactor); + qreal horizontalPositionFactor() const; + qreal verticalPositionFactor() const; void setSizeFactor(qreal sizeFactor); qreal sizeFactor() const; void setStartAngle(qreal startAngle); @@ -125,7 +103,6 @@ Q_SIGNALS: void sizeFactorChanged(); void positionChanged(); - void sizePolicyChanged(); private Q_SLOTS: // TODO: should be private and not visible in the interface at all void sliceChanged(); @@ -144,12 +121,12 @@ private: friend class PieSlice; QList m_slices; - qreal m_sizeFactor; - PiePosition m_position; - PieSizePolicy m_sizePolicy; - qreal m_total; + qreal m_hPositionFactor; + qreal m_vPositionFactor; + qreal m_pieSizeFactor; qreal m_pieStartAngle; qreal m_pieEndAngle; + qreal m_total; }; QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/piechart/qpieslice.cpp b/src/piechart/qpieslice.cpp index b42cf75..fb8cc0b 100644 --- a/src/piechart/qpieslice.cpp +++ b/src/piechart/qpieslice.cpp @@ -4,8 +4,8 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE #define DEFAULT_PEN_COLOR Qt::black #define DEFAULT_BRUSH_COLOR Qt::white -#define DEFAULT_LABEL_ARM_LENGTH 40 -#define DEFAULT_EXPOLODE_DISTANCE 20 +#define DEFAULT_LABEL_ARM_LENGTH_FACTOR 0.15 +#define DEFAULT_EXPOLODE_DISTANCE_FACTOR 0.15 /*! \class QPieSlice @@ -42,14 +42,14 @@ QPieSlice::QPieSlice(QObject *parent) m_value(0), m_isLabelVisible(false), m_isExploded(false), - m_explodeDistance(DEFAULT_EXPOLODE_DISTANCE), + m_explodeDistanceFactor(DEFAULT_EXPOLODE_DISTANCE_FACTOR), m_percentage(0), m_startAngle(0), m_angleSpan(0), m_pen(DEFAULT_PEN_COLOR), m_brush(DEFAULT_BRUSH_COLOR), m_labelPen(DEFAULT_PEN_COLOR), - m_labelArmLength(DEFAULT_LABEL_ARM_LENGTH) + m_labelArmLengthFactor(DEFAULT_LABEL_ARM_LENGTH_FACTOR) { } @@ -65,14 +65,14 @@ QPieSlice::QPieSlice(qreal value, QString label, QObject *parent) m_label(label), m_isLabelVisible(false), m_isExploded(false), - m_explodeDistance(DEFAULT_EXPOLODE_DISTANCE), + m_explodeDistanceFactor(DEFAULT_EXPOLODE_DISTANCE_FACTOR), m_percentage(0), m_startAngle(0), m_angleSpan(0), m_pen(DEFAULT_PEN_COLOR), m_brush(DEFAULT_BRUSH_COLOR), m_labelPen(DEFAULT_PEN_COLOR), - m_labelArmLength(DEFAULT_LABEL_ARM_LENGTH) + m_labelArmLengthFactor(DEFAULT_LABEL_ARM_LENGTH_FACTOR) { } @@ -116,7 +116,7 @@ bool QPieSlice::isLabelVisible() const /*! Returns true if slice is exloded from the pie. - \sa setExploded() + \sa setExploded(), setExplodeDistanceFactor() */ bool QPieSlice::isExploded() const { @@ -124,13 +124,19 @@ bool QPieSlice::isExploded() const } /*! - Returns the explosion distance of the slice. - Default value is 20. - \sa setExplodeDistance() + Returns the explode distance factor. + + The factor is relative to pie radius. For example: + 1.0 means the distance is the same as the radius. + 0.5 means the distance is half of the radius. + + Default value is 0.15. + + \sa setExplodeDistanceFactor() */ -qreal QPieSlice::explodeDistance() const +qreal QPieSlice::explodeDistanceFactor() const { - return m_explodeDistance; + return m_explodeDistanceFactor; } /*! @@ -205,13 +211,19 @@ QFont QPieSlice::labelFont() const } /*! - Returns the label arm lenght used in this slice. - Default value is 40 pixels. - \sa setLabelArmLength() + Gets the label arm lenght factor. + + The factor is relative to pie radius. For example: + 1.0 means the length is the same as the radius. + 0.5 means the length is half of the radius. + + Default value is 0.15 + + \sa setLabelArmLengthFactor() */ -qreal QPieSlice::labelArmLength() const +qreal QPieSlice::labelArmLengthFactor() const { - return m_labelArmLength; + return m_labelArmLengthFactor; } /*! @@ -247,7 +259,7 @@ qreal QPieSlice::labelArmLength() const */ /*! - Sets the value of this slice. + Sets the \a value of this slice. \sa value() */ void QPieSlice::setValue(qreal value) @@ -284,7 +296,7 @@ void QPieSlice::setLabelVisible(bool visible) /*! Sets this slice \a exploded. - \sa isExploded(), setExplodeDistance() + \sa isExploded(), explodeDistanceFactor() */ void QPieSlice::setExploded(bool exploded) { @@ -295,14 +307,20 @@ void QPieSlice::setExploded(bool exploded) } /*! - Sets the explosion \a distance of this slice. - It is the distance the slice is moved away from the pie center. - \sa explodeDistance(), isExploded() + Sets the explode distance \a factor. + + The factor is relative to pie radius. For example: + 1.0 means the distance is the same as the radius. + 0.5 means the distance is half of the radius. + + Default value is 0.15 + + \sa explodeDistanceFactor() */ -void QPieSlice::setExplodeDistance(qreal distance) +void QPieSlice::setExplodeDistanceFactor(qreal factor) { - if (m_explodeDistance != distance) { - m_explodeDistance = distance; + if (m_explodeDistanceFactor != factor) { + m_explodeDistanceFactor = factor; emit changed(); } } @@ -360,13 +378,20 @@ void QPieSlice::setLabelFont(QFont font) } /*! - Sets the label arm \a length used to draw the label in this slice. - \sa labelArmLength() + Sets the label arm lenght \a factor. + + The factor is relative to pie radius. For example: + 1.0 means the length is the same as the radius. + 0.5 means the length is half of the radius. + + Default value is 0.15 + + \sa labelArmLengthFactor() */ -void QPieSlice::setLabelArmLength(qreal length) +void QPieSlice::setLabelArmLengthFactor(qreal factor) { - if (m_labelArmLength != length) { - m_labelArmLength = length; + if (m_labelArmLengthFactor != factor) { + m_labelArmLengthFactor = factor; emit changed(); } } diff --git a/src/piechart/qpieslice.h b/src/piechart/qpieslice.h index d97cd49..427fd75 100644 --- a/src/piechart/qpieslice.h +++ b/src/piechart/qpieslice.h @@ -29,8 +29,8 @@ public: bool isLabelVisible() const; void setExploded(bool exploded); bool isExploded() const; - void setExplodeDistance(qreal distance); - qreal explodeDistance() const; + void setExplodeDistanceFactor(qreal factor); + qreal explodeDistanceFactor() const; // generated data qreal percentage() const; @@ -46,8 +46,8 @@ public: QPen labelPen() const; void setLabelFont(QFont font); QFont labelFont() const; - void setLabelArmLength(qreal len); - qreal labelArmLength() const; + void setLabelArmLengthFactor(qreal factor); + qreal labelArmLengthFactor() const; // TODO: label position in general // setLabelFlags(inside|outside|labelArmOn|labelArmOff|???) @@ -71,7 +71,7 @@ private: QString m_label; bool m_isLabelVisible; bool m_isExploded; - qreal m_explodeDistance; + qreal m_explodeDistanceFactor; // generated data qreal m_percentage; @@ -83,7 +83,7 @@ private: QBrush m_brush; QPen m_labelPen; QFont m_labelFont; - qreal m_labelArmLength; + qreal m_labelArmLengthFactor; }; QTCOMMERCIALCHART_END_NAMESPACE