Marble

MarbleGraphicsItem.cpp
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2009-2010 Bastian Holst <[email protected]>
4 //
5 
6 #include "MarbleGraphicsItem.h"
7 
8 #include "MarbleGraphicsItem_p.h"
9 
10 // Marble
11 #include "MarbleDebug.h"
12 #include "ViewportParams.h"
13 
14 // Qt
15 #include <QList>
16 #include <QPainter>
17 #include <QPixmap>
18 #include <QMouseEvent>
19 
20 using namespace Marble;
21 
22 MarbleGraphicsItem::MarbleGraphicsItem(MarbleGraphicsItemPrivate *dd)
23  : d_ptr(dd)
24 {
25 }
26 
27 MarbleGraphicsItem::~MarbleGraphicsItem()
28 {
29  delete d_ptr;
30 }
31 
32 bool MarbleGraphicsItem::paintEvent( QPainter *painter, const ViewportParams *viewport )
33 {
34  Q_D(MarbleGraphicsItem);
35 
36  if (!d->m_visibility) {
37  return true;
38  }
39 
40  if (d->m_repaintNeeded) {
41  d->updateChildPositions();
42  d->m_pixmap = QPixmap();
43  d->m_repaintNeeded = false;
44  }
45 
46  setProjection( viewport );
47 
48  if (d->positions().size() == 0) {
49  return true;
50  }
51 
52  // At the moment, as GraphicsItems can't be zoomed or rotated ItemCoordinateCache
53  // and DeviceCoordianteCache is exactly the same
54  if ( ItemCoordinateCache == cacheMode()
55  || DeviceCoordinateCache == cacheMode() )
56  {
57  const qreal scale = painter->device()->devicePixelRatio();
58 
59  const QSize neededPixmapSize = scale * size().toSize() + QSize( 1, 1 ); // adding a pixel for rounding errors
60 
61  if (d->m_pixmap.size() != neededPixmapSize ||
62  d->m_pixmap.devicePixelRatio() != scale) {
63 
64 
65  if ( size().isValid() && !size().isNull() ) {
66  d->m_pixmap = QPixmap(neededPixmapSize);
67  d->m_pixmap.setDevicePixelRatio(scale);
68  }
69  else {
70  mDebug() << "Warning: Invalid pixmap size suggested: " << d->m_size;
71  }
72 
73  d->m_pixmap.fill(Qt::transparent);
74  QPainter pixmapPainter(&d->m_pixmap);
75  // We paint in best quality here, as we only have to paint once.
76  pixmapPainter.setRenderHint( QPainter::Antialiasing, true );
77  // The cache image will get a 0.5 pixel bounding to save antialiasing effects.
78  pixmapPainter.translate( 0.5, 0.5 );
79  paint( &pixmapPainter );
80 
81  // Paint children
82  for (MarbleGraphicsItem *item: d->m_children) {
83  item->paintEvent( &pixmapPainter, viewport );
84  }
85  }
86 
87  for (const QPointF& position: d->positions()) {
88  painter->drawPixmap(position, d->m_pixmap);
89  }
90  }
91  else {
92  for (const QPointF& position: d->positions()) {
93  painter->save();
94 
95  painter->translate( position );
96  paint( painter );
97 
98  // Paint children
99  for (MarbleGraphicsItem *item: d->m_children) {
100  item->paintEvent( painter, viewport );
101  }
102 
103  painter->restore();
104  }
105  }
106 
107  return true;
108 }
109 
110 bool MarbleGraphicsItem::contains( const QPointF& point ) const
111 {
112  Q_D(const MarbleGraphicsItem);
113  for (const QRectF& rect: d->boundingRects()) {
114  if( rect.contains( point ) )
115  return true;
116  }
117  return false;
118 }
119 
120 QVector<QRectF> MarbleGraphicsItemPrivate::boundingRects() const
121 {
122  const QVector<QPointF> positions = this->positions();
123 
125  list.reserve(positions.count());
126 
127  for (const QPointF &point: positions) {
128  QRectF rect( point, m_size );
129  if( rect.x() < 0 )
130  rect.setLeft( 0 );
131  if( rect.y() < 0 )
132  rect.setTop( 0 );
133 
134  list.append( rect );
135  }
136 
137  return list;
138 }
139 
140 QSizeF MarbleGraphicsItem::size() const
141 {
142  Q_D(const MarbleGraphicsItem);
143  return d->m_size;
144 }
145 
146 AbstractMarbleGraphicsLayout *MarbleGraphicsItem::layout() const
147 {
148  Q_D(const MarbleGraphicsItem);
149  return d->m_layout;
150 }
151 
152 void MarbleGraphicsItem::setLayout( AbstractMarbleGraphicsLayout *layout )
153 {
154  Q_D(MarbleGraphicsItem);
155  // Deleting the old layout
156  delete d->m_layout;
157  d->m_layout = layout;
158  update();
159 }
160 
161 MarbleGraphicsItem::CacheMode MarbleGraphicsItem::cacheMode() const
162 {
163  Q_D(const MarbleGraphicsItem);
164  return d->m_cacheMode;
165 }
166 
167 void MarbleGraphicsItem::setCacheMode( CacheMode mode )
168 {
169  Q_D(MarbleGraphicsItem);
170  d->m_cacheMode = mode;
171  if (d->m_cacheMode == NoCache) {
172  d->m_repaintNeeded = true;
173  }
174 }
175 
176 void MarbleGraphicsItem::update()
177 {
178  Q_D(MarbleGraphicsItem);
179  d->m_repaintNeeded = true;
180 
181  // Update the parent.
182  if (d->m_parent) {
183  d->m_parent->update();
184  }
185 }
186 
187 bool MarbleGraphicsItem::visible() const
188 {
189  Q_D(const MarbleGraphicsItem);
190  return d->m_visibility;
191 }
192 
193 void MarbleGraphicsItem::setVisible( bool visible )
194 {
195  Q_D(MarbleGraphicsItem);
196  d->m_visibility = visible;
197 }
198 
199 void MarbleGraphicsItem::hide()
200 {
201  setVisible( false );
202 }
203 
204 void MarbleGraphicsItem::show()
205 {
206  setVisible( true );
207 }
208 
209 void MarbleGraphicsItem::setSize( const QSizeF& size )
210 {
211  Q_D(MarbleGraphicsItem);
212  if (d->m_size != size) {
213  d->m_size = size;
214  update();
215  }
216 }
217 
218 QSizeF MarbleGraphicsItem::contentSize() const
219 {
220  return size();
221 }
222 
223 void MarbleGraphicsItem::setContentSize( const QSizeF& size )
224 {
225  setSize( size );
226 }
227 
228 QRectF MarbleGraphicsItem::contentRect() const
229 {
230  return QRectF( QPointF( 0, 0 ), contentSize() );
231 }
232 
233 void MarbleGraphicsItem::paint( QPainter *painter )
234 {
235  Q_UNUSED( painter );
236 }
237 
238 bool MarbleGraphicsItem::eventFilter( QObject *object, QEvent *e )
239 {
240  if ( ! ( e->type() == QEvent::MouseButtonDblClick
241  || e->type() == QEvent::MouseMove
242  || e->type() == QEvent::MouseButtonPress
243  || e->type() == QEvent::MouseButtonRelease ) )
244  {
245  return false;
246  }
247 
248  Q_D(const MarbleGraphicsItem);
249  QMouseEvent *event = static_cast<QMouseEvent*> (e);
250 
251  if (!d->m_children.isEmpty()) {
252  const QVector<QPointF> absolutePositions = d->absolutePositions();
253 
254  for( const QPointF& absolutePosition: absolutePositions ) {
255  QPoint shiftedPos = event->pos() - absolutePosition.toPoint();
256 
257  if ( QRect( QPoint( 0, 0 ), size().toSize() ).contains( shiftedPos ) ) {
258  for (MarbleGraphicsItem *child: d->m_children) {
259  const QVector<QRectF> childRects = child->d_func()->boundingRects();
260 
261  for( const QRectF& childRect: childRects ) {
262  if( childRect.toRect().contains( shiftedPos ) ) {
263  if( child->eventFilter( object, e ) ) {
264  return true;
265  }
266  }
267  }
268  }
269  }
270  }
271  }
272 
273  return false;
274 }
275 
277 {
278  Q_D(MarbleGraphicsItem);
279  d->setProjection(viewport);
280 }
void append(const T &value)
int devicePixelRatio() const const
MouseButtonDblClick
void drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
KIOFILEWIDGETS_EXPORT QStringList list(const QString &fileClass)
bool contains(const QRect &rectangle, bool proper) const const
void reserve(int alloc)
A public class that controls what is visible in the viewport of a Marble map.
Binds a QML item to a specific geodetic location in screen coordinates.
QEvent::Type type() const const
bool isValid(QStringView ifopt)
void update(Part *part, const QByteArray &data, qint64 dataSize)
void translate(const QPointF &offset)
QPaintDevice * device() const const
void restore()
int count(const T &value) const const
void save()
transparent
Q_D(Todo)
QDebug mDebug()
a function to replace qDebug() in Marble library code
Definition: MarbleDebug.cpp:31
Q_INVOKABLE void setProjection(uint proj)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Oct 2 2023 03:52:09 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.