Marble

ScreenGraphicsItem.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later
2//
3// SPDX-FileCopyrightText: 2009-2010 Bastian Holst <bastianholst@gmx.de>
4//
5
6// Self
7#include "ScreenGraphicsItem.h"
8#include "ScreenGraphicsItem_p.h"
9
10// Marble
11#include "MarbleDebug.h"
12#include "MarbleWidget.h"
13
14// Qt
15#include <QMouseEvent>
16
17using namespace Marble;
18
19ScreenGraphicsItem::ScreenGraphicsItem(MarbleGraphicsItem *parent)
20 : MarbleGraphicsItem(new ScreenGraphicsItemPrivate(this, parent))
21{
22}
23
24ScreenGraphicsItem::ScreenGraphicsItem(ScreenGraphicsItemPrivate *dd)
25 : MarbleGraphicsItem(dd)
26{
27}
28
29ScreenGraphicsItem::~ScreenGraphicsItem() = default;
30
31QPointF ScreenGraphicsItem::position() const
32{
33 Q_D(const ScreenGraphicsItem);
34 return d->m_position;
35}
36
37void ScreenGraphicsItem::setPosition(const QPointF &position)
38{
39 Q_D(ScreenGraphicsItem);
40 d->m_position = position;
41}
42
43QPointF ScreenGraphicsItem::positivePosition() const
44{
45 Q_D(const ScreenGraphicsItem);
46 return d->positivePosition();
47}
48
49QList<QPointF> ScreenGraphicsItem::absolutePositions() const
50{
51 Q_D(const ScreenGraphicsItem);
52 return d->absolutePositions();
53}
54
55ScreenGraphicsItem::GraphicsItemFlags ScreenGraphicsItem::flags() const
56{
57 Q_D(const ScreenGraphicsItem);
58 return d->m_flags;
59}
60
61void ScreenGraphicsItem::setFlags(ScreenGraphicsItem::GraphicsItemFlags flags)
62{
63 Q_D(ScreenGraphicsItem);
64 d->m_flags = flags;
65}
66
67bool ScreenGraphicsItem::eventFilter(QObject *object, QEvent *e)
68{
69 auto widget = dynamic_cast<MarbleWidget *>(object);
70 if (!widget) {
71 return MarbleGraphicsItem::eventFilter(object, e);
72 }
73
74 Q_D(ScreenGraphicsItem);
75 if (!d->m_floatItemMoving) {
76 if (MarbleGraphicsItem::eventFilter(object, e)) {
77 return true;
78 }
79
80 if (!visible() || !d->isMovable()) {
81 return false;
82 }
83
84 if (e->type() == QEvent::MouseMove) {
85 return false;
86 }
87
88 // Move ScreenGraphicsItem
89 if (e->type() == QEvent::MouseButtonPress) {
90 auto event = static_cast<QMouseEvent *>(e);
91
92 // Click and move above a float item triggers moving the float item
93 if (contains(event->pos())) {
94 if (event->button() == Qt::LeftButton) {
95 d->m_floatItemMoveStartPos = event->pos();
96 d->m_floatItemMoving = true;
97 return true;
98 }
99 }
100 }
101
102 return false;
103 } else {
104 // Move ScreenGraphicsItem
106 auto event = static_cast<QMouseEvent *>(e);
107 // The rect the item was painted on before. We add one pixel as antialiasing could
108 // result into painting on these pixels to.
109 QRectF floatItemRect = QRectF(positivePosition() - QPoint(1, 1), size() + QSize(2, 2));
110
111 if (e->type() == QEvent::MouseMove && event->buttons() & Qt::LeftButton) {
112 const QPoint &point = event->pos();
113 QPointF position = positivePosition();
114 qreal newX = qMax<qreal>(0, position.x() + point.x() - d->m_floatItemMoveStartPos.x());
115 qreal newY = qMax<qreal>(0, position.y() + point.y() - d->m_floatItemMoveStartPos.y());
116
117 // docking behavior
118 const qreal dockArea = 60.0; // Alignment area width/height
119 const qreal dockJump = 30.0; // Alignment indicator jump size
120 if (widget->width() - size().width() - newX < dockArea) {
121 newX = qMin(qreal(-1.0), size().width() + newX - widget->width());
122 if (d->m_floatItemMoveStartPos.x() < event->pos().x()) {
123 // Indicate change to right alignment with a short jump
124 newX = qMax(newX, -(dockArea - dockJump));
125 }
126 }
127 if (widget->height() - size().height() - newY < dockArea) {
128 newY = qMin(qreal(-1.0), size().height() + newY - widget->height());
129 if (d->m_floatItemMoveStartPos.y() < event->pos().y()) {
130 // Indicate change to bottom alignment with a short jump
131 newY = qMax(newY, -(dockArea - dockJump));
132 }
133 }
134
135 setPosition(QPointF(newX, newY));
136 // The rect the item will be painted on now. We add one pixel as
137 // antialiasing could result into painting on these pixels to.
138 QRect newFloatItemRect = QRectF(positivePosition() - QPoint(1, 1), size() + QSize(2, 2)).toRect();
139 d->m_floatItemMoveStartPos = event->pos();
140 QRegion dirtyRegion(floatItemRect.toRect());
141 dirtyRegion = dirtyRegion.united(newFloatItemRect);
142
143 widget->setAttribute(Qt::WA_NoSystemBackground, false);
144 widget->update(dirtyRegion);
145 widget->setAttribute(Qt::WA_NoSystemBackground, widget->viewport()->mapCoversViewport());
146 return true;
147 }
148
149 if (e->type() == QEvent::MouseButtonRelease) {
150 d->m_floatItemMoving = false;
151 }
152
153 // Use a special cursor as long as the item is moved
154 if (d->m_floatItemMoving) {
155 widget->setCursor(QCursor(Qt::SizeAllCursor));
156 return true;
157 }
158 }
159
160 return MarbleGraphicsItem::eventFilter(object, e);
161 }
162}
This file contains the headers for MarbleWidget.
A widget class that displays a view of the earth.
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
Binds a QML item to a specific geodetic location in screen coordinates.
Type type() const const
int x() const const
int y() const const
qreal x() const const
qreal y() const const
QRect toRect() const const
qreal height() const const
qreal width() const const
SizeAllCursor
LeftButton
WA_NoSystemBackground
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:15:45 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.