qlegend.cpp
661 lines
| 20.9 KiB
| text/x-c
|
CppLexer
/ src / qlegend.cpp
sauimone
|
r524 | #include "qchartglobal.h" | ||
#include "qlegend.h" | ||||
#include "qseries.h" | ||||
sauimone
|
r547 | #include "legendmarker_p.h" | ||
sauimone
|
r716 | #include "legendscrollbutton_p.h" | ||
sauimone
|
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
|
r626 | #include "chartpresenter_p.h" | ||
sauimone
|
r529 | #include <QPainter> | ||
#include <QPen> | ||||
sauimone
|
r524 | |||
sauimone
|
r547 | #include <QGraphicsSceneEvent> | ||
sauimone
|
r529 | |||
sauimone
|
r547 | QTCOMMERCIALCHART_BEGIN_NAMESPACE | ||
sauimone
|
r529 | |||
sauimone
|
r524 | QLegend::QLegend(QGraphicsItem *parent) | ||
: QGraphicsObject(parent) | ||||
sauimone
|
r626 | ,mPos(0,0) | ||
,mSize(0,0) | ||||
sauimone
|
r582 | ,mMinimumSize(50,20) // TODO: magic numbers | ||
sauimone
|
r616 | ,mMaximumSize(150,100) | ||
sauimone
|
r716 | ,m_brush(Qt::darkGray) // TODO: from theme? | ||
,mPreferredLayout(QLegend::PreferredLayoutTop) | ||||
,mFirstMarker(0) | ||||
,mMargin(5) | ||||
sauimone
|
r524 | { | ||
sauimone
|
r716 | // setVisible(false); | ||
mScrollButtonLeft = new LegendScrollButton(LegendScrollButton::ScrollButtonIdLeft, this); | ||||
mScrollButtonRight = new LegendScrollButton(LegendScrollButton::ScrollButtonIdRight, this); | ||||
mScrollButtonUp = new LegendScrollButton(LegendScrollButton::ScrollButtonIdUp, this); | ||||
mScrollButtonDown = new LegendScrollButton(LegendScrollButton::ScrollButtonIdDown, this); | ||||
connect(mScrollButtonLeft,SIGNAL(clicked(QGraphicsSceneMouseEvent*)),this,SLOT(handleScrollButtonClicked(QGraphicsSceneMouseEvent*))); | ||||
connect(mScrollButtonRight,SIGNAL(clicked(QGraphicsSceneMouseEvent*)),this,SLOT(handleScrollButtonClicked(QGraphicsSceneMouseEvent*))); | ||||
connect(mScrollButtonUp,SIGNAL(clicked(QGraphicsSceneMouseEvent*)),this,SLOT(handleScrollButtonClicked(QGraphicsSceneMouseEvent*))); | ||||
connect(mScrollButtonDown,SIGNAL(clicked(QGraphicsSceneMouseEvent*)),this,SLOT(handleScrollButtonClicked(QGraphicsSceneMouseEvent*))); | ||||
sauimone
|
r626 | setZValue(ChartPresenter::LegendZValue); | ||
sauimone
|
r524 | } | ||
void QLegend::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) | ||||
{ | ||||
Tero Ahola
|
r611 | Q_UNUSED(option) | ||
Q_UNUSED(widget) | ||||
sauimone
|
r716 | painter->setOpacity(0.8); | ||
Michal Klocek
|
r645 | painter->setPen(m_pen); | ||
painter->setBrush(m_brush); | ||||
sauimone
|
r626 | painter->drawRect(boundingRect()); | ||
sauimone
|
r524 | } | ||
QRectF QLegend::boundingRect() const | ||||
{ | ||||
sauimone
|
r626 | return QRectF(mPos,mSize); | ||
sauimone
|
r524 | } | ||
Michal Klocek
|
r645 | void QLegend::setBrush(const QBrush& brush) | ||
sauimone
|
r540 | { | ||
Michal Klocek
|
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
|
r540 | } | ||
Michal Klocek
|
r645 | QPen QLegend::pen() const | ||
sauimone
|
r540 | { | ||
Michal Klocek
|
r645 | return m_pen; | ||
sauimone
|
r540 | } | ||
sauimone
|
r616 | void QLegend::setPreferredLayout(QLegend::PreferredLayout preferred) | ||
{ | ||||
mPreferredLayout = preferred; | ||||
sauimone
|
r716 | updateLayout(); | ||
} | ||||
QLegend::PreferredLayout QLegend::preferredLayout() const | ||||
{ | ||||
return mPreferredLayout; | ||||
sauimone
|
r616 | } | ||
sauimone
|
r626 | QSizeF QLegend::maximumSize() const | ||
sauimone
|
r582 | { | ||
sauimone
|
r626 | return mMaximumSize; | ||
sauimone
|
r582 | } | ||
sauimone
|
r626 | void QLegend::setMaximumSize(const QSizeF size) | ||
sauimone
|
r582 | { | ||
sauimone
|
r626 | mMaximumSize = size; | ||
sauimone
|
r716 | updateLayout(); | ||
sauimone
|
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
|
r716 | updateLayout(); | ||
sauimone
|
r582 | } | ||
Tero Ahola
|
r611 | void QLegend::handleSeriesAdded(QSeries* series, Domain* domain) | ||
sauimone
|
r524 | { | ||
Tero Ahola
|
r611 | Q_UNUSED(domain) | ||
sauimone
|
r586 | createMarkers(series); | ||
sauimone
|
r637 | connectSeries(series); | ||
sauimone
|
r716 | updateLayout(); | ||
sauimone
|
r586 | } | ||
void QLegend::handleSeriesRemoved(QSeries* series) | ||||
{ | ||||
sauimone
|
r637 | disconnectSeries(series); | ||
sauimone
|
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); | ||||
} | ||||
sauimone
|
r716 | updateLayout(); | ||
sauimone
|
r586 | } | ||
sauimone
|
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
|
r643 | connect(marker,SIGNAL(destroyed()),this,SLOT(handleMarkerDestroyed())); | ||
sauimone
|
r637 | mMarkers.append(marker); | ||
childItems().append(marker); | ||||
} | ||||
sauimone
|
r716 | updateLayout(); | ||
sauimone
|
r637 | } | ||
sauimone
|
r643 | void QLegend::handleRemoved(QList<QPieSlice *> slices) | ||
{ | ||||
Tero Ahola
|
r647 | Q_UNUSED(slices) | ||
sauimone
|
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
|
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); | ||||
sauimone
|
r716 | updateLayout(); | ||
} | ||||
void QLegend::handleScrollButtonClicked(QGraphicsSceneMouseEvent *event) | ||||
{ | ||||
Q_UNUSED(event); // Maybe later somethin happens with right click... | ||||
// TODO: detect sender object. scroll to appropiate direction. | ||||
LegendScrollButton* scrollButton = static_cast<LegendScrollButton*> (sender()); | ||||
Q_ASSERT(scrollButton); | ||||
switch (scrollButton->id()) { | ||||
case LegendScrollButton::ScrollButtonIdLeft: | ||||
case LegendScrollButton::ScrollButtonIdUp: { | ||||
// Lower limit is same in these cases | ||||
mFirstMarker--; | ||||
checkMarkerBounds(); | ||||
break; | ||||
} | ||||
case LegendScrollButton::ScrollButtonIdRight: | ||||
case LegendScrollButton::ScrollButtonIdDown: { | ||||
mFirstMarker++; | ||||
checkMarkerBounds(); | ||||
break; | ||||
} | ||||
default: { | ||||
break; | ||||
} | ||||
} | ||||
updateLayout(); | ||||
sauimone
|
r637 | } | ||
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
|
r586 | void QLegend::createMarkers(QSeries *series) | ||
{ | ||||
sauimone
|
r565 | switch (series->type()) | ||
{ | ||||
case QSeries::SeriesTypeLine: { | ||||
QLineSeries* lineSeries = static_cast<QLineSeries*>(series); | ||||
sauimone
|
r586 | appendMarkers(lineSeries); | ||
sauimone
|
r565 | break; | ||
} | ||||
case QSeries::SeriesTypeArea: { | ||||
QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series); | ||||
sauimone
|
r586 | appendMarkers(areaSeries->upperSeries()); | ||
Michal Klocek
|
r572 | if(areaSeries->lowerSeries()) | ||
sauimone
|
r586 | appendMarkers(areaSeries->lowerSeries()); | ||
sauimone
|
r565 | break; | ||
} | ||||
case QSeries::SeriesTypeBar: { | ||||
QBarSeries* barSeries = static_cast<QBarSeries*>(series); | ||||
sauimone
|
r586 | appendMarkers(barSeries); | ||
sauimone
|
r565 | break; | ||
} | ||||
case QSeries::SeriesTypeStackedBar: { | ||||
QStackedBarSeries* stackedBarSeries = static_cast<QStackedBarSeries*>(series); | ||||
sauimone
|
r586 | appendMarkers(stackedBarSeries); | ||
sauimone
|
r565 | break; | ||
} | ||||
case QSeries::SeriesTypePercentBar: { | ||||
QPercentBarSeries* percentBarSeries = static_cast<QPercentBarSeries*>(series); | ||||
sauimone
|
r586 | appendMarkers(percentBarSeries); | ||
sauimone
|
r565 | break; | ||
} | ||||
case QSeries::SeriesTypeScatter: { | ||||
QScatterSeries *scatterSeries = static_cast<QScatterSeries *>(series); | ||||
sauimone
|
r586 | appendMarkers(scatterSeries); | ||
sauimone
|
r565 | break; | ||
} | ||||
case QSeries::SeriesTypePie: { | ||||
QPieSeries *pieSeries = static_cast<QPieSeries *>(series); | ||||
sauimone
|
r586 | appendMarkers(pieSeries); | ||
sauimone
|
r565 | break; | ||
} | ||||
case QSeries::SeriesTypeSpline: { | ||||
QSplineSeries* splineSeries = static_cast<QSplineSeries*>(series); | ||||
sauimone
|
r586 | appendMarkers(splineSeries); | ||
sauimone
|
r565 | break; | ||
} | ||||
default: { | ||||
sauimone
|
r586 | qDebug()<< "QLegend::createMarkers" << series->type() << "not implemented."; | ||
sauimone
|
r565 | break; | ||
} | ||||
} | ||||
sauimone
|
r576 | } | ||
sauimone
|
r586 | void QLegend::appendMarkers(QXYSeries* series) | ||
sauimone
|
r529 | { | ||
sauimone
|
r565 | LegendMarker* marker = new LegendMarker(series,this); | ||
marker->setName(series->name()); | ||||
marker->setBrush(series->brush()); | ||||
sauimone
|
r567 | connect(marker,SIGNAL(clicked(QSeries*,Qt::MouseButton)),this,SIGNAL(clicked(QSeries*,Qt::MouseButton))); | ||
sauimone
|
r637 | connect(marker,SIGNAL(destroyed()),this,SLOT(handleMarkerDestroyed())); | ||
sauimone
|
r565 | mMarkers.append(marker); | ||
childItems().append(marker); | ||||
} | ||||
sauimone
|
r586 | void QLegend::appendMarkers(QBarSeries *series) | ||
sauimone
|
r565 | { | ||
foreach(QBarSet* s, series->barSets()) { | ||||
sauimone
|
r576 | LegendMarker* marker = new LegendMarker(series,s,this); | ||
sauimone
|
r565 | marker->setName(s->name()); | ||
marker->setBrush(s->brush()); | ||||
sauimone
|
r567 | connect(marker,SIGNAL(clicked(QBarSet*,Qt::MouseButton)),this,SIGNAL(clicked(QBarSet*,Qt::MouseButton))); | ||
sauimone
|
r670 | connect(s,SIGNAL(valueChanged()),marker,SLOT(changed())); | ||
sauimone
|
r637 | connect(marker,SIGNAL(destroyed()),this,SLOT(handleMarkerDestroyed())); | ||
sauimone
|
r565 | mMarkers.append(marker); | ||
childItems().append(marker); | ||||
sauimone
|
r529 | } | ||
sauimone
|
r565 | } | ||
sauimone
|
r529 | |||
sauimone
|
r586 | void QLegend::appendMarkers(QPieSeries *series) | ||
sauimone
|
r565 | { | ||
foreach(QPieSlice* s, series->slices()) { | ||||
sauimone
|
r576 | LegendMarker* marker = new LegendMarker(series,s,this); | ||
sauimone
|
r565 | marker->setName(s->label()); | ||
marker->setBrush(s->sliceBrush()); | ||||
sauimone
|
r567 | connect(marker,SIGNAL(clicked(QPieSlice*,Qt::MouseButton)),this,SIGNAL(clicked(QPieSlice*,Qt::MouseButton))); | ||
sauimone
|
r587 | connect(s,SIGNAL(changed()),marker,SLOT(changed())); | ||
sauimone
|
r637 | connect(s,SIGNAL(destroyed()),marker,SLOT(deleteLater())); | ||
connect(marker,SIGNAL(destroyed()),this,SLOT(handleMarkerDestroyed())); | ||||
sauimone
|
r565 | mMarkers.append(marker); | ||
childItems().append(marker); | ||||
sauimone
|
r529 | } | ||
} | ||||
sauimone
|
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
|
r716 | void QLegend::updateLayout() | ||
sauimone
|
r529 | { | ||
// Calculate layout for markers and text | ||||
if (mMarkers.count() <= 0) { | ||||
// Nothing to do | ||||
return; | ||||
} | ||||
sauimone
|
r716 | checkMarkerBounds(); | ||
sauimone
|
r529 | |||
sauimone
|
r626 | // Find out widest item. | ||
sauimone
|
r716 | QSizeF markerMaxSize = maximumMarkerSize(); | ||
sauimone
|
r626 | |||
sauimone
|
r716 | // Use max height as scroll button size | ||
rescaleScrollButtons(QSize(markerMaxSize.height() ,markerMaxSize.height())); | ||||
sauimone
|
r616 | |||
sauimone
|
r626 | qreal totalWidth = 0; | ||
qreal totalHeight = 0; | ||||
sauimone
|
r616 | switch (mPreferredLayout) | ||
{ | ||||
sauimone
|
r716 | // Both cases organise items horizontally | ||
case QLegend::PreferredLayoutBottom: | ||||
case QLegend::PreferredLayoutTop: { | ||||
qreal xStep = markerMaxSize.width(); | ||||
qreal x = mPos.x() + mMargin; | ||||
qreal y = mPos.y() + mMargin; | ||||
sauimone
|
r626 | int column = 0; | ||
int maxColumns = 1; | ||||
sauimone
|
r716 | qreal scrollButtonPadding = 0; | ||
// Set correct visibility for scroll scrollbuttons | ||||
if (scrollButtonsVisible()) { | ||||
mScrollButtonLeft->setVisible(true); | ||||
mScrollButtonRight->setVisible(true); | ||||
totalWidth += (mScrollButtonLeft->boundingRect().width() + mMargin) * 2; // scrollbuttons visible, so add their width to total width | ||||
x += mScrollButtonLeft->boundingRect().width() + mMargin; // start position changes by scrollbutton width | ||||
scrollButtonPadding = mScrollButtonLeft->boundingRect().width(); | ||||
} else { | ||||
mScrollButtonLeft->setVisible(false); | ||||
mScrollButtonRight->setVisible(false); | ||||
} | ||||
mScrollButtonUp->setVisible(false); | ||||
mScrollButtonDown->setVisible(false); | ||||
for (int i=0; i<mMarkers.count(); i++) { | ||||
LegendMarker* m = mMarkers.at(i); | ||||
if (i<mFirstMarker) { | ||||
// Markers before first are not visible. | ||||
m->setVisible(false); | ||||
} else { | ||||
if ((x + xStep + scrollButtonPadding) > (mPos.x() + mMaximumSize.width())) { | ||||
// This marker would go outside legend rect. | ||||
m->setVisible(false); | ||||
} else { | ||||
// This marker is ok | ||||
m->setVisible(true); | ||||
m->setPos(x,y); | ||||
x += xStep; | ||||
column++; | ||||
} | ||||
sauimone
|
r626 | } | ||
sauimone
|
r716 | maxColumns = column; | ||
sauimone
|
r616 | } | ||
sauimone
|
r716 | |||
mScrollButtonLeft->setPos(mPos.x() + mMargin, y); | ||||
mScrollButtonRight->setPos(x+mMargin,y); | ||||
totalWidth += maxColumns * markerMaxSize.width() + mMargin * 2; | ||||
totalHeight = markerMaxSize.height() + mMargin * 2; | ||||
sauimone
|
r616 | break; | ||
sauimone
|
r529 | } | ||
sauimone
|
r716 | // Both cases organize items vertically | ||
case QLegend::PreferredLayoutLeft: | ||||
case QLegend::PreferredLayoutRight: { | ||||
qreal yStep = markerMaxSize.height(); | ||||
qreal x = mPos.x() + mMargin; | ||||
qreal y = mPos.y() + mMargin; | ||||
int row = 1; | ||||
int maxRows = 1; | ||||
qreal scrollButtonPadding = 0; | ||||
// Set correct visibility for scroll scrollbuttons | ||||
if (scrollButtonsVisible()) { | ||||
mScrollButtonUp->setVisible(true); | ||||
mScrollButtonDown->setVisible(true); | ||||
totalHeight += (mScrollButtonUp->boundingRect().height() + mMargin) * 2; // scrollbuttons visible, so add their height to total height | ||||
y += mScrollButtonUp->boundingRect().height() + mMargin; // start position changes by scrollbutton height | ||||
scrollButtonPadding = mScrollButtonUp->boundingRect().height(); | ||||
} else { | ||||
mScrollButtonUp->setVisible(false); | ||||
mScrollButtonDown->setVisible(false); | ||||
sauimone
|
r616 | } | ||
sauimone
|
r716 | mScrollButtonLeft->setVisible(false); | ||
mScrollButtonRight->setVisible(false); | ||||
for (int i=0; i<mMarkers.count(); i++) { | ||||
LegendMarker* m = mMarkers.at(i); | ||||
if (i<mFirstMarker) { | ||||
// Markers before first are not visible. | ||||
m->setVisible(false); | ||||
} else { | ||||
if ((y + yStep + scrollButtonPadding) > (mPos.y() + mMaximumSize.height())) { | ||||
// This marker would go outside legend rect. | ||||
m->setVisible(false); | ||||
} else { | ||||
// This marker is ok | ||||
m->setVisible(true); | ||||
m->setPos(x,y); | ||||
y += yStep; | ||||
row++; | ||||
} | ||||
} | ||||
maxRows = row; | ||||
} | ||||
mScrollButtonUp->setPos(mPos.x() + mMargin, mPos.y() + mMargin); | ||||
mScrollButtonDown->setPos(mPos.x() + mMargin, y + mMargin); | ||||
totalWidth += markerMaxSize.width() + mMargin * 2; | ||||
totalHeight = maxRows * markerMaxSize.height() + mMargin * 4 + scrollButtonPadding; // TODO: check this | ||||
/* | ||||
qreal yStep = markerMaxSize.height(); | ||||
qreal x = mPos.x() + mMargin; | ||||
qreal y = mPos.y() + mMargin; | ||||
sauimone
|
r626 | int row = 0; | ||
int maxRows = 1; | ||||
int maxColumns = 1; | ||||
sauimone
|
r716 | for (int i=0; i<mMarkers.count(); i++) { | ||
LegendMarker* m = mMarkers.at(i); | ||||
if (i<mFirstMarker) { | ||||
// Markers before first are not visible. | ||||
m->setVisible(false); | ||||
} else { | ||||
if ((y + markerMaxSize.height() + mMargin*2) > (mPos.y() + mMaximumSize.height())) { | ||||
// This marker would go outside legend rect. | ||||
m->setVisible(false); | ||||
} else { | ||||
// This marker is ok | ||||
m->setVisible(true); | ||||
maxRows = row; | ||||
m->setPos(x,y); | ||||
y += yStep; | ||||
row++; | ||||
} | ||||
sauimone
|
r626 | } | ||
sauimone
|
r716 | maxRows = row; | ||
sauimone
|
r616 | } | ||
sauimone
|
r716 | totalWidth = maxColumns * markerMaxSize.width() + mMargin * 2; | ||
totalHeight = maxRows * markerMaxSize.height() + mMargin * 2; | ||||
*/ | ||||
sauimone
|
r616 | break; | ||
} | ||||
default: { | ||||
break; | ||||
} | ||||
} | ||||
sauimone
|
r626 | mSize.setWidth(totalWidth); | ||
mSize.setHeight(totalHeight); | ||||
sauimone
|
r716 | |||
update(); | ||||
} | ||||
void QLegend::rescaleScrollButtons(const QSize &size) | ||||
{ | ||||
QPolygonF left; | ||||
left << QPointF(size.width(),0) << QPointF(0,size.height()/2) << QPointF(size.width(),size.height()); | ||||
QPolygonF right; | ||||
right << QPointF(0,0) << QPointF(size.width(),size.height()/2) << QPointF(0,size.height()); | ||||
QPolygonF up; | ||||
up << QPointF(0,size.height()) << QPointF(size.width()/2,0) << QPointF(size.width(),size.height()); | ||||
QPolygonF down; | ||||
down << QPointF(0,0) << QPointF(size.width()/2,size.height()) << QPointF(size.width(),0); | ||||
mScrollButtonLeft->setPolygon(left); | ||||
mScrollButtonRight->setPolygon(right); | ||||
mScrollButtonUp->setPolygon(up); | ||||
mScrollButtonDown->setPolygon(down); | ||||
} | ||||
QSizeF QLegend::maximumMarkerSize() | ||||
{ | ||||
QSizeF max(0,0); | ||||
foreach (LegendMarker* m, mMarkers) { | ||||
if (m->boundingRect().width() > max.width()) { | ||||
max.setWidth(m->boundingRect().width()); | ||||
} | ||||
if (m->boundingRect().height() > max.height()) { | ||||
max.setHeight(m->boundingRect().height()); | ||||
} | ||||
} | ||||
return max; | ||||
} | ||||
void QLegend::checkMarkerBounds() | ||||
{ | ||||
if ((mPreferredLayout == QLegend::PreferredLayoutLeft) || (mPreferredLayout == QLegend::PreferredLayoutRight)) { | ||||
// Bounds limited by height | ||||
int max; | ||||
if (scrollButtonsVisible()) { | ||||
max = (mMaximumSize.height() - mScrollButtonLeft->boundingRect().height() * 2 - mMargin*2) / maximumMarkerSize().height(); | ||||
} else { | ||||
max = mMaximumSize.height() / maximumMarkerSize().height(); | ||||
} | ||||
if (mFirstMarker > mMarkers.count() - max) { | ||||
mFirstMarker = mMarkers.count() - max; | ||||
} | ||||
} else { | ||||
// Bounds limited by width | ||||
int max; | ||||
if (scrollButtonsVisible()) { | ||||
max = (mMaximumSize.width() - mScrollButtonLeft->boundingRect().width() * 2 - mMargin*2) / maximumMarkerSize().width(); | ||||
} else { | ||||
max = mMaximumSize.width() / maximumMarkerSize().width(); | ||||
} | ||||
if (mFirstMarker > mMarkers.count() - max) { | ||||
mFirstMarker = mMarkers.count() - max; | ||||
} | ||||
} | ||||
if (mFirstMarker < 0) { | ||||
mFirstMarker = 0; | ||||
} | ||||
} | ||||
bool QLegend::scrollButtonsVisible() | ||||
{ | ||||
// Just a helper to clarify, what the magic below means :) | ||||
if ((mPreferredLayout == QLegend::PreferredLayoutTop) || (mPreferredLayout == QLegend::PreferredLayoutBottom)) { | ||||
return (maximumMarkerSize().width() * mMarkers.count() + mMargin * 3 > mMaximumSize.width()); | ||||
} | ||||
return (maximumMarkerSize().height() * mMarkers.count() + mMargin * 3 > mMaximumSize.height()); | ||||
sauimone
|
r529 | } | ||
sauimone
|
r524 | #include "moc_qlegend.cpp" | ||
QTCOMMERCIALCHART_END_NAMESPACE | ||||