Marble

MarbleGraphicsItem.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later
2//
3// SPDX-FileCopyrightText: 2009-2010 Bastian Holst <bastianholst@gmx.de>
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
20using namespace Marble;
21
22MarbleGraphicsItem::MarbleGraphicsItem(MarbleGraphicsItemPrivate *dd)
23 : d_ptr(dd)
24{
25}
26
27MarbleGraphicsItem::~MarbleGraphicsItem()
28{
29 delete d_ptr;
30}
31
32bool 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
110bool 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
120QVector<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
140QSizeF MarbleGraphicsItem::size() const
141{
142 Q_D(const MarbleGraphicsItem);
143 return d->m_size;
144}
145
146AbstractMarbleGraphicsLayout *MarbleGraphicsItem::layout() const
147{
148 Q_D(const MarbleGraphicsItem);
149 return d->m_layout;
150}
151
152void 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
161MarbleGraphicsItem::CacheMode MarbleGraphicsItem::cacheMode() const
162{
163 Q_D(const MarbleGraphicsItem);
164 return d->m_cacheMode;
165}
166
167void 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
176void 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
187bool MarbleGraphicsItem::visible() const
188{
189 Q_D(const MarbleGraphicsItem);
190 return d->m_visibility;
191}
192
193void MarbleGraphicsItem::setVisible( bool visible )
194{
195 Q_D(MarbleGraphicsItem);
196 d->m_visibility = visible;
197}
198
199void MarbleGraphicsItem::hide()
200{
201 setVisible( false );
202}
203
204void MarbleGraphicsItem::show()
205{
206 setVisible( true );
207}
208
209void 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
218QSizeF MarbleGraphicsItem::contentSize() const
219{
220 return size();
221}
222
223void MarbleGraphicsItem::setContentSize( const QSizeF& size )
224{
225 setSize( size );
226}
227
228QRectF MarbleGraphicsItem::contentRect() const
229{
230 return QRectF( QPointF( 0, 0 ), contentSize() );
231}
232
233void MarbleGraphicsItem::paint( QPainter *painter )
234{
235 Q_UNUSED( painter );
236}
237
238bool MarbleGraphicsItem::eventFilter( QObject *object, QEvent *e )
239{
240 if ( ! ( e->type() == QEvent::MouseButtonDblClick
241 || e->type() == QEvent::MouseMove
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
276void MarbleGraphicsItem::setProjection( const ViewportParams *viewport )
277{
278 Q_D(MarbleGraphicsItem);
279 d->setProjection(viewport);
280}
This file contains the headers for ViewportParams.
A public class that controls what is visible in the viewport of a Marble map.
bool isValid(QStringView ifopt)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
Binds a QML item to a specific geodetic location in screen coordinates.
MouseButtonDblClick
Type type() const const
void append(QList< T > &&value)
qsizetype count() const const
void reserve(qsizetype size)
qreal devicePixelRatio() const const
QPaintDevice * device() const const
void drawPixmap(const QPoint &point, const QPixmap &pixmap)
void restore()
void save()
void translate(const QPoint &offset)
QSize toSize() const const
transparent
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jun 21 2024 12:00:07 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.