/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the Qt Commercial Charts Add-on. ** ** $QT_BEGIN_LICENSE$ ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. ** ** If you have questions regarding the use of this file, please use ** contact form at http://qt.digia.com ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "chartaxiselement_p.h" #include "qabstractaxis_p.h" #include "chartpresenter_p.h" #include "abstractchartlayout_p.h" #include #include #include QTCOMMERCIALCHART_BEGIN_NAMESPACE ChartAxisElement::ChartAxisElement(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis) : ChartElement(item), m_axis(axis), m_animation(0), m_grid(new QGraphicsItemGroup(item)), m_arrow(new QGraphicsItemGroup(item)), m_shades(new QGraphicsItemGroup(item)), m_labels(new QGraphicsItemGroup(item)), m_title(new QGraphicsSimpleTextItem(item)), m_intervalAxis(intervalAxis) { //initial initialization m_arrow->setHandlesChildEvents(false); m_arrow->setZValue(ChartPresenter::AxisZValue); m_labels->setZValue(ChartPresenter::AxisZValue); m_shades->setZValue(ChartPresenter::ShadesZValue); m_grid->setZValue(ChartPresenter::GridZValue); m_title->setZValue(ChartPresenter::GridZValue); handleVisibleChanged(axis->isVisible()); connectSlots(); setFlag(QGraphicsItem::ItemHasNoContents, true); } ChartAxisElement::~ChartAxisElement() { } void ChartAxisElement::connectSlots() { QObject::connect(axis(), SIGNAL(visibleChanged(bool)), this, SLOT(handleVisibleChanged(bool))); QObject::connect(axis(), SIGNAL(lineVisibleChanged(bool)), this, SLOT(handleArrowVisibleChanged(bool))); QObject::connect(axis(), SIGNAL(gridVisibleChanged(bool)), this, SLOT(handleGridVisibleChanged(bool))); QObject::connect(axis(), SIGNAL(labelsVisibleChanged(bool)), this, SLOT(handleLabelsVisibleChanged(bool))); QObject::connect(axis(), SIGNAL(shadesVisibleChanged(bool)), this, SLOT(handleShadesVisibleChanged(bool))); QObject::connect(axis(), SIGNAL(labelsAngleChanged(int)), this, SLOT(handleLabelsAngleChanged(int))); QObject::connect(axis(), SIGNAL(linePenChanged(const QPen&)), this, SLOT(handleArrowPenChanged(const QPen&))); QObject::connect(axis(), SIGNAL(labelsPenChanged(const QPen&)), this, SLOT(handleLabelsPenChanged(const QPen&))); QObject::connect(axis(), SIGNAL(labelsBrushChanged(const QBrush&)), this, SLOT(handleLabelsBrushChanged(const QBrush&))); QObject::connect(axis(), SIGNAL(labelsFontChanged(const QFont&)), this, SLOT(handleLabelsFontChanged(const QFont&))); QObject::connect(axis(), SIGNAL(gridLinePenChanged(const QPen&)), this, SLOT(handleGridPenChanged(const QPen&))); QObject::connect(axis(), SIGNAL(shadesPenChanged(const QPen&)), this, SLOT(handleShadesPenChanged(const QPen&))); QObject::connect(axis(), SIGNAL(shadesBrushChanged(const QBrush&)), this, SLOT(handleShadesBrushChanged(const QBrush&))); QObject::connect(axis(), SIGNAL(titleTextChanged(const QString&)), this, SLOT(handleTitleTextChanged(const QString&))); QObject::connect(axis(), SIGNAL(titleFontChanged(const QFont&)), this, SLOT(handleTitleFontChanged(const QFont&))); QObject::connect(axis(), SIGNAL(titlePenChanged(const QPen&)), this, SLOT(handleTitlePenChanged(const QPen&))); QObject::connect(axis(), SIGNAL(titleBrushChanged(const QBrush&)), this, SLOT(handleTitleBrushChanged(const QBrush&))); QObject::connect(axis(), SIGNAL(titleVisibleChanged(bool)), this, SLOT(handleTitleVisibleChanged(bool))); QObject::connect(axis()->d_ptr.data(), SIGNAL(rangeChanged(qreal, qreal)), this, SLOT(handleRangeChanged(qreal, qreal))); } void ChartAxisElement::handleArrowVisibleChanged(bool visible) { m_arrow->setVisible(visible); } void ChartAxisElement::handleGridVisibleChanged(bool visible) { m_grid->setVisible(visible); } void ChartAxisElement::handleLabelsVisibleChanged(bool visible) { QGraphicsLayoutItem::updateGeometry(); presenter()->layout()->invalidate(); m_labels->setVisible(visible); } void ChartAxisElement::handleShadesVisibleChanged(bool visible) { m_shades->setVisible(visible); } void ChartAxisElement::handleTitleVisibleChanged(bool visible) { QGraphicsLayoutItem::updateGeometry(); presenter()->layout()->invalidate(); m_title->setVisible(visible); } void ChartAxisElement::handleLabelsAngleChanged(int angle) { foreach (QGraphicsItem *item, m_labels->childItems()) item->setRotation(angle); QGraphicsLayoutItem::updateGeometry(); presenter()->layout()->invalidate(); } void ChartAxisElement::handleLabelsPenChanged(const QPen &pen) { foreach (QGraphicsItem *item, m_labels->childItems()) static_cast(item)->setPen(pen); } void ChartAxisElement::handleLabelsBrushChanged(const QBrush &brush) { foreach (QGraphicsItem *item, m_labels->childItems()) static_cast(item)->setBrush(brush); } void ChartAxisElement::handleLabelsFontChanged(const QFont &font) { foreach (QGraphicsItem *item, m_labels->childItems()) static_cast(item)->setFont(font); QGraphicsLayoutItem::updateGeometry(); presenter()->layout()->invalidate(); } void ChartAxisElement::handleTitleTextChanged(const QString &title) { QGraphicsLayoutItem::updateGeometry(); presenter()->layout()->invalidate(); m_title->setText(title); } void ChartAxisElement::handleTitlePenChanged(const QPen &pen) { m_title->setPen(pen); } void ChartAxisElement::handleTitleBrushChanged(const QBrush &brush) { m_title->setBrush(brush); } void ChartAxisElement::handleTitleFontChanged(const QFont &font) { if (m_title->font() != font) { m_title->setFont(font); QGraphicsLayoutItem::updateGeometry(); presenter()->layout()->invalidate(); } } void ChartAxisElement::handleVisibleChanged(bool visible) { setVisible(visible); if (!visible) { m_grid->setVisible(visible); m_arrow->setVisible(visible); m_shades->setVisible(visible); m_labels->setVisible(visible); m_title->setVisible(visible); } else { m_grid->setVisible(axis()->isGridLineVisible()); m_arrow->setVisible(axis()->isLineVisible()); m_shades->setVisible(axis()->shadesVisible()); m_labels->setVisible(axis()->labelsVisible()); m_title->setVisible(axis()->isTitleVisible()); } if (presenter()) presenter()->layout()->invalidate(); } QRect ChartAxisElement::labelBoundingRect(const QFontMetrics &fn, const QString &label) const { QRect boundingRect = fn.boundingRect(label); // Take label rotation into account if (axis()->labelsAngle()) { QTransform transform; transform.rotate(axis()->labelsAngle()); boundingRect = transform.mapRect(boundingRect); } return boundingRect; } void ChartAxisElement::handleRangeChanged(qreal min, qreal max) { Q_UNUSED(min); Q_UNUSED(max); if (!isEmpty()) { QVector layout = calculateLayout(); updateLayout(layout); QSizeF before = effectiveSizeHint(Qt::PreferredSize); QSizeF after = sizeHint(Qt::PreferredSize); if (before != after) { QGraphicsLayoutItem::updateGeometry(); // We don't want to call invalidate on layout, since it will change minimum size of // component, which we would like to avoid since it causes nasty flips when scrolling // or zooming, instead recalculate layout and use plotArea for extra space. presenter()->layout()->setGeometry(presenter()->layout()->geometry()); } } } bool ChartAxisElement::isEmpty() { return axisGeometry().isEmpty() || gridGeometry().isEmpty() || qFuzzyCompare(min(), max()); } qreal ChartAxisElement::min() const { return m_axis->d_ptr->min(); } qreal ChartAxisElement::max() const { return m_axis->d_ptr->max(); } QStringList ChartAxisElement::createValueLabels(qreal min, qreal max, int ticks, const QString &format) { QStringList labels; if (max <= min || ticks < 1) return labels; int n = qMax(int(-qFloor(log10((max - min) / (ticks - 1)))), 0); n++; if (format.isNull()) { for (int i = 0; i < ticks; i++) { qreal value = min + (i * (max - min) / (ticks - 1)); labels << QString::number(value, 'f', n); } } else { QByteArray array = format.toLatin1(); for (int i = 0; i < ticks; i++) { qreal value = min + (i * (max - min) / (ticks - 1)); if (format.contains("d") || format.contains("i") || format.contains("c")) { labels << QString().sprintf(array, (qint64)value); } else if (format.contains("u") || format.contains("o") || format.contains("x", Qt::CaseInsensitive)) { labels << QString().sprintf(array, (quint64)value); } else if (format.contains("f", Qt::CaseInsensitive) || format.contains("e", Qt::CaseInsensitive) || format.contains("g", Qt::CaseInsensitive)) { labels << QString().sprintf(array, value); } else { labels << QString(); } } } return labels; } QStringList ChartAxisElement::createLogValueLabels(qreal min, qreal max, qreal base, int ticks, const QString &format) { QStringList labels; if (max <= min || ticks < 1) return labels; int n = 0; if (ticks > 1) n = qMax(int(-qFloor(log10((max - min) / (ticks - 1)))), 0); n++; int firstTick; if (base > 1) firstTick = ceil(log10(min) / log10(base)); else firstTick = ceil(log10(max) / log10(base)); if (format.isNull()) { for (int i = firstTick; i < ticks + firstTick; i++) { qreal value = qPow(base, i); labels << QString::number(value, 'f', n); } } else { QByteArray array = format.toLatin1(); for (int i = firstTick; i < ticks + firstTick; i++) { qreal value = qPow(base, i); if (format.contains("d") || format.contains("i") || format.contains("c")) { labels << QString().sprintf(array, (qint64)value); } else if (format.contains("u") || format.contains("o") || format.contains("x", Qt::CaseInsensitive)) { labels << QString().sprintf(array, (quint64)value); } else if (format.contains("f", Qt::CaseInsensitive) || format.contains("e", Qt::CaseInsensitive) || format.contains("g", Qt::CaseInsensitive)) { labels << QString().sprintf(array, value); } else { labels << QString(); } } } return labels; } QStringList ChartAxisElement::createDateTimeLabels(qreal min, qreal max,int ticks,const QString &format) { QStringList labels; if (max <= min || ticks < 1) return labels; int n = qMax(int(-floor(log10((max - min) / (ticks - 1)))), 0); n++; for (int i = 0; i < ticks; i++) { qreal value = min + (i * (max - min) / (ticks - 1)); labels << QDateTime::fromMSecsSinceEpoch(value).toString(format); } return labels; } void ChartAxisElement::axisSelected() { emit clicked(); } #include "moc_chartaxiselement_p.cpp" QTCOMMERCIALCHART_END_NAMESPACE