KD Chart API Documentation  3.1
KDChartAbstractCoordinatePlane.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** This file is part of the KD Chart library.
4 **
5 ** SPDX-FileCopyrightText: 2001 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
6 **
7 ** SPDX-License-Identifier: MIT
8 **
9 ****************************************************************************/
10 
12 #include "KDChartAbstractCoordinatePlane_p.h"
13 
14 #include "KDChartChart.h"
15 #include "KDChartGridAttributes.h"
16 
17 #include <KDABLibFakes>
18 
19 #include <QGridLayout>
20 #include <QMouseEvent>
21 #include <QRubberBand>
22 #include <QtCore/qmath.h>
23 
24 using namespace KDChart;
25 
26 #define d d_func()
27 
28 AbstractCoordinatePlane::Private::Private()
29  : AbstractArea::Private()
30 {
31  // this block left empty intentionally
32 }
33 
34 AbstractCoordinatePlane::AbstractCoordinatePlane(KDChart::Chart *parent)
35  : AbstractArea(new Private())
36 {
37  d->parent = parent;
38  d->init();
39 }
40 
42 {
43  Q_EMIT destroyedCoordinatePlane(this);
44 }
45 
46 void AbstractCoordinatePlane::init()
47 {
48  d->initialize(); // virtual method to init the correct grid: cartesian, polar, ...
51  Qt::QueuedConnection);
52 }
53 
55 {
56  // diagrams are invisible and paint through their paint() method
57  diagram->hide();
58 
59  d->diagrams.append(diagram);
60  diagram->setParent(d->parent);
63  layoutPlanes(); // there might be new axes, etc
68 
69  update();
70  Q_EMIT boundariesChanged();
71 }
72 
73 /*virtual*/
75 {
76  if (diagram && oldDiagram_ != diagram) {
77  AbstractDiagram *oldDiagram = oldDiagram_;
78  if (d->diagrams.count()) {
79  if (!oldDiagram) {
80  oldDiagram = d->diagrams.first();
81  if (oldDiagram == diagram)
82  return;
83  }
84  takeDiagram(oldDiagram);
85  }
86  delete oldDiagram;
89  layoutPlanes(); // there might be new axes, etc
90  update();
91  }
92 }
93 
94 /*virtual*/
96 {
97  const int idx = d->diagrams.indexOf(diagram);
98  if (idx != -1) {
99  d->diagrams.removeAt(idx);
100  diagram->setParent(nullptr);
101  diagram->setCoordinatePlane(nullptr);
105  layoutDiagrams();
106  update();
107  }
108 }
109 
111 {
112  if (d->diagrams.isEmpty()) {
113  return nullptr;
114  } else {
115  return d->diagrams.first();
116  }
117 }
118 
120 {
121  return d->diagrams;
122 }
123 
125 {
127 #ifndef QT_NO_STL
128  qCopy(d->diagrams.begin(), d->diagrams.end(), std::back_inserter(list));
129 #else
130  for (AbstractDiagram *a : d->diagrams)
131  list.push_back(a);
132 #endif
133  return list;
134 }
135 
137 {
138  d->gridAttributes = a;
139  update();
140 }
141 
143 {
144  return d->gridAttributes;
145 }
146 
148 {
149  return d->grid->updateData(this);
150 }
151 
153 {
154  d->grid->setNeedRecalculate();
155 }
156 
158 {
159  d->referenceCoordinatePlane = plane;
160 }
161 
163 {
164  return d->referenceCoordinatePlane;
165 }
166 
168 {
169  d->parent = parent;
170 }
171 
173 {
174  return d->parent;
175 }
176 
178 {
179  return d->parent;
180 }
181 
182 /* pure virtual in QLayoutItem */
184 {
185  return false; // never empty!
186  // coordinate planes with no associated diagrams
187  // are showing a default grid of ()1..10, 1..10) stepWidth 1
188 }
189 /* pure virtual in QLayoutItem */
191 {
192  return Qt::Vertical | Qt::Horizontal;
193 }
194 /* pure virtual in QLayoutItem */
196 {
197  // No maximum size set. Especially not parent()->size(), we are not layouting
198  // to the parent widget's size when using Chart::paint()!
199  return QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX);
200 }
201 /* pure virtual in QLayoutItem */
203 {
204  return QSize(60, 60); // this default can be overwritten by derived classes
205 }
206 /* pure virtual in QLayoutItem */
208 {
209  // we return our maxiumu (which is the full size of the Chart)
210  // even if we know the plane will be smaller
211  return maximumSize();
212 }
213 /* pure virtual in QLayoutItem */
215 {
216  if (d->geometry != r) {
217  // inform the outside word by Signal geometryChanged()
218  // via a queued connection to internal_geometryChanged()
219  Q_EMIT internal_geometryChanged(d->geometry, r);
220 
221  d->geometry = r;
222  // Note: We do *not* call update() here
223  // because it would invoke KDChart::update() recursively.
224  }
225 }
226 /* pure virtual in QLayoutItem */
228 {
229  return d->geometry;
230 }
231 
233 {
234  // qDebug("KDChart::AbstractCoordinatePlane::update() called");
235  Q_EMIT needUpdate();
236 }
237 
239 {
240  // qDebug("KDChart::AbstractCoordinatePlane::relayout() called");
241  Q_EMIT needRelayout();
242 }
243 
245 {
246  // qDebug("KDChart::AbstractCoordinatePlane::relayout() called");
247  Q_EMIT needLayoutPlanes();
248 }
249 
251 {
252  d->enableRubberBandZooming = enable;
253 
254  if (!enable && d->rubberBand != nullptr) {
255  delete d->rubberBand;
256  d->rubberBand = nullptr;
257  }
258 }
259 
261 {
262  return d->enableRubberBandZooming;
263 }
264 
266 {
267  if (d->enableCornerSpacers == enable)
268  return;
269 
270  d->enableCornerSpacers = enable;
271  Q_EMIT needRelayout();
272 }
273 
275 {
276  return d->enableCornerSpacers;
277 }
278 
280 {
281  if (event->button() == Qt::LeftButton) {
282  if (d->enableRubberBandZooming && d->rubberBand == nullptr)
283  d->rubberBand = new QRubberBand(QRubberBand::Rectangle, qobject_cast<QWidget *>(parent()));
284 
285  if (d->rubberBand != nullptr) {
286  d->rubberBandOrigin = event->pos();
287  d->rubberBand->setGeometry(QRect(event->pos(), QSize()));
288  d->rubberBand->show();
289 
290  event->accept();
291  }
292  } else if (event->button() == Qt::RightButton) {
293  if (d->enableRubberBandZooming && !d->rubberBandZoomConfigHistory.isEmpty()) {
294  // restore the last config from the stack
295  ZoomParameters config = d->rubberBandZoomConfigHistory.pop();
296  setZoomFactorX(config.xFactor);
297  setZoomFactorY(config.yFactor);
298  setZoomCenter(config.center());
299 
300  QWidget *const p = qobject_cast<QWidget *>(parent());
301  if (p != nullptr)
302  p->update();
303 
304  event->accept();
305  }
306  }
307 
308  for (AbstractDiagram *a : qAsConst(d->diagrams)) {
309  a->mousePressEvent(event);
310  }
311 }
312 
314 {
315  if (event->button() == Qt::RightButton) {
316  // otherwise the second click gets lost
317  // which is pretty annoying when zooming out fast
318  mousePressEvent(event);
319  }
320  for (AbstractDiagram *a : qAsConst(d->diagrams)) {
321  a->mouseDoubleClickEvent(event);
322  }
323 }
324 
326 {
327  if (d->rubberBand != nullptr) {
328  // save the old config on the stack
329  d->rubberBandZoomConfigHistory.push(ZoomParameters(zoomFactorX(), zoomFactorY(), zoomCenter()));
330 
331  // this is the height/width of the rubber band in pixel space
332  const auto rubberWidth = static_cast<qreal>(d->rubberBand->width());
333  const auto rubberHeight = static_cast<qreal>(d->rubberBand->height());
334 
335  if (rubberWidth > 0.0 && rubberHeight > 0.0) {
336  // this is the center of the rubber band in pixel space
337  const qreal centerX = qFloor(d->rubberBand->geometry().width() / 2.0 + d->rubberBand->geometry().x());
338  const qreal centerY = qCeil(d->rubberBand->geometry().height() / 2.0 + d->rubberBand->geometry().y());
339 
340  const qreal rubberCenterX = static_cast<qreal>(centerX - geometry().x());
341  const qreal rubberCenterY = static_cast<qreal>(centerY - geometry().y());
342 
343  // this is the height/width of the plane in pixel space
344  const qreal myWidth = static_cast<qreal>(geometry().width());
345  const qreal myHeight = static_cast<qreal>(geometry().height());
346 
347  // this describes the new center of zooming, relative to the plane pixel space
348  const qreal newCenterX = rubberCenterX / myWidth / zoomFactorX() + zoomCenter().x() - 0.5 / zoomFactorX();
349  const qreal newCenterY = rubberCenterY / myHeight / zoomFactorY() + zoomCenter().y() - 0.5 / zoomFactorY();
350 
351  // this will be the new zoom factor
352  const qreal newZoomFactorX = zoomFactorX() * myWidth / rubberWidth;
353  const qreal newZoomFactorY = zoomFactorY() * myHeight / rubberHeight;
354 
355  // and this the new center
356  const QPointF newZoomCenter(newCenterX, newCenterY);
357 
358  setZoomFactorX(newZoomFactorX);
359  setZoomFactorY(newZoomFactorY);
360  setZoomCenter(newZoomCenter);
361  }
362 
363  d->rubberBand->parentWidget()->update();
364  delete d->rubberBand;
365  d->rubberBand = nullptr;
366 
367  event->accept();
368  }
369 
370  for (AbstractDiagram *a : qAsConst(d->diagrams)) {
371  a->mouseReleaseEvent(event);
372  }
373 }
374 
376 {
377  if (d->rubberBand != nullptr) {
378  const QRect normalized = QRect(d->rubberBandOrigin, event->pos()).normalized();
379  d->rubberBand->setGeometry(normalized & geometry());
380 
381  event->accept();
382  }
383 
384  for (AbstractDiagram *a : qAsConst(d->diagrams)) {
385  a->mouseMoveEvent(event);
386  }
387 }
388 
389 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) && defined(Q_COMPILER_MANGLES_RETURN_TYPE)
390 const
391 #endif
392  bool
394 {
395  return d->isVisiblePoint(this, point);
396 }
397 
399 {
400  Q_UNUSED(p);
401  return this;
402 }
403 
404 #if !defined(QT_NO_DEBUG_STREAM)
405 #include "KDChartEnums.h"
406 
407 QDebug KDChart::operator<<(QDebug stream, const DataDimension &r)
408 {
409  stream << "DataDimension("
410  << " start=" << r.start
411  << " end=" << r.end
413  << " isCalculated=" << r.isCalculated
414  << " calcMode=" << (r.calcMode == AbstractCoordinatePlane::Logarithmic ? "Logarithmic" : "Linear")
415  << " stepWidth=" << r.stepWidth
416  << " subStepWidth=" << r.subStepWidth
417  << " )";
418  return stream;
419 }
420 #endif
421 
422 #undef d
Definition of global enums.
static QString granularitySequenceToString(GranularitySequence sequence)
Definition: KDChartEnums.h:99
An area in the chart with a background, a frame, etc.
Base class common for all coordinate planes, CartesianCoordinatePlane, PolarCoordinatePlane,...
void destroyedCoordinatePlane(AbstractCoordinatePlane *)
virtual void addDiagram(AbstractDiagram *diagram)
virtual void mousePressEvent(QMouseEvent *event)
void setGlobalGridAttributes(const GridAttributes &)
virtual void replaceDiagram(AbstractDiagram *diagram, AbstractDiagram *oldDiagram=nullptr)
virtual AbstractCoordinatePlane * sharedAxisMasterPlane(QPainter *p=nullptr)
bool isVisiblePoint(const QPointF &point) const
virtual void mouseReleaseEvent(QMouseEvent *event)
Qt::Orientations expandingDirections() const override
void setReferenceCoordinatePlane(AbstractCoordinatePlane *plane)
virtual void mouseDoubleClickEvent(QMouseEvent *event)
void internal_geometryChanged(QRect, QRect)
void geometryChanged(QRect, QRect)
AbstractCoordinatePlane * referenceCoordinatePlane() const
virtual void takeDiagram(AbstractDiagram *diagram)
virtual void mouseMoveEvent(QMouseEvent *event)
AbstractDiagram defines the interface for diagram classes.
virtual void setCoordinatePlane(AbstractCoordinatePlane *plane)
A chart with one or more diagrams.
Definition: KDChartChart.h:84
Helper class for one dimension of data, e.g. for the rows in a data model, or for the labels of an ax...
AbstractCoordinatePlane::AxesCalcMode calcMode
KDChartEnums::GranularitySequence sequence
A set of attributes controlling the appearance of grids.
const QPointF center() const
QDebug operator<<(QDebug stream, const DataDimension &r)
QList< AbstractDiagram * > AbstractDiagramList
QList< DataDimension > DataDimensionsList
QList< const AbstractDiagram * > ConstAbstractDiagramList

© 2001 Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
https://www.kdab.com/development-resources/qt-tools/kd-chart/
Generated by doxygen 1.9.1