##// END OF EJS Templates
Legend disabled by defaut. User can turn in on, by calling setVisible
Legend disabled by defaut. User can turn in on, by calling setVisible

File last commit:

r652:4ab0d58be448
r652:4ab0d58be448
Show More
qlegend.cpp
491 lines | 14.0 KiB | text/x-c | CppLexer
sauimone
framework for legend
r524 #include "qchartglobal.h"
#include "qlegend.h"
#include "qseries.h"
sauimone
Separated legend marker to private header. Added signals for left and right mouse click
r547 #include "legendmarker_p.h"
sauimone
more intelligent legend. fixed compiler warning in bar.cpp
r565 #include "qxyseries.h"
#include "qlineseries.h"
#include "qareaseries.h"
#include "qscatterseries.h"
#include "qsplineseries.h"
#include "qbarseries.h"
#include "qstackedbarseries.h"
#include "qpercentbarseries.h"
#include "qbarset.h"
#include "qpieseries.h"
#include "qpieslice.h"
sauimone
Adaptive layout to legend. Tries to fit all items inside given maximum size
r626 #include "chartpresenter_p.h"
sauimone
First version of legend. Simple markers and serie names. Using drilldown as example for now.
r529 #include <QPainter>
#include <QPen>
sauimone
framework for legend
r524
sauimone
Separated legend marker to private header. Added signals for left and right mouse click
r547 #include <QGraphicsSceneEvent>
sauimone
First version of legend. Simple markers and serie names. Using drilldown as example for now.
r529
sauimone
Separated legend marker to private header. Added signals for left and right mouse click
r547 QTCOMMERCIALCHART_BEGIN_NAMESPACE
sauimone
First version of legend. Simple markers and serie names. Using drilldown as example for now.
r529
sauimone
framework for legend
r524 QLegend::QLegend(QGraphicsItem *parent)
: QGraphicsObject(parent)
sauimone
Adaptive layout to legend. Tries to fit all items inside given maximum size
r626 ,mPos(0,0)
,mSize(0,0)
sauimone
legend scaling with chart
r582 ,mMinimumSize(50,20) // TODO: magic numbers
sauimone
legend layouting change
r616 ,mMaximumSize(150,100)
Michal Klocek
Adds force option to chartTheme...
r645 ,m_brush(Qt::darkGray) // TODO: from theme?
sauimone
legend layouting change
r616 ,mPreferredLayout(QLegend::PreferredLayoutVertical)
sauimone
framework for legend
r524 {
sauimone
Legend disabled by defaut. User can turn in on, by calling setVisible
r652 setVisible(false);
sauimone
Adaptive layout to legend. Tries to fit all items inside given maximum size
r626 setZValue(ChartPresenter::LegendZValue);
sauimone
framework for legend
r524 }
void QLegend::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Tero Ahola
Squashed bunch of warnings
r611 Q_UNUSED(option)
Q_UNUSED(widget)
sauimone
Adaptive layout to legend. Tries to fit all items inside given maximum size
r626 painter->setOpacity(0.5);
Michal Klocek
Adds force option to chartTheme...
r645 painter->setPen(m_pen);
painter->setBrush(m_brush);
sauimone
Adaptive layout to legend. Tries to fit all items inside given maximum size
r626 painter->drawRect(boundingRect());
sauimone
framework for legend
r524 }
QRectF QLegend::boundingRect() const
{
sauimone
Adaptive layout to legend. Tries to fit all items inside given maximum size
r626 return QRectF(mPos,mSize);
sauimone
framework for legend
r524 }
Michal Klocek
Adds force option to chartTheme...
r645 void QLegend::setBrush(const QBrush& brush)
sauimone
background to legend, theme applies
r540 {
Michal Klocek
Adds force option to chartTheme...
r645 if(m_brush!=brush){
m_brush = brush;
update();
}
}
QBrush QLegend::brush() const
{
return m_brush;
}
void QLegend::setPen(const QPen& pen)
{
if(m_pen!=pen){
m_pen = pen;
update();
}
sauimone
background to legend, theme applies
r540 }
Michal Klocek
Adds force option to chartTheme...
r645 QPen QLegend::pen() const
sauimone
background to legend, theme applies
r540 {
Michal Klocek
Adds force option to chartTheme...
r645 return m_pen;
sauimone
background to legend, theme applies
r540 }
sauimone
legend layouting change
r616 void QLegend::setPreferredLayout(QLegend::PreferredLayout preferred)
{
mPreferredLayout = preferred;
layoutChanged();
}
sauimone
Adaptive layout to legend. Tries to fit all items inside given maximum size
r626 QSizeF QLegend::maximumSize() const
sauimone
legend scaling with chart
r582 {
sauimone
Adaptive layout to legend. Tries to fit all items inside given maximum size
r626 return mMaximumSize;
sauimone
legend scaling with chart
r582 }
sauimone
Adaptive layout to legend. Tries to fit all items inside given maximum size
r626 void QLegend::setMaximumSize(const QSizeF size)
sauimone
legend scaling with chart
r582 {
sauimone
Adaptive layout to legend. Tries to fit all items inside given maximum size
r626 mMaximumSize = size;
sauimone
Legend disabled by defaut. User can turn in on, by calling setVisible
r652 layoutChanged();
sauimone
Adaptive layout to legend. Tries to fit all items inside given maximum size
r626 }
void QLegend::setSize(const QSizeF size)
{
mSize = size;
if (mSize.width() > mMaximumSize.width()) {
mSize.setWidth(mMaximumSize.width());
}
if (mSize.height() > mMaximumSize.height()) {
mSize.setHeight(mMaximumSize.height());
}
}
void QLegend::setPos(const QPointF &pos)
{
mPos = pos;
sauimone
Legend disabled by defaut. User can turn in on, by calling setVisible
r652 layoutChanged();
sauimone
legend scaling with chart
r582 }
Tero Ahola
Squashed bunch of warnings
r611 void QLegend::handleSeriesAdded(QSeries* series, Domain* domain)
sauimone
framework for legend
r524 {
Tero Ahola
Squashed bunch of warnings
r611 Q_UNUSED(domain)
sauimone
handleThemeChanged slot to legend.
r586 createMarkers(series);
sauimone
Added handling for pieslice add/remove to legend
r637 connectSeries(series);
sauimone
handleThemeChanged slot to legend.
r586 layoutChanged();
}
void QLegend::handleSeriesRemoved(QSeries* series)
{
sauimone
Added handling for pieslice add/remove to legend
r637 disconnectSeries(series);
sauimone
handleThemeChanged slot to legend.
r586 if (series->type() == QSeries::SeriesTypeArea)
{
// This is special case. Area series has upper and lower series, which each have markers
QAreaSeries* s = static_cast<QAreaSeries*> (series);
deleteMarkers(s->upperSeries());
deleteMarkers(s->lowerSeries());
} else {
deleteMarkers(series);
}
layoutChanged();
}
sauimone
Added handling for pieslice add/remove to legend
r637 void QLegend::handleAdded(QList<QPieSlice*> slices)
{
QPieSeries* series = static_cast<QPieSeries*> (sender());
foreach(QPieSlice* s, slices) {
LegendMarker* marker = new LegendMarker(series,s,this);
marker->setName(s->label());
marker->setBrush(s->sliceBrush());
connect(marker,SIGNAL(clicked(QPieSlice*,Qt::MouseButton)),this,SIGNAL(clicked(QPieSlice*,Qt::MouseButton)));
connect(s,SIGNAL(changed()),marker,SLOT(changed()));
connect(s,SIGNAL(destroyed()),marker,SLOT(deleteLater()));
sauimone
fixed bug in legend marker removing
r643 connect(marker,SIGNAL(destroyed()),this,SLOT(handleMarkerDestroyed()));
sauimone
Added handling for pieslice add/remove to legend
r637 mMarkers.append(marker);
childItems().append(marker);
}
layoutChanged();
}
sauimone
fixed bug in legend marker removing
r643 void QLegend::handleRemoved(QList<QPieSlice *> slices)
{
Tero Ahola
Warnings treated as errors; fixed one
r647 Q_UNUSED(slices)
sauimone
fixed bug in legend marker removing
r643 // Propably no need to listen for this, since removed slices are deleted and we listen destroyed signal
// qDebug() << "QLegend::handleRemoved(QList<QPieSlice*> slices) count:" << slices.count();
}
sauimone
Added handling for pieslice add/remove to legend
r637 void QLegend::handleMarkerDestroyed()
{
// TODO: what if more than one markers are destroyed and we update layout after first one?
LegendMarker* m = static_cast<LegendMarker*> (sender());
mMarkers.removeOne(m);
layoutChanged();
}
void QLegend::connectSeries(QSeries *series)
{
// Connect relevant signals from series
switch (series->type())
{
case QSeries::SeriesTypeLine: {
// QLineSeries* lineSeries = static_cast<QLineSeries*>(series);
break;
}
case QSeries::SeriesTypeArea: {
// QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series);
break;
}
case QSeries::SeriesTypeBar: {
// QBarSeries* barSeries = static_cast<QBarSeries*>(series);
break;
}
case QSeries::SeriesTypeStackedBar: {
// QStackedBarSeries* stackedBarSeries = static_cast<QStackedBarSeries*>(series);
break;
}
case QSeries::SeriesTypePercentBar: {
// QPercentBarSeries* percentBarSeries = static_cast<QPercentBarSeries*>(series);
break;
}
case QSeries::SeriesTypeScatter: {
// QScatterSeries *scatterSeries = static_cast<QScatterSeries *>(series);
break;
}
case QSeries::SeriesTypePie: {
QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
connect(pieSeries,SIGNAL(added(QList<QPieSlice*>)),this,SLOT(handleAdded(QList<QPieSlice*>)));
// connect(pieSeries,SIGNAL(removed(QList<QPieSlice*>)),this,SLOT(handleRemoved(QList<QPieSlice*>)));
break;
}
case QSeries::SeriesTypeSpline: {
// QSplineSeries* splineSeries = static_cast<QSplineSeries*>(series);
break;
}
default: {
qDebug()<< "QLegend::connectSeries" << series->type() << "not implemented.";
break;
}
}
}
void QLegend::disconnectSeries(QSeries *series)
{
// Connect relevant signals from series
switch (series->type())
{
case QSeries::SeriesTypeLine: {
// QLineSeries* lineSeries = static_cast<QLineSeries*>(series);
break;
}
case QSeries::SeriesTypeArea: {
// QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series);
break;
}
case QSeries::SeriesTypeBar: {
// QBarSeries* barSeries = static_cast<QBarSeries*>(series);
break;
}
case QSeries::SeriesTypeStackedBar: {
// QStackedBarSeries* stackedBarSeries = static_cast<QStackedBarSeries*>(series);
break;
}
case QSeries::SeriesTypePercentBar: {
// QPercentBarSeries* percentBarSeries = static_cast<QPercentBarSeries*>(series);
break;
}
case QSeries::SeriesTypeScatter: {
// QScatterSeries *scatterSeries = static_cast<QScatterSeries *>(series);
break;
}
case QSeries::SeriesTypePie: {
QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
disconnect(pieSeries,SIGNAL(added(QList<QPieSlice*>)),this,SLOT(handleAdded(QList<QPieSlice*>)));
// disconnect(pieSeries,SIGNAL(removed(QList<QPieSlice*>)),this,SLOT(handleRemoved(QList<QPieSlice*>)));
break;
}
case QSeries::SeriesTypeSpline: {
// QSplineSeries* splineSeries = static_cast<QSplineSeries*>(series);
break;
}
default: {
qDebug()<< "QLegend::disconnectSeries" << series->type() << "not implemented.";
break;
}
}
}
sauimone
handleThemeChanged slot to legend.
r586 void QLegend::createMarkers(QSeries *series)
{
sauimone
more intelligent legend. fixed compiler warning in bar.cpp
r565 switch (series->type())
{
case QSeries::SeriesTypeLine: {
QLineSeries* lineSeries = static_cast<QLineSeries*>(series);
sauimone
handleThemeChanged slot to legend.
r586 appendMarkers(lineSeries);
sauimone
more intelligent legend. fixed compiler warning in bar.cpp
r565 break;
}
case QSeries::SeriesTypeArea: {
QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series);
sauimone
handleThemeChanged slot to legend.
r586 appendMarkers(areaSeries->upperSeries());
Michal Klocek
Bugfix dangling pointer in qlegend, remove debug info
r572 if(areaSeries->lowerSeries())
sauimone
handleThemeChanged slot to legend.
r586 appendMarkers(areaSeries->lowerSeries());
sauimone
more intelligent legend. fixed compiler warning in bar.cpp
r565 break;
}
case QSeries::SeriesTypeBar: {
QBarSeries* barSeries = static_cast<QBarSeries*>(series);
sauimone
handleThemeChanged slot to legend.
r586 appendMarkers(barSeries);
sauimone
more intelligent legend. fixed compiler warning in bar.cpp
r565 break;
}
case QSeries::SeriesTypeStackedBar: {
QStackedBarSeries* stackedBarSeries = static_cast<QStackedBarSeries*>(series);
sauimone
handleThemeChanged slot to legend.
r586 appendMarkers(stackedBarSeries);
sauimone
more intelligent legend. fixed compiler warning in bar.cpp
r565 break;
}
case QSeries::SeriesTypePercentBar: {
QPercentBarSeries* percentBarSeries = static_cast<QPercentBarSeries*>(series);
sauimone
handleThemeChanged slot to legend.
r586 appendMarkers(percentBarSeries);
sauimone
more intelligent legend. fixed compiler warning in bar.cpp
r565 break;
}
case QSeries::SeriesTypeScatter: {
QScatterSeries *scatterSeries = static_cast<QScatterSeries *>(series);
sauimone
handleThemeChanged slot to legend.
r586 appendMarkers(scatterSeries);
sauimone
more intelligent legend. fixed compiler warning in bar.cpp
r565 break;
}
case QSeries::SeriesTypePie: {
QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
sauimone
handleThemeChanged slot to legend.
r586 appendMarkers(pieSeries);
sauimone
more intelligent legend. fixed compiler warning in bar.cpp
r565 break;
}
case QSeries::SeriesTypeSpline: {
QSplineSeries* splineSeries = static_cast<QSplineSeries*>(series);
sauimone
handleThemeChanged slot to legend.
r586 appendMarkers(splineSeries);
sauimone
more intelligent legend. fixed compiler warning in bar.cpp
r565 break;
}
default: {
sauimone
handleThemeChanged slot to legend.
r586 qDebug()<< "QLegend::createMarkers" << series->type() << "not implemented.";
sauimone
more intelligent legend. fixed compiler warning in bar.cpp
r565 break;
}
}
sauimone
Legend can handle removing of series
r576 }
sauimone
handleThemeChanged slot to legend.
r586 void QLegend::appendMarkers(QXYSeries* series)
sauimone
First version of legend. Simple markers and serie names. Using drilldown as example for now.
r529 {
sauimone
more intelligent legend. fixed compiler warning in bar.cpp
r565 LegendMarker* marker = new LegendMarker(series,this);
marker->setName(series->name());
marker->setBrush(series->brush());
sauimone
combined clicked and rightclicked events of legend to one event with parameter
r567 connect(marker,SIGNAL(clicked(QSeries*,Qt::MouseButton)),this,SIGNAL(clicked(QSeries*,Qt::MouseButton)));
sauimone
Added handling for pieslice add/remove to legend
r637 connect(marker,SIGNAL(destroyed()),this,SLOT(handleMarkerDestroyed()));
sauimone
more intelligent legend. fixed compiler warning in bar.cpp
r565 mMarkers.append(marker);
childItems().append(marker);
}
sauimone
handleThemeChanged slot to legend.
r586 void QLegend::appendMarkers(QBarSeries *series)
sauimone
more intelligent legend. fixed compiler warning in bar.cpp
r565 {
foreach(QBarSet* s, series->barSets()) {
sauimone
Legend can handle removing of series
r576 LegendMarker* marker = new LegendMarker(series,s,this);
sauimone
more intelligent legend. fixed compiler warning in bar.cpp
r565 marker->setName(s->name());
marker->setBrush(s->brush());
sauimone
combined clicked and rightclicked events of legend to one event with parameter
r567 connect(marker,SIGNAL(clicked(QBarSet*,Qt::MouseButton)),this,SIGNAL(clicked(QBarSet*,Qt::MouseButton)));
sauimone
removed handlethemechange for legend. Too complex solution. Legend now listens the changed signals from series
r587 connect(s,SIGNAL(changed()),marker,SLOT(changed()));
sauimone
Added handling for pieslice add/remove to legend
r637 connect(marker,SIGNAL(destroyed()),this,SLOT(handleMarkerDestroyed()));
sauimone
more intelligent legend. fixed compiler warning in bar.cpp
r565 mMarkers.append(marker);
childItems().append(marker);
sauimone
First version of legend. Simple markers and serie names. Using drilldown as example for now.
r529 }
sauimone
more intelligent legend. fixed compiler warning in bar.cpp
r565 }
sauimone
First version of legend. Simple markers and serie names. Using drilldown as example for now.
r529
sauimone
handleThemeChanged slot to legend.
r586 void QLegend::appendMarkers(QPieSeries *series)
sauimone
more intelligent legend. fixed compiler warning in bar.cpp
r565 {
foreach(QPieSlice* s, series->slices()) {
sauimone
Legend can handle removing of series
r576 LegendMarker* marker = new LegendMarker(series,s,this);
sauimone
more intelligent legend. fixed compiler warning in bar.cpp
r565 marker->setName(s->label());
marker->setBrush(s->sliceBrush());
sauimone
combined clicked and rightclicked events of legend to one event with parameter
r567 connect(marker,SIGNAL(clicked(QPieSlice*,Qt::MouseButton)),this,SIGNAL(clicked(QPieSlice*,Qt::MouseButton)));
sauimone
removed handlethemechange for legend. Too complex solution. Legend now listens the changed signals from series
r587 connect(s,SIGNAL(changed()),marker,SLOT(changed()));
sauimone
Added handling for pieslice add/remove to legend
r637 connect(s,SIGNAL(destroyed()),marker,SLOT(deleteLater()));
connect(marker,SIGNAL(destroyed()),this,SLOT(handleMarkerDestroyed()));
sauimone
more intelligent legend. fixed compiler warning in bar.cpp
r565 mMarkers.append(marker);
childItems().append(marker);
sauimone
First version of legend. Simple markers and serie names. Using drilldown as example for now.
r529 }
}
sauimone
handleThemeChanged slot to legend.
r586 void QLegend::deleteMarkers(QSeries *series)
{
// Search all markers that belong to given series and delete them.
foreach (LegendMarker *m, mMarkers) {
if (m->series() == series) {
mMarkers.removeOne(m);
delete m;
}
}
}
sauimone
First version of legend. Simple markers and serie names. Using drilldown as example for now.
r529 void QLegend::layoutChanged()
{
// Calculate layout for markers and text
if (mMarkers.count() <= 0) {
// Nothing to do
return;
}
sauimone
Adaptive layout to legend. Tries to fit all items inside given maximum size
r626 // Find out widest item.
qreal itemMaxWidth = 0;
qreal itemMaxHeight = 0;
foreach (LegendMarker* m, mMarkers) {
if (m->boundingRect().width() > itemMaxWidth) {
itemMaxWidth = m->boundingRect().width();
}
if (m->boundingRect().height() > itemMaxHeight) {
itemMaxHeight = m->boundingRect().height();
}
}
int maxHorizontalItems = boundingRect().width() / itemMaxWidth;
int maxVerticalItems = boundingRect().height() / itemMaxHeight;
sauimone
legend layouting change
r616
sauimone
Adaptive layout to legend. Tries to fit all items inside given maximum size
r626 if (mMarkers.count() > maxHorizontalItems * maxVerticalItems) {
// TODO: overlapping layout
qDebug() << "Warning. Not enough space to layout all legend items properly.";
}
sauimone
legend layouting change
r616
sauimone
Adaptive layout to legend. Tries to fit all items inside given maximum size
r626 qreal margin = 5;
qreal totalWidth = 0;
qreal totalHeight = 0;
sauimone
legend layouting change
r616 switch (mPreferredLayout)
{
case QLegend::PreferredLayoutHorizontal: {
sauimone
Adaptive layout to legend. Tries to fit all items inside given maximum size
r626 /*
qreal xStep = mMaximumSize.width() / (mMarkers.count()+1);
if (xStep > itemMaxWidth) {
xStep = itemMaxWidth;
}
qreal yStep = mMaximumSize.height() / (mMarkers.count()+1);
if (yStep > itemMaxHeight) {
yStep = itemMaxHeight;
}*/
qreal xStep = itemMaxWidth;
qreal yStep = itemMaxHeight;
qreal x = mPos.x() + margin;
qreal y = mPos.y() + margin;
int row = 1;
int column = 0;
int maxRows = 1;
int maxColumns = 1;
sauimone
legend layouting change
r616 foreach (LegendMarker* m, mMarkers) {
sauimone
Adaptive layout to legend. Tries to fit all items inside given maximum size
r626 maxRows = row;
m->setPos(x,y);
sauimone
legend layouting change
r616 x += xStep;
sauimone
Adaptive layout to legend. Tries to fit all items inside given maximum size
r626 column++;
if (column > maxColumns) {
maxColumns = column;
}
if ((x + itemMaxWidth + margin*2) > (mPos.x() + mMaximumSize.width())) {
x = mPos.x() + margin;
y += yStep;
row++;
column = 0;
}
sauimone
legend layouting change
r616 }
sauimone
Adaptive layout to legend. Tries to fit all items inside given maximum size
r626 totalWidth = maxColumns * itemMaxWidth + margin * 2;
totalHeight = maxRows * itemMaxHeight + margin * 2;
sauimone
legend layouting change
r616 break;
sauimone
First version of legend. Simple markers and serie names. Using drilldown as example for now.
r529 }
sauimone
legend layouting change
r616 case QLegend::PreferredLayoutVertical: {
sauimone
Adaptive layout to legend. Tries to fit all items inside given maximum size
r626 /*
qreal xStep = mMaximumSize.width() / (mMarkers.count()+1);
if (xStep > itemMaxWidth) {
xStep = itemMaxWidth;
sauimone
legend layouting change
r616 }
sauimone
Adaptive layout to legend. Tries to fit all items inside given maximum size
r626 qreal yStep = mMaximumSize.height() / (mMarkers.count()+1);
if (yStep > itemMaxHeight) {
yStep = itemMaxHeight;
}*/
qreal xStep = itemMaxWidth;
qreal yStep = itemMaxHeight;
qreal x = mPos.x() + margin;
qreal y = mPos.y() + margin;
int row = 0;
int column = 1;
int maxRows = 1;
int maxColumns = 1;
sauimone
legend layouting change
r616 foreach (LegendMarker* m, mMarkers) {
sauimone
Adaptive layout to legend. Tries to fit all items inside given maximum size
r626 maxColumns = column;
m->setPos(x,y);
sauimone
legend layouting change
r616 y += yStep;
sauimone
Adaptive layout to legend. Tries to fit all items inside given maximum size
r626 row++;
if (row > maxRows) {
maxRows = row;
}
if ((y + itemMaxHeight + margin*2) > (mPos.y() + mMaximumSize.height())) {
y = mPos.y() + margin;
x += xStep;
column++;
row = 0;
}
sauimone
legend layouting change
r616 }
sauimone
Adaptive layout to legend. Tries to fit all items inside given maximum size
r626 totalWidth = maxColumns * itemMaxWidth + margin * 2;
totalHeight = maxRows * itemMaxHeight + margin * 2;
sauimone
legend layouting change
r616 break;
}
default: {
break;
}
}
sauimone
Adaptive layout to legend. Tries to fit all items inside given maximum size
r626 mSize.setWidth(totalWidth);
mSize.setHeight(totalHeight);
sauimone
First version of legend. Simple markers and serie names. Using drilldown as example for now.
r529 }
sauimone
framework for legend
r524 #include "moc_qlegend.cpp"
QTCOMMERCIALCHART_END_NAMESPACE