##// END OF EJS Templates
Set the first pie slice exploded and label visible in chartthemes demo
Set the first pie slice exploded and label visible in chartthemes demo

File last commit:

r685:c7c4c30aaeb9
r699:367aeb7897cf
Show More
axisitem.cpp
400 lines | 9.9 KiB | text/x-c | CppLexer
#include "axisitem_p.h"
#include "qchartaxis.h"
#include "chartpresenter_p.h"
#include "chartanimator_p.h"
#include <QPainter>
#include <QDebug>
#include <cmath>
static int label_padding = 5;
QTCOMMERCIALCHART_BEGIN_NAMESPACE
Axis::Axis(QChartAxis* axis,ChartPresenter* presenter,AxisType type) :
Chart(presenter),
m_chartAxis(axis),
m_type(type),
m_labelsAngle(0),
m_grid(presenter->rootItem()),
m_shades(presenter->rootItem()),
m_labels(presenter->rootItem()),
m_axis(presenter->rootItem()),
m_min(0),
m_max(0),
m_ticksCount(0)
{
//initial initialization
m_axis.setZValue(ChartPresenter::AxisZValue);
m_axis.setHandlesChildEvents(false);
m_shades.setZValue(ChartPresenter::ShadesZValue);
m_grid.setZValue(ChartPresenter::GridZValue);
QObject::connect(m_chartAxis,SIGNAL(updated()),this,SLOT(handleAxisUpdated()));
QObject::connect(m_chartAxis->categories(),SIGNAL(updated()),this,SLOT(handleAxisCategoriesUpdated()));
handleAxisUpdated();
}
Axis::~Axis()
{
}
void Axis::createItems(int count)
{
if(m_axis.children().size()==0)
m_axis.addToGroup(new AxisItem(this));
for (int i = 0; i < count; ++i) {
m_grid.addToGroup(new QGraphicsLineItem());
m_labels.addToGroup(new QGraphicsSimpleTextItem());
m_axis.addToGroup(new QGraphicsLineItem());
if((m_grid.childItems().size())%2 && m_grid.childItems().size()>2) m_shades.addToGroup(new QGraphicsRectItem());
}
}
void Axis::deleteItems(int count)
{
QList<QGraphicsItem *> lines = m_grid.childItems();
QList<QGraphicsItem *> labels = m_labels.childItems();
QList<QGraphicsItem *> shades = m_shades.childItems();
QList<QGraphicsItem *> axis = m_axis.childItems();
for (int i = 0; i < count; ++i) {
if(lines.size()%2 && lines.size()>1) delete(shades.takeLast());
delete(lines.takeLast());
delete(labels.takeLast());
delete(axis.takeLast());
}
}
void Axis::updateLayout(QVector<qreal>& layout)
{
if(animator()){
animator()->updateLayout(this,layout);
}
else setLayout(layout);
}
QStringList Axis::createLabels(int ticks, qreal min, qreal max) const
{
Q_ASSERT(max>=min);
Q_ASSERT(ticks>1);
QStringList labels;
int n = qMax(int(-floor(log10((max-min)/(ticks-1)))),0);
QChartAxisCategories* categories = m_chartAxis->categories();
for(int i=0; i< ticks; i++) {
qreal value = min + (i * (max - min)/ (ticks-1));
if(categories->count()==0) {
labels << QString::number(value,'f',n);
}
else {
QString label = categories->label(value);
labels << label;
}
}
return labels;
}
void Axis::setAxisOpacity(qreal opacity)
{
m_axis.setOpacity(opacity);
}
qreal Axis::axisOpacity() const
{
return m_axis.opacity();
}
void Axis::setGridOpacity(qreal opacity)
{
m_grid.setOpacity(opacity);
}
qreal Axis::gridOpacity() const
{
return m_grid.opacity();
}
void Axis::setLabelsOpacity(qreal opacity)
{
m_labels.setOpacity(opacity);
}
qreal Axis::labelsOpacity() const
{
return m_labels.opacity();
}
void Axis::setShadesOpacity(qreal opacity)
{
m_shades.setOpacity(opacity);
}
qreal Axis::shadesOpacity() const
{
return m_shades.opacity();
}
void Axis::setLabelsAngle(int angle)
{
foreach(QGraphicsItem* item , m_labels.childItems()) {
QPointF center = item->boundingRect().center();
item->setRotation(angle);
}
m_labelsAngle=angle;
}
void Axis::setLabelsPen(const QPen& pen)
{
foreach(QGraphicsItem* item , m_labels.childItems()) {
static_cast<QGraphicsSimpleTextItem*>(item)->setPen(pen);
}
}
void Axis::setLabelsBrush(const QBrush& brush)
{
foreach(QGraphicsItem* item , m_labels.childItems()) {
static_cast<QGraphicsSimpleTextItem*>(item)->setBrush(brush);
}
}
void Axis::setLabelsFont(const QFont& font)
{
foreach(QGraphicsItem* item , m_labels.childItems()) {
static_cast<QGraphicsSimpleTextItem*>(item)->setFont(font);
}
}
void Axis::setShadesBrush(const QBrush& brush)
{
foreach(QGraphicsItem* item , m_shades.childItems()) {
static_cast<QGraphicsRectItem*>(item)->setBrush(brush);
}
}
void Axis::setShadesPen(const QPen& pen)
{
foreach(QGraphicsItem* item , m_shades.childItems()) {
static_cast<QGraphicsRectItem*>(item)->setPen(pen);
}
}
void Axis::setAxisPen(const QPen& pen)
{
foreach(QGraphicsItem* item , m_axis.childItems()) {
static_cast<QGraphicsLineItem*>(item)->setPen(pen);
}
}
void Axis::setGridPen(const QPen& pen)
{
foreach(QGraphicsItem* item , m_grid.childItems()) {
static_cast<QGraphicsLineItem*>(item)->setPen(pen);
}
}
QVector<qreal> Axis::calculateLayout() const
{
Q_ASSERT(m_ticksCount>=2);
QVector<qreal> points;
points.resize(m_ticksCount);
switch (m_type)
{
case X_AXIS:
{
const qreal deltaX = m_rect.width()/(m_ticksCount-1);
for (int i = 0; i < m_ticksCount; ++i) {
int x = i * deltaX + m_rect.left();
points[i] = x;
}
}
break;
case Y_AXIS:
{
const qreal deltaY = m_rect.height()/(m_ticksCount-1);
for (int i = 0; i < m_ticksCount; ++i) {
int y = i * -deltaY + m_rect.bottom();
points[i] = y;
}
}
break;
}
return points;
}
void Axis::setLayout(QVector<qreal>& layout)
{
int diff = m_layoutVector.size() - layout.size();
if(diff>0) {
deleteItems(diff);
}
else if(diff<0) {
createItems(-diff);
}
if(diff!=0) handleAxisUpdated();
QStringList ticksList = createLabels(layout.size(),m_min,m_max);
QList<QGraphicsItem *> lines = m_grid.childItems();
QList<QGraphicsItem *> labels = m_labels.childItems();
QList<QGraphicsItem *> shades = m_shades.childItems();
QList<QGraphicsItem *> axis = m_axis.childItems();
Q_ASSERT(labels.size() == ticksList.size());
Q_ASSERT(layout.size() == ticksList.size());
switch (m_type)
{
case X_AXIS:
{
QGraphicsLineItem *lineItem = static_cast<QGraphicsLineItem*>(axis.at(0));
lineItem->setLine(m_rect.left(), m_rect.bottom(), m_rect.right(), m_rect.bottom());
for (int i = 0; i < layout.size(); ++i) {
QGraphicsLineItem *lineItem = static_cast<QGraphicsLineItem*>(lines.at(i));
lineItem->setLine(layout[i], m_rect.top(), layout[i], m_rect.bottom());
QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem*>(labels.at(i));
labelItem->setText(ticksList.at(i));
QPointF center = labelItem->boundingRect().center();
labelItem->setTransformOriginPoint(center.x(), center.y());
labelItem->setPos(layout[i] - center.x(), m_rect.bottom() + label_padding);
if((i+1)%2 && i>1) {
QGraphicsRectItem *rectItem = static_cast<QGraphicsRectItem*>(shades.at(i/2-1));
rectItem->setRect(layout[i-1],m_rect.top(),layout[i]-layout[i-1],m_rect.height());
}
lineItem = static_cast<QGraphicsLineItem*>(axis.at(i+1));
lineItem->setLine(layout[i],m_rect.bottom(),layout[i],m_rect.bottom()+5);
}
}
break;
case Y_AXIS:
{
QGraphicsLineItem *lineItem = static_cast<QGraphicsLineItem*>(axis.at(0));
lineItem->setLine(m_rect.left() , m_rect.top(), m_rect.left(), m_rect.bottom());
for (int i = 0; i < layout.size(); ++i) {
QGraphicsLineItem *lineItem = static_cast<QGraphicsLineItem*>(lines.at(i));
lineItem->setLine(m_rect.left() , layout[i], m_rect.right(), layout[i]);
QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem*>(labels.at(i));
labelItem->setText(ticksList.at(i));
QPointF center = labelItem->boundingRect().center();
labelItem->setTransformOriginPoint(center.x(), center.y());
labelItem->setPos(m_rect.left() - labelItem->boundingRect().width() - label_padding , layout[i]-center.y());
if((i+1)%2 && i>1) {
QGraphicsRectItem *rectItem = static_cast<QGraphicsRectItem*>(shades.at(i/2-1));
rectItem->setRect(m_rect.left(),layout[i],m_rect.width(),layout[i-1]-layout[i]);
}
lineItem = static_cast<QGraphicsLineItem*>(axis.at(i+1));
lineItem->setLine(m_rect.left()-5,layout[i],m_rect.left(),layout[i]);
}
}
break;
default:
qDebug()<<"Unknown axis type";
break;
}
m_layoutVector=layout;
}
bool Axis::isEmpty()
{
return m_rect.isEmpty() || m_min==m_max || m_ticksCount==0;
}
//handlers
void Axis::handleAxisCategoriesUpdated()
{
if(isEmpty()) return;
updateLayout(m_layoutVector);
}
void Axis::handleAxisUpdated()
{
if(isEmpty()) return;
if(m_chartAxis->isAxisVisible()) {
setAxisOpacity(100);
}
else {
setAxisOpacity(0);
}
if(m_chartAxis->isGridLineVisible()) {
setGridOpacity(100);
}
else {
setGridOpacity(0);
}
if(m_chartAxis->labelsVisible())
{
setLabelsOpacity(100);
}
else {
setLabelsOpacity(0);
}
if(m_chartAxis->shadesVisible()) {
setShadesOpacity(m_chartAxis->shadesOpacity());
}
else {
setShadesOpacity(0);
}
setLabelsAngle(m_chartAxis->labelsAngle());
setAxisPen(m_chartAxis->axisPen());
setLabelsPen(m_chartAxis->labelsPen());
setLabelsBrush(m_chartAxis->labelsBrush());
setLabelsFont(m_chartAxis->labelsFont());
setGridPen(m_chartAxis->gridLinePen());
setShadesPen(m_chartAxis->shadesPen());
setShadesBrush(m_chartAxis->shadesBrush());
}
void Axis::handleRangeChanged(qreal min, qreal max,int tickCount)
{
if(min==max || tickCount<2) return;
m_min = min;
m_max = max;
m_ticksCount= tickCount;
if(isEmpty()) return;
QVector<qreal> layout = calculateLayout();
updateLayout(layout);
}
void Axis::handleGeometryChanged(const QRectF& rect)
{
m_rect = rect;
if(isEmpty()) return;
QVector<qreal> layout = calculateLayout();
updateLayout(layout);
}
void Axis::axisSelected()
{
qDebug()<<"TODO axis clicked";
}
//TODO "nice numbers algorithm"
#include "moc_axisitem_p.cpp"
QTCOMMERCIALCHART_END_NAMESPACE