KD Chart 2  [rev.2.7]
ReverseMapper.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 ** Copyright (C) 2001-2020 Klaralvdalens Datakonsult AB. All rights reserved.
3 **
4 ** This file is part of the KD Chart library.
5 **
6 ** Licensees holding valid commercial KD Chart licenses may use this file in
7 ** accordance with the KD Chart Commercial License Agreement provided with
8 ** the Software.
9 **
10 **
11 ** This file may be distributed and/or modified under the terms of the
12 ** GNU General Public License version 2 and version 3 as published by the
13 ** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
14 **
15 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17 **
18 ** Contact info@kdab.com if any conditions of this licensing are not
19 ** clear to you.
20 **
21 **********************************************************************/
22 
23 #include "ReverseMapper.h"
24 
25 #include <math.h>
26 
27 #include <QRect>
28 #include <QtDebug>
29 #include <QPolygonF>
30 #include <QPainterPath>
31 #include <QGraphicsScene>
32 
33 #include "KDChartAbstractDiagram.h"
34 #include "ChartGraphicsItem.h"
35 
36 using namespace KDChart;
37 
39  : m_scene( 0 )
40  , m_diagram( 0 )
41 {
42 }
43 
45  : m_scene( 0 )
46  , m_diagram( diagram )
47 {
48 }
49 
51 {
52  delete m_scene; m_scene = 0;
53 }
54 
56 {
57 
58  m_diagram = diagram;
59 }
60 
62 {
63  m_itemMap.clear();
64  delete m_scene;
65  m_scene = new QGraphicsScene();
66 }
67 
68 QModelIndexList ReverseMapper::indexesIn( const QRect& rect ) const
69 {
70  Q_ASSERT( m_diagram );
71  if ( m_scene && m_scene->sceneRect().intersects( rect ) ) {
72  QList<QGraphicsItem *> items = m_scene->items( rect );
73  QModelIndexList indexes;
74  Q_FOREACH( QGraphicsItem* item, items ) {
75  ChartGraphicsItem* i = qgraphicsitem_cast<ChartGraphicsItem*>( item );
76  if ( i ) {
77  QModelIndex index ( m_diagram->model()->index( i->row(), i->column(), m_diagram->rootIndex() ) ); // checked
78  indexes << index;
79  }
80  }
81  return indexes;
82  } else {
83  return QModelIndexList();
84  }
85 }
86 
87 QModelIndexList ReverseMapper::indexesAt( const QPointF& point ) const
88 {
89  Q_ASSERT( m_diagram );
90  if ( m_scene && m_scene->sceneRect().contains( point ) ) {
91  QList<QGraphicsItem *> items = m_scene->items( point );
92  QModelIndexList indexes;
93  Q_FOREACH( QGraphicsItem* item, items ) {
94  ChartGraphicsItem* i = qgraphicsitem_cast<ChartGraphicsItem*>( item );
95  if ( i ) {
96  QModelIndex index ( m_diagram->model()->index( i->row(), i->column(), m_diagram->rootIndex() ) ); // checked
97  if ( !indexes.contains(index) )
98  indexes << index;
99  }
100  }
101  return indexes;
102  } else {
103  return QModelIndexList();
104  }
105 }
106 
107 QPolygonF ReverseMapper::polygon( int row, int column ) const
108 {
109  if ( !m_diagram->model()->hasIndex( row, column, m_diagram->rootIndex() ) )
110  return QPolygon();
111  const QModelIndex index = m_diagram->model()->index( row, column, m_diagram->rootIndex() ); // checked
112  return m_itemMap.contains( index ) ? m_itemMap[ index ]->polygon() : QPolygon();
113 }
114 
115 QRectF ReverseMapper::boundingRect( int row, int column ) const
116 {
117  if ( !m_diagram->model()->hasIndex( row, column, m_diagram->rootIndex() ) )
118  return QRectF();
119  const QModelIndex index = m_diagram->model()->index( row, column, m_diagram->rootIndex() ); // checked
120  return m_itemMap.contains( index ) ? m_itemMap[ index ]->polygon().boundingRect() : QRectF();
121 }
122 
124 {
125  Q_ASSERT( m_scene );
126  m_scene->addItem( item );
127  m_itemMap.insert( m_diagram->model()->index( item->row(), item->column(), m_diagram->rootIndex() ), item ); // checked
128 }
129 
130 void ReverseMapper::addRect( int row, int column, const QRectF& rect )
131 {
132  addPolygon( row, column, QPolygonF( rect ) );
133 }
134 
135 void ReverseMapper::addPolygon( int row, int column, const QPolygonF& polygon )
136 {
137  ChartGraphicsItem* item = new ChartGraphicsItem( row, column );
138  item->setPolygon( polygon );
139  addItem( item );
140 }
141 
142 void ReverseMapper::addCircle( int row, int column, const QPointF& location, const QSizeF& diameter )
143 {
144  QPainterPath path;
145  QPointF ossfet( -0.5*diameter.width(), -0.5*diameter.height() );
146  path.addEllipse( QRectF( location + ossfet, diameter ) );
147  addPolygon( row, column, QPolygonF( path.toFillPolygon() ) );
148 }
149 
150 void ReverseMapper::addLine( int row, int column, const QPointF& from, const QPointF& to )
151 {
152  // that's no line, dude... make a small circle around that point, instead
153  if ( from == to )
154  {
155  addCircle( row, column, from, QSizeF( 1.5, 1.5 ) );
156  return;
157  }
158  // lines do not make good polygons to click on. we calculate a 2
159  // pixel wide rectangle, where the original line is excatly
160  // centered in.
161  // make a 3 pixel wide polygon from the line:
162  static const QPointF pixel( 1.0, 1.0 );
163  QPointF left, right;
164  if ( from.x() < to.x() ) {
165  left = from;
166  right = to;
167  } else {
168  right = from;
169  left = to;
170  }
171  const QPointF lineVector( right - left );
172  const qreal lineVectorLength = sqrt( lineVector.x() * lineVector.x() + lineVector.y() * lineVector.y() );
173  const QPointF lineVectorUnit( lineVector / lineVectorLength );
174  const QPointF normOfLineVectorUnit( -lineVectorUnit.y(), lineVectorUnit.x() );
175  // now the four polygon end points:
176  const QPointF one( left - lineVectorUnit + normOfLineVectorUnit );
177  const QPointF two( left - lineVectorUnit - normOfLineVectorUnit );
178  const QPointF three( right + lineVectorUnit - normOfLineVectorUnit );
179  const QPointF four( right + lineVectorUnit + normOfLineVectorUnit );
180  addPolygon( row, column, QPolygonF() << one << two << three << four );
181 }
Graphics item used inside of the ReverseMapper.
QModelIndexList indexesAt(const QPointF &point) const
QModelIndexList indexesIn(const QRect &rect) const
AbstractDiagram defines the interface for diagram classes.
void addRect(int row, int column, const QRectF &rect)
void addItem(ChartGraphicsItem *item)
void addLine(int row, int column, const QPointF &from, const QPointF &to)
void setDiagram(AbstractDiagram *diagram)
void addPolygon(int row, int column, const QPolygonF &polygon)
QPolygonF polygon(int row, int column) const
void addCircle(int row, int column, const QPointF &location, const QSizeF &diameter)
QRectF boundingRect(int row, int column) const

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/