12 #include "KDChartAbstractDiagram_p.h"
14 #include <QAbstractProxyModel>
15 #include <QApplication>
25 #include "KDChartPainterSaver_p.h"
29 #include <KDABLibFakes>
38 : QAbstractItemView(parent)
51 void AbstractDiagram::init()
54 d->reverseMapper.setDiagram(
this);
65 (horizontalScrollBarPolicy() == other->horizontalScrollBarPolicy()) && (verticalScrollBarPolicy() == other->verticalScrollBarPolicy()) &&
67 (frameShadow() == other->frameShadow()) && (frameShape() == other->frameShape()) &&
70 (lineWidth() == other->lineWidth()) && (midLineWidth() == other->midLineWidth()) &&
72 (alternatingRowColors() == other->alternatingRowColors()) && (hasAutoScroll() == other->hasAutoScroll()) && (dragDropMode() == other->dragDropMode()) && (dragDropOverwriteMode() == other->dragDropOverwriteMode()) && (horizontalScrollMode() == other->horizontalScrollMode()) && (verticalScrollMode() == other->verticalScrollMode()) && (dragEnabled() == other->dragEnabled()) && (editTriggers() == other->editTriggers()) && (iconSize() == other->iconSize()) && (selectionBehavior() == other->selectionBehavior()) && (selectionMode() == other->selectionMode()) && (showDropIndicator() == other->showDropIndicator()) && (tabKeyNavigation() == other->tabKeyNavigation()) && (textElideMode() == other->textElideMode()) &&
86 if (
d->databoundariesDirty) {
88 d->databoundariesDirty =
false;
90 return d->databoundaries;
95 d->databoundariesDirty =
true;
101 if (newModel == model()) {
107 d->setAttributesModel(amodel);
109 QAbstractItemView::setModel(newModel);
111 QAbstractItemModel *oldModel = QAbstractItemView::model();
112 if (oldModel !=
nullptr) {
117 scheduleDelayedItemsLayout();
124 if (selectionModel()) {
128 QAbstractItemView::setSelectionModel(newSelectionModel);
129 if (selectionModel()) {
145 if (amodel->sourceModel() != model()) {
146 qWarning(
"KDChart::AbstractDiagram::setAttributesModel() failed: "
147 "Trying to set an attributesmodel which works on a different "
148 "model than the diagram.");
151 if (qobject_cast<PrivateAttributesModel *>(amodel)) {
152 qWarning(
"KDChart::AbstractDiagram::setAttributesModel() failed: "
153 "Trying to set an attributesmodel that is private to another diagram.");
157 d->setAttributesModel(amodel);
158 scheduleDelayedItemsLayout();
165 return d->usesExternalAttributesModel();
170 return d->attributesModel;
173 QModelIndex AbstractDiagram::conditionallyMapFromSource(
const QModelIndex &index)
const
182 QAbstractItemView::setRootIndex(idx);
189 d->attributesModelRootIndex = idx;
191 scheduleDelayedItemsLayout();
198 if (!
d->attributesModelRootIndex.isValid())
199 d->attributesModelRootIndex =
d->attributesModel->mapFromSource(rootIndex());
200 return d->attributesModelRootIndex;
211 d->plane->layoutDiagrams();
214 QAbstractItemView::doItemsLayout();
218 const QModelIndex &bottomRight,
219 const QVector<int> &)
222 Q_UNUSED(bottomRight);
225 scheduleDelayedItemsLayout();
230 d->attributesModel->setData(
231 conditionallyMapFromSource(index),
232 QVariant::fromValue(hidden),
239 d->setDatasetAttrs(dataset, QVariant::fromValue(hidden),
DataHiddenRole);
245 d->attributesModel->setModelData(QVariant::fromValue(hidden),
DataHiddenRole);
257 if (boolFlag.isValid())
258 return boolFlag.value<
bool>();
264 const QVariant boolFlag(
attributesModel()->data(conditionallyMapFromSource(index),
266 if (boolFlag.isValid()) {
267 return boolFlag.value<
bool>();
269 int dataset = index.column() /
d->datasetDimension;
276 d->attributesModel->setData(conditionallyMapFromSource(index), QVariant::fromValue(a),
305 const QVariant headerAttrs(
307 if (headerAttrs.isValid())
315 conditionallyMapFromSource(index),
331 d->allowOverlappingDataValueTexts = allow;
337 return d->allowOverlappingDataValueTexts;
342 d->antiAliasing = enabled;
348 return d->antiAliasing;
353 d->percent = percent;
363 const QModelIndex &index,
367 d->paintDataValueText(painter, index, pos, value);
376 d->forgetAlreadyPaintedDataValues();
377 const int rowCount = model()->rowCount(rootIndex());
378 const int columnCount = model()->columnCount(rootIndex());
380 for (
int row = 0; row < rowCount; ++row) {
381 QModelIndex index = model()->index(row, column, rootIndex());
386 y = index.data().toReal();
388 x = index.data().toReal();
389 y = model()->index(row, column + 1, rootIndex()).data().toReal();
398 const QModelIndex &index,
407 const PainterSaver painterSaver(painter);
409 const QSizeF maSize(ma.
markerSize().width() / painter->transform().m11(),
410 ma.
markerSize().height() / painter->transform().m22());
411 QBrush indexBrush(
brush(index));
412 QPen indexPen(ma.
pen());
416 paintMarker(painter, ma, indexBrush, indexPen, pos, maSize);
423 d->reverseMapper.addCircle(index.row(), index.column(), pos, 2 * maSize);
427 const QModelIndex &index,
440 const QSizeF &maSize)
442 const QPen oldPen(painter->pen());
450 const qreal x = pos.x();
451 const qreal y = pos.y();
452 painter->drawLine(QPointF(x - 1.0, y - 1.0),
453 QPointF(x + 1.0, y - 1.0));
454 painter->drawLine(QPointF(x - 1.0, y),
455 QPointF(x + 1.0, y));
456 painter->drawLine(QPointF(x - 1.0, y + 1.0),
457 QPointF(x + 1.0, y + 1.0));
459 painter->drawPoint(pos);
461 const PainterSaver painterSaver(painter);
462 QPen painterPen(
pen);
464 painter->setBrush(
brush);
465 painter->setRenderHint(QPainter::Antialiasing);
466 painter->translate(pos);
469 if (markerAttributes.
threeD()) {
470 QRadialGradient grad;
471 grad.setCoordinateMode(QGradient::ObjectBoundingMode);
472 QColor drawColor =
brush.color();
473 grad.setCenter(0.5, 0.5);
475 grad.setFocalPoint(0.35, 0.35);
476 grad.setColorAt(0.00, drawColor.lighter(150));
477 grad.setColorAt(0.20, drawColor);
478 grad.setColorAt(0.50, drawColor.darker(150));
479 grad.setColorAt(0.75, drawColor.darker(200));
480 grad.setColorAt(0.95, drawColor.darker(250));
481 grad.setColorAt(1.00, drawColor.darker(200));
482 QBrush newBrush(grad);
483 newBrush.setTransform(
brush.transform());
484 painter->setBrush(newBrush);
486 painter->drawEllipse(QRectF(0 - maSize.height() / 2, 0 - maSize.width() / 2,
487 maSize.height(), maSize.width()));
490 QRectF rect(0 - maSize.width() / 2, 0 - maSize.height() / 2,
491 maSize.width(), maSize.height());
492 painter->drawRect(rect);
496 QVector<QPointF> diamondPoints;
497 QPointF top, left, bottom, right;
498 top = QPointF(0, 0 - maSize.height() / 2);
499 left = QPointF(0 - maSize.width() / 2, 0);
500 bottom = QPointF(0, maSize.height() / 2);
501 right = QPointF(maSize.width() / 2, 0);
502 diamondPoints << top << left << bottom << right;
503 painter->drawPolygon(diamondPoints);
511 painter->setBrush(Qt::NoBrush);
513 painter->drawEllipse(QRectF(0 - maSize.height() / 2, 0 - maSize.width() / 2,
514 maSize.height(), maSize.width()));
520 const qreal w02 = maSize.width() * 0.2;
521 const qreal w05 = maSize.width() * 0.5;
522 const qreal h02 = maSize.height() * 0.2;
523 const qreal h05 = maSize.height() * 0.5;
524 QVector<QPointF> crossPoints;
526 p[0] = QPointF(-w02, -h05);
527 p[1] = QPointF(w02, -h05);
528 p[2] = QPointF(w02, -h02);
529 p[3] = QPointF(w05, -h02);
530 p[4] = QPointF(w05, h02);
531 p[5] = QPointF(w02, h02);
532 p[6] = QPointF(w02, h05);
533 p[7] = QPointF(-w02, h05);
534 p[8] = QPointF(-w02, h02);
535 p[9] = QPointF(-w05, h02);
536 p[10] = QPointF(-w05, -h02);
537 p[11] = QPointF(-w02, -h02);
538 for (
int i = 0; i < 12; ++i)
541 painter->drawPolygon(crossPoints);
545 QPointF left, right, top, bottom;
546 left = QPointF(-maSize.width() / 2, 0);
547 right = QPointF(maSize.width() / 2, 0);
548 top = QPointF(0, -maSize.height() / 2);
549 bottom = QPointF(0, maSize.height() / 2);
551 painter->drawLine(left, right);
552 painter->drawLine(top, bottom);
559 const QRectF pathBoundingRect = path.boundingRect();
560 const qreal xScaling = maSize.height() / pathBoundingRect.height();
561 const qreal yScaling = maSize.width() / pathBoundingRect.width();
562 const qreal scaling = qMin(xScaling, yScaling);
563 painter->scale(scaling, scaling);
565 painter->drawPath(path);
569 Q_ASSERT_X(
false,
"paintMarkers()",
570 "Type item does not match a defined Marker Type.");
573 painter->setPen(oldPen);
582 const int rowCount = model()->rowCount(rootIndex());
583 const int columnCount = model()->columnCount(rootIndex());
585 for (
int row = 0; row < rowCount; ++row) {
586 QModelIndex index = model()->index(row, column, rootIndex());
591 y = index.data().toReal();
593 x = index.data().toReal();
594 y = model()->index(row, column + 1, rootIndex()).data().toReal();
604 conditionallyMapFromSource(index),
630 if (penSettings.isValid())
631 return penSettings.value<QPen>();
638 conditionallyMapFromSource(index),
646 conditionallyMapFromSource(index),
672 if (brushSettings.isValid())
673 return brushSettings.value<QBrush>();
690 d->unitPrefixMap[column][orientation] = prefix;
700 d->unitPrefix[orientation] = prefix;
711 d->unitSuffixMap[column][orientation] = suffix;
721 d->unitSuffix[orientation] = suffix;
733 if (!fallback ||
d->unitPrefixMap[column].contains(orientation))
734 return d->unitPrefixMap[column][orientation];
735 return d->unitPrefix[orientation];
744 return d->unitPrefix[orientation];
756 if (!fallback ||
d->unitSuffixMap[column].contains(orientation))
757 return d->unitSuffixMap[column][orientation];
758 return d->unitSuffix[orientation];
767 return d->unitSuffix[orientation];
773 return d->reverseMapper.boundingRect(index.row(), index.column()).toRect();
784 return QModelIndex();
804 const QModelIndexList indexes =
d->indexesIn(rect);
805 QItemSelection selection;
806 for (
const QModelIndex &index : indexes) {
807 selection.append(QItemSelectionRange(index));
809 selectionModel()->select(selection, command);
815 const auto constIndexes = selection.indexes();
816 for (
const QModelIndex &index : constIndexes) {
817 polygon <<
d->reverseMapper.polygon(index.row(), index.column());
819 return polygon.isEmpty() ? QRegion() : QRegion(polygon.toPolygon());
824 QPolygonF polygon =
d->reverseMapper.polygon(index.row(), index.column());
825 return polygon.isEmpty() ? QRegion() : QRegion(polygon.toPolygon());
849 for (
int i = 0; i < rowCount; ++i) {
863 const int datasetCount =
d->datasetCount();
864 for (
int i = 0; i < datasetCount; ++i) {
865 ret <<
d->datasetAttrs(i, Qt::DisplayRole).toString();
876 const int datasetCount =
d->datasetCount();
877 for (
int i = 0; i < datasetCount; ++i) {
889 const int datasetCount =
d->datasetCount();
890 for (
int i = 0; i < datasetCount; ++i) {
898 QList<MarkerAttributes> ret;
902 const int datasetCount =
d->datasetCount();
903 for (
int i = 0; i < datasetCount; ++i) {
911 if (!justReturnTheStatus) {
912 Q_ASSERT_X(model(),
"AbstractDiagram::checkInvariants()",
913 "There is no usable model set, for the diagram.");
916 "There is no usable coordinate plane set, for the diagram.");
923 return d->datasetDimension;
929 qDebug() <<
"Setting the dataset dimension using AbstractDiagram::setDatasetDimension is "
930 "obsolete. Use the specific diagram types instead.";
935 Q_ASSERT(dimension != 0);
936 if (
d->datasetDimension == dimension) {
939 d->datasetDimension = dimension;
940 d->attributesModel->setDatasetDimension(dimension);
948 qWarning() <<
"AbstractDiagram::valueForCell(): Requesting value for invalid index!";
949 return std::numeric_limits<qreal>::quiet_NaN();
951 return d->attributesModel->data(
965 return d->indexAt(point);
970 return d->indexesAt(point);
975 return d->indexesIn(rect);
Declaring the class KDChart::DataValueAttributes.
QPointF translate(const TernaryPoint &point)
Base class common for all coordinate planes, CartesianCoordinatePlane, PolarCoordinatePlane,...
AbstractDiagram defines the interface for diagram classes.
void setModel(QAbstractItemModel *model) override
void setDataValueAttributes(const QModelIndex &index, const DataValueAttributes &a)
virtual Q_DECL_DEPRECATED void paintDataValueTexts(QPainter *painter)
virtual const QPair< QPointF, QPointF > calculateDataBoundaries() const =0
virtual AttributesModel * attributesModel() const
bool compare(const AbstractDiagram *other) const
void setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command) override
int verticalOffset() const override
void setUnitPrefix(const QString &prefix, int column, Qt::Orientation orientation)
virtual bool checkInvariants(bool justReturnTheStatus=false) const
void setPen(const QModelIndex &index, const QPen &pen)
virtual void paintMarker(QPainter *painter, const MarkerAttributes &markerAttributes, const QBrush &brush, const QPen &, const QPointF &point, const QSizeF &size)
int horizontalOffset() const override
~AbstractDiagram() override
QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) override
DataValueAttributes dataValueAttributes() const
void paintDataValueText(QPainter *painter, const QModelIndex &index, const QPointF &pos, qreal value)
void setAntiAliasing(bool enabled)
QStringList datasetLabels() const
QRect visualRect(const QModelIndex &index) const override
void layoutChanged(AbstractDiagram *)
AbstractDiagram(Private *p, QWidget *parent, AbstractCoordinatePlane *plane)
QModelIndex attributesModelRootIndex() const
returns a QModelIndex pointing into the AttributesModel that corresponds to the root index of the dia...
const QPair< QPointF, QPointF > dataBoundaries() const
Return the bottom left and top right data point, that the diagram will display (unless the grid adjus...
void scrollTo(const QModelIndex &index, ScrollHint hint=EnsureVisible) override
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector< int > &roles=QVector< int >()) override
QList< QBrush > datasetBrushes() const
virtual void setAttributesModel(AttributesModel *model)
Sets an external AttributesModel on this diagram.
Q_DECL_DEPRECATED qreal valueForCell(int row, int column) const
QString unitPrefix(int column, Qt::Orientation orientation, bool fallback=false) const
bool allowOverlappingDataValueTexts() const
AbstractCoordinatePlane * coordinatePlane() const
void setHidden(const QModelIndex &index, bool hidden)
bool isIndexHidden(const QModelIndex &index) const override
QList< QPen > datasetPens() const
void setDataBoundariesDirty() const
void setUnitSuffix(const QString &suffix, int column, Qt::Orientation orientation)
QModelIndexList indexesIn(const QRect &rect) const
void setBrush(const QModelIndex &index, const QBrush &brush)
Q_DECL_DEPRECATED void setPercentMode(bool percent)
Deprecated method that turns the percent mode of this diagram on or off.
void setAllowOverlappingDataValueTexts(bool allow)
QStringList itemRowLabels() const
bool percentMode() const
Returns whether this diagram is drawn in percent mode.
void setSelectionModel(QItemSelectionModel *selectionModel) override
Q_DECL_DEPRECATED void setDatasetDimension(int dimension)
virtual bool usesExternalAttributesModel() const
int datasetDimension() const
virtual void setCoordinatePlane(AbstractCoordinatePlane *plane)
QModelIndex indexAt(const QPoint &point) const override
bool antiAliasing() const
QModelIndexList indexesAt(const QPoint &point) const
void setRootIndex(const QModelIndex &idx) override
Reimplemented for internal purposes.
virtual QRegion visualRegion(const QModelIndex &index) const
virtual Q_DECL_DEPRECATED void paintMarkers(QPainter *painter)
void aboutToBeDestroyed()
QList< MarkerAttributes > datasetMarkers() const
void doItemsLayout() override
QString unitSuffix(int column, Qt::Orientation orientation, bool fallback=false) const
void setAttributesModelRootIndex(const QModelIndex &)
void setDatasetDimensionInternal(int dimension)
QRegion visualRegionForSelection(const QItemSelection &selection) const override
QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override
Reimplemented for internal purposes.
A proxy model used for decorating data with attributes.
QVariant data(int role) const
int rowCount(const QModelIndex &) const override
QVariant modelData(int role) const
void initFrom(const AttributesModel *other)
bool compare(const AttributesModel *other) const
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::DisplayRole) override
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
bool setModelData(const QVariant value, int role)
Diagram attributes dealing with data value labels.
MarkerAttributes markerAttributes() const
void setShowOverlappingDataLabels(bool showOverlappingDataLabels)
A set of attributes controlling the appearance of data set markers.
QPainterPath customMarkerPath() const
QColor markerColor() const
QSizeF markerSize() const
static QPen scalePen(const QPen &pen)
Internally used class just adding a special constructor used by AbstractDiagram.
@ DataValueLabelAttributesRole