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.
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
QRect toRect() const const
SizeAllCursor
LeftButton
WA_NoSystemBackground
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Jan 24 2025 11:52:09 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.