12#include "KDChartChart_p.h"
14#include <QApplication>
33#include "KDChartPainterSaver_p.h"
41#include "../evaldialog/evaldialog.h"
44#include <KDABLibFakes>
54static bool isZeroArea(
const QRect &r)
59static QString lineProlog(
int nestingDepth,
int lineno)
63 return numbering + indent;
66static void dumpLayoutTreeRecurse(
QLayout *l,
int *counter,
int depth)
71 QString prolog = lineProlog(depth, *counter);
80 for (
int i = 0; i < l->
count(); i++) {
83 dumpLayoutTreeRecurse(childL, counter, depth + 1);
87 if (!isZeroArea(child->
geometry())) {
88 prolog = lineProlog(depth + 1, *counter);
90 qDebug() << colorOn + prolog <<
typeid(*child).name() << child->
geometry()
101static void dumpLayoutTree(
QLayout *l)
104 dumpLayoutTreeRecurse(l, &counter, 0);
252 const int count = layout->
count();
253 for (
int i = 0; i < count; i++) {
260void Chart::Private::slotUnregisterDestroyedLegend(
Legend *l)
262 chart->takeLegend(l);
265void Chart::Private::slotUnregisterDestroyedHeaderFooter(
HeaderFooter *hf)
267 chart->takeHeaderFooter(hf);
272 coordinatePlanes.removeAll(plane);
274 if (p->referenceCoordinatePlane() == plane) {
275 p->setReferenceCoordinatePlane(
nullptr);
281Chart::Private::Private(
Chart *chart_)
283 , useNewLayoutSystem(false)
286 , planesLayout(nullptr)
287 , headerLayout(nullptr)
288 , footerLayout(nullptr)
289 , dataAndLegendLayout(nullptr)
290 , leftOuterSpacer(nullptr)
291 , rightOuterSpacer(nullptr)
292 , topOuterSpacer(nullptr)
293 , bottomOuterSpacer(nullptr)
294 , isFloatingLegendsLayoutDirty(true)
295 , isPlanesLayoutDirty(true)
296 , globalLeadingLeft(0)
297 , globalLeadingRight(0)
298 , globalLeadingTop(0)
299 , globalLeadingBottom(0)
301 for (
int row = 0; row < 3; ++row) {
302 for (
int column = 0; column < 3; ++column) {
303 for (
int i = 0; i < 2; i++) {
304 innerHdFtLayouts[i][row][column] =
nullptr;
310Chart::Private::~Private()
319struct ConnectedComponentsComparator
321 bool operator()(
const LayoutGraphNode *lhs,
const LayoutGraphNode *rhs)
const
323 return lhs->priority < rhs->priority;
331 for (LayoutGraphNode *node : qAsConst(nodeList)) {
332 visitedComponents[node] =
Unknown;
335 for (
int i = 0; i < nodeList.
size(); ++i) {
336 LayoutGraphNode *curNode = nodeList[i];
337 LayoutGraphNode *representativeNode = curNode;
338 if (visitedComponents[curNode] !=
Visited) {
342 curNode = stack.
pop();
343 Q_ASSERT(visitedComponents[curNode] !=
Visited);
344 visitedComponents[curNode] =
Visited;
345 if (curNode->bottomSuccesor && visitedComponents[curNode->bottomSuccesor] !=
Visited)
346 stack.
push(curNode->bottomSuccesor);
347 if (curNode->leftSuccesor && visitedComponents[curNode->leftSuccesor] !=
Visited)
348 stack.
push(curNode->leftSuccesor);
349 if (curNode->sharedSuccesor && visitedComponents[curNode->sharedSuccesor] !=
Visited)
350 stack.
push(curNode->sharedSuccesor);
351 if (curNode->priority < representativeNode->priority)
352 representativeNode = curNode;
354 connectedComponents.
append(representativeNode);
357 std::sort(connectedComponents.
begin(), connectedComponents.
end(), ConnectedComponentsComparator());
358 return connectedComponents;
361struct PriorityComparator
370 const LayoutGraphNode *lhsNode = m_mapping[lhs];
372 const LayoutGraphNode *rhsNode = m_mapping[rhs];
374 return lhsNode->priority < rhsNode->priority;
382 if (node && node->diagramPlane && node->diagramPlane->diagram()) {
383 auto *diag = qobject_cast<AbstractCartesianDiagram *>(node->diagramPlane->diagram());
385 const auto constAxes = diag->axes();
387 switch (axis->position()) {
389 node->topAxesLayout =
true;
392 node->bottomAxesLayout =
true;
395 node->leftAxesLayout =
true;
398 node->rightAxesLayout =
true;
408 lhs->topAxesLayout |= rhs->topAxesLayout;
409 rhs->topAxesLayout = lhs->topAxesLayout;
411 lhs->bottomAxesLayout |= rhs->bottomAxesLayout;
412 rhs->bottomAxesLayout = lhs->bottomAxesLayout;
414 lhs->leftAxesLayout |= rhs->leftAxesLayout;
415 rhs->leftAxesLayout = lhs->leftAxesLayout;
417 lhs->rightAxesLayout |= rhs->rightAxesLayout;
418 rhs->rightAxesLayout = lhs->rightAxesLayout;
423 Chart::Private::AxisType type,
426 if (!plane || !plane->
diagram())
431 auto *diagram = qobject_cast<AbstractCartesianDiagram *>(plane->
diagram());
437 const auto constAxes = diagram->axes();
448 qobject_cast<AbstractCartesianDiagram *>(curPlane->diagram());
452 const auto constAxes = diagram->axes();
454 if (curSearchedAxis == curAxis) {
456 if (!sharedAxes->
contains(curSearchedAxis))
457 sharedAxes->
append(curSearchedAxis);
478 if (curPlane->diagram()) {
479 allNodes.
append(
new LayoutGraphNode);
480 allNodes[allNodes.
size() - 1]->diagramPlane = curPlane;
481 allNodes[allNodes.
size() - 1]->priority = allNodes.
size();
483 planeNodeMapping[curPlane] = allNodes[allNodes.
size() - 1];
487 for (LayoutGraphNode *curNode : qAsConst(allNodes)) {
490 Q_ASSERT(sharedAxes.
size() < 2);
492 if (sharedAxes.
size() == 1 && xSharedPlanes.
size() > 1) {
495 for (
int i = 0; i < xSharedPlanes.
size() - 1; ++i) {
496 LayoutGraphNode *tmpNode = planeNodeMapping[xSharedPlanes[i]];
498 LayoutGraphNode *tmpNode2 = planeNodeMapping[xSharedPlanes[i + 1]];
500 tmpNode->bottomSuccesor = tmpNode2;
512 LayoutGraphNode axisInfoNode;
513 for (
int count = 0; count < 2; ++count) {
514 for (
int i = 0; i < xSharedPlanes.
size(); ++i) {
521 Q_ASSERT(sharedAxes.
size() < 2);
522 if (sharedAxes.
size() == 1 && ySharedPlanes.
size() > 1) {
525 for (
int i = 0; i < ySharedPlanes.
size() - 1; ++i) {
526 LayoutGraphNode *tmpNode = planeNodeMapping[ySharedPlanes[i]];
528 LayoutGraphNode *tmpNode2 = planeNodeMapping[ySharedPlanes[i + 1]];
530 tmpNode->leftSuccesor = tmpNode2;
542 LayoutGraphNode axisInfoNode;
543 for (
int count = 0; count < 2; ++count) {
544 for (
int i = 0; i < ySharedPlanes.
size(); ++i) {
550 if (curNode->diagramPlane->referenceCoordinatePlane())
551 curNode->sharedSuccesor = planeNodeMapping[curNode->diagramPlane->referenceCoordinatePlane()];
577 planeInfos.
insert(plane, p);
579 const auto constDiagrams = plane->
diagrams();
582 qobject_cast<AbstractCartesianDiagram *>(abstractDiagram);
587 const auto constAxes = diagram->axes();
596 axisInfos.
insert(axis, i);
598 AxisInfo i = axisInfos[axis];
599 if (i.plane == plane) {
606 PlaneInfo pi = planeInfos[plane];
608 if (!pi.referencePlane) {
610 pi.referencePlane = i.plane;
612 pi.horizontalOffset += 1;
614 planeInfos[plane] = pi;
616 pi = planeInfos[i.plane];
618 pi.verticalOffset += 1;
621 planeInfos[i.plane] = pi;
627 p = planeInfos[plane];
628 if (p.referencePlane ==
nullptr) {
630 p.gridLayout->setContentsMargins(0, 0, 0, 0);
631 planeInfos[plane] = p;
637void Chart::Private::slotLayoutPlanes()
642 if (planesLayout && dataAndLegendLayout)
643 dataAndLegendLayout->removeItem(planesLayout);
645 const bool hadPlanesLayout = planesLayout !=
nullptr;
648 planesLayout->getContentsMargins(&left, &top, &right, &bottom);
659 planeLayoutItems.clear();
663 planesLayout =
new QBoxLayout(oldPlanesDirection);
665 isPlanesLayoutDirty =
true;
667 if (useNewLayoutSystem) {
669 planesLayout->
addLayout(gridPlaneLayout);
672 planesLayout->setContentsMargins(left, top, right, bottom);
686 for (
int i = 0; i < connectedComponents.
size(); ++i) {
687 LayoutGraphNode *curComponent = connectedComponents[i];
688 for (LayoutGraphNode *curRowComponent = curComponent; curRowComponent; curRowComponent = curRowComponent->bottomSuccesor) {
690 for (LayoutGraphNode *curColComponent = curRowComponent; curColComponent; curColComponent = curColComponent->leftSuccesor) {
691 Q_ASSERT(curColComponent->diagramPlane->diagrams().size() == 1);
692 const auto constDiagrams = curColComponent->diagramPlane->diagrams();
694 const int planeRowOffset = 1;
695 const int planeColOffset = 1;
699 planeLayoutItems << curColComponent->diagramPlane;
700 auto *cartDiag = qobject_cast<AbstractCartesianDiagram *>(diagram);
702 gridPlaneLayout->addItem(curColComponent->diagramPlane, row + planeRowOffset, col + planeColOffset, 2, 2);
703 curColComponent->diagramPlane->setParentLayout(gridPlaneLayout);
708 if (curComponent->sharedSuccesor) {
709 gridPlaneLayout->
addItem(curColComponent->sharedSuccesor->diagramPlane, row + planeRowOffset, col + planeColOffset, 2, 2);
710 curColComponent->sharedSuccesor->diagramPlane->setParentLayout(gridPlaneLayout);
711 planeLayoutItems << curColComponent->sharedSuccesor->diagramPlane;
713 const auto constAxes = cartDiag->axes();
715 if (axis->isAbscissa()) {
716 if (curColComponent->bottomSuccesor)
723 switch (axis->position()) {
728 axis->setParentLayout(topLayout);
734 axis->setParentLayout(bottomLayout);
740 axis->setParentLayout(leftLayout);
747 axis->setParentLayout(rightLayout);
750 planeLayoutItems << axis;
754 gridPlaneLayout->addLayout(leftLayout, row + planeRowOffset, col, 2, 1,
757 gridPlaneLayout->addLayout(rightLayout, row, col + planeColOffset + 2, 2, 1,
760 gridPlaneLayout->addLayout(topLayout, row, col + planeColOffset, 1, 2,
763 gridPlaneLayout->addLayout(bottomLayout, row + planeRowOffset + 2,
766 gridPlaneLayout->addItem(curColComponent->diagramPlane, row, col, 4, 4);
767 curColComponent->diagramPlane->setParentLayout(gridPlaneLayout);
769 col += planeColOffset + 2 + (1);
774 const int rowOffset = axisOffset + 2;
786 if (dataAndLegendLayout) {
787 dataAndLegendLayout->addLayout(planesLayout, 1, 1);
788 dataAndLegendLayout->setRowStretch(1, 1000);
789 dataAndLegendLayout->setColumnStretch(1, 1000);
792#ifdef NEW_LAYOUT_DEBUG
793 for (
int i = 0; i < gridPlaneLayout->rowCount(); ++i) {
794 for (
int j = 0; j < gridPlaneLayout->columnCount(); ++j) {
795 if (gridPlaneLayout->itemAtPosition(i, j))
796 qDebug() << Q_FUNC_INFO <<
"item at" << i << j << gridPlaneLayout->itemAtPosition(i, j)->geometry();
798 qDebug() << Q_FUNC_INFO <<
"item at" << i << j <<
"no item present";
804 if (hadPlanesLayout) {
805 planesLayout->setContentsMargins(left, top, right, bottom);
808 planesLayout->setContentsMargins(0, 0, 0, 0);
809 planesLayout->setSpacing(0);
818 Q_ASSERT(planeInfos.
contains(plane));
819 PlaneInfo &pi = planeInfos[plane];
820 const int column = pi.horizontalOffset;
821 const int row = pi.verticalOffset;
826 PlaneInfo &refPi = pi;
829 while (!planeLayout && refPi.referencePlane) {
830 refPi = planeInfos[refPi.referencePlane];
831 planeLayout = refPi.gridLayout;
833 Q_ASSERT_X(planeLayout,
834 "Chart::Private::slotLayoutPlanes()",
835 "Invalid reference plane. Please check that the reference plane has been added to the Chart.");
837 planesLayout->addLayout(planeLayout);
843 planeLayoutItems << plane;
845 planeLayout->
addItem(plane, row, column, 1, 1, {});
849 const auto constDiagrams = plane->diagrams();
852 qobject_cast<AbstractCartesianDiagram *>(abstractDiagram);
857 if (pi.referencePlane !=
nullptr) {
858 pi.topAxesLayout = planeInfos[pi.referencePlane].topAxesLayout;
859 pi.bottomAxesLayout = planeInfos[pi.referencePlane].bottomAxesLayout;
860 pi.leftAxesLayout = planeInfos[pi.referencePlane].leftAxesLayout;
861 pi.rightAxesLayout = planeInfos[pi.referencePlane].rightAxesLayout;
865 if (pi.topAxesLayout ==
nullptr) {
870 if (pi.bottomAxesLayout ==
nullptr) {
875 if (pi.leftAxesLayout ==
nullptr) {
880 if (pi.rightAxesLayout ==
nullptr) {
886 if (pi.referencePlane !=
nullptr) {
887 planeInfos[pi.referencePlane].topAxesLayout = pi.topAxesLayout;
888 planeInfos[pi.referencePlane].bottomAxesLayout = pi.bottomAxesLayout;
889 planeInfos[pi.referencePlane].leftAxesLayout = pi.leftAxesLayout;
890 planeInfos[pi.referencePlane].rightAxesLayout = pi.rightAxesLayout;
894 const auto constAxes = diagram->axes();
900 axis->setCachedSizeDirty();
902 planeLayoutItems << axis;
904 switch (axis->position()) {
906 axis->setParentLayout(pi.topAxesLayout);
907 pi.topAxesLayout->addItem(axis);
910 axis->setParentLayout(pi.bottomAxesLayout);
911 pi.bottomAxesLayout->addItem(axis);
914 axis->setParentLayout(pi.leftAxesLayout);
915 pi.leftAxesLayout->addItem(axis);
918 axis->setParentLayout(pi.rightAxesLayout);
919 pi.rightAxesLayout->addItem(axis);
922 Q_ASSERT_X(
false,
"Chart::paintEvent",
"unknown axis position");
925 axisInfos.
insert(axis, AxisInfo());
932 if (!pi.topAxesLayout->parent()) {
933 planeLayout->
addLayout(pi.topAxesLayout, row - 1, column);
935 if (!pi.bottomAxesLayout->parent()) {
936 planeLayout->
addLayout(pi.bottomAxesLayout, row + 1, column);
938 if (!pi.leftAxesLayout->parent()) {
939 planeLayout->
addLayout(pi.leftAxesLayout, row, column - 1);
941 if (!pi.rightAxesLayout->parent()) {
942 planeLayout->
addLayout(pi.rightAxesLayout, row, column + 1);
947#define ADD_AUTO_SPACER_IF_NEEDED( \
948 spacerRow, spacerColumn, hLayoutIsAtTop, hLayout, vLayoutIsAtLeft, vLayout) \
950 if (hLayout || vLayout) { \
951 AutoSpacerLayoutItem *spacer = new AutoSpacerLayoutItem(hLayoutIsAtTop, hLayout, vLayoutIsAtLeft, vLayout); \
952 planeLayout->addItem(spacer, spacerRow, spacerColumn, 1, 1); \
953 spacer->setParentLayout(planeLayout); \
954 planeLayoutItems << spacer; \
958 if (plane->isCornerSpacersEnabled()) {
966 if (dataAndLegendLayout) {
967 dataAndLegendLayout->addLayout(planesLayout, 1, 1);
968 dataAndLegendLayout->setRowStretch(1, 1000);
969 dataAndLegendLayout->setColumnStretch(1, 1000);
976void Chart::Private::createLayouts()
980 layout->setContentsMargins(0, 0, 0, 0);
982 layout->addSpacing(globalLeadingLeft);
983 leftOuterSpacer = layout->itemAt(layout->count() - 1)->spacerItem();
988 vLayout->setContentsMargins(0, 0, 0, 0);
991 layout->addLayout(vLayout, 1000);
992 layout->addSpacing(globalLeadingRight);
993 rightOuterSpacer = layout->itemAt(layout->count() - 1)->spacerItem();
996 vLayout->addSpacing(globalLeadingTop);
997 topOuterSpacer = vLayout->itemAt(vLayout->count() - 1)->spacerItem();
1000 headerLayout->setContentsMargins(0, 0, 0, 0);
1001 vLayout->addLayout(headerLayout);
1004 dataAndLegendLayout->setContentsMargins(0, 0, 0, 0);
1006 vLayout->addLayout(dataAndLegendLayout, 1000);
1009 footerLayout->setContentsMargins(0, 0, 0, 0);
1011 vLayout->addLayout(footerLayout);
1017 for (
int row = 0; row < 3; ++row) {
1018 for (
int column = 0; column < 3; ++column) {
1020 for (
int headOrFoot = 0; headOrFoot < 2; headOrFoot++) {
1022 innerLayout->setContentsMargins(0, 0, 0, 0);
1023 innerLayout->setAlignment(align);
1024 innerHdFtLayouts[headOrFoot][row][column] = innerLayout;
1026 QGridLayout *outerLayout = headOrFoot == 0 ? headerLayout : footerLayout;
1027 outerLayout->
addLayout(innerLayout, row, column, align);
1033 vLayout->addSpacing(globalLeadingBottom);
1034 bottomOuterSpacer = vLayout->itemAt(vLayout->count() - 1)->spacerItem();
1037 dataAndLegendLayout->addLayout(planesLayout, 1, 1);
1038 dataAndLegendLayout->setRowStretch(1, 1);
1039 dataAndLegendLayout->setColumnStretch(1, 1);
1042void Chart::Private::slotResizePlanes()
1044 if (!dataAndLegendLayout) {
1047 if (!overrideSize.isValid()) {
1056 plane->layoutDiagrams();
1060void Chart::Private::updateDirtyLayouts()
1062 if (isPlanesLayoutDirty) {
1064 p->setGridNeedsRecalculate();
1066 p->layoutDiagrams();
1069 if (isPlanesLayoutDirty || isFloatingLegendsLayoutDirty) {
1070 chart->reLayoutFloatingLegends();
1072 isPlanesLayoutDirty =
false;
1073 isFloatingLegendsLayoutDirty =
false;
1076void Chart::Private::reapplyInternalLayouts()
1078 QRect geo = layout->geometry();
1081 layout->setGeometry(geo);
1085void Chart::Private::paintAll(
QPainter *painter)
1087 updateDirtyLayouts();
1089 QRect rect(
QPoint(0, 0), overrideSize.isValid() ? overrideSize : chart->size());
1098 chart->reLayoutFloatingLegends();
1101 planeLayoutItem->paintAll(*painter);
1103 for (
TextArea *textLayoutItem : qAsConst(textLayoutItems)) {
1104 textLayoutItem->paintAll(*painter);
1106 for (
Legend *legend : qAsConst(legends)) {
1110 legend->paintIntoRect(*painter, legend->geometry());
1121 , _d(new Private(this))
1123#if defined KDAB_EVAL
1124 EvalDialog::checkEvalLicense(
"KD Chart");
1146 d->frameAttributes = a;
1151 return d->frameAttributes;
1156 d->backgroundAttributes = a;
1161 return d->backgroundAttributes;
1167 if (
layout ==
d->planesLayout)
1169 if (
d->planesLayout) {
1172 for (
int i =
d->planesLayout->count() - 1;
i >= 0; --
i) {
1173 d->planesLayout->takeAt(
i);
1175 delete d->planesLayout;
1178 d->slotLayoutPlanes();
1183 return d->planesLayout;
1188 if (
d->coordinatePlanes.isEmpty()) {
1189 qWarning() <<
"Chart::coordinatePlane: warning: no coordinate plane defined.";
1192 return d->coordinatePlanes.first();
1198 return d->coordinatePlanes;
1214 d, &Private::slotUnregisterDestroyedPlane);
1219 d->coordinatePlanes.insert(index, plane);
1221 d->slotLayoutPlanes();
1229 if (
d->coordinatePlanes.count()) {
1244 const int idx =
d->coordinatePlanes.indexOf(plane);
1246 d->coordinatePlanes.takeAt(
idx);
1251 d->mouseClickedPlanes.removeAll(plane);
1253 d->slotLayoutPlanes();
1269 d->globalLeadingLeft = leading;
1271 d->reapplyInternalLayouts();
1276 return d->globalLeadingLeft;
1281 d->globalLeadingTop = leading;
1283 d->reapplyInternalLayouts();
1288 return d->globalLeadingTop;
1293 d->globalLeadingRight = leading;
1295 d->reapplyInternalLayouts();
1300 return d->globalLeadingRight;
1305 d->globalLeadingBottom = leading;
1307 d->reapplyInternalLayouts();
1312 return d->globalLeadingBottom;
1317 if (target.
isEmpty() || !painter) {
1325 if (
dynamic_cast<QWidget *
>(painter->
device()) !=
nullptr) {
1349 d->isPlanesLayoutDirty =
true;
1350 d->isFloatingLegendsLayoutDirty =
true;
1355 d->overrideSize = target.
size();
1356 d->paintAll(painter);
1357 d->overrideSize =
QSize();
1362 d->isPlanesLayoutDirty =
true;
1363 d->isFloatingLegendsLayoutDirty =
true;
1379 d->isPlanesLayoutDirty =
true;
1380 d->isFloatingLegendsLayoutDirty =
true;
1410 legend->
move(
static_cast<int>(
pt.x()),
static_cast<int>(
pt.y()));
1418 d->paintAll(&painter);
1429 qWarning(
"Unknown header/footer position");
1433 d->headerFooters.append(
hf);
1434 d->textLayoutItems.append(
hf);
1436 d, &Private::slotUnregisterDestroyedHeaderFooter);
1438 d, &Private::slotHeaderFooterPositionChanged);
1458 d->slotResizePlanes();
1466 if (
d->headerFooters.count()) {
1486 d, &Private::slotUnregisterDestroyedHeaderFooter);
1488 d->headerFooters.takeAt(
idx);
1491 d->textLayoutItems.remove(
d->textLayoutItems.indexOf(
headerFooter));
1493 d->slotResizePlanes();
1496void Chart::Private::slotHeaderFooterPositionChanged(
HeaderFooter *hf)
1498 chart->takeHeaderFooter(hf);
1499 chart->addHeaderFooter(hf);
1504 if (
d->headerFooters.isEmpty()) {
1507 return d->headerFooters.first();
1513 return d->headerFooters;
1518 auto *legend = qobject_cast<Legend *>(aw);
1520 chart->takeLegend(legend);
1521 chart->addLegendInternal(legend,
false);
1527 addLegendInternal(
legend,
true);
1531void Chart::addLegendInternal(
Legend *legend,
bool setMeasures)
1539 qWarning(
"Not showing legend because PositionCenter is not supported for legends.");
1546 qWarning(
"Not showing legend because of unknown legend position.");
1594 for (
int i = 0;
i < 3;
i++) {
1595 for (
int j = 0;
j < 3;
j++) {
1618 d, &Private::slotUnregisterDestroyedLegend);
1620 d, &Private::slotLegendPositionChanged);
1623 d->slotResizePlanes();
1630 if (
d->legends.count()) {
1650 d->legends.takeAt(
idx);
1656 d->slotResizePlanes();
1662 return d->legends.isEmpty() ? 0 :
d->legends.first();
1675 if (plane->geometry().contains(
event->pos()) && plane->diagrams().size() > 0) {
1678 plane->mousePressEvent(&
ev);
1679 d->mouseClickedPlanes.append(plane);
1689 if (plane->geometry().contains(
event->pos()) && plane->diagrams().size() > 0) {
1692 plane->mouseDoubleClickEvent(&
ev);
1700#if QT_VERSION > QT_VERSION_CHECK(5, 14, 0)
1707 if (plane->geometry().contains(
event->pos()) && plane->diagrams().size() > 0) {
1717 plane->mouseMoveEvent(&
ev);
1724#if QT_VERSION > QT_VERSION_CHECK(5, 14, 0)
1731 if (plane->geometry().contains(
event->pos()) && plane->diagrams().size() > 0) {
1741 plane->mouseReleaseEvent(&
ev);
1744 d->mouseClickedPlanes.clear();
1753 const auto constDiagrams = plane->diagrams();
1759 index = diagram->indexAt(helpEvent->
pos());
1762 const QModelIndexList indexes = diagram->indexesIn(
QRect(helpEvent->
pos() -
QPoint(15, 15),
QSize(30, 30)));
1763 index = indexes.isEmpty() ?
QModelIndex() : indexes.front();
1782 return d_func()->useNewLayoutSystem;
1787 d_func()->useNewLayoutSystem = value;
static const Qt::Alignment s_gridAlignments[3][3]
static QVector< LayoutGraphNode * > getPrioritySortedConnectedComponents(QVector< LayoutGraphNode * > &nodeList)
static void getRowAndColumnForPosition(KDChartEnums::PositionValue pos, int *row, int *column)
static void mergeNodeAxisInformation(LayoutGraphNode *lhs, LayoutGraphNode *rhs)
static void invalidateLayoutTree(QLayoutItem *item)
void checkExistingAxes(LayoutGraphNode *node)
static CoordinatePlaneList findSharingAxisDiagrams(AbstractCoordinatePlane *plane, const CoordinatePlaneList &list, Chart::Private::AxisType type, QVector< CartesianAxis * > *sharedAxes)
#define ADD_AUTO_SPACER_IF_NEEDED( spacerRow, spacerColumn, hLayoutIsAtTop, hLayout, vLayoutIsAtLeft, vLayout)
Definition of global enums.
@ MeasureOrientationMinimum
static void paintFrameAttributes(QPainter &painter, const QRect &rectangle, const KDChart::FrameAttributes &attributes)
static void paintBackgroundAttributes(QPainter &painter, const QRect &rectangle, const KDChart::BackgroundAttributes &attributes)
Base class common for all coordinate planes, CartesianCoordinatePlane, PolarCoordinatePlane,...
void destroyedCoordinatePlane(AbstractCoordinatePlane *)
AbstractDiagramList diagrams()
AbstractDiagram * diagram()
void setParent(Chart *parent)
AbstractCoordinatePlane * referenceCoordinatePlane() const
AbstractDiagram defines the interface for diagram classes.
void removeFromParentLayout()
void setParentLayout(QLayout *lay)
Cartesian coordinate plane.
A chart with one or more diagrams.
AbstractCoordinatePlane * coordinatePlane()
void reLayoutFloatingLegends()
void setFrameAttributes(const FrameAttributes &a)
Specify the frame attributes to be used, by default is it a thin black line.
void setUseNewLayoutSystem(bool value)
void setGlobalLeadingLeft(int leading)
void replaceLegend(Legend *legend, Legend *oldLegend=nullptr)
HeaderFooter * headerFooter()
void addLegend(Legend *legend)
LegendList legends() const
FrameAttributes frameAttributes() const
void setGlobalLeadingRight(int leading)
void mouseDoubleClickEvent(QMouseEvent *event) override
void paintEvent(QPaintEvent *event) override
Draws the background and frame, then calls paint().
void setGlobalLeadingTop(int leading)
CoordinatePlaneList coordinatePlanes()
void paint(QPainter *painter, const QRect &target)
void takeLegend(Legend *legend)
void takeCoordinatePlane(AbstractCoordinatePlane *plane)
void setCoordinatePlaneLayout(QLayout *layout)
void insertCoordinatePlane(int index, AbstractCoordinatePlane *plane)
HeaderFooterList headerFooters()
Chart(QWidget *parent=nullptr)
void mouseMoveEvent(QMouseEvent *event) override
bool event(QEvent *event) override
void resizeEvent(QResizeEvent *event) override
void setGlobalLeading(int left, int top, int right, int bottom)
void setBackgroundAttributes(const BackgroundAttributes &a)
Specify the background attributes to be used, by default there is no background.
void addHeaderFooter(HeaderFooter *headerFooter)
void mousePressEvent(QMouseEvent *event) override
void mouseReleaseEvent(QMouseEvent *event) override
void takeHeaderFooter(HeaderFooter *headerFooter)
void setGlobalLeadingBottom(int leading)
void replaceCoordinatePlane(AbstractCoordinatePlane *plane, AbstractCoordinatePlane *oldPlane=nullptr)
BackgroundAttributes backgroundAttributes() const
void addCoordinatePlane(AbstractCoordinatePlane *plane)
QLayout * coordinatePlaneLayout()
void replaceHeaderFooter(HeaderFooter *headerFooter, HeaderFooter *oldHeaderFooter=nullptr)
A set of attributes for frames around items.
void setPen(const QPen &pen)
static void setFactors(qreal factorX, qreal factorY)
static GlobalMeasureScaling * instance()
static void resetFactors()
static void setPaintDevice(QPaintDevice *paintDevice)
static QPaintDevice * paintDevice()
Legend defines the interface for the legend drawing class.
const RelativePosition floatingPosition() const
void destroyedLegend(Legend *)
TextAttributes titleTextAttributes() const
void needSizeHint() override
Qt::Alignment alignment() const
QSize sizeHint() const override
void setReferenceArea(const QWidget *area)
void setTextAttributes(const TextAttributes &a)
Position position() const
TextAttributes textAttributes() const
void setTitleTextAttributes(const TextAttributes &a)
Measure is used to specify relative and absolute sizes in KDChart, e.g. font sizes.
KDChartEnums::PositionValue value() const
static void setScaleFactor(const qreal scaleFactor)
static void resetScaleFactor()
Defines relative position information: reference area, position in this area (reference position),...
A text area in the chart with a background, a frame, etc.
A set of text attributes.
void setFontSize(const Measure &measure)
QList< AbstractCoordinatePlane * > CoordinatePlaneList
virtual void addItem(QLayoutItem *item) override
void addLayout(QLayout *layout, int stretch)
void addItem(QLayoutItem *item, int row, int column, int rowSpan, int columnSpan, Qt::Alignment alignment)
void addLayout(QLayout *layout, int row, int column, Qt::Alignment alignment)
void setColumnStretch(int column, int stretch)
void setRowStretch(int row, int stretch)
bool contains(const Key &key) const const
QHash::iterator insert(const Key &key, const T &value)
const QPoint & pos() const const
virtual int count() const const=0
virtual Qt::Orientations expandingDirections() const const override
virtual QRect geometry() const const override
virtual QLayoutItem * itemAt(int index) const const=0
virtual QSize maximumSize() const const override
virtual QSize minimumSize() const const override
bool setAlignment(QWidget *w, Qt::Alignment alignment)
void setContentsMargins(int left, int top, int right, int bottom)
Qt::Alignment alignment() const const
virtual Qt::Orientations expandingDirections() const const=0
virtual QRect geometry() const const=0
virtual bool hasHeightForWidth() const const
virtual void invalidate()
virtual QLayout * layout()
virtual QSize maximumSize() const const=0
virtual QSize minimumSize() const const=0
void setAlignment(Qt::Alignment alignment)
virtual QSize sizeHint() const const=0
void append(const T &value)
QVariant data(int role) const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
T qobject_cast(QObject *object)
int logicalDpiX() const const
int logicalDpiY() const const
QPaintDevice * device() const const
void translate(const QPointF &offset)
bool isEmpty() const const
QPoint topLeft() const const
bool contains(const T &value) const const
QSet< T > fromList(const QList< T > &list)
QSet::iterator insert(const T &value)
QString fromLatin1(const char *str, int size)
QString number(int n, int base)
QTextStream & left(QTextStream &stream)
QTextStream & right(QTextStream &stream)
void showText(const QPoint &pos, const QString &text, QWidget *w)
void append(const T &value)
QVector::iterator begin()
bool contains(const T &value) const const
bool isEmpty() const const