Marble

WidgetGraphicsItem.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later
2//
3// SPDX-FileCopyrightText: 2010 Bastian Holst <bastianholst@gmx.de>
4//
5
6// Self
7#include "WidgetGraphicsItem.h"
8#include "WidgetGraphicsItem_p.h"
9
10// Marble
11#include "MarbleDebug.h"
12#include "MarbleWidget.h"
13
14// Qt
15#include <QApplication>
16#include <QMouseEvent>
17#include <QPainter>
18#include <QWidget>
19
20using namespace Marble;
21
22WidgetGraphicsItemPrivate::WidgetGraphicsItemPrivate(WidgetGraphicsItem *widgetGraphicsItem, MarbleGraphicsItem *parent)
23 : ScreenGraphicsItemPrivate(widgetGraphicsItem, parent)
24 , m_widget(nullptr)
25 , m_marbleWidget(nullptr)
26 , m_activeWidget(nullptr)
27{
28 // nothing to do
29}
30
31WidgetGraphicsItemPrivate::~WidgetGraphicsItemPrivate()
32{
33 delete m_widget;
34}
35
36WidgetGraphicsItem::WidgetGraphicsItem(MarbleGraphicsItem *parent)
37 : ScreenGraphicsItem(new WidgetGraphicsItemPrivate(this, parent))
38{
39}
40
41WidgetGraphicsItem::~WidgetGraphicsItem() = default;
42
43void WidgetGraphicsItem::setWidget(QWidget *widget)
44{
45 Q_D(WidgetGraphicsItem);
46 d->m_widget = widget;
47
48 QSize size = widget->sizeHint().expandedTo(widget->size());
49 size = size.expandedTo(widget->minimumSize());
50 size = size.boundedTo(widget->maximumSize());
51 setSize(size);
52 widget->resize(size);
53}
54
55QWidget *WidgetGraphicsItem::widget() const
56{
57 Q_D(const WidgetGraphicsItem);
58 return d->m_widget;
59}
60
61void WidgetGraphicsItem::paint(QPainter *painter)
62{
63 Q_D(WidgetGraphicsItem);
64 if (d->m_widget == nullptr)
65 return;
66
67 // Paint widget without a background
68 d->m_widget->render(painter, QPoint(0, 0), QRegion(), QWidget::RenderFlags(QWidget::DrawChildren));
69}
70
71bool WidgetGraphicsItem::eventFilter(QObject *object, QEvent *e)
72{
73 Q_D(WidgetGraphicsItem);
74 if (!visible() || d->m_widget == nullptr) {
75 return false;
76 }
77
78 auto widget = dynamic_cast<MarbleWidget *>(object);
79 if (!widget) {
80 return ScreenGraphicsItem::eventFilter(object, e);
81 }
82
83 if (d->m_marbleWidget != widget) {
84 // Delayed initialization
85 d->m_marbleWidget = widget;
86 }
87
88 Q_ASSERT(d->m_marbleWidget);
89
92 // Mouse events are forwarded to the underlying widget
93 auto event = static_cast<QMouseEvent *>(e);
94
95 const QList<QPointF> widgetPositions = absolutePositions();
96 QRectF widgetItemRect;
97 QPoint shiftedPos;
98 QList<QPointF>::ConstIterator it = widgetPositions.begin();
99 bool foundRightPosition = false;
100 for (; !foundRightPosition && it != widgetPositions.end(); ++it) {
101 widgetItemRect = QRectF(*it, size());
102
103 if (widgetItemRect.contains(event->pos())) {
104 foundRightPosition = true;
105 shiftedPos = event->pos() - widgetItemRect.topLeft().toPoint();
106 }
107 }
108
109 if (foundRightPosition) {
110 QWidget *child = d->m_widget->childAt(shiftedPos);
111
112 if (d->m_activeWidget && d->m_activeWidget != child) {
113 QEvent leaveEvent(QEvent::Leave);
114 QApplication::sendEvent(d->m_activeWidget, &leaveEvent);
115 }
116
117 if (child && d->m_activeWidget != child) {
118 QEvent enterEvent(QEvent::Enter);
119 QApplication::sendEvent(child, &enterEvent);
120 }
121 d->m_activeWidget = child;
122
123 if (child) {
124 shiftedPos -= child->pos(); // transform to children's coordinates
125 QMouseEvent shiftedEvent = QMouseEvent(e->type(), shiftedPos, event->globalPos(), event->button(), event->buttons(), event->modifiers());
126 if (QApplication::sendEvent(child, &shiftedEvent)) {
127 d->m_marbleWidget->setCursor(d->m_widget->cursor());
128 return true;
129 }
130 }
131 } else {
132 if (d->m_activeWidget) {
133 QEvent leaveEvent(QEvent::Leave);
134 QApplication::sendEvent(d->m_activeWidget, &leaveEvent);
135 d->m_activeWidget = nullptr;
136 }
137 }
138 }
139
140 return ScreenGraphicsItem::eventFilter(object, e);
141}
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.
bool sendEvent(QObject *receiver, QEvent *event)
MouseButtonDblClick
Type type() const const
iterator begin()
iterator end()
QPoint toPoint() const const
bool contains(const QPointF &point) const const
QPointF topLeft() const const
QSize boundedTo(const QSize &otherSize) const const
QSize expandedTo(const QSize &otherSize) const const
QWidget * childAt(const QPoint &p) const const
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.