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 <QMouseEvent>
17#include <QPainter>
18#include <QPixmap>
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() || DeviceCoordinateCache == cacheMode()) {
55 const qreal scale = painter->device()->devicePixelRatio();
56
57 const QSize neededPixmapSize = scale * size().toSize() + QSize(1, 1); // adding a pixel for rounding errors
58
59 if (d->m_pixmap.size() != neededPixmapSize || d->m_pixmap.devicePixelRatio() != scale) {
60 if (size().isValid() && !size().isNull()) {
61 d->m_pixmap = QPixmap(neededPixmapSize);
62 d->m_pixmap.setDevicePixelRatio(scale);
63 } else {
64 mDebug() << "Warning: Invalid pixmap size suggested: " << d->m_size;
65 }
66
67 d->m_pixmap.fill(Qt::transparent);
68 QPainter pixmapPainter(&d->m_pixmap);
69 // We paint in best quality here, as we only have to paint once.
70 pixmapPainter.setRenderHint(QPainter::Antialiasing, true);
71 // The cache image will get a 0.5 pixel bounding to save antialiasing effects.
72 pixmapPainter.translate(0.5, 0.5);
73 paint(&pixmapPainter);
74
75 // Paint children
76 for (MarbleGraphicsItem *item : std::as_const(d->m_children)) {
77 item->paintEvent(&pixmapPainter, viewport);
78 }
79 }
80
81 for (const QPointF &position : d->positions()) {
82 painter->drawPixmap(position, d->m_pixmap);
83 }
84 } else {
85 for (const QPointF &position : d->positions()) {
86 painter->save();
87
88 painter->translate(position);
89 paint(painter);
90
91 // Paint children
92 for (MarbleGraphicsItem *item : std::as_const(d->m_children)) {
93 item->paintEvent(painter, viewport);
94 }
95
96 painter->restore();
97 }
98 }
99
100 return true;
101}
102
103bool MarbleGraphicsItem::contains(const QPointF &point) const
104{
105 Q_D(const MarbleGraphicsItem);
106 for (const QRectF &rect : d->boundingRects()) {
107 if (rect.contains(point))
108 return true;
109 }
110 return false;
111}
112
113QList<QRectF> MarbleGraphicsItemPrivate::boundingRects() const
114{
115 const QList<QPointF> positions = this->positions();
116
118 list.reserve(positions.count());
119
120 for (const QPointF &point : positions) {
121 QRectF rect(point, m_size);
122 if (rect.x() < 0)
123 rect.setLeft(0);
124 if (rect.y() < 0)
125 rect.setTop(0);
126
127 list.append(rect);
128 }
129
130 return list;
131}
132
133QSizeF MarbleGraphicsItem::size() const
134{
135 Q_D(const MarbleGraphicsItem);
136 return d->m_size;
137}
138
139AbstractMarbleGraphicsLayout *MarbleGraphicsItem::layout() const
140{
141 Q_D(const MarbleGraphicsItem);
142 return d->m_layout;
143}
144
145void MarbleGraphicsItem::setLayout(AbstractMarbleGraphicsLayout *layout)
146{
147 Q_D(MarbleGraphicsItem);
148 // Deleting the old layout
149 delete d->m_layout;
150 d->m_layout = layout;
151 update();
152}
153
154MarbleGraphicsItem::CacheMode MarbleGraphicsItem::cacheMode() const
155{
156 Q_D(const MarbleGraphicsItem);
157 return d->m_cacheMode;
158}
159
160void MarbleGraphicsItem::setCacheMode(CacheMode mode)
161{
162 Q_D(MarbleGraphicsItem);
163 d->m_cacheMode = mode;
164 if (d->m_cacheMode == NoCache) {
165 d->m_repaintNeeded = true;
166 }
167}
168
169void MarbleGraphicsItem::update()
170{
171 Q_D(MarbleGraphicsItem);
172 d->m_repaintNeeded = true;
173
174 // Update the parent.
175 if (d->m_parent) {
176 d->m_parent->update();
177 }
178}
179
180bool MarbleGraphicsItem::visible() const
181{
182 Q_D(const MarbleGraphicsItem);
183 return d->m_visibility;
184}
185
186void MarbleGraphicsItem::setVisible(bool visible)
187{
188 Q_D(MarbleGraphicsItem);
189 d->m_visibility = visible;
190}
191
192void MarbleGraphicsItem::hide()
193{
194 setVisible(false);
195}
196
197void MarbleGraphicsItem::show()
198{
199 setVisible(true);
200}
201
202void MarbleGraphicsItem::setSize(const QSizeF &size)
203{
204 Q_D(MarbleGraphicsItem);
205 if (d->m_size != size) {
206 d->m_size = size;
207 update();
208 }
209}
210
211QSizeF MarbleGraphicsItem::contentSize() const
212{
213 return size();
214}
215
216void MarbleGraphicsItem::setContentSize(const QSizeF &size)
217{
218 setSize(size);
219}
220
221QRectF MarbleGraphicsItem::contentRect() const
222{
223 return QRectF(QPointF(0, 0), contentSize());
224}
225
226void MarbleGraphicsItem::paint(QPainter *painter)
227{
228 Q_UNUSED(painter);
229}
230
231bool MarbleGraphicsItem::eventFilter(QObject *object, QEvent *e)
232{
234 || e->type() == QEvent::MouseButtonRelease)) {
235 return false;
236 }
237
238 Q_D(const MarbleGraphicsItem);
239 auto event = static_cast<QMouseEvent *>(e);
240
241 if (!d->m_children.isEmpty()) {
242 const QList<QPointF> absolutePositions = d->absolutePositions();
243
244 for (const QPointF &absolutePosition : absolutePositions) {
245 QPoint shiftedPos = event->pos() - absolutePosition.toPoint();
246
247 if (QRect(QPoint(0, 0), size().toSize()).contains(shiftedPos)) {
248 for (MarbleGraphicsItem *child : d->m_children) {
249 const QList<QRectF> childRects = child->d_func()->boundingRects();
250
251 for (const QRectF &childRect : childRects) {
252 if (childRect.toRect().contains(shiftedPos)) {
253 if (child->eventFilter(object, e)) {
254 return true;
255 }
256 }
257 }
258 }
259 }
260 }
261 }
262
263 return false;
264}
265
266void MarbleGraphicsItem::setProjection(const ViewportParams *viewport)
267{
268 Q_D(MarbleGraphicsItem);
269 d->setProjection(viewport);
270}
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 Nov 8 2024 12:02:44 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.