chartpresenter.cpp
570 lines
| 16.2 KiB
| text/x-c
|
CppLexer
Jani Honkonen
|
r794 | /**************************************************************************** | ||
Michal Klocek
|
r969 | ** | ||
Titta Heikkala
|
r2776 | ** Copyright (C) 2015 The Qt Company Ltd | ||
Michal Klocek
|
r969 | ** All rights reserved. | ||
Titta Heikkala
|
r2776 | ** For any questions to The Qt Company, please use contact form at http://qt.io | ||
Michal Klocek
|
r969 | ** | ||
Titta Heikkala
|
r2740 | ** This file is part of the Qt Charts module. | ||
Michal Klocek
|
r969 | ** | ||
Titta Heikkala
|
r2740 | ** Licensees holding valid commercial license for Qt may use this file in | ||
** accordance with the Qt License Agreement provided with the Software | ||||
** or, alternatively, in accordance with the terms contained in a written | ||||
Titta Heikkala
|
r2776 | ** agreement between you and The Qt Company. | ||
Michal Klocek
|
r969 | ** | ||
** If you have questions regarding the use of this file, please use | ||||
Titta Heikkala
|
r2740 | ** contact form at http://qt.io | ||
Michal Klocek
|
r969 | ** | ||
****************************************************************************/ | ||||
Titta Heikkala
|
r2714 | #include <private/chartpresenter_p.h> | ||
#include <QtCharts/QChart> | ||||
#include <private/chartitem_p.h> | ||||
#include <private/qchart_p.h> | ||||
#include <QtCharts/QAbstractAxis> | ||||
#include <private/qabstractaxis_p.h> | ||||
#include <private/chartdataset_p.h> | ||||
#include <private/chartanimation_p.h> | ||||
#include <private/qabstractseries_p.h> | ||||
#include <QtCharts/QAreaSeries> | ||||
#include <private/chartaxiselement_p.h> | ||||
#include <private/chartbackground_p.h> | ||||
#include <private/cartesianchartlayout_p.h> | ||||
#include <private/polarchartlayout_p.h> | ||||
#include <private/charttitle_p.h> | ||||
#include <QtCore/QTimer> | ||||
#include <QtGui/QTextDocument> | ||||
Miikka Heikkinen
|
r2826 | #include <QtWidgets/QGraphicsScene> | ||
Michal Klocek
|
r131 | |||
Titta Heikkala
|
r2712 | QT_CHARTS_BEGIN_NAMESPACE | ||
Michal Klocek
|
r131 | |||
Miikka Heikkinen
|
r2483 | ChartPresenter::ChartPresenter(QChart *chart, QChart::ChartType type) | ||
Jani Honkonen
|
r2131 | : QObject(chart), | ||
m_chart(chart), | ||||
m_options(QChart::NoAnimation), | ||||
Titta Heikkala
|
r2804 | m_animationDuration(ChartAnimationDuration), | ||
m_animationCurve(QEasingCurve::OutQuart), | ||||
Jani Honkonen
|
r2131 | m_state(ShowState), | ||
m_background(0), | ||||
Miikka Heikkinen
|
r2498 | m_plotAreaBackground(0), | ||
Miikka Heikkinen
|
r2707 | m_title(0), | ||
Miikka Heikkinen
|
r2710 | m_localizeNumbers(false) | ||
Miikka Heikkinen
|
r2820 | #ifndef QT_NO_OPENGL | ||
, m_glWidget(0) | ||||
, m_glUseWidget(true) | ||||
#endif | ||||
Michal Klocek
|
r131 | { | ||
Miikka Heikkinen
|
r2483 | if (type == QChart::ChartTypeCartesian) | ||
m_layout = new CartesianChartLayout(this); | ||||
else if (type == QChart::ChartTypePolar) | ||||
m_layout = new PolarChartLayout(this); | ||||
Q_ASSERT(m_layout); | ||||
Michal Klocek
|
r131 | } | ||
ChartPresenter::~ChartPresenter() | ||||
{ | ||||
Miikka Heikkinen
|
r2820 | #ifndef QT_NO_OPENGL | ||
delete m_glWidget.data(); | ||||
#endif | ||||
Michal Klocek
|
r131 | } | ||
Michal Klocek
|
r2273 | void ChartPresenter::setGeometry(const QRectF rect) | ||
Michal Klocek
|
r131 | { | ||
Miikka Heikkinen
|
r2483 | if (m_rect != rect) { | ||
m_rect = rect; | ||||
foreach (ChartItem *chart, m_chartItems) { | ||||
chart->domain()->setSize(rect.size()); | ||||
chart->setPos(rect.topLeft()); | ||||
} | ||||
Miikka Heikkinen
|
r2820 | #ifndef QT_NO_OPENGL | ||
if (!m_glWidget.isNull()) | ||||
m_glWidget->setGeometry(m_rect.toRect()); | ||||
#endif | ||||
Miikka Heikkinen
|
r2716 | emit plotAreaChanged(m_rect); | ||
Miikka Heikkinen
|
r2483 | } | ||
Michal Klocek
|
r2273 | } | ||
Michal Klocek
|
r1698 | |||
Michal Klocek
|
r2273 | QRectF ChartPresenter::geometry() const | ||
{ | ||||
Miikka Heikkinen
|
r2483 | return m_rect; | ||
Michal Klocek
|
r2273 | } | ||
Michal Klocek
|
r1698 | |||
Michal Klocek
|
r2273 | void ChartPresenter::handleAxisAdded(QAbstractAxis *axis) | ||
{ | ||||
axis->d_ptr->initializeGraphics(rootItem()); | ||||
Titta Heikkala
|
r2804 | axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve); | ||
Miikka Heikkinen
|
r2483 | ChartAxisElement *item = axis->d_ptr->axisItem(); | ||
Michal Klocek
|
r2273 | item->setPresenter(this); | ||
item->setThemeManager(m_chart->d_ptr->m_themeManager); | ||||
m_axisItems<<item; | ||||
m_axes<<axis; | ||||
Michal Klocek
|
r2105 | m_layout->invalidate(); | ||
Michal Klocek
|
r223 | } | ||
Jani Honkonen
|
r2131 | void ChartPresenter::handleAxisRemoved(QAbstractAxis *axis) | ||
Michal Klocek
|
r223 | { | ||
Miikka Heikkinen
|
r2483 | ChartAxisElement *item = axis->d_ptr->m_item.take(); | ||
Michal Klocek
|
r1729 | item->hide(); | ||
item->disconnect(); | ||||
sauimone
|
r1562 | item->deleteLater(); | ||
Michal Klocek
|
r2273 | m_axisItems.removeAll(item); | ||
m_axes.removeAll(axis); | ||||
Michal Klocek
|
r2154 | m_layout->invalidate(); | ||
Michal Klocek
|
r223 | } | ||
Michal Klocek
|
r2273 | void ChartPresenter::handleSeriesAdded(QAbstractSeries *series) | ||
Michal Klocek
|
r131 | { | ||
Michal Klocek
|
r2273 | series->d_ptr->initializeGraphics(rootItem()); | ||
Titta Heikkala
|
r2804 | series->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve); | ||
Miikka Heikkinen
|
r2707 | series->d_ptr->setPresenter(this); | ||
Michal Klocek
|
r2273 | ChartItem *chart = series->d_ptr->chartItem(); | ||
chart->setPresenter(this); | ||||
chart->setThemeManager(m_chart->d_ptr->m_themeManager); | ||||
Miikka Heikkinen
|
r2820 | chart->setDataSet(m_chart->d_ptr->m_dataset); | ||
Michal Klocek
|
r2273 | chart->domain()->setSize(m_rect.size()); | ||
chart->setPos(m_rect.topLeft()); | ||||
chart->handleDomainUpdated(); //this could be moved to intializeGraphics when animator is refactored | ||||
m_chartItems<<chart; | ||||
m_series<<series; | ||||
Michal Klocek
|
r2105 | m_layout->invalidate(); | ||
Michal Klocek
|
r131 | } | ||
Jani Honkonen
|
r2131 | void ChartPresenter::handleSeriesRemoved(QAbstractSeries *series) | ||
Michal Klocek
|
r139 | { | ||
Michal Klocek
|
r2273 | ChartItem *chart = series->d_ptr->m_item.take(); | ||
chart->hide(); | ||||
chart->disconnect(); | ||||
chart->deleteLater(); | ||||
Titta Heikkala
|
r2767 | if (chart->animation()) | ||
chart->animation()->stopAndDestroyLater(); | ||||
Michal Klocek
|
r2273 | m_chartItems.removeAll(chart); | ||
m_series.removeAll(series); | ||||
m_layout->invalidate(); | ||||
Michal Klocek
|
r153 | } | ||
Michal Klocek
|
r298 | void ChartPresenter::setAnimationOptions(QChart::AnimationOptions options) | ||
{ | ||||
Jani Honkonen
|
r2131 | if (m_options != options) { | ||
Miikka Heikkinen
|
r2555 | QChart::AnimationOptions oldOptions = m_options; | ||
Jani Honkonen
|
r2131 | m_options = options; | ||
Miikka Heikkinen
|
r2555 | if (options.testFlag(QChart::SeriesAnimations) != oldOptions.testFlag(QChart::SeriesAnimations)) { | ||
foreach (QAbstractSeries *series, m_series) | ||||
Titta Heikkala
|
r2804 | series->d_ptr->initializeAnimations(m_options, m_animationDuration, | ||
m_animationCurve); | ||||
Michal Klocek
|
r2273 | } | ||
Miikka Heikkinen
|
r2555 | if (options.testFlag(QChart::GridAxisAnimations) != oldOptions.testFlag(QChart::GridAxisAnimations)) { | ||
foreach (QAbstractAxis *axis, m_axes) | ||||
Titta Heikkala
|
r2804 | axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve); | ||
Michal Klocek
|
r2273 | } | ||
Miikka Heikkinen
|
r2555 | m_layout->invalidate(); // So that existing animations don't just stop halfway | ||
Jani Honkonen
|
r2131 | } | ||
Michal Klocek
|
r531 | } | ||
Titta Heikkala
|
r2804 | void ChartPresenter::setAnimationDuration(int msecs) | ||
{ | ||||
if (m_animationDuration != msecs) { | ||||
m_animationDuration = msecs; | ||||
foreach (QAbstractSeries *series, m_series) | ||||
series->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve); | ||||
foreach (QAbstractAxis *axis, m_axes) | ||||
axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve); | ||||
m_layout->invalidate(); // So that existing animations don't just stop halfway | ||||
} | ||||
} | ||||
void ChartPresenter::setAnimationEasingCurve(const QEasingCurve &curve) | ||||
{ | ||||
if (m_animationCurve != curve) { | ||||
m_animationCurve = curve; | ||||
foreach (QAbstractSeries *series, m_series) | ||||
series->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve); | ||||
foreach (QAbstractAxis *axis, m_axes) | ||||
axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve); | ||||
m_layout->invalidate(); // So that existing animations don't just stop halfway | ||||
} | ||||
} | ||||
Michal Klocek
|
r2273 | void ChartPresenter::setState(State state,QPointF point) | ||
Michal Klocek
|
r439 | { | ||
Michal Klocek
|
r2273 | m_state=state; | ||
m_statePoint=point; | ||||
Michal Klocek
|
r531 | } | ||
Michal Klocek
|
r298 | QChart::AnimationOptions ChartPresenter::animationOptions() const | ||
{ | ||||
return m_options; | ||||
} | ||||
Michal Klocek
|
r1534 | void ChartPresenter::createBackgroundItem() | ||
Michal Klocek
|
r855 | { | ||
Michal Klocek
|
r1965 | if (!m_background) { | ||
m_background = new ChartBackground(rootItem()); | ||||
Miikka Heikkinen
|
r2516 | m_background->setPen(Qt::NoPen); // Theme doesn't touch pen so don't use default | ||
m_background->setBrush(QChartPrivate::defaultBrush()); | ||||
Michal Klocek
|
r1965 | m_background->setZValue(ChartPresenter::BackgroundZValue); | ||
Michal Klocek
|
r1534 | } | ||
} | ||||
Michal Klocek
|
r855 | |||
Miikka Heikkinen
|
r2498 | void ChartPresenter::createPlotAreaBackgroundItem() | ||
{ | ||||
if (!m_plotAreaBackground) { | ||||
if (m_chart->chartType() == QChart::ChartTypeCartesian) | ||||
m_plotAreaBackground = new QGraphicsRectItem(rootItem()); | ||||
else | ||||
m_plotAreaBackground = new QGraphicsEllipseItem(rootItem()); | ||||
// Use transparent pen instead of Qt::NoPen, as Qt::NoPen causes | ||||
// antialising artifacts with axis lines for some reason. | ||||
m_plotAreaBackground->setPen(QPen(Qt::transparent)); | ||||
m_plotAreaBackground->setBrush(Qt::NoBrush); | ||||
m_plotAreaBackground->setZValue(ChartPresenter::PlotAreaZValue); | ||||
m_plotAreaBackground->setVisible(false); | ||||
} | ||||
} | ||||
Michal Klocek
|
r1534 | void ChartPresenter::createTitleItem() | ||
{ | ||||
Michal Klocek
|
r1965 | if (!m_title) { | ||
m_title = new ChartTitle(rootItem()); | ||||
m_title->setZValue(ChartPresenter::BackgroundZValue); | ||||
Michal Klocek
|
r1534 | } | ||
} | ||||
Tero Ahola
|
r1524 | |||
Jani Honkonen
|
r2131 | void ChartPresenter::startAnimation(ChartAnimation *animation) | ||
Michal Klocek
|
r1534 | { | ||
Miikka Heikkinen
|
r2555 | animation->stop(); | ||
QTimer::singleShot(0, animation, SLOT(startChartAnimation())); | ||||
Michal Klocek
|
r1534 | } | ||
Michal Klocek
|
r855 | |||
Jani Honkonen
|
r2131 | void ChartPresenter::setBackgroundBrush(const QBrush &brush) | ||
Michal Klocek
|
r1534 | { | ||
createBackgroundItem(); | ||||
Michal Klocek
|
r1965 | m_background->setBrush(brush); | ||
Michal Klocek
|
r1534 | m_layout->invalidate(); | ||
} | ||||
Michal Klocek
|
r855 | |||
Michal Klocek
|
r1534 | QBrush ChartPresenter::backgroundBrush() const | ||
{ | ||||
Jani Honkonen
|
r2131 | if (!m_background) | ||
return QBrush(); | ||||
Michal Klocek
|
r1965 | return m_background->brush(); | ||
Michal Klocek
|
r1534 | } | ||
Michal Klocek
|
r855 | |||
Jani Honkonen
|
r2131 | void ChartPresenter::setBackgroundPen(const QPen &pen) | ||
Michal Klocek
|
r1534 | { | ||
createBackgroundItem(); | ||||
Michal Klocek
|
r1965 | m_background->setPen(pen); | ||
Michal Klocek
|
r1534 | m_layout->invalidate(); | ||
} | ||||
Michal Klocek
|
r855 | |||
Michal Klocek
|
r1534 | QPen ChartPresenter::backgroundPen() const | ||
{ | ||||
Jani Honkonen
|
r2131 | if (!m_background) | ||
return QPen(); | ||||
Michal Klocek
|
r1965 | return m_background->pen(); | ||
Michal Klocek
|
r1534 | } | ||
Michal Klocek
|
r913 | |||
Miikka Heikkinen
|
r2549 | void ChartPresenter::setBackgroundRoundness(qreal diameter) | ||
{ | ||||
createBackgroundItem(); | ||||
m_background->setDiameter(diameter); | ||||
m_layout->invalidate(); | ||||
} | ||||
qreal ChartPresenter::backgroundRoundness() const | ||||
{ | ||||
if (!m_background) | ||||
return 0; | ||||
return m_background->diameter(); | ||||
} | ||||
Miikka Heikkinen
|
r2498 | void ChartPresenter::setPlotAreaBackgroundBrush(const QBrush &brush) | ||
{ | ||||
createPlotAreaBackgroundItem(); | ||||
m_plotAreaBackground->setBrush(brush); | ||||
m_layout->invalidate(); | ||||
} | ||||
QBrush ChartPresenter::plotAreaBackgroundBrush() const | ||||
{ | ||||
if (!m_plotAreaBackground) | ||||
return QBrush(); | ||||
return m_plotAreaBackground->brush(); | ||||
} | ||||
void ChartPresenter::setPlotAreaBackgroundPen(const QPen &pen) | ||||
{ | ||||
createPlotAreaBackgroundItem(); | ||||
m_plotAreaBackground->setPen(pen); | ||||
m_layout->invalidate(); | ||||
} | ||||
QPen ChartPresenter::plotAreaBackgroundPen() const | ||||
{ | ||||
if (!m_plotAreaBackground) | ||||
return QPen(); | ||||
return m_plotAreaBackground->pen(); | ||||
} | ||||
Jani Honkonen
|
r2131 | void ChartPresenter::setTitle(const QString &title) | ||
Michal Klocek
|
r1534 | { | ||
createTitleItem(); | ||||
Michal Klocek
|
r1965 | m_title->setText(title); | ||
Michal Klocek
|
r1534 | m_layout->invalidate(); | ||
} | ||||
Michal Klocek
|
r913 | |||
Michal Klocek
|
r1534 | QString ChartPresenter::title() const | ||
{ | ||||
Jani Honkonen
|
r2131 | if (!m_title) | ||
return QString(); | ||||
Michal Klocek
|
r1965 | return m_title->text(); | ||
Michal Klocek
|
r1534 | } | ||
Michal Klocek
|
r855 | |||
Jani Honkonen
|
r2131 | void ChartPresenter::setTitleFont(const QFont &font) | ||
Michal Klocek
|
r1534 | { | ||
createTitleItem(); | ||||
Michal Klocek
|
r1965 | m_title->setFont(font); | ||
Michal Klocek
|
r1534 | m_layout->invalidate(); | ||
} | ||||
Michal Klocek
|
r855 | |||
Michal Klocek
|
r1534 | QFont ChartPresenter::titleFont() const | ||
{ | ||||
Jani Honkonen
|
r2131 | if (!m_title) | ||
return QFont(); | ||||
Michal Klocek
|
r1965 | return m_title->font(); | ||
Michal Klocek
|
r1534 | } | ||
Michal Klocek
|
r913 | |||
Michal Klocek
|
r1534 | void ChartPresenter::setTitleBrush(const QBrush &brush) | ||
{ | ||||
createTitleItem(); | ||||
Miikka Heikkinen
|
r2539 | m_title->setDefaultTextColor(brush.color()); | ||
Michal Klocek
|
r1534 | m_layout->invalidate(); | ||
} | ||||
Michal Klocek
|
r869 | |||
Michal Klocek
|
r1534 | QBrush ChartPresenter::titleBrush() const | ||
{ | ||||
Jani Honkonen
|
r2131 | if (!m_title) | ||
return QBrush(); | ||||
Miikka Heikkinen
|
r2539 | return QBrush(m_title->defaultTextColor()); | ||
Michal Klocek
|
r1534 | } | ||
void ChartPresenter::setBackgroundVisible(bool visible) | ||||
{ | ||||
createBackgroundItem(); | ||||
Michal Klocek
|
r1965 | m_background->setVisible(visible); | ||
Michal Klocek
|
r1534 | } | ||
Michal Klocek
|
r871 | |||
Michal Klocek
|
r855 | |||
Michal Klocek
|
r1534 | bool ChartPresenter::isBackgroundVisible() const | ||
{ | ||||
Jani Honkonen
|
r2131 | if (!m_background) | ||
return false; | ||||
Michal Klocek
|
r1965 | return m_background->isVisible(); | ||
Michal Klocek
|
r855 | } | ||
Miikka Heikkinen
|
r2498 | void ChartPresenter::setPlotAreaBackgroundVisible(bool visible) | ||
{ | ||||
createPlotAreaBackgroundItem(); | ||||
m_plotAreaBackground->setVisible(visible); | ||||
} | ||||
bool ChartPresenter::isPlotAreaBackgroundVisible() const | ||||
{ | ||||
if (!m_plotAreaBackground) | ||||
return false; | ||||
return m_plotAreaBackground->isVisible(); | ||||
} | ||||
Michal Klocek
|
r1534 | void ChartPresenter::setBackgroundDropShadowEnabled(bool enabled) | ||
Michal Klocek
|
r855 | { | ||
Michal Klocek
|
r1534 | createBackgroundItem(); | ||
Michal Klocek
|
r1965 | m_background->setDropShadowEnabled(enabled); | ||
Michal Klocek
|
r855 | } | ||
Michal Klocek
|
r1534 | bool ChartPresenter::isBackgroundDropShadowEnabled() const | ||
Michal Klocek
|
r855 | { | ||
Jani Honkonen
|
r2131 | if (!m_background) | ||
return false; | ||||
Michal Klocek
|
r1965 | return m_background->isDropShadowEnabled(); | ||
Michal Klocek
|
r855 | } | ||
Michal Klocek
|
r143 | |||
Miikka Heikkinen
|
r2707 | void ChartPresenter::setLocalizeNumbers(bool localize) | ||
{ | ||||
m_localizeNumbers = localize; | ||||
m_layout->invalidate(); | ||||
} | ||||
Miikka Heikkinen
|
r2708 | void ChartPresenter::setLocale(const QLocale &locale) | ||
Miikka Heikkinen
|
r2707 | { | ||
Miikka Heikkinen
|
r2708 | m_locale = locale; | ||
m_layout->invalidate(); | ||||
Miikka Heikkinen
|
r2707 | } | ||
Miikka Heikkinen
|
r2483 | AbstractChartLayout *ChartPresenter::layout() | ||
Michal Klocek
|
r1241 | { | ||
Michal Klocek
|
r1534 | return m_layout; | ||
Michal Klocek
|
r1241 | } | ||
Jani Honkonen
|
r2131 | QLegend *ChartPresenter::legend() | ||
Michal Klocek
|
r1534 | { | ||
return m_chart->legend(); | ||||
} | ||||
Michal Klocek
|
r1965 | void ChartPresenter::setVisible(bool visible) | ||
{ | ||||
m_chart->setVisible(visible); | ||||
} | ||||
Jani Honkonen
|
r2131 | ChartBackground *ChartPresenter::backgroundElement() | ||
Michal Klocek
|
r1965 | { | ||
return m_background; | ||||
} | ||||
Miikka Heikkinen
|
r2498 | QAbstractGraphicsShapeItem *ChartPresenter::plotAreaElement() | ||
{ | ||||
return m_plotAreaBackground; | ||||
} | ||||
Miikka Heikkinen
|
r2483 | QList<ChartAxisElement *> ChartPresenter::axisItems() const | ||
Michal Klocek
|
r1534 | { | ||
Michal Klocek
|
r2273 | return m_axisItems; | ||
Michal Klocek
|
r1534 | } | ||
Michal Klocek
|
r2273 | QList<ChartItem *> ChartPresenter::chartItems() const | ||
Michal Klocek
|
r2105 | { | ||
Michal Klocek
|
r2273 | return m_chartItems; | ||
Michal Klocek
|
r2105 | } | ||
Jani Honkonen
|
r2131 | ChartTitle *ChartPresenter::titleElement() | ||
Michal Klocek
|
r1534 | { | ||
Michal Klocek
|
r1965 | return m_title; | ||
Michal Klocek
|
r1241 | } | ||
Miikka Heikkinen
|
r2539 | QRectF ChartPresenter::textBoundingRect(const QFont &font, const QString &text, qreal angle) | ||
{ | ||||
Miikka Heikkinen
|
r2543 | static QGraphicsTextItem dummyTextItem; | ||
Miikka Heikkinen
|
r2592 | static bool initMargin = true; | ||
if (initMargin) { | ||||
dummyTextItem.document()->setDocumentMargin(textMargin()); | ||||
initMargin = false; | ||||
} | ||||
Miikka Heikkinen
|
r2539 | |||
Miikka Heikkinen
|
r2543 | dummyTextItem.setFont(font); | ||
dummyTextItem.setHtml(text); | ||||
QRectF boundingRect = dummyTextItem.boundingRect(); | ||||
Miikka Heikkinen
|
r2539 | |||
// Take rotation into account | ||||
if (angle) { | ||||
QTransform transform; | ||||
transform.rotate(angle); | ||||
boundingRect = transform.mapRect(boundingRect); | ||||
} | ||||
return boundingRect; | ||||
} | ||||
// boundingRect parameter returns the rotated bounding rect of the text | ||||
QString ChartPresenter::truncatedText(const QFont &font, const QString &text, qreal angle, | ||||
Titta Heikkala
|
r2604 | qreal maxWidth, qreal maxHeight, QRectF &boundingRect) | ||
Miikka Heikkinen
|
r2539 | { | ||
QString truncatedString(text); | ||||
boundingRect = textBoundingRect(font, truncatedString, angle); | ||||
Titta Heikkala
|
r2604 | if (boundingRect.width() > maxWidth || boundingRect.height() > maxHeight) { | ||
Miikka Heikkinen
|
r2541 | // It can be assumed that almost any amount of string manipulation is faster | ||
// than calculating one bounding rectangle, so first prepare a list of truncated strings | ||||
// to try. | ||||
Titta Heikkala
|
r2712 | static QRegExp truncateMatcher(QStringLiteral("&#?[0-9a-zA-Z]*;$")); | ||
Miikka Heikkinen
|
r2543 | |||
Miikka Heikkinen
|
r2541 | QVector<QString> testStrings(text.length()); | ||
int count(0); | ||||
static QLatin1Char closeTag('>'); | ||||
static QLatin1Char openTag('<'); | ||||
static QLatin1Char semiColon(';'); | ||||
static QLatin1String ellipsis("..."); | ||||
while (truncatedString.length() > 1) { | ||||
int chopIndex(-1); | ||||
int chopCount(1); | ||||
QChar lastChar(truncatedString.at(truncatedString.length() - 1)); | ||||
if (lastChar == closeTag) | ||||
chopIndex = truncatedString.lastIndexOf(openTag); | ||||
else if (lastChar == semiColon) | ||||
Miikka Heikkinen
|
r2543 | chopIndex = truncateMatcher.indexIn(truncatedString, 0); | ||
Miikka Heikkinen
|
r2541 | |||
if (chopIndex != -1) | ||||
chopCount = truncatedString.length() - chopIndex; | ||||
truncatedString.chop(chopCount); | ||||
testStrings[count] = truncatedString + ellipsis; | ||||
count++; | ||||
} | ||||
Miikka Heikkinen
|
r2539 | |||
Miikka Heikkinen
|
r2541 | // Binary search for best fit | ||
int minIndex(0); | ||||
int maxIndex(count - 1); | ||||
int bestIndex(count); | ||||
QRectF checkRect; | ||||
Titta Heikkala
|
r2604 | |||
Miikka Heikkinen
|
r2541 | while (maxIndex >= minIndex) { | ||
int mid = (maxIndex + minIndex) / 2; | ||||
checkRect = textBoundingRect(font, testStrings.at(mid), angle); | ||||
Titta Heikkala
|
r2604 | if (checkRect.width() > maxWidth || checkRect.height() > maxHeight) { | ||
Miikka Heikkinen
|
r2541 | // Checked index too large, all under this are also too large | ||
minIndex = mid + 1; | ||||
} else { | ||||
// Checked index fits, all over this also fit | ||||
maxIndex = mid - 1; | ||||
bestIndex = mid; | ||||
boundingRect = checkRect; | ||||
} | ||||
} | ||||
// Default to "..." if nothing fits | ||||
if (bestIndex == count) { | ||||
boundingRect = textBoundingRect(font, ellipsis, angle); | ||||
truncatedString = ellipsis; | ||||
} else { | ||||
truncatedString = testStrings.at(bestIndex); | ||||
Miikka Heikkinen
|
r2539 | } | ||
} | ||||
return truncatedString; | ||||
} | ||||
Miikka Heikkinen
|
r2707 | QString ChartPresenter::numberToString(double value, char f, int prec) | ||
{ | ||||
if (m_localizeNumbers) | ||||
return m_locale.toString(value, f, prec); | ||||
else | ||||
return QString::number(value, f, prec); | ||||
} | ||||
Miikka Heikkinen
|
r2709 | QString ChartPresenter::numberToString(int value) | ||
{ | ||||
if (m_localizeNumbers) | ||||
return m_locale.toString(value); | ||||
else | ||||
return QString::number(value); | ||||
} | ||||
Miikka Heikkinen
|
r2820 | void ChartPresenter::ensureGLWidget() | ||
{ | ||||
#ifndef QT_NO_OPENGL | ||||
// GLWidget pointer is wrapped in QPointer as its parent is not in our control, and therefore | ||||
// can potentially get deleted unexpectedly. | ||||
if (m_glWidget.isNull() && m_glUseWidget && m_chart->scene()) { | ||||
QObject *parent = m_chart->scene()->parent(); | ||||
while (parent) { | ||||
QWidget *parentWidget = qobject_cast<QWidget *>(parent); | ||||
if (parentWidget) { | ||||
m_glWidget = new GLWidget(m_chart->d_ptr->m_dataset->glXYSeriesDataManager(), | ||||
parentWidget); | ||||
m_glWidget->setGeometry(m_rect.toRect()); | ||||
m_glWidget->show(); | ||||
break; | ||||
} | ||||
parent = parent->parent(); | ||||
} | ||||
} | ||||
#endif | ||||
} | ||||
Michal Klocek
|
r131 | #include "moc_chartpresenter_p.cpp" | ||
Titta Heikkala
|
r2712 | QT_CHARTS_END_NAMESPACE | ||