KD Chart API Documentation  3.1
ReverseMapper.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 
11 #include "ReverseMapper.h"
12 
13 #include <math.h>
14 
15 #include <QGraphicsScene>
16 #include <QPainterPath>
17 #include <QPolygonF>
18 #include <QRect>
19 #include <QtDebug>
20 
21 #include "ChartGraphicsItem.h"
22 #include "KDChartAbstractDiagram.h"
23 
24 using namespace KDChart;
25 
27 {
28 }
29 
31  : m_diagram(diagram)
32 {
33 }
34 
36 {
37  delete m_scene;
38  m_scene = nullptr;
39 }
40 
42 {
43  m_diagram = diagram;
44 }
45 
47 {
48  m_itemMap.clear();
49  delete m_scene;
50  m_scene = new QGraphicsScene();
51 }
52 
53 QModelIndexList ReverseMapper::indexesIn(const QRect &rect) const
54 {
55  Q_ASSERT(m_diagram);
56  if (m_scene && m_scene->sceneRect().intersects(rect)) {
57  const QList<QGraphicsItem *> items = m_scene->items(rect);
58  QModelIndexList indexes;
59  for (QGraphicsItem *item : items) {
60  auto *i = qgraphicsitem_cast<ChartGraphicsItem *>(item);
61  if (i) {
62  QModelIndex index(m_diagram->model()->index(i->row(), i->column(), m_diagram->rootIndex())); // checked
63  indexes << index;
64  }
65  }
66  return indexes;
67  } else {
68  return QModelIndexList();
69  }
70 }
71 
72 QModelIndexList ReverseMapper::indexesAt(const QPointF &point) const
73 {
74  Q_ASSERT(m_diagram);
75  if (m_scene && m_scene->sceneRect().contains(point)) {
76  const QList<QGraphicsItem *> items = m_scene->items(point);
77  QModelIndexList indexes;
78  for (QGraphicsItem *item : items) {
79  auto *i = qgraphicsitem_cast<ChartGraphicsItem *>(item);
80  if (i) {
81  QModelIndex index(m_diagram->model()->index(i->row(), i->column(), m_diagram->rootIndex())); // checked
82  if (!indexes.contains(index))
83  indexes << index;
84  }
85  }
86  return indexes;
87  } else {
88  return QModelIndexList();
89  }
90 }
91 
92 QPolygonF ReverseMapper::polygon(int row, int column) const
93 {
94  if (!m_diagram->model()->hasIndex(row, column, m_diagram->rootIndex()))
95  return QPolygon();
96  const QModelIndex index = m_diagram->model()->index(row, column, m_diagram->rootIndex()); // checked
97  return m_itemMap.contains(index) ? m_itemMap[index]->polygon() : QPolygon();
98 }
99 
100 QRectF ReverseMapper::boundingRect(int row, int column) const
101 {
102  if (!m_diagram->model()->hasIndex(row, column, m_diagram->rootIndex()))
103  return QRectF();
104  const QModelIndex index = m_diagram->model()->index(row, column, m_diagram->rootIndex()); // checked
105  return m_itemMap.contains(index) ? m_itemMap[index]->polygon().boundingRect() : QRectF();
106 }
107 
109 {
110  Q_ASSERT(m_scene);
111  m_scene->addItem(item);
112  m_itemMap.insert(m_diagram->model()->index(item->row(), item->column(), m_diagram->rootIndex()), item); // checked
113 }
114 
115 void ReverseMapper::addRect(int row, int column, const QRectF &rect)
116 {
117  addPolygon(row, column, QPolygonF(rect));
118 }
119 
120 void ReverseMapper::addPolygon(int row, int column, const QPolygonF &polygon)
121 {
122  auto *item = new ChartGraphicsItem(row, column);
123  item->setPolygon(polygon);
124  addItem(item);
125 }
126 
127 void ReverseMapper::addCircle(int row, int column, const QPointF &location, const QSizeF &diameter)
128 {
129  QPainterPath path;
130  QPointF ossfet(-0.5 * diameter.width(), -0.5 * diameter.height());
131  path.addEllipse(QRectF(location + ossfet, diameter));
132  addPolygon(row, column, QPolygonF(path.toFillPolygon()));
133 }
134 
135 void ReverseMapper::addLine(int row, int column, const QPointF &from, const QPointF &to)
136 {
137  // that's no line, dude... make a small circle around that point, instead
138  if (from == to) {
139  addCircle(row, column, from, QSizeF(1.5, 1.5));
140  return;
141  }
142  // lines do not make good polygons to click on. we calculate a 2
143  // pixel wide rectangle, where the original line is exactly
144  // centered in.
145  // make a 3 pixel wide polygon from the line:
146  QPointF left, right;
147  if (from.x() < to.x()) {
148  left = from;
149  right = to;
150  } else {
151  right = from;
152  left = to;
153  }
154  const QPointF lineVector(right - left);
155  const qreal lineVectorLength = sqrt(lineVector.x() * lineVector.x() + lineVector.y() * lineVector.y());
156  const QPointF lineVectorUnit(lineVector / lineVectorLength);
157  const QPointF normOfLineVectorUnit(-lineVectorUnit.y(), lineVectorUnit.x());
158  // now the four polygon end points:
159  const QPointF one(left - lineVectorUnit + normOfLineVectorUnit);
160  const QPointF two(left - lineVectorUnit - normOfLineVectorUnit);
161  const QPointF three(right + lineVectorUnit - normOfLineVectorUnit);
162  const QPointF four(right + lineVectorUnit + normOfLineVectorUnit);
163  addPolygon(row, column, QPolygonF() << one << two << three << four);
164 }
AbstractDiagram defines the interface for diagram classes.
Graphics item used inside of the ReverseMapper.
QModelIndexList indexesIn(const QRect &rect) const
void setDiagram(AbstractDiagram *diagram)
void addItem(ChartGraphicsItem *item)
QPolygonF polygon(int row, int column) const
void addCircle(int row, int column, const QPointF &location, const QSizeF &diameter)
void addLine(int row, int column, const QPointF &from, const QPointF &to)
void addRect(int row, int column, const QRectF &rect)
QRectF boundingRect(int row, int column) const
void addPolygon(int row, int column, const QPolygonF &polygon)
QModelIndexList indexesAt(const QPointF &point) const

© 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